3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
编写一个按月度或季度自动调仓的策略,核心逻辑在于时间周期的判断和目标仓位的调整。
在 QMT 中,实现这一功能的最佳方式是利用 handlebar 函数监控时间变化,并使用 order_target_percent(按目标比例下单)函数来自动调整持仓。
init):
handlebar):
rebalance):
order_target_percent 函数,将持仓调整至目标比例。该函数会自动计算需要买入或卖出的数量。以下是一个完整的 Python 策略代码。你可以直接将其复制到 QMT 的策略编辑器中。
# -*- coding: gbk -*-
import time
def init(ContextInfo):
"""
策略初始化函数
"""
# 1. 设置资金账号 (请替换为您的实际账号)
ContextInfo.accID = '6000000000'
ContextInfo.set_account(ContextInfo.accID)
# 2. 设定投资组合及目标权重 (示例:股债平衡策略)
# 格式:{'股票代码': 目标仓位比例},总和建议为 1.0 (100%)
ContextInfo.target_portfolio = {
'510300.SH': 0.6, # 沪深300ETF 占 60%
'511260.SH': 0.4 # 十年国债ETF 占 40%
}
# 设置股票池,确保能获取到这些标的的数据
ContextInfo.set_universe(list(ContextInfo.target_portfolio.keys()))
# 3. 设置调仓频率参数
# 可选值: 'month' (月度), 'quarter' (季度)
ContextInfo.rebalance_freq = 'month'
# 4. 记录上一次调仓的月份,初始化为 -1
ContextInfo.last_rebalance_month = -1
print("策略初始化完成,调仓频率:{}".format(ContextInfo.rebalance_freq))
def handlebar(ContextInfo):
"""
K线运行函数,每根K线执行一次
"""
# 获取当前K线的时间戳
timetag = ContextInfo.get_bar_timetag(ContextInfo.barpos)
# 将时间戳转换为日期字符串,格式 YYYYMMDD
date_str = timetag_to_datetime(timetag, '%Y%m%d')
# 提取当前月份 (int类型)
current_month = int(date_str[4:6])
# 判断是否需要调仓
need_rebalance = False
# 如果当前月份与上一次调仓月份不同,说明进入了新的月份
if current_month != ContextInfo.last_rebalance_month:
if ContextInfo.rebalance_freq == 'month':
# 月度调仓:每个月变化都触发
need_rebalance = True
elif ContextInfo.rebalance_freq == 'quarter':
# 季度调仓:仅在 1, 4, 7, 10 月触发
if current_month in [1, 4, 7, 10]:
need_rebalance = True
# 执行调仓逻辑
if need_rebalance:
print("=" * 30)
print(f"触发调仓信号 - 日期: {date_str}, 月份: {current_month}")
rebalance(ContextInfo)
# 更新上一次调仓月份,防止当月重复调仓
ContextInfo.last_rebalance_month = current_month
def rebalance(ContextInfo):
"""
执行调仓的核心函数
"""
# 遍历目标组合中的每一只股票和权重
for stock_code, target_weight in ContextInfo.target_portfolio.items():
# 使用 order_target_percent 接口
# 该接口会自动计算当前持仓价值与目标价值的差额,并进行买卖
# 参数说明:
# stock_code: 代码
# target_weight: 目标比例 (0.6 代表 60%)
# style: 下单选价类型,'LATEST' 为最新价,'FIX' 为指定价
# price: 价格,使用最新价时填 -1
order_target_percent(stock_code, target_weight, 'LATEST', -1, ContextInfo, ContextInfo.accID)
print(f"调整标的: {stock_code}, 目标权重: {target_weight * 100}%")
# 可选:如果投资组合中有股票被剔除,需要在这里处理卖出逻辑
# (本示例假设组合固定,若组合动态变化,需额外遍历持仓列表卖出不在目标池的股票)
timetag_to_datetime:
get_bar_timetag 返回的是毫秒级时间戳。timetag_to_datetime(timetag, '%Y%m%d') 将其转换为易于处理的字符串格式(如 "20231001"),方便提取月份。调仓频率控制:
current_month != ContextInfo.last_rebalance_month 判断是否进入了新月份。current_month in [1, 4, 7, 10] 的判断,确保只在季度初调仓。order_target_percent (核心交易函数):
目标持仓市值 = 总资产 * 目标权重。当前持仓和目标持仓,如果当前持仓不足则买入,过多则卖出,一步到位。ContextInfo.accID 修改为您真实的资金账号,并确保 QMT 客户端已登录交易柜台。handlebar 每天运行一次,会在每个月/季度的第一个交易日触发调仓。order_target_percent 会按最新价下单。如果在盘后运行(非交易时间),信号会生成但无法成交,除非使用 do_order 或等到第二天开盘。order_target_percent 是基于账户总资产计算的。如果账户中有其他非策略持仓,可能会影响计算结果。建议该账号专用于此策略,或在代码中手动计算可用资金。Q: 如何将策略改为每年调仓一次?
A: 在 handlebar 中修改判断逻辑,提取年份,判断年份是否变化即可。
Q: 如果我想在每月的最后一个交易日调仓怎么办?
A: 可以使用 ContextInfo.get_trading_dates 获取交易日历,判断当前日期是否为当月列表中的最后一个日期。
Q: order_target_percent 会自动卖出不在 target_portfolio 里的股票吗?
A: 不会。该函数只针对传入的 stock_code 进行调整。如果你想清仓不在目标列表里的股票,需要先遍历 ContextInfo.get_trade_detail_data 获取当前持仓,将不在目标列表中的股票权重设为 0 并调用下单函数。