3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在构建 ETF 日内轮动策略时,核心在于规避未来函数、合理分配资金(分散持仓)以及在有限资金下通过“先卖后买”释放流动性。此外,由于 A 股 ETF 具备 T+0 交易特性,我们需要在聚宽中开启实验性的 T+0 模式。
以下是完整的策略设计与 Python 源码实现:
initialize 中通过 set_option('use_real_price', True) 开启真实价格模式,并使用 set_option('t0_mode', True) 允许日内买入后立刻卖出。history 获取候选 ETF 过去 5 天的收盘价,计算涨幅并降序排列,筛选出涨幅最高的前 $N$ 只 ETF。available_cash)后,再执行买入逻辑,防止因资金占用导致买入失败。# 导入聚宽函数库
import jqdata
import pandas as pd
import numpy as np
def initialize(context):
# 1. 设定沪深300作为基准
set_benchmark('000300.XSHG')
# 2. 开启真实价格模式(动态复权)
set_option('use_real_price', True)
# 3. 开启 T+0 交易模式(允许日内回转交易)
set_option('t0_mode', True)
# 设定交易费率:ETF 佣金万分之三,无印花税,最低5元
set_order_cost(OrderCost(open_tax=0, close_tax=0, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='fund')
# 策略参数设置
g.etf_pool = [
'510300.XSHG', # 300ETF
'510500.XSHG', # 500ETF
'518880.XSHG', # 黄金ETF
'159915.XSHE', # 创业板ETF
'513100.XSHG', # 纳指ETF
'510050.XSHG' # 50ETF
]
g.hold_num = 3 # 同时分散持仓的 ETF 数量
g.momentum_window = 5 # 动量计算窗口(天)
# 每日 14:50 进行日内轮动调仓(避开开盘剧烈波动,并在收盘前完成轮动)
run_daily(handle_rotation, time='14:50')
def handle_rotation(context):
# 获取当前持仓列表
current_positions = list(context.portfolio.positions.keys())
# 1. 动量筛选:获取过去 5 天的收盘价(不含今天)
hist_data = history(g.momentum_window + 1, unit='1d', field='close', security_list=g.etf_pool, df=True)
# 计算 5 日变化率
returns = (hist_data.iloc[-1] - hist_data.iloc[0]) / hist_data.iloc[0]
# 降序排列并筛选前 N 只
target_etfs = list(returns.sort_values(ascending=False).index[:g.hold_num])
log.info(f"今日目标持仓 ETF: {target_etfs}")
# 2. 先卖后买逻辑:释放资金
# 找出需要清仓的 ETF
to_sell = [etf for etf in current_positions if etf not in target_etfs]
for etf in to_sell:
order_target(etf, 0)
log.info(f"[先卖] 清仓未入选 ETF: {etf}")
# 3. 动态计算买入仓位
# 卖出执行后,获取最新总资产,计算单只 ETF 预算
total_value = context.portfolio.total_value
single_budget = total_value / g.hold_num
# 4. 执行买入/调仓
for etf in target_etfs:
# 目标是使该 ETF 的持仓价值达到 single_budget
order_target_value(etf, single_budget)
log.info(f"[后买] 调整目标持仓价值: {etf} -> 预算: {single_budget:.2f}元")
def after_trading_end(context):
# 每日收盘后打印持仓详情
log.info("每日收盘持仓详情:")
for security, position in context.portfolio.positions.items():
log.info(f"标的: {security}, 总仓位: {position.total_amount}, 价值: {position.value:.2f}元")
set_option('t0_mode', True):此实验性设置允许在回测和模拟盘中,买入的 A 股或 ETF 在当天即可卖出,完美契合日内 T+0 轮动需求。order_target_value(security, value):直接将标的仓位调整至目标价值。配合“先卖后买”流程,能自动计算补仓或减仓额度,极大地简化了分散持仓的比例控制代码。