楼主: zhangxbabc
33 0

[其他] 【QMT】QMT MACD 金叉死叉交易策略 (附 Python 源码) [推广有奖]

  • 0关注
  • 0粉丝

等待验证会员

学前班

80%

还不是VIP/贵宾

-

威望
0
论坛币
0 个
通用积分
0.6664
学术水平
0 点
热心指数
0 点
信用等级
0 点
经验
30 点
帖子
2
精华
0
在线时间
0 小时
注册时间
2018-4-29
最后登录
2018-4-29

楼主
zhangxbabc 发表于 2025-12-3 18:43:13 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币

在 QMT 平台使用 Python 实现 MACD 金叉死叉交易策略

本文将详细介绍如何基于 QMT 量化交易平台,利用 Python 编写一个经典的 MACD 技术指标交易策略。该策略以“金叉买入、死叉卖出”为核心逻辑,结合真实行情数据进行信号判断与交易执行,适合初学者快速掌握量化策略开发流程。

策略核心逻辑解析

本策略依赖于 MACD 指标的三要素:快线(DIF)、慢线(DEA)以及柱状图(MACD 值)。通过监测 DIF 与 DEA 的交叉关系来生成买卖信号。

  • 金叉(买入信号):当 DIF 线由下向上穿越 DEA 线时触发,表示短期趋势强于长期趋势,视为看涨信号。
  • 死叉(卖出信号):当 DIF 线由上向下穿越 DEA 线时触发,意味着上涨动能减弱,作为清仓依据。
talib

交易执行规则

为避免频繁交易和无效信号干扰,策略设置了持仓状态判断机制:

  • 若出现金叉信号且当前未持有仓位,则执行全仓买入操作;
  • 若发生死叉信号且账户中已有持仓,则立即全部卖出,实现止盈或止损。

代码实现结构说明

整个策略分为两个主要函数:init 用于初始化设置,handlebar 负责每根 K 线到来时的处理逻辑。

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

def init(ContextInfo):
    """
    策略启动时仅运行一次,完成参数设定与账户绑定
    """
    # 设置资金账号(请替换为实际账号)
    ContextInfo.accid = '6000000000'
    
    # 指定账户类型:支持 'STOCK' 或 'FUTURE'
    ContextInfo.accountType = 'STOCK'
    
    # 绑定指定账户以便接收成交回报
    ContextInfo.set_account(ContextInfo.accid)
    
    # 定义 MACD 计算参数
    ContextInfo.fast_period = 12   # 快速均线周期
    ContextInfo.slow_period = 26   # 慢速均线周期
    ContextInfo.signal_period = 9  # 信号线平滑周期
    
    print("策略初始化完成,MACD参数: {}, {}, {}".format(
        ContextInfo.fast_period, ContextInfo.slow_period, ContextInfo.signal_period))

def handlebar(ContextInfo):
    """
    每根K线到达时自动调用一次
    """
    # 获取当前主图显示的股票代码与K线周期
    stock_code = ContextInfo.stockcode
    period = ContextInfo.period

    # 1. 获取历史行情数据
    data_len = 100  # 取最近100根K线确保指标计算稳定
    market_data = ContextInfo.get_market_data_ex(
        fields=['close'],
        codes=[stock_code],
        period=period,
        count=data_len,
        dividend_type='front'  # 前复权处理,利于技术分析
    )

    # 数据校验:若获取失败或长度不足则跳过本次处理
    if stock_code not in market_data or len(market_data[stock_code]) < 35:
        return

    # 提取收盘价并转换为 NumPy 数组供 talib 使用
    close_price = market_data[stock_code]['close']
    close_np = np.array(close_price)

    # 2. 计算 MACD 指标值
    diff, dea, macd = talib.MACD(
        close_np,
        fastperiod=ContextInfo.fast_period,
        slowperiod=ContextInfo.slow_period,
        signalperiod=ContextInfo.signal_period
    )

    # 获取最新两根K线的 DIF 和 DEA 数值
    current_diff = diff[-1]    # 当前K线
    current_dea = dea[-1]
    last_diff = diff[-2]       # 上一根K线
    last_dea = dea[-2]

    # 排除无效值(NaN)
    if np.isnan(current_diff) or np.isnan(last_diff):
        return

    # 3. 判断交叉信号
    golden_cross = (last_diff < last_dea) and (current_diff > current_dea)  # 金叉
    death_cross = (last_diff > last_dea) and (current_diff < current_dea)    # 死叉

    # 查询当前持仓情况
    positions = ContextInfo.get_positions()
    has_position = len(positions) > 0

    # 执行交易指令
    if golden_cross and not has_position:
        # 全仓买入
        order_value = ContextInfo.get_cash() * 0.99  # 预留部分资金防误差
        ContextInfo.order_value(stock_code, price=0, value=order_value, side='buy', order_type='market')
        print(f"【买入】在 {stock_code} 触发金叉,执行市价单买入")

    elif death_cross and has_position:
        # 清仓卖出
        for pos in positions:
            if pos['symbol'] == stock_code:
                sell_amount = pos['volume']
                ContextInfo.order_volume(stock_code, price=0, volume=sell_amount, side='sell', order_type='market')
                print(f"【卖出】在 {stock_code} 触发死叉,执行市价单清仓")

总结

该策略完整实现了 MACD 指标驱动的自动化交易流程,涵盖数据获取、指标计算、信号识别与订单执行四大环节。用户可根据自身需求调整参数、优化入场条件或加入风控模块以提升实战表现。

golden_cross = (last_diff < last_dea) and (current_diff > current_dea)

# 死叉判断:上一K线满足 DIF > DEA,当前K线变为 DIF < DEA

death_cross = (last_diff > last_dea) and (current_diff < current_dea)

# 获取当前持仓信息

# 注意:在回测环境中,ContextInfo.get_position() 可能无法使用,建议采用 get_trade_detail_data 方法获取持仓数据

# 为兼容实盘与回测场景,此处通过交易明细进行持仓查询

positions = ContextInfo.get_trade_detail_data(ContextInfo.accid, ContextInfo.accountType, 'POSITION')

current_vol = 0

for pos in positions:

    if pos.m_strInstrumentID == stock_code:

        current_vol = pos.m_nVolume

        break

# 执行交易逻辑

# 获取最新成交价格用于下单操作

last_price = close_price.iloc[-1]

# 仅在K线收盘后执行下单操作,防止盘中信号频繁波动(也可结合 ContextInfo.is_last_bar() 判断)

# 在回测中每根bar都会触发;实盘通常在bar结束或tick级别处理

# --- 买入条件触发 ---

if golden_cross:

    if current_vol == 0:

        print(f"[{ContextInfo.barpos}] {stock_code} 出现金叉信号,准备买入")

        ContextInfo.draw_text(True, last_price, '金叉买入')

        # 下单示例:买入1000股(实际应根据可用资金动态计算)

        # opType=23 表示买入,orderType=1101 代表普通下单,priceType=5 使用最新价

        passorder(23, 1101, ContextInfo.accid, stock_code, 5, -1, 1000, ContextInfo)

# --- 卖出条件触发 ---

elif death_cross:

    if current_vol > 0:

        print(f"[{ContextInfo.barpos}] {stock_code} 出现死叉信号,准备卖出")

        ContextInfo.draw_text(True, last_price, '死叉卖出')

        # 卖出全部当前持仓

        # opType=24 表示卖出操作

        passorder(24, 1101, ContextInfo.accid, stock_code, 5, -1, current_vol, ContextInfo)

# (可选)在副图区域绘制MACD相关指标,便于回测分析

ContextInfo.paint('DIFF', current_diff, -1, 0, 'white')

ContextInfo.paint('DEA', current_dea, -1, 0, 'yellow')

# 绘制柱状图(MACD柱)

macd_color = 'red' if macd[-1] > 0 else 'green'

ContextInfo.paint('MACD', macd[-1] * 2, -1, 42, macd_color) # 国内软件习惯将 (diff-dea) 的值乘以2显示

使用步骤说明

  • 创建策略:打开 QMT 策略编辑器,新建一个 Python 类型的策略文件。
  • 粘贴代码:将上述完整策略代码复制到编辑器中。
  • 配置账号信息

    定位到相关函数中的参数设置部分

    ContextInfo.accid = '6000000000'
    ,找到占位符
    '6000000000'
    ,将其替换为您实际使用的资金账户号码。
    init

  • 补充历史数据

    进入 QMT 菜单栏,点击【数据管理】→【补充数据】,下载所需股票的历史日线或分钟线数据,以支持回测或实盘运行。

  • 运行或回测策略
    • 回测模式:点击编辑器上方“回测”按钮,设定时间范围、比较基准和交易费率后开始测试。
    • 实盘/模拟交易:可在行情图表中加载该策略,或通过“模型交易”模块启动运行。

核心代码要点解析

get_market_data_ex
:推荐使用此接口获取行情数据。本例中采用前复权模式
dividend_type='front'
,原因是技术指标如 MACD 在未复权情况下会因除权除息产生数据断层,影响信号准确性。

talib.MACD
:QMT 平台内置了高效的
talib
计算库,适用于快速生成各类技术指标。需要注意的是,
talib
返回的
macd
序列一般为
diff - dea
格式,开发者需了解其输出结构以便正确引用。

国内常用的看盘工具(例如同花顺、通达信)所展示的MACD柱状图一般为

(diff - dea) * 2

因此,在绘图过程中,我对其进行了相应的

* 2

处理,以保证显示效果的一致性。

passorder
:该函数是QMT系统中最为核心的下单指令模块。

  • 23
    :用于执行买入操作;
  • 24
    :用于执行卖出操作;
  • 1101
    :表示按股数进行交易,适用于单账户、单只股票的委托下单模式;
  • 5
    :意味着采用最新价格成交,在回测环境中通常使用K线的收盘价,在实盘中则依据最新的Tick数据进行撮合。

常见问题解答(Q&A)

Q: 回测为何没有产生任何交易记录?
A: 可能原因如下:
1. 请确认是否已成功下载所需的历史行情数据。
2. 检查

ContextInfo.accid

参数是否配置正确。即使在回测模式下使用的是虚拟账户,程序中获取持仓信息仍依赖于指定的账号ID。

Q: 如何修改MACD的技术参数?
A: 只需调整

init

函数内部的

ContextInfo.fast_period

等相关变量即可实现参数自定义。

Q: 实盘运行时如何减少信号闪烁问题?
A: 上述策略代码会在

handlebar

环境中持续运行,而该值会随着最新Tick数据实时更新。为防止在K线尚未结束时就触发交易(即出现信号闪烁),建议结合

ContextInfo.is_last_bar()

与时间判断逻辑,或设定仅在K线即将收尾时刻(如14:59:50)才发出订单,从而提升信号稳定性。

二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:python 交易策略 MACD ACD Mac

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注cda
拉您进交流群
GMT+8, 2025-12-5 20:25