第十三章:策略参数调优

做市策略写好了,回测也跑通了。然后呢?

你会发现一个尴尬的事实——策略能不能赚钱,很大程度上取决于那几个参数。比如订单簿深度用多少档?报价更新频率设多快?库存上限设多少?

这些参数,说白了就是策略的「旋钮」。拧对了,收益曲线漂亮得像艺术品。拧错了,回撤能让你怀疑人生。

我见过太多人,策略逻辑写得挺好,结果参数随便填了几个数,上线就亏。嗯,今天我们就聊聊怎么科学地调这些参数。

13.1 参数调优的本质

先想清楚一个问题:我们到底在调什么?

做市策略的参数,通常分三类:

  • 风险控制类:最大持仓、止损线、报价偏离度
  • 策略行为类:报价频率、订单生命周期、价差倍数
  • 市场感知类:波动率窗口、成交量阈值、订单簿深度

每一类参数,都对应着策略的某个行为模式。调参的本质,就是在「激进」和「保守」之间找到平衡点。

核心原则:参数调优不是找「最优解」,而是找「稳健区间」。

最优解往往在过拟合的边缘。稳健区间才是能上线赚钱的。

13.2 网格搜索:最笨但最可靠的方法

网格搜索,说白了就是穷举。你把每个参数的可能取值列出来,然后遍历所有组合。

比如你有两个参数:

  • 参数A:报价深度,取值范围 [1, 3, 5, 10]
  • 参数B:价差倍数,取值范围 [0.5, 1.0, 1.5, 2.0]

总共 4×4 = 16 种组合。全部跑一遍回测,选收益最高的那组。

# 网格搜索示例
import itertools

param_grid = {
    'depth': [1, 3, 5, 10],
    'spread_mult': [0.5, 1.0, 1.5, 2.0]
}

best_score = -float('inf')
best_params = None

for depth, spread in itertools.product(param_grid['depth'], param_grid['spread_mult']):
    score = backtest_strategy(depth, spread)
    if score > best_score:
        best_score = score
        best_params = {'depth': depth, 'spread_mult': spread}

print(f"最优参数: {best_params}, 得分: {best_score}")

网格搜索的优点很明显:简单、直观、可解释。缺点也很致命:参数多了就爆炸。5个参数,每个取10个值,就是10万次回测。我有个项目,网格搜索跑了整整三天三夜。

我的习惯:先用粗网格找到大致区域,再用细网格精调。别一上来就搞精细搜索,那是浪费电。

13.3 随机搜索:用概率换效率

随机搜索的思路很简单:既然穷举太慢,那就在参数空间里随机采样。

你想想看,网格搜索在某个维度上取了10个值,但可能最优解恰好不在这些点上。随机搜索反而有可能「蒙中」更好的点。

# 随机搜索示例
import random

def random_search(param_ranges, n_iterations=100):
    best_score = -float('inf')
    best_params = None
    
    for _ in range(n_iterations):
        params = {
            'depth': random.choice([1, 3, 5, 10]),
            'spread_mult': random.uniform(0.5, 2.0),
            'vol_window': random.randint(10, 100)
        }
        score = backtest_strategy(**params)
        if score > best_score:
            best_score = score
            best_params = params
    
    return best_params, best_score

随机搜索有个数学上的优势:当参数空间维度很高时,随机采样的覆盖效率远高于网格搜索。我记得有一篇论文专门论证过这个,结论是随机搜索在大多数情况下比网格搜索更划算。

注意:随机搜索的结果不稳定。同样的代码跑两次,可能得到不同的「最优参数」。我建议多跑几次,取出现频率最高的参数组合。

13.4 贝叶斯优化:用历史信息指导搜索

网格搜索和随机搜索,本质上都是「盲搜」。它们没有利用已经跑过的结果来指导下一步搜索。

贝叶斯优化就不一样了。它会建立一个「代理模型」,预测参数空间里哪些区域可能更优。然后每次采样都选最有潜力的点。

# 使用 scikit-optimize 进行贝叶斯优化
from skopt import gp_minimize
from skopt.space import Integer, Real

def objective(params):
    depth, spread_mult, vol_window = params
    return -backtest_strategy(depth, spread_mult, vol_window)  # 取负值,因为我们要最小化

space = [
    Integer(1, 10, name='depth'),
    Real(0.5, 2.0, name='spread_mult'),
    Integer(10, 100, name='vol_window')
]

result = gp_minimize(objective, space, n_calls=50, random_state=42)
print(f"最优参数: {result.x}, 最优得分: {-result.fun}")

贝叶斯优化的好处是收敛快。通常只需要网格搜索 10%-20% 的计算量,就能找到差不多的结果。我在一个高频做市项目里用过,原本网格搜索要跑 2000 次,贝叶斯优化 200 次就搞定了。

但要注意,贝叶斯优化也有坑。它容易陷入局部最优,尤其是目标函数有很多「尖峰」的时候。我建议先用随机搜索跑几轮,把结果作为贝叶斯优化的初始点。

13.5 过拟合防范:调参最大的坑

调参最大的敌人,不是参数多,而是过拟合。

什么叫过拟合?就是你找到的参数,在历史数据上表现完美,一到实盘就崩。

为什么会这样?因为市场数据里有很多「噪声」。你调参的时候,可能恰好拟合了这些噪声,而不是真正的市场规律。

过拟合的典型症状

  • 回测夏普比率 > 5(除非你是文艺复兴基金)
  • 参数稍微变一点,收益就大幅波动
  • 不同时间段回测结果差异巨大

怎么防范?我总结了几个实用方法:

13.5.1 交叉验证

别只用一段数据调参。把数据分成几段,轮流做训练集和测试集。比如用 2023 年 1-6 月的数据调参,然后用 7-12 月的数据验证。

# 时间序列交叉验证示例
def time_series_cv(data, n_splits=5):
    scores = []
    for i in range(n_splits):
        train_end = int(len(data) * (i + 1) / (n_splits + 1))
        test_end = int(len(data) * (i + 2) / (n_splits + 1))
        
        train_data = data[:train_end]
        test_data = data[train_end:test_end]
        
        params = optimize_params(train_data)
        score = evaluate_params(params, test_data)
        scores.append(score)
    
    return np.mean(scores), np.std(scores)

13.5.2 参数稳定性检查

找到最优参数后,别急着用。在最优参数附近随机采样,看看收益变化是否剧烈。如果稍微动一下参数收益就暴跌,说明这个「最优」很可能是过拟合的。

13.5.3 样本外测试

这是最笨但最有效的方法。调参的时候留出一段数据完全不碰,等参数定好了,用这段「新鲜」数据跑一次。如果结果还行,那参数大概率靠谱。

我曾经犯过一个错误:用 2022 年全年的数据调参,结果参数在 2023 年 1 月就失效了。后来才发现,2022 年市场波动率异常高,参数完全被带偏了。从那以后,我坚持用不同市场环境的数据做验证。

13.6 实战建议:调参流程

说了这么多,到底怎么落地?我分享一下自己的调参流程:

  1. 先定范围:根据经验,给每个参数设定合理的取值范围。别太宽,也别太窄。
  2. 粗筛:用随机搜索跑 100-200 次,找到几个有潜力的区域。
  3. 精调:在潜力区域用贝叶斯优化跑 50-100 次。
  4. 验证:用交叉验证和样本外数据做双重检验。
  5. 稳定性测试:在最优参数附近做敏感性分析。
  6. 实盘小试:用小资金上线跑一周,观察实际表现。

这套流程下来,虽然不能保证找到「最优解」,但至少能找到一个「靠谱解」。做市交易,稳定比什么都重要。

最后提醒一句:参数调优是锦上添花,不是雪中送炭。如果你的策略逻辑本身有问题,调再多参数也没用。先把策略逻辑打磨好,再来调参。

参数调优方法对比 网格搜索 穷举所有参数组合 优点:简单可靠 缺点:维度灾难 适用:参数少(≤3个) 计算量:高 随机搜索 随机采样参数空间 优点:效率高 缺点:结果不稳定 适用:参数中等(3-6个) 计算量:中 贝叶斯优化 用历史指导搜索 优点:收敛快 缺点:局部最优 适用:参数多(≥5个) 计算量:低 过拟合防范措施 ① 交叉验证:分段验证参数稳定性 ② 参数稳定性检查:邻域采样测试 ③ 样本外测试:留一段数据不参与调参 ④ 实盘小试:小资金验证后再放大 推荐流程:随机搜索粗筛 → 贝叶斯精调 → 过拟合验证

无相订单流研究社 微信Lucian808555