🚀 AI 一键生成 qmt 策略代码

如何在 QMT 平台编写一个简单的期货日内交易策略?

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

问题描述

请编写一个期货交易策略,在满足某个条件时买入开仓,在另一个条件满足时卖出平仓。

解决方案

这是一个基于 QMT 平台的期货交易策略示例。

为了演示“满足条件买入开仓,满足另一条件卖出平仓”的逻辑,我编写了一个经典的双均线策略(Dual Moving Average Crossover)

策略逻辑:

  1. 买入开仓(做多):当短期均线(例如5日线)上穿长期均线(例如10日线),且当前无持仓时,买入开仓。
  2. 卖出平仓(平多):当短期均线下穿长期均线,且当前有多头持仓时,卖出平仓。

注意: 代码中使用了 sell_close_tdayfirst 函数,表示平仓时优先平今仓(符合国内期货交易所通常的规则)。

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

def init(ContextInfo):
    """
    初始化函数,策略启动时执行一次
    """
    # 1. 设置资金账号 (请替换为您真实的期货资金账号)
    ContextInfo.accID = 'YOUR_ACCOUNT_ID' 
    ContextInfo.set_account(ContextInfo.accID)
    
    # 2. 设置交易标的 (此处以沪深300股指期货主力合约为例)
    ContextInfo.target = 'IF00.IF' 
    
    # 3. 设置均线参数
    ContextInfo.short_period = 5   # 短期均线周期
    ContextInfo.long_period = 10   # 长期均线周期
    
    # 4. 设定运行周期 (例如日线 '1d', 分钟线 '1m')
    # 注意:实际运行时,周期通常由界面主图周期决定,这里仅作逻辑参考
    
    print("策略初始化完成")

def handlebar(ContextInfo):
    """
    K线处理函数,每根K线或每个Tick执行一次
    """
    # 获取当前K线索引
    index = ContextInfo.barpos
    
    # 如果K线数量不足以计算长期均线,直接返回
    if index < ContextInfo.long_period:
        return

    # 1. 获取历史行情数据 (收盘价)
    # 获取过去 long_period + 2 根K线的数据,确保有足够数据计算
    data = ContextInfo.get_market_data(
        ['close'], 
        stock_code=[ContextInfo.target], 
        count=ContextInfo.long_period + 2, 
        period=ContextInfo.period
    )
    
    # 检查数据是否获取成功
    if data is None or len(data) == 0:
        return
        
    # 提取收盘价序列 (pandas Series)
    close_series = data[ContextInfo.target]['close']
    
    # 2. 计算均线
    ma_short = close_series.rolling(window=ContextInfo.short_period).mean().iloc[-1]
    ma_long = close_series.rolling(window=ContextInfo.long_period).mean().iloc[-1]
    
    # 获取上一根K线的均线值(用于判断交叉)
    prev_ma_short = close_series.rolling(window=ContextInfo.short_period).mean().iloc[-2]
    prev_ma_long = close_series.rolling(window=ContextInfo.long_period).mean().iloc[-2]

    # 3. 获取当前持仓状态
    position = get_position(ContextInfo.target, ContextInfo.accID)
    
    # 4. 交易逻辑判断
    
    # --- 金叉:短线上穿长线 -> 买入开仓 ---
    # 条件:当前短线>长线 且 上一时刻短线<=长线 且 当前无多单
    if ma_short > ma_long and prev_ma_short <= prev_ma_long and position == 0:
        print(f"产生买入信号: 短期均线({ma_short:.2f}) 上穿 长期均线({ma_long:.2f})")
        
        # 下单:买入开仓,数量1手,使用最新价报价
        # 参数说明: buy_open(标的, 数量, 报价类型, 价格, ContextInfo, 账号)
        buy_open(ContextInfo.target, 1, "LATEST", 0, ContextInfo, ContextInfo.accID)
        
    # --- 死叉:短线下穿长线 -> 卖出平仓 ---
    # 条件:当前短线<长线 且 上一时刻短线>=长线 且 当前有多单
    elif ma_short < ma_long and prev_ma_short >= prev_ma_long and position > 0:
        print(f"产生平仓信号: 短期均线({ma_short:.2f}) 下穿 长期均线({ma_long:.2f})")
        
        # 下单:卖出平仓 (平今优先),数量1手
        # 参数说明: sell_close_tdayfirst(标的, 数量, 报价类型, 价格, ContextInfo, 账号)
        sell_close_tdayfirst(ContextInfo.target, 1, "LATEST", 0, ContextInfo, ContextInfo.accID)

    # 5. 在图表上画线 (可选,方便回测观察)
    ContextInfo.paint('MA_Short', ma_short, -1, 0)
    ContextInfo.paint('MA_Long', ma_long, -1, 0)

def get_position(stock_code, account_id):
    """
    辅助函数:获取指定合约的多头持仓数量
    """
    # 获取持仓列表
    positions = get_trade_detail_data(account_id, 'future', 'position')
    
    for pos in positions:
        # 找到对应合约
        if pos.m_strInstrumentID == stock_code:
            # 区分多空方向 (期货中 48=多头, 49=空头)
            # 这里只演示做多逻辑,所以只返回多头持仓
            if pos.m_nDirection == 48: 
                return pos.m_nVolume
                
    return 0

代码关键点说明:

  1. 编码格式:第一行 # -*- coding: gbk -*- 是必须的,否则 QMT 可能会出现中文乱码或报错。
  2. init 函数
    • 你需要将 'YOUR_ACCOUNT_ID' 替换为你实际的期货资金账号。
    • ContextInfo.target 设置为你想要交易的合约代码(如 IF00.IF 代表股指期货主力)。
  3. handlebar 函数
    • 这是策略的核心循环,随行情驱动。
    • 使用 get_market_data 获取历史数据并计算均线。
    • 通过比较当前均线和上一时刻均线来判断“金叉”和“死叉”。
  4. 交易函数
    • buy_open: 买入开仓。
    • sell_close_tdayfirst: 卖出平仓。期货交易中区分“平今”和“平昨”,此函数会自动优先平掉今日新开的仓位,如果今日无仓则平昨日老仓,是比较通用的平仓方式。
  5. get_position 辅助函数
    • QMT 的 ContextInfo 对象本身不直接存储简单的持仓数字,需要调用 get_trade_detail_data 遍历持仓列表来查询当前合约的持仓量,防止重复开仓。

如何运行:

  1. 在 QMT 界面进入“模型研究”或“策略编辑器”。
  2. 新建一个 Python 策略。
  3. 将上述代码复制进去。
  4. 修改账号 ID。
  5. 点击“编译”检查无误后,可以在回测模式下测试,或在实盘模式下运行(请务必先在模拟盘测试)。