ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

期货量化策略如何防止过拟合?参数优化与稳健性检验实战指南

期货量化策略如何防止过拟合?参数优化与稳健性检验实战指南 1. 先搞清楚过拟合在期货量化里意味着什么做期货量化的人很少有谁没碰过“参数优化”这个环节。把均线周期一拖止损线位数一拉点一次回测年化从 8% 变成 35%谁看了都心动。我在做螺纹钢、橡胶这类品种的日内 CTA 和隔夜波段策略时也做过太多这样“顺手”的优化。结果毫无例外参数换一个区间就失灵换一个品种就失效甚至同一段数据多往后推两天绩效曲线就连续回撤。这个问题的核心不是“参数优化”本身可恶而是我们对它的使用方式太粗暴了。参数优化本质上是把策略的参数空间扫一遍寻找让历史表现最好的组合。问题在于历史数据里的信息分成两类一类是相对稳定的市场规律一类是纯粹的噪声。参数优化算法不区分这两类信息它只会找一个在历史上最“贴脸”的参数组合。噪声被大量记忆下来就成了过拟合。很多朋友一听“过拟合”就以为只有那些跑深度学习、几百个因子的团队才会遇到。这是误解。哪怕你只有一个双均线系统两个参数一样可以过得严严实实。因为过拟合不完全取决于参数数量而取决于你给参数留了多少“自由发挥”的空间。观察一次历史行情里均线金叉后顺利拉出大阳线于是你就把均线周期微调成恰好能抓住那一次行情的数值止损设在恰好离最低点差两个 tick 的位置你觉得自己在优化策略其实是在做一笔事后诸葛的模拟。1.1 过拟合不是“参数多”的专利我见过不少新手逻辑我的策略只有两三个参数肯定不会有过拟合问题吧这个直觉是错的。过拟合的成因是“复杂度的自由度超过数据有效信息的支撑能力”。哪怕参数很少只要你在选参时看的是同一段历史数据的多次试错每一次试错都在“偷看答案”。看十次你就对那段行情形成了极强的记忆。参数多的策略只是让这件事更容易发生但真正引发质变的因素是你对同一段数据进行了多少次切片式的“优化借鉴”。举个例子。你用某一年的螺纹钢行情调均线周期从 10 到 60 每隔 1 测试一共 50 次选到最漂亮的一组。请问这个过程中的每一次回测是不是都在消耗你对这批数据的新鲜感是。即便你的模型只有一条均线和一个固定止损你也等于在这段数据上做了 50 次模式匹配选出了一个最巧合的答案。换一段行情大概率就不是那么回事了。这个道理我用了一个很生活化的比喻理解它期末考试的题目你反复背了十遍连每个选项的陷阱都能背出来你觉得自己考得很好但换成一套新题目你会发现自己对知识点的理解并没有那么牢。参数优化和考试背诵的差别只在于优化过程不带心理负担看起来很理性实际上比盲目背诵更危险。1.2 过拟合在期货策略中的具体表现过拟合的实盘症状有迹可循不用等真正的实盘亏损才去排查。我总结过自己在品种和策略里反复见到的几种信号参数敏感度极高周期参数从 20 改到 19绩效从 30% 年化变成 -12%改到 21 又变成 28%。这种陡峭的“参数悬崖”极大概率是过拟合。单品种特化某个参数组合在焦煤上特别猛但你放到热卷、铁矿、甲醇上一试全崩。这通常意味着你只是记住了焦煤某段行情的形状。样本内和样本外差异巨大前面三年曲线漂亮后面两年无论怎么回放都明显衰减甚至亏损。换月、交割、复权方式不同绩效剧烈变化。真实可用的策略对数据细节应该有稳定性除非你交易的就是跨期价差。优化出的止损位带有“无意义精度”比如止损 17 个 tick、止盈 53 个 tick。市场不会精确到这种“恰好”的程度。这类参数是典型的噪声记忆。以上这些表现大多数不是交易者故意犯错而是优化流程里没有引入“对抗过拟合”的机制。后面章节讲的就是怎么把这种对抗机制加进日常流程。1.3 从源头分解数据、逻辑、执行三层防线面对过拟合不能只靠“我少调几次参数”这种意志力。有效的做法是从三个层面设计防线第一层是数据层面。入场前就把训练集和验证集分开并且坚持验证集只使用一次。很多人回测喜欢反反复复在完整数据集上“看效果”这等于把验证和训练揉在一锅粥里再也说不清楚哪个是真实表现。第二层是逻辑层面。策略要有经济学或市场微观层面的逻辑基础。我常问自己我凭什么觉得这个规律存在如果答案只是“回测里出现这个信号后往往涨”那可靠性很低。如果答案能落到“节假日前后资金谨慎、持仓等待节后方向选择”这类可理解的行为逻辑上参数即便失效你也知道怎么迭代逻辑。第三层是执行层面。回测模型要尽量包含滑点、手续费、涨跌停约束、仓位限制。把成本手续写得太理想优化算法会发现你的策略大量收益来自成交价完美跳过障碍——这不是策略优势是回测缺陷。执行层面的失真会量产“操作性过拟合”。这三层防线每一层都是独立的。单靠任何一层都不够但一起做能拒绝掉绝大部分“好看但不中用”的参数组合。2. 参数优化常用方法盘点网格、随机与贝叶斯优化接下来说具体优化的“器”。我在期货策略上跑过的参数优化方式主要就三种网格搜索、随机搜索、贝叶斯优化。它们的目标一致但计算开销、搜索效率、使用场景完全不同。2.1 网格搜索最有直觉但最容易迷失网格搜索就是把参数空间按步长切分计算每个组合的表现。比如双均线策略快线 5 到 50慢线 20 到 200步长 5一共就有 10×37 等于 370 组组合。加上止损、仓位规则组合数量很快就膨胀。网格搜索最大的优点是简单、可解释而且能输出一张完整的“参数平面”方便你观察绩效在参数空间中的分布。这一点对防过拟合很有价值后面我会专门讲参数平面分析。但它有两个代价一是计算耗时随维度指数增长二是它容易让人把“选定一组最优”当作终点忽略邻域参数的表现。我自己不会完全抛弃网格但会把网格当作三维可视化工具来用而不是当作参数决策器。先画图看全局再决定该往哪个区域深入。2.2 随机搜索与贝叶斯优化什么时候用当参数维度上升到 4 个以上网格组合很容易破万组。这时候该用随机搜索或贝叶斯优化。随机搜索的思路很简单在参数空间内随机采样比如跑 2000 组观察绩效分布挑比较好的区域继续采样。它比网格更有优势的地方在于在“参数数量多而有效区间窄”的场景里随机采样更容易碰到那些不一样的可能性。网格搜索如果步长选得不好可能恰好跳过全部有效参数。贝叶斯优化更聪明它会根据之前测试的结果用一个概率模型估计“参数空间各处的潜在效果”然后优先探索那些既有希望、又存在不确定性的区域。对于回测慢的策略这是效率最高的方案之一。期货策略的回测如果包含分钟级数据和复杂的撮合逻辑几分钟才能跑一组参数网格完全不现实贝叶斯优化可以帮你把有效探索次数降到几百组以内。我需要提醒一点不要因为贝叶斯优化听起来高深就迷信它。它给出的一组“最优参数”同样可能是过拟合尖峰因为它只是在效率更高地搜索历史表现最好的点。你需要做的事和网格搜索一样检查参数的邻域是否稳定、样本外是否有效。2.3 从我实盘角度出发优化方式的选型建议我的建议不复杂照着用就行参数只有 2 到 3 个且回测速度快优先网格搜索同时生成参数平面图做敏感性分析。参数 3 到 5 个回测速度中等用随机搜索先摸分布再用局部网格精修。参数 5 个以上或者单次回测超过 1 分钟用贝叶斯优化但必须配合样本外验证。无论用哪种优化方式最终交付的参数必须通过“平坦区域检验”和“时间外样本检验”否则一律不用。还有一个容易忽略的问题不要只做一次优化就完事。我习惯按滚动窗口做多次优化观察“最优参数”随时间是否会漂移。如果最优参数在近五年内每年都不一样说明策略对参数依赖太强本身就很不健康。这个点放到第五部分详细展示。3. 避免过拟合的五个核心技巧这一节是整篇文章的灵魂。我按下述五个技巧在实践中逐一使用它们共同抵御了绝大多数无效优化。3.1 时间滚动样本内外验证别做“一次性拟合”最常见的错误是把全部历史数据丢进去优化再在同样的数据上评估绩效。那是典型的“开卷考试”。正确的做法是把数据按时间切开用一段数据训练参数用另一段数据检验参数。以我的习惯为例想要测试一个日内突破策略在最近几年的表现我不会把 2019 到 2024 年全部塞进优化器。我会先用 2019 到 2022 年做参数扫描选定一组参数然后把 2023 到 2024 年当作从未看过的样本外数据只跑一次验证。如果样本外绩效显著低于样本内这组参数就不合格。更进一步的做法是滚动前推验证也叫 walk-forward。它的流程是在时间点 t 训练在 t1 段验证然后把训练窗口往前推再训练再验证。这样的好处是能观察到一个策略在不同市场环境下的参数稳定性。我一般把数据切成 3 到 4 段每段训练、验证循环一次取验证结果的平均值作为策略的有效表现而不是单看某一次验证曲线的最高峰。这里有一个非常现实的操作细节验证集只能使用一次。如果你看完样本外表现不好马上调整参数再重新跑一次验证那你已经“污染”了验证集。第二次的样本外表现不再是独立检验它已经携带了你的主观矫正。所以一旦开始验证就要忍住“再调一下”的手痒若确实要迭代就把验证集再往后推移引入真正新鲜的数据。3.2 参数平面分析挑平稳高原而不是孤峰网格搜索不仅是为了找出“最大值”更关键的是看绩效平面长什么样。我举一个自己 2022 年处理过的例子。策略是常见的唐奇安通道突破参数包括入场周期 N 和止损倍数 M。画出的绩效热力图显示在 N 介于 20 到 45、M 介于 1.5 到 2.5 的区域年化收益呈现出不太平滑的连接带整体差异不超过 5 个百分点。但当你把 N 调到 38、M 调到 2.1 时会出现一根孤立的尖峰年化瞬间高出其他组合 18 个百分点。那根尖峰就是过拟合的最典型标记。为什么因为真实市场规律通常是缓慢渐变的相邻参数表现差异不大说明策略对参数选择不敏感任何一组邻域参数都能抓到类似行情。而孤立尖峰的出现意味着只有那一组参数恰好匹配了历史上某几个极端行情的细节这种匹配很难在未来再现。操作上我会在参数数组上选出“表现较好的平坦区域”然后取该区域的中心点或稳健点而不是取最大值。如果平坦区域内年化收益都在 18% 到 22% 之间那取 18% 那组参数是合理的孤峰 40% 反而不该用。用代码表达也很简单选择合适的稳健性统计量而不是 maximport numpy as np import pandas as pd # 假设 flat_region 是根据参数平面筛选出的一组候选组合 # 每个元素是 (param_dict, annual_return, max_drawdown) candidates [ {fast: 20, slow: 120, ret: 0.19, mdd: 0.12}, {fast: 22, slow: 125, ret: 0.20, mdd: 0.13}, {fast: 25, slow: 130, ret: 0.21, mdd: 0.14}, {fast: 38, slow: 210, ret: 0.42, mdd: 0.11}, # 孤峰 ] # 策略按绩效排序但排除孤峰 candidates_sorted sorted(candidates, keylambda x: x[ret], reverseTrue) # 孤峰识别观察它与次优之间的收益差以及邻域连续性 # 如果最大收益与第二名的差异远大于第二名到第三名的差异先标记为可疑 ret_gap_1 candidates_sorted[0][ret] - candidates_sorted[1][ret] ret_gap_2 candidates_sorted[1][ret] - candidates_sorted[2][ret] print(f最高降次高: {ret_gap_1:.2%}, 次高降第三: {ret_gap_2:.2%}) # 实际选择时宁可要“稳健平庸”不要“尖峰惊艳” robust_choice candidates_sorted[2] # 举例跳过孤峰选平坦区域内的稳健组合 print(robust_choice)这组代码不是为了直接跑出答案而是提醒你现在很多现成框架会默认给你“全参数空间最优解”你需要在业务判断层面拒绝它。3.3 多品种多周期稳健性你的秘密武器单品种的样本外表现都可靠吗不一定。因为一个品种的历史行情也可能存在偶然段。比如某个品种在某几年走了特别清晰的趋势你针对这个品种调出来的参数放到别的品种或别的周期上就没用了。我的习惯是任何参数组合都必须同时通过多品种和多周期的复验。以螺纹钢、热卷、铁矿石、焦炭、甲醇这几个流动性较好的品种为例策略在螺纹钢参数优化后我会直接把同一组参数放到其他品种上不做任何调整地回测。如果收益大幅度衰减甚至亏损这组参数极可能是螺纹钢特化形态。多品种复验不需要每个品种都赚钱但至少要做到“不出现无法解释的巨大亏损”。如果某个品种产生异常回撤要分清究竟是策略逻辑不适用该品种还是优化过程过拟合了螺纹钢。这个区别并不难判断把参数平原画出来如果螺纹钢的参数平面有明显孤峰而其他品种参数平面平淡那就是特化。多周期也一样。一个趋势策略如果在小时线上有效那至少在 30 分钟和日线上不能变成一个彻底亏损的“反向指标”。跨周期一致性不代表直接用同一组参数而是指逻辑的普适性。如果策略只能在某一个特定周期上有效其他周期全部亏掉那要高度怀疑是噪声拟合。品种和周期的复验有一个附带收益你会被迫让策略保持简洁。因为每增加一个规则和参数都会降低它多品种适用的概率。这种“被迫整洁”本身就是防止过拟合的方法。3.4 用惩罚项约束参数精度在优化目标中加入惩罚项压制“高精度参数”和“极端参数”是另一种有效的防过拟合手段。我用这样一个思路策略优化的目标函数不再是单一年化收益最大值而是“扣除了参数复杂度代价后的净收益”。常见做法包括参数精度惩罚对止损参数限制为 5、10、15、20 这样的整数档位避免出现 17、23 这类精度因为那样等于让模型记住了行情细节。参数数量惩罚参数越多惩罚越大每增加一个有实际影响的参数要求它带来显著的绩效提升否则不采用。样本外惩罚把样本外表现作为负向参考如果样本外和样本内的绩效差距过大整体评分下调。我常用一个简单的目标函数结合夏普比率、最大回撤和参数稳定性def fitness(annual_return, sharpe, max_drawdown, param_count, y_margin0.5): # 参数数量多减分更多同时限制回撤 complexity_penalty 0.02 * param_count score 0.5 * annual_return 0.3 * sharpe - 0.4 * max_drawdown - complexity_penalty return score这只是一个示例权重你完全可以根据风险偏好调整。重点不在公式而在“参数数量、参数精度必须付出代价”的意识。否则优化算法自然会把所有有利条件统统用上到头来你得到的是一个记忆库。3.5 数据泄漏与未来函数检查这是血泪教训程序员出身的朋友经常会在处理 K 线数据时无意中掺入未来信息。比如用当天的最高价去判断当天入场信号这等于作弊。更隐蔽的是用全局归一化后的指标去生成信号归一化参数本身用到了未来数据。我用过一个经典案例某个策略在优化后回测绩效优秀但仔细排查后发现技术指标计算时我用了全样本的均值与标准差进行标准化。这个标准化参数看起来只是个数据处理细节却把未来几年的统计信息带进了每一个信号。幸好及时发现否则这份“策略”上实盘就是稳定亏损。未来函数的排查我总结出几个习惯写回测时所有指标只能使用截至当前 K 线收盘的数据。如果用滚动窗口计算指标必须在循环内逐步更新窗口不能在整段数据上预先算好。对涉及归一化的指标用历史滚动窗口的均值、标准差而不是全样本的。逐根 K 线用手工推演几个样本核对信号发生的时间点是否晚于价格确认这在调试时比任何自动化测试都直观。还有一类数据泄漏来自“幸存者偏差”做商品期货往往还好因为品种存在退市少但如果你做的是股票或指数成分股的历史回测就要注意当时的成分股和现在的成分股不同。期货上的数据泄漏主要来自换月拼接主力合约切换时的价格跳变如果处理不当会给策略带来虚拟的跳空盈利。处理主力合约连续时要么用复权价要么在回测撮合中明确禁止在换月瞬间以“无缝成交”方式平仓。4. 期货交易成本与微观结构约束下的参数优化期货和股票与加密货币不同。期货有保证金、换月、涨跌停、夜盘、不同合约流动性和差异化手续费。参数优化如果忽略这些等于在一张没有重力的小图上做飞行测试。4.1 滑点、手续费、冲击成本怎么折算进优化在参数优化的初始阶段就要把交易成本写入回测并纳入参数评分。滑点尤其重要很多短周期策略对价格敏感优化的参数往往极度依赖“入场价就是最高点之后瞬间反转”等难以实现的成交质量。我自己处理成本的方式是分档保守档每手单边计 1 个 tick 滑点加上手续费。例如螺纹钢一个 tick 是 1 元/吨一手 10 吨那么单边成本就是 10 元滑点加合约手续费。严厉档每手单边计 2 个 tick 滑点并把手续费按期货公司默认标准加一倍。窄止损策略必须过严厉档测试。操作时不要把“滑点”放在优化结束后手动减一下而是直接在回测引擎撮合成交时按不利方向滑点并在参数评估函数里加入交易成本。这样优化器会自动避开那些高频次交易、低单笔期望的“伪盈利”区域。4.2 涨跌停、跳空、换月对参数选择的影响商品期货有涨跌停制度连续涨跌停时持仓无法按理想价位平仓。这会导致回测中的“按收盘价平仓”完全不现实。参数优化若偏好设置紧止损又没有模拟涨跌停约束很容易高估风险。跳空是另一个大坑。你在夜盘开盘跳空高开超过止损位回测模型可能默认以开盘价和止损价中较优价格成交而实盘只能吃到开盘价之后的市场深度。为了稳健我在回测引擎里默认止损失效时按下一根真实成交 K 线的开盘价并叠加不利滑点成交。这样做会让很多“漂亮参数”现出原形但换来的真实性极其宝贵。换月不处理好的后果也很严重。主力合约切换时旧合约流动性和新合约不同且价差跳变不是真实可交易的价差。如果回测直接采用主力合约价格序列换月当天的剧烈价差可能被策略误判为信号产生虚假盈利。我建议用复权方式拼接连续合约并在实盘交易规则里设定换月移仓窗口不要在切换瞬间无成本平仓。4.3 为什么“完美回测”往往靠不可交易价格实现很多参数优化得到的高绩效仔细拆开看收益往往集中在少数几笔“极端完美成交”的交易上。比如某一天触发了入场信号成交在极低点另一天触发了离场信号成交在极高点。这种回测里的交易区间和时间充满了“刚刚好”的巧合。我处理这个问题时有一个习惯单独统计每笔交易的滑点敏感性影响。做法很简单按市价模拟时把入场和离场分别加上 1 个 tick、2 个 tick、3 个 tick 的不利滑点重新计算收益。如果策略的最终净值对单个 tick 的滑点极其敏感那说明策略其实是在和交易成本比赛而不是在和市场规律比赛。绝大多数有效策略至少应该能承受 2 个 tick 的滑点变动而不改变盈亏结构。4.4 一套我常用的成本惩罚公式我习惯把所有交易成本折算成“单边费用比例”然后在优化评分中扣除。这样做的好处是不同品种、不同手数之间可以横向对比。def cost_adjusted_return(gross_return, trade_count, avg_slippage_ticks, tick_value, contract_value, fee_per_lot, lots1): # gross_return 为未计成本的毛利比例 # trade_count 为总交易次数 # avg_slippage_ticks 为平均每边滑点 tick 数 # tick_value 为最小变动价位对应的盈亏额 # contract_value 为单手合约价值 # fee_per_lot 为单边手续费 # 单边合计成本滑点 手续费 avg_slippage_cost avg_slippage_ticks * tick_value * lots total_cost_per_trade (avg_slippage_cost fee_per_lot * lots) * 2 # 双边 total_cost_ratio total_cost_per_trade * trade_count / contract_value net_return gross_return - total_cost_ratio return net_return这套思路不是唯一的但它的价值在于把“优化目标”和“真实可交易性”绑定在一起。参数优化一旦把成本纳入目标就不会再去选择那些依赖高频低质交易的参数区。5. 完整实操记录一个双均线通道策略的优化全过程我会用一个非常简单的策略示例完整展示我如何把上面所有技巧串起来。这个策略不带任何圣杯属性只是方便说明流程。5.1 策略需求定义与数据准备假设策略逻辑如下当快线上穿慢线且价格创出过去 N 日新高时做多当快线下穿慢线或价格创出过去 N 日新低时平多。反手同理做空。这个策略实际上是一个简单的双均线加通道过滤。为了演示参数优化我保留三个参数fast快线周期slow慢线周期channel通道突破周期数据使用某商品期货主力连续日线时间范围 2018 年 1 月到 2024 年 12 月。我把 2018-2022 作为训练优化期2023-2024 作为样本外验证期。这里有一个关键习惯所有数据在优化前只做最基本的复权与拼接不允许在训练阶段看到验证期数据。我甚至会把验证期数据从工作目录中暂时移走防止自己在调试中无意间瞟到。5.2 网格优化代码与参数平面计算我先把参数空间跑一遍得到完整的绩效矩阵。import numpy as np import pandas as pd def run_backtest(df, fast, slow, channel, cost_per_trade0.001): # 极简示意返回年化收益和最大回撤 # 实际回测请使用完整撮合逻辑 df df.copy() df[fast] df[close].rolling(fast).mean() df[slow] df[close].rolling(slow).mean() df[high_n] df[high].rolling(channel).max().shift(1) df[low_n] df[low].rolling(channel).min().shift(1) position 0 equity [0.0] for i in range(1, len(df)): # 信号判断省略核心是展示参数扫描结构 pass return 0.15, 0.10 # 示例返回 fast_range range(10, 51, 5) slow_range range(60, 201, 10) channel_range range(10, 41, 5) results [] for fast in fast_range: for slow in slow_range: if fast slow: continue for channel in channel_range: ann_ret, mdd run_backtest(train_df, fast, slow, channel) results.append((fast, slow, channel, ann_ret, mdd))跑完之后我会把结果转成一个三维结构对“fast 和 slow”两个维度做切片画热力图观察绩效的分布。代码只是最粗略的骨架但流程的核心是扫描完所有组合后我不要只看最大值而是把参数平面画出来观察哪里是“高原”。5.3 样本外与多品种复验扫描结果中训练期里最优的一组参数可能是 fast15slow80channel20年化 34%。但参数平面显示它的邻域极不稳定从 fast15 改成 10 后年化掉到 8%改成 20 后掉到 11%。与此同时另一个区域 fast25slow120channel30 到 35 之间的年化收益都稳定在 18% 到 22% 区间。按照 3.2 的方法我会放弃 34% 的孤峰选择 20% 左右的高原区域。然后把这组“高原参数”放到样本外数据 2023-2024 上验证。验证结果若仍能保持 16% 到 20% 的年化且回撤可控这组参数才算初步通过。下一步是多品种复验。我会在热卷、铁矿、甲醇、PTA、塑料等多个品种上使用同一组参数不做任何重新优化。如果大部分品种能保持正收益少数品种亏损但在合理范围那策略逻辑的可复制性较强如果只有原品种盈利其他全部亏损直接淘汰。5.4 最终参数的选择思路最终参数我不会选验证期中表现最好的那一组而是选“验证期中位数表现靠前且邻域稳定”的组合。更简单地把参数平面上年化收益处于前 20% 的区域全部标记出来。再计算这些区域中每个参数组合的邻域标准差选邻域标准差较小的组合。最后通过样本外和多品种复验的那一组才作为实盘候选。这个流程听起来保守但保护作用极强。我过去的经验是过度追求训练期最优参数实盘基本都在半年到一年内出现异常回撤而通过“高原检测”和“多品种复验”选出的参数往往能存活更久。6. 常见问题排查与避坑速查表最后把我在实盘和回测中踩过、见过的坑集中盘点一下。这些问题很典型希望你能跳过。6.1 回测很好、实盘崩盘的三个根源第一根成本失真。回测时滑点设为零手续费设成“象征性”水平。结果实盘里策略实际收益被成本磨损掉大半。检查方法把滑点调成 2 到 3 个 tick 再跑一遍如果绩效崩塌成本就是根因。第二根信号生成依赖完美成交。比如用 K 线收盘价确认信号但假设在同一根 K 线的收盘价成交。实盘中信号确认和成交之间存在延迟尤其在快速行情里延迟会导致成交价显著偏离。检查方法把信号确认推迟到下一根 K 线开盘价且开盘价叠加不利滑点再看绩效。第三根过拟合。训练期最优参数是孤峰参数平面周围一片“毒区”到了实盘遇到不同的波动率状态后策略立刻失效。检查方法画出参数热力图看看所选参数是不是处于连续高原而不是独立尖峰。6.2 参数敏感性发现的“雷区”怎么处理你可能会在处理参数平面时发现某个区域有“如果参数略变最大回撤瞬间放大”的现象。即使收益还不错这也是雷区。回撤放大意味着策略对参数极其敏感可能只差几个单位就会触发一连串不顺畅的交易。处理方式把该区域排除哪怕它收益再高。因为未来的参数漂移和数据噪声是必然的你需要的是容错性不是历史最优。另一种雷区是“优化参数分布在边界位置”。比如 slow 周期的可测范围是 60 到 240如果最优参数集中在 60 附近说明你可能没有把空间探索完整甚至真实有效参数可能在 60 以内。这时候应该扩展参数范围重新扫描而不是直接接受边界解。6.3 避坑速查表参数优化的自检清单检查项错误做法正确做法训练/验证数据整段历史同时优化和评价严格切分训练期与验证期验证期只使用一次参数选择直接选绩效最大值选参数平原/高原区域内的稳健组合参数精度保留 17、23、36 这类任意精度步长设为整数、5 或 10 倍数的可解释档位交易成本优化结束后统一减成本在回测撮合和参数评分阶段就计入成本未来函数全样本标准化、未来数据参与指标计算严格滚动窗口逐根 K 线核验多品种验证只测单一品种同一组参数在多个相关性不高的品种上复验换月处理直接拼接主力合约价格正确复权或指定移仓窗口多周期验证只测单一周期至少再验证一个相邻周期的稳定性参数数量往策略里堆过滤条件每个新参数必须带来显著且稳健的收益提升否则删除样本外结果不好就调参再试验证集只使用一次重新迭代必须引入新数据这套自检清单我打印出来贴在工位上。每跑一轮优化就逐项对照能拦住绝大多数由手痒导致的“优化悲剧”。我自己的体感是参数优化有用的前提是你根本不指望找到“最优参数”而是找到“最不容易失效的窄参数区”。真正靠前的业绩来自策略逻辑和风控执行而不是某组精密校准的数字。每次回测跑完多问自己一句这个参数换一个品种、再换一段行情还能站得住脚吗问多了手自然就不敢乱动了。
返回列表