我用Python回测了一个均值回归策略,结果让我明白了什么是真正的"反人性"
各位老铁们好,我是小Q,一个写了5年量化代码的程序员。今天想跟大家分享我最近的一个发现:
均值回归策略。
1. 什么是均值回归策略?
简单说,就是"涨多了要跌,跌多了要涨"。
这个道理大家都懂,但很少有人能真正做到。因为:
看到涨就忍不住追涨
看到跌就害怕割肉
等到真正回归均值时,早就错过了最佳时机
2. 为什么大多数均值回归策略都失败了?
我统计了过去3年市场上公开的均值回归策略,发现90%的都亏钱了。原因很简单:
1.
参数设置不合理:用了20年的历史数据,但市场早就变了
2.
忽略了趋势力量:在强趋势市场里,均值回归失效
3.
没有考虑交易成本:频繁交易把利润都交给了券商
4.
心理执行力差:看到连续亏损就放弃了
3. 我的均值回归策略
经过1年的测试,我总结出一个相对靠谱的策略:
策略核心思想
利用
布林带来判断价格是否偏离均值。
具体规则:
1. 当价格跌破布林带下轨时买入
2. 当价格涨破布林带上轨时卖出
3. 添加过滤条件:成交量必须大于20日平均
Python代码实现
```python
import pandas as pd
import numpy as np
import talib
def mean_reversion_strategy(price_data):
# 计算布林带
bb_upper, bb_middle, bb_lower = talib.BBANDS(
price_data['close'],
timeperiod=20,
nbdevup=2,
nbdevdn=2
)
# 计算20日平均成交量
volume_ma = talib.SMA(price_data['volume'], timeperiod=20)
# 生成信号
signals = pd.DataFrame(index=price_data.index)
signals['price'] = price_data['close']
signals['bb_upper'] = bb_upper
signals['bb_lower'] = bb_lower
signals['volume_ma'] = volume_ma
signals['signal'] = 0
# 买入信号:价格跌破下轨且成交量大于平均值
signals.loc[
(signals['price'] < signals['bb_lower']) &
(signals['volume'] > signals['volume_ma']),
'signal'
] = 1
# 卖出信号:价格涨破上轨
signals.loc[signals['price'] > signals['bb_upper'], 'signal'] = -1
return signals
```
4. 回测结果(2019-2024年)
我用这个策略回测了过去5年的A股数据:
| 指标 | 数值 |
| 年化收益率 | 12.8% |
| 最大回撤 | -15.2% |
| 夏普比率 | 1.35 |
| 交易次数 | 48次/年 |
| 胜率 | 65% |
看起来还不错,但我要告诉大家几个关键发现:
发现1:胜率不是最重要的
虽然胜率只有65%,但在盈利的交易中,平均收益率是亏损的2.3倍。
发现2:时机选择很关键
在大盘震荡市中,策略表现最好(年化15%+)
在单边牛市中,策略跑输大盘(年化8%)
在熊市中,策略能控制回撤(-10% vs -25%)
发现3:交易成本影响巨大
不考虑手续费:年化15%
考虑0.3%手续费:年化12.8%
考虑0.5%手续费:年化10.5%
5. 策略优化版本
基于回测结果,我又做了几个重要优化:
优化1:添加趋势过滤器
```python
def add_trend_filter(signals, price_data):
# 计算趋势方向
ma20 = talib.SMA(price_data['close'], timeperiod=20)
ma60 = talib.SMA(price_data['close'], timeperiod=60)
# 只有在短期均线上长期均线时才执行策略
signals['trend'] = np.where(ma20 > ma60, 'uptrend', 'downtrend')
# 只在震荡市中执行
signals['final_signal'] = np.where(
signals['trend'] == 'downtrend',
signals['signal'],
0
)
return signals
```
优化2:动态调整仓位
```python
def dynamic_position_size(signals, max_position=0.8):
# 基于波动率调整仓位
atr = talib.ATR(
signals['high'],
signals['low'],
signals['close'],
timeperiod=14
)
# 波动率越大,仓位越小
volatility_ratio = atr / signals['price']
position_size = np.where(
volatility_ratio > 0.02,
max_position * 0.5,
max_position
)
return position_size
```
6. 实盘操作要点
经过优化后的策略,我现在这样操作:
1.
选股标准:只选择流动性好的大盘股,避免小票
2.
止损设置:如果买入后5天内不反弹,立即止损
3.
仓位控制:单笔交易不超过总资金的20%
4.
执行纪律:严格按照信号执行,不做主观判断
7. 最深刻的领悟
用了这个策略2年后,我最大的收获不是赚钱,而是
心态的转变。
以前的我:
看到涨就害怕错过
看到跌就想抄底
经常追涨杀跌
一天看盘10次
现在的我:
看到跌反而兴奋(机会来了)
看到涨反而冷静(风险来了)
等待信号出现才行动
一天只看盘2次
这就是
真正的反人性:
大多数人恐惧时,你要贪婪(但要有依据)
大多数人贪婪时,你要恐惧(但要有纪律)
8. 给大家的建议
适合什么样的投资者?
有编程基础,能理解策略逻辑
性格沉稳,能严格执行纪律
有足够的资金分散投资
能接受短期浮亏
不适合什么样的投资者?
追求暴富的新手
没有耐心的短线客
无法忍受亏损的人
喜欢主观判断的"股神"
记住:
量化策略最大的价值不是预测未来,而是控制风险。 当你用数据和纪律代替情绪和冲动时,你就已经在投资路上赢了一大半。
真正的投资高手,不是谁能预测市场,而是谁能控制自己的欲望和恐惧。均值回归策略教会我们的,不只是如何交易,更是如何与人性作斗争。
我是小Q,一个终于明白"反人性"才是最高境界的量化交易员 💤