做了3年量化交易,这些坑我希望早点知道
本文没有暴富故事,只有真实踩坑经历。如果你正在或准备做量化交易,希望这些教训能帮你少走弯路。
我从2022年开始接触量化交易,从最初的满腔热血,到后来被市场反复教育,再到现在稍微能稳定盈利。三年下来,踩过的坑比赚的钱还多。
今天把这些坑整理出来,不是为了劝退,而是希望后来者能绕过去。
一、数据坑:你以为的数据,不是真正的数据
坑1:复权数据的陷阱
刚开始做回测时,我直接用了前复权数据,回测结果特别漂亮——年化收益60%+,夏普比率2.5。
兴冲冲上了实盘,结果第一个月就亏了8%。
后来才搞明白:前复权会改变历史价格。比如某只股票现价10元,一年前发生过10送10,前复权后一年前的价格会显示为5元(实际是10元)。用这种数据回测,相当于用了"未来信息"。
正确做法:
- 回测用不复权数据 + 手动处理除权除息
- 或者用后复权数据,但买卖信号要转换成真实价格
# 错误示范
df = get_stock_data("000001", adjust="qfq") # 前复权
signal = df['close'] > df['close'].shift(20) # 这个信号有问题
# 正确做法
df_raw = get_stock_data("000001", adjust=None) # 不复权
df_hfq = get_stock_data("000001", adjust="hfq") # 后复权用于计算指标
# 信号用后复权算,下单用真实价格
坑2:停牌股的幸存者偏差
有一次我回测一个选股策略,从2015年的股票池开始选。结果收益率高得离谱。
后来发现问题:2015年之后很多股票退市或长期停牌了,但我的股票池是用"当前可交易的股票",天然过滤掉了那些"死掉"的标的。
这就是典型的幸存者偏差——你只看到了活下来的,没看到死掉的。
正确做法:
- 用时点数据,即在回测的每个时间点,只用当时可交易的股票
- 或者使用包含历史退市股的全量数据库
坑3:数据源不一致的坑
这个坑我踩了不止一次。
有段时间我用A数据源做回测,用B数据源做实盘监控。结果经常出现回测显示应该买入,但实盘没有触发信号。
debug了很久才发现:同一只股票同一天,不同数据源的收盘价可能差几分钱。对于日线策略可能影响不大,但对于一些阈值判断(比如突破某个价位),几分钱就是触发和不触发的区别。
更坑的是,有的数据源会在收盘后调整数据(比如集合竞价成交价调整),导致你5点钟拿到的数据和第二天早上拿到的不一样。
正确做法:
- 回测和实盘用同一个数据源
- 数据落库时记录获取时间
- 关键数据做交叉验证
二、策略坑:回测很美好,现实很骨感
坑4:过拟合——回测年化80%,实盘亏20%
这是新手最容易犯的错误,我也不例外。
当时我写了一个均线策略,通过不断调参,把MA5/MA13这个组合调出来了——回测三年,年化收益78%,最大回撤12%,完美。
实盘跑了三个月,亏了23%。
问题出在哪?我在历史数据上"凑"出了一个完美参数。MA5/MA13这个组合之所以历史表现好,可能只是巧合。换一段数据,MA7/MA15可能更好。这就是过拟合。
怎么判断是否过拟合:
- 参数敏感性测试:MA5/MA13能赚,MA5/MA12和MA5/MA14也应该差不多
- 样本外测试:留一段数据不参与调参,最后验证
- 逻辑先行:先有交易逻辑,再验证,而不是从数据里"挖"规律
# 参数敏感性测试示例
results = []
for short in range(3, 10):
for long in range(10, 30):
ret = backtest(df, short, long)
results.append((short, long, ret))
# 如果只有MA5/MA13附近的一小块区域表现好,其他都很差
# 那大概率是过拟合
坑5:忽略交易成本
早期我做回测,手续费设的是万一(0.01%),印花税没算,滑点没算。
后来实盘才发现:
- 手续费:最低5元,小资金很吃亏
- 印花税:卖出千分之一
- 滑点:流动性差的股票,买一和卖一价差可能有1%
一个日均换手一次的策略,一年下来光成本就要吃掉10-15%的收益。
实际成本估算:
# 单次交易成本(买+卖)
commission = 0.0003 * 2 # 万三双向
stamp_tax = 0.001 # 印花税(卖出)
slippage = 0.002 # 滑点估算
total_cost = commission + stamp_tax + slippage # 约0.36%
# 如果每周换一次仓
annual_cost = 0.0036 * 52 # 约18.7%
现在我的回测框架里,交易成本是强制项,设得比实际还高一点。如果扣完成本还能赚钱,才值得跑实盘。
坑6:回测收益很高,实际跑不了那么多钱
有一次我找到一个小市值因子策略,回测年化40%。兴奋地准备上大资金。
结果发现:策略要求买的那些股票,日成交额只有几百万。我要是下500万进去,自己就能把股价拉涨停。
这就是策略容量问题。很多回测漂亮的策略,是建立在"无限流动性"假设上的。
正确做法:
- 回测时加入流动性过滤(比如只选日成交额>1亿的)
- 计算策略容量上限
- 分批建仓,而不是一次性买入
三、心态坑:最难过的是自己这关
坑7:回撤时忍不住手动干预
这个坑我踩了无数次。
策略回撤5%的时候,我告诉自己"再观察观察"。回撤10%的时候,我开始怀疑策略是不是失效了。回撤15%的时候,我手动平仓了。
然后,股价开始反弹,如果我没平仓,现在应该已经赚回来了。
量化交易最反人性的地方就在这:你必须信任系统,哪怕它正在亏钱。
后来我的做法是:
- 提前设定好最大回撤阈值(比如20%)
- 没到阈值之前,不允许自己手动干预
- 真到阈值了,该止损就止损,然后复盘策略
坑8:把运气当实力
2023年我有一个策略,上线三个月赚了35%。当时觉得自己简直是天才。
后来复盘发现:那三个月大盘本身就涨了20%,我的策略满仓做多,稍微跑赢大盘而已。不是我的策略好,是赶上了牛市。
怎么判断是运气还是实力?
- 看超额收益(相对基准的收益),而不是绝对收益
- 看多个市场周期的表现,而不是某一段
- 做归因分析:收益到底来自选股、择时、还是市场beta
坑9:追求完美参数
新手(包括曾经的我)总想找到"最优参数"。
但实际上,市场在变,最优参数也在变。去年最优的参数,今年可能是最差的。
现在我的原则是:
- 不追求最优,追求"足够好"
- 参数选择有逻辑支撑(比如MA20代表月线,有经济含义)
- 宁可选择钝化一点的参数,也不要过于敏感
四、工程坑:代码和系统的问题
坑10:数据接口挂了,整个系统崩溃
2024年有一次,我用的某个免费数据接口突然挂了,整整三天没恢复。结果那三天策略完全停摆,错过了几个交易信号。
这件事让我意识到:单点依赖是大忌。
后来我的做法是:
- 重要数据至少两个来源
- 主数据源挂了,自动切换备用源
- 数据每天落库备份
坑11:回测代码和实盘代码不一致
这是一个很隐蔽的bug。
我的回测代码里,信号是在收盘后生成的,第二天开盘买入。但实盘代码里,我不小心写成了"信号触发立即买入"。
结果就是实盘用了收盘前几分钟的数据生成信号,然后立即下单——相当于用了"未来数据"。
正确做法:
- 回测和实盘用同一套核心代码
- 或者至少保证逻辑完全一致
- 实盘上线前,用历史数据对比回测结果
坑12:没有日志和监控
最初我的策略就是一个Python脚本,crontab定时跑。跑完了也不知道执行了什么,有没有报错。
直到有一次策略默默失败了一周,我才发现——那一周本应该有3次交易,结果一次都没执行。
现在我的每个策略都有:
- 详细的运行日志
- 关键指标监控(持仓、收益、回撤)
- 异常报警(微信/邮件)
五、一些建议
踩了这么多坑之后,我总结了几条原则:
-
数据质量第一:宁可花时间搞定数据,也不要在垃圾数据上建策略
-
简单策略优先:复杂的策略更容易过拟合,维护成本也高
-
先求生存,再求发展:控制回撤比追求收益更重要
-
做好工程化:代码、数据、监控,每一环都要可靠
-
保持记录:每一笔交易、每一次复盘都记录下来
-
接受亏损:亏损是量化交易的一部分,关键是控制亏损的幅度
写在最后
量化交易不是躺赚的事情。我见过太多人带着"自动赚钱机器"的幻想入场,最后亏得一塌糊涂。
但如果你真的喜欢这件事,愿意花时间研究、愿意承受亏损、愿意不断迭代,量化交易是一条值得走的路。
坑总是要踩的,但希望你能踩得少一点。
有什么问题可以在评论区讨论,后续我也会分享更多实战经验。
下一篇预告:《我的量化交易工作流:从想法到实盘的完整流程》