风险管理 Agent:波动率与相关性如何换算仓位上限 难度:入门 风险管理 Agent( 中的 )是固定决策层的第一道闸门。无论分析师们多么一致地看多,它都会先问:这只股票波动有多大、与现有持仓相关性多高、按规则最多还能暴露多少美元。它把「观点」翻译成 (剩余可建仓美元上限),供组合管理换算为 。 本文你将学到 为什么风控在 里串行且始终存在 波动率指标的真实计算公式(日波动、年化、百分位) 与 的分段逻辑 从组合净值到现金约束的完整链路 风控输出如何写入 在流程中的位置 与塔勒布等人格 Agent 不同:人格讨论「该不该碰这类脆弱资产」,风控做工程化限额——「碰了也不能超过组合 X%」。 第一阶段:拉价与算波动率 对 中每个标的: → 。
难度:入门
风险管理 Agent(src/agents/risk_manager.py 中的 risk_management_agent)是固定决策层的第一道闸门。无论分析师们多么一致地看多,它都会先问:这只股票波动有多大、与现有持仓相关性多高、按规则最多还能暴露多少美元。它把「观点」翻译成 remaining_position_limit(剩余可建仓美元上限),供组合管理换算为 max_shares。
create_workflow 里串行且始终存在calculate_volatility_adjusted_limit 与 calculate_correlation_multiplier 的分段逻辑remaining_position_limit 从组合净值到现金约束的完整链路analyst_signals与塔勒布等人格 Agent 不同:人格讨论「该不该碰这类脆弱资产」,风控做工程化限额——「碰了也不能超过组合 X%」。
对 tickers ∪ portfolio.positions.keys() 中每个标的:
get_prices(start_date, end_date) → prices_to_df。0.05×√252、百分位 100(视为高风险)。calculate_volatility_metrics(prices_df, lookback_days=60)。| 步骤 | 公式/逻辑 |
|---|---|
| 日收益 | close.pct_change().dropna() |
| 近期样本 | 取最后 min(60, len) 个交易日 |
| 日波动 | recent_returns.std() |
| 年化波动 | daily_vol × √252 |
| 波动百分位 | 若历史 ≥ 30 日:算 30 日滚动波动序列,当前日波动在其中的百分位 (rolling_vol <= daily_vol).mean() × 100;否则默认 50 |
同时保存 returns_by_ticker[ticker] = daily_returns,供相关性矩阵使用;current_prices[ticker] = close.iloc[-1]。
当至少 2 个 ticker 有收益序列时:
returns_df = pd.DataFrame(returns_by_ticker).dropna(how="any") correlation_matrix = returns_df.corr() # 需 ≥2 列且 ≥5 行
对每个待交易 ticker,取可比对象:
active_positions(|long - short| > 0)记录 avg_correlation_with_active、max_correlation_with_active、Top3 相关标的。
total_portfolio_value = cash + Σ(long_shares × price) - Σ(short_shares × price)
这是风险限额计算的基数,不是分析师信号的一部分。
对每个 tickers 中的标的:
long_value = long × current_price short_value = short × current_price current_position_value = |long_value - short_value|
vol_adjusted_limit_pct = calculate_volatility_adjusted_limit(annualized_vol)
| 年化波动区间 | vol_multiplier | 实际占比(base=20%) |
|---|---|---|
| < 15% | 1.25 | 最高约 25% |
| 15%–30% | 1.0 - (vol-0.15)×0.5 | 约 20% → 12.5% |
| 30%–50% | 0.75 - (vol-0.30)×0.5 | 约 15% → 5% |
| ≥ 50% | 0.50 | 约 10% |
| 边界钳制 | max(0.25, min(1.25, ×)) | 最终 5%–25% |
corr_multiplier = calculate_correlation_multiplier(avg_corr)
| 平均相关系数 | 乘数 | 含义 |
|---|---|---|
| ≥ 0.80 | 0.70 | 高度同涨同跌, sharply 缩仓 |
| 0.60–0.80 | 0.85 | 明显相关,适度缩仓 |
| 0.40–0.60 | 1.00 | 中性 |
| 0.20–0.40 | 1.05 | 略增分散化奖励 |
| < 0.20 | 1.10 | 低相关,略放宽 |
combined_limit_pct = vol_adjusted_limit_pct × corr_multiplier position_limit = total_portfolio_value × combined_limit_pct remaining_position_limit = position_limit - current_position_value max_position_size = min(remaining_position_limit, cash)
注意:最终写入的是 remaining_position_limit 字段,值为 max_position_size(已考虑现金上限)。组合管理用 int(remaining_position_limit // current_price) 得 max_shares。
每个 ticker 的风险条目示例字段:
| 字段 | 类型 | 含义 |
|---|---|---|
| remaining_position_limit | float | 剩余可买/可加仓美元(已 min 现金) |
| current_price | float | 最新收盘价 |
| volatility_metrics | dict | daily/annualized vol、percentile、data_points |
| correlation_metrics | dict | 平均/最大相关、top_correlated_tickers |
| reasoning | dict | portfolio_value、position_limit、各中间量 |
风控不产出 bullish/bearish 信号;它的角色是约束容器,不是方向裁判。
| 场景 | 风控行为 |
|---|---|
| 所有人强烈看多 | remaining_position_limit 仍可能被波动率压低 |
| 标的年化波动 > 50% | vol_multiplier ≈ 0.5,单票上限约组合 10% |
| 新股与持仓高度相关(avg_corr ≥ 0.8) | 再 × 0.7,实质限额约砍三成 |
| 现金不足 | min(remaining, cash) 直接卡死可加仓位 |
| 无价格数据 | remaining_position_limit = 0,组合管理只能 hold |
portfolio_manager.py 读取:
risk_data = analyst_signals["risk_management_agent"][ticker] position_limits[ticker] = risk_data["remaining_position_limit"] max_shares[ticker] = int(position_limits[ticker] // current_price)
LLM 选的 quantity 必须 ≤ allowed_actions 中对应动作的上限,而上限源头就是本章算法。
| 函数名 | 作用 |
|---|---|
risk_management_agent |
主入口,协调拉价、算波动、建相关矩阵、输出限额 |
calculate_volatility_metrics |
从 OHLC 收盘价序列提取波动三指标 |
calculate_volatility_adjusted_limit |
年化波动 → 组合占比上限 |
calculate_correlation_multiplier |
平均 Pearson 相关 → 乘数调整 |
开启 show_reasoning=True 运行 CLI 时,终端会打印 risk_analysis 全量字典。重点查看 reasoning.risk_adjustment 字符串,其中同时展示 combined_position_limit_pct 与 base_position_limit_pct,便于理解相关性是否在波动率基础上进一步压缩了额度。
风险管理 Agent 是可审计的「安全栏」:60 日收益标准差 → 年化波动 → 分段仓位比例 → 相关性乘数 → 美元限额 → 现金钳制。它从不推翻分析师的看多或看空,只回答「在现有组合状态下还能承担多少名义暴露」。一致看多不等于满仓;下一层组合管理才在硬约束内做 buy / sell / short / cover / hold 终局选择。
下一篇请阅读同目录下的《组合管理 Agent:最终交易建议如何生成》(文件名 17-portfolio-manager.md)。