精通日志记录(第七部分):如何在图表上显示日志·综合运用
把日志数组拼成可读文本串
在 MT5 的 EA 或指标里,把多行日志整理成一段带前缀的文本,是调试面板输出的常见需求。下面这段循环从配置长度 m_config.size 读取日志数组 m_logs,逐行拼接到 result 字符串。 循环边界用 i <= m_config.size-1,意味着把数组里全部元素都走一遍,而不是常见的 i < size 写法,两者在 size 为 0 时行为一致,但前者更容易让人误以为会越界。 若某行 formated 不为空,就拼上 side 前缀和换行;为空则只补一个带 side 的空行。最终函数返回完整 result。外汇与贵金属行情跳动快,这类文本拼接建议在低频事件里跑,避免每 tick 都重建字符串拖慢执行。
for(class="type">int i = class="num">0; i <= m_config.size-class="num">1; i++) { class="type">class="kw">string line = m_logs[i].formated; if(line != "") { result += side + " " + line + "\n"; } else { result += side + "\n"; } } } class="kw">return result; }
「收尾时清掉图表注释」
CLogifyHandlerComment 类还差一个收口动作:处理程序退出时把图表上之前用 Emit() 写上去的 Comment 文本抹掉。Emit() 负责显示,Close() 就负责反向清空,逻辑对称。 和其他要关文件、断连接、释放内存的处理器不同,这里只需从图表移除注释。MetaTrader 给的办法很直白——不带参数调用 Comment(),也就是 Comment(""),屏幕上的文字立刻消失。 下面这段是 Close() 方法本体,只做一件事: //+------------------------------------------------------------------+
| // | Closes the handler and releases any resources |
|---|
//+------------------------------------------------------------------+ void CLogifyHandlerComment::Close(void) { //--- Clear Comment(""); } //+------------------------------------------------------------------+ 逐行看:函数声明为 void 返回、无入参;进入作用域后仅一行注释加一句 Comment(""),空字符串触发终端清除图表注释。没有资源泄漏风险,也不需要额外析构逻辑。 在 EA 的 OnDeinit() 里调一下这个 Close(),能在品种切换或终止运行时避免旧提示残留在图上。外汇与贵金属波动剧烈、高风险,这类清理虽小,但能减少误读屏幕信号的概率。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Closes the handler and releases any resources | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void CLogifyHandlerComment::Close(class="type">void) { class=class="str">"cmt">//--- Clear Comment(""); } class=class="str">"cmt">//+------------------------------------------------------------------+
◍ 把图表日志处理程序跑起来看效果
光看接口定义没用,得在 MT5 图表上实跑才能确认 CLogifyHandlerComment 是不是真能替你盯盘。我们写了个最简脚本,模拟 EA 从启动到崩坏的全过程:调试、信息、警报、错误、致命,五级日志全触发一遍。 测试时把面板设成单线边框、日志向下滚动(最新在底部),size 给 10 行,标题写死成 "Expert name"。Sleep() 不是必选项,但脚本里用 1500/800/800/500/100 毫秒的间隔把事件拉开,不然五条日志同一帧砸出来,根本分不清时序。 外汇和贵金属盘面事件间隔本就随机,这种人为延时只是让肉眼能追上滚动速度;真实 EA 里你该按事件自然发生节奏来,别硬塞 Sleep 拖慢主线程。 代码里的 formatter 用了 "hh:mm:ss" 加 "[{levelname}]: {msg}",RSI 那行会打出 "RSI indicator value calculated: 72.56" 并带 Period:14 的上下文——你复制去跑,EURUSD 0.1 手的买单日志和 12345678 号订单的止损调整警报应该依次落到底部。跑完若图表能逐行推旧留新,这处理程序就算验证可用。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Import CLogify | class=class="str">"cmt">//+------------------------------------------------------------------+ class="macro">#include <Logify/Logify.mqh> CLogify logify; class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Expert initialization | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">int OnInit() { class=class="str">"cmt">//--- Handler config MqlLogifyHandleCommentConfig m_config; m_config.size = class="num">10; class=class="str">"cmt">// Max log lines m_config.frame_style = LOG_FRAME_STYLE_NONE; class=class="str">"cmt">// Frame style m_config.direction = LOG_DIRECTION_UP; class=class="str">"cmt">// Log direction(up) m_config.title = "Expert name"; class=class="str">"cmt">// Log panel title class=class="str">"cmt">//--- Create and configure handler CLogifyHandlerComment *handler_comment = new CLogifyHandlerComment(); handler_comment.SetConfig(m_config); handler_comment.SetLevel(LOG_LEVEL_DEBUG); class=class="str">"cmt">// Min log level handler_comment.SetFormatter(new CLogifyFormatter("hh:mm:ss", "{date_time} [{levelname}]: {msg}")); class=class="str">"cmt">//--- Add handler to Logify logify.AddHandler(handler_comment); class=class="str">"cmt">//--- Test logs logify.Debug("Initializing Expert Advisor...", "Init", ""); Sleep(class="num">1500); logify.Debug("RSI indicator value calculated: class="num">72.56", "Indicators", "Period: class="num">14"); Sleep(class="num">800); logify.Info("Buy order sent successfully", "Order Management", "Symbol: EURUSD, Volume: class="num">0.1"); Sleep(class="num">800); logify.Alert("Stop Loss adjusted to breakeven level", "Risk Management", "Order ID: class="num">12345678"); Sleep(class="num">500); logify.Error("Failed to send sell order", "Order Management", "Reason: Insufficient balance"); Sleep(class="num">100); logify.Fatal("Failed to initialize EA: Invalid settings", "Initialization", "Missing or incorrect parameters"); class="kw">return(INIT_SUCCEEDED); } class=class="str">"cmt">//+------------------------------------------------------------------+
别急着下结论
Logify 这套 MQL5 日志库到这节算是把骨架搭完了:从核心类 Logify.mqh 到 Comment 图表处理器,覆盖了级别筛选、格式化、文件与数据库落盘。文件清单里 Experts/Logify/LogiftTest.mq5 是直接可跑的验证入口,开 MT5 加载就能看到带时间戳和上下文的日志流。 不过技术保鲜期短。作者原话提到数据库处理器目前只是打印占位,真正写 sqlite 还没落地;IntervalWatcher.mqh 虽能跑定时例程,但是否扛得住高频 tick 没给回测。外汇与贵金属 EA 调试涉及实盘,属于高风险场景,别把库当免死金牌。 真要上手,先改 LogifyHandlerComment.mqh 里的输出字段,把仓位上下文塞进图表注释,比单纯看终端省一半盯盘时间。剩下的坑,等下一篇更新再填。