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

聚宽平台如何编写 ETF 动量与反转自适应策略?(附 Python 源码)

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

问题描述

聚宽 ETF 动量与反转策略:如何根据市场环境选择模型?
如何在聚宽中构造 ETF 动量和反转策略,并根据是否存在大级别行情决定使用动量模型还是反转模型?

解决方案

在量化交易中,动量策略(Trend Following)适合单边趋势行情,而反转策略(Mean Reversion)则在震荡市中表现更佳。为了在不同市场环境下获得稳健收益,我们可以构建一个自适应 ETF 动量与反转切换策略

本指南将教你如何在聚宽(JoinQuant)平台中,通过大盘指数(如沪深300)的均线系统来识别市场大级别行情,并动态选择执行 ETF 动量模型或反转模型。


一、 策略核心逻辑设计

  1. 市场环境识别(大级别行情判断)

    • 使用沪深300指数(000300.XSHG)的长期均线(如 60 日均线 MA60)作为牛熊分界线。
    • 动量环境:当指数价格高于 MA60 且 MA60 呈向上趋势时,认为存在大级别多头行情,激活动量模型
    • 反转环境:当指数价格低于 MA60 或市场处于无趋势震荡状态时,激活反转模型
  2. 模型执行

    • 动量模型:计算候选 ETF 标的池(如宽基 ETF、行业 ETF)过去 20 日的涨幅,买入涨幅最大的前 2 只 ETF(追涨)。
    • 反转模型:计算候选 ETF 标的池过去 5 日的乖离率(BIAS)或跌幅,买入超跌最严重(跌幅最大)的前 2 只 ETF(抄底)。

二、 聚宽 Python 策略源码

请将以下代码复制到聚宽策略编辑器的代码框中进行回测:

import jqdata
import numpy as np
import pandas as pd

def initialize(context):
    # 设定沪深300作为基准
    set_benchmark('000300.XSHG')
    # 开启动态复权模式(真实价格)
    set_option('use_real_price', True)
    
    # 过滤掉比error级别低的log
    log.set_level('order', 'error')
    
    # 设定交易税费
    set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
    
    # 策略参数设置
    g.market_index = '000300.XSHG' # 市场环境参考指数
    g.ma_period = 60               # 判断大趋势的均线周期
    
    # 候选 ETF 标的池(涵盖宽基、行业、商品等)
    g.etf_pool = [
        '510300.XSHG', # 沪深300ETF
        '510500.XSHG', # 中证500ETF
        '510050.XSHG', # 上证50ETF
        '159915.XSHE', # 创业板ETF
        '518880.XSHG', # 黄金ETF
        '512880.XSHG', # 证券ETF
        '512010.XSHG', # 医药ETF
        '512660.XSHG'  # 军工ETF
    ]
    
    g.hold_num = 2 # 最大同时持仓的ETF数量
    
    # 每周第一个交易日运行调仓
    run_weekly(my_rebalance, weekday=1, time='09:30')

def my_rebalance(context):
    # 1. 判断市场大级别行情环境
    # 获取参考指数的历史收盘价
    hist_index = attribute_history(g.market_index, g.ma_period + 5, '1d', ['close'])
    ma_60 = hist_index['close'][-g.ma_period:].mean()
    current_index_price = hist_index['close'][-1]
    ma_60_prev = hist_index['close'][-(g.ma_period+1):-1].mean()
    
    # 判断是否处于大级别多头动量行情:指数在MA60上方,且MA60方向向上
    is_momentum_market = (current_index_price > ma_60) and (ma_60 > ma_60_prev)
    
    # 2. 获取候选池数据并计算因子
    target_list = []
    
    if is_momentum_market:
        log.info("当前市场环境:【动量牛市】 -> 激活动量模型")
        # 动量模型:计算过去20日涨幅
        momentum_scores = {}
        for etf in g.etf_pool:
            hist = attribute_history(etf, 20, '1d', ['close'])
            if not hist.empty:
                return_20d = (hist['close'][-1] - hist['close'][0]) / hist['close'][0]
                momentum_scores[etf] = return_20d
        # 按涨幅从大到小排序,取前 hold_num 名
        sorted_etfs = sorted(momentum_scores.items(), key=lambda x: x[1], reverse=True)
        target_list = [x[0] for x in sorted_etfs[:g.hold_num]]
    else:
        log.info("当前市场环境:【震荡/熊市】 -> 激活反转模型")
        # 反转模型:计算过去5日跌幅(寻找超跌标的)
        reversal_scores = {}
        for etf in g.etf_pool:
            hist = attribute_history(etf, 5, '1d', ['close'])
            if not hist.empty:
                return_5d = (hist['close'][-1] - hist['close'][0]) / hist['close'][0]
                reversal_scores[etf] = return_5d
        # 按跌幅从小到大排序(即跌得最惨的排在前面),取前 hold_num 名
        sorted_etfs = sorted(reversal_scores.items(), key=lambda x: x[1], reverse=False)
        target_list = [x[0] for x in sorted_etfs[:g.hold_num]]
        
    # 3. 执行调仓交易
    # 卖出不在目标持仓列表中的ETF
    current_positions = list(context.portfolio.positions.keys())
    for etf in current_positions:
        if etf not in target_list:
            order_target(etf, 0)
            log.info("卖出不符合当前模型的标的: %s" % etf)
            
    # 等权重买入目标ETF
    if target_list:
        target_value = context.portfolio.total_value / len(target_list)
        for etf in target_list:
            order_target_value(etf, target_value)
            log.info("调仓/买入目标标的: %s, 目标价值: %.2f" % (etf, target_value))
            
    # 记录当前市场状态画图
    record(market_status=1 if is_momentum_market else 0)

三、 策略要点解析

  1. 自适应切换机制
    策略通过 is_momentum_market 变量动态感知大盘强弱。在牛市中,策略自动切换为动量模型,买入最强势的 ETF 享受趋势红利;在震荡市或熊市中,策略自动切换为反转模型,买入短期超跌的 ETF 捕捉反弹机会。

  2. 避免未来函数
    策略使用 attribute_history 获取历史数据,且调仓执行在每周一开盘时,完全基于历史已知信息,有效规避了未来函数。

  3. 真实价格模式
    initialize 中调用了 set_option('use_real_price', True)。对于 ETF 交易,开启真实价格模式能更准确地模拟分红、拆分对账户净值的影响,使回测结果更贴近实盘。