🚀 AI 一键生成 qmt 策略代码

日线定方向、分钟线找买点:多周期共振策略源码

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

问题描述

如何实现日线和分钟线共振的交易策略?

解决方案

实现日线和分钟线共振(Multi-timeframe Resonance)的交易策略,核心逻辑是**“大周期定方向,小周期找买点”**。

策略逻辑设计

  1. 大周期(日线):用于判断主要趋势。
    • 指标:20日均线(MA20)。
    • 逻辑:当日线收盘价 > 日线MA20时,判定为多头趋势,允许做多;否则禁止开仓或清仓。
  2. 小周期(5分钟线):用于寻找具体的进场和出场信号。
    • 指标:5周期均线(MA5)和 10周期均线(MA10)。
    • 买入信号:日线处于多头趋势 5分钟线出现金叉(MA5上穿MA10)。
    • 卖出信号:5分钟线出现死叉(MA5下穿MA10)。
  3. 运行频率:策略应挂载在 5分钟 周期上运行,以便及时捕捉分钟级别的信号。

QMT 策略代码实现

以下是完整的 Python 策略代码。请在 QMT 的策略编辑器中新建一个 Python 策略,将代码复制进去。

注意

  1. 请将 ContextInfo.account_id 替换为您真实的资金账号。
  2. 运行时请选择 5分钟 周期作为主图周期。
# -*- coding: gbk -*-
import pandas as pd
import numpy as np

def init(ContextInfo):
    """
    初始化函数,设定策略参数和变量
    """
    # 1. 设置资金账号 (请修改为您自己的账号)
    ContextInfo.account_id = '6000000000' 
    ContextInfo.account_type = 'STOCK' # 股票账号
    ContextInfo.set_account(ContextInfo.account_id)
    
    # 2. 设置股票池 (示例:平安银行)
    ContextInfo.stock_code = '000001.SZ'
    ContextInfo.set_universe([ContextInfo.stock_code])
    
    # 3. 策略参数设置
    # 日线参数
    ContextInfo.day_period = '1d'
    ContextInfo.day_ma_len = 20      # 日线趋势均线
    
    # 分钟线参数 (主图运行周期建议设为 5m)
    ContextInfo.min_period = '5m'    # 策略运行周期
    ContextInfo.min_ma_fast = 5      # 分钟快线
    ContextInfo.min_ma_slow = 10     # 分钟慢线
    
    # 交易数量
    ContextInfo.trade_vol = 100      # 每次交易100股

def get_position(ContextInfo, stock_code):
    """
    获取当前持仓数量的辅助函数
    """
    try:
        # 获取持仓对象列表
        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
    except Exception as e:
        print("获取持仓失败: ", e)
    return 0

def handlebar(ContextInfo):
    """
    K线运行逻辑,每根K线(或Tick)调用一次
    """
    # 获取当前正在处理的股票代码
    stock = ContextInfo.stock_code
    
    # ----------------------------------------------------------------
    # 第一步:获取日线数据,判断大趋势 (大周期)
    # ----------------------------------------------------------------
    # 获取足够计算MA20的日线数据
    # 注意:dividend_type='front' 为前复权,确保价格连续
    day_data_map = ContextInfo.get_market_data_ex(
        ['close'], 
        [stock], 
        period=ContextInfo.day_period, 
        count=ContextInfo.day_ma_len + 5, 
        dividend_type='front', 
        fill_data=True, 
        subscribe=True
    )
    
    if stock not in day_data_map:
        return # 数据未准备好
        
    df_day = day_data_map[stock]
    if len(df_day) < ContextInfo.day_ma_len:
        return # 数据长度不足
    
    # 计算日线 MA20
    day_ma = df_day['close'].rolling(window=ContextInfo.day_ma_len).mean()
    
    # 获取最新的日线收盘价和均线值
    # 注意:盘中运行时,iloc[-1] 是包含当天实时数据的(动态复盘)
    current_day_close = df_day['close'].iloc[-1]
    current_day_ma = day_ma.iloc[-1]
    
    # 判断日线趋势:收盘价 > MA20 为多头趋势
    is_day_bullish = current_day_close > current_day_ma

    # ----------------------------------------------------------------
    # 第二步:获取分钟线数据,寻找买卖点 (小周期)
    # ----------------------------------------------------------------
    # 获取分钟线数据
    min_data_map = ContextInfo.get_market_data_ex(
        ['close'], 
        [stock], 
        period=ContextInfo.min_period, 
        count=ContextInfo.min_ma_slow + 5, 
        dividend_type='front', 
        fill_data=True, 
        subscribe=True
    )
    
    if stock not in min_data_map:
        return
        
    df_min = min_data_map[stock]
    if len(df_min) < ContextInfo.min_ma_slow:
        return

    # 计算分钟线均线
    min_ma_fast = df_min['close'].rolling(window=ContextInfo.min_ma_fast).mean()
    min_ma_slow = df_min['close'].rolling(window=ContextInfo.min_ma_slow).mean()
    
    # 获取当前和上一根K线的均线值,用于判断交叉
    curr_fast = min_ma_fast.iloc[-1]
    curr_slow = min_ma_slow.iloc[-1]
    prev_fast = min_ma_fast.iloc[-2]
    prev_slow = min_ma_slow.iloc[-2]
    
    # 判断金叉:快线上穿慢线
    is_golden_cross = (prev_fast <= prev_slow) and (curr_fast > curr_slow)
    
    # 判断死叉:快线下穿慢线
    is_death_cross = (prev_fast >= prev_slow) and (curr_fast < curr_slow)

    # ----------------------------------------------------------------
    # 第三步:交易执行逻辑 (共振判断)
    # ----------------------------------------------------------------
    
    # 获取当前持仓
    current_pos = get_position(ContextInfo, stock)
    
    # 1. 买入逻辑:日线多头趋势 + 分钟线金叉 + 当前无持仓
    if is_day_bullish and is_golden_cross and current_pos == 0:
        print(f"【买入信号】{stock} 日线趋势向上,5分钟金叉。价格: {df_min['close'].iloc[-1]}")
        # 23: 买入, 1101: 单股单账号, 5: 最新价
        passorder(23, 1101, ContextInfo.account_id, stock, 5, -1, ContextInfo.trade_vol, ContextInfo)
    
    # 2. 卖出逻辑:分钟线死叉 + 当前有持仓 (止盈/止损)
    # 注:这里只看小周期死叉离场,也可以加上日线转空的条件
    elif is_death_cross and current_pos > 0:
        print(f"【卖出信号】{stock} 5分钟死叉。价格: {df_min['close'].iloc[-1]}")
        # 24: 卖出, 1101: 单股单账号, 5: 最新价
        passorder(24, 1101, ContextInfo.account_id, stock, 5, -1, current_pos, ContextInfo)

    # 调试信息输出 (可选)
    if ContextInfo.is_last_bar():
        print(f"监控中: {stock} | 日线多头: {is_day_bullish} | 5分快线: {curr_fast:.2f} | 5分慢线: {curr_slow:.2f}")

代码关键点解析

  1. 跨周期数据获取 (get_market_data_ex)

    • QMT 的 get_market_data_ex 接口非常强大,允许你在同一个策略中请求不同周期的数据。
    • 代码中分别请求了 period=ContextInfo.day_period ('1d') 和 period=ContextInfo.min_period ('5m') 的数据。
    • 注意:在分钟周期上运行策略时,获取到的日线数据最后一行通常是当日截至目前的动态数据。这符合“共振”的逻辑,即参考当天的实时趋势。
  2. 共振逻辑实现

    • 变量 is_day_bullish 锁定了大方向。只有当它为 True 时,代码才会进入买入判断逻辑。
    • 变量 is_golden_cross 提供了精确的进场时机。
    • 两者结合 if is_day_bullish and is_golden_cross: 实现了共振。
  3. 交易执行 (passorder)

    • 使用了标准的 passorder 函数。
    • opType=23 代表股票买入,24 代表股票卖出。
    • prType=5 代表使用最新价下单(实盘中可能需要考虑滑点或使用对手价 prType=14)。
  4. 持仓检查

    • 为了防止重复开仓,代码中增加了一个 get_position 辅助函数,通过 get_trade_detail_data 接口查询当前账户的实际持仓。

如何回测与运行

  1. 回测设置
    • 在策略编辑器右侧的“回测参数”中,设置好开始和结束时间。
    • 主图周期:必须选择 5分钟 (或 1分钟/15分钟,取决于你想捕捉的小周期级别)。如果选日线,分钟线的逻辑将无法正常触发。
    • 基准:选择沪深300或其他。
  2. 数据下载
    • 确保在“数据管理”中下载了对应股票的 日线5分钟线 历史数据。
  3. 实盘/模拟
    • 点击“运行”即可启动。确保账号已登录且 ContextInfo.account_id 填写正确。

Q&A

Q: 为什么不在日线周期上运行这个策略?
A: 如果在日线周期上运行,handlebar 每天只会在收盘时调用一次。这样你就无法捕捉到盘中 5 分钟级别的金叉买点,失去了“共振”中利用小周期优化进场点的意义。

Q: 如何让日线趋势判断更稳定,不随盘中价格波动而变化?
A: 当前代码使用的是当日实时价格与 MA20 比较。如果你希望趋势判断更保守,可以使用昨日的收盘数据。修改代码如下:

# 使用倒数第二根K线(昨日)的数据
prev_day_close = df_day['close'].iloc[-2]
prev_day_ma = day_ma.iloc[-2]
is_day_bullish = prev_day_close > prev_day_ma

Q: get_market_data_exget_market_data 有什么区别?
A: get_market_data_ex 是 QMT 推荐的新版接口,返回的数据结构更清晰(字典包含 DataFrame),且支持更丰富的参数(如复权方式、停牌填充等),在处理多股、多周期数据时更稳定。