MQL5 Cookbook: 处理 TradeTransaction 事件·进阶篇
⚙️

MQL5 Cookbook: 处理 TradeTransaction 事件·进阶篇

(2/3)· 市价单到限价单的五个触发阶段,多数 EA 作者只盯 OnTrade 漏掉了一半账户信号

实战向进阶 第 2/3 篇
接上篇,我们继续深挖交易事件的内核。不少老手写了几年 EA,仍以为开仓只触发一次回调,结果在订单状态同步上反复踩坑。其实一个市价开仓会连推五次 OnTradeTransaction,错过任何一次都可能让风控逻辑慢半拍。

从日志看清挂单到成交的全过程

在 MT5 的 EA 调试里,TradeProcessor 这类日志前缀能直接还原一笔 EURUSD H1 订单从发单到成交的链路。上面这段记录里,17:41:12.280 先打出挂单参数:交易品种 EURUSD、成交量 0.11 手、过期方式 ORDER_TIME_GTC(即长期有效单),且当时 Take Profit 与 Stop Limit 触发价都显示为 0.0000,说明这一刻止盈未设、触发价留空。

  • 分钟后,17:52:36.722 出现 Transaction 分割线,订单 22535869 状态变为 ORDER_STATE_STARTED,成交类型 DEAL_TYPE_BUY,成交价 1.3137,SL/TP 依旧是 0.0000。也就是说,这笔 0.11 手的欧元买单在约 11 分钟窗口内由挂单转活跃并市价买入,且全程未带止损止盈。

外汇与贵金属波动剧烈,这种零防护的 0.11 手裸单在 EURUSD 上若遇跳空,可能瞬间扩大浮亏。开 MT5 把专家日志调成包含 Trade 标签,就能复现同样的字段顺序,用来核对自己的下单模块有没有漏填止损。

◍ 从日志看懂挂单撤销与市价成交

在 MT5 的 EA 调试里,TradeProcessor 这类日志能直接暴露订单生命周期。上面这段 EURUSD H1 的回放里,17:52:36.722 先打出一条 TRADE_TRANSACTION_ORDER_DELETE,说明某个挂单被删掉了;同一毫秒里还能看到 ORDER_TIME_GTC 与过期时间 1970.01.01 00:00,意味着该单设为永久有效但未填具体到期。

  • 分钟后的 17:57:32.234,日志切换到一笔实成交:ORDER_STATE_FILLED 配合 DEAL_TYPE_BUY、ORDER_TYPE_BUY,成交价 1.3137,订单号 22535869,成交量 0.11 手。注意 SL 与 TP 都是 0.0000,代表这一笔进场没带止损止盈。

外汇和贵金属杠杆高,0 止损的市价单遇到跳空可能瞬间扩大浮亏。把这段日志复制到 MT5 Experts 或 Journal 标签对照看,你能立刻分辨出哪次是删单、哪次是真进场,不必等账户余额说话。

「从日志看挂单到成交的字段映射」

在 MT5 的 EA 调试里,TradeProcessor 这类日志能把一笔 EURUSD H1 的订单生命周期摊开给你看。上面这段记录里,17:57:32 先打出挂单属性:过期时间停在 1970.01.01 00:00,过期类型是 ORDER_TIME_GTC,说明这是一枚不下架的待成交单。 两分钟后(17:59:40.718)日志切到 Transaction 块,关键信息落地:成交票号 15258202、DEAL_TYPE_BUY、关联订单票号 22535869、ORDER_STATE_STARTED 且 ORDER_TYPE_BUY,成交价 1.3137。注意此时 SL/TP 都是 0.0000,也就是这单进场时没带止损止盈。 别把 1970.01.01 当成真过期日 那个零值时间只是 MQL5 里 datetime 未初始化的默认显示,GTC 单本来就不依赖过期字段。若你写代码用 OrderGetInteger(ORDER_TIME_EXPIRATION) 去判断生命周期,得先排除零值,否则容易误判为已失效。 让小布替你跑这套 开 MT5 随便挂一单 EURUSD 的 GTC 买单,用 Experts 日志过滤 TradeProcessor 字样,对照上面字段确认 SL/TP 为零时的输出结构,比你读文档直观得多。外汇与贵金属杠杆交易风险高,日志验证仅用于理解机制,不代表任何方向倾向。

从日志揪出挂单的有效期与成交动作

在 MT5 的 Experts 日志里,TradeProcessor 这类 EA 会打印每笔订单的关键字段。上面这段 EURUSD H1 的片段里,同一毫秒(17:59:40.718)连续出现三条记录,分别对应订单属性、成交事件与手数。 第一行的 QI 标记显示 Order expiration type: ORDER_TIME_GTC,说明该挂单为长期有效单,不会被平台在当日收盘强制取消。外汇与贵金属交易带高杠杆,GTC 单若忘记撤除,可能在跳空时被动成交。 被高亮的那行 CK 给出 Type of the trade transaction: TRADE_TRANSACTION_DEAL_ADD,这是成交追加信号——意味着一笔市价或挂单转成交已写入交易账户,而非仅仅下到池子里。 RQ 行里的 Volume in lots: 0.11 是实际成交手数。把这三行连起来看:一个 0.11 手的 GTC 类订单在此时刻完成了 DEAL_ADD。开 MT5 接上自己的 EA,搜 CK+DEAL_ADD 就能快速统计真实成交频率,不必等回测报告。

MQL5 / C++
QI      class="num">0    class="num">17:class="num">59:class="num">40.718    TradeProcessor(EURUSD,H1)      Order expiration type: ORDER_TIME_GTC
CK      class="num">0    class="num">17:class="num">59:class="num">40.718    TradeProcessor(EURUSD,H1)      Type of the trade transaction: TRADE_TRANSACTION_DEAL_ADD
RQ      class="num">0    class="num">17:class="num">59:class="num">40.718    TradeProcessor(EURUSD,H1)      Volume in lots: class="num">0.11

◍ 限价单的事务触发次数与调试路径

限价订单和仓位不同,每次操作触发的 OnTradeTransaction 调用次数更杂:下单纯三次,修改两次,删除或成交各四次。这种非对称节奏意味着你不能用一个固定规划去覆盖全部限价单生命周期,得按动作拆开看。 在 MT5 任意图表用调试模式挂 EA,下限价单的第一跳是 TRADE_TRANSACTION_REQUEST,即请求连接;第二跳 ORDER_ADDED 把单子塞进已开列表;第三跳 ORDER_UPDATE 刷新状态,订单状态字段会变成 ORDER_STATE_PLACED。日志里盯紧 'Transaction' 块即可,不用全量读。 删除限价单时处理器会被喊四次,触发成交也是四种事务组合。下面这段是 EURUSD 下限价买单时打印的 Transaction 原始条目,注意 ORDER_STATE_STARTED 与 TRADE_TRANSACTION_REQUEST 同帧出现,价格/SL/TP 均为 0.0000 说明此刻只是请求态。 外汇与贵金属限价单受滑点、流动性影响,实际触发次数可能因经纪商执行差异而偏移,建议自行跑一遍验证。

MQL5 / C++
IO        class="num">0     class="num">18:class="num">13:class="num">33.195    TradeProcessor(EURUSD,H1)    ---===Transaction===---
NK        class="num">0     class="num">18:class="num">13:class="num">33.195    TradeProcessor(EURUSD,H1)    Ticket of the deal: class="num">0
RR        class="num">0     class="num">18:class="num">13:class="num">33.195    TradeProcessor(EURUSD,H1)    Type of the deal: DEAL_TYPE_BUY
DE        class="num">0     class="num">18:class="num">13:class="num">33.195    TradeProcessor(EURUSD,H1)    Ticket of the order: class="num">0
JS        class="num">0     class="num">18:class="num">13:class="num">33.195    TradeProcessor(EURUSD,H1)    Status of the order: ORDER_STATE_STARTED
JN        class="num">0     class="num">18:class="num">13:class="num">33.195    TradeProcessor(EURUSD,H1)    Type of the order: ORDER_TYPE_BUY
FD        class="num">0     class="num">18:class="num">13:class="num">33.195    TradeProcessor(EURUSD,H1)    Price: class="num">0.0000
FN        class="num">0     class="num">18:class="num">13:class="num">33.195    TradeProcessor(EURUSD,H1)    Level of Stop Loss: class="num">0.0000
HF        class="num">0     class="num">18:class="num">13:class="num">33.195    TradeProcessor(EURUSD,H1)    Level of Take Profit: class="num">0.0000
FQ        class="num">0     class="num">18:class="num">13:class="num">33.195    TradeProcessor(EURUSD,H1)    Price that triggers the Stop Limit order: class="num">0.0000
RR        class="num">0     class="num">18:class="num">13:class="num">33.195    TradeProcessor(EURUSD,H1)    Trade symbol:
HD        class="num">0     class="num">18:class="num">13:class="num">33.195    TradeProcessor(EURUSD,H1)    Pending order expiration time: class="num">1970.01.class="num">01 class="num">00:class="num">00
GS        class="num">0     class="num">18:class="num">13:class="num">33.195    TradeProcessor(EURUSD,H1)    Order expiration type: ORDER_TIME_GTC
DN        class="num">0     class="num">18:class="num">13:class="num">33.195    TradeProcessor(EURUSD,H1)    Type of the trade transaction: TRADE_TRANSACTION_REQUEST

「从日志抓一笔挂单请求的字段真相」

上面这段是 EA 在 EURUSD 的 H1 图表上打印的一笔挂单请求日志,时间截到 18:13:33.195,同一毫秒内把请求结构全部吐出。注意 EA 自身跑在 EURUSD 上,但 Trade symbol 字段写的是 GBPUSD,这种跨品种下单在日志里最容易看漏。 关键字段里,Type of the trade operation 是 TRADE_ACTION_PENDING,说明这不是市价单而是挂单动作;Type of the order 为 ORDER_TYPE_BUY_LIMIT,价格挂在 1.6500。Stop Loss、Take Profit、StopLimit 全是 0.0000,意味着这笔挂单没带任何防护位,外汇和贵金属这种高波动品种里裸挂单风险偏高,价格反向扫过可能直接吃满波动。 Order expiration type 是 ORDER_TIME_GTC,过期时间显示 1970.01.01 00:00,也就是经典的零值代表永久有效。Magic number 为 0、Deviation 为 0、Volume in lots 为 0.00——手数零说明这大概率只是结构打印而非真实发单,开 MT5 把 EA 日志级别调出来对照自己的请求体,能立刻看出哪行字段被填错。

把事务日志交给小布盯盘
这些诊断小布盯盘的 AIGC 已内置,打开对应品种页即可看到每次 TradeTransaction 的类型分布与异常单号,你专注决策而非翻日志。

常见问题

OnTrade 在交易账户状态整体变动后触发一次,偏结果层;OnTradeTransaction 在事务每个阶段触发,能拿到订单号与事务类型,适合做细粒度追踪。
因为开仓经历请求完成、订单列入、订单删除、转入历史、成交写入等阶段,每个阶段都是独立事务,倾向触发五次而非合并。
可以,小布盯盘的 AIGC 模块会聚合账户事件流,标注重复单号或缺失阶段的事务,省去你手动打印调试。
历史订单转移与成交写入类事务常被忽略,但它们是确认仓位真正落账的依据,漏掉会导致余额计算偏移。
能,用 EventChartCustom 发自定义事件、OnChartEvent 接收,与系统交易事件互不阻塞,但需注意优先级避免竞态。