Summary: 用MQL4自定义指标为MT4 EA搭建专属消息窗口,解决Comment()一闪而过和Alert()无法追溯的痛点,引用官方文档并附实战代码。




我受够了错过MT4的报警。不是因为我不专心,而是MT4里那个Comment()函数,基本上就是个摆设。你在左上角写一句话,下一笔tick过来直接给你清了。Alert()更离谱,弹个窗几秒钟就没了,或者响个声音——要是你刚好不在电脑前,等于白报。

上个月我在测一个新EA,回测跑了一个小时回来看,中间发生过什么事完全不知道。开过几单、有没有报错、改过几次止损,全没记录。我就开始翻MQL4的文档,还真让我找到了一个大多数人都跳过去的东西——#property indicator_separate_window加上ObjectCreate()画标签的方法。

默认的报警方式为什么不好用



在讲解决方案之前,我先说一下为什么MT4默认的那几招对跑回测的人来说都不太顶用。

Comment()在图表角落显示文本,简单,但它只保留你最后写的那句话。下一笔tick一来,前面的全没了。如果你的EA在一个tick里干了好几件事——开仓、改止损、报个错——你只能看到最后一条,前面的信息全丢。

Alert()弹个窗,但弹窗不堆叠。EA连续触发三条报警,你可能只看到最后一条就没了。

Print()往终端的"EA交易"标签页里写日志,这个其实还行,但你要手动去翻,而且那个标签页里还混着其他EA和终端自己的各种信息,看得很累。

我想要的是能持续显示、像聊天记录一样往上堆、而且不用我去翻日志的东西。

自定义指标做消息窗口



MQL4文档其实专门有一节讲这个,在"创建普通程序"那一章里。方案是用一个自定义指标,这个指标的唯一作用就是开一个子窗口,然后在里面用图形对象显示文本消息。指标本身不做任何计算,就是个容器。

核心思路是这样的:
  • 建一个自定义指标,声明#property indicator_separate_window

  • 指标OnCalculate()函数是空的,不干活

  • 用一个单独的包含文件(Inform.mqh)来管理所有图形对象的创建和排布

  • 每来一条新消息,就加到列表最下面,旧消息整体往上移一行


  • MQL4教程里给了一个完整的模板。Inform()函数接收消息编号和可选的整数/实数参数,然后创建一个标签对象存起来,通过调整Y坐标来滚动消息列表。

    第一步:建一个容器指标



    MetaEditor里新建一个自定义指标,叫Inform.mq4,代码极其简单:

    ``mql4
    //--------------------------------------------------------------------
    // Inform.mq4
    // 仅供学习参考使用
    //--------------------------------------------------------------------
    #property indicator_separate_window // 独立的指标窗口
    //--------------------------------------------------------------------
    int start() // 特殊函数start()
    {
    }
    //--------------------------------------------------------------------
    `

    就这么几行。指标本身什么事都不干,就是开一个子窗口让你写消息。

    第二步:消息管理逻辑



    真正干活的是
    Inform.mqh。MQL4教程里给了一个完整的实现,最多能存30条消息,新消息来了旧的自动往上滚。

    几个关键函数:

    Inform(0)——每笔tick调用一次,检查消息是不是超时了。连续15秒没有新消息,所有已显示的消息就变灰色。这个设计很贴心——瞟一眼颜色就知道EA是不是还活着。

    Inform(-1)——EA卸载的时候调用,把所有图形对象删掉。做清理很重要,因为MT4不会自动清理你创建的标签。

    Inform(Mess_Number, Number, Value)——主函数。根据Mess_Number生成对应格式的消息。每个编号对应一个模板,比如"Closed order Buy X"或者"Not enough money for X lots"之类。

    消息系统用一个数组
    Name_Grf_Txt[30]存所有标签的名字。来新消息的时候:
  • 删掉第29条(最老的那条)

  • 把第28到第0条全部上移一个位置

  • 在最下面新建一个标签


  • 这样你就有了一个能滚动的30条消息历史,而且还能按类型设颜色。

    第三步:把消息系统挂到自己的EA里



    要在自己的EA里用这个,先把
    Inform.mq4放到MQL4/Indicators目录里编译一遍。再把Inform.mqh放到MQL4/Include目录。

    在EA代码里加上:

    `mql4
    #include
    `

    然后想发消息的时候直接调
    Inform()就行:

    `mql4
    Inform(1, ticket); // "Closed order Buy X"
    Inform(11, 0, lots); // "Not enough money for X lots"(红色字体)
    `

    函数内部还带了
    PlaySound(),所以音频提醒和文字记录一块来,不会错过。

    为什么这个方案比别的都好用



    这个方案解决的是"离开一会儿回来不知道发生了什么"的问题。你跑出去喝杯水再回来,消息窗口里清清楚楚列着EA在你这段时间里干了什么。不用翻日志、不用猜刚才那个声音是开仓还是报错。

    我最近三周在三个不同EA上都用了这套。每个EA单独开一个消息窗口,互不干扰。跑回测的时候,我能看到完整的事件序列,不用停掉回测去翻日志。

    性能方面有个坑要注意



    图形对象不停地创建和删除,如果你每秒发几十条消息,EA确实会变慢。但MQL4教程里的实现只用了30个对象,来了新消息就复用旧的,不会无限制地新建,所以性能开销其实还好。

    如果是高频策略,可以把消息数量砍到10或15条,改一下数组大小和循环上限就行。

    说个真实例子



    上周我有个EA老是在不该平仓的时候自己平掉。我把
    Inform()加到了所有决策点——入场条件、止损触发、止盈触发。EA再瞎操作的时候,我直接看消息窗口就知道它在哪一步抽风了。最后查出来是移动止损的计算逻辑写错了。如果没有消息历史,我可能要在日志里翻半天才能找到问题。

    MQL4官方教程里"Combined Use of Programs"那一章有一个完整示例,展示了怎么把这个消息系统跟
    iCustom()`结合起来做基于自定义指标的交易决策。

    参考来源:MQL4教程 – 创建普通程序(book.mql4.com),MQL4参考 – 自定义指标(docs.mql4.com),MQL4教程 – 程序的组合使用(book.mql4.com)。

    本文首发于FXEAR.com,原创内容,未经授权禁止转载。