3、网格搜索法:全网格搜索原理、实现步骤、优缺点分析、适用场景

说到参数优化,网格搜索法可能是最直观、最容易理解的方法了。我刚开始做量化的时候,第一个接触的优化方法就是它。说白了,就是把所有可能的参数组合都试一遍,然后挑出最好的那个。

你可能会问:这么简单粗暴的方法,真的有用吗?嗯,有用,但得看场景。让我慢慢给你拆解。

3.1 全网格搜索的原理

网格搜索的核心思想其实就四个字:穷举遍历

假设你的策略有两个参数:n1(短期均线周期)和 n2(长期均线周期)。你想知道 n1 在 5 到 20 之间、n2 在 20 到 60 之间哪个组合最好。网格搜索会怎么做?它会生成一个二维网格:

  • n1 取 5, 6, 7, ..., 20(共 16 个值)
  • n2 取 20, 25, 30, ..., 60(共 9 个值)
  • 总共 16 × 9 = 144 个组合

然后,对每个组合跑一遍回测,记录下绩效指标。最后,从这 144 个结果里挑出最优的那个。

我画了一张图,帮你理解这个网格结构:

全网格搜索示意图 ★最优 参数 n1(短期周期) 参数 n2(长期周期) 参数组合 最优解

每个红点代表一个参数组合,橙色圈出来的就是最优解。你看,思路就是这么简单。

3.2 实现步骤

网格搜索的实现步骤,我一般分成五步走:

  1. 定义参数空间:确定每个参数的取值范围和步长
  2. 生成参数网格:用笛卡尔积生成所有组合
  3. 遍历评估:对每个组合跑回测,记录绩效
  4. 结果排序:按目标指标(如夏普比率)排序
  5. 选择最优:挑出排名靠前的组合

给你看一段 Python 代码,这是我常用的实现方式:

import itertools
import numpy as np
import pandas as pd

def grid_search(strategy_func, param_grid, data, metric='sharpe'):
    """
    全网格搜索实现
    :param strategy_func: 策略函数,接收参数和data,返回绩效指标
    :param param_grid: 参数字典,如 {'n1': range(5, 21, 1), 'n2': range(20, 61, 5)}
    :param data: 历史数据
    :param metric: 优化目标指标
    """
    results = []
    
    # 生成所有参数组合
    keys = param_grid.keys()
    values = param_grid.values()
    
    total = 1
    for v in values:
        total *= len(v)
    print(f'总组合数: {total}')
    
    # 遍历所有组合
    for combo in itertools.product(*values):
        params = dict(zip(keys, combo))
        
        # 跑回测
        perf = strategy_func(params, data)
        
        results.append({
            **params,
            metric: perf[metric]
        })
    
    # 转成DataFrame并排序
    df = pd.DataFrame(results)
    df = df.sort_values(metric, ascending=False)
    
    return df

# 使用示例
param_grid = {
    'fast_ma': range(5, 21, 1),
    'slow_ma': range(20, 61, 5)
}

# result = grid_search(my_strategy, param_grid, hist_data)
# print(result.head(10))
💡 我的小技巧: 实际项目中,我习惯先做粗粒度搜索(大步长),找到大致区域后,再在最优区域附近做细粒度搜索。这样能大幅减少计算量。

3.3 优缺点分析

网格搜索的优点很明显,但缺点也同样致命。我直接给你列个表,一目了然:

维度 优点 缺点
完整性 覆盖所有组合,不会遗漏 组合数随参数数量指数增长
可解释性 结果直观,容易理解 无法处理参数间的非线性关系
实现难度 代码简单,容易上手 计算资源消耗大
并行化 天然可并行,加速容易 对连续参数空间有离散误差
过拟合风险 容易在历史数据上过拟合

我来说说几个关键点:

维度灾难——这是网格搜索最大的敌人。假设你有 5 个参数,每个参数取 10 个值,那就是 10^5 = 10 万次回测。如果每次回测需要 1 秒,那就是 27 个小时。你想想看,这还只是 5 个参数。

离散化误差——网格搜索只能检查你定义的离散点。最优解可能恰好落在两个网格点之间。我曾经遇到过这种情况:步长设为 5 时找不到好结果,改成步长 3 反而找到了。嗯,这里要注意。

⚠️ 避坑指南: 我曾经在优化一个多因子策略时,用了 8 个参数做全网格搜索。结果跑了整整 3 天,最后发现最优组合在样本外表现极差。后来我才意识到,参数越多,过拟合风险越大。网格搜索不是万能的,别贪心。

3.4 适用场景

网格搜索不是银弹,它有自己的用武之地。我个人总结了几类适合的场景:

  • 参数数量少(≤3个):这时候计算量可控,全网格搜索是最稳妥的选择
  • 参数空间较小:比如每个参数只有 5-10 个候选值
  • 需要可解释性:当你需要向团队或客户解释优化过程时,网格搜索的直观性是个大优势
  • 作为基准方法:在尝试更复杂的优化方法前,先用网格搜索跑一遍,看看最优解的大致位置
  • 参数是离散值:比如选择哪几根均线、使用哪个技术指标,这些天然就是离散的

不适合的场景也很明显:

  • 参数超过 4 个——计算量会爆炸
  • 参数是连续值——离散化会丢失精度
  • 需要快速迭代——网格搜索太慢了

我的建议: 网格搜索最适合做「初步探索」。先用大步长、少参数跑一遍,找到大致的「好区域」,然后再用更精细的方法(比如贝叶斯优化)去深入挖掘。别一上来就搞全网格,那是给自己找麻烦。

说白了,网格搜索就像用筛子筛沙子。筛子孔太大,会漏掉好东西;孔太小,又筛得太慢。关键是要找到那个平衡点。

好了,网格搜索就讲到这里。下一节我们聊聊随机搜索,它能在一定程度上解决网格搜索的「维度灾难」问题。到时候我会告诉你,为什么有时候「随机」反而比「全量」更聪明。


公众号:蓝海资料掘金营,微信deep3321