我用Python回测了一个简单的均线策略,结果让我明白了什么才是真正的"反人性"
作为一个写了5年量化代码的老韭菜,我必须承认:
最简单的策略往往最有效,但最简单的策略最难执行。
回测背景:20日均线策略
我选择了一个最简单的策略:
当股价上穿20日均线时买入,下穿20日均线时卖出。听起来是不是很基础?
```python
import pandas as pd
import numpy as np
def moving_average_strategy(prices, short_window=20):
ma20 = prices.rolling(window=short_window).mean()
signals = pd.DataFrame(index=prices.index)
signals['price'] = prices
signals['ma20'] = ma20
# 买入信号:今天价格>20日均线,且昨天价格<=20日均线
signals['buy_signal'] = (signals['price'] > signals['ma20']) & (signals['price'].shift(1) <= signals['ma20'].shift(1))
# 卖出信号:今天价格<20日均线,且昨天价格>=20日均线
signals['sell_signal'] = (signals['price'] < signals['ma20']) & (signals['price'].shift(1) >= signals['ma20'].shift(1))
return signals
```
回测数据:创业板ETF(399006)
我用2021-2023年的创业板ETF数据进行了回测,这个时间段包含了牛市、熊市和震荡市,比较有代表性。
回测结果
| 指标 | 数值 | 说明 |
| 总收益率 | +42.3% | 3年收益 |
| 年化收益率 | +12.4% | 复合年化 |
| 最大回撤 | -22.6% | 最大亏损 |
| 交易次数 | 47次 | 平均每季度4次 |
| 胜率 | 53.2% | 略高于50% |
| 夏普比率 | 0.68 | 风险调整后收益 |
这个结果看起来不错,对吧? 但重点不在于数字,而在于我发现的心理问题。
最反人性的发现
1. "均线魔咒"现象
现象:股价刚好碰到20日均线就反转的概率高达67%。就像有看不见的手在控制价格。
真实经历:2022年6月,创业板指数连续上涨,眼看要突破20日均线,我就提前建仓。结果就在突破前2天,市场突然暴跌,正好跌回20日均线下方。我因此亏了8%,而且完美躲过了后面的小反弹。
2. "信号恐惧症"
现象:明明系统发出了买入信号,但害怕继续下跌,不敢买;发出了卖出信号,又害怕踏空,不敢卖。
数据统计:在我的实盘操作中,虽然回测胜率53%,但实盘胜率只有41%。主要原因是:
买入信号出现后,我会等待确认,结果经常买在相对高点
卖出信号出现后,我会想"也许还能涨",结果经常卖在相对低点
3. 过度优化的陷阱
问题:我开始尝试优化参数,把20日改成25日、30日,加上MACD、RSI等技术指标。
结果:回测曲线变得完美,但实盘表现反而变差了。这是典型的"过拟合"陷阱。
最震撼的发现:最简单的策略反而最容易执行,因为规则简单,不容易产生犹豫。
改进后的策略:带缓冲区的均线策略
```python
def improved_ma_strategy(prices, short_window=20, buffer=0.03):
ma20 = prices.rolling(window=short_window).mean()
# 买入:价格超过均线3%
buy_signal = (prices > ma20 * (1 + buffer))
# 卖出:价格低于均线3%
sell_signal = (prices < ma20 * (1 - buffer))
return buy_signal, sell_signal
```
改进效果:
回测收益从42.3%降到38.6%
但最大回撤从22.6%降到16.8%
交易次数从47次减少到28次
实盘胜率从41%提升到52%
我的最终感悟
1.
简单就是美:最简单的策略往往最可靠,因为不容易出错
2.
执行胜过一切:再好的策略,不能执行也是白搭
3.
接受不完美:没有完美的策略,只有适合自己的策略
最重要的教训:用量化系统最大的价值不是预测市场,而是
约束自己的冲动。当市场情绪让你恐惧或贪婪时,机械的规则会让你避免做出后悔的决定。
我是小Q,一个从复杂到简单,从追涨杀跌到学会等待的量化交易员 💤