
参数枚举优化到底在干什么
程序化交易里,参数枚举优化就是让电脑帮你试。你写一个策略,比如均线交叉,然后告诉电脑:短期均线从5到60,长期均线从20到250,步长都设成5,把所有组合跑一遍,看看哪组历史回测收益最高。电脑勤快,几万组参数一会儿就跑完,最后给你一份排行榜。你挑第一名,拿去实盘。
这个过程本质是在历史数据里找最漂亮的曲线。问题是,历史不会简单重复。你找到的那组参数,可能只是刚好贴合了那段行情的噪音。就像你拿一把钥匙去试一万把锁,总能找到一把能拧开的,但那把钥匙未必能开明天的锁。

枚举优化最大的坑 过拟合
过拟合是参数枚举的头号敌人。什么叫过拟合?策略在历史数据上表现完美,一到实盘就稀里哗啦。原因是你让电脑在噪音里挖出了根本不存在的规律。
举个股票的例子。你发现某只票在每年1月第3个星期二买入,持有5天卖出,过去十年年年赚钱。这组参数看起来很棒,但背后的逻辑是什么?没有逻辑。它就是数据挖掘出来的巧合。明年1月第3个星期二,市场环境变了,这个规律就失效了。
期货里更明显。螺纹钢主力合约,你优化出一组参数:当5分钟K线RSI低于18且成交量突破20日均量1.5倍时做多。历史回测夏普比率3.0,最大回撤5%。实盘一跑,连续三个月亏损。因为那组参数精准地捕捉了2016年到2018年螺纹钢特定阶段的波动特征,换到2020年以后的行情,波动节奏完全变了。
参数枚举优化出来的参数,可靠性天然存疑。它给你的是样本内最优,不是未来最优。
怎么判断优化出来的参数可不可靠
样本外测试是底线
你把历史数据切成两段。前70%用来枚举优化,找出最优参数。后30%不动,拿来验证。如果后30%的表现和前70%差不多,参数初步靠谱。如果后30%直接崩掉,说明参数只在前70%的特定行情里有效,扔掉。
股票策略还要注意一点:不同股票池的验证。你在沪深300成分股上优化的参数,放到中证500上跑一跑,还能不能赚钱?能,说明参数有普适性。不能,说明它只对那300只票的特定走势敏感。
滚动向前测试更贴近实战
样本外测试只切一刀,滚动向前测试切很多刀。具体做法:用2015年到2016年数据优化参数,拿到2017年去跑。再用2016年到2017年优化,拿到2018年去跑。以此类推。每一段优化出来的参数,只在紧接着的下一年使用。
这样你得到一串实盘模拟结果。如果大部分年份都赚钱,只有一两年小亏,参数可靠。如果某几年暴赚,某几年暴亏,说明参数在赌行情,稳定性差。
参数平原比参数孤峰可靠
枚举优化后,你得到一张参数-收益热力图。如果最优点周围一片都是绿色,稍微改改参数收益变化不大,这叫参数平原。这种参数抗干扰能力强,未来行情稍微偏离历史,策略不会突然失效。
反过来,最优点像一根针,周围全是亏钱的红色,稍微动一下参数就巨亏。这叫参数孤峰,是过拟合的典型特征。孤峰参数绝对不能上实盘。
经济逻辑必须说得通
参数背后要有交易逻辑支撑。均线参数选20和60,因为20天代表一个月交易天数,60天代表一个季度。这有行为金融学基础,很多机构按月度、季度调仓。你选17和53,虽然回测收益更高,但逻辑上说不通,可靠性就打折扣。
期货策略里,波动率过滤参数也有逻辑。你设置ATR阈值来过滤震荡市,阈值可以优化,但必须符合该品种正常的波动范围。螺纹钢日内ATR通常在50到150点之间波动,你优化出一个阈值是20点,意味着你只在极端窄幅震荡里不开仓,这跟没过滤区别不大。
代码演示 枚举优化加样本外验证
import pandas as pd
import numpy as np
# 假设df是包含close的DataFrame
def backtest_ma(df, short, long):
df = df.copy()
df['ma_s'] = df['close'].rolling(short).mean()
df['ma_l'] = df['close'].rolling(long).mean()
df['signal'] = np.where(df['ma_s'] > df['ma_l'], 1, 0)
df['ret'] = df['close'].pct_change() * df['signal'].shift(1)
return df['ret'].sum()
# 样本内枚举
best_sharpe = -np.inf
best_params = None
for short in range(5, 61, 5):
for long in range(20, 251, 5):
if short >= long:
continue
total_ret = backtest_ma(train_df, short, long)
if total_ret > best_sharpe:
best_sharpe = total_ret
best_params = (short, long)
print('样本内最优参数', best_params)
# 样本外验证
test_ret = backtest_ma(test_df, best_params[0], best_params[1])
print('样本外收益', test_ret)
这段代码先在全量数据上枚举,找到收益最高的短期和长期均线组合。然后拿这个组合去样本外数据跑一遍。如果样本外收益远低于样本内,甚至为负,说明参数不可靠。
期货参数枚举的特殊注意点
期货有杠杆、有到期换月、有夜盘。参数枚举时,合约拼接方式不同,结果天差地别。你按主力合约价格拼接,和按复权价格拼接,优化出来的参数可能完全相反。做期货参数优化,必须固定一种连续合约生成方式,并且在不同品种上交叉验证。
黑色系和化工系波动特征不同,农产品和金属也不同。一个参数在螺纹钢上有效,在原油上未必。你要么针对每个品种单独优化,要么找一组在多个品种上都接近平原的参数。后者虽然单品种收益低一些,但可靠性高得多。
给普通交易者的实操建议
第一,参数不要太多。一个策略超过三个可优化参数,过拟合概率急剧上升。每多一个参数,你就多了一把拟合噪音的钥匙。
第二,优化目标别只看收益。夏普比率、最大回撤、胜率、盈亏比要一起看。一个参数组合收益最高但回撤巨大,实盘你扛不住。
第三,手工微调比电脑枚举更可靠。你先用逻辑定一个大概范围,比如均线选20到60,然后手工试几组,选那个在样本外也不差的。电脑枚举出来的精确数字,比如37.5和112.3,往往没有意义。
第四,实盘先小仓位。再可靠的参数,也需要实盘验证。用最小仓位跑三个月,看看实际滑点、手续费、成交情况和回测差多少。差太多,参数再好也不能用。
参数枚举优化出来的参数,不能直接信。它是一张地图,不是终点。你要用样本外测试、滚动向前测试、参数平原检验和经济逻辑过滤,一层层筛。筛完剩下的参数,才值得放进实盘。股票和期货都一样,市场在变,参数也得跟着变。定期重新优化,但永远别把优化结果当圣旨。