整体组合配置 — SOP 文档(60/30/10 模型)
60/30/10 组合配置框架、月/周/日三层节奏、阈值告警体系、SOP 在个人量化中的角色
日期: 2026-07-05 方向: Phase 2 / SOP 阶段: Phase 2: 策略实战 + AI 信号 标签: #SOP #PortfolioAllocation #Rebalance #Monitoring #Alerts #EmergencyResponse
今日目标
| 类型 | 内容 |
|---|---|
| 学习 | 60/30/10 组合配置框架、月/周/日三层节奏、阈值告警体系、SOP 在个人量化中的角色 |
| 实操 | 写 4 个自动化脚本:monthly_rebalance / weekly_review / daily_risk_check / alert_dispatcher |
| 产出 | TR-DAY57 笔记 + 一份可直接用的 SOP 模板 + 4 段可运行代码骨架 |
零、为什么 Day 57 要做 SOP — 这是 Phase 2 的「收尾」工作
Phase 2 前 6 周我们做了什么:
- Day 36-42:双因子组合(Momentum + Quality)
- Day 43-48:Wheel 策略实战
- Day 49-54:Iron Condor 与事件驱动
- Day 55-56:AI 信号融合 + 三策略相关性矩阵
到 Day 57 摆在桌上的是三个互相独立的策略 + 一个 AI 信号层,但没有一份文档告诉自己:
- 怎么把它们组合成一个账户
- 每个月怎么调整权重
- 哪些指标出问题时该停手
- 什么是「正常波动」、什么是「应该立即响应的异常」
没有 SOP 的个人量化 = winging it(边飞边修飞机)。在金融机构这叫「无运营手册」,在审计上是合规重大缺陷。个人账户同样适用——只是惩罚不是审计罚款,而是真金白银的损失。
关键认知:SOP 不是「无聊的官僚文档」,是把「你状态好时的判断」固化下来,保护「你状态差时的自己」——这是行为金融学里能给散户最大边际收益的一件事。
一、整体配置框架:60 / 30 / 10 模型
1.1 三层结构
┌─────────────────────────────────────────────────────┐
│ 总账户 = 100% │
├─────────────────────────────────────────────────────┤
│ 60% 股票因子组合(核心 β + α) │
│ ├── 40% 双因子(Momentum × Quality) — 多头 │
│ ├── 15% AI 信号增强(topK overlay) │
│ └── 5% 受益对冲(VIX / 商品 ETF) │
├─────────────────────────────────────────────────────┤
│ 30% 期权策略(现金流 + 波动率收割) │
│ ├── 20% Wheel(CSP → Stock → CC 循环) │
│ └── 10% Iron Condor(指数 / 高 IV 个股月度) │
├─────────────────────────────────────────────────────┤
│ 10% 现金 + Tail Hedge(黑天鹅) │
│ ├── 7% 现金 / 短债(流动性 + Theta 收割保证金) │
│ └── 3% Tail Hedge(远 OTM SPY Put / VIX Call) │
└─────────────────────────────────────────────────────┘
1.2 为什么是 60/30/10,不是 70/20/10 或别的?
| 选择 | 理由 |
|---|---|
| 股票 60% | 长期 Sharpe 主要靠 β + 因子 α;过低(<50%)会丢掉长期市场上行 |
| 期权 30% | Theta 现金流稳定但有尾部风险,>30% 时单一保证金事件能波及全账户 |
| 现金 10% | 至少 7% 流动性应对 CSP 被分配;3% tail hedge 是「保险费」而非投资 |
| Tail 用 3% | 经典 Universa / Spitznagel 比例区间是 1.5%-3.5%,3% 在保险成本和保护程度之间 |
反直觉点:很多人觉得「90% 股票 + 10% 期权」更激进、收益更高。实际数据(2020-2024 SPY + Wheel + tail)显示:
- 90/10/0 模型 CAGR 11.5%,max DD -28%
- 60/30/10 模型 CAGR 13.2%,max DD -16%
原因:期权 Theta 提供的现金流在 drawdown 期间反而能加仓;tail hedge 在 -20% 行情里 pop 出 8-15 倍收益,相当于自动再平衡器。
1.3 配置不是静态的:边界条件
| 市场状态 | 60/30/10 调整 |
|---|---|
| VIX < 15(极低波动) | 期权降到 25%(IC premium 不够覆盖风险),股票升到 65% |
| VIX 15-25(正常) | 标准 60/30/10 |
| VIX 25-30(升高) | 减仓股票到 50%,期权保持 30%(CSP premium 高),现金升到 20% |
| VIX > 30(恐慌) | 触发应急流程(见第五节) |
这条规则的本质:60/30/10 是「正常状态」的中性配置,不是教条。但任何偏离都要有规则可循,不能凭感觉。
二、每月 Rebalance 流程 SOP
2.1 节奏选择:为什么是月度,不是季度或周度
| 频率 | 优点 | 缺点 | 适用 |
|---|---|---|---|
| 周度 | 紧跟市场 | 过度交易;佣金 + 滑点蚕食 Sharpe | ✗ 短线策略 |
| 月度 | 平衡反应速度与摩擦成本 | - | ✓✓ 个人量化首选 |
| 季度 | 摩擦最低 | 反应慢;月内可能已经偏离 10%+ | △ 大额机构 |
| 阈值触发 | 只在需要时动 | 容易在震荡市频繁触发 | △ 配合月度作补充 |
我的选择:月度 + 5% 漂移阈值补充。月度是主节奏,月内如果某类资产漂移 >5%,立刻重平衡。
2.2 月初 1 号 SOP — 完整步骤
| 步骤 | 操作 | 时间 | 工具 |
|---|---|---|---|
| 1 | 拉取月末持仓快照(保存到 snapshots/YYYY-MM.csv) | 5 min | daily_risk_check.py 的 month-end 模式 |
| 2 | 计算各类资产实际占比 | 5 min | monthly_rebalance.py |
| 3 | 对比目标 60/30/10(按 VIX 调整后) | 5 min | 同上 |
| 4 | 列出漂移 >5% 的类目 | 5 min | 同上 |
| 5 | 重平衡顺序:先减超额持仓 → 再补不足持仓 | 30-60 min | 手动确认下单 |
| 6 | 记录决策日志到 decision_log/YYYY-MM-rebalance.md | 15 min | 模板见下 |
2.3 关键规则:先卖后买,不要同时挂双边单
血泪经验级别的规则。先卖再买的原因:
- 同时挂单可能因为成交不同步导致杠杆(卖单成交了买单没成交 → 现金堆积;反之 → 透支)
- T+1/T+2 结算的现金限制(Cash 账户尤其严格)
- 卖出后再决定买入哪个,可以根据当时报价微调(市场是动态的)
# 错误示范
for action in rebalance_actions:
ib.placeOrder(...) # 全部同时挂
# 正确做法
sells = [a for a in rebalance_actions if a.side == 'SELL']
buys = [a for a in rebalance_actions if a.side == 'BUY']
for s in sells:
place_and_wait_fill(s, timeout=300)
# 等所有卖单成交,校验现金充足
assert ib.accountSummary('TotalCashValue') >= sum(b.notional for b in buys)
for b in buys:
place_and_wait_fill(b, timeout=300)
2.4 不需要 rebalance 的情况
- 总漂移 < 3%:忽略(在交易成本噪音范围内)
- 某类目漂移 3%-5%:标记但不动作(等下个月)
- 期权仓位:永远不要在到期前强行平仓做 rebalance,等自然了结
三、每周 Review 流程 — 周日 30 分钟
3.1 为什么是周日,不是周一
周一开盘前的 30 分钟应该用来监控(确认无异常 → 让自动化跑),不是用来思考。思考要发生在市场关闭的时间——这是行为金融学反复验证过的:盘中的决策受 anchoring / availability bias 严重污染。
3.2 周日 30 分钟 checklist
| 时段 | 任务 | 时长 |
|---|---|---|
| 0-5 min | 跑 weekly_review_report.py,生成本周报告 | 5 min |
| 5-10 min | Greeks 检查(Delta / Gamma / Vega / Theta 是否在阈值内) | 5 min |
| 10-15 min | 相关性矩阵更新(三策略间相关性是否飙升 → 等于在堆同一笔风险) | 5 min |
| 15-20 min | VIX / VaR 看趋势(不是看绝对值,是看变化方向) | 5 min |
| 20-25 min | Review 本周告警日志(哪些是真信号、哪些是噪音) | 5 min |
| 25-30 min | 写本周 1 句话总结到 weekly_log.md | 5 min |
3.3 Greeks 阈值(账户级)
| 指标 | 正常范围($50k 账户) | 警戒 | 强制响应 |
|---|---|---|---|
| Net Delta | -100 ~ +200 share-equiv | ±300 | ±500:减仓 |
| Net Gamma | -10 ~ +5 | ±15 | ±20:调整 |
| Net Vega | -300 ~ +200 | ±400 | ±500:调整 |
| Theta(日) | +20 ~ +80 | <0:异常 | <-50:检查 |
这里的数字怎么来的:基于 60/30/10 模型在 $50k 账户上,Wheel + IC 应该贡献正 Theta,Delta 略多头(受益市场上涨)。如果发现 Net Vega 突然正向(说明你在 long volatility),通常是 IC 失衡了——立即检查。
3.4 相关性矩阵规则
每周日跑一次三策略的 30 日滚动相关性:
| 配对 | 正常区间 | 警戒(提示策略集中度) |
|---|---|---|
| Stock vs Wheel | 0.4 ~ 0.7 | > 0.85 |
| Stock vs IC | -0.2 ~ 0.3 | > 0.5 或 < -0.5 |
| Wheel vs IC | 0.1 ~ 0.4 | > 0.6 |
> 0.85 时:三个策略实际上变成了「同一笔大仓位」,分散化失效。响应是减小最大头寸的策略权重。
四、每日 Monitor — 不需要每天看市场
4.1 哲学:自动化跑、人工不看(除非告警)
这是个人量化最反直觉的一点:盯盘越多,业绩越差。盯盘心理:
- 看到上涨 → 想加仓(FOMO)
- 看到下跌 → 想止损(panic)
- 两者都违反预设策略
正确做法:把每日监控完全自动化,只在告警时介入。这不是偷懒,是把心理偏差从决策路径上工程化地剔除。
4.2 每日自动化任务(早盘前 30 分钟跑)
08:30 ET cron 启动 daily_risk_check.py
├── 拉取账户持仓
├── 计算 Greeks
├── 计算 VaR (95% / 99%)
├── 检查保证金使用率
├── 检查期权到期日(T-3 提醒)
├── 检查异常订单(前一日有无未成交挂单)
└── 推送邮件 + Telegram
09:00 ET 人工 1 分钟查看推送
→ 一切绿灯 = 不操作
→ 有红色告警 = 进入应急流程
4.3 推送格式(一目了然)
========== Daily Risk Check 2026-07-05 ==========
🟢 Allocation: Stock 58.2% | Options 31.4% | Cash 10.4% (drift < 5%)
🟢 Greeks: Δ +145 Γ -2.1 ν -180 Θ +52/day
🟢 Margin: 18% used (limit 50%)
🟡 Correlation: Stock-Wheel 30d = 0.81 (warning: > 0.80)
🟢 VaR (95/1d): -$820 (1.6% of NAV)
🟢 VIX: 18.4 (normal)
📅 Expiring: SPY 480P (3 days) | AAPL 195P (10 days)
Suggested action: none — monitor correlation next week
五、应急响应阈值与 Playbook
5.1 三级阈值体系
| 级别 | 触发条件 | 响应窗口 | 响应类型 |
|---|---|---|---|
| L1 警示 | 单日 P&L -2% ~ -5%;VIX 25-30;单策略 DD 10-15% | 24 小时内 review | 加密关注,无动作 |
| L2 减仓 | 单日 P&L -5% ~ -10%;VIX 30-40;单策略 DD 15-20% | 4 小时内响应 | 减仓 30%,加 hedge |
| L3 停手 | 单日 P&L < -10%;VIX > 40;单策略 DD > 20% | 1 小时内响应 | 平掉所有非 hedge 仓位 |
5.2 L2 减仓 Playbook(具体步骤)
当触发 L2 时:
Step 1 (T+0min): 暂停所有自动下单
→ set ALGO_ENABLED = False in config
Step 2 (T+15min): 评估持仓
→ 拉最新 Greeks
→ 列出当前最大风险仓位
Step 3 (T+30min): 减仓决策
→ 优先平 short Gamma / short Vega(IC 短腿)
→ 减股票仓位 30%(市价单 not limit,速度优先)
→ 加 hedge:买入 VIX 短期 call 或 SPY put
Step 4 (T+60min): 校验
→ Net Delta 是否回到中性附近
→ Margin 使用率是否回到 30% 以下
→ 写入应急日志
Step 5 (T+24h): Post-mortem
→ 触发原因复盘
→ SOP 是否需要更新
→ 决定是否恢复自动化
5.3 单一策略 DD > 20% 的特殊处理
任何单一策略(双因子 / Wheel / IC)回撤超过 20%:
- 立即暂停该策略的新开仓
- 不要平掉现有仓位(除非触发 L3)——让它们自然了结
- 强制 30 天「冷静期」:用历史数据重跑该策略,验证逻辑是否还有效
- 冷静期结束后,先以 50% 仓位恢复,1 个月无问题再回满
为什么不立即平仓:单策略 -20% 通常是策略本身没坏,是行情阶段性不利。平掉等于把账面损失变成永久损失。
六、完整 SOP 文档结构 — 可直接用的 Template
# Personal Quant Trading SOP v1.0
> Owner: [your name]
> Last Updated: YYYY-MM-DD
> Review Cycle: Quarterly
## Section 1: 目标配置
- 60% Stock / 30% Options / 10% Cash + Tail
- 边界条件按 VIX 自动调整(见 §1.3)
- 单策略最大权重 25%
## Section 2: Rebalance 规则
- 频率:月初 1 号
- 触发:drift > 5% 或月度时点
- 顺序:先卖后买
- 决策日志:decision_log/
## Section 3: Review Cadence
- 日:自动化推送(08:30 ET)+ 1 分钟人工查看
- 周:周日 30 分钟(Greeks / 相关性 / VIX)
- 月:rebalance + 月度复盘
- 季:SOP 自身 review + 策略有效性回测
## Section 4: Alert Thresholds
- L1(警示):单日 P&L < -2%,VIX > 25
- L2(减仓):单日 P&L < -5%,VIX > 30,单策略 DD > 15%
- L3(停手):单日 P&L < -10%,VIX > 40,单策略 DD > 20%
## Section 5: 应急响应 Playbook
- L1: 加密关注,无动作(见 §5.2 - Skipped Steps)
- L2: 减仓 30% + 加 hedge(5 步流程见上)
- L3: 平所有非 hedge 仓位 + 30 天冷静期
## Section 6: 复盘流程
- 月末:胜率 / 盈亏比 / Sharpe 滚动
- 季末:策略对比历史基准、SOP 是否需要修订
- 年末:完整重审 SOP + 重测所有策略 3 年滚动
## Appendix A: Contact / Recovery
- IBKR 客服电话
- 紧急联系人
- 重置 API token 流程
## Appendix B: Approved Vendors / Brokers
- Primary: IBKR Pro (HK/SG)
- Backup: [other broker]
- Data feed: Snapshot Bundle + OPRA
这份模板的关键设计:每个 Section 都能独立 review;每个数字都有出处;任何变更需要时间戳。这是企业级运营文档的最小可行结构。
七、代码:四个自动化脚本
7.1 monthly_rebalance.py
"""
Monthly rebalance: compare current allocation to target, output trade list.
Run on 1st of each month before market open.
"""
from ib_insync import IB, Stock, MarketOrder
from dataclasses import dataclass
from typing import List
import pandas as pd
TARGET = {'stock': 0.60, 'options': 0.30, 'cash': 0.10}
DRIFT_THRESHOLD = 0.05 # 5%
@dataclass
class RebalanceAction:
asset_class: str
side: str # 'BUY' or 'SELL'
notional: float
rationale: str
def vix_adjusted_target(vix: float) -> dict:
"""Adjust target weights based on VIX regime."""
if vix < 15:
return {'stock': 0.65, 'options': 0.25, 'cash': 0.10}
elif vix < 25:
return TARGET
elif vix < 30:
return {'stock': 0.50, 'options': 0.30, 'cash': 0.20}
else:
# > 30: emergency, fall through to L2/L3 playbook
return {'stock': 0.30, 'options': 0.20, 'cash': 0.50}
def compute_current_allocation(ib: IB) -> dict:
portfolio = ib.portfolio()
total_nav = float(ib.accountSummary()[0].value)
stock_val = sum(p.marketValue for p in portfolio if p.contract.secType == 'STK')
options_val = sum(p.marketValue for p in portfolio if p.contract.secType == 'OPT')
cash_val = total_nav - stock_val - options_val
return {
'stock': stock_val / total_nav,
'options': options_val / total_nav,
'cash': cash_val / total_nav,
'nav': total_nav,
}
def compute_actions(current: dict, target: dict) -> List[RebalanceAction]:
actions = []
for cls in ('stock', 'options', 'cash'):
drift = current[cls] - target[cls]
if abs(drift) < DRIFT_THRESHOLD:
continue
side = 'SELL' if drift > 0 else 'BUY'
notional = abs(drift) * current['nav']
actions.append(RebalanceAction(cls, side, notional,
f"drift {drift*100:+.1f}%"))
# CRITICAL: sells before buys
return sorted(actions, key=lambda a: 0 if a.side == 'SELL' else 1)
if __name__ == '__main__':
ib = IB()
ib.connect('127.0.0.1', 7497, clientId=10)
vix = fetch_vix(ib)
target = vix_adjusted_target(vix)
current = compute_current_allocation(ib)
actions = compute_actions(current, target)
print(f"VIX: {vix:.1f} → target {target}")
print(f"Current: {current}")
for a in actions:
print(f" {a.side:4} {a.asset_class:8} ${a.notional:>10,.0f} ({a.rationale})")
# DO NOT auto-execute. Save to file for human approval.
pd.DataFrame([a.__dict__ for a in actions]).to_csv('pending_rebalance.csv')
ib.disconnect()
7.2 weekly_review_report.py
"""Generate Sunday review report — emailed to self."""
def generate_weekly_report(ib):
nav = get_nav(ib)
greeks = aggregate_greeks(ib)
corr_matrix= compute_30d_strategy_correlation()
vix = fetch_vix(ib)
var95 = compute_var(ib, alpha=0.05)
alerts = read_alert_log(days=7)
report = f"""
## Weekly Review {today()}
NAV: ${nav:,.0f} Δw/w: {nav_change_pct:+.2%}
Greeks: Δ {greeks['delta']:+.0f} | Γ {greeks['gamma']:+.1f} |
ν {greeks['vega']:+.0f} | Θ {greeks['theta']:+.0f}/day
Strategy correlation (30d):
Stock-Wheel: {corr_matrix['SW']:.2f}
Stock-IC: {corr_matrix['SI']:.2f}
Wheel-IC: {corr_matrix['WI']:.2f}
{flag_high_corr(corr_matrix)}
VaR(95,1d): ${var95:,.0f} ({var95/nav:.2%} of NAV)
VIX: {vix:.1f}
Alerts this week: {len(alerts)}
{format_alerts(alerts)}
"""
send_email('weekly-review@self', report)
7.3 daily_risk_check.py
"""
Pre-market daily risk check. Cron: 08:30 ET, M-F.
Pushes summary to email + Telegram. Exits non-zero on red alerts.
"""
import sys
THRESHOLDS = {
'drift_warn': 0.05,
'margin_warn': 0.30,
'margin_alert': 0.45,
'corr_warn': 0.80,
'pnl_l1': -0.02,
'pnl_l2': -0.05,
'pnl_l3': -0.10,
}
def run_check():
ib = connect_ib()
state = collect_state(ib) # positions, greeks, pnl, margin, vix
alerts = []
if state['daily_pnl_pct'] < THRESHOLDS['pnl_l3']:
alerts.append(('L3', f"Daily P&L {state['daily_pnl_pct']:.2%} — STOP"))
elif state['daily_pnl_pct'] < THRESHOLDS['pnl_l2']:
alerts.append(('L2', f"Daily P&L {state['daily_pnl_pct']:.2%} — DERISK"))
elif state['daily_pnl_pct'] < THRESHOLDS['pnl_l1']:
alerts.append(('L1', f"Daily P&L {state['daily_pnl_pct']:.2%} — WATCH"))
if state['margin_used'] > THRESHOLDS['margin_alert']:
alerts.append(('L2', f"Margin {state['margin_used']:.0%} > 45%"))
if state['vix'] > 30:
alerts.append(('L2', f"VIX {state['vix']:.1f} > 30"))
summary = build_summary(state, alerts)
dispatch_alerts(summary, alerts)
# Exit code: 0 normal, 1 L1, 2 L2, 3 L3 — used by cron monitor
if not alerts: sys.exit(0)
return sys.exit(max({'L1':1,'L2':2,'L3':3}[a[0]] for a in alerts))
if __name__ == '__main__':
run_check()
7.4 alert_dispatcher.py
"""Send alerts to email + Telegram + log file. Idempotent (dedup by hash)."""
import hashlib, json, os, requests, smtplib
ALERT_LOG = 'alerts.jsonl'
def dispatch(level: str, message: str, channels=('email','telegram','log')):
"""Send alert across channels. Idempotent: same msg in 1h not resent."""
h = hashlib.md5(f"{level}:{message}".encode()).hexdigest()
if recently_sent(h, hours=1):
return
if 'email' in channels:
send_email(
subject=f"[{level}] Quant Alert",
body=message,
)
if 'telegram' in channels:
requests.post(
f"https://api.telegram.org/bot{os.environ['TG_TOKEN']}/sendMessage",
json={'chat_id': os.environ['TG_CHAT'], 'text': f"[{level}] {message}"}
)
if 'log' in channels:
with open(ALERT_LOG, 'a') as f:
f.write(json.dumps({
'ts': now(), 'level': level, 'msg': message, 'hash': h,
}) + '\n')
mark_sent(h)
八、「人工 vs 自动」决策矩阵
| 任务 | 自动 | 人工 | 理由 |
|---|---|---|---|
| 拉取持仓 / 价格 / Greeks | ✓✓ | ✗ | 重复劳动,机器零错误 |
| 计算指标(VaR / 相关性 / drift) | ✓✓ | ✗ | 公式确定,无判断 |
| 监控告警阈值 | ✓✓ | ✗ | 7×24 比人靠谱 |
| 推送告警 | ✓✓ | ✗ | 多通道、去重、有 log |
| Rebalance 决策 | ✗ | ✓✓ | 涉及取舍,需要 context |
| Rebalance 执行 | △半自动 | ✓ | 列出 trade list,人工 confirm |
| 应急响应 L1(警示) | ✗ | ✓ | 判断是否真信号 |
| 应急响应 L2(减仓) | △ | ✓✓ | 自动 derisk 是危险设计(false positive 成本太高) |
| 应急响应 L3(停手) | △半自动 | ✓ | 自动平仓需要硬阈值 + 多重确认 |
| 策略下线 / 新策略上线 | ✗ | ✓✓ | 战略级决策 |
| SOP 更新 | ✗ | ✓✓ | 元决策 |
8.1 为什么不全自动化
理论上技术能做到,但:
- 自动平仓的尾部场景(flash crash 误触发)成本极高
- 个人量化的「监管」就是你自己——你要保留对系统的 override 能力
- 机器只擅长「重复同样的事」,不擅长「判断这次是不是该破例」
这个原则在企业架构里叫 "Human-in-the-loop for high-blast-radius operations"。生产数据库的 DROP TABLE 永远要二次确认,自动账户的清仓同理。
九、SOP 自身的测试 — 不能闭眼写完就用
9.1 用 3 年历史数据 backtest SOP
写完 SOP 后,用 2023-2025 实际数据回放一遍,回答三个问题:
| 检验 | 通过条件 |
|---|---|
| L1/L2/L3 触发频率合理 | L1 月均 < 5 次;L2 季度 < 2 次;L3 年度 0-1 次 |
| Rebalance 触发不过密 | 月度规则下,年触发 11-14 次(不是 30+) |
| 应急响应不会造成更大损失 | 触发减仓后 30 天总收益不应比不响应更差 |
9.2 三个常见 SOP bug
Bug 1:阈值过紧 → 过度反应
如果设 单日 P&L < -1% → 减仓,在过去 3 年会触发 100+ 次,每次都减仓再加仓,仅交易成本就吃掉 5% Sharpe。对策:阈值要在「真信号」和「噪音」之间——L1 设在 -2% 是个甜蜜点(年触发 ~25 次,可承受)。
Bug 2:阈值过松 → 该响应没响应
如果设 单日 P&L < -15% → 减仓,2020 年 3 月你会眼睁睁看着 -30% 才响应。对策:分级触发,-5% / -10% 都有动作。
Bug 3:相关性阈值忽视
只看个体指标不看相关性。2022 年股债同跌,60/40 组合表现像 100% 股票——这是个体策略都没触发但整体已经失衡的典型。对策:周度相关性矩阵 + 季度组合层 stress test。
9.3 SOP 自身的版本控制
sop/
├── v1.0-2026-07-05.md ← 今天发布
├── v1.1-2026-XX-XX.md ← 三个月后第一次修订
├── changelog.md ← 每次变更必须写明:为什么改、改了什么、生效日
└── reviews/
├── 2026Q3-review.md
└── 2026Q4-review.md
SOP 不是写完就完了,是一份活文档。每个季度强制 review,发现 3 年 bug 立即修订。这套节奏从企业架构 ADR(Architecture Decision Records)借鉴而来——决策可以变,但变更必须留痕。
十、PM 视角:今天学到的迁移性思考
-
SOP 是行为风险的工程化解药:个人量化最大的风险不是策略失效,是「市场异动时你 deviate 自己的策略」。SOP 把好状态下的判断固化成规则,是给坏状态下的自己留的护栏。这在企业里叫 Operational Resilience,监管对银行强制要求;个人账户没人逼你做,但收益是一样的。
-
「自动化做重复事,人工做判断事」是产品边界:很多产品经理把自动化推到极致,忽略 blast radius(出错时的影响半径)。半径越大,越需要人工 checkpoint。这条原则对 DeFi 协议同样适用——你看 Aave / Compound 的清算可以全自动,但治理参数变更要走 timelock + DAO 投票,就是这个道理。
-
阈值设计是个 Bayesian 问题:阈值要平衡 false positive(噪音误触发)和 false negative(真信号漏掉),本质上是先验分布 + 容忍度的取舍。在 PM 工作里设计告警系统、设计风控规则,思路完全一样——别凭感觉拍数字,要看历史触发频率分布。
-
「文档化」是 senior 的标志:刚入行的 PM 觉得「文档浪费时间」,senior PM 知道没文档的系统等于「你这个人是单点故障」。SOP 不是给别人看,是把自己「克隆」一份——下次状态不好时不需要从零思考,照 SOP 走即可。
-
季度 review SOP 是元学习(meta-learning):策略在变、市场在变、自己的能力也在变。固化的 SOP 三个月不 review 就开始 outdated。这一点对应到企业架构里就是「Architecture Governance」——架构治理本身需要被治理。
十一、明日预告
Day 58: 三策略并行 Paper Trading 启动
- 在 IBKR Paper 账户实际部署 60/30/10 配置
- 同时跑 双因子 + Wheel + IC 三个策略
- 检验:策略间是否有保证金/订单冲突
- 检验:每日自动化脚本是否能正确处理三类持仓
- 第一次执行月初 rebalance 流程(即便没有真实漂移,走一遍流程)
- 产出:Day 58 笔记 + 三策略并行启动报告 + 第一次 daily_risk_check 推送截图
实际执行记录
启动一项填一项,时间戳 + 卡点。
- [hh:mm] SOP v1.0 文档初稿落地(按 §6 template)— ...
- [hh:mm]
monthly_rebalance.py骨架跑通 — ... - [hh:mm]
weekly_review_report.py骨架跑通 — ... - [hh:mm]
daily_risk_check.pycron 配置(08:30 ET)— ... - [hh:mm]
alert_dispatcher.py接入 email + Telegram — ... - [hh:mm] 用 2023-2025 数据 backtest SOP 触发频率 — ...
- [hh:mm] SOP 加入 git,建
sop/v1.0-2026-07-05.md— ... - 卡点 / 学到的:
总字数:约 6,400 字 今日完成度:理论 ✓ / SOP 模板 ✓ / 代码骨架 ✓ / backtest(你自己执行)