精华帖子

AI策略网格搜索参数寻优

由bqtnziby创建,最终由bqtnziby 被浏览 1 用户

在量化策略当中,策略逻辑当然是排在第一位的。但是,在一个策略已经表现较好时,对参数进行调整,往往能收获更多的超额收益。本文以模板策略中的可视化AI策略为例,进行参数寻优过程,看能为绩效结果提高带来什么效果。

一、策略核心逻辑回顾

模板中的可视化AI策略的核心逻辑如下:

  1. 因子筛选层:从全市场股票中提取价值类(PE_TTM、PB、PS_TTM)、动量类(momentum_5、reversal_5)、波动类(volatility_5)、换手类(turn)等12个核心因子,同时通过st_status=0(剔除ST股)和list_days>260(上市满1年)进行基础过滤,确保股票池的有效性。
  2. 标签标注层:以“未来5日涨跌幅”为预测目标,通过m_lead(close,5)/m_lead(open,1)计算_future_return,并采用分位数裁剪(去极值)、等频分箱(c_cbins)生成排序标签,为模型训练提供监督信号。
  3. 模型排序层:使用StockRanker树模型(排序算法),以2021-2024年数据为训练集、2025年数据为预测集,输出股票的“预期收益排序分数”,分数越高代表未来收益潜力越强。
  4. 交易执行层:按排序分数选取前N只股票,每M个交易日进行一次调仓,采用等权仓位分配方式,通过BigTrader交易引擎完成买卖执行与绩效跟踪。

训练期选择的是2021年1月1日-2024年12月31日,在这里经过StockRanker之后,我们可以得到以下的绩效图:

经过多次参数的调整之后,我们发现绩效结果变化不大,说明策略大概率是有效的。那么,我们现在进行参数寻优,以求更好的绩效结果。

二、参数寻优

参数寻优并非盲目试错,而是“策略模块-可调参数-绩效目标”的精准匹配。以下从四个核心环节拆解体系化寻优逻辑:

1.参数空间选择

参数空间的设计需遵循“抓主要矛盾”原则,优先选择对策略绩效影响最直接的变量。结合上述策略框架,参数空间与策略模块的映射关系如下表所示:

策略模块 优化参数 参数含义与意义
模型排序 number_of_trees StockRanker树数量,控制模型拟合能力
模型排序 number_of_leaves 单棵树叶子节点数,平衡模型复杂度与泛化性
持仓管理 hold_count 单次持仓股票数量,影响分散度
交易调仓 rebalance_days 调仓周期(交易日),平衡交易成本与机会成本

上面四个参数即为我们此次参数寻优调整的对象,以下我们用持股数量和调仓周期两个参数进行演示:

2.参数注入

我们将需要调整的参数注入原策略逻辑中,我们使用run_backtest_with_params函数来连接参数和策略,其核心作用是将参数动态注入对应模块,驱动策略完整运行。

代码中用例如下:

2.1模型层面

将number_of_trees和number_of_leaves传入M.stockranker.v9,控制树模型的复杂度:

    m5 = M.stockranker.v9(
        train_data=m3.data,
        predict_data=m4.data,
        learning_algorithm="排序",
        number_of_leaves=params['number_of_leaves'],
        min_docs_per_leaf=1000,
        number_of_trees=params['number_of_trees'],
        learning_rate=0.1,
        max_bins=1023,
        feature_fraction=1,
        data_row_fraction=1,
        sort_by="date,instrument",
        plot_charts=False,
        ndcg_discount_base=1
    )

2.2持仓层面

hold_count决定排序后选取的股票数量,直接影响持仓分散度:

    m6 = M.score_to_position.v4(
        input_1=m5.predictions,
        score_field="score DESC",
        hold_count=params['hold_count'],
        position_expr="1 AS position",
        total_position=1,
        extract_data=True
    )

2.3交易层面

rebalance_days控制调仓频率,需与策略的因子有效性周期匹配:

    m7 = M.bigtrader.v47(
        data=m6.data,
        start_date="",
        end_date="",
        .................
        handle_order=m7_handle_order_bigquant_run,
        after_trading=m7_after_trading_bigquant_run,
        capital_base=1000000,
        frequency="daily",
        product_type="股票",
        rebalance_period_type="交易日",
        rebalance_period_days=str(params['rebalance_days']),#此处注入rebalance_day
        ............

3.网格搜索执行

网格搜索算法优势在于“穷举性”——确保在给定参数空间内不遗漏最优组合。parameter_optimization函数的核心执行逻辑如下:

  1. 组合生成:通过itertools.product对参数空间进行笛卡尔积运算,生成所有可能的参数组合。例如本文参数空间共生成1×1×3×2=6组组合。
  2. 结果缓存:加载历史结果文件(optimization_results.csv),跳过已测试的参数组合,避免重复计算,尤其适用于回测耗时较长的场景。
  3. 遍历测试:对每组参数调用run_backtest_with_params,实时将参数与绩效结果合并保存至CSV文件,防止程序中断导致数据丢失。
def parameter_optimization():
    """参数平原寻优主函数"""
    
    # 生成所有参数组合
    param_names = list(param_grid.keys())
    param_values = list(param_grid.values())
    all_combinations = list(product(*param_values))
    
    print(f"总共需要测试 {len(all_combinations)} 组参数组合")
    print("=" * 80)
    
    results = []
    results_file = 'optimization_results.csv'
    
    # 加载已有结果
    if os.path.exists(results_file):
        existing_results = pd.read_csv(results_file)
        results = existing_results.to_dict('records')
        print(f"加载了 {len(results)} 组已有结果")
    
    for i, combination in enumerate(all_combinations):
        params = dict(zip(param_names, combination))
        
        # 检查是否已测试过
        already_tested = any(
            all(result.get(k) == v for k, v in params.items())
            for result in results
        )
        ..........

4.如何衡量参数调整结果:多维度评判

单一绩效指标无法全面衡量策略优劣,所以我们构建“多维度加权评分体系”,结合策略目标设计评估逻辑:

    # 最终分析
    results_df = pd.DataFrame(results)
    print("\n" + "=" * 80)
    print("寻优完成!结果已保存到 optimization_results.csv")
    
    # 按夏普比率排序
    print("\n按夏普比率排序的 Top 5:")
    print("-" * 80)
    top_5 = results_df.nlargest(5, 'sharpe_ratio')
    print(top_5.to_string(index=False))
    
    # 综合评分
    results_df['score'] = (results_df['sharpe_ratio'] * 0.5 + 
                           results_df['annual_return'] * 0.3 - 
                           results_df['max_drawdown'].abs() * 0.2)
  • 单指标排序:先按夏普比率(风险调整后收益的核心指标)排序,筛选Top5组合,初步锁定风险收益比优异的参数。
  • 综合评分公式:考虑到策略的“稳健性优先”目标,设计如下评分公式: results_df['score'] = (results_df['sharpe_ratio'] * 0.5 + results_df['annual_return'] * 0.3 - results_df['max_drawdown'].abs() * 0.2) 权重逻辑:夏普比率(50%)> 年化收益率(30%)> 最大回撤(20%),既重视收益,也强调风险控制。
  • 最优参数确定:选取综合评分最高的参数组合,确保策略在收益、风险、风险调整效率之间达到最佳平衡。

5.调整参数后绩效展示

我们为了演示方便,本文只对其中两个参数进行了寻优,一共2*3=6个寻优网格:

param_grid = {
    'return_period_long': [90],
    'return_period_short': [30],
    'rank_threshold_long': [0.1],
    'rank_threshold_short': [0.1],
    'hold_count': [5, 10, 15],#进行寻优
    'rebalance_days': [5, 10],#进行寻优
    'number_of_trees': [20],
    'number_of_leaves': [30],
}

想要改变其它参数,可以在[ · , · ]中加入不同数值进行寻优,经过上述寻优之后绩效结果如下:

可以看到收益率提升50%左右,并且阿尔法和夏普比率都得到了提高。风险方面,虽然贝塔、收益波动率和最大回撤相应上涨,但是总体表现与原策略差异不大。

三、优化方向

1.优化算法升级:当参数数量增多或候选值范围扩大时,网格搜索的计算成本呈指数级增长,可改用贝叶斯优化(Bayesian Optimization)。其核心优势是基于历史测试结果构建概率模型,智能选择下一个最可能提升绩效的参数组合,大幅减少迭代次数。(贝叶斯优化在知识库精华帖子中有介绍文档)

2.过拟合防控:滚动窗口验证:采用“滚动训练-验证”框架,例如每半年用过去3年数据进行参数优化,再用接下来半年数据验证绩效。若参数在多个滚动窗口中均表现稳定,则说明其泛化能力强,不易受历史数据过拟合影响。(如何用WFA进行滚动参数寻优在知识库中有帖子介绍)


参数寻优代码:

https://bigquant.com/codesharev3/9037a6fd-05ed-47e6-93ad-70866e5787e9

\

标签

量化策略
{link}