首页 / 交易学院 / 小布知识库 / EA 交易事件处理:用 OnTrade() 监控每一笔成交
EA 交易事件处理:用 OnTrade() 监控每一笔成交

EA 交易事件处理:用 OnTrade() 监控每一笔成交

交易事件、OnTrade 触发次数、订单/持仓快照对比法

EA 开发实战 难度 · 进阶 2026-07-11 13 分钟阅读
#EA#OnTrade#交易事件#事件驱动#监控

一、为什么需要 OnTrade

下单不是「发了就完事」:成交可能部分成交、被拒、或因滑点价格不同。EA 需要知道「我的单到底成没成、成了多少、成交价多少」,才能正确更新状态、决定下一步。OnTrade 就是终端在成交/持仓/订单变化时通知 EA 的钩子,是连接「发单」与「知单」的桥梁。

没有 OnTrade,EA 只能在下一次 OnTick 里去查持仓猜结果,既慢又容易在快速波动里误判。把成交后的状态同步交给 OnTrade,主逻辑才干净。

二、OnTrade 的触发时机

当订单被成交、被拒、持仓被修改或删除时,终端会调用 OnTrade()。它不传参数,你要在函数里用 PositionsTotal / HistorySelect 等主动查询「现在发生了什么」。关键是:OnTrade 可能在一次下单后连续触发多次(如部分成交再补全),逻辑要能处理重复通知。

三、用 OnTrade 同步状态

典型用法:在 OnTrade 里检查当前持仓,更新「是否已开仓」「入场价」「订单ticket」等状态变量。这样无论成交发生在哪个 tick,EA 的状态都能及时跟上,下一根 OnTick 看到的就最新。

void OnTrade()
{
   bool has = (PositionSelect(_Symbol));
   if(has) myOpenPrice = PositionGetDouble(POSITION_PRICE_OPEN);
   myHasPos = has;
}

四、OnTrade 与 OnTick 的分工

规则很清晰:OnTick 负责「决策与发单」(看信号、算手数、调 CTrade),OnTrade 负责「成交后同步状态」(更新持仓、记录成交价)。不要把下单逻辑塞进 OnTrade,也别在 OnTick 里反复轮询成交——各管一段,代码不打架。

五、处理部分成交与拒绝

市价单在大行情里可能部分成交(只成一部分),限价单可能根本不成交。OnTrade 里要能识别「订单状态」:用 OrderGetInteger(ORDER_STATE) 看是 FILLED / PARTIAL / CANCELED / REJECTED。对部分成交,要决定是补还是等;对拒绝,要记录原因(Retcode)而非假装成功。

⚠ 别假设一单就全成
大单、跳空、低流动性下,一次 OrderSend 可能只部分成交或被拒。OnTrade 里必须核对实际成交状态,否则 EA 会基于「我以为成了」做出错误后续决策。

六、实战:下单后确认成交

一个稳健模式:在 OnTick 里发单并记录期望 ticket;在 OnTrade 里核对 HistorySelect 后的实际 Deal,确认成交价/成交量,更新 myOpenPrice 与 myHasPos。若发现被拒,写日志并触发风控(如暂停 N 秒)。这条链路做扎实,EA 的「账」才清楚。

void OnTrade()
{
   HistorySelect(TimeCurrent()-86400, TimeCurrent());
   ulong tkt = myPendingTicket;
   if(OrderSelect(tkt) && OrderGetInteger(ORDER_STATE)==ORDER_STATE_FILLED)
      Print("filled at ", OrderGetDouble(ORDER_PRICE_FILL));
}

七、常见坑

八、用 OnTrade 触发风控与统计

OnTrade 不只是同步持仓,更是做账与事后动作的好地方。每次成交,你可以在这里累加当日成交笔数、记录实际成交价与期望值偏差、更新连续亏损计数,这些状态供 OnTick 的风控分支使用(比如连亏三笔后暂停新单)。把统计放进成交事件,能保证「每笔真实成交只计一次」,比在 OnTick 里轮询更准。

还可以用它触发通知:成交后 SendNotification 或写文件日志,让你在手机上第一时间知道 EA 已进场或离场,而不必盯着终端。注意通知类调用要轻量,别在 OnTrade 里再做重计算或下单,否则事件内部又触发事件,形成重入。

九、OnTrade 的重入与禁忌

终端在「一笔订单引发一连串成交」时,可能连续多次调用 OnTrade(比如部分成交、改仓、平仓拆成多条 Deal)。因此 OnTrade 里的代码必须是幂等且轻量的:只读持仓或历史、更新标量状态、发通知,不要在这里再下新单或做耗时循环。

若你确实需要在成交后做交易动作(例如平仓同时开反向仓),正确做法是在 OnTrade 里只置一个待处理标志,真正的发单留给 OnTick 去执行。这样既能响应成交,又规避了在事件回调里交易导致的不可预期行为。

✦ 铁律分工
OnTrade 等于知单与记账,OnTick 等于决策与发单。把发单塞进 OnTrade,是 EA 偶发卡死、重复下单的根源之一。

十、小结

✦ OnTick 决策,OnTrade 记账
把「发单」与「知单」拆给两个事件:OnTick 看信号发单,OnTrade 在成交后同步真实状态。账清楚了,EA 才不会基于幻觉做决策。

常见问题

OnTick 负责看信号、算手数、发单(决策);OnTrade 负责成交后同步真实持仓与成交价(记账)。别把下单塞进 OnTrade,也别在 OnTick 反复轮询成交。
在 OnTrade 里用 OrderGetInteger(ORDER_STATE) 查状态:FILLED / PARTIAL / REJECTED。部分成交要决定补还是等,拒绝要记 Retcode,别假设全成。
会,一次成交可能触发多次(部分成交再补全)。逻辑要幂等,能处理重复通知,别在里面又发单造成死循环。