🚀 AI 一键生成 qmt 策略代码
立即体验

如何在 QMT 平台实现商品期货双向网格交易策略?(附 Python 源码与风控机制)

qmt | 发布时间: 2026/7/31
以下内容由 EasyQuant 生成。

问题描述

请根据以下 SEO 主题生成完整页面内容:

Title: QMT 期货双向网格交易策略开发与资金风控

Question: 请帮我编写一个适用于 QMT 的商品期货动态网格交易策略

解决方案

QMT 商品期货双向网格交易策略开发与资金风控

网格交易是一种基于价格震荡进行低买高卖(或高卖低买)的自动化交易策略。在商品期货交易中,结合双向网格(多空同时挂单)与动态风控体系,可以在震荡行情中获取稳定的波段收益。

本文将基于 QMT(迅投量化原生 Python API)介绍如何编写一个商品期货动态双向网格策略,并包含关键的资金与持仓风控机制。


一、策略核心逻辑

  1. 双向建仓:以基准价为中心,按照设定的网格间距(如 1%),向下布置买网格(多头开仓),向上布置卖网格(空头开仓)。
  2. 动态平仓:多头持仓在价格上涨达到止盈间距时平仓;空头持仓在价格下跌达到止盈间距时平仓。
  3. 基准价更新:每当触发网格成交并平仓后,以最新成交价更新网格基准价格。
  4. 风控机制
    • 最大持仓限制:限制多头/空头最大持仓手数,防止趋势单边突破时爆仓。
    • 资金利用率风控:实时监控账户保证金占用,超限后暂停开仓。

二、QMT 策略 Python 源码实现

在 QMT 策略编辑器中,需定义 inithandlebar 核心函数。策略编写示例如下:

#coding:gbk
import numpy as np

def init(ContextInfo):
    # 1. 策略基本设置
    ContextInfo.symbol = 'rb2401.SF'  # 交易合约(以螺纹钢为例)
    ContextInfo.set_universe([ContextInfo.symbol])
    ContextInfo.account = '110476'    # 资金账号
    ContextInfo.set_account(ContextInfo.account)
    
    # 2. 网格参数配置
    ContextInfo.grid_ratio = 0.01      # 网格间距 1%
    ContextInfo.order_lots = 1         # 每单交易手数
    ContextInfo.max_pos = 5            # 单向最大持仓手数
    ContextInfo.base_price = 0.0       # 初始网格基准价
    
    # 3. 全局状态控制
    ContextInfo.long_pos = 0           # 多头持仓
    ContextInfo.short_pos = 0          # 空头持仓
    print("【策略初始化】商品期货双向网格策略加载成功")

def handlebar(ContextInfo):
    # 只在最新 Bar 或 Tick 来时运行核心逻辑
    if not ContextInfo.is_last_bar():
        return
    
    # 获取最新行情
    ticks = ContextInfo.get_full_tick([ContextInfo.symbol])
    if ContextInfo.symbol not in ticks:
        return
    
    last_price = ticks[ContextInfo.symbol]['lastPrice']
    
    # 初始化基准价格
    if ContextInfo.base_price == 0.0:
        ContextInfo.base_price = last_price
        print(f"【基准价设定】初始网格基准价: {ContextInfo.base_price}")
        return
    
    # 获取账户资金与持仓风控
    account_info = get_trade_detail_data(ContextInfo.account, 'FUTURE', 'ACCOUNT')
    if account_info:
        available_cash = account_info[0].m_dAvailable
        balance = account_info[0].m_dBalance
        # 风控:保证金占用超过 80% 时停止开仓
        if (balance - available_cash) / balance > 0.8:
            print("【风控警告】保证金占用率过高,暂停开仓")
            return
            
    # 更新持仓数据
    positions = get_trade_detail_data(ContextInfo.account, 'FUTURE', 'POSITION')
    ContextInfo.long_pos = 0
    ContextInfo.short_pos = 0
    for pos in positions:
        if pos.m_strInstrumentID == ContextInfo.symbol.split('.')[0]:
            if pos.m_nDirection == 48: # 多头
                ContextInfo.long_pos = pos.m_nVolume
            elif pos.m_nDirection == 49: # 空头
                ContextInfo.short_pos = pos.m_nVolume

    # 4. 双向网格交易逻辑
    upper_grid = ContextInfo.base_price * (1 + ContextInfo.grid_ratio)
    lower_grid = ContextInfo.base_price * (1 - ContextInfo.grid_ratio)
    
    # ---- 价格突破下轨:触发多头开仓 或 空头止盈 ----
    if last_price <= lower_grid:
        # 空头止盈平仓
        if ContextInfo.short_pos > 0:
            print(f"【平空止盈】最新价 {last_price} <= 下轨 {lower_grid}")
            passorder(8, 1101, ContextInfo.account, ContextInfo.symbol, 5, -1, ContextInfo.order_lots, ContextInfo)
            ContextInfo.base_price = last_price
        # 多头逢低开仓(需受最大持仓限制)
        elif ContextInfo.long_pos < ContextInfo.max_pos:
            print(f"【开多进场】最新价 {last_price} <= 下轨 {lower_grid}")
            passorder(0, 1101, ContextInfo.account, ContextInfo.symbol, 5, -1, ContextInfo.order_lots, ContextInfo)
            ContextInfo.base_price = last_price
            
    # ---- 价格突破上轨:触发空头开仓 或 多头止盈 ----
    elif last_price >= upper_grid:
        # 多头止盈平仓
        if ContextInfo.long_pos > 0:
            print(f"【平多止盈】最新价 {last_price} >= 上轨 {upper_grid}")
            passorder(6, 1101, ContextInfo.account, ContextInfo.symbol, 5, -1, ContextInfo.order_lots, ContextInfo)
            ContextInfo.base_price = last_price
        # 空头逢高开仓(需受最大持仓限制)
        elif ContextInfo.short_pos < ContextInfo.max_pos:
            print(f"【开空进场】最新价 {last_price} >= 上轨 {upper_grid}")
            passorder(3, 1101, ContextInfo.account, ContextInfo.symbol, 5, -1, ContextInfo.order_lots, ContextInfo)
            ContextInfo.base_price = last_price

三、风控与实盘注意事项

  1. 单边趋势风险:网格交易极度害怕单边行情。如果价格出现持续单边上涨或下跌,策略会不断逆势加仓直到达到 max_pos,导致浮亏扩大。建议配合 ATR 指标设置全局止损线。
  2. 合约乘数与保证金:在算资金利用率和手数时,请使用 ContextInfo.get_contract_multiplier(code) 获取合约乘数,精准计算所需的保证金。
  3. 下单选价类型:示例代码中使用最新价(prType=5)下单,实盘中为提高成交率可将 prType 设置为对手价(14)或挂单价(13)。