🚀 AI 一键生成 qmt 策略代码

如何用 Python 编写一个日内均值回归交易策略?

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

问题描述

请帮我写一个日内均值回归策略,当价格低于移动平均线一定幅度时买入,高于时卖出。

解决方案

这是一个基于 QMT 平台的 日内均值回归策略

策略逻辑

  1. 核心思想:价格总是围绕移动平均线波动。当价格偏离均线过大时,倾向于回归均值。
  2. 买入条件:当收盘价 低于 移动平均线一定幅度(例如 1%)时,认为超卖,执行买入。
  3. 卖出条件:当收盘价 高于 移动平均线一定幅度(例如 1%)时,认为超买,执行卖出(平仓)。
  4. 周期:策略运行在分钟线(如 1分钟、3分钟或 5分钟)上,以捕捉日内波动。

策略代码

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

def init(ContextInfo):
    """
    初始化函数,设定策略参数和账户
    """
    # 1. 设置策略参数
    ContextInfo.stock_code = '600000.SH'  # 标的股票:浦发银行
    ContextInfo.period = 20               # 均线周期:20个bar
    ContextInfo.threshold = 0.01          # 偏离幅度阈值:1% (0.01)
    ContextInfo.trade_amount = 1000       # 每次交易数量(股)
    ContextInfo.account_id = '6000000000' # 请替换为您的资金账号
    ContextInfo.account_type = 'STOCK'    # 账号类型:STOCK-股票,FUTURE-期货
    
    # 2. 设置股票池和周期
    ContextInfo.set_universe([ContextInfo.stock_code])
    ContextInfo.set_account(ContextInfo.account_id)
    
    # 3. 辅助变量
    print("策略初始化完成:日内均值回归策略")

def get_position(ContextInfo, stock_code):
    """
    辅助函数:获取当前持仓数量
    """
    # 获取持仓对象列表
    positions = get_trade_detail_data(ContextInfo.account_id, ContextInfo.account_type, 'POSITION')
    
    for pos in positions:
        if pos.m_strInstrumentID + '.' + pos.m_strExchangeID == stock_code:
            return pos.m_nVolume
    return 0

def handlebar(ContextInfo):
    """
    K线处理函数,每根K线执行一次
    """
    # 获取当前正在处理的K线索引
    index = ContextInfo.barpos
    stock = ContextInfo.stock_code
    
    # 1. 获取历史行情数据
    # 获取过去 period + 5 根K线的数据,确保计算均线有足够数据
    # period='1m' 代表取1分钟线,可根据实际运行周期调整
    data_dict = ContextInfo.get_market_data_ex(
        ['close'], 
        [stock], 
        period='follow', # 跟随主图周期
        count=ContextInfo.period + 5,
        dividend_type='front' # 前复权
    )
    
    if stock not in data_dict:
        return
        
    df = data_dict[stock]
    
    # 数据不足时不计算
    if len(df) < ContextInfo.period:
        return

    # 2. 计算技术指标
    # 计算移动平均线 (MA)
    ma = df['close'].rolling(window=ContextInfo.period).mean()
    
    # 获取最新一根K线的收盘价和均线值
    current_price = df['close'].iloc[-1]
    current_ma = ma.iloc[-1]
    
    # 确保均线有效
    if np.isnan(current_ma):
        return

    # 计算上下轨
    upper_band = current_ma * (1 + ContextInfo.threshold) # 上轨
    lower_band = current_ma * (1 - ContextInfo.threshold) # 下轨

    # 3. 获取当前持仓
    current_pos = get_position(ContextInfo, stock)

    # 4. 交易逻辑
    # 信号 1: 价格低于下轨 -> 买入
    if current_price < lower_band:
        if current_pos == 0: # 如果当前空仓
            print(f"时间: {df.index[-1]}, 价格: {current_price:.2f} 低于下轨 {lower_band:.2f}, 触发买入")
            # 下单:买入
            # opType=23(买入), orderType=1101(单股单账号普通下单)
            passorder(23, 1101, ContextInfo.account_id, stock, 5, -1, ContextInfo.trade_amount, ContextInfo)
    
    # 信号 2: 价格高于上轨 -> 卖出
    elif current_price > upper_band:
        if current_pos > 0: # 如果当前有持仓
            # 检查可用持仓(如果是T+1市场,需要额外判断可用持仓,此处简化为有持仓即卖出)
            print(f"时间: {df.index[-1]}, 价格: {current_price:.2f} 高于上轨 {upper_band:.2f}, 触发卖出")
            # 下单:卖出
            # opType=24(卖出)
            passorder(24, 1101, ContextInfo.account_id, stock, 5, -1, current_pos, ContextInfo)

    # (可选) 绘制指标到图表,方便回测观察
    ContextInfo.paint('MA', current_ma, -1, 0, 'yellow')
    ContextInfo.paint('Upper', upper_band, -1, 0, 'red')
    ContextInfo.paint('Lower', lower_band, -1, 0, 'green')

代码关键点解析

  1. 数据获取 (get_market_data_ex):

    • 使用了 period='follow',这意味着策略会根据你在 QMT 界面上选择的周期(如 1分钟、5分钟)来自动获取对应的数据。
    • 获取了 close 收盘价,并使用 Pandas 的 rolling().mean() 计算移动平均线。
  2. 交易信号:

    • 下轨 (Lower Band) = MA * (1 - 0.01)。当价格跌破下轨,意味着价格短期超跌,预期会反弹,因此买入。
    • 上轨 (Upper Band) = MA * (1 + 0.01)。当价格突破上轨,意味着价格短期超涨,预期会回调,因此卖出。
  3. 下单函数 (passorder):

    • opType=23 代表股票买入。
    • opType=24 代表股票卖出。
    • prType=5 代表使用最新价下单(price 参数填 -1 即可)。
    • 注意:在实盘中,请务必将 ContextInfo.account_id 替换为您真实的资金账号。
  4. 持仓查询 (get_position):

    • 通过 get_trade_detail_data 获取当前账户的持仓列表,遍历查找目标股票的持仓量,防止重复买入或卖空(A股不支持直接做空)。

如何运行

  1. 打开 QMT 客户端,进入【模型研究】或【策略交易】。
  2. 新建一个 Python 策略,将上述代码粘贴进去。
  3. 修改 ContextInfo.account_id 为你的实际账号。
  4. 在右侧设置中,选择运行周期(例如 1分钟5分钟)。
  5. 点击【运行】或【回测】。

Q&A

Q: 如何修改均线的长度?
A: 修改 init 函数中的 ContextInfo.period = 20,将 20 改为你想要的数字(如 60)。

Q: 如何调整买卖的敏感度?
A: 修改 init 函数中的 ContextInfo.threshold = 0.01

  • 调大(如 0.02):交易次数变少,只有价格波动很大时才交易。
  • 调小(如 0.005):交易次数变多,捕捉微小的波动。

Q: 这个策略可以用于期货吗?
A: 可以,但需要修改以下几点:

  1. ContextInfo.account_type 改为 'FUTURE'
  2. passorderopType 需要修改:期货开多是 0,平多是 6(优先平今)或 7(优先平昨);开空是 3,平空是 89
  3. 逻辑上需要增加做空逻辑(高于上轨开空,回归均值平空)。