MQL5 调试三板斧:Comment、Alert、Print 与 CLogger
一、三种手段:评估、逐步调试、写日志
原文把“找错”分成三类:评估结果对不对、用断点逐步调试、把过程写进日志。记录函数最常用的是 Comment、Alert、Print 三个。它们解决的问题不同:想实时看当前值用 Comment,想弹窗+声音提醒用 Alert,想持续落盘分析用 Print。
二、Comment / Alert / Print 的区别
- Comment():在图表左上角显示当前状态,不落盘,适合即时看变量,但输出受限、只显当前值、偏慢。
- Alert():弹独立窗口+声音,同时写入 Terminal_dir\MQL5\Logs\data.txt,但频繁调用会冻结终端,策略测试器里不适用。
- Print():写入终端“Experts”选项卡和 Logs\data.txt,无声音、最适合作持续记录,但所有信息混写一个日志、不便分组。
三、CLogger:把日志写进独立文件
三个内置函数不够灵活,原文给出 CLogger.mqh 把日志封装成文件类:按项目名+日期建文件、自动加时间戳、支持消息分类与颜色、带缓存按条数/时间刷盘。用法:
#include <CLogger.mqh>
CLogger logger;
logger.SetSetting("我的项目","我的日志","注释",60);
logger.init();
logger.write("测试消息","错误",Red,__FILE__,__LINE__);
logger.flush(); logger.deinit();
四、调试技巧:分级输出
原文用一个 input int dLvl 控制输出级别(0 紧急红、1 通知、2 调试),再用 debug() 函数比较级别决定是否输出。这样不用改源码就能在“安静运行”和“详细排错”之间切换。配合 Print/Alert 快速定位:循环里 Print(i) 能找出“本该赋值却没赋”的漏网之鱼。
五、常见错误与排查清单
六、实战建议
小 EA 用 Print+级别宏足够;大型项目用 CLogger 分文件、分类、带缓存更可控。日志路径在 MQL5\Files\ 下,超 10MB 自动分新文件。推荐配合 LogMon 这类查看器按分类/颜色/声音监控。切记:调试代码在发布前应降级或移除,避免污染正式日志。
七、把调试输出封装成可分级宏
正式项目推荐把 Print/Alert 包一层级别判断,这样发布时把级别调高就能静默,排错时调低就详细。下面这种轻量宏思路既不需要 CLogger 也能用:
#define DBG_LVL 2 // 0 紧急 1 通知 2 调试
void dbg(int lvl, string msg)
{
if(lvl<=DBG_LVL) PrintFormat("[DBG %d] %s", lvl, msg);
}
// 用法:dbg(2, "i="+(string)i); 发布时 DBG_LVL 设 0 即可屏蔽调试输出
八、排错清单(按出现频率)
九、分级日志设计
日志别只 Print 一把梭,要分级:INFO 记录正常流程、WARN 记录可疑(如滑点偏大)、ERROR 记录异常(下单失败)。分级后你能在海量输出里只筛 ERROR,快速定位问题。
每条日志带时间戳、上下文(品种、ticket、函数名),出事时才能还原现场。没上下文的日志等于没记。
十、用日志定位两类经典 bug
「不开仓」:开 INFO 日志看信号函数每 tick 的返回值,若长期是 0,说明信号条件永远不满足或数据未就绪;「重复开仓」:看 OnTrade 是否在事件里又发单,或信号没去重每 tick 都触发。
void Log(int level, string ctx, string msg)
{
if(level < LOG_LEVEL) return;
Print(TimeToString(TimeCurrent()), " [", ctx, "] ", msg);
}
十一、日志性能:高频 Print 的代价
每 tick 都 Print 到终端会严重拖慢 EA,尤其多品种。正确做法:调试期用 Print,上线前改用 CLogger 写文件(异步、批量),或只记录 WARN/ERROR 级。文件日志还能事后离线分析。
CLogger 把日志落盘到 Files 目录,配合回测日志,你能精确复盘「哪笔在什么行情下成交」,这是系统化最被低估的透明度红利。