免责声明:本文基于个人学习经验整理,仅供技术交流参考,不构成投资建议。
一、前言
从事期货量化交易二十年,我最大的感悟是:单一因子的策略越来越难赚钱了。
多因子策略通过组合多个因子,可以提高策略的稳健性。今天这篇文章,我来分享一下期货多因子策略的开发入门。
二、什么是多因子策略?
多因子策略的核心思想:
- 因子:能够预测未来收益的特征(如动量、波动率等)
- 多因子:组合多个因子,取长补短
- 因子组合:通过加权等方式综合多个因子
三、常用期货因子
3.1 动量因子
defcalc_momentum(df,period=20):"""动量因子:过去N日收益率"""df['momentum']=df['close'].pct_change(period)returndf['momentum']3.2 波动率因子
importnumpyasnpdefcalc_volatility(df,period=20):"""波动率因子:过去N日收益率标准差"""returns=df['close'].pct_change()df['volatility']=returns.rolling(period).std()returndf['volatility']3.3 均线偏离因子
defcalc_ma_deviation(df,period=20):"""均线偏离因子:价格相对均线的偏离度"""ma=df['close'].rolling(period).mean()df['ma_deviation']=(df['close']-ma)/mareturndf['ma_deviation']3.4 成交量因子
defcalc_volume_ratio(df,period=20):"""成交量比率因子:当前成交量/平均成交量"""avg_volume=df['volume'].rolling(period).mean()df['volume_ratio']=df['volume']/avg_volumereturndf['volume_ratio']3.5 RSI因子
defcalc_rsi(df,period=14):"""RSI因子"""delta=df['close'].diff()gain=delta.where(delta>0,0)loss=-delta.where(delta<0,0)avg_gain=gain.rolling(period).mean()avg_loss=loss.rolling(period).mean()rs=avg_gain/avg_loss df['rsi']=100-(100/(1+rs))returndf['rsi']四、因子计算完整示例
fromtqsdkimportTqApi,TqAuthimportpandasaspdimportnumpyasnp api=TqApi(auth=TqAuth("账户","密码"))symbol="SHFE.rb2505"klines=api.get_kline_serial(symbol,60*60*24,500)# 日线api.wait_update()# 转为DataFramedf=klines.to_dataframe()# 计算各因子defcalc_all_factors(df):"""计算所有因子"""# 1. 动量因子df['momentum_5']=df['close'].pct_change(5)df['momentum_20']=df['close'].pct_change(20)# 2. 波动率因子returns=df['close'].pct_change()df['volatility']=returns.rolling(20).std()# 3. 均线偏离ma20=df['close'].rolling(20).mean()df['ma_deviation']=(df['close']-ma20)/ma20# 4. 成交量比率avg_vol=df['volume'].rolling(20).mean()df['volume_ratio']=df['volume']/avg_vol# 5. RSIdelta=df['close'].diff()gain=delta.where(delta>0,0).rolling(14).mean()loss=(-delta.where(delta<0,0)).rolling(14).mean()df['rsi']=100-100/(1+gain/loss)# 6. 价格位置(相对近期高低点)high_20=df['high'].rolling(20).max()low_20=df['low'].rolling(20).min()df['price_position']=(df['close']-low_20)/(high_20-low_20)returndf df=calc_all_factors(df)print(df[['datetime','close','momentum_20','volatility','rsi']].tail(10))api.close()五、因子标准化
不同因子的量级不同,需要标准化:
defstandardize_factors(df,factor_cols):"""因子标准化(Z-score)"""forcolinfactor_cols:mean=df[col].rolling(60).mean()std=df[col].rolling(60).std()df[f'{col}_zscore']=(df[col]-mean)/stdreturndf factor_cols=['momentum_20','volatility','ma_deviation','volume_ratio','rsi']df=standardize_factors(df,factor_cols)六、因子组合
6.1 等权组合
defequal_weight_score(df,factor_cols):"""等权因子组合"""zscore_cols=[f'{col}_zscore'forcolinfactor_cols]df['composite_score']=df[zscore_cols].mean(axis=1)returndf6.2 自定义权重
defweighted_score(df,factor_weights):"""加权因子组合"""score=0forfactor,weightinfactor_weights.items():score+=df[f'{factor}_zscore']*weight df['composite_score']=scorereturndf# 使用weights={'momentum_20':0.3,'ma_deviation':0.25,'rsi':0.2,'volume_ratio':0.15,'volatility':0.1,}df=weighted_score(df,weights)七、多因子策略实现
fromtqsdkimportTqApi,TqAuth,TqBacktest,TqSimfromdatetimeimportdateimportpandasaspd# 参数SYMBOL="SHFE.rb2505"ENTRY_THRESHOLD=1.0# 开仓阈值EXIT_THRESHOLD=-0.5# 平仓阈值VOLUME=1# 因子权重FACTOR_WEIGHTS={'momentum_20':0.3,'ma_deviation':0.25,'rsi_factor':0.2,# RSI转换后的因子'volume_ratio':0.15,'volatility':0.1,}api=TqApi(TqSim(),backtest=TqBacktest(start_dt=date(2024,1,1),end_dt=date(2025,6,30)),auth=TqAuth("账户","密码"))klines=api.get_kline_serial(SYMBOL,60*60,500)# 1小时K线position=api.get_position(SYMBOL)print("多因子策略启动...")whileTrue:api.wait_update()ifapi.is_changing(klines):iflen(klines)<60:continuedf=klines.to_dataframe()# 计算因子df['momentum_20']=df['close'].pct_change(20)ma20=df['close'].rolling(20).mean()df['ma_deviation']=(df['close']-ma20)/ma20 df['volume_ratio']=df['volume']/df['volume'].rolling(20).mean()returns=df['close'].pct_change()df['volatility']=returns.rolling(20).std()# RSI转换(RSI>70做空因子,RSI<30做多因子)delta=df['close'].diff()gain=delta.where(delta>0,0).rolling(14).mean()loss=(-delta.where(delta<0,0)).rolling(14).mean()rsi=100-100/(1+gain/loss)df['rsi_factor']=(50-rsi)/50# 标准化到-1到1# 标准化因子forfactorinFACTOR_WEIGHTS.keys():mean=df[factor].rolling(60).mean()std=df[factor].rolling(60).std()df[f'{factor}_zscore']=(df[factor]-mean)/std# 计算综合得分score=0forfactor,weightinFACTOR_WEIGHTS.items():zscore=df[f'{factor}_zscore'].iloc[-1]ifpd.notna(zscore):score+=zscore*weight# 交易逻辑ifposition.pos_long==0andposition.pos_short==0:ifscore>ENTRY_THRESHOLD:api.insert_order(SYMBOL,"BUY","OPEN",VOLUME)print(f"做多 | 得分:{score:.2f}")elifscore<-ENTRY_THRESHOLD:api.insert_order(SYMBOL,"SELL","OPEN",VOLUME)print(f"做空 | 得分:{score:.2f}")elifposition.pos_long>0:ifscore<EXIT_THRESHOLD:api.insert_order(SYMBOL,"SELL","CLOSE",position.pos_long)print(f"平多 | 得分:{score:.2f}")elifposition.pos_short>0:ifscore>-EXIT_THRESHOLD:api.insert_order(SYMBOL,"BUY","CLOSE",position.pos_short)print(f"平空 | 得分:{score:.2f}")八、因子分析
8.1 因子IC分析
defcalc_factor_ic(df,factor_col,forward_returns_col,period=20):"""计算因子IC(信息系数)"""# 计算未来收益df['forward_return']=df['close'].pct_change(period).shift(-period)# 计算IC(相关系数)ic=df[factor_col].rolling(60).corr(df['forward_return'])returnic.mean(),ic.std()# 使用ic_mean,ic_std=calc_factor_ic(df,'momentum_20','forward_return')print(f"动量因子 IC均值:{ic_mean:.4f}, IC标准差:{ic_std:.4f}")print(f"IC_IR:{ic_mean/ic_std:.4f}")8.2 因子相关性
importseabornassnsimportmatplotlib.pyplotasplt# 计算因子相关性矩阵factor_cols=['momentum_20','ma_deviation','volatility','volume_ratio','rsi']corr_matrix=df[factor_cols].corr()# 绘制热力图plt.figure(figsize=(10,8))sns.heatmap(corr_matrix,annot=True,cmap='coolwarm',center=0)plt.title('因子相关性矩阵')plt.show()九、总结
期货多因子策略开发的核心步骤:
- 因子挖掘:发现有预测能力的因子
- 因子计算:正确计算各因子值
- 因子标准化:统一因子量级
- 因子组合:通过权重组合多个因子
- 策略实现:基于综合得分做交易决策
- 因子分析:分析因子有效性和相关性
从使用体验来说,我目前用TqSdk做因子策略开发,主要因为数据获取方便,回测和实盘代码一致。
希望这篇入门教程对你有所帮助!
声明:本文基于个人学习经验整理,仅供技术交流参考,不构成任何投资建议。