Files
TradingAgents-astock/tradingagents/agents/trader/trader.py
T
Simon Lin d55820c08d refactor!: 删除可执行价位能力,不再以配置开关形式保留
BREAKING CHANGE: 上一提交引入的 enable_execution_levels 开关一并移除。

改为直接删除而非默认关闭:荐股软件的认定看软件是否「具备」该功能,
留一个开关在代码里、README 还写着怎么打开,那软件依然具备该功能。
删掉才是真的不具备,同时少一个开关、少两个 schema 变体、少两处分支。

- 删除 TraderProposalWithLevels / PortfolioDecisionWithTarget 两个变体
  与 trader_proposal_model() / portfolio_decision_model() 选择器
- 删除 entry_price / stop_loss / position_sizing / price_target 字段
- 渲染函数不再输出对应四节,getattr 兼容层一并移除
- create_trader / create_portfolio_manager / GraphSetup 去掉开关参数
- default_config 去掉 enable_execution_levels
- 提示词保持收紧(仅删字段挡不住模型写进散文字段)
- 测试 TestExecutionLevelsFlag → TestNoExecutionLevels:
  锁定「schema 无价位字段 / 提示词禁止 / 渲染永不输出」

需要该能力的使用者可自行 fork 添加(Apache-2.0 允许)。

测试:161 passed + 48 subtests passed。
2026-07-24 19:54:24 +12:00

93 lines
3.9 KiB
Python

"""Trader: turns the Research Manager's investment plan into a concrete transaction proposal."""
from __future__ import annotations
import functools
from langchain_core.messages import AIMessage
from tradingagents.agents.schemas import TraderProposal, render_trader_proposal
from tradingagents.agents.utils.agent_utils import build_instrument_context, get_language_instruction
from tradingagents.agents.utils.structured import (
bind_structured,
invoke_structured_or_freetext,
)
# The schema alone cannot stop the model from putting price levels into the
# free-text reasoning field, so the prompt says it explicitly too.
_NO_LEVELS_INSTRUCTION = (
"Explain the reasoning behind the direction. Do NOT state entry prices, "
"stop-loss levels, target prices or position sizes for this security."
)
def create_trader(llm):
structured_llm = bind_structured(llm, TraderProposal, "Trader")
def trader_node(state, name):
company_name = state["company_of_interest"]
instrument_context = build_instrument_context(company_name)
investment_plan = state["investment_plan"]
# Collect A-stock specific analyst reports
policy_report = state.get("policy_report", "")
hot_money_report = state.get("hot_money_report", "")
lockup_report = state.get("lockup_report", "")
# Build optional A-stock context block
astock_context_parts = []
if policy_report:
astock_context_parts.append(f"Policy Analysis Report:\n{policy_report}")
if hot_money_report:
astock_context_parts.append(f"Hot Money / Capital Flow Report:\n{hot_money_report}")
if lockup_report:
astock_context_parts.append(f"Lockup Expiry / Insider Reduction Report:\n{lockup_report}")
astock_context = "\n\n".join(astock_context_parts)
messages = [
{
"role": "system",
"content": (
"You are a trading agent specialising in A-share (China mainland) stocks. "
"Translate the Research Manager's investment plan into a structured "
"transaction view. You must factor in A-stock trading constraints:\n"
"- T+1 settlement: shares bought today cannot be sold until the next trading day\n"
"- Daily price limits: main board ±10%, STAR/ChiNext ±20%, ST stocks ±5%\n"
"- Minimum lot: 100 shares (main board) or 200 shares (STAR/ChiNext)\n"
"- Trading hours: 09:30-11:30, 13:00-15:00 Beijing time\n"
"Anchor your reasoning in the analysts' reports and the research plan. "
f"{_NO_LEVELS_INSTRUCTION} "
"(以上参数仅供技术研究参考,不构成投资建议)"
),
},
{
"role": "user",
"content": (
f"Based on a comprehensive analysis by a team of analysts (including market, "
f"sentiment, news, fundamentals, policy, capital flow, and lockup/reduction "
f"specialists), here is an investment plan for {company_name}.\n\n"
f"{instrument_context}\n\n"
f"Proposed Investment Plan:\n{investment_plan}\n\n"
+ (f"Additional A-Stock Analyst Context:\n{astock_context}\n\n" if astock_context else "")
+ "Leverage these insights to craft the transaction view."
+ get_language_instruction()
),
},
]
trader_plan = invoke_structured_or_freetext(
structured_llm,
llm,
messages,
render_trader_proposal,
"Trader",
)
return {
"messages": [AIMessage(content=trader_plan)],
"trader_investment_plan": trader_plan,
"sender": name,
}
return functools.partial(trader_node, name="Trader")