MQL5 交易工具包(第 8 部分):如何在代码库中实现和使用历史管理 EX5 库·进阶篇
📚

MQL5 交易工具包(第 8 部分):如何在代码库中实现和使用历史管理 EX5 库·进阶篇

(2/3)· 从已开发的库到实战调用,6 节拆解函数接口与集成陷阱,省掉重复造轮子

含代码示例偏理论 第 2/3 篇
很多人把交易历史读取写成几十行重复循环,却没意识到现成 EX5 库一行就能拿到最后平仓单。本篇接着上篇的库开发,直接讲怎么把它塞进你的 EA 和脚本里跑起来。

「历史管理器接口与宏定义怎么摆」

做 MT5 历史数据抓取,第一步是把时间窗口和对象范围用宏固化下来,避免每次调用都手写魔法数字。下面这组定义把「近一月」算成当前时间减去月线周期秒数,近一年乘 12,EPOCH 直接给 0 对应 1970-01-01 零点,TODAY 到 THIS_YEAR 用 12~15 的枚举值占位,ALL_SYMBOLS 留空串表示不筛选品种。 核心能力来自外部编译模块 Wanateki/Toolkit/HistoryManager/HistoryManager.ex5,用 #import 挂进来。它暴露了四类历史读取:成交(Deal)、订单(Order)、持仓(Position)、挂单(PendingOrder),每类都有带时间区间和可选 symbol/magic 的重载,也有不传时间只按全量或按 symbol+magic 的简化版。 实盘回测时最常用的是 LastClosedPosition 系列——直接拿上一笔已平持仓的类型、成交量、品种、订单号、盈亏。比如 LastClosedPositionProfit 填 double 引用,调用成功返回 true,失败说明当前账户历史上还没有平仓记录。外汇与贵金属杠杆高,用这些接口做仓位复盘前,先确认历史缓存已通过 HistorySelect 加载,否则可能读到空数组。

MQL5 / C++
class="macro">#define ONE_MONTH class="type">class="kw">datetime(TimeCurrent() - PeriodSeconds(PERIOD_MN1))
class="macro">#define ONE_YEAR class="type">class="kw">datetime(TimeCurrent() - (PeriodSeconds(PERIOD_MN1) * class="num">12))
class="macro">#define EPOCH class="num">0 class=class="str">"cmt">// 1st Jan class="num">1970
class=class="str">"cmt">//--
class="macro">#define TODAY class="num">12
class="macro">#define THIS_WEEK class="num">13
class="macro">#define THIS_MONTH class="num">14
class="macro">#define THIS_YEAR class="num">15
class=class="str">"cmt">//--
class="macro">#define ALL_SYMBOLS ""
class="macro">#define ALL_POSITIONS class="num">1110
class="macro">#define ALL_ORDERS class="num">1111
class="macro">#define ALL_DEALS class="num">1112
class=class="str">"cmt">//--
class="macro">#class="kw">import "Wanateki/Toolkit/HistoryManager/HistoryManager.ex5"
class=class="str">"cmt">//--
class="type">void PrintDealsHistory(class="type">class="kw">datetime fromDateTime, class="type">class="kw">datetime toDateTime);
class="type">void PrintOrdersHistory(class="type">class="kw">datetime fromDateTime, class="type">class="kw">datetime toDateTime);
class="type">void PrintPositionsHistory(class="type">class="kw">datetime fromDateTime, class="type">class="kw">datetime toDateTime);
class="type">void PrintPendingOrdersHistory(class="type">class="kw">datetime fromDateTime, class="type">class="kw">datetime toDateTime);
class=class="str">"cmt">//--
class="type">bool GetDealsData(DealData &dealsData[], class="type">class="kw">datetime fromDateTime, class="type">class="kw">datetime toDateTime, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool GetOrdersData(OrderData &ordersData[], class="type">class="kw">datetime fromDateTime, class="type">class="kw">datetime toDateTime, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool GetPositionsData(PositionData &positionsData[], class="type">class="kw">datetime fromDateTime, class="type">class="kw">datetime toDateTime, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool GetPendingOrdersData(PendingOrderData &pendingOrdersData[], class="type">class="kw">datetime fromDateTime, class="type">class="kw">datetime toDateTime, class="type">class="kw">string symbol, class="type">ulong magic);
class=class="str">"cmt">//--
class="type">bool GetDealsData(DealData &dealsData[], class="type">class="kw">datetime fromDateTime, class="type">class="kw">datetime toDateTime);
class="type">bool GetOrdersData(OrderData &ordersData[], class="type">class="kw">datetime fromDateTime, class="type">class="kw">datetime toDateTime);
class="type">bool GetPositionsData(PositionData &positionsData[], class="type">class="kw">datetime fromDateTime, class="type">class="kw">datetime toDateTime);
class="type">bool GetPendingOrdersData(PendingOrderData &pendingOrdersData[], class="type">class="kw">datetime fromDateTime, class="type">class="kw">datetime toDateTime);
class=class="str">"cmt">//--
class="type">bool GetAllDealsData(DealData &dealsData[]);
class="type">bool GetAllOrdersData(OrderData &ordersData[]);
class="type">bool GetAllPositionsData(PositionData &positionsData[]);
class="type">bool GetAllPendingOrdersData(PendingOrderData &pendingOrdersData[]);
class=class="str">"cmt">//--
class="type">bool GetAllDealsData(DealData &dealsData[], class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool GetAllOrdersData(OrderData &ordersData[], class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool GetAllPositionsData(PositionData &positionsData[], class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool GetAllPendingOrdersData(PendingOrderData &pendingOrdersData[], class="type">class="kw">string symbol, class="type">ulong magic);
class=class="str">"cmt">//--
class="type">bool GetLastClosedPositionData(PositionData &lastClosedPositionInfo);
class="type">bool LastClosedPositionType(class="type">ENUM_POSITION_TYPE &lastClosedPositionType);
class="type">bool LastClosedPositionVolume(class="type">class="kw">double &lastClosedPositionVolume);
class="type">bool LastClosedPositionSymbol(class="type">class="kw">string &lastClosedPositionSymbol);
class="type">bool LastClosedPositionTicket(class="type">ulong &lastClosedPositionTicket);
class="type">bool LastClosedPositionProfit(class="type">class="kw">double &lastClosedPositionProfit);

◍ 抓取已平仓与挂单的历史快照

做复盘或信号触发时,最常卡在「上一笔单子到底怎么死的」。下面这组接口把最近一笔已平仓头寸的全字段都吐出来,净盈亏、点值盈亏、开平时间、SL/TP 价位与点数、swap、佣金、魔术码、注释、持仓时长全部可拿,返回 bool 告诉你取没取到。 bool LastClosedPositionNetProfit(double &lastClosedPositionNetProfit); bool LastClosedPositionPipProfit(int &lastClosedPositionPipProfit); bool LastClosedPositionClosePrice(double &lastClosedPositionClosePrice); bool LastClosedPositionOpenPrice(double &lastClosedPositionOpenPrice); bool LastClosedPositionSlPrice(double &lastClosedPositionSlPrice); bool LastClosedPositionTpPrice(double &lastClosedPositionTpPrice); bool LastClosedPositionSlPips(int &lastClosedPositionSlPips); bool LastClosedPositionTpPips(int &lastClosedPositionTpPips); bool LastClosedPositionOpenTime(datetime &lastClosedPositionOpenTime); bool LastClosedPositionCloseTime(datetime &lastClosedPositionCloseTime); bool LastClosedPositionSwap(double &lastClosedPositionSwap); bool LastClosedPositionCommission(double &lastClosedPositionCommission); bool LastClosedPositionInitiatedByPendingOrder(bool &lastClosedPositionInitiatedByPendingOrder); bool LastClosedPositionInitiatingOrderType(ENUM_ORDER_TYPE &lastClosedPositionInitiatingOrderType); bool LastClosedPositionId(ulong &lastClosedPositionId); bool LastClosedPositionOpeningOrderTicket(ulong &lastClosedPositionOpeningOrderTicket); bool LastClosedPositionOpeningDealTicket(ulong &lastClosedPositionOpeningDealTicket); bool LastClosedPositionClosingDealTicket(ulong &lastClosedPositionClosingDealTicket); bool LastClosedPositionMagic(ulong &lastClosedPositionMagic); bool LastClosedPositionComment(string &lastClosedPositionComment); bool LastClosedPositionDuration(long &lastClosedPositionDuration); 逐行拆解:每个函数签名都是「bool 函数名(类型 &引用变量)」,调用时传入变量地址,函数内填值,返回 true 代表历史池里确有这笔平仓记录。LastClosedPositionNetProfit 取净盈亏(已扣 swap 与佣金),LastClosedPositionPipProfit 取以点计盈亏,LastClosedPositionSlPips / TpPips 把止损止盈从价位换算成点数,LastClosedPositionDuration 给的是持仓毫秒数,需自行除以 1000 得秒。 除了单笔,还有聚合取数:GetLastClosedProfitablePositionData 直接拿最近一笔盈利平仓的 PositionData 结构,GetLastClosedLossPositionData 对应亏损单。若你想区分「被扫损」还是「主动平」,可用 LastClosedPositionInitiatedByPendingOrder 配合 LastClosedPositionInitiatingOrderType 判断来源。 挂单侧同样有完整追踪。GetLastFilledPendingOrderData 取最近成交挂单,LastFilledPendingOrderType 给 ORDER_TYPE_BUY_LIMIT 等枚举,LastFilledPendingOrderTimeSetup 是挂单创建时间,LastFilledPendingOrderTimeDone 是成交时间,二者相减可得挂单「躺了多久才触发」。GetLastCanceledPendingOrderData 与 LastCanceledPendingOrderType 则覆盖被撤单情形。外汇与贵金属波动剧烈,这类历史快照仅作概率参考,实盘仍需控仓。

MQL5 / C++
class="type">bool LastClosedPositionNetProfit(class="type">class="kw">double &lastClosedPositionNetProfit);
class="type">bool LastClosedPositionPipProfit(class="type">int &lastClosedPositionPipProfit);
class="type">bool LastClosedPositionClosePrice(class="type">class="kw">double &lastClosedPositionClosePrice);
class="type">bool LastClosedPositionOpenPrice(class="type">class="kw">double &lastClosedPositionOpenPrice);
class="type">bool LastClosedPositionSlPrice(class="type">class="kw">double &lastClosedPositionSlPrice);
class="type">bool LastClosedPositionTpPrice(class="type">class="kw">double &lastClosedPositionTpPrice);
class="type">bool LastClosedPositionSlPips(class="type">int &lastClosedPositionSlPips);
class="type">bool LastClosedPositionTpPips(class="type">int &lastClosedPositionTpPips);
class="type">bool LastClosedPositionOpenTime(class="type">class="kw">datetime &lastClosedPositionOpenTime);
class="type">bool LastClosedPositionCloseTime(class="type">class="kw">datetime &lastClosedPositionCloseTime);
class="type">bool LastClosedPositionSwap(class="type">class="kw">double &lastClosedPositionSwap);
class="type">bool LastClosedPositionCommission(class="type">class="kw">double &lastClosedPositionCommission);
class="type">bool LastClosedPositionInitiatedByPendingOrder(class="type">bool &lastClosedPositionInitiatedByPendingOrder);
class="type">bool LastClosedPositionInitiatingOrderType(ENUM_ORDER_TYPE &lastClosedPositionInitiatingOrderType);
class="type">bool LastClosedPositionId(class="type">ulong &lastClosedPositionId);
class="type">bool LastClosedPositionOpeningOrderTicket(class="type">ulong &lastClosedPositionOpeningOrderTicket);
class="type">bool LastClosedPositionOpeningDealTicket(class="type">ulong &lastClosedPositionOpeningDealTicket);
class="type">bool LastClosedPositionClosingDealTicket(class="type">ulong &lastClosedPositionClosingDealTicket);
class="type">bool LastClosedPositionMagic(class="type">ulong &lastClosedPositionMagic);
class="type">bool LastClosedPositionComment(class="type">class="kw">string &lastClosedPositionComment);
class="type">bool LastClosedPositionDuration(class="type">long &lastClosedPositionDuration);
class=class="str">"cmt">//--
class="type">bool GetLastClosedProfitablePositionData(PositionData &lastClosedProfitablePositionInfo);
class="type">bool GetLastClosedLossPositionData(PositionData &lastClosedLossPositionData);
class=class="str">"cmt">//--
class="type">bool GetLastFilledPendingOrderData(PendingOrderData &getLastFilledPendingOrderData);
class="type">bool LastFilledPendingOrderType(ENUM_ORDER_TYPE &lastFilledPendingOrderType);
class="type">bool LastFilledPendingOrderSymbol(class="type">class="kw">string &lastFilledPendingOrderSymbol);
class="type">bool LastFilledPendingOrderTicket(class="type">ulong &lastFilledPendingOrderTicket);
class="type">bool LastFilledPendingOrderPriceOpen(class="type">class="kw">double &lastFilledPendingOrderPriceOpen);
class="type">bool LastFilledPendingOrderSlPrice(class="type">class="kw">double &lastFilledPendingOrderSlPrice);
class="type">bool LastFilledPendingOrderTpPrice(class="type">class="kw">double &lastFilledPendingOrderTpPrice);
class="type">bool LastFilledPendingOrderSlPips(class="type">int &lastFilledPendingOrderSlPips);
class="type">bool LastFilledPendingOrderTpPips(class="type">int &lastFilledPendingOrderTpPips);
class="type">bool LastFilledPendingOrderTimeSetup(class="type">class="kw">datetime &lastFilledPendingOrderTimeSetup);
class="type">bool LastFilledPendingOrderTimeDone(class="type">class="kw">datetime &lastFilledPendingOrderTimeDone);
class="type">bool LastFilledPendingOrderExpirationTime(class="type">class="kw">datetime &lastFilledPendingOrderExpirationTime);
class="type">bool LastFilledPendingOrderPositionId(class="type">ulong &lastFilledPendingOrderPositionId);
class="type">bool LastFilledPendingOrderMagic(class="type">ulong &lastFilledPendingOrderMagic);
class="type">bool LastFilledPendingOrderReason(ENUM_ORDER_REASON &lastFilledPendingOrderReason);
class="type">bool LastFilledPendingOrderTypeFilling(ENUM_ORDER_TYPE_FILLING &lastFilledPendingOrderTypeFilling);
class="type">bool LastFilledPendingOrderTypeTime(class="type">class="kw">datetime &lastFilledPendingOrderTypeTime);
class="type">bool LastFilledPendingOrderComment(class="type">class="kw">string &lastFilledPendingOrderComment);
class=class="str">"cmt">//--
class="type">bool GetLastCanceledPendingOrderData(PendingOrderData &getLastCanceledPendingOrderData);
class="type">bool LastCanceledPendingOrderType(ENUM_ORDER_TYPE &lastCanceledPendingOrderType);

撤单与平仓记录的接口抓取点

做复盘或自动风控时,最常漏掉的两类数据是被取消的挂单和已平仓头寸。下面这组接口把最近一次取消挂单的字段全部暴露出来,从交易品种、订单号到止损止盈点数、挂单与作废时间,一共 17 个读取函数,全部以布尔返回值表示是否成功取到。 紧接着是已平仓头寸的批量读取接口,共 21 个函数。它们都比撤单接口多两个入参:symbol 和 magic,意味着你可以按品种和魔数精确过滤,只拉自己 EA 跑的那部分历史仓位。 实际用法上,比如想统计最近一笔平仓的净盈亏,调 LastClosedPositionNetProfit 即可,返回 double 直接进日志或发告警。外汇与贵金属杠杆高,这类历史读取只用于分析,不能据此直接推断后续行情概率。 让小布替你跑这套 把 symbol 传成 _Symbol、magic 填你 EA 的实际魔数,循环调 LastClosedPositionProfit 和 LastClosedPositionPipProfit,能在 MT5 策略测试器里快速打出每笔平仓的盈亏分布,比手动翻成交记录快得多。

MQL5 / C++
class="type">bool LastCanceledPendingOrderSymbol(class="type">class="kw">string &lastCanceledPendingOrderSymbol);
class="type">bool LastCanceledPendingOrderTicket(class="type">ulong &lastCanceledPendingOrderTicket);
class="type">bool LastCanceledPendingOrderPriceOpen(class="type">class="kw">double &lastCanceledPendingOrderPriceOpen);
class="type">bool LastCanceledPendingOrderSlPrice(class="type">class="kw">double &lastCanceledPendingOrderSlPrice);
class="type">bool LastCanceledPendingOrderTpPrice(class="type">class="kw">double &lastCanceledPendingOrderTpPrice);
class="type">bool LastCanceledPendingOrderSlPips(class="type">int &lastCanceledPendingOrderSlPips);
class="type">bool LastCanceledPendingOrderTpPips(class="type">int &lastCanceledPendingOrderTpPips);
class="type">bool LastCanceledPendingOrderTimeSetup(class="type">class="kw">datetime &lastCanceledPendingOrderTimeSetup);
class="type">bool LastCanceledPendingOrderTimeDone(class="type">class="kw">datetime &lastCanceledPendingOrderTimeDone);
class="type">bool LastCanceledPendingOrderExpirationTime(class="type">class="kw">datetime &lastCanceledPendingOrderExpirationTime);
class="type">bool LastCanceledPendingOrderPositionId(class="type">ulong &lastCanceledPendingOrderPositionId);
class="type">bool LastCanceledPendingOrderMagic(class="type">ulong &lastCanceledPendingOrderMagic);
class="type">bool LastCanceledPendingOrderReason(ENUM_ORDER_REASON &lastCanceledPendingOrderReason);
class="type">bool LastCanceledPendingOrderTypeFilling(ENUM_ORDER_TYPE_FILLING &lastCanceledPendingOrderTypeFilling);
class="type">bool LastCanceledPendingOrderTypeTime(class="type">class="kw">datetime &lastCanceledPendingOrderTypeTime);
class="type">bool LastCanceledPendingOrderComment(class="type">class="kw">string &lastCanceledPendingOrderComment);
class=class="str">"cmt">//*
class=class="str">"cmt">//--
class="type">bool GetLastClosedPositionData(PositionData &lastClosedPositionInfo, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastClosedPositionType(class="type">ENUM_POSITION_TYPE &lastClosedPositionType, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastClosedPositionVolume(class="type">class="kw">double &lastClosedPositionVolume, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastClosedPositionSymbol(class="type">class="kw">string &lastClosedPositionSymbol, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastClosedPositionTicket(class="type">ulong &lastClosedPositionTicket, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastClosedPositionProfit(class="type">class="kw">double &lastClosedPositionProfit, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastClosedPositionNetProfit(class="type">class="kw">double &lastClosedPositionNetProfit, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastClosedPositionPipProfit(class="type">int &lastClosedPositionPipProfit, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastClosedPositionClosePrice(class="type">class="kw">double &lastClosedPositionClosePrice, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastClosedPositionOpenPrice(class="type">class="kw">double &lastClosedPositionOpenPrice, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastClosedPositionSlPrice(class="type">class="kw">double &lastClosedPositionSlPrice, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastClosedPositionTpPrice(class="type">class="kw">double &lastClosedPositionTpPrice, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastClosedPositionSlPips(class="type">int &lastClosedPositionSlPips, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastClosedPositionTpPips(class="type">int &lastClosedPositionTpPips, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastClosedPositionOpenTime(class="type">class="kw">datetime &lastClosedPositionOpenTime, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastClosedPositionCloseTime(class="type">class="kw">datetime &lastClosedPositionCloseTime, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastClosedPositionSwap(class="type">class="kw">double &lastClosedPositionSwap, class="type">class="kw">string symbol, class="type">ulong magic);

「抓最近平仓与挂单成交的明细字段」

写 EA 时经常要回看上一笔已平掉仓位的来龙去脉,比如它是市价单开的还是挂单触发的、吃了多少佣金、拿了多久。下面这组函数把最近平仓仓位的关键属性一次性暴露出来,调用时传入 symbol 和 magic 做过滤,返回 bool 表示是否真的查到了数据。 bool LastClosedPositionCommission(double &lastClosedPositionCommission, string symbol, ulong magic); bool LastClosedPositionInitiatingOrderType(ENUM_ORDER_TYPE &lastClosedPositionInitiatingOrderType, string symbol, ulong magic); bool LastClosedPositionId(ulong &lastClosedPositionId, string symbol, ulong magic); bool LastClosedPositionInitiatedByPendingOrder(bool &lastClosedPositionInitiatedByPendingOrder, string symbol, ulong magic); bool LastClosedPositionOpeningOrderTicket(ulong &lastClosedPositionOpeningOrderTicket, string symbol, ulong magic); bool LastClosedPositionOpeningDealTicket(ulong &lastClosedPositionOpeningDealTicket, string symbol, ulong magic); bool LastClosedPositionClosingDealTicket(ulong &lastClosedPositionClosingDealTicket, string symbol, ulong magic); bool LastClosedPositionMagic(ulong &lastClosedPositionMagic, string symbol, ulong magic); bool LastClosedPositionComment(string &lastClosedPositionComment, string symbol, ulong magic); bool LastClosedPositionDuration(long &lastClosedPositionDuration, string symbol, ulong magic); //-- bool GetLastClosedProfitablePositionData(PositionData &lastClosedProfitablePositionInfo, string symbol, ulong magic); bool GetLastClosedLossPositionData(PositionData &lastClosedLossPositionData, string symbol, ulong magic); //-- bool GetLastFilledPendingOrderData(PendingOrderData &lastFilledPendingOrderData, string symbol, ulong magic); bool LastFilledPendingOrderType(ENUM_ORDER_TYPE &lastFilledPendingOrderType, string symbol, ulong magic); bool LastFilledPendingOrderSymbol(string &lastFilledPendingOrderSymbol, string symbol, ulong magic); bool LastFilledPendingOrderTicket(ulong &lastFilledPendingOrderTicket, string symbol, ulong magic); bool LastFilledPendingOrderPriceOpen(double &lastFilledPendingOrderPriceOpen, string symbol, ulong magic); bool LastFilledPendingOrderSlPrice(double &lastFilledPendingOrderSlPrice, string symbol, ulong magic); bool LastFilledPendingOrderTpPrice(double &lastFilledPendingOrderTpPrice, string symbol, ulong magic); bool LastFilledPendingOrderSlPips(int &lastFilledPendingOrderSlPips, string symbol, ulong magic); bool LastFilledPendingOrderTpPips(int &lastFilledPendingOrderTpPips, string symbol, ulong magic); bool LastFilledPendingOrderTimeSetup(datetime &lastFilledPendingOrderTimeSetup, string symbol, ulong magic); bool LastFilledPendingOrderTimeDone(datetime &lastFilledPendingOrderTimeDone, string symbol, ulong magic); bool LastFilledPendingOrderExpirationTime(datetime &lastFilledPendingOrderExpirationTime, string symbol, ulong magic); bool LastFilledPendingOrderPositionId(ulong &lastFilledPendingOrderPositionId, string symbol, ulong magic); bool LastFilledPendingOrderMagic(ulong &lastFilledPendingOrderMagic, string symbol, ulong magic); 逐行看:LastClosedPositionCommission 取上一平仓位佣金,引用参数回写;LastClosedPositionInitiatingOrderType 回写起源订单类型(市价或挂单);LastClosedPositionId 回写仓位 ID。LastClosedPositionInitiatedByPendingOrder 用 bool 告诉你这仓是不是挂单触发的。 OpeningOrderTicket / OpeningDealTicket / ClosingDealTicket 分别拿开仓订单号、开仓成交号、平仓成交号,方便你去历史里对账。Duration 是持仓时长(毫秒级 long),结合佣金就能算单位时间成本。 GetLastClosedProfitablePositionData 和 GetLastClosedLossPositionData 直接把盈利仓、亏损仓的整体结构体甩出来,比一个个字段取更省事。挂单侧同理:LastFilledPendingOrder 系列覆盖类型、品种、成交价、SL/TP 价格与点数、布置时间、成交时间、过期时间、关联仓位 ID 和 magic。 实盘里外汇和贵金属波动剧烈、杠杆高风险大,用这些接口做平仓后统计时,注意 magic 过滤错了就会误读别的通畅 EA 的仓位。开 MT5 接上自己 EA 的 history 池,打印 LastClosedPositionDuration 和 Commission,大概率能发现某段行情里持仓过夜成本被低估了。

MQL5 / C++
class="type">bool LastClosedPositionCommission(class="type">class="kw">double &lastClosedPositionCommission, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastClosedPositionInitiatingOrderType(ENUM_ORDER_TYPE &lastClosedPositionInitiatingOrderType, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastClosedPositionId(class="type">ulong &lastClosedPositionId, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastClosedPositionInitiatedByPendingOrder(class="type">bool &lastClosedPositionInitiatedByPendingOrder, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastClosedPositionOpeningOrderTicket(class="type">ulong &lastClosedPositionOpeningOrderTicket, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastClosedPositionOpeningDealTicket(class="type">ulong &lastClosedPositionOpeningDealTicket, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastClosedPositionClosingDealTicket(class="type">ulong &lastClosedPositionClosingDealTicket, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastClosedPositionMagic(class="type">ulong &lastClosedPositionMagic, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastClosedPositionComment(class="type">class="kw">string &lastClosedPositionComment, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastClosedPositionDuration(class="type">long &lastClosedPositionDuration, class="type">class="kw">string symbol, class="type">ulong magic);
class=class="str">"cmt">//--
class="type">bool GetLastClosedProfitablePositionData(PositionData &lastClosedProfitablePositionInfo, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool GetLastClosedLossPositionData(PositionData &lastClosedLossPositionData, class="type">class="kw">string symbol, class="type">ulong magic);
class=class="str">"cmt">//--
class="type">bool GetLastFilledPendingOrderData(PendingOrderData &lastFilledPendingOrderData, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastFilledPendingOrderType(ENUM_ORDER_TYPE &lastFilledPendingOrderType, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastFilledPendingOrderSymbol(class="type">class="kw">string &lastFilledPendingOrderSymbol, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastFilledPendingOrderTicket(class="type">ulong &lastFilledPendingOrderTicket, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastFilledPendingOrderPriceOpen(class="type">class="kw">double &lastFilledPendingOrderPriceOpen, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastFilledPendingOrderSlPrice(class="type">class="kw">double &lastFilledPendingOrderSlPrice, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastFilledPendingOrderTpPrice(class="type">class="kw">double &lastFilledPendingOrderTpPrice, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastFilledPendingOrderSlPips(class="type">int &lastFilledPendingOrderSlPips, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastFilledPendingOrderTpPips(class="type">int &lastFilledPendingOrderTpPips, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastFilledPendingOrderTimeSetup(class="type">class="kw">datetime &lastFilledPendingOrderTimeSetup, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastFilledPendingOrderTimeDone(class="type">class="kw">datetime &lastFilledPendingOrderTimeDone, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastFilledPendingOrderExpirationTime(class="type">class="kw">datetime &lastFilledPendingOrderExpirationTime, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastFilledPendingOrderPositionId(class="type">ulong &lastFilledPendingOrderPositionId, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastFilledPendingOrderMagic(class="type">ulong &lastFilledPendingOrderMagic, class="type">class="kw">string symbol, class="type">ulong magic);

◍ 抓取挂单成交与撤单的尾巴数据

做复盘或预警时,最怕只知道“有挂单成交了”,却拿不到那一张单的成交原因、填充方式、挂单生命周期。下面这组接口把最近一次成交挂单和最近一次被撤挂单的字段全拆开给你,按 symbol + magic 过滤,避免把别的 EA 痕迹混进来。 成交侧四个轻量函数分别回吐 ENUM_ORDER_REASON、ENUM_ORDER_TYPE_FILLING、挂单类型时间、注释;撤单侧则更细,从订单类型、开仓价、SL/TP 点数到建单时间、撤单时间、过期时间一共 19 个字段都能单独取。 实际验证办法:在 MT5 策略测试器里跑一个下挂单的 EA,把 LastCanceledPendingOrderSlPips 打进 Print,观察撤单后返回的点数是否和你设的止损距一致;外汇与贵金属杠杆高,挂单撤改频繁,这类字段拿不准就容易误判策略表现。 BoolToString 和 GetPeriodStart 是配套小工具,前者把布尔转字符串方便写日志,后者按 periodType 取周期起点时间,常用于给撤单统计框定“本根 K 线内”的范围。

MQL5 / C++
class="type">bool LastFilledPendingOrderReason(ENUM_ORDER_REASON &lastFilledPendingOrderReason, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastFilledPendingOrderTypeFilling(ENUM_ORDER_TYPE_FILLING &lastFilledPendingOrderTypeFilling, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastFilledPendingOrderTypeTime(class="type">class="kw">datetime &lastFilledPendingOrderTypeTime, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastFilledPendingOrderComment(class="type">class="kw">string &lastFilledPendingOrderComment, class="type">class="kw">string symbol, class="type">ulong magic);
class=class="str">"cmt">//--
class="type">bool GetLastCanceledPendingOrderData(PendingOrderData &lastCanceledPendingOrderData, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastCanceledPendingOrderType(ENUM_ORDER_TYPE &lastCanceledPendingOrderType, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastCanceledPendingOrderSymbol(class="type">class="kw">string &lastCanceledPendingOrderSymbol, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastCanceledPendingOrderTicket(class="type">ulong &lastCanceledPendingOrderTicket, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastCanceledPendingOrderPriceOpen(class="type">class="kw">double &lastCanceledPendingOrderPriceOpen, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastCanceledPendingOrderSlPrice(class="type">class="kw">double &lastCanceledPendingOrderSlPrice, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastCanceledPendingOrderTpPrice(class="type">class="kw">double &lastCanceledPendingOrderTpPrice, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastCanceledPendingOrderSlPips(class="type">int &lastCanceledPendingOrderSlPips, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastCanceledPendingOrderTpPips(class="type">int &lastCanceledPendingOrderTpPips, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastCanceledPendingOrderTimeSetup(class="type">class="kw">datetime &lastCanceledPendingOrderTimeSetup, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastCanceledPendingOrderTimeDone(class="type">class="kw">datetime &lastCanceledPendingOrderTimeDone, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastCanceledPendingOrderExpirationTime(class="type">class="kw">datetime &lastCanceledPendingOrderExpirationTime, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastCanceledPendingOrderPositionId(class="type">ulong &lastCanceledPendingOrderPositionId, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastCanceledPendingOrderMagic(class="type">ulong &lastCanceledPendingOrderMagic, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastCanceledPendingOrderReason(ENUM_ORDER_REASON &lastCanceledPendingOrderReason, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastCanceledPendingOrderTypeFilling(ENUM_ORDER_TYPE_FILLING &lastCanceledPendingOrderTypeFilling, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastCanceledPendingOrderTypeTime(class="type">class="kw">datetime &lastCanceledPendingOrderTypeTime, class="type">class="kw">string symbol, class="type">ulong magic);
class="type">bool LastCanceledPendingOrderComment(class="type">class="kw">string &lastCanceledPendingOrderComment, class="type">class="kw">string symbol, class="type">ulong magic);
class=class="str">"cmt">//--
class="type">class="kw">string BoolToString(class="type">bool boolVariable);
class="type">class="kw">datetime GetPeriodStart(class="type">int periodType);
class="macro">#class="kw">import

历史管理库的函数分组与落地用法

把历史管理 EX5 库的函数按用途拆开看,比直接翻头文件省事。整体可归为七类:打印指定时段历史、按品种和幻数检索历史、拉全量历史、分析最近平仓、区分最近盈亏平仓、查最近成交或撤销的挂单,以及两个工具函数。 打印类四个函数都是 void 型,不返回值,只接 fromDateTime / toDateTime 两个 datetime 参数,把 deals、orders、positions、pending orders 各自塞进 MT5 日志。调试 EA 时若想确认某天成交,直接传 ONE_DAY 到 NOW 就能在终端日志里看到明细。 检索类允许按交易品种和幻数过滤,结果写进结构体数组,方便后续算胜率或摊薄成本。全量类则不强制时间窗,适合做账户级复盘。分析最近平仓的一组最实用:LastClosedPositionProfit() 取毛利,LastClosedPositionComment() 取备注,LastClosedPositionHoldingTime() 算持仓秒数——这些都能按品种和幻数切分,定位某条策略的尾巴。 最近盈亏平仓各有一个聚合函数,一次调用拿全部属性;挂单侧同理,GetLastFilledPendingOrderData() 与 GetLastCanceledPendingOrderData() 分别覆盖成交和撤销的挂单,下设专用函数取单价、SL/TP 点数距离、设立与执行时间戳。工具函数里 BoolToString() 转字符串便于写日志,GetDateTimeRange() 吃 TODAY / THIS_WEEK 等宏,一行出 datetime。外汇与贵金属杠杆高,用这些函数回测历史时须自行校验点值和库存费,避免误读净值。 下面这段是打印类原型加调用示例,逐行看:void PrintDealsHistory 定义不返回值的成交打印函数,入参为起止时间;注释标明打印过去 24 小时;PrintDealsHistory(ONE_DAY, NOW) 实际用宏调用。其余三个打印函数结构完全一致,只是对象换成 orders、positions、pending orders。检索类开头如 GetDealsData 将 DealData 数组以引用传出,再接时间窗与过滤参数。

MQL5 / C++
class="type">void PrintDealsHistory(
  class="type">class="kw">datetime fromDateTime,
  class="type">class="kw">datetime toDateTime
);
class=class="str">"cmt">// Print the deals history for the last class="num">24 hours(class="num">1 day)
PrintDealsHistory(ONE_DAY, NOW);
class="type">void PrintOrdersHistory(
  class="type">class="kw">datetime fromDateTime,
  class="type">class="kw">datetime toDateTime
);
class=class="str">"cmt">// Print the orders history for the last class="num">24 hours(class="num">1 day)
PrintOrdersHistory(ONE_DAY, NOW);
class="type">void PrintPositionsHistory(
  class="type">class="kw">datetime fromDateTime,
  class="type">class="kw">datetime toDateTime
);
class=class="str">"cmt">// Print the positions history for the last class="num">24 hours(class="num">1 day)
PrintPositionsHistory(ONE_DAY, NOW);
class="type">void PrintPendingOrdersHistory(
  class="type">class="kw">datetime fromDateTime,
  class="type">class="kw">datetime toDateTime
);
class=class="str">"cmt">// Print the pending orders history for the last class="num">24 hours(class="num">1 day)
PrintPendingOrdersHistory(ONE_DAY, NOW);
class="type">bool GetDealsData(
  DealData &dealsData[], class=class="str">"cmt">// [out]
  class="type">class="kw">datetime fromDateTime,
  class="type">class="kw">datetime toDateTime,
交给小布盯盘看盘后诊断
这些历史扫描逻辑小布盯盘的 AIGC 已内置,打开对应品种页即可看到近期平仓与挂单分布,你只需专注策略判断。

常见问题

库封装了检索、排序和筛选,调用如 GetLastClosedPositionData 一行返回结构,避免手写时间区间与类型判断的重复代码。
通常把库放进 Libraries 目录并在 #include 后链接,注意目标位数一致与函数导入声明,无需改原有交易发单逻辑。
手动单幻数为 0,使用自定义筛选器时需显式包含该值,否则只统计 EA 开出的单,分析样本会偏。
可以,小布盯盘品种页的历史面板输出字段与该库函数对齐,便于你把线下分析和线上诊断对照,不必再自己解析报表。
按设计返回最近已成交挂单数据,若区间内无成交则返回空结构,调用方需先做有效性判断再读字段。