3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
这是一个基于**净利润增长率(Net Profit Growth Rate)**的选股策略设计与实现。
Growth.NetProfitGrowRate(净利润增长率)。# -*- coding: gbk -*-
import pandas as pd
import numpy as np
def init(ContextInfo):
"""
策略初始化函数
"""
# 1. 设置账号(请替换为您的实际资金账号)
# ContextInfo.set_account('您的资金账号')
# 2. 策略参数设置
ContextInfo.target_num = 10 # 持仓股票数量
ContextInfo.rebalance_period = 20 # 调仓周期(交易日)
ContextInfo.days_counter = 0 # 计数器
# 3. 设置股票池:这里使用沪深300作为选股范围
# 注意:get_stock_list_in_sector 获取的是当前成分股,回测时建议使用 get_sector 获取历史成分股
# 这里为了演示方便,使用当前沪深300成分股
ContextInfo.stock_pool = ContextInfo.get_stock_list_in_sector('沪深300')
ContextInfo.set_universe(ContextInfo.stock_pool)
print("策略初始化完成,股票池大小:", len(ContextInfo.stock_pool))
def handlebar(ContextInfo):
"""
K线周期运行函数
"""
# 1. 判断是否到达调仓周期
if ContextInfo.days_counter % ContextInfo.rebalance_period != 0:
ContextInfo.days_counter += 1
return
# 重置计数器并增加
ContextInfo.days_counter += 1
print(f"=== 开始调仓: {ContextInfo.barpos} ===")
# 2. 获取当前时间
# get_bar_timetag 返回的是毫秒时间戳
timetag = ContextInfo.get_bar_timetag(ContextInfo.barpos)
current_date = timetag_to_datetime(timetag, '%Y%m%d')
# 3. 获取因子数据:净利润增长率
# 因子名称:Growth.NetProfitGrowRate
factor_name = 'Growth.NetProfitGrowRate'
stock_list = ContextInfo.stock_pool
# 获取因子数据,返回的是 pandas DataFrame 或 Series
# 注意:get_factor_data 的时间参数是闭区间
factor_data = ContextInfo.get_factor_data(
[factor_name],
stock_list,
current_date,
current_date
)
# 4. 数据处理与选股
if factor_data is None or len(factor_data) == 0:
print("未获取到因子数据,跳过本次调仓")
return
# 将数据转换为 DataFrame 方便处理
# get_factor_data 返回结构通常是 {stock: {date: value}} 或者 DataFrame
# 在单日查询下,通常需要整理格式
df_factor = pd.DataFrame(factor_data)
# 如果返回的是空或者全NaN,跳过
if df_factor.empty:
print("因子数据为空")
return
# 提取特定因子列,并去除空值
# 注意:根据返回数据的结构,可能需要转置或索引调整,这里假设返回的是以股票代码为索引的结构
if factor_name in df_factor.columns:
series_factor = df_factor[factor_name].dropna()
else:
# 尝试处理多重索引或不同返回格式的情况
# 这种情况下通常直接取 values 即可,视具体版本数据结构而定
# 这里做一个通用的处理尝试
try:
series_factor = df_factor.iloc[:, 0].dropna()
except:
print("数据格式解析失败")
return
# 排序:按净利润增长率从大到小排序
sorted_stocks = series_factor.sort_values(ascending=False)
# 选取前 N 只股票
target_stocks = sorted_stocks.head(ContextInfo.target_num).index.tolist()
print(f"选中股票: {target_stocks}")
# 5. 交易执行
# 获取当前持仓
positions = ContextInfo.get_trade_detail_data(ContextInfo.accid, 'stock', 'position')
current_holdings = [obj.m_strInstrumentID for obj in positions]
# 卖出不在目标列表中的股票
for stock in current_holdings:
if stock not in target_stocks:
# 目标价值设为0即为清仓
order_target_value(stock, 0, ContextInfo, ContextInfo.accid)
print(f"卖出平仓: {stock}")
# 买入目标股票
# 计算每只股票的目标市值(总资产 / 目标数量)
# 获取账户总资产
account_info = ContextInfo.get_trade_detail_data(ContextInfo.accid, 'stock', 'account')
if len(account_info) > 0:
total_asset = account_info[0].m_dBalance
target_value_per_stock = total_asset / ContextInfo.target_num
for stock in target_stocks:
# 使用 order_target_value 自动调整仓位到目标市值
order_target_value(stock, target_value_per_stock, ContextInfo, ContextInfo.accid)
print(f"买入/调仓: {stock}, 目标市值: {target_value_per_stock}")
else:
print("未获取到账户资产信息,无法下单")
数据获取 (get_factor_data):
Growth.NetProfitGrowRate 这个因子。QMT 的因子库非常丰富,直接调用因子比自己去查财报原始数据(get_financial_data)并计算同比增长率要方便且准确得多。pandas 格式,非常适合进行排序和筛选。时间处理:
barpos 对应的时间是毫秒级时间戳,必须使用 timetag_to_datetime 转换为 YYYYMMDD 字符串格式,才能作为参数传给数据获取接口。交易执行 (order_target_value):
order_target_value 是最稳健的调仓方式。容错处理:
dropna, empty check) 的判断,防止因为某些股票停牌或财报数据缺失导致策略报错停止。init 函数中,取消注释 ContextInfo.set_account 并填入您的真实或模拟资金账号。Q: 为什么使用 get_factor_data 而不是 get_financial_data?
A: get_financial_data 获取的是原始财报数据(如“净利润”绝对值),你需要自己写代码去获取去年的数据并计算增长率 (今年-去年)/去年。而 get_factor_data 直接提供了计算好的因子(如 Growth.NetProfitGrowRate),处理了除权、财报调整等复杂情况,开发效率更高。
Q: 如何查看还有哪些因子可用?
A: 在 QMT 的帮助文档中,查找“多因子数据接口”或“股票因子库”章节(通常在附录 5.2),可以看到如 Valuation_and_Market_Cap.PE (市盈率), Profitability_and_Earning Quality.ROE (净资产收益率) 等大量因子。
Q: 策略回测时没有交易是怎么回事?
A: 1. 检查 ContextInfo.set_account 是否设置正确。2. 检查回测时间段内是否有数据(如果是节假日或数据未下载,可能取不到因子数据)。3. 确保在“数据管理”中下载了对应的“多因子数据”和“日线数据”。