首页 / 交易学院 / MT5 交易事件模型:一次请求为何触发多个 OnTrade
MT5 交易事件模型:一次请求为何触发多个 OnTrade

MT5 交易事件模型:一次请求为何触发多个 OnTrade

从 OrderSend 到成交回包,理清异步交易事件的来龙去脉

EA 开发实战 难度 · 进阶 2026-07-15 10 分钟阅读
#MT5#OnTrade#交易事件#异步#OrderSend

理解交易事件模型,是写出健壮 EA 的前提。MT5 的异步特性意味着:你发的“一个请求”和客户端收到的“事件”并不是一一对应的。本文顺着请求到成交的完整链路,把这件事讲透。

一、请求如何从客户端到服务器

手动交易按 F9 打开请求窗口,程序用 OrderSend() 发送。发往服务器前,客户端先做强正确性检查(如买几百万手、负价),错误请求根本不会出门——这是为保护服务器不被程序 bug 刷爆。可用 OrderCheck() 预检,结果存入 MqlTradeCheckResult。

二、服务器的初步检查

请求到达后,服务器校验资金是否充足、价格/止损止盈是否正确、数量(最小/最大/步长/持仓限额)、品种状态与交易时段、账户限制等。不通过即拒绝,回包写入 MqlTradeResult(通过 OrderSend 第二参数取回)。通过检查的请求进入等待队列,寿命 3 分钟,超时删除。

三、OnTrade:交易事件处理函数

MQL5 的事件模型会在订单/持仓/成交/历史变化时调用预定义的 OnTrade()。注意:OnTrade 仅供 EA 使用,你在指标或脚本里写同名函数也不会被触发。

四、关键真相:一个请求 → 多个事件

例:一个买 10 手 EURUSD 的挂单,被 1+4+5 手三笔反向成交吃掉。作为结果,客户端会收到 7 个 Trade 事件(每笔成交、每次数量变化、订单移入历史各算一个)。

⚠ 不要假设一一对应
不能依赖“一个请求一个事件”的假设。OnTrade 可能因一次操作被连串调用——每个订单状态、持仓、历史的变化都会单独生成事件。

五、消息是独立到达的

来自服务器的消息各自独立到达:订单单证可能先到,而 Trade 事件、活动列表更新稍后才到;生至出现“成交已执行、订单已进历史”的情况也属正常,因为服务器处理远快于网络传输。

六、可靠的事件处理算法:对比状态

唯一能确定“账户到底变了什么”的方法,是比较前后快照。做法:全局声明 orders/positions/deals/history_orders 计数器;OnInit 里用 HistorySelect 初始化;在 OnTick/OnTrade 中重新 HistorySelect 并比较前后数量与状态,差异即变化;用 CheckStartDateInTradeHistory 滚动历史窗口。

✦ 对比优于推断
由于消息异步且可能乱序,靠“这次 OnTrade 一定意味着 X”来推断并不可靠;维护计数器快照、比较差异才是最稳的做法。

小结

常见问题

不能。OnTrade 只被 EA 调用;指标/脚本里即使写了同名函数也不会触发。
一次操作(如部分成交)会改变订单状态、持仓、交易历史等多处,每处变化生成一个独立事件,逐个推送,于是 OnTrade 被连串调用。
不代表。true 只表示请求通过客户端初步检查、被服务器接受进入队列;是否真成交要看 MqlTradeResult 的字段。
维护订单/持仓/成交的计数器快照,在 OnTrade/OnTick 里重新 HistorySelect 并比较前后数量与状态,差异即变化。