3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在聚宽(JoinQuant)平台上实现ETF轮动策略时,许多宽客容易陷入“因子堆砌”和“过度拟合”的陷阱。为了提升策略在实盘中的稳健性,必须通过科学的方法精简因子,并剔除冗余的辅助过滤模块。以下是系统性的优化方案:
每一个保留的因子或过滤模块,必须有坚实的经济学或行为金融学逻辑。例如:
利用聚宽的 analyze_factor 工具对候选因子进行单因子分析:
quantile_turnover 评估因子的交易成本。如果一个辅助因子略微提升了收益,但大幅增加了换手率,应果断剔除。如果必须使用多个因子,应在计算前进行正交化处理(如聚宽提供的 neutralize 中性化方法),消除彼此的线性相关部分,只保留纯净的超额收益贡献。
以下是一个精简、稳健的ETF轮动策略示例。该策略仅保留核心动量因子(21日收益率)与大盘均线风控,不包含任何冗余的微观过滤模块,具有极强的抗过拟合能力。
import pandas as pd
from jqdata import *
def initialize(context):
# 设定沪深300作为基准
set_benchmark('000300.XSHG')
# 开启动态复权模式(真实价格)
set_option('use_real_price', True)
# 核心ETF候选池(覆盖宽基、行业及黄金,避免同质化)
g.etf_pool = [
'510300.XSHG', # 沪深300 ETF
'510500.XSHG', # 中证500 ETF
'159915.XSHE', # 创业板 ETF
'518880.XSHG', # 黄金 ETF
'513100.XSHG' # 纳指 ETF
]
# 核心风控参考标的
g.market_index = '000300.XSHG'
# 调仓周期:每周第一个交易日
run_weekly(market_open, weekday=1, time='09:30')
def market_open(context):
# 1. 大盘风控模块(极简风控:若沪深300跌破20日均线,则全仓避险)
index_close = attribute_history(g.market_index, 20, '1d', ['close'])['close']
ma20 = index_close.mean()
current_index_price = index_close[-1]
if current_index_price < ma20:
log.info("大盘处于弱势,清仓避险")
for asset in context.portfolio.positions:
order_target(asset, 0)
return
# 2. 核心动量计算(仅使用单一核心因子:21日收益率)
scores = {}
for etf in g.etf_pool:
hist = attribute_history(etf, 21, '1d', ['close'])['close']
# 计算21日动量(当前价格 / 21日前价格 - 1)
momentum = (hist[-1] / hist[0]) - 1
scores[etf] = momentum
# 3. 轮动决策:选择动量最强的1只ETF
best_etf = max(scores, key=scores.get)
# 如果最强ETF的动量为负,则不持仓
if scores[best_etf] <= 0:
log.info("所有候选ETF动量均为负,空仓观望")
for asset in context.portfolio.positions:
order_target(asset, 0)
return
# 4. 执行调仓(卖出非目标,买入目标)
for asset in list(context.portfolio.positions.keys()):
if asset != best_etf:
order_target(asset, 0)
# 买入最强ETF
cash = context.portfolio.available_cash
if cash > 0:
order_value(best_etf, cash)
log.info("调仓买入最强动量ETF: %s" % best_etf)