3、参数空间探索:网格搜索法、随机搜索法、贝叶斯优化入门

做市策略的参数优化,说白了就是在一堆数字里找到最赚钱的那组组合。我见过不少新手上来就凭感觉调参数,结果回测曲线好看,实盘一跑就崩。嗯,这里要明确一点:参数空间探索不是瞎蒙,是有方法论支撑的。

我个人习惯把参数优化分成三个层次。第一层是暴力枚举,第二层是随机抽样,第三层是智能搜索。今天咱们就把这三层都过一遍,看看它们各自适合什么场景。

核心观点:没有最好的搜索方法,只有最合适的。参数少用网格,参数多用随机,计算资源充裕用贝叶斯。

3.1 网格搜索法:最笨但最可靠

网格搜索,顾名思义,就是把参数空间切成一张网。每个交叉点都跑一次回测。比如你有两个参数:订单间隔(5秒到30秒)和挂单深度(1档到5档),那就形成一个二维网格。

我在项目中遇到过这样的情况:一个同事用网格搜索优化了三个参数,跑了整整两天。结果发现最优解就在网格边界上。为什么?因为网格太粗了,错过了中间区域。所以网格搜索的关键在于步长选择。

# 网格搜索示例代码
import numpy as np

# 定义参数网格
interval_grid = np.arange(5, 31, 5)  # 5秒步长
depth_grid = np.arange(1, 6, 1)      # 1档步长

best_sharpe = -np.inf
best_params = None

for interval in interval_grid:
    for depth in depth_grid:
        # 这里调用回测函数
        sharpe = run_backtest(interval, depth)
        if sharpe > best_sharpe:
            best_sharpe = sharpe
            best_params = (interval, depth)

print(f"最优参数: 间隔={best_params[0]}秒, 深度={best_params[1]}档")
print(f"最优夏普: {best_sharpe:.2f}")

我的经验:网格搜索适合参数少于4个的场景。超过4个,网格数量会爆炸式增长。比如每个参数取10个值,4个参数就是10^4=10000次回测。你想想看,这得跑多久?

3.2 随机搜索法:用概率换效率

随机搜索的思路很简单:在参数空间里随机撒点。每个点代表一组参数组合,跑回测,记录结果。重复N次,取最优。

你可能会问:随机搜索能比网格搜索更好吗?其实,从数学上看,随机搜索在高维空间里效率更高。为什么?因为网格搜索的采样点均匀分布,但最优解往往集中在某个区域。随机搜索虽然看起来乱,但能在更少的采样次数里覆盖更多有价值的区域。

我曾经用随机搜索优化一个5参数的做市策略。网格搜索需要10^5=10万次回测,而随机搜索只用了2000次就找到了接近最优的解。效率提升了50倍。

# 随机搜索示例代码
import random

def random_search(n_iterations=2000):
    best_sharpe = -np.inf
    best_params = None
    
    for i in range(n_iterations):
        # 在合理范围内随机采样
        interval = random.uniform(5, 30)
        depth = random.randint(1, 5)
        spread_mult = random.uniform(0.5, 2.0)
        order_size = random.randint(1, 10)
        cancel_time = random.uniform(1, 10)
        
        sharpe = run_backtest(interval, depth, spread_mult, order_size, cancel_time)
        
        if sharpe > best_sharpe:
            best_sharpe = sharpe
            best_params = (interval, depth, spread_mult, order_size, cancel_time)
    
    return best_params, best_sharpe

避坑指南:我曾经犯过一个错误——随机搜索的采样范围设得太宽。结果大部分采样点都在无效区域,白白浪费了计算资源。建议先用少量采样确定有效区域,再缩小范围精细搜索。

3.3 贝叶斯优化入门

贝叶斯优化,听起来高大上,其实核心思想很简单:用历史采样结果来指导下一步采样。它不像网格搜索那样盲目,也不像随机搜索那样完全随机。它有个「记忆」,知道哪些区域可能更好。

贝叶斯优化的两个核心组件:

  • 概率代理模型:通常用高斯过程(GP)来拟合参数与目标函数的关系。说白了,就是根据已有的采样点,预测整个参数空间的「地形图」。
  • 采集函数:决定下一步去哪里采样。常用的有期望改进(EI)、置信上界(UCB)等。它会平衡「探索」(去未知区域)和「利用」(去已知好区域)。

我个人习惯用贝叶斯优化来处理计算成本高的场景。比如每次回测需要10分钟,那网格搜索和随机搜索都不现实。贝叶斯优化通常只需要几十次迭代就能找到不错的解。

# 贝叶斯优化示例(使用scikit-optimize库)
from skopt import gp_minimize
from skopt.space import Real, Integer

# 定义参数空间
space = [
    Real(5, 30, name='interval'),
    Integer(1, 5, name='depth'),
    Real(0.5, 2.0, name='spread_mult'),
    Integer(1, 10, name='order_size'),
    Real(1, 10, name='cancel_time')
]

# 定义目标函数(最大化夏普比率)
def objective(params):
    interval, depth, spread_mult, order_size, cancel_time = params
    sharpe = run_backtest(interval, depth, spread_mult, order_size, cancel_time)
    return -sharpe  # gp_minimize默认最小化,所以取负

# 执行贝叶斯优化
result = gp_minimize(
    objective, 
    space, 
    n_calls=50,  # 迭代次数
    random_state=42
)

print(f"最优参数: {result.x}")
print(f"最优夏普: {-result.fun:.2f}")

我的建议:贝叶斯优化不是万能的。如果参数空间非常崎岖(有很多局部最优),高斯过程的拟合效果会变差。这时候可以试试随机森林作为代理模型,或者增加初始采样点。

3.4 三种方法的对比

方法 适用参数数量 计算效率 找到全局最优的概率 实现难度
网格搜索 1-3个 低(指数增长) 高(步长足够细时)
随机搜索 3-10个 中(线性增长) 中(依赖采样次数)
贝叶斯优化 5-20个 高(智能采样) 高(理论保证)

嗯,这里要注意:表格只是参考。实际项目中,我经常混合使用。比如先用随机搜索粗筛,再用贝叶斯优化精调。或者先用网格搜索确定大致范围,再用贝叶斯优化深入挖掘。

3.5 实战中的选择策略

说了这么多理论,到底怎么选?我总结了一个简单的决策流程:

  1. 参数少于4个,计算资源充足:用网格搜索。步长取细一点,确保不遗漏最优解。
  2. 参数4-8个,计算资源有限:用随机搜索。采样次数设为参数数量的100-200倍。
  3. 参数多于8个,或每次回测很耗时:用贝叶斯优化。迭代次数设为参数数量的10-20倍。
  4. 不确定选哪个:先跑100次随机搜索,看看目标函数的分布。如果分布集中,说明参数空间比较平滑,贝叶斯优化效果会好。如果分布分散,说明空间崎岖,可能需要更多采样。

核心提醒:参数优化不是一劳永逸的事。市场在变,最优参数也在变。我建议每周或每月重新优化一次参数,或者设置一个监控机制,当策略表现下降时自动触发重新优化。

最后说一句:别迷信任何一种方法。工具是死的,人是活的。理解每种方法的原理和适用场景,才能在实战中做出正确的选择。

参数空间探索方法选择流程图 参数优化需求 参数数量? ≤3个 网格搜索 步长取细 4-8个 随机搜索 100-200倍采样 ≥8个 贝叶斯优化 10-20倍迭代 可混合使用 得到最优参数 虚线表示可选的混合策略 实际项目中建议根据计算资源和策略复杂度灵活选择