🚀 AI 一键生成 qmt 策略代码

QMT 中如何使用 `order_target_percent` 实现投资组合的自动再平衡?

qmt | 发布时间: 2025/12/18
以下内容由 EasyQuant 生成。

问题描述

请编写一个能自动进行投资组合再平衡的策略

解决方案

这是一个基于 QMT (Quantitative Trading Platform) API 编写的自动投资组合再平衡策略

策略逻辑说明

该策略旨在实现一个经典的定期等权重再平衡(Equal-Weight Rebalancing)逻辑:

  1. 标的池:选取一组固定的股票(示例中选取了白酒、金融等行业的龙头股)。
  2. 目标权重:策略目标是让持仓中每只股票的市值保持相等(例如 5 只股票,每只占总资产的 20%)。
  3. 再平衡频率:按进行。每当月份发生变化时(即每个月的第一天交易日),触发调仓。
  4. 交易执行:使用 order_target_percent 函数。该函数会自动计算需要买入或卖出的数量,将仓位调整至目标比例。

策略代码

# -*- coding: gbk -*-
import pandas as pd
import time

def init(ContextInfo):
    """
    初始化函数,策略启动时调用一次
    """
    # 1. 设置资金账号 (请替换为您真实的资金账号)
    # 格式如: '6000000248'
    ContextInfo.account_id = 'YOUR_ACCOUNT_ID' 
    ContextInfo.set_account(ContextInfo.account_id)
    
    # 2. 设置股票池 (示例:贵州茅台, 五粮液, 平安银行, 招商银行, 宁德时代)
    # 用户可根据需求修改此列表
    ContextInfo.stock_list = ['600519.SH', '000858.SZ', '000001.SZ', '600036.SH', '300750.SZ']
    ContextInfo.set_universe(ContextInfo.stock_list)
    
    # 3. 设置再平衡参数
    # 记录上一次再平衡的月份,用于判断是否跨月
    ContextInfo.last_rebalance_month = -1
    
    # 4. 设置回测参数 (仅回测模式有效)
    # 资金 100万
    ContextInfo.capital = 1000000
    # 费率设置:万分之三
    ContextInfo.set_commission(0, [0.001, 0.001, 0.0003, 0.0003, 0.0003, 5])
    # 滑点设置:0.01元
    ContextInfo.set_slippage(1, 0.01)

    print("策略初始化完成,标的池数量: {}".format(len(ContextInfo.stock_list)))

def handlebar(ContextInfo):
    """
    行情事件函数,每根K线运行一次
    """
    # 获取当前K线的时间戳
    timetag = ContextInfo.get_bar_timetag(ContextInfo.barpos)
    # 将时间戳转换为 datetime 格式的字符串
    current_date_str = timetag_to_datetime(timetag, '%Y%m%d')
    # 提取当前月份 (格式 YYYYMM)
    current_month = int(current_date_str[0:6])
    
    # 判断是否需要跳过 (例如未到最后一根K线,或者非交易时间)
    # 在回测模式下,通常在日线周期的每一根Bar执行
    
    # --- 再平衡逻辑判断 ---
    # 如果当前月份与上一次记录的月份不同,说明进入了新的月份,执行再平衡
    if current_month != ContextInfo.last_rebalance_month:
        print(">>> 检测到月份变化,执行再平衡。当前日期: {}".format(current_date_str))
        
        # 执行调仓函数
        rebalance(ContextInfo)
        
        # 更新记录的月份
        ContextInfo.last_rebalance_month = current_month

def rebalance(ContextInfo):
    """
    执行再平衡的核心逻辑
    """
    stock_count = len(ContextInfo.stock_list)
    if stock_count == 0:
        return

    # 计算每只股票的目标权重 (等权重)
    # 如果有5只股票,每只权重为 1/5 = 0.2 (20%)
    target_weight = 1.0 / stock_count
    
    print("开始调仓,目标每只股票持仓权重: {:.2%}".format(target_weight))
    
    # 遍历股票池中的每一只股票进行调整
    for stock in ContextInfo.stock_list:
        # 获取当前标的名称,用于日志输出
        stock_name = ContextInfo.get_stock_name(stock)
        
        # 使用 order_target_percent 进行下单
        # 该函数会自动计算:(总资产 * 目标比例 - 当前持仓市值) / 股价
        # 正数买入,负数卖出
        # 注意:order_target_percent 依赖于账户的总资产数据
        
        # 参数说明: 
        # stock: 代码
        # target_weight: 目标比例 (0.2 表示 20%)
        # order_type: 1101 (单股、单账号、普通、股/手方式下单) - 这里虽然是target_percent,但底层通常映射到具体的下单指令
        # price: -1 (使用默认价格,通常是市价或最新价,取决于交易设置)
        # ContextInfo: 上下文
        # account_id: 账号
        
        # 注意:QMT的 order_target_percent 封装在 Python API 中,
        # 它会自动处理买卖方向。
        order_target_percent(stock, target_weight, "LATEST", 0.0, ContextInfo, ContextInfo.account_id)
        
        print("已发送调仓指令: {} ({}), 目标权重: {:.2%}".format(stock, stock_name, target_weight))

    print("本次再平衡指令发送完毕。")

代码关键点解析

  1. # -*- coding: gbk -*-:

    • QMT 的 Python 编辑器默认使用 GBK 编码,这行代码必须放在第一行,否则中文注释会导致乱码或报错。
  2. init 函数:

    • ContextInfo.set_account: 必须设置真实的资金账号,否则无法获取持仓和资金信息,order_target_percent 也无法正确计算。
    • ContextInfo.stock_list: 这里定义了投资组合的范围。
  3. handlebar 函数:

    • 这是策略的驱动引擎。我们通过 timetag_to_datetime 获取当前 K 线的时间。
    • 跨月判断逻辑:通过比较 current_monthlast_rebalance_month。如果不同,说明这是新月份的第一个交易 K 线,触发调仓。
  4. rebalance 函数:

    • 核心算法target_weight = 1.0 / len(stock_list)。这是最简单的等权重模型。
    • order_target_percent: 这是 QMT 提供的便捷交易函数。
      • 它会自动读取当前账户的总资产(现金+持仓市值)。
      • 它会计算目标持仓市值 = 总资产 * target_weight
      • 它会对比当前持仓,自动发出买入或卖出指令,将仓位调整到目标水平。

如何在 QMT 中运行

  1. 打开 QMT 客户端,进入【模型研究】或【策略交易】界面。
  2. 新建一个 Python 策略。
  3. 将上述代码完整复制粘贴到编辑器中。
  4. 修改账号:将 ContextInfo.account_id = 'YOUR_ACCOUNT_ID' 中的 'YOUR_ACCOUNT_ID' 替换为您实际的资金账号。
  5. 回测
    • 在右侧设置回测区间(例如最近一年)。
    • 周期选择“日线”。
    • 点击“回测”按钮查看净值曲线。
  6. 实盘/模拟盘
    • 确保 QMT 交易端已登录。
    • 将策略加载到运行单元,点击“运行”。

常见问题 (Q&A)

Q: 如何将等权重改为按市值加权?
A: 您需要在 rebalance 函数中获取每只股票的总市值,计算总市值之和,然后计算每只股票的权重 weight = 个股总市值 / 所有股票总市值,最后将这个动态的 weight 传给 order_target_percent

Q: 为什么回测时没有交易?
A: 请检查:1. ContextInfo.stock_list 中的股票在回测区间内是否已上市;2. 是否下载了对应的历史日线数据;3. 资金账号设置是否符合回测虚拟账号规则(回测模式下通常不需要真实账号,但代码逻辑中引用了 account_id,回测引擎会模拟一个)。

Q: order_target_percent 下单失败怎么办?
A: 可能是因为资金不足、股票停牌或跌停无法卖出。在实盘中,建议配合 get_trade_detail_data 查询委托状态,或者在 rebalance 前增加风控判断(如检查股票状态 ContextInfo.is_suspended_stock)。