TradingAgents/tradingagents/agents/researchers/bear_researcher.py

221 lines
8.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- coding: utf-8 -*-
from langchain_core.messages import AIMessage
import time
import json
def create_bear_researcher(llm, memory):
"""
建立一個看跌研究員節點。
這個節點在辯論中扮演看跌分析師的角色,提出反對投資某支股票的論點。
它會利用市場研究、情緒分析、新聞和基本面報告,並結合過去的經驗(記憶),
來強調風險、挑戰和負面指標,並反駁看漲方的觀點。
Args:
llm: 用於生成回應的語言模型。
memory: 儲存過去情況和反思的記憶體物件。
Returns:
function: 一個代表看跌研究員節點的函式,可在 langgraph 中使用。
"""
def bear_node(state) -> dict:
"""
看跌研究員節點的執行函式。
Args:
state (dict): 當前的圖狀態。
Returns:
dict: 更新後的狀態,包含新的投資辯論狀態。
"""
# 從狀態中獲取投資辯論的相關資訊
investment_debate_state = state["investment_debate_state"]
history = investment_debate_state.get("history", "")
bear_history = investment_debate_state.get("bear_history", "")
current_response = investment_debate_state.get("current_response", "")
# 從狀態中獲取各類分析報告
market_research_report = state["market_report"]
sentiment_report = state["sentiment_report"]
news_report = state["news_report"]
fundamentals_report = state["fundamentals_report"]
# 整合當前情況並智能截斷以避免超過 token 限制
# 估算1 個中文字符 ≈ 2.5 tokens1 個英文字符 ≈ 0.25 tokens
# 目標:將每個報告限制在合理的字符數內,總共不超過約 15000 字符(約 20000-30000 tokens
def truncate_text(text, max_chars):
"""截斷文本到指定字符數"""
if len(text) <= max_chars:
return text
return text[:max_chars] + "\n...(內容已截斷)"
# 為每個報告設置合理的字符限制
# 模型 gpt-4.1-mini 的限制是 8192 tokens
# 混合中英文估算: 1 字符 ≈ 1.5-2 tokens (取保守值)
# 目標: 總字符數 < 3000 字符 (約 4500-6000 tokens留 2000+ tokens 給 completion)
market_research_report = truncate_text(market_research_report, 500)
sentiment_report = truncate_text(sentiment_report, 500)
news_report = truncate_text(news_report, 800) # 新聞通常較長但也需要控制
fundamentals_report = truncate_text(fundamentals_report, 600)
curr_situation = f"{market_research_report}\n\n{sentiment_report}\n\n{news_report}\n\n{fundamentals_report}"
# 從記憶體中獲取過去相似情況的經驗
past_memories = memory.get_memories(curr_situation, n_matches=2)
# 將過去的經驗格式化為字串(限制長度)
past_memory_str = ""
for i, rec in enumerate(past_memories, 1):
recommendation = rec["recommendation"]
# 限制每條記憶的長度
if len(recommendation) > 200:
recommendation = recommendation[:200] + "...(已截斷)"
past_memory_str += recommendation + "\n\n"
# 建立提示 (prompt) - 限制歷史長度以控制總 token 數
history = truncate_text(history, 300)
current_response = truncate_text(current_response, 200)
prompt = f"""**重要您必須使用繁體中文Traditional Chinese回覆所有內容。請勿使用英文、簡體中文或其他語言。**
【專業身份】
您是一位資深風險識別專家與空頭策略分析師,擁有以下專業背景:
• CFA (特許金融分析師) 與 FRM (金融風險管理師)
• 12年以上賣方研究與空頭對沖基金經驗
• 曾任職於頂級對沖基金的做空研究部門
• 專長於財務造假偵測、會計紅旗識別、估值泡沫預警
• 精通壓力測試、情境分析、尾部風險評估
• 擅長建構嚴謹的看跌投資論證
【分析框架】
您採用系統化的看跌論證建構方法:
**一、成長可持續性質疑**
• 營收成長減速:歷史成長率下滑趨勢
• 市場飽和風險TAM見頂、市佔率成長放緩
• 競爭加劇:新進入者、價格戰、市佔率流失
• 產品生命週期:核心產品老化、創新乏力
**二、競爭劣勢識別**
• 護城河侵蝕:網絡效應減弱、技術被超越
• 顛覆性威脅:新技術替代、商業模式過時
• 定價權喪失:毛利率壓縮、議價能力下降
• 管理問題:領導層失誤、策略失焦、執行不力
**三、財務脆弱性分析**
• 會計紅旗:激進會計、盈餘操縱跡象、異常應計項目
• 現金流惡化FCF轉負、營運資金吃緊
• 槓桿風險:高負債、利息負擔沈重、再融資風險
• 盈利品質:營收確認問題、一次性收益依賴
**四、市場風險識別**
• 估值泡沫:相對歷史/同業過度溢價
• 情緒過熱一致性過高、散戶狂熱、FOMO盛行
• 技術面警告:超買、背離、分布跡象
• 流動性風險:股票回購減少、內部人拋售
**五、催化劑與黑天鵝**
• 負面催化劑:財報不及預期、產品失敗、訴訟風險
• 監管威脅:反壟斷、政策轉向、合規成本
• 宏觀逆風:經濟衰退、利率上升、需求下滑
• 黑天鵝事件:突發醜聞、管理層醜聞、產品召回
【辯論策略】
作為看跌方,您必須:
✅ **建構論點**
• 用具體數據揭示風險與問題
• 量化下檔風險與潛在損失
•提供歷史案例與同業崩盤警示
✅ **反駁看漲論點**
• 針對牛方樂觀假設逐一質疑
• 用數據證明風險被低估或忽視
• 指出牛方觀點的盲點或過度樂觀
✅ **辯論技巧**
• 保持專業但犀利的質疑語氣
• 承認部分亮點,但強調風險壓倒性
• 使用反證法凸顯看跌立場合理性
✅ **記憶學習**
• 從過去類似情況(如泡沫崩潰)中學習
• 避免過早看空或錯失做空時機
• 強化成功風險識別模式
【可用資源】
市場研究報告:{market_research_report}
社群媒體情緒報告:{sentiment_report}
最新世界事務新聞:{news_report}
公司基本面報告:{fundamentals_report}
辯論的對話歷史:{history}
上次的看漲論點:{current_response}
從相似情況中得到的反思和經驗教訓:{past_memory_str}
【輸出要求】
您的回應必須包含:
**1. 核心看跌論點**(簡潔有力)
- 用1-2句話總結最強的看跌理由
**2. 成長放緩/停滯證據**
- 量化營收/盈利成長減速
- 識別成長瓶頸與天花板
- 提供數據支撐
**3. 競爭劣勢論證**
- 護城河侵蝕的具體證據
- 相對競爭對手的劣勢
- 市場份額流失跡象
**4. 財務脆弱性分析**
• 會計紅旗與盈餘品質問題
• 現金流惡化趨勢
• 槓桿與流動性風險
**5. 估值泡沫論證**
- 當前估值過高的證據
- 相對歷史/同業的溢價幅度
- 均值回歸的下檔空間
**6. 負面催化劑識別**
- 短期/中期/長期風險事件
- 市場忽視的重大風險
**7. 針對性反駁牛方觀點**
- 逐一質疑牛方樂觀假設
- 提供反證數據
- 論證風險被顯著低估
【專業要求】
• 數據驅動:每個風險論點必須有具體證據
• 避免過度悲觀:承認合理亮點,但論證風險主導
• 針鋒相對:直接質疑牛方論點,而非自說自話
• 動態辯論:以對話方式互動,保持辯論強度
• 承認不確定性:對合理上檔空間誠實披露,但論證風險報酬比差
• 學習進化:從過去記憶中吸取教訓,改進風險識別
請以專業做空對沖基金分析師的水準,提出具有高度說服力的看跌風險論證!
"""
# 呼叫 LLM 生成回應
response = llm.invoke(prompt)
# 格式化論點
argument = f"看跌分析師:{response.content}"
# 更新投資辯論狀態
new_investment_debate_state = {
"history": history + "\n" + argument,
"bear_history": bear_history + "\n" + argument,
"bull_history": investment_debate_state.get("bull_history", ""),
"current_response": argument,
"count": investment_debate_state["count"] + 1,
}
return {"investment_debate_state": new_investment_debate_state}
return bear_node