3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
本策略属于动量轮动与趋势跟踪相结合的量化投资策略。其核心逻辑分为以下三个步骤:
请在聚宽回测环境中运行以下 Python 3 策略代码:
import numpy as np
import pandas as pd
from scipy.stats import linregress
from jqdata import *
def initialize(context):
# 1. 策略基本设置
set_benchmark('000300.XSHG')
set_option('use_real_price', True)
log.set_level('order', 'info')
# 2. 定义行业与宽基 ETF 候选池
g.etf_pool = [
'510300.XSHG', # 沪深300 ETF
'510500.XSHG', # 中证500 ETF
'159915.XSHE', # 创业板 ETF
'518880.XSHG', # 黄金 ETF
'512880.XSHG', # 证券 ETF
'512010.XSHG', # 医药 ETF
'512660.XSHG', # 军工 ETF
'515000.XSHG', # 科技 ETF
'512480.XSHG', # 半导体 ETF
'159928.XSHE', # 消费 ETF
]
# 3. 设定调仓参数
g.max_hold = 5 # 最大持有数量
g.ma_window = 20 # 均线过滤周期
g.reg_window = 25 # 线性回归周期
# 4. 每周第一个交易日开盘运行调仓
run_weekly(my_rebalance, weekday=1, time='09:30')
def my_rebalance(context):
# 获取历史数据
# 需要获取最大窗口(25天)的数据
hist = history(g.reg_window, unit='1d', field='close', security_list=g.etf_pool, df=True)
candidates = {}
for etf in g.etf_pool:
prices = hist[etf].values
if len(prices) < g.reg_window or np.isnan(prices).any():
continue
# 步骤 1: 20日均线过滤
ma20 = prices[-g.ma_window:].mean()
current_price = prices[-1]
if current_price > ma20:
# 步骤 2: 25日对数价格线性回归
log_prices = np.log(prices)
x = np.arange(len(log_prices))
# 使用 scipy 计算线性回归
slope, intercept, r_value, p_value, std_err = linregress(x, log_prices)
r_squared = r_value ** 2
# 计算趋势质量得分 (斜率 * R2)
# 只有斜率为正(即上涨趋势)才考虑
if slope > 0:
score = slope * r_squared
candidates[etf] = score
# 步骤 3: 排序并选择前 5 只
sorted_candidates = sorted(candidates.items(), key=lambda item: item[1], reverse=True)
target_etfs = [item[0] for item in sorted_candidates[:g.max_hold]]
log.info(f"今日通过过滤与筛选的 ETF 目标持仓: {target_etfs}")
# 步骤 4: 执行调仓操作(卖出不在目标持仓中的,等权买入目标持仓)
current_positions = list(context.portfolio.positions.keys())
# 1. 卖出不在目标列表中的 ETF
for etf in current_positions:
if etf not in target_etfs:
order_target(etf, 0)
log.info(f"卖出清仓: {etf}")
# 2. 计算等权分配资金
if len(target_etfs) > 0:
target_value = context.portfolio.total_value / len(target_etfs)
for etf in target_etfs:
order_target_value(etf, target_value)
log.info(f"调仓/买入: {etf} 至目标价值 {target_value:.2f} 元")