3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在多因子选股中,**动量因子(Momentum)**是极其经典的一类风格因子。为了捕捉不同维度的动量效应,我们在此定义并比较两种动量因子:
relative_strength。我们继承聚宽的 Factor 类,实现上述带标准化偏离和递近权重的均线动量因子:
import numpy as np
import pandas as pd
from jqfactor import Factor, calc_factors
class MA_Momentum_Weighted(Factor):
name = 'ma_momentum_weighted'
# 需要过去 20 天的偏离度,而计算 MA5 需要额外 5 天,因此窗口设为 25
max_window = 25
dependencies = ['close']
def calc(self, data):
close = data['close'] # DataFrame: index为日期(25天), columns为股票代码
# 1. 计算 5 日均线 (MA5)
ma5 = close.rolling(window=5).mean()
# 2. 计算价格相对于 MA5 的偏离度
bias = (close - ma5) / ma5
# 3. 取最近 20 天的偏离度数据进行加权
bias_20 = bias.iloc[-20:]
# 4. 定义递近权重 (1 到 20)
weights = np.arange(1, 21).reshape(-1, 1)
# 5. 计算加权偏离度均值
weighted_bias = (bias_20 * weights).sum(axis=0) / weights.sum()
# 6. 计算过去 20 天偏离度的标准差,用于标准化
sigma_20 = bias_20.std(axis=0)
# 7. 避免除以 0,进行标准化处理
factor_value = weighted_bias / (sigma_20 + 1e-6)
return pd.Series(factor_value, index=close.columns)
以下是一个完整的聚宽策略模板,通过 initialize 设定定时任务,每月初计算两类动量因子,并分别构建多头组合进行回测对比:
from jqdata import *
from jqfactor import get_factor_values
# 导入自定义因子类(若在研究环境中,可直接复制上述类定义)
def initialize(context):
set_benchmark('000300.XSHG')
set_option('use_real_price', True)
# 佣金印花税设置
set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
# 策略参数设置
g.factor_type = 'MA_MOMENTUM' # 可选: 'MA_MOMENTUM' 或 'CLASSIC_MOMENTUM'
g.hold_num = 10 # 持股数量
# 每月第一个交易日开盘运行
run_monthly(rebalance, monthday=1, time='09:30')
def rebalance(context):
# 1. 获取沪深300成分股
stocks = get_index_stocks('000300.XSHG', date=context.previous_date)
# 2. 获取因子值
if g.factor_type == 'CLASSIC_MOMENTUM':
# 获取聚宽因子库中的经典动量因子 momentum
factor_data = get_factor_values(
securities=stocks,
factors=['momentum'],
end_date=context.previous_date,
count=1
)['momentum'].iloc[-1]
else:
# 计算自定义的带权重均线动量因子
# 在回测中,可使用 calc_factors 实时计算
factor_dict = calc_factors(
securities=stocks,
factors=[MA_Momentum_Weighted()],
start_date=context.previous_date,
end_date=context.previous_date
)
factor_data = factor_dict['ma_momentum_weighted'].iloc[-1]
# 3. 因子值去极值与标准化(可选,此处直接按因子值从大到小排序)
factor_data = factor_data.dropna().sort_values(ascending=False)
# 4. 选取前 10 只高动量股票
target_list = list(factor_data.index[:g.hold_num])
# 5. 调仓执行
# 卖出不在目标池的股票
for stock in list(context.portfolio.positions.keys()):
if stock not in target_list:
order_target(stock, 0)
# 等权重买入目标股票
position_value = context.portfolio.total_value / g.hold_num
for stock in target_list:
order_target_value(stock, position_value)
在聚宽回测结束后,建议从以下三个维度对比两种动量策略的表现: