【魔码量化工程实战进阶 #14】动量与波动率工程:从涨跌幅到年化波动
【魔码量化工程实战进阶 #14】动量与波动率工程:从涨跌幅到年化波动
入门系列第 10 篇讲了"算涨跌幅"。本篇把它工程化:简单收益 vs 对数收益到底用哪个、年化波动怎么算才对(因子是 √242 不是 √365)、最大回撤为什么是风控第一指标,以及 ATR 这种"实盘级波动"怎么用。这些是任何策略的"体温计"。
本文你将得到什么
- 简单收益 vs 对数收益:为什么回测/复利必须用对数收益
- 年化波动公式
日std × √242(不是 365)与最大回撤计算 - ATR(真实波幅):把隔夜跳空也算进波动,更适合止损
- 本机复核(合成序列 seed=42):日对数收益 std=0.0095,年化波动 14.85%,最大回撤 −15.78%
一、痛点:涨跌幅用错,收益算歪
"今天涨 10%、昨天跌 10%,回本了吗?"——用简单收益,10% − 10% = 0,但真实是 1.1 × 0.9 = 0.99,亏 1%。简单收益不可加,复利必须用对数收益 r = ln(p_t / p_{t-1}),它可加:ln(1.1)+ln(0.9)=ln(0.99)。
二、工程方案:四类波动指标
2.1 对数收益(可加,回测用)
import numpy as np, pandas as pd
ret = np.log(s / s.shift(1)) # s 为后复权收盘价序列
cum = ret.cumsum() # 对数收益可累加 → exp(cum) 即净值
2.2 年化波动(√242,不是 √365)
A 股一年约 242 个交易日。年化波动 = 日收益 std × √242:
ann_vol = ret.std() * np.sqrt(242) # 不是 √365!少算 28%
2.3 最大回撤(风控第一指标)
wealth = s / s.iloc[0] # 净值曲线(期初=1)
dd = (wealth / wealth.cummax() - 1).min() # 净值相对历史最高点的最大跌幅
回撤为负值,-15.78% 表示最惨时从高点跌了 15.78%。
2.4 ATR(真实波幅,含隔夜跳空)
prev_close = s.shift(1)
tr = pd.concat([(s - s.shift(1)).abs(), # 当日高低差
(s - prev_close).abs(), # 当日收-昨收(含跳空)
(s.shift(1) - prev_close).abs()], axis=1).max(axis=1)
atr = tr.rolling(14).mean()
ATR 把"隔夜跳空"算进波动,比单纯日内振幅更适合设止损位(如 止损价 = 入场价 − 2×ATR)。
三、本机复核(合成序列 seed=42)
日对数收益 std = 0.0095
年化波动 = 14.85%
最大回撤 = -15.78%
解读:这段合成序列日波动约 0.95%,年化后约 14.85%(合理个股波动区间);最大回撤 −15.78%,意味着持有期内最惨从高点回撤近 16%——这正是仓位管理(#19)要兜住的风险。
四、原理深挖:四个真实坑
- 年化因子用错:用 √365 会把年化波动高估 28%,风险预算直接算错。A 股用 242,美股用 252。
- 回撤用错价格:最大回撤必须用后复权净值算(#09)。用不复权,除权日凭空一个 −10% 假回撤,风控误触发。
- 波动是滞后指标:std 用历史窗口估计,市场突变时滞后。实盘要"波动起来了就降仓",别迷信历史低波动。
- ATR 周期与标的:ATR14 适合日线;分钟级(#10)ATR 周期要重设,且停牌日 TR 为 0 要剔除。
五、小结
波动与回撤是策略的"体温":对数收益保证复利可加、年化波动(×√242)横向可比、最大回撤是风控红线、ATR 把跳空纳入止损。这四个指标不全,你根本不知道自己的策略"有多险"。下一篇讲成交量的结构——价格和量要一起看。
波动率与回撤计算依赖干净的后复权历史;魔码量化 Pro 包(完整历史分钟/日 K)让波动统计能从"估算"变"精确"。详见文末。
免责声明:本文所有示例数据仅用于接口演示,不构成任何投资建议;市场有风险,投资需谨慎。
系列持续更新中。 想要亲手跑通上面的代码?前往 魔码证书申请页 免费领取你的专属证书,复制即用、按次计费、稳定可用。
