组合管理 Agent:LLM 如何在硬约束内拍板


文档摘要

组合管理 Agent:LLM 如何在硬约束内拍板 难度:入门 组合管理 Agent( 中的 )是虚拟投委会的主持人兼拍板人。它阅读 中全部研究结论(压缩为 ),读取风控给出的 与 ,经 算出每种动作的最大股数,再调用 LLM 在合法动作集合内选出最终指令。 本文你将学到 与 的 Pydantic 决策 schema 与五种动作 的确定性算法 如何结合现金、保证金与持仓 的预填充 hold 与 LLM 最小 Prompt 策略 读输出时的推荐顺序 在流程中的位置 提醒:输出仍是研究模拟建议,不是已成交的真实订单。 决策 Schema(源码级) 最终 为 , 解析 得到 字典。

组合管理 Agent:LLM 如何在硬约束内拍板

难度:入门

组合管理 Agent(src/agents/portfolio_manager.py 中的 portfolio_management_agent)是虚拟投委会的主持人兼拍板人。它阅读 analyst_signals 中全部研究结论(压缩为 {sig, conf}),读取风控给出的 remaining_position_limitcurrent_price,经 compute_allowed_actions 算出每种动作的最大股数,再调用 LLM 在合法动作集合内选出最终指令。

本文你将学到

  • PortfolioDecisionPortfolioManagerOutput 的 Pydantic 决策 schema
  • max_shares 与五种动作 buy/sell/short/cover/hold 的确定性算法
  • compute_allowed_actions 如何结合现金、保证金与持仓
  • generate_trading_decision 的预填充 hold 与 LLM 最小 Prompt 策略
  • 读输出时的推荐顺序

在流程中的位置

提醒:输出仍是研究模拟建议,不是已成交的真实订单。

决策 Schema(源码级)

class PortfolioDecision(BaseModel): action: Literal["buy", "sell", "short", "cover", "hold"] quantity: int # 股数,hold 时为 0 confidence: int # 0–100 reasoning: str # 简短理由,Prompt 要求 ≤100 字符 class PortfolioManagerOutput(BaseModel): decisions: dict[str, PortfolioDecision] # ticker → 决策

最终 HumanMessage.contentjson.dumps({ticker: decision.model_dump()})run_hedge_fund 解析 messages[-1] 得到 decisions 字典。

第一阶段:从风控到 max_shares

对每个 ticker:

risk_data = analyst_signals["risk_management_agent"][ticker] position_limits[ticker] = risk_data["remaining_position_limit"] current_prices[ticker] = risk_data["current_price"] max_shares[ticker] = int(position_limits[ticker] // current_price) # price>0 时

max_shares 是 buy 与 short 新增暴露的共同天花板(股数维度)。

第二阶段:压缩分析师信号

遍历 analyst_signals,跳过 risk_management_agent 键,提取:

ticker_signals[agent] = {"sig": signal, "conf": confidence}

风控条目不参与方向投票,只提供价格与限额。_compact_signals 会剔除空 Agent,减小 LLM Token。

第三阶段:compute_allowed_actions 确定性算法

对每只股票,先读取 long_sharesshort_sharescashmargin_requirement(默认 0.5)、margin_usedequity(缺省等于 cash)。

五种动作上限

动作 计算逻辑 为 0 时
buy min(max_shares, int(cash // price)) 无现金或无限额
sell long_shares(全平上限) 无多头
short min(max_shares, int(available_margin // price)),其中 available_margin = max(0, equity/margin_requirement - margin_used);若 margin_requirement≤0 则仅受 max_shares 约束 无保证金余量
cover short_shares 无空头
hold 恒合法,quantity=0 永远可用

修剪规则:容量为 0 的动作从字典删除,只保留 hold 与正容量动作,降低 Prompt 噪音。

动作语义表

action 直观含义 quantity 含义
buy 增加多头 买入股数 ≤ allowed buy
sell 减少多头 卖出股数 ≤ 持仓多头
short 增加空头(模拟) 做空股数 ≤ allowed short
cover 减少空头 买回股数 ≤ 持仓空头
hold 维持现状 固定为 0

第四阶段:generate_trading_decision 与 LLM

预填充纯 hold

若某 ticker 的 allowed_actions 仅有 {"hold": 0}(无任何可交易容量),不送 LLM,直接:

PortfolioDecision(action="hold", quantity=0, confidence=100, reasoning="No valid trade available")

LLM Prompt 结构

System:你是 portfolio manager;输入为每票分析师信号与已校验的 allowed max qty;每票选一个 allowed action,quantity ≤ max;理由极简;只返回 JSON。

Human 注入:

  • signals:紧凑 JSON {TICKER: {agent: {sig, conf}}}
  • allowed{TICKER: {buy: N, sell: M, ...}}

失败回退

call_llmdefault_factory:解析失败时,未预填充的 ticker 全部 hold, confidence=0, reasoning="Default decision: hold",再与预填充 hold 合并。

为什么「信号多数派」≠ 自动照抄

  1. 硬约束优先:即使 10 位分析师全部 bullish,若 max_shares=0,只能 hold。
  2. 动作类型受限:有多头时才能 sell;有空头时才能 cover;short 受保证金方程约束,可能与 bullish 信号冲突时出现「看多但无法加仓」。
  3. LLM 折中:Prompt 未要求「服从多数票」,只要求在 allowed 内择优;低置信度分歧时可能选小仓位 buy 或 hold。
  4. quantity 独立:signal 是方向,quantity 由限额与 LLM 综合决定,非信号张数的简单函数。

读输出推荐顺序

  1. decisions[TICKER].actionquantity
  2. 对照 analyst_signals 找分歧最大的 Agent 及其 reasoning
  3. risk_management_agent[TICKER].reasoning 中的 combined_position_limit_pctremaining_limit
  4. 若困惑,重放 allowed_actions 逻辑:是现金、保证金还是波动率卡住了交易

完整数据流小结

分析师并行 → analyst_signals(方向) ↓ 风控串行 → remaining_position_limit, current_price ↓ 组合管理 → max_shares → allowed_actions → LLM → PortfolioDecision ↓ messages[-1].content → run_hedge_fund 返回 decisions

源码函数索引

函数名 作用
portfolio_management_agent 主入口,汇总信号、算 max_shares、调用 LLM
compute_allowed_actions 确定性计算五种动作的最大合法股数
generate_trading_decision 预填充 hold、构造 Prompt、合并 LLM 输出
_compact_signals 剥离冗余字段,仅保留 sig 与 conf

多组合扩展说明

agent_idportfolio_manager_ 为前缀(可视化编辑器场景),风控键名自动映射为 risk_management_agent_{suffix},保证每个组合经理读取配对的风控输出。CLI 默认使用无前缀的 portfolio_managerrisk_management_agent

调试建议

对比 analyst_signals 中某 ticker 的各 Agent signal 字段与最终 decisions[TICKER].action:若 action 为 hold 而多数分析师 bullish,优先检查 allowed_actions 是否只剩 hold——这通常意味着风控限额或现金已耗尽,而非 LLM「不听话」。

本章收束

Agent 体系三层结构至此完整:人格与专题负责观点,风控负责界线(波动率 × 相关性 → 美元上限),组合负责拍板(五种动作 + 股数 + 置信度 + 理由)。风控算的是「还能花多少钱」,组合算的是「这笔钱买还是卖、买多少」。LLM 只在合法动作集合内行使自由裁量,工程约束始终优先。

请打开上手实践支柱《AI 对冲基金上手实践》,目录名 03-hands-on,把本章结构跑成终端里的一次真实输出。


发布者: 作者: virattt 转发
评论区 (0)
U