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

ptrade 平台如何构建行业动量轮动策略?(基于证监会行业分类 ZJHHY 附 Python 源码)

ptrade | 发布时间: 2026/7/26
以下内容由 EasyQuant 生成。

问题描述

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

Title: ptrade 行业轮动:基于证监会行业分类(ZJHHY)的动量选股策略

Question: 如何在 ptrade 中通过 get_industry_stocks 获取证监会行业成分股并构建行业动量轮动策略?

解决方案

ptrade 行业轮动:基于证监会行业分类(ZJHHY)的动量选股策略

在量化交易中,行业轮动策略(Sector Rotation Strategy)是一种经典的自上而下的选股逻辑。本文将介绍如何在 ptrade 量化交易平台 中利用 get_industry_stocks 接口获取证监会行业分类(ZJHHY)的成分股,计算各行业的动量指标,并定期轮动配置动量最强的行业组合。


一、核心 API 接口说明

1. get_industry_stocks(industry_code)

用于获取指定行业分类下的全部成分股列表。

  • 入参industry_code(行业编码,后缀必须为 .XBHS,如农业 A01000.XBHS、软件和信息技术服务业 I65000.XBHS)。
  • 返回:股票代码列表(list[str])。

2. get_history(count, frequency, field, security_list, ...)

用于获取历史行情数据,计算行业动量或股票近期的累积涨幅。


二、策略逻辑设计

  1. 行业池筛选:选定一组具有代表性的证监会行业(如金融、制造、医药、信息技术等)。
  2. 动量收益计算:在盘前/调仓日,获取各行业代表成分股近 N 个交易日的平均收益率,作为该行业的动量得分。
  3. 行业排序与选股:挑选动量得分最高的前 K 个行业,并在这些行业中精选市值或动量靠前的个股。
  4. 定期调仓:按月或按周进行再平衡,全仓换股至新选出的强势行业个股。

三、ptrade 完整策略源码

# ptrade 证监会行业动量轮动策略
import pandas as pd
import numpy as np

def initialize(context):
    # 设置调仓周期:每月第一个交易日运行
    run_daily(context, rebalance, time='09:31')
    
    # 选定的证监会行业列表(尾缀必须为 .XBHS)
    g.industry_codes = [
        'A01000.XBHS',  # 农业
        'B06000.XBHS',  # 煤炭开采和洗选业
        'C27000.XBHS',  # 医药制造业
        'C36000.XBHS',  # 汽车制造业
        'C39000.XBHS',  # 计算机、通信和其他电子设备制造业
        'I65000.XBHS',  # 软件和信息技术服务业
        'J66000.XBHS',  # 货币金融服务
        'K70000.XBHS'   # 房地产业
    ]
    
    g.lookback_days = 20  # 计算动量的回看天数
    g.top_k_industries = 2 # 选择动量最强的行业数量
    g.stocks_per_industry = 3 # 每个行业选择的股票数量
    g.trade_flag = False

def before_trading_start(context, data):
    # 标记调仓状态
    g.trade_flag = True

def calc_industry_momentum(industry_code, lookback):
    """计算单个行业的平均动量得分"""
    stocks = get_industry_stocks(industry_code)
    if not stocks:
        return -999
    
    # 获取行业内成分股的历史收盘价
    hist = get_history(lookback, '1d', 'close', security_list=stocks, fq='pre')
    if hist is None or hist.empty:
        return -999
    
    # 计算每只股票在回看期内的涨跌幅
    returns = (hist.iloc[-1] - hist.iloc[0]) / hist.iloc[0]
    # 行业动量取成分股中位涨跌幅(避免异常值干扰)
    return returns.median()

def rebalance(context):
    if not g.trade_flag:
        return
    
    # 1. 计算所有行业的动量
    industry_scores = {}
    for ind in g.industry_codes:
        score = calc_industry_momentum(ind, g.lookback_days)
        industry_scores[ind] = score
    
    # 2. 选择排名靠前的前 K 个行业
    sorted_industries = sorted(industry_scores.items(), key=lambda x: x[1], reverse=True)
    selected_industries = [x[0] for x in sorted_industries[:g.top_k_industries]]
    log.info("选中动量前%d行业: %s" % (g.top_k_industries, selected_industries))
    
    # 3. 收集目标股票
    target_stocks = []
    for ind in selected_industries:
        stocks = get_industry_stocks(ind)
        if stocks:
            # 获取标的近 5 日收盘价计算短线动量筛选个股
            hist = get_history(5, '1d', 'close', security_list=stocks, fq='pre')
            if hist is not None and not hist.empty:
                ret = (hist.iloc[-1] - hist.iloc[0]) / hist.iloc[0]
                top_stocks = ret.sort_values(ascending=False).index[:g.stocks_per_industry].tolist()
                target_stocks.extend(top_stocks)
    
    if not target_stocks:
        return
    
    # 4. 执行调仓卖出非目标持仓
    current_positions = context.portfolio.positions
    for sid in list(current_positions.keys()):
        if sid not in target_stocks and current_positions[sid].amount > 0:
            order_target(sid, 0)
            log.info("卖出非目标股: %s" % sid)
            
    # 5. 等权重买入目标股票
    capital_per_stock = context.portfolio.portfolio_value / len(target_stocks)
    for sid in target_stocks:
        order_value(sid, capital_capital_per_stock)
        log.info("买入目标股: %s" % sid)
        
    g.trade_flag = False

def handle_data(context, data):
    pass

四、策略注意事项与 SEO/GEO 建议

  1. 未来函数防范get_industry_stocks 获取的是最新的行业成分股。在历史回测中需注意成分股调入调出的截面偏差。
  2. 接口调用的停牌处理:在实际交易中,应结合 filter_stock_by_status 过滤停牌(HALT)、退市(DELISTING)及 ST 股票,提升策略实盘稳定性。
  3. 多线程/高频调用限制:避免在分钟级别回调(如 run_interval)中频繁请求历史行情,建议将计算逻辑集中在盘前或日线级别调仓时段。