🚀 AI 一键生成 joinquant 策略代码
立即体验

如何在 joinquant 中实现 MinTrackingError 追踪误差最小化策略?

joinquant | 发布时间: 2026/8/1
以下内容由 EasyQuant 生成。

问题描述

请根据以下 SEO 主题生成完整页面内容:

Title: joinquant 组合优化:MinTrackingError 追踪误差最小化策略

Question: 请问如何在 joinquant 中使用组合优化器构建追踪误差最小化策略?

解决方案

在 JoinQuant 中构建 MinTrackingError 追踪误差最小化策略

在量化投资中,追踪误差最小化(MinTrackingError) 是一种常见的组合优化目标,主要用于指数增强或基准复制策略。其核心目标是在满足一定约束条件(如权重限制、行业限制等)的前提下,使投资组合收益率与基准指数收益率之间的方差(即追踪误差)达到最小。

在聚宽(JoinQuant)平台中,我们可以通过内置的 jqlib.optimizer 优化器模块快速实现该策略。


1. 核心 API 介绍

优化器函数:portfolio_optimizer

from jqlib.optimizer import portfolio_optimizer, MinTrackingError, WeightConstraint, Bound

目标函数:MinTrackingError

  • 用法MinTrackingError(benchmark, count=250)
  • 参数
    • benchmark:基准标的代码,如 '000300.XSHG'(沪深300)。
    • count:回溯的历史收益率天数,默认为 250 天。

2. 完整策略代码示例

以下策略在每月第一个交易日运行,选出沪深300成分股的一部分标的,使用 MinTrackingError 优化器计算最优配置权重,并完成调仓。

import pandas as pd
from jqdata import *
from jqlib.optimizer import portfolio_optimizer, MinTrackingError, WeightConstraint, Bound

def initialize(context):
    # 设定沪深300作为基准
    set_benchmark('000300.XSHG')
    # 开启动态复权模式(真实价格)
    set_option('use_real_price', True)
    
    # 交易设置:买卖佣金万三,印花税千一
    set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
    
    # 定时按月调仓
    run_monthly(market_open, monthday=1, time='09:30', reference_security='000300.XSHG')

def market_open(context):
    # 1. 选取成分股作为候选股票池(例如:沪深300前30只股票)
    stocks = get_index_stocks('000300.XSHG')[:30]
    
    # 2. 调用组合优化器
    # 目标:相对于沪深300最小化追踪误差
    # 约束:组合总权重在 90% 到 100% 之间,单只股票权重上限为 10%
    optimized_weight = portfolio_optimizer(
        date=context.previous_date,
        securities=stocks,
        target=MinTrackingError(benchmark='000300.XSHG', count=250),
        constraints=[WeightConstraint(low=0.9, high=1.0)],
        bounds=[Bound(low=0.0, high=0.1)],
        return_none_if_fail=True
    )
    
    # 3. 优化成功后进行调仓
    if optimized_weight is not None:
        # 卖出不在优化结果中的持仓
        for stock in context.portfolio.positions.keys():
            if stock not in optimized_weight or optimized_weight[stock] == 0:
                order_target_value(stock, 0)
                
        # 按优化分配的权重进行下单
        total_value = context.portfolio.total_value
        for stock, weight in optimized_weight.items():
            target_value = total_value * weight
            order_target_value(stock, target_value)
        log.info("优化调仓完成!")
    else:
        log.warn("组合优化失败,保持当前持仓。")

3. 注意事项

  1. 数据动态复权:建议在 initialize 中设置 set_option('use_real_price', True),以避免前复权导致的未来函数问题。
  2. 计算历史区间count 参数控制计算协方差矩阵和追踪误差的数据窗口,通常建议设定为 250 个交易日(约 1 年)。
  3. 求解失败处理:当约束条件过于苛刻(例如限制单股上限太低而股票数量不足)时,优化器可能返回 None。建议设置 return_none_if_fail=True 并添加兜底的控制逻辑。