构建自动运行的 EA(第 07 部分):账户类型(II)·综合运用
📘

构建自动运行的 EA(第 07 部分):账户类型(II)·综合运用

第 3/3 篇

「EA 被踢出图表时析构函数怎么清场」

析构函数不像普通类方法那样由你主动调用,它只在类对象消亡那一刻由系统触发一次。问题在于,对象何时消亡往往由编译器决定,你很难精确干预;但当 EA 从图表被移除时,恰恰是析构函数派上用场的时机。 我们可以在管理类里加一个自定义错误枚举值,比如 ERR_Excommunicate,用来标记“EA 因严重错误被强制踢出图表”。析构函数内部不去接收参数,而是读取 _LastError 判断是不是这个值,进而决定要不要替 EA 擦屁股。 代码逻辑很直接:若 _LastError 等于 ERR_USER_ERROR_FIRST + ERR_Excommunicate,说明 EA 是被赶走的。此时若有挂单(m_TicketPending > 0)就发删除请求,若有持仓(m_Position.Ticket > 0)就发平仓请求,最后在终端打印一句被踢原因。 别把这套当保险丝。EA 可能因为极端行情或平台强制回收而被瞬间终止,析构函数根本来不及跑。外汇和贵金属杠杆高、滑点凶,你作为交易者得自己养成习惯:每次手动移除 EA 后,去工具箱确认挂单和持仓是否真清零。 下面这段 MQL5 是析构函数的实际写法,注意高亮行的判断与两个 if 分支:

MQL5 / C++
class C_Manager : class="kw">private C_Orders
{
      enum eErrUser {ERR_Unknown, ERR_Excommunicate};
      class="kw">private :
            ~C_Manager()
            {
                  if (_LastError == (ERR_USER_ERROR_FIRST + ERR_Excommunicate))
                  {
                        if (m_TicketPending > class="num">0) RemoveOrderPendent(m_TicketPending);
                        if (m_Position.Ticket > class="num">0) ClosePosition(m_Position.Ticket);
                        Print("EA was kicked off the chart for making a serious mistake.");
                  }
            }

◍ 给 EA 留一点容错余地

把 C_Manager 写成零容忍并不现实。市场休市返回的 TRADE_RETCODE_MARKET_CLOSED,或终端里禁用了算法交易导致的 TRADE_RETCODE_CLIENT_DISABLES_AT,都不是 EA 逻辑本身的错,这类情形应当被放过。 我们在 C_Manager 里放了一个公开的 CheckToleranceLevel,让 EA 在怀疑出错时来问一句“这错严不严重”。它只按 _LastError 做分流:成功就直接 return;未知类严重错误打印后调用 SetUserError 挂异常并 ExpertRemove 把自己从图表踢掉;其余低严重度错误仅提示并 ResetLastError 清掉标记。 下面这段就是该函数的骨架,注意 ERR_USER_ERROR_FIRST + ERR_Unknown 分支代表不可恢复故障,default 分支代表可容忍噪声: 别把容错写成摆设 原文示例里 C_Manager 并未主动调用 CheckToleranceLevel,容错能力只是“理论上很高”。实战中你应在下单、改仓、查持仓等固定代码点插入调用,否则真出错时 EA 会静默留在图上继续乱跑。外汇与贵金属杠杆高,这类静默故障可能放大滑点与错单风险。

MQL5 / C++
                class="type">void CheckToleranceLevel(class="type">void)
                {
                    class="kw">switch (_LastError)
                    {
                        case ERR_SUCCESS: class="kw">return;
                        case ERR_USER_ERROR_FIRST + ERR_Unknown:
                            Print("A serious error has occurred in the EA system. This one cannot class="kw">continue on the chart.");
                            SetUserError(ERR_Excommunicate);
                            ExpertRemove();
                            break;
                        class="kw">default:
                            Print("A low severity error has occurred in the EA system. Your code is:", _LastError);
                            ResetLastError();
                    }
                }

下一篇才碰 EA 编码的雷

前两篇把类系统的底层逻辑铺开了,这一节只是个过渡:手动验证能跑通,不代表自动 EA 能直接搬。MT5 里挂 EA 涉及计时、滑点和上下文丢失,坑比看代码多。 作者原序列里下一篇才讲 EA 编码的预防措施和风险,现在你能做的只有一件事——把前两层例子在策略测试器里手跑一遍,确认自己对类生命周期的理解没偏差。 外汇和贵金属杠杆高,EA 任何自动化都先当会爆仓的玩具看。等下篇出来,再决定哪些逻辑值得写成自动单。

常见问题

重点释放已开指标句柄、删除自建图形对象、平掉或标记挂单。不清理会导致指标泄漏和图表残留线,下次加载容易报错。
在订单发送前加滑点上限与重试次数,并用IsStopped()检测终止信号及时退出循环。别把容错写死,按品种波动调参数。
可以。小布能读取你的EA代码并标出未释放的句柄与残留对象,给出修改建议,省去你手动逐行排查。
先搞清生命周期与容错边界,后面写交易逻辑才不会一上线就崩。基础清场和容错是实盘存活的前提。
高波动时段挂单更易滑点失控,清场时务必遍历PositionSelect遍历平掉市价单并Delete按魔术码删挂单。