量化交易中如何快速验证交易逻辑并避免过度拟合

企业微信

量化交易中如何快速验证交易逻辑并避免过度拟合

搞量化交易的人都有一个通病:脑子里蹦出一个自认为绝妙的交易逻辑,立马就想写代码回测,恨不得第二天就上实盘赚钱。结果呢?代码一跑,曲线漂亮得不行,实盘一上,亏得亲妈都不认识。问题出在哪?不是你的逻辑不够“妙”,而是你验证逻辑的方法出了大问题。今天咱们不聊虚的,就聊怎么用最短的时间、最少的代码,把一个小想法快速验证清楚,并且避开那些让无数人栽跟头的坑。

先想清楚你到底在验证什么

很多人一上来就打开编辑器敲代码,均线怎么算、止损怎么设、仓位怎么调。停!你连自己要验证什么都没搞明白。任何一个交易逻辑,剥到最里面,无非就三件事:入场条件、出场条件、仓位管理。这三个东西必须能用一句话说清楚,说不清楚就说明你自己还没想明白。

拿一个最朴素的逻辑举例:当20日均线上穿60日均线时做多,下穿时平仓。这句话里面,入场信号是均线交叉,出场信号是反向交叉,仓位管理默认全仓。你要验证的就是这个交叉信号到底有没有预测能力。别在验证阶段加什么移动止损、动态仓位、多周期过滤,那些都是后话。验证阶段要的是干净的、可复现的逻辑表达,不是花里胡哨的策略大杂烩。

把逻辑写成伪代码,一行一条,不超过五行。写不出来就说明逻辑太模糊,回测出来的结果你根本不知道是哪个条件起了作用。

量化交易中如何快速验证交易逻辑并避免过度拟合

用最少的数据和最快的代码跑第一轮

验证逻辑的第一步不是追求精度,而是追求速度。很多人一开始就拉十年分钟级数据,跑几十个参数组合,光数据清洗就花三天。等你跑完,黄花菜都凉了。第一轮验证只需要日线数据,标的选一个流动性好的指数或者ETF,时间跨度三到五年足够。

Python里面用pandas加numpy,几十行代码就能把均线交叉回测跑出来:


import pandas as pd

import numpy as np

df = pd.read_csv('data.csv', parse_dates=['date'], index_col='date')

df['ma20'] = df['close'].rolling(20).mean()

df['ma60'] = df['close'].rolling(60).mean()

df['signal'] = np.where(df['ma20'] > df['ma60'], 1, 0)

df['position'] = df['signal'].shift(1)  # 避免未来函数

df['ret'] = df['close'].pct_change()

df['strategy_ret'] = df['position'] * df['ret']

df['nav'] = (1 + df['strategy_ret']).cumprod()

这段代码里最重要的就两件事:shift(1) 和pct_change。前者确保你用的是昨天收盘后的信号来交易今天的行情,后者算的是最简单的收益率。别小看这个shift,多少人的回测曲线是靠着偷看第二天行情画出来的,把shift加上,曲线立刻从天堂掉到人间。

第一轮跑完,如果夏普比率低于0.5,或者最大回撤超过30%,直接放弃,别浪费时间优化参数。一个好的逻辑在粗糙的数据上也能看出苗头,一个烂逻辑你优化到死也救不回来。

样本外测试是照妖镜

第一轮回测看着还行,别急着高兴。你手里这份数据已经被你反复看过了,哪怕你嘴上说没调参数,脑子里早就对这个时间段的市场走势有了印象。这时候必须做样本外测试。把数据切成两段,前70%用来开发逻辑,后30%完全不碰。或者更狠一点,找一个和你标的高度相关的另一个市场数据来跑,比如用上证50的逻辑去跑沪深300。

样本外测试的结果比样本内差是正常的,差太多就是过拟合。差多少算太多?夏普比率掉一半以上,或者最大回撤翻倍,基本就可以判定逻辑没有普适性。很多人舍不得放弃,觉得“再调调参数就能救回来”,这就是典型的赌徒心理。样本外亏钱的逻辑,实盘只会亏得更多,因为实盘还有滑点和手续费。

参数敏感性测试一分钟搞定

有个特别快的方法能测出你的逻辑是不是靠参数凑出来的:把你逻辑里的核心参数从中间值往两边各扩两步,看结果稳不稳。拿均线举例,20和60是基准,试试15和55、25和65、30和70。如果这些组合的收益曲线形状差别不大,说明逻辑不依赖特定参数,有生命力。如果只有20和60能赚钱,其他的都亏,那你就别骗自己了,这逻辑就是个数字巧合。

这个测试不需要跑完整回测,看看信号频率和胜率的变化趋势就够了。信号频率随参数变化剧烈波动,说明逻辑对市场节奏太敏感,实盘环境稍微变一下就不灵了。

蒙特卡洛模拟比回测更诚实

回测曲线只有一条,但市场有无数种可能的走法。把历史交易信号提取出来,随机打乱交易顺序,或者随机抽取交易子集,跑一千次,看看资金曲线的分布。如果一千次模拟里有30%以上的情况是亏钱的,那你的逻辑本质上就是在赌运气。

这个操作在Python里也就几行代码的事。把每笔交易的收益率拿出来,随机排列组合生成一千条新的净值曲线,看最终收益的分布。分布越集中、正收益比例越高,逻辑越可靠。分布散成一片,说明你的回测曲线就是幸存者偏差的产物。

模拟盘是最后的减速带

回测和现实之间永远隔着一层纸,这层纸就是交易执行。信号在收盘前五分钟出现,你来得及下单吗?流动性够不够吃下你的单子?滑点比你在回测里设的大多少?这些问题回测全测不出来。

最快的验证方式是用模拟盘跑两周到一个月。别小看这两周,它能把你的逻辑在真实数据流下暴露得干干净净。信号触发时间和实盘吻合吗?盘中有没有出现过回测里没见过的极端行情?模拟盘不需要跑太久,但必须跑,不跑模拟盘直接上实盘的,都是在拿真金白银交学费。

逻辑验证的底线原则

最后说几条铁律。第一,永远不要用未来数据,哪怕是收盘价,也要确认你的信号是在收盘之后才计算出来的,第二天开盘才能交易。第二,交易次数太少不说明问题,一个逻辑只交易了十几次,赚了也是运气,至少三十次以上才有统计意义。第三,手续费和滑点不能省,回测里加点手续费,曲线立刻现原形,连手续费都扛不住的逻辑不是好逻辑。

验证交易逻辑这件事,最忌讳的就是“我觉得”。你觉得市场会反弹,你觉得这个指标有用,你觉得参数优化一下就能赚钱。量化交易的全部意义就是用数据代替“我觉得”。快速验证的核心不是快,而是用最粗暴的方式把你的逻辑扒光,看它到底有没有穿底裤。穿了的留下,没穿的扔掉,别跟自己的钱过不去。

转载请注明出处:https://www.lianghuajiaoyi.top/wenzhang/lianghua-jiaoyi-jiaoyi-luoji-1491.html