4. 最大回撤控制:动态止损、回撤阈值设定、基于波动率的仓位调整
做量化策略,最怕什么?
不是赚得少,是亏得狠。我见过太多策略,夏普比率漂亮得很,年化收益也诱人,结果一次黑天鹅事件,净值直接腰斩。嗯,这就是最大回撤失控的后果。
今天咱们聊聊怎么管住这个“回撤猛兽”。说白了,就是三招:动态止损、回撤阈值设定、基于波动率的仓位调整。这三板斧用好了,你的策略就能在市场里活得久、活得稳。
4.1 动态止损:别让亏损滚雪球
静态止损,比如“亏5%就砍”,太死板了。市场波动大的时候,5%可能只是正常抖动;波动小的时候,5%已经是重伤。
我个人习惯用动态止损。核心思路是:止损线跟着价格走,或者跟着波动率走。
4.1.1 跟踪止损(Trailing Stop)
这是最常用的动态止损方式。止损线不是固定的,而是随着盈利增加而上移。比如,你设置一个“回撤3%就平仓”的跟踪止损。价格从100涨到110,止损线就从97上移到106.7。价格跌了?止损线不动。
我在项目中遇到过一个问题:跟踪止损太灵敏,容易被洗出去。后来我加了一个“最小保护距离”,比如至少保证1%的利润空间,效果好了很多。
跟踪止损价 = max( 历史最高价 × (1 - 回撤比例), 初始止损价 )
4.1.2 波动率自适应止损
这个更高级一点。止损幅度不是固定的百分比,而是根据当前市场的波动率动态调整。波动率大的时候,止损放宽;波动率小的时候,止损收紧。
具体怎么做?用ATR(平均真实波幅)来设定。
# 波动率自适应止损示例
import numpy as np
def atr_stop(high, low, close, period=14, multiplier=2.0):
# 计算ATR
tr = np.maximum(high - low,
np.abs(high - close.shift(1)),
np.abs(low - close.shift(1)))
atr = tr.rolling(period).mean()
# 止损价 = 当前价 - multiplier * ATR
stop_price = close - multiplier * atr
return stop_price
你看,当ATR变大时,止损距离自动拉宽,不容易被正常波动震出去;ATR变小时,止损收紧,保护利润。我曾经用这个逻辑在股指期货上做过回测,最大回撤直接降了40%。
4.2 回撤阈值设定:给策略上“保险丝”
动态止损管的是单笔交易。但有时候,单笔没亏多少,连续几笔亏损加起来,回撤就大了。这时候需要回撤阈值来管总账。
4.2.1 绝对回撤阈值
设定一个固定的最大回撤比例,比如“净值从最高点回撤15%,就清仓”。这个简单粗暴,但有效。
我建议把阈值分成几档:
| 回撤幅度 | 操作 | 说明 |
|---|---|---|
| 5% | 减仓50% | 预警,降低风险暴露 |
| 10% | 减仓80% | 严重警告,只留底仓 |
| 15% | 清仓 | 强制止损,保护本金 |
为什么要分档?因为直接清仓可能错过反弹。分档操作给了策略一个“缓冲期”。
4.2.2 动态回撤阈值
绝对阈值有个问题:不同市场环境下,合理的回撤幅度不一样。牛市里回撤15%可能很正常,熊市里回撤5%就该跑了。
所以,我更喜欢用动态回撤阈值。比如,把阈值和市场的波动率挂钩:
# 动态回撤阈值示例
def dynamic_drawdown_threshold(volatility, base_threshold=0.10):
# 波动率越高,阈值越宽
# 假设年化波动率正常范围是15%-30%
vol_ratio = volatility / 0.20 # 以20%为基准
threshold = base_threshold * vol_ratio
# 限制范围,防止太宽或太窄
threshold = np.clip(threshold, 0.05, 0.25)
return threshold
说白了,就是市场越动荡,我给你的“犯错空间”越大。但上限是25%,不能再多了。
4.3 基于波动率的仓位调整:让仓位和风险匹配
前面两招都是“事后止损”。但真正的高手,是在事前就控制好风险。怎么做?仓位调整。
核心思想很简单:波动率大的时候,少买点;波动率小的时候,多买点。这样,每笔交易承担的风险大致相等。
4.3.1 等风险仓位(Risk Parity)
传统方法是用固定仓位,比如每次开仓10%的资金。但不同股票的波动率可能差好几倍。用固定仓位,波动大的股票实际风险更大。
等风险仓位的思想是:让每笔交易的风险敞口相等。
# 等风险仓位计算
def risk_parity_position(capital, price, volatility, risk_per_trade=0.01):
# risk_per_trade: 每笔交易愿意承担的风险比例(如1%)
# 风险敞口 = 仓位市值 × 波动率
# 目标:仓位市值 × 波动率 = capital × risk_per_trade
position_value = capital * risk_per_trade / volatility
shares = position_value / price
return shares
举个例子:你有100万资金,愿意每笔承担1%的风险(即1万元)。股票A波动率20%,股票B波动率40%。那么:
- 股票A的仓位 = 100万 × 1% / 20% = 5万元
- 股票B的仓位 = 100万 × 1% / 40% = 2.5万元
你看,波动率大的股票仓位自动变小。这样,无论买哪个,每笔交易的最大预期亏损都控制在1万元左右。
4.3.2 波动率目标仓位(Volatility Targeting)
这个更激进一点。你不是控制每笔的风险,而是控制整个组合的波动率。比如,你希望组合的年化波动率稳定在15%。
怎么做?每天根据当前市场的波动率,调整整体仓位。
# 波动率目标仓位调整
def volatility_targeting(current_vol, target_vol=0.15, max_leverage=2.0):
# 目标仓位比例 = 目标波动率 / 当前波动率
target_weight = target_vol / current_vol
# 限制杠杆
target_weight = min(target_weight, max_leverage)
return target_weight
假设当前市场年化波动率是30%,你想控制在15%。那么仓位比例 = 15% / 30% = 0.5,也就是半仓。如果波动率降到10%,仓位比例 = 15% / 10% = 1.5,可以加杠杆到1.5倍。
我在做CTA策略时用过这个方法。效果很稳,净值曲线平滑了很多。但要注意,这个方法在波动率突变时会有滞后,需要配合快速止损使用。
动态止损 → 管单笔亏损
回撤阈值 → 管总账户风险
波动率仓位 → 事前控制风险暴露
三者结合,形成“事前-事中-事后”的完整风控闭环。
4.4 实战中的避坑指南
讲完了理论,说说我踩过的坑。
- 止损太紧: 我曾经把ATR止损的multiplier设成1.5,结果频繁被洗,手续费都亏了不少。后来改成2.5,好多了。
- 回撤阈值设得太死: 固定15%清仓,结果市场大跌后快速反弹,完美踏空。后来我加了“重新入场条件”,比如“连续3日上涨且突破20日均线”再进场。
- 波动率仓位调整太频繁: 每天调仓,交易成本太高。我改成每周调一次,或者波动率变化超过20%才调。
嗯,这些坑都是真金白银换来的教训。你想想看,如果一开始就能避开,能省多少钱?
4.5 知识体系总览
下面这张图,把本章的核心逻辑串起来了。你可以把它当作风控系统的设计蓝图。
这张图你看懂了吗?从上到下,从单笔到总账户,从被动止损到主动仓位管理。三层联动,缺一不可。
好了,关于最大回撤控制,今天就聊到这儿。记住,风控不是限制你赚钱,而是让你在市场里活得久。活得久,才能赚得多。
公众号:蓝海资料掘金营,微信deep3321