3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在 QMT 中编写指数增强策略,核心步骤包括:获取指数成分股、获取成分股权重、应用增强逻辑(调整权重)、归一化权重以及执行交易。
以下是针对您需求的详细解答和完整的策略代码示例。
ContextInfo.get_sector(index_code)。ContextInfo.get_weight_in_index(index_code, stock_code)。
order_target_percent,它可以自动计算当前持仓与目标权重的差额进行买卖。以下代码展示了一个简单的指数增强框架。作为示例,增强逻辑设定为:如果股价在 20 日均线之上,则超配 20%;如果在均线之下,则低配 20%。 您可以将这部分替换为您自己的判断逻辑。
# -*- coding: gbk -*-
import pandas as pd
def init(ContextInfo):
# 1. 设置策略参数
ContextInfo.index_code = '000300.SH' # 基准指数:沪深300
ContextInfo.account_id = 'YOUR_ACCOUNT_ID' # 请替换为您的资金账号
ContextInfo.account_type = 'STOCK' # 账号类型:STOCK, FUTURE 等
ContextInfo.rebalance_period = 20 # 调仓周期:每20根K线调仓一次
# 设置账号(实盘/回测必须)
ContextInfo.set_account(ContextInfo.account_id)
# 2. 设置股票池为指数成分股(用于回测数据下载)
# 注意:get_sector 获取的是当前成分股,回测中若需历史成分股需注意数据准确性
components = ContextInfo.get_sector(ContextInfo.index_code)
ContextInfo.set_universe(components)
def handlebar(ContextInfo):
# 1. 判断是否到达调仓周期
# 使用 barpos 判断,或者使用 timetag 判断日期
if ContextInfo.barpos % ContextInfo.rebalance_period != 0:
return
print(f"开始执行调仓,当前K线位置: {ContextInfo.barpos}")
# 2. 获取指数成分股
# get_sector 第二个参数传入当前时间戳,可尝试获取当时成分股(视数据源支持情况)
current_time = ContextInfo.get_bar_timetag(ContextInfo.barpos)
components = ContextInfo.get_sector(ContextInfo.index_code, current_time)
if not components:
print("未获取到成分股信息")
return
# 3. 获取增强所需的行情数据 (用于示例逻辑:计算均线)
# 获取过去20天的收盘价
market_data = ContextInfo.get_market_data_ex(
['close'],
components,
period='1d',
count=21,
dividend_type='front'
)
# 4. 计算目标权重
target_weights = {}
total_adjusted_weight = 0.0
# 临时存储调整后的权重
temp_weights = {}
for stock in components:
# 4.1 获取原始权重 (单位是 %,需要除以 100 转换为小数)
raw_weight_percent = ContextInfo.get_weight_in_index(ContextInfo.index_code, stock)
base_weight = raw_weight_percent / 100.0
# 如果获取不到权重(如新股或数据缺失),暂按0处理或跳过
if base_weight <= 0:
continue
# 4.2 应用增强逻辑 (自定义判断部分)
# 示例逻辑:收盘价 > 20日均线 -> 超配 1.2倍;否则 -> 低配 0.8倍
adjustment_factor = 1.0
if stock in market_data:
df = market_data[stock]
if len(df) >= 21:
close_prices = df['close']
current_price = close_prices.iloc[-1]
ma20 = close_prices.iloc[-21:-1].mean() # 前20日均线
if current_price > ma20:
adjustment_factor = 1.2 # 超配
else:
adjustment_factor = 0.8 # 低配
# 计算调整后权重
adj_weight = base_weight * adjustment_factor
temp_weights[stock] = adj_weight
total_adjusted_weight += adj_weight
# 5. 权重归一化 (Normalization)
# 确保所有股票的目标权重之和为 1 (100%)
if total_adjusted_weight > 0:
for stock, w in temp_weights.items():
target_weights[stock] = w / total_adjusted_weight
else:
print("权重计算异常,总权重为0")
return
# 6. 执行交易
# 遍历计算出的目标权重进行调仓
# 注意:这里只处理了在指数内的股票。如果需要卖出已经被剔除出指数的股票,
# 需要先获取当前持仓,将不在 target_weights 里的股票清仓。
# 6.1 先处理清仓逻辑 (不在目标列表里的持仓股票卖出)
positions = get_trade_detail_data(ContextInfo.account_id, ContextInfo.account_type, 'POSITION')
for pos in positions:
stock_code = pos.m_strInstrumentID + '.' + pos.m_strExchangeID
if stock_code not in target_weights and pos.m_nVolume > 0:
order_target_percent(stock_code, 0, ContextInfo, ContextInfo.account_id)
print(f"卖出非成分股/被剔除股票: {stock_code}")
# 6.2 执行买入/调仓
for stock, weight in target_weights.items():
# order_target_percent 接受的 weight 是小数 (0.05 代表 5%)
order_target_percent(stock, weight, ContextInfo, ContextInfo.account_id)
print("调仓指令发送完毕")
get_weight_in_index 获取的是静态数据,通常随行情包更新。在回测模式下,QMT 会尝试匹配历史权重,但建议在实盘前仔细核对数据源。order_target_percent 是最适合此类策略的函数,它会自动计算买卖数量。请确保在 init 中正确设置了 ContextInfo.set_account。Q: 如何将增强逻辑改为基于因子的打分?
A: 您可以在 init 中通过 ContextInfo.get_factor_data 预先获取因子数据,或者在 handlebar 中读取本地计算好的 CSV 文件。在遍历成分股时,根据因子值的大小来设定 adjustment_factor。
Q: get_weight_in_index 返回的是流通市值权重还是总市值权重?
A: 这取决于指数本身的编制规则。对于沪深300等主流指数,通常是分级靠档后的自由流通市值权重。QMT 返回的是交易所或指数公司公布的权重数据。
Q: 为什么代码第一行要加 # -*- coding: gbk -*-?
A: QMT 的 Python 编辑器和底层环境默认使用 GBK 编码。如果不加这一行,代码中的中文字符(注释或打印信息)可能会导致乱码或运行报错。