4. 贝叶斯优化

在量化策略参数优化中,网格搜索与随机搜索虽然简单直观,但面对高维参数空间或每次评估成本高昂的回测场景时,效率往往不尽如人意。贝叶斯优化(Bayesian Optimization)通过构建参数与目标函数之间的概率代理模型,能够以更少的迭代次数找到更优的参数组合,尤其适合回测一次耗时数分钟甚至更长的复杂策略。

4.1 贝叶斯优化原理

贝叶斯优化的核心思想是:利用已有的评估结果,建立一个概率模型来近似未知的目标函数,然后通过一个采集函数(Acquisition Function)决定下一个最有潜力的采样点。整个过程可以看作“边探索边利用”的智能搜索过程。

核心流程: 初始化样本 → 构建高斯过程代理模型 → 优化采集函数选择下一个评估点 → 执行回测获得新结果 → 更新代理模型 → 重复直至收敛。

与网格搜索的暴力枚举不同,贝叶斯优化会记住每一次回测的结果,并利用这些信息推测参数空间中哪些区域可能藏着更优的解,从而避免在无效区域浪费计算资源。

贝叶斯优化迭代流程 贝叶斯优化迭代流程 初始化样本 高斯过程代理模型 优化采集函数 回测评估 更新代理模型 关键:每次迭代都利用历史信息,在“探索未知区域”与“利用已知最优区域”之间自动平衡 相比网格搜索,贝叶斯优化通常能节省 60%–80% 的回测次数

4.2 高斯过程(Gaussian Process, GP)

高斯过程是贝叶斯优化中最常用的代理模型。它不直接预测某个参数组合的目标值(如夏普比率),而是给出一个均值预测和不确定性估计(方差)。

概念 数学含义 在策略优化中的角色
均值函数 μ(x) 在参数 x 处的预测期望值 表示该参数组合预期能获得的绩效指标
协方差函数 k(x, x') 衡量两个参数点之间的相关性 决定代理模型的平滑程度与泛化能力
后验分布 融合先验与观测数据后的更新分布 提供每个参数点的预测均值与置信区间
直观理解: 高斯过程就像一张“弹性橡胶膜”,每次回测结果都会拉扯这张膜,使其在已评估点附近更贴合真实值,而在未评估区域则保持较大的不确定性(方差大)。

4.3 采集函数(Acquisition Function)

采集函数是贝叶斯优化的“决策大脑”,它利用高斯过程输出的均值和方差,为每个候选参数点计算一个“值得评估”的分数。常见的采集函数有三种:

采集函数 全称 核心公式(简化) 偏好倾向 适用场景
EI Expected Improvement EI(x) = E[max(f(x) - f*, 0)] 平衡探索与利用 通用场景,最常用
UCB Upper Confidence Bound UCB(x) = μ(x) + κ·σ(x) 偏向探索(κ大时) 需要快速覆盖未知区域
PI Probability of Improvement PI(x) = Φ((μ(x) - f*) / σ(x)) 偏向利用 已接近最优解,精细调优

其中 f* 为当前最优观测值,μ(x) 和 σ(x) 分别为高斯过程在 x 处的预测均值和标准差,κ 为探索-利用权衡参数,Φ 为标准正态累积分布函数。

实践建议: 在策略参数优化的早期阶段,推荐使用 UCB(κ=2.0~3.0)快速探索;中期切换为 EI 实现稳定收敛;后期若已接近局部最优,可使用 PI 进行精细搜索。实际应用中,EI 因其鲁棒性成为默认首选。
三种采集函数对比示意 三种采集函数对比示意 EI (Expected Improvement) E[max(f(x) - f*, 0)] 平衡探索与利用,通用首选 UCB (Upper Confidence Bound) μ(x) + κ·σ(x) 偏向探索,适合早期快速扫描 PI (Probability of Improvement) Φ((μ(x) - f*) / σ(x)) 偏向利用,适合精细调优 采集函数选择策略 • 早期阶段(前 20% 迭代):使用 UCB,κ=2.5,快速探索参数空间 • 中期阶段(20%–70% 迭代):切换为 EI,平衡探索与利用 • 后期阶段(最后 30% 迭代):使用 PI,在最优区域附近精细搜索

4.4 Python 实现示例

以下使用 scikit-optimize 库演示贝叶斯优化在双均线策略参数优化中的应用。该库封装了高斯过程与采集函数,使用简洁。

import numpy as np
import pandas as pd
from skopt import gp_minimize
from skopt.space import Integer
from skopt.utils import use_named_args

# 模拟回测函数:双均线策略,参数为短周期和长周期
def backtest_strategy(short_window, long_window):
    """
    模拟回测函数,返回夏普比率(实际使用时替换为真实回测引擎)
    """
    # 模拟:短周期与长周期差距适中时夏普较高
    spread = long_window - short_window
    sharpe = 0.5 + 0.3 * np.exp(-((spread - 30) ** 2) / 200)
    # 加入随机噪声模拟回测不确定性
    noise = np.random.normal(0, 0.02)
    return -(sharpe + noise)  # gp_minimize 默认最小化,取负值

# 定义参数搜索空间
param_space = [
    Integer(5, 50, name='short_window'),
    Integer(20, 200, name='long_window')
]

# 使用命名参数包装目标函数
@use_named_args(param_space)
def objective(short_window, long_window):
    return backtest_strategy(short_window, long_window)

# 执行贝叶斯优化
result = gp_minimize(
    func=objective,
    dimensions=param_space,
    n_calls=50,           # 总评估次数
    n_initial_points=10,  # 初始随机采样点数
    acq_func='EI',        # 采集函数:Expected Improvement
    random_state=42
)

# 输出最优结果
print(f"最优参数:short_window={result.x[0]}, long_window={result.x[1]}")
print(f"最优夏普比率(取反后):{result.fun:.4f}")
print(f"实际最优夏普比率:{-result.fun:.4f}")

# 查看每次迭代的收敛过程
print(f"迭代次数:{len(result.func_vals)}")
print(f"最终最优值:{-result.fun:.4f}")
关键参数说明:
• n_calls:总评估次数,建议设置为参数维度的 10–20 倍。
• n_initial_points:初始随机采样点数,用于构建初始高斯过程模型,建议为总次数的 20%。
• acq_func:采集函数类型,可选 'EI'、'UCB'、'PI'。
• random_state:随机种子,保证结果可复现。

4.5 贝叶斯优化 vs 传统方法对比

对比维度 网格搜索 随机搜索 贝叶斯优化
搜索策略 穷举所有组合 随机采样 基于历史结果智能选择
所需评估次数 极高(组合爆炸) 中等 低(通常 30–100 次)
对高维空间适应性 差 一般 较好(≤10 维)
是否利用历史信息 否 否 是(构建代理模型)
不确定性量化 无 无 有(高斯过程方差)
实现复杂度 低 低 中(需调采集函数参数)
适用场景判断: 如果一次回测耗时超过 10 秒,且参数维度在 3–10 之间,贝叶斯优化是性价比最高的选择。对于超低维度(1–2 维)或超低耗时(毫秒级),网格搜索仍然可用。

4.6 实践注意事项

  • 参数空间边界: 确保参数上下界合理,避免高斯过程在边界外进行无意义的外推。
  • 目标函数噪声: 回测结果本身存在随机性(如市场数据切片差异),高斯过程可以建模噪声,但建议设置 noise='gaussian' 或提供噪声水平估计。
  • 采集函数调参: UCB 的 κ 参数控制探索强度,κ 越大越偏向探索;EI 无需额外参数,鲁棒性更好。
  • 早停机制: 当连续多次迭代的最优值提升幅度小于阈值(如 0.1%)时,可以提前终止优化,节省计算资源。
  • 多峰问题: 策略参数空间通常存在多个局部最优,建议多次运行贝叶斯优化(不同随机种子)并对比结果。