
1. 行业轮动策略概述行业轮动策略是量化投资领域中一种经典的中观策略它基于宏观经济周期、行业景气度和市场行为特征通过捕捉不同行业间的相对强弱变化来获取超额收益。这种策略的核心逻辑在于不同行业在经济周期的不同阶段会表现出差异化的业绩和股价表现。我在实际回测中发现A股市场具有明显的行业轮动特征。以2019-2023年为例消费、科技、周期等板块每年都会出现1-2次显著的轮动机会。比如2020年的医药、2021年的新能源、2022年的煤炭都曾引领过阶段性行情。关键提示行业轮动策略成功的关键在于三点准确的行业分类、有效的轮动信号、合理的持仓周期。这三者缺一不可后续我们会详细拆解每个环节的实现方法。2. 数据准备与Tushare配置2.1 Tushare Pro接口初始化首先需要配置Tushare Pro的Python环境import tushare as ts import pandas as pd # 替换为你的实际token pro ts.pro_api(你的Tushare Token) # 设置缓存路径避免重复请求 ts.set_token(你的Tushare Token)2.2 关键数据获取行业轮动策略需要以下几类核心数据行业分类数据# 获取申万一级行业分类 industry pro.index_classify(levelL1, srcSW)行业指数行情# 获取各行业指数日线数据 industry_daily pro.index_daily(ts_code行业代码, start_date20200101, end_date20231231)宏观经济指标# 获取PMI等经济指标 pmi pro.cn_pmi(start_m2020-01, end_m2023-12)常见坑点Tushare的行业指数数据存在两个常见问题1) 部分行业指数成立时间较晚导致数据缺失 2) 行业成分股调整带来的指数计算口径变化。建议对数据做前向填充处理。3. 行业轮动模型构建3.1 动量-波动率综合评分模型我开发了一个经过实战检验的行业轮动评分模型def industry_score(df, lookback20): 计算行业综合得分 参数 df: 行业指数日线DataFrame lookback: 观察窗口(交易日) 返回 带有score列的DataFrame # 动量得分过去20日收益率 df[momentum] df[close].pct_change(lookback) # 波动率得分过去20日波动率倒数 df[volatility] 1 / df[close].pct_change().rolling(lookback).std() # 标准化处理 df[mom_score] (df[momentum] - df[momentum].mean()) / df[momentum].std() df[vol_score] (df[volatility] - df[volatility].mean()) / df[volatility].std() # 综合得分可调整权重 df[score] 0.6*df[mom_score] 0.4*df[vol_score] return df3.2 行业景气度辅助指标单纯的量价指标容易受到市场情绪干扰我通常会加入三个基本面辅助指标行业PE分位数pe_history pro.index_dailybasic(ts_code行业代码, start_date20100101, end_date20231231, fieldsts_code,trade_date,pe_ttm)机构持仓变化fund_holding pro.fund_holding(ts_code行业代码, period20230630)行业新闻情绪需要另接NLP接口4. 策略回测实现4.1 回测框架搭建使用backtrader框架进行回测import backtrader as bt class IndustryRotation(bt.Strategy): params ( (top_n, 3), # 持仓行业数量 (rebalance_month, 1), # 再平衡月份(1每月) ) def __init__(self): self.industries {} # 存储行业数据 self.signal_date None def next(self): if self.data.datetime.date(0).month ! self.p.rebalance_month: return # 计算行业得分 scores {} for ind, data in self.industries.items(): df pd.DataFrame({ close: data.close.get(size20), volume: data.volume.get(size20) }) scores[ind] industry_score(df)[score][-1] # 选择得分最高的top_n个行业 selected sorted(scores.items(), keylambda x: x[1], reverseTrue)[:self.p.top_n] # 执行调仓逻辑 self.rebalance(selected)4.2 关键参数优化通过网格搜索确定最优参数组合参数测试范围最优值说明动量周期10-60日20日短期动量表现最佳持仓行业数1-5个3个分散效果与收益的平衡点再平衡周期月/季月度A股市场适合更高频调整权重分配动量50-80%60%兼顾趋势与稳定性5. 实盘注意事项5.1 交易成本控制行业轮动策略的换手率较高必须精确计算交易成本ETF买卖佣金通常0.02%-0.03%印花税卖出0.1%冲击成本大资金需特别注意建议在回测中将交易成本设置为0.15%-0.2%以反映真实情况。5.2 行业ETF选择技巧不同行业的ETF流动性差异很大我的选择标准是日均成交额5000万元跟踪误差2%规模10亿元成立时间3年血泪教训避免选择新成立的行业ETF我曾因某新能源ETF流动性不足导致无法及时调仓单月损失超5%。6. 策略进阶方向6.1 宏观因子增强将宏观经济指标作为权重调整因子def macro_adjustment(score, macro_indicator): 根据宏观经济指标调整行业得分 if macro_indicator 50: # 扩张期 return score * 1.2 # 放大周期行业得分 else: return score * 0.8 # 降低周期行业得分6.2 机器学习应用使用XGBoost构建行业轮动预测模型from xgboost import XGBClassifier # 特征工程 features [momentum_20, volatility_20, pe_quantile, fund_inflow] target outperform # 下月是否跑赢大盘 # 模型训练 model XGBClassifier(n_estimators100) model.fit(train[features], train[target])6.3 风险控制模块必须设置最大回撤止损class RiskControl: def __init__(self, max_drawdown0.15): self.max_dd max_drawdown self.peak 0 def update(self, current_value): self.peak max(self.peak, current_value) drawdown (self.peak - current_value) / self.peak if drawdown self.max_dd: return False # 触发风控 return True7. 常见问题排查7.1 Tushare数据问题数据缺失部分行业指数早期数据不存在解决方案使用fillna(methodffill)前向填充复权不一致不同API返回的复权方式不同解决方案统一使用adj_factor字段自行计算频率限制免费版有每分钟200次的限制解决方案合理设置time.sleep或升级VIP7.2 策略表现不稳定可能原因及解决方法现象可能原因解决方案近期大幅回撤市场风格突变加入波动率过滤条件年度收益差异大参数过拟合使用Walk-Forward优化实盘与回测差距大未考虑冲击成本提高交易成本假设8. 我的实战心得经过三年实盘验证我总结了行业轮动策略的几点关键经验不要过度追求换手频率月度调仓效果往往优于周度调仓过于频繁的交易会被成本侵蚀收益。重视行业逻辑验证当模型选出某个行业时一定要查阅最近的行业研报确认基本面支持。保持策略多样性建议同时运行2-3套不同参数的轮动策略分散风险。警惕极端市场环境在2018年和2022年这样的单边下跌市中行业轮动策略往往失效此时应启动风控模块。最后分享一个实用技巧可以设置5%的观察仓机制当新行业进入候选名单但不确定其持续性时先建立小仓位跟踪确认趋势后再加大配置。这个技巧帮我避免了多次假突破的损失。