实战 — 低 IV Rank 时 Long Calendar
Long Calendar 的入场触发体系(VIX + IVR 双条件)、theta/vega/gamma 的同时摆位、退出三场景的决策树
日期: 2026-07-19 方向: Phase 3 / Calendar 实战 阶段: Phase 3: 实盘+规模化+迁移 标签: #Calendar #LongVol #IVRank #SPY #ATMCalendar #ComboOrder #PaperTrade
今日目标
| 类型 | 内容 |
|---|---|
| 学习 | Long Calendar 的入场触发体系(VIX + IVR 双条件)、theta/vega/gamma 的同时摆位、退出三场景的决策树 |
| 实操 | 在 paper 账户开第一张 SPY ATM Calendar(14/60 DTE,net debit ~$3.50) + 写 calendar_paper.py 自动监控 |
| 产出 | TR-DAY71 笔记 + 可运行的 calendar 监控脚本 + 三个 exit scenario 的判定规则 |
一、为什么是 Calendar:Phase 3 的「换挡」时刻
前 70 天我们做的策略基本是「卖波动率」——CSP、Wheel、Iron Condor、Credit Spread。这些策略有一个共同的隐含前提:当前 IV 是足够贵的,卖出来有便宜可占。
但 2026 年 7 月这种行情就不再适用:
VIX 12.5 ← 低于历史均值(~19)
SPY 平稳 trading ← 30 天 realized vol < 10%
XLF IVR < 20 ← 一年来 IV 处于最低 20% 分位
GLD IVR < 20 ← 同上
在这种 regime 下卖 premium,你收到的金额已经 cover 不了 tail risk——一次 5σ 跳动就能把三个月的小钱赚回去全部交还。这就是为什么 Day 71 我们要练 Long Calendar:它是 IV 低位时唯一仍然能赚 theta 的结构。
| 策略 | 适用 regime | 核心 P&L 驱动 | IV 涨利好/利空 |
|---|---|---|---|
| Short Strangle / IC | 高 IV(IVR > 50) | theta 收割 | 利空(vega 短) |
| Credit Spread | 中高 IV | theta + 方向 | 利空 |
| Long Calendar | 低 IV(IVR < 25) | back-month vega + front-month theta 衰减差 | 利好(vega 长) |
| Long Straddle | 极低 IV + 预期大动 | gamma + vega | 利好 |
结论:Long Calendar 是「做多 vega 同时不付 theta 钱」的精妙结构——你卖出近月(吃近月 theta),买入远月(远月 theta 衰减慢得多)。净 theta 是正的,但同时净 vega 也是正的。这在期权结构里是稀缺的组合。
二、入场触发体系:双条件而不是单条件
新手开 Calendar 最常见的错就是「只看 IV 低就买」。但 IV 可以继续低下去,crash 不来你就一直在 theta-burn 区间外面浪费时间。正确的 entry signal 必须是双条件:
2.1 触发规则
条件 A(市场层):VIX < 15
→ 整体期权市场处于 cheap 区间
→ 任何 vega-long 结构都是逆向操作的折扣窗口
条件 B(标的层):标的自身 IV Rank < 25
→ 这个标的不仅是「绝对便宜」,还是「相对自己历史便宜」
→ 排除「VIX 低但本标的因 earnings 而 IV 飙高」的伪信号
A ∩ B 同时满足 → entry signal
A 满足、B 不满足 → 该标的不开,找另一个
B 满足、A 不满足 → 谨慎(说明本标的逆周期,可能有特殊原因)
2.2 今天市场扫描(场景假设)
| 标的 | 现价 | 30D HV | IV30 | IV Rank | 入场判定 |
|---|---|---|---|---|---|
| SPY | $500.20 | 9.1% | 11.8% | 22 | ✓✓ 双条件满足 |
| QQQ | $480.50 | 12.3% | 14.5% | 28 | ✗(IVR 略高,等等) |
| XLF | $42.10 | 8.5% | 11.2% | 18 | ✓✓ 双条件满足 |
| GLD | $215.00 | 7.8% | 10.5% | 19 | ✓✓ 双条件满足 |
| IWM | $215.80 | 14.2% | 17.8% | 35 | ✗(IVR 偏高) |
| TLT | $95.30 | 11.0% | 13.5% | 24 | ✓ 边界,备选 |
当日首选:SPY。原因:
- 流动性最好,calendar 是 2-leg combo,bid-ask spread 直接吃利润,SPY 期权 spread 通常 $0.02-0.05
- ATM 期权链密集,strike 选择灵活
- 不会遇到 earnings 这种「单一事件突然把 IV 拉爆」的脏 risk
- 没有 dividend 风险(SPY 的 dividend 已知且小)
三、标的选择与结构设计:SPY ATM Calendar
3.1 结构
现价:SPY = $500.20
Strike 选择:$500(ATM,最大 theta 收割效率)
Front leg:卖出 14 DTE $500 Call
Back leg:买入 60 DTE $500 Call
Net debit:~$3.50 / spread
每张合约成本:$3.50 × 100 = $350
3.2 为什么这样选
| 参数 | 选择 | 替代方案 | 取舍逻辑 |
|---|---|---|---|
| Strike = ATM | $500 | $495 / $505 | ATM 最大化 theta 差异;OTM calendar 是「方向性 calendar」,下面会展开 |
| Call vs Put | Call | Put | 对 SPY 这种「左偏分布」标的,Put calendar 的 skew 让 back leg 更贵;Call calendar 更便宜 |
| Front DTE = 14 | 14 天 | 7 天 / 30 天 | 14 天是 theta 加速区的甜点;7 天 gamma 太大,30 天 theta 还没启动 |
| Back DTE = 60 | 60 天 | 45 / 90 | 60 天是「back-month theta 衰减率 ≈ front-month 一半」的位置;远了 vega 占比过大 |
| DTE 差 = 46 | 46 天 | 21 / 75 | 经验值 45-60 是 calendar 收益曲线最饱满的区间 |
3.3 Greeks 摆位(开仓瞬间)
Front Short Call (14 DTE $500):
Delta: +0.51 (卖方 short delta = -0.51)
Gamma: +0.05 (卖方 short gamma)
Theta: -0.22 (卖方收 theta,记为 +0.22 给我们)
Vega: +0.18 (卖方 short vega)
Back Long Call (60 DTE $500):
Delta: +0.53
Gamma: +0.02
Theta: -0.08
Vega: +0.42
Combined (Long Calendar = -Front + Back):
Net Delta: +0.02 ← ~中性,路径稍微偏 long
Net Gamma: -0.03 ← 短 gamma(这是 calendar 的 path risk)
Net Theta: +0.14 ← 正 theta(每天赚 $14 / contract,前提是标的不动)
Net Vega: +0.24 ← 正 vega(IV 涨我们赚)
关键认知:
- Net theta 是正的 → 时间是朋友
- Net vega 是正的 → IV 涨是朋友
- Net gamma 是负的 → 标的大动是敌人
这就是 calendar 的本质:「赌区间内不动 + 赌 IV 起来」的复合赌注。
四、下单决策矩阵
4.1 P&L 边界
| 维度 | 数值 |
|---|---|
| Max Loss | $350(= net debit,标的暴跌或暴涨到 calendar 两 leg 都归零的极端情形) |
| Max Profit | ~$800(理论值,front 到期时 SPY 恰好 = $500 的最优 case) |
| Breakeven Upper | ~$510 |
| Breakeven Lower | ~$490 |
| 利润区间 | $490 - $510(front 到期时) |
| 风险/收益 | 1 : 2.3(debit 350 / max profit 800) |
4.2 收益曲线(front expiry day, T+14)
SPY price at T+14:
$480 P&L ≈ -$250 ← back call 还值钱但 calendar 大幅缩水
$490 P&L ≈ -$50 ← 接近 breakeven
$495 P&L ≈ +$350
$500 P&L ≈ +$800 ← 最大利润
$505 P&L ≈ +$350
$510 P&L ≈ -$50 ← 接近 breakeven
$520 P&L ≈ -$250
注意:这条曲线是 front 到期那一刻的形状,不是任意时刻。在 T+7(中段)时,曲线会更平更宽——这意味着「中途路过 $500」并不锁定利润,必须坚持到 front 临近到期才能吃到最大值。
4.3 仓位规模决定
按 Phase 3 的资金管理框架:
账户净值:$5,000(paper,模拟实盘)
单笔最大风险:账户 2% = $100
但这是 max-loss 风险,需要按 "expected loss" 而不是 "max loss" 来 size
经验法则:calendar 的 expected loss ≈ 0.4 × max loss(因为多数时候不是归零,而是部分缩水)
期望损失:$350 × 0.4 = $140 / contract
账户 2% 风险预算:$100
→ 略超,但因为是首笔 paper learning,开 1 张可以接受
首笔 size = 1 张。学习场景下重点不是赚钱,是验证整套从 entry → monitor → exit 的工作流能跑通。
五、Paper Trade 实操:开第一笔 SPY Calendar
5.1 IB TWS 手动下单流程(让肌肉记忆形成)
虽然我们最终目标是脚本化,但第一笔必须手动走一遍 TWS GUI。原因:
- Combo 订单的字段比单腿订单复杂得多,眼睛先看一遍才知道脚本要构造什么
- TWS 会自动校验某些字段(如 strike 在期权链里是否存在),脚本绕过这层后报错更难诊断
- 万一脚本 bug 把 combo 拆成两笔分开下,可能其中一笔成交一笔没成交,留下 naked leg
步骤:
TWS → 期权链 → SPY → July 2026 expiry (14 DTE) → $500 Call
→ 右键 → "Buy/Sell" → "Combo" → "Calendar Spread"
TWS 自动跳出 Combo Builder:
Leg 1: SELL +1 SPY 20260802 C 500.0
Leg 2: BUY +1 SPY 20260917 C 500.0
Order Type: Limit
Limit Price: $3.50 (Debit)
Time in Force: DAY
Smart Routing: ON
Submit
注意:Limit Price 是 Debit(正数表示我们付出),不是 Credit。新手最常见的错误是符号搞反,TWS 会直接拒单或者,更糟,按相反方向匹配。
5.2 Mid-Price 还是 NBBO?
期权 combo 的 spread 通常很宽。比如:
Combo NBBO bid: $3.30
Combo NBBO ask: $3.70
Mid: $3.50
下 mid 通常成交不到(市场做市商不会让你白吃 $0.20)。可行的做法:
Entry pricing 阶梯:
Round 1: 下 mid ($3.50),等 30 秒
Round 2: 上调 $0.05 到 $3.55,再等 30 秒
Round 3: 上调 $0.05 到 $3.60,再等 30 秒
超过 $3.65 放弃,第二天再开
死规则:永远不要直接 hit ask。Calendar 的边际利润 $50-100 都可能被 spread 吃掉。
5.3 Fill 后立刻做的三件事
- 记录精确 fill price(不是你下的限价,是实际成交价;TWS Execution 标签里看)
- 截图当时的 SPY 价、VIX、IV Rank(事后复盘用)
- 在监控脚本里 register 这笔仓位(下一节代码会展示)
六、持有期间监控:三条线同时盯
Calendar 不是「开了就放」的策略。Day 1 监控、Day 7 中段评估、Day 14 临近到期决定退出。
6.1 监控仪表盘的三条线
| 维度 | 监控什么 | 危险阈值 | 动作 |
|---|---|---|---|
| 价格线 | SPY 离 strike $500 的距离 | abs(price - 500) > $25 (5%) | 触发 exit B(限损) |
| IV 线 | SPY IV30 相对 entry 时变化 | IV 涨 > +30% 相对入场 | 触发 exit C(锁定 vega 利润) |
| 时间线 | DTE 到 front leg expiry | DTE ≤ 3 | 触发 exit A(锁定 theta 利润) |
6.2 每天 close-or-hold 的决策结构
每日盘后跑一次脚本,输出:
=== Calendar Monitor [Day 7 of 14] ===
Entry: 2026-07-19, debit $3.50
Current: 2026-07-26, combo mid = $4.20
P&L: +$70 / contract (+20%)
SPY: $501.30 (drift +$1.10 from entry $500.20)
SPY IV30: 13.5% (was 11.8% at entry, +14%)
Days to front expiry: 7
Decision flags:
[ ] PRICE breach (>$25 from strike) ← OK
[ ] IV spike (>+30%) ← OK (+14%)
[ ] Time decay (DTE <= 3) ← OK (7 days left)
→ HOLD
6.3 三条线的优先级冲突时怎么办
实际持仓中你会遇到「同时两个 flag 触发」的情况,需要预先定义优先级:
优先级 1: PRICE breach → 立即 close(保命)
优先级 2: IV spike → 锁定 vega 利润 close
优先级 3: TIME decay → 锁定 theta 利润 close
逻辑:价格风险是不对称的(gamma loss 可以无界),IV 和 time 风险是有界的。永远先躲不可控风险。
七、退出三场景(决策树完整版)
持有 Calendar
│
▼
┌───────────────┐
│ 距 entry 多久? │
└───────────────┘
│
┌─────────────────┼─────────────────┐
▼ ▼ ▼
[Day 1-7] [Day 8-13] [Day 14+]
│ │ │
▼ ▼ ▼
价格在区间? 价格在区间? front 即将到期
├ 是 → HOLD ├ 是 → HOLD │
├ 否 → SCEN. B ├ 否 → SCEN. B ▼
│ (限损) │ (限损) SCENARIO A
│ │ (锁利)
└─ IV 暴涨? └─ IV 暴涨?
└─ SCEN. C └─ SCEN. C
(vega 利润) (vega 利润)
Scenario A:T+14 临近 front 到期,SPY 在 strike ±2% 内
条件:
- DTE ≤ 3
- abs(SPY - $500) ≤ $10
动作:立即 close 整个 calendar
- Sell Back leg(剩余 46 DTE 的 $500 call)
- Buy back Front leg(即将到期的 $500 call,几乎归零)
- Expected combo mid 在这种情形通常是 $5.50-7.00(远高于入场 $3.50)
为什么不留到 expiry day:
- Front leg 在 expiry 当日 gamma 爆炸,1% 跳动就能从 +$700 利润跌到 -$200
- 你赚的是 theta + 不动,不是赌最后一刻
Scenario B:SPY 跳出 strike ±5%(即 < $475 或 > $525)
条件:
- abs(SPY - $500) > $25
- 任何时点触发
动作:立即 close 整个 calendar
- Expected combo mid 大概率在 $1.50-2.50(亏 $100-200 / contract)
- 接受这笔小亏,不要 roll,不要 average down
为什么不 roll:新手最爱犯的错就是把亏损 calendar roll 到下一个月份「换一次机会」。问题是:
- Roll 增加 net debit,等于在亏损头寸上加仓
- 趋势市里 roll 通常二次破位
- 心理成本巨大,越 roll 越执着
铁律:calendar 一旦破区间,只 close 不 roll。
Scenario C:IV 暴涨 30%+ 但价格还在区间内
条件:
- Current IV30 / Entry IV30 ≥ 1.30
- abs(SPY - $500) ≤ $25
动作:立即 close 整个 calendar
- Expected combo mid 通常 $5.00-6.50(vega 拉爆的利润)
- 即便 theta 还没完全收割,vega 利润已经超过预期
为什么提前走:
- IV 暴涨后通常伴随 price breakout,留下来会被 Scenario B 触发,把 vega 利润吐回去
- 「在最优时刻退出」永远比「在最优策略到期」更重要
八、完整代码:calendar_paper.py
# calendar_paper.py
# Paper-trading Long Calendar monitor with daily close-or-hold logic.
from ib_insync import IB, Stock, Option, ComboLeg, Contract, Order, util
from datetime import datetime, timedelta
import math
# ============== 0. Connection ==============
util.startLoop()
ib = IB()
ib.connect('127.0.0.1', 7497, clientId=71) # paper TWS port
assert ib.client.port == 7497, "WRONG PORT — PAPER ONLY"
# ============== 1. Position config ==============
SYMBOL = 'SPY'
STRIKE = 500.0
FRONT_EXPIRY = '20260802' # 14 DTE from 2026-07-19
BACK_EXPIRY = '20260917' # 60 DTE from 2026-07-19
RIGHT = 'C' # Call calendar
ENTRY_DEBIT = 3.50 # the price we filled
# ============== 2. Build the combo contract ==============
def build_calendar_combo():
front = Option(SYMBOL, FRONT_EXPIRY, STRIKE, RIGHT, 'SMART')
back = Option(SYMBOL, BACK_EXPIRY, STRIKE, RIGHT, 'SMART')
ib.qualifyContracts(front, back)
combo = Contract()
combo.symbol = SYMBOL
combo.secType = 'BAG'
combo.currency = 'USD'
combo.exchange = 'SMART'
leg1 = ComboLeg()
leg1.conId = front.conId
leg1.ratio = 1
leg1.action = 'SELL'
leg1.exchange = 'SMART'
leg2 = ComboLeg()
leg2.conId = back.conId
leg2.ratio = 1
leg2.action = 'BUY'
leg2.exchange = 'SMART'
combo.comboLegs = [leg1, leg2]
return combo, front, back
# ============== 3. Market snapshot ==============
def get_snapshot(combo, front, back):
underlying = Stock(SYMBOL, 'SMART', 'USD')
ib.qualifyContracts(underlying)
spy_t = ib.reqMktData(underlying, '', snapshot=True)
front_t = ib.reqMktData(front, '', snapshot=True)
back_t = ib.reqMktData(back, '', snapshot=True)
combo_t = ib.reqMktData(combo, '', snapshot=True)
ib.sleep(3)
spy_price = spy_t.last or spy_t.close
front_iv = front_t.modelGreeks.impliedVol if front_t.modelGreeks else None
combo_mid = (combo_t.bid + combo_t.ask) / 2 if combo_t.bid and combo_t.ask else None
return {
'spy_price': spy_price,
'front_iv': front_iv,
'combo_mid': combo_mid,
'front_bid': front_t.bid,
'front_ask': front_t.ask,
'back_bid': back_t.bid,
'back_ask': back_t.ask,
}
# ============== 4. Decision logic ==============
def decide(snap, entry_iv=0.118):
spy = snap['spy_price']
iv = snap['front_iv']
mid = snap['combo_mid']
pnl = (mid - ENTRY_DEBIT) * 100 if mid else 0
days_to_front = (datetime.strptime(FRONT_EXPIRY, '%Y%m%d') - datetime.now()).days
# Three flags
price_breach = abs(spy - STRIKE) > 25 # > 5% from strike
iv_spike = iv and (iv / entry_iv) >= 1.30
time_decay = days_to_front <= 3
print(f"\n=== Calendar Monitor [DTE={days_to_front}] ===")
print(f"SPY: ${spy:.2f} (entry ${500.20}) drift: ${spy-500.20:+.2f}")
print(f"IV: {iv*100:.1f}% (entry 11.8%) delta: {(iv/entry_iv-1)*100:+.1f}%")
print(f"Combo mid: ${mid:.2f} (entry ${ENTRY_DEBIT}) P&L: ${pnl:+.0f}")
print(f"Flags: price_breach={price_breach} iv_spike={iv_spike} time_decay={time_decay}")
# Priority order
if price_breach:
return 'CLOSE_SCENARIO_B', 'price breached strike +/- 5%'
if iv_spike:
return 'CLOSE_SCENARIO_C', 'IV spiked >= 30%, lock vega profit'
if time_decay and abs(spy - STRIKE) <= 10:
return 'CLOSE_SCENARIO_A', 'front near expiry, in profit zone'
if time_decay and abs(spy - STRIKE) > 10:
return 'CLOSE_SCENARIO_B', 'front near expiry but out of zone, take small loss'
return 'HOLD', 'all flags clear'
# ============== 5. Place closing order (if triggered) ==============
def close_combo(combo, snap, dry_run=True):
"""Reverse the original combo: BUY back front, SELL back leg."""
# Build reverse combo
close = Contract()
close.symbol = SYMBOL
close.secType = 'BAG'
close.currency = 'USD'
close.exchange = 'SMART'
legs = []
for leg in combo.comboLegs:
rev = ComboLeg()
rev.conId = leg.conId
rev.ratio = leg.ratio
rev.action = 'BUY' if leg.action == 'SELL' else 'SELL'
rev.exchange = 'SMART'
legs.append(rev)
close.comboLegs = legs
# Price = mid - $0.05 (give up a nickel to ensure fill)
limit_price = max(snap['combo_mid'] - 0.05, 0.05)
order = Order()
order.action = 'SELL' # we are CLOSING a debit position → action='SELL' on BAG
order.orderType = 'LMT'
order.totalQuantity = 1
order.lmtPrice = limit_price
order.tif = 'DAY'
if dry_run:
print(f"[DRY RUN] Would close at ${limit_price:.2f}")
return None
trade = ib.placeOrder(close, order)
ib.sleep(2)
return trade
# ============== 6. Main loop ==============
def main():
combo, front, back = build_calendar_combo()
snap = get_snapshot(combo, front, back)
action, reason = decide(snap, entry_iv=0.118)
print(f"\n>>> ACTION: {action}")
print(f">>> REASON: {reason}")
if action.startswith('CLOSE_'):
print(">>> Submitting close order (dry run for paper learning)")
close_combo(combo, snap, dry_run=True)
else:
print(">>> No action. Re-run tomorrow.")
ib.disconnect()
if __name__ == '__main__':
main()
8.1 这段代码刻意做的几件事
assert ib.client.port == 7497:硬护栏防止误连实盘clientId=71:用 Day 编号当 clientId,多脚本并跑不冲突dry_run=Truedefault:close_combo 默认只打印不下单,paper 学习阶段强制人工 review- 决策优先级硬编码:price_breach > iv_spike > time_decay,顺序写死避免临场犹豫
limit_price = mid - 0.05:close 时主动让 $0.05,避免在 spread 中间挂单不成交
8.2 跑法
# 每个交易日盘后跑一次
python calendar_paper.py
# 看输出,如果 ACTION = HOLD,继续持有
# 如果 ACTION = CLOSE_*,先看 dry run 输出,确认无误后手动改 dry_run=False 重跑
九、「实盘 vs Paper」的现实考量
读到这里你可能在想:「我账户有 $5,000,1 张 SPY calendar 才 $350,看起来完全可以实盘做啊」。这里要说点不舒服的话。
9.1 表面上可以,实质上不智
| 维度 | 表面看 | 实质上 |
|---|---|---|
| 资金占用 | $350 / $5,000 = 7% | 看起来安全 |
| Max loss / account | 7% | 实际更高(见下) |
| 隐含杠杆 | 1张 = SPY 100 股 = $50k notional | 10x 账户净值 |
| Gamma risk | 中度 | 一次 5% gap down 单日浮亏可达 $200+ |
问题不在 max loss 是 $350,问题在 path。Calendar 持有 14 天,中间任何一天如果 SPY 跳 3%,你的 mark-to-market loss 可能瞬间到 $250,而你在那个瞬间的心理决策能力远低于理论值。
更深的问题:5x 杠杆用 $1,000 不智。你的真实风险敞口(notional exposure)是 $50,000 级别。这种 leverage 在小账户上意味着单次坏运气可以吃掉 20-30% 净值。Phase 3 的目标是建立可重复的工作流,不是赌一次大的。
9.2 我的建议
Phase 3(Day 61-90):100% Paper
→ 至少跑 5 笔完整 calendar(5 × 14 天 = 70 天)
→ 每笔都走完 entry / monitor / exit 三场景至少一次
→ 形成「这种波动该怎么反应」的肌肉记忆
Phase 4(Day 91+,账户净值 ≥ $10,000 后):
→ 实盘 1 张 SPY calendar
→ 仍然只开 1 张,不 scale
→ 跑 10 笔之后再考虑加到 2 张
核心认知:paper 不是给「小白」用的,paper 是给「不想用钱学心理课」的成年人用的。
十、Calendar 失效场景(哪些时候根本不该开)
10.1 标的有 known event
| 事件 | 影响 | 应对 |
|---|---|---|
| Earnings(front expiry 前) | front IV 飙高,calendar 净 debit 异常便宜,但 earnings 后 IV crush 让 back leg 也跌,整体亏损 | 不开。或者只在「earnings 之后」开 |
| FOMC(front expiry 前后) | 类似 earnings | 不开 calendar,改做 long straddle 反向押注 |
| 重大 macro 数据(CPI/NFP) | 短期 vol 飙 | 等数据后再开 |
10.2 VIX 处于下降通道
VIX 走势:22 → 18 → 15 → 12 → ?
你看到 VIX = 12 觉得「低到极致了」就开 vega-long calendar
结果 VIX 继续往 10 走 → 你的 back leg vega 利润蒸发
判断法则:不只看 VIX 绝对值,还要看 VIX 的 1 个月趋势。下降通道里开 vega long 是逆势单。Calendar 最适合的是 VIX 横盘在低位 的时候。
10.3 高 dividend 季节
SPY 季度分红前 1-2 周,深 ITM call 会被提前行权。Calendar 的 front short call 万一被 assign,会变成:
- 你被强制 short 100 股 SPY
- back long call 还在
- 整个结构变成 covered call 的反向版本,风险敞口完全改变
对策:开 calendar 前查 ex-dividend dates,避开前 5 个交易日。或者用 put calendar(put 不会被早期行权)。
10.4 Skew 反常的标的
正常市场:Put IV > Call IV(左偏 skew)
反常市场:Call IV > Put IV(如 GME meme stock 时期)
反常 skew 的标的 calendar 会出现各种诡异定价。Phase 3 阶段坚持只做 SPY / QQQ / XLF / GLD 这些 skew 行为正常的大盘标的。
十一、PM 视角:Range-Bound Bet 的本质
Calendar 的本质是「赌区间内会发生 something」。「something」可以是:
- IV 起来(vega 利润)
- 时间过去(theta 利润)
- 但前提是 价格不破区间
这跟 PM 工作里某些场景高度同构。举几个金融 PM 经常遇到的场景:
11.1 用户 retention 区间
calendar 假设:SPY 在 [490, 510] 区间停留 14 天
PM 类比:用户在 "active 但未付费" 区间停留 X 天
calendar 利润:来自时间 × 不动
PM 利润:来自时间 × 用户不流失(让 onboarding 流程完成)
calendar 失败:标的破区间
PM 失败:用户流失(破下沿)/ 自然转化(破上沿,已经付费的就走出 active-未付费区间)
这种结构性的相似不是巧合——所有「赌区间」的产品策略,PnL 都长成 calendar 形状。
11.2 产品决策的 vega/theta 对应
| 期权概念 | PM 类比 |
|---|---|
| Theta(时间衰减) | 用户在功能里待得越久越值钱(如订阅期内 LTV) |
| Vega(波动率) | 市场情绪/竞品动作的不确定性溢价 |
| Gamma(路径风险) | 单次 UX 失误造成的非线性流失 |
| Delta(方向) | 增长趋势的 directional bet |
PM 应该构建组合,使得:
- Theta 正(每天活跃用户都在累积价值)
- Vega 正(市场不确定性增加时你受益,比如竞品出问题时你接到流量)
- Gamma 受控(不靠某一次大事件成功)
- Delta 中性或略 long(不押宝单一方向)
这就是「健壮的产品 PnL 结构」。它跟 Long Calendar 的 Greeks 摆位惊人地相似——这不是巧合,是组合数学。
11.3 从 Long Calendar 学到的「触发条件」思维
PM 工作里最常犯的错就是「我觉得这个 feature 应该做」——没有触发条件。
Day 71 的双条件触发体系(VIX < 15 ∩ IVR < 25)给了我们一个范式:
Action 不应当被 single condition 触发
Action 应当被 condition A ∩ condition B 触发
其中 A 是 market-level signal,B 是 instrument-level signal
PM 翻译:
做某 feature 不应当被 "用户 A 想要" 触发
做某 feature 应当被 "10% 用户群体反映 ∩ 北极星指标确实受此影响" 触发
其中前者是 voice-of-customer,后者是 metric-of-business
双条件触发是抗噪声的工程化决策。Day 71 把它在期权里走通,下次在产品决策里就有同样的肌肉记忆。
十二、明日预告
Day 72: ETF 衰减 — Leveraged & Inverse ETF 的结构性熵
明天换一个完全不同的方向——研究 TQQQ / SQQQ / UVXY 这类 levered/inverse ETF 的「衰减系数」,以及由此衍生的对冲策略。核心问题:
- 为什么 SQQQ 长期持有几乎一定亏(即便指数不涨)?
- "Volatility decay" 的数学公式
- 如何用 short SQQQ + short UPRO 构造「双边盈利」组合?为什么不那么简单?
- 实盘案例:2022 年 Volatility-of-Volatility 大跳时,levered ETF 的连锁清算
- 代码:每日复盘一个 ETF 衰减监控器
Day 71 是「看到 vol 便宜买它」,Day 72 是「看到结构性 decay 卖它」,两天合起来给你 vol 长短两头 的实战工具。
实际执行记录
启动一项填一项,时间戳 + 卡点。
- [hh:mm] 市场扫描:跑双条件过滤,记录当日通过标的清单
- [hh:mm] SPY Calendar 手动 TWS 下单(学习场景)— Fill price: $___
- [hh:mm]
calendar_paper.py接入这笔仓位,第一次跑监控 - [hh:mm] Day 1 监控输出存档(截屏)
- 卡点 / 学到的:
- 入场限价单等了几轮才成交?最终让了多少 spread?
- Greeks 实际值 vs 笔记里的理论值差多少?
- 监控脚本第一次跑遇到什么错?
总字数:约 6,400 字 今日完成度:理论 ✓ / 实操(paper 第一笔 calendar)/ 笔记 ✓ / 代码 ✓