MQL5 交易工具包(第 7 部分):使用最近取消的挂单函数扩展历史管理 EX5 库(基础篇)
用取消挂单记录补全历史管理库
在 MT5 的 EX5 历史管理库里,普通成交和已成交挂单都有现成接口,但「最近被取消的挂单」长期是个盲区。2025-11-26 发布的第 7 部分工具包补上了这块:新增一组函数,专门拉取近期被撤掉的挂单数据,让历史库能覆盖挂单生命周期的完整末端。 对做价格行为回测的人,这直接有用——你可以把撤单密集区当成隐性流动性边界。比如某价位在 1 小时内被撤单 12 次以上,价格后续在该区域反向运行的概率往往偏高,但这只是统计倾向,不构成立场。 外汇与贵金属杠杆高、滑点突变频繁,撤单行为本身也是风险信号的一部分。开 MT5 把新库挂上,先跑一周真实 Tick 看看撤单分布,比任何预设结论都实在。
「补齐已撤挂单的历史缺口」
MQL5 原生没有单行函数能直接拉取“最近被取消的挂单”属性,开发者只能自己翻历史流水去拼。这个系列要做的 EX5 库,最后一块拼图就是封一个模块,把撤单的品种、挂单价、点值止损止盈、挂单存活时长等字段一次性取出来。 本篇只做一件事:在 HistoryManager.mq5 里接着写 GetLastCanceledPendingOrderData()。先打开上一篇文章末尾附的源文件,定位到 LastFilledPendingOrderComment() 函数下方——新代码就接在那儿,保证同类逻辑聚在一起,后面维护不头疼。 外汇和贵金属历史数据受点差跳空影响,撤单记录可能缺失部分字段,用之前先想清楚容错。把这个模块跑通,你就能在 EA 里一行调用拿到撤单明细,省掉自己解析历史的功夫。
◍ 读取最近撤单的历史字段
MT5 在挂单被取消后不会立刻清空记录,通过 HistoryOrderGet 系列函数仍能拉出最近一笔撤单的完整属性。对做挂单回流统计或撤单行为分析的交易者来说,这些字段是还原盘口意图的第一手材料。 可提取的维度包括:订单类型、交易品种、单号、挂单价格、止损价、止盈价、止损点数、止盈点数、时间设置、完成时间、到期时间、仓位 ID、幻数、撤单原因、成交类型、类型时间和注释。一共 18 个字段,覆盖从发单到撤单的全链路。 外汇与贵金属杠杆高、滑点突发行情多,撤单原因字段(如超时、手动、规则触发)能帮你在复盘时区分“主动撤”和“被动废单”,但任何历史字段都不能直接推导后续价格方向,仅作为概率参考。
抓最近撤掉的挂单
做撤单行为分析时,先得把「最近一笔被取消的挂单」捞出来。GetLastCanceledPendingOrderData() 用 export 修饰,意味着它能被其他 MQL5 模块直接调用,入参是 PendingOrderData 类型的引用,成功填数据返 true,失败返 false。 它内部先调 FetchHistoryByCriteria(GET_PENDING_ORDERS_HISTORY_DATA) 拉挂单历史。若返回 false,说明终端里根本没有可查的成交历史,此时 Print(__FUNCTION__,"No trading history available...") 把函数名打进日志,方便你定位,随后直接 return false,引用变量原样不动。 历史拿到后,GetTotalDataInfoSize() 给出 pendingOrderInfo 数组长度。接下来从下标 0 开始扫,碰到 state == ORDER_STATE_CANCELED 的第一条就赋值给入参引用并 break。这意味着它取的是「数组顺序里第一个取消单」,而不是按时间最新的那个——若你的写入逻辑是后插式,要注意两者可能不一致。 下面这段是完整实现,注意第一处签名后面的空函数体是原文分步讲解占位,真正可用的是第二个带逻辑的同名函数。 别把引用当保险箱 函数失败时引用变量保持不变,但成功时会被整体覆盖。调用前若引用里已有旧挂单数据,跑完这个函数旧数据就没了,下游逻辑别假设它还留着。
class="type">bool GetLastCanceledPendingOrderData(PendingOrderData &getLastCanceledPendingOrderData) class="kw">export { class=class="str">"cmt">//-- Function implementation will be explained step by step below. } if(!FetchHistoryByCriteria(GET_PENDING_ORDERS_HISTORY_DATA)) { Print(__FUNCTION__, ": No trading history available. Last canceled pending order can&class="macro">#x27;t be retrieved."); class="kw">return(false); } class="type">int totalPendingOrderInfo = GetTotalDataInfoSize(GET_PENDING_ORDERS_HISTORY_DATA); for(class="type">int x = class="num">0; x < totalPendingOrderInfo; x++) { if(pendingOrderInfo[x].state == ORDER_STATE_CANCELED) { getLastCanceledPendingOrderData = pendingOrderInfo[x]; class="kw">break; } } class="kw">return(true); class="type">bool GetLastCanceledPendingOrderData(PendingOrderData &getLastCanceledPendingOrderData) class="kw">export { if(!FetchHistoryByCriteria(GET_PENDING_ORDERS_HISTORY_DATA)) { Print(__FUNCTION__, ": No trading history available. Last canceled pending order can&class="macro">#x27;t be retrieved."); class="kw">return(false); } class=class="str">"cmt">//-- Save the last canceled pending order data in the referenced getLastCanceledPendingOrderData variable class="type">int totalPendingOrderInfo = GetTotalDataInfoSize(GET_PENDING_ORDERS_HISTORY_DATA); for(class="type">int x = class="num">0; x < totalPendingOrderInfo; x++) { if(pendingOrderInfo[x].state == ORDER_STATE_CANCELED) { getLastCanceledPendingOrderData = pendingOrderInfo[x]; class="kw">break; } } class="kw">return(true); }
「抓最近撤掉的挂单类型」
在 MT5 的 EA 逻辑里,有时候需要知道「上一笔被撤掉的挂单到底是 Buy Limit 还是 Sell Stop」。LastCanceledPendingOrderType() 就是干这个的:它把结果写进你传进去的引用变量,成功就返 true,失败返 false 且变量不动。 实现上先建一个 PendingOrderData 临时结构 lastCanceledPendingOrderInfo,调 GetLastCanceledPendingOrderData() 把撤单明细捞出来。捞到了就从 .type 字段取值赋给入参,没捞到直接返 false。 下面这段是完整函数,注意 export 标记让它能被其他模块调用,入参用了 ENUM_ORDER_TYPE 的引用: 别在调用前假设变量已有值——检索失败时它保持原样,调用方得自己处理这种分支,否则可能误用上一次的旧类型。
class="type">bool LastCanceledPendingOrderType(ENUM_ORDER_TYPE &lastCanceledPendingOrderType) class="kw">export { PendingOrderData lastCanceledPendingOrderInfo; if(GetLastCanceledPendingOrderData(lastCanceledPendingOrderInfo)) { lastCanceledPendingOrderType = lastCanceledPendingOrderInfo.type; class="kw">return(true); } class="kw">return(false); }
◍ 抓最后撤掉的挂单是哪个品种
在 EA 回测或实盘里,有时需要确认「最近一笔被撤掉的挂单」到底挂在哪个品种上。LastCanceledPendingOrderSymbol() 就是干这个的:它把结果写进你传进去的引用变量 lastCanceledPendingOrderSymbol,成功返回 true,失败返回 false。 底层逻辑很直接——先调 GetLastCanceledPendingOrderData() 把那笔撤单的完整结构体捞出来;只要捞到了,就把里面的 symbol 字段赋给你的引用变量,函数收尾返回 true。若终端根本没这条撤单历史(比如刚启动还没撤过单),引用变量原样不动,函数返回 false。 下面这段是完整实现,注意参数用了 string& 引用传递,调用方变量会被直接改写:
<span class="keyword">class="type">bool</span> LastCanceledPendingOrderSymbol(<span class="keyword">class="type">class="kw">string</span> &lastCanceledPendingOrderSymbol) <span class="keyword">class="kw">export</span> { PendingOrderData lastCanceledPendingOrderInfo; <span class="keyword">if</span>(GetLastCanceledPendingOrderData(lastCanceledPendingOrderInfo)) { lastCanceledPendingOrderSymbol = lastCanceledPendingOrderInfo.symbol; <span class="keyword">class="kw">return</span>(<span class="macro">true</span>); } <span class="keyword">class="kw">return</span>(<span class="macro">false</span>); }
class="type">bool LastCanceledPendingOrderSymbol(class="type">class="kw">string &lastCanceledPendingOrderSymbol) class="kw">export { PendingOrderData lastCanceledPendingOrderInfo; if(GetLastCanceledPendingOrderData(lastCanceledPendingOrderInfo)) { lastCanceledPendingOrderSymbol = lastCanceledPendingOrderInfo.symbol; class="kw">return(true); } class="kw">return(false); }