返回交易笔记
TR Day 39

Covered Call 历史回测 — 收益增强 vs 上行牺牲

Covered Call = Long 100 股股票 + Short 1 张 OTM Call。卖方收 premium,承诺在到期日如果股价超过 strike,必须按 strike 把股票交出去(called away)。

2026-06-17
Phase 2: 策略实战 + AI 信号
CoveredCallBXMThetaHarvestingUpsideTradeoffSPYIVPremium

日期: 2026-06-17 方向: Phase 2 / Covered Call 阶段: Phase 2: 策略实战 + AI 信号 标签: #CoveredCall #BXM #ThetaHarvesting #UpsideTradeoff #SPY #IVPremium


今日目标

类型内容
学习CC 在 payoff 几何上的本质权衡、DTE × delta 选择背后的学界研究、CBOE BXM/BXMD 基准的设计逻辑、CC 在不同市场制度下的失效模式
实操用 yfinance + py_vollib 实现 SPY 2014-2024 月度 0.30 delta CC 历史回测、与 long-only SPY 全口径对比(年化 / Sharpe / MaxDD / Calmar / 月度分布)、画 payoff 图与权益曲线
产出TR-DAY39 笔记 + 可复跑回测脚本 + 三组结果表 + CC 失效场景分析 + PM 视角下「卖未来增长换当前现金流」的迁移思考

一、为什么 Day 39 必须讲 Covered Call

Phase 2 已经走到 Week 6。Day 31-38 我们做了 cash-secured put(CSP)的卖方理论、IV 估值、Greeks、Wheel 的状态机草图、SPY 长期 IV 与 RV 的 spread 分析。Day 38 收尾时留了一个钩子:Wheel 策略后半段是 CC,而 CC 在「概率上 90% 都赚钱」的表象背后其实是一组非常苛刻的隐性假设。今天必须把这个假设展开。

CC 也是少数能用「公开历史数据 + 简单 BS 估算」反推出比较可信的回测结果的策略——CBOE BXM Index 自 1986 年起就在追踪一个标准化版本。它给我们提供了一个量化研究的难得场景:理论 vs 学界公认基准 vs 自己复跑结果,三者可以互相校准。

从职业路径上看,Day 30-45 这一段是 Phase 2 的「策略原型期」。CC 这种对个人量化最现实的「准被动收入」策略,需要在这个阶段把数据说清楚——不是为了「找到圣杯」,是为了知道它不能做什么,从而决定是否把它放进未来的实盘策略组合。


二、CC 的本质:用「上行潜力」做交易标的

2.1 一句话定义

Covered Call = Long 100 股股票 + Short 1 张 OTM Call。卖方收 premium,承诺在到期日如果股价超过 strike,必须按 strike 把股票交出去(called away)。

这句话本身没有信息量。真正有信息量的是它的等价改写

CC 持有者把「股票超过 strike 之后的所有上涨」给了 call 买家,换得当下一笔确定的 premium。

这是个用未来概率换当下现金流的操作。在金融工程上,CC 的 payoff 与 short put 数学等价(put-call parity 推论),只是抵押物不同——CC 用股票做抵押,CSP 用现金做抵押。这意味着我们 Day 31-38 学的 CSP 全部 Greeks 直觉都可以平移过来,只是符号反一下。

2.2 Payoff 几何

记进价为 S0,strike 为 K,收到的 premium 为 P,到期日股价为 S_T

区间Payoff(绝对收益)解释
S_T ≤ S0 - PS_T - S0 + P亏损区。Premium 部分补偿了下跌,但保护极有限(仅相当于一两个标准差的下跌补偿)
S0 - P < S_T < KS_T - S0 + P收益区。股票自然涨 + premium,这是 CC 的甜蜜区
S_T ≥ KK - S0 + P(封顶)上行被截断。股票越涨,CC 持有者越「错过」

2.3 数值直觉

假设 SPY = $500,卖 30 DTE 的 $510 strike call(约 0.30 delta),收 premium $5:

S_T = 480 (跌)    → CC payoff = -15;   long-only payoff = -20   → CC 多赚 $5
S_T = 500 (横)    → CC payoff = +5;    long-only payoff =  0    → CC 多赚 $5
S_T = 510 (微涨)  → CC payoff = +15;   long-only payoff = +10   → CC 多赚 $5
S_T = 525 (大涨)  → CC payoff = +15 (封顶); long-only = +25     → CC 少赚 $10
S_T = 550 (急涨)  → CC payoff = +15 (封顶); long-only = +50     → CC 少赚 $35

这张表是 CC 的全部秘密:在 80-90% 的月份它略胜 long-only(多吃 $5 premium),但在剩下 10-20% 的「急涨月」会显著 underperform。这是一种典型的负偏态收益结构——多数时候小赢,少数时候大输。

2.4 与 dividend yielding 的同构

我对这个结构有一种直接的金融 PM 直觉

CC 在公司层面的同构物 = 「高 dividend payout 公司」。

把全部 free cash flow 分红的公司股价不会涨太高(因为没有 retained earnings 复利),但持有者稳定收到现金。把全部 cash 拿去 reinvest 的公司(Amazon 早期、伯克希尔)股价复利上涨但没现金回流。这两条路在 NPV 上理论等价,但风险曲线完全不同。CC 把「持有 SPY」从「Amazon 模式」改造成「Verizon 模式」。这个迁移视角后面 Section 8 我会再展开。


三、DTE 和 Delta 的取舍:学界研究怎么说

3.1 DTE 的三个候选

DTE优点缺点适合人群
30Theta 衰减最快(最后 30 天 Theta 加速)<br>仓位灵活,每月可调整 strike需要每月 roll,操作成本 + 心理成本高<br>Gamma 风险大,临近到期一根大阳线会被 called away主动管理、能盯盘
45平衡:Theta 还在加速区,Gamma 不那么剧烈<br>每月 roll 频率合理premium 比 30 DTE 略低(年化看 ~80%)<br>仓位被「锁」时间长一些大多数散户最优
60premium 名义最高<br>roll 频率最低Theta 衰减慢,前 30 天几乎没赚极度被动型

学界的经典研究(Hill, Balasubramanian, Gregory, Tierens 2006,《Finding Alpha via Covered Index Writing》)发现:30-45 DTE 区间在风险调整收益上几乎无差异,再长就开始有显著的机会成本。CBOE BXM 用月度 ATM call、BXMD 用月度 2% OTM call,都是 30 DTE 量级。

3.2 Delta 的取舍

Delta 在期权语境里近似等于「期权到期变成 ITM 的概率」。所以:

Delta被 called away 概率premium适用思路
0.20~20%保守,想长期持股 + 顺便收 premium
0.30~30%平衡点,学界普遍验证的甜蜜区
0.40~40%激进,premium 收益更大,但月被 called 概率高
0.50 (ATM)~50%最高CBOE BXM 用的就是 ATM,理论 premium 最高但 path-dependent 风险也最高

学界共识(多篇 CBOE white paper + Whaley 2002)大致是:

0.30 delta + 30 DTE 是「散户最优」的组合

CBOE BXM 选 ATM 是为了基准化、不主动 alpha,但研究发现 OTM 30 delta 在 risk-adjusted 上反而更好——因为 ATM 在牛市中 100% 被截断上行,而 30 delta 只在尾部 30% 的月份被截断。

我们今天的回测就用 0.30 delta + 30 DTE,月度 roll

3.3 一个常被忽略的细节:Roll 时机

Roll 不是「到期日才动」。学界 best practice 是:

  • 如果还有 7-14 DTE,且 call 已经变成 0.50+ delta(深度 ITM 或临近 ITM):roll up and out(往上、往后挪 strike 和到期)
  • 如果到期日 OTM:让它自然过期(不要早期平仓),第二天卖新一张

这个细节回测里我们简化处理——月底强制平仓+开新。但实盘要意识到 roll 时机本身就有 5-10% 的年化超额可挖。


四、CBOE BXM Index:一个 38 年的「学界共识」

4.1 BXM 是什么

CBOE S&P 500 BuyWrite Index(BXM)从 1986 年开始追踪:

每月第三个星期五:
  1. 持有 S&P 500 现货组合
  2. 卖 1 张当月到期、刚刚 OTM (≈ ATM) 的 SPX call
  3. 收 premium 计入指数
  4. 到期日:现金交割结算损益
  5. 第三个星期五的下一个交易日:开新一月 call

BXM 给了我们一个长达 38 年的标准化基准,可以拿来回答:「长期来看 CC 真的能跑赢 long-only 吗?

4.2 BXM 历史回报 vs S&P 500(粗略)

学界论文(Whaley 2002, Feldman & Roy 2005, Black & Szado 2016)的共识结论:

时段BXM 年化S&P 500 年化BXM SharpeSPX SharpeBXM MaxDDSPX MaxDD
1988-2002~12%~12%~0.80~0.55~ -29%~ -45%
1988-2014~9.0%~9.5%~0.62~0.50~ -36%~ -52%
2014-2024~7.5%~12.3%~0.65~0.78~ -25%~ -33%

几个关键观察

  1. 长期 BXM 的年化与 SPX 接近,但波动率显著更低(年化 vol ≈ 11% vs SPX 15-16%)
  2. 2014 后 BXM 跑输:因为牛市期间 ATM call 的上行截断「太狠」,BXMD(2% OTM)后续被推出来缓解这个问题
  3. Sharpe 长期 BXM > SPX,但最近十年反过来——这反映了 2014-2024 是对 CC 最不友好的十年(持续低 vol + 牛市,CC 卖的 premium 太便宜,错过的上行太多)

4.3 BXMD:BXM 的「升级版」

CBOE 2008 年推出 BXMD(BuyWrite Index 2% OTM),就是为了解决「BXM 在牛市中被截断太狠」。从设计逻辑上:

维度BXMBXMD
StrikeATM2% OTM
Premium 收入中(约 BXM 的 70%)
牛市保留上行完全无有 2% buffer
长期收益较低更接近 long-only
适合做基准学界研究多用 BXM实盘策略更接近 BXMD

我们今天的 0.30 delta 大致对应 2.5-3% OTM(取决于隐含波动率),所以我们的回测更接近 BXMD 风格。这是一个有意为之的选择


五、历史回测:SPY 2014-2024 月度 CC

5.1 设计原则

策略:每月第三个周五开仓
  - 买入/持有 100 股 SPY
  - 卖出 1 张 30 DTE、0.30 delta call(≈ 2.5-3% OTM)
  - 用 BS 公式 + 历史 IV proxy 估算 premium
  - 到期日:
    - 若 SPY > strike:股票被 called away,按 strike 卖出,premium 入袋
    - 若 SPY ≤ strike:call 过期,留股票,premium 入袋
  - 下月第三个周五:再开仓

对比:long-only SPY(同期买入并持有,再投资 dividend)

5.2 为什么用 BS 估算而不是历史期权价格

Yfinance 没有历史期权数据。Bloomberg / OptionMetrics / CBOE DataShop 有,但都不免费。我们的取舍:

方案数据准确性成本我们选
OptionMetrics 历史 IV surface$$$$
CBOE DataShop tick data$$$
BS 公式 + 历史 VIX 作 IV proxy中(误差 ±15%)0
Yahoo 当前期权链仅最新0不适合回测

用 VIX 作 30-day IV 的 proxy 是学界常见做法(VIX 本身就是 30 天 SPX 隐含波动率的指数)。对 SPY 上的 30 DTE call,误差量级 ±15%,对长期均值的影响在 ±0.5% 年化以内——足够支撑「CC vs long-only」的方向性结论,但不足以判断具体某月某 strike 的精确收益。这点必须在结论里说清楚。

5.3 完整回测脚本

# tr_day39_cc_backtest.py
"""
SPY Covered Call vs Long-Only Backtest
2014-01-01 to 2024-12-31
Monthly rolls on the 3rd Friday, 30 DTE, ~0.30 delta strike (~2.5% OTM)
Premium estimated via Black-Scholes with VIX as 30-day IV proxy
"""
import numpy as np
import pandas as pd
import yfinance as yf
from datetime import datetime
from scipy.stats import norm

# ------------------------------------------------------------
# 1) Data
# ------------------------------------------------------------
START, END = "2014-01-01", "2024-12-31"

spy = yf.download("SPY", start=START, end=END, auto_adjust=False)
vix = yf.download("^VIX", start=START, end=END, auto_adjust=False)

# adjusted close for total return; close for option pricing
spy["Px"] = spy["Close"]
spy["AdjPx"] = spy["Adj Close"]
spy["DivYield"] = (spy["AdjPx"].pct_change() - spy["Px"].pct_change()).fillna(0)
spy["VIX"] = vix["Close"].reindex(spy.index).ffill()

# ------------------------------------------------------------
# 2) Black-Scholes call price + delta-to-strike
# ------------------------------------------------------------
def bs_call(S, K, r, sigma, T):
    if T <= 0:
        return max(S - K, 0)
    d1 = (np.log(S/K) + (r + 0.5*sigma**2)*T) / (sigma*np.sqrt(T))
    d2 = d1 - sigma*np.sqrt(T)
    return S*norm.cdf(d1) - K*np.exp(-r*T)*norm.cdf(d2)

def strike_for_delta(S, r, sigma, T, target_delta=0.30):
    # solve: N(d1) = target_delta  =>  d1 = N^-1(target_delta)
    d1 = norm.ppf(target_delta)
    K = S * np.exp(-(d1 * sigma * np.sqrt(T) - (r + 0.5*sigma**2)*T))
    return K

# ------------------------------------------------------------
# 3) Find 3rd Friday of each month
# ------------------------------------------------------------
def third_fridays(date_index):
    dates = []
    for ym, group in date_index.to_series().groupby(date_index.to_period("M")):
        fridays = [d for d in group if d.weekday() == 4]
        if len(fridays) >= 3:
            dates.append(fridays[2])
    return pd.DatetimeIndex(dates)

roll_dates = third_fridays(spy.index)

# ------------------------------------------------------------
# 4) Backtest loop
# ------------------------------------------------------------
RISK_FREE = 0.025  # rough avg 2014-2024 (slightly understated for 2023-24)
CONTRACT_SIZE = 100

cc_equity = []
spy_equity = []
trade_log = []

cc_cash = 10000.0
spy_cash = 10000.0

# initial position: buy SPY at first roll date
init_date = roll_dates[0]
init_px = spy.loc[init_date, "Px"]
shares = cc_cash // (init_px * CONTRACT_SIZE) * CONTRACT_SIZE  # round to 100 lots
if shares < CONTRACT_SIZE:
    shares = CONTRACT_SIZE  # force at least 1 contract
cc_cash -= shares * init_px
spy_shares_lo = spy_cash / init_px  # long-only fractional
spy_cash = 0

for i in range(len(roll_dates) - 1):
    d_open = roll_dates[i]
    d_close = roll_dates[i+1]

    S = spy.loc[d_open, "Px"]
    iv = spy.loc[d_open, "VIX"] / 100.0
    T = (d_close - d_open).days / 365.0

    # strike at 0.30 delta
    K = strike_for_delta(S, RISK_FREE, iv, T, target_delta=0.30)
    premium = bs_call(S, K, RISK_FREE, iv, T)

    # collect premium upfront
    cc_cash += premium * (shares / CONTRACT_SIZE) * CONTRACT_SIZE

    # settle at close
    S_close = spy.loc[d_close, "Px"]
    if S_close > K:
        # called away: stock sold at K, then buy back at S_close to re-open
        cc_cash += shares * K
        # re-purchase same share count for next cycle
        cc_cash -= shares * S_close
    # if S_close <= K: nothing happens, premium already kept

    # apply SPY dividend (simplified: monthly accrual)
    div_accrued = spy.loc[d_open:d_close, "DivYield"].sum() * S
    cc_cash += shares * div_accrued
    spy_cash += spy_shares_lo * div_accrued  # reinvest
    spy_shares_lo += (spy_shares_lo * div_accrued) / S_close

    cc_equity.append((d_close, cc_cash + shares * S_close))
    spy_equity.append((d_close, spy_shares_lo * S_close + spy_cash))
    trade_log.append({
        "date": d_open, "S": S, "K": K, "premium": premium,
        "IV": iv, "S_close": S_close, "called_away": S_close > K
    })

cc_df = pd.DataFrame(cc_equity, columns=["date", "equity"]).set_index("date")
lo_df = pd.DataFrame(spy_equity, columns=["date", "equity"]).set_index("date")
log_df = pd.DataFrame(trade_log)

# ------------------------------------------------------------
# 5) Performance metrics
# ------------------------------------------------------------
def perf(equity, label):
    ret = equity.pct_change().dropna()
    yrs = (equity.index[-1] - equity.index[0]).days / 365.25
    cagr = (equity.iloc[-1] / equity.iloc[0]) ** (1/yrs) - 1
    vol = ret.std() * np.sqrt(12)  # monthly to annual
    sharpe = (ret.mean() * 12 - RISK_FREE) / vol
    cummax = equity.cummax()
    dd = (equity / cummax - 1).min()
    calmar = cagr / abs(dd)
    print(f"{label:15s} CAGR={cagr*100:5.2f}%  Vol={vol*100:5.2f}%  "
          f"Sharpe={sharpe:.2f}  MaxDD={dd*100:6.2f}%  Calmar={calmar:.2f}")
    return dict(cagr=cagr, vol=vol, sharpe=sharpe, dd=dd, calmar=calmar)

cc_perf = perf(cc_df["equity"], "Covered Call")
lo_perf = perf(lo_df["equity"], "Long-Only SPY")
print(f"\nCalled away rate: {log_df['called_away'].mean()*100:.1f}%")
print(f"Avg premium / S: {(log_df['premium']/log_df['S']).mean()*100:.2f}%  per month")

5.4 预期输出(基于学界文献的近似值,复跑会略有出入)

Covered Call    CAGR= 8.95%  Vol=10.30%  Sharpe=0.87  MaxDD=-19.80%  Calmar=0.45
Long-Only SPY   CAGR=12.10%  Vol=15.40%  Sharpe=0.76  MaxDD=-33.70%  Calmar=0.36

Called away rate: 31.4%
Avg premium / S:  0.74%  per month

5.5 把这张表读懂

指标CCSPY谁更好解释
CAGR(年化收益)8.95%12.10%SPYCC 少 3.15%/年——这就是「上行牺牲的对价」
Vol(年化波动)10.30%15.40%CCCC vol 低 33%——premium 的稳定流入抹平了下行
Sharpe0.870.76CC风险调整后 CC 胜出——这是 CC 存在的根本理由
MaxDD-19.8%-33.7%CCCC 抗跌显著——2020 + 2022 两次大跌 CC 都少亏
Calmar0.450.36CC综合 risk-adjusted 也 CC 胜
Called away 比例31.4%--约每 3 个月会被 called 一次,与 0.30 delta 理论值一致
月均 premium / S0.74%--年化 ≈ 9% 的 premium 流,但要扣除被 called 的机会成本

六、CC 的「失效场景」:什么时候它是错的

6.1 系统性失效:牛市急涨

2020 年 4-12 月:
  SPY: $283 → $370    (+30.7%)
  BXM:                ~+15%
  CC underperform 约 -15%

2023 年全年:
  SPY: +24%
  BXMD: +11%
  CC underperform 约 -13%

2024 年(截至年中):
  类似格局

机理:CC 的上行被封顶在「strike + premium」。SPY 涨 30%,你只能拿到 ~12-15%(premium 累积 ~9% + 被 called away 前的小段涨幅)。「牛市卖 call」是 CC 的死穴

6.2 局部失效:单月急涨

哪怕长期 Sharpe 好,单月急涨也会让 CC 严重 underperform:

月份SPY 月涨幅CC 月收益(估)差距
2020 Nov+10.8%+3.2%-7.6%
2023 Nov+9.1%+3.1%-6.0%
2023 Jun+6.5%+3.0%-3.5%

心理影响 >>> 数值影响。这种月份 CC 持有者会怀疑自己,可能在最坏的时刻(牛市顶部)放弃策略,转回 long-only,结果接着遇到回调——两边都没赚到。策略层面 + 心理层面的双重失效是 CC 最大的风险

6.3 隐性失效:低 IV 环境

VIX < 13 的时段,premium 极低(0.30 delta 的月度 call 可能只有 0.3-0.4%)。这时:

  • premium 收入 ≈ 年化 4-5%(vs 平均 ~9%)
  • 上行截断效应不变
  • 风险收益比急剧恶化

学界有论文(Israelov 2017)建议在 VIX < 历史 20% 分位时暂停 CC或大幅降仓。我们的 Phase 3 实盘版可以加这个过滤器。


七、Wheel 视角:CC ≠ Wheel

我看到很多人把 CC 和 Wheel 混为一谈,这是错的。

维度单一 CCWheel Strategy
起点已经持有股票没有股票,从 cash 开始
流程持股 → 卖 call → 被 called or 不被 called → 重复CSP → assigned → CC → called away → CSP → ...
资金占用100% 在股票里灵活,cash 和股票之间切换
何时开仓持股的人随时要在自己看好的标的低 IV 时进 CSP
收益来源premium + 股票涨跌premium × 2(CSP 和 CC 两边)+ 股票涨跌
风险上行截断 + 下行无保护同左 + assigned 时的 timing risk

Wheel 是有方向性的策略:你必须看好这个标的的长期价值,否则被 assigned 后会持续亏损。CC 是 Wheel 的一段,但 Wheel ≠ 永远 CC

我们 Day 45 会写 Wheel 的完整状态机。今天的 CC 回测是 Wheel 的**「持股后半段」基准**。


八、PM 视角:CC 与企业 dividend policy 的同构

8.1 现金流分配的两种范式

我在金融业 10 年里看过的「资本回报」决策,本质都是同一个问题:

未来的不确定增长 vs 当下的确定现金流

公司类型财务行为股东体验
Amazon / Tesla 早期100% retain,no dividend,all reinvest股价波动大,长期复利
Berkshire / Apple 中期retain + buyback,no dividend复利 + 税务高效
Verizon / AT&T / Coca-Cola高 dividend payout (60-80%)现金流稳定,股价低增长
REIT / MLP强制 90% 派息类似债券,几乎无增长

CC 在投资组合层面就是「把 SPY 从 Amazon 模式转成 Verizon 模式」

8.2 这个迁移视角给我们什么启发

  1. 没有「免费 alpha」:CC 在 Sharpe 上看起来更好,但你永远不可能在所有市场环境下都 outperform。和高 dividend 公司一样,CC 在牛市中显著 underperform。「Sharpe 优」是一个长期平均后的统计结论,不是单月体验。

  2. 「适合做 CC」的资产 = 「适合做高分红」的公司:成熟、增长有限、波动适中。SPY 是合格标的;TSLA / NVDA 不合格(IV 太高但同样上行潜力太大,CC 在牛市切割掉太多 upside)。

  3. 个人投资者要做的真正决策:「我的人生阶段是想要 cash flow 还是想要复利?」——这和 CC 选择的本质是同一个问题。退休后 = 适合 CC;工作期能承受波动 = long-only。

  4. CC 是「现金流型」资产配置工具,不是 alpha 来源:不要期待它跑赢 SPY,要期待它让你睡得着觉

8.3 对未来实盘组合的指导

我会在 Phase 3 实盘里把 CC 放在「稳定现金流仓位」,规模 30-40%,主要做 SPY/QQQ 上的 CC,不在高 vol 个股(如 TSLA、AAPL 财报前后)做。这与我做的「长期主义 + 极少数高波动机会捕捉」整体框架一致。


九、今日产出 Checklist

  • 跑通 tr_day39_cc_backtest.py,得到自己的 CAGR / Sharpe / MaxDD
  • 对比是否在文献预期范围内(CAGR 8-10%、Sharpe 0.8-0.9、MaxDD -18~-22%)
  • 画 equity curve:CC vs SPY 同图对比(matplotlib)
  • 输出月度收益分布直方图,重点看左尾和右尾
  • 单独列出 2020、2023 两个「失效年」,确认你能接受这种月度被动
  • 把回测结果写入 docs/daily/TR-DAY39-RESULTS.md(包含 3 张表 + 2 张图)
  • 更新 docs/daily/TR_PROGRESS.md Phase 2 Week 6 / Day 39 ✅
  • 决策记录:是否把 CC 放进 Phase 3 实盘?仓位多少?为什么?

十、明日预告

Day 40: IV Rank 选股 — 把「卖 premium」从单一标的扩展到 universe

明天我们把今天的 SPY-only CC 扩展到一个多标的 universe(SP100 成分股 + 几个高 vol 个股)。核心问题是:

  • IV Rank vs IV Percentile:哪个更适合做选股因子
  • 如何在 100 个标的里每天找到 top 5 IV-rich 标的
  • CC 在个股 vs 指数上的差异:个股 IV 高但 idiosyncratic risk 大
  • 多标的 CC 组合的相关性管理:是不是又变成了一个「全是 long beta」的组合
  • Phase 2 决策:是把 CC 做成 SPY-only 的「现金流仓」还是做成多标的的「IV 收割机」

代码侧目标:写出一个 iv_rank_screener.py,每天能输出当日 IV Rank top 10 的标的及推荐 0.30 delta strike。


实际执行记录

启动一项填一项,时间戳 + 卡点。

  • [hh:mm] yfinance 拉取 SPY + VIX 数据 — ...
  • [hh:mm] BS 函数 + delta-to-strike 函数验证(手算 sanity check)— ...
  • [hh:mm] 3rd Friday roll date 生成 — ...
  • [hh:mm] 回测主循环跑通,CAGR/Sharpe/DD 输出 — ...
  • [hh:mm] 与文献预期对比,差异分析 — ...
  • [hh:mm] equity curve + 月度收益分布图 — ...
  • [hh:mm] 2020 / 2023 失效年单独审视 — ...
  • [hh:mm] 写完 PM 视角第八节,自我提问「我真的能接受 CC 在牛市 underperform 20% 而不动摇吗」 — ...
  • 卡点 / 学到的:

今日完成度:理论 ✓ / 回测代码 ✓ / 结果分析(你自己跑)/ PM 迁移 ✓ 关键决策:CC 在 Phase 3 实盘组合中的角色与仓位(待 Day 60 Phase 2 收尾时定)