来自专业程序员的提示(第一部分):代码存储、调试和编译。 操控项目和日志·进阶篇
🗂️

来自专业程序员的提示(第一部分):代码存储、调试和编译。 操控项目和日志·进阶篇

(2/3)· 当 EA 跨模拟与实盘反复拷贝出错,是时候把项目结构和日志当成生产系统来管

进阶 第 2/3 篇
把同一个 EA 在三个终端里各改一版,最后谁才是线上真的跑的那版?很多人调试到崩溃,才发现自己从没统一过代码源。用复制粘贴同步策略,等于主动埋下不可复现的 bug。

用 Git 管住你的 MQL5 代码

写 EA 和指标的人常忽略一件事:MT5 里的 .mq5 和 .mqh 跟普通源码一样会越改越乱,尤其是你同时在测多个版本策略时。团队开发更不用说,没有版本控制,回滚一次旧逻辑能折腾半天。Git 是目前最直接的选择,本地仓库加实验分支,切版本基本是一键的事。 实操上,装 Git 命令行加 TortoiseGit 图形壳就够了。在 D:\Project\MQL5 下放一个 .gitignore,决定哪些文件进版本库、哪些永远不跟踪。上面那段忽略规则里,*.ex4/*.ex5 编译产物直接排除,Experts/* 这类目录内容全忽略,但 !Experts/Cayman 又把你自己写的 Cayman 策略目录拉回来——这套白名单式写法能避免把平台自带库全传上云。 云端用 Bitbucket 个人仓免费,仓名跟项目对齐(比如 CaymanMQL5)就行。本地首提交后 Push 上去,硬盘坏掉也不丢代码。平时改完一段逻辑就 Commit 并写清备注,日后查历史比翻聊天记录靠谱得多。 下面是该 .gitignore 的完整内容,复制进文件即可生效:

MQL5 / C++
# exclude files
*.ex4
*.ex5
*.dat
log.txt
# exclude directories completely
Images
Indicators
Libraries
Logs
Presets
Profiles
Services
"Shared Projects"
Levels
Params
# exclude directory contents
Experts/*
Files/*
Include/*
Scripts/*
# except for directories
!Experts/Cayman
!Files/Cayman
!Include/Cayman
!Scripts/Cayman
!Scripts/CaymanDev

◍ 用模拟终端隔离调试再同步实盘

EA 上线后,实盘终端里只放编译好的二进制文件(*.ex?),源码 *.mq? 不要留在生产环境,避免误改和泄露逻辑。所有断点、打印、参数试错都应在模拟账户对应的独立 MT5 终端完成,这样实盘成交流不会被调试动作干扰。 调试通过的版本,用一份 robocopy 批处理从模拟端 MQL5 目录镜像到实盘终端目录即可,比手动拖文件稳妥。下面这段批处理只同步 Experts / Scripts 下的 *.ex?,Files 里排除 AppSettings.txt 和 Levels、Params 目录,防止把调试态配置覆盖进实盘。 外汇与贵金属杠杆高,模拟与实盘即使同策略,滑点和点差也可能让结果偏移,同步后务必在实盘观察前几单的执行日志。

MQL5 / C++
@echo off
setlocal
set PROJECT=Cayman
set SOURCE=d:\Project\MQL5
set TARGET=c:\Users\Pro\AppData\Roaming\MetaQuotes\Terminal\2E8DC23981084565FA3E19C061F586B2\MQL5
set PARAMS=/MIR /NJH /NJS
rem MIR - MIRror a directory tree and class="kw">delete dest files/folders that no longer exist in source
rem NJH - No Job Header
rem NJS - No Job Summary
echo Copy *.ex? class=class="str">"cmt">// Source to Production
echo Source = %SOURCE%
echo Production = %TARGET%
robocopy %SOURCE%\Experts\%PROJECT% %TARGET%\Experts\%PROJECT% *.ex? %PARAMS%
robocopy %SOURCE%\Scripts\%PROJECT% %TARGET%\Scripts\%PROJECT% *.ex? %PARAMS%
rem Copy all files except AppSettings.txt, [Levels], [Params]
robocopy %SOURCE%\Files\%PROJECT% %TARGET%\Files\%PROJECT% *.* %PARAMS% /XF AppSettings.txt /XD Levels Params
robocopy %SOURCE%\Scripts\Cayman %TARGET%\Scripts\Cayman *.ex? /NJH /NJS
robocopy %SOURCE%\Scripts\CaymanDev %TARGET%\Scripts\CaymanDev *.ex? /NJH /NJS
echo.
endlocal
pause

「一次性编译所有代码文件」

目标是维持代码一致性。 故此,您应该避免某些修改,例如函数参数。 智能交易系统能够顺利地编译,但也有可能某个脚本会调用旧版函数。 脚本 (之前编译的) 可以运行良好,但它不会执行所需的功能。 对于批处理编译,您可以采用以下文件: [CODE] @echo off setlocal set METAEDITOR=<span class="string">"C:\Program Files\RoboForex - MetaTrader 5\metaeditor64.exe"</span> set CAYMAN=d:\Project\MQL5\Scripts\Cayman set CAYMAN_DEV=d:\Project\MQL5\Scripts\CaymanDev echo METAEDITOR=%METAEDITOR% echo CAYMAN=%CAYMAN% echo CAYMAN_DEV=%CAYMAN_DEV% echo. echo Wait compile... D: cd %CAYMAN% echo %CAYMAN% <span class="keyword">for</span> %%F in (*.mq?) <span class="keyword">do</span> ( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;%METAEDITOR% /compile:%%F /<span class="functions">log</span> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;type %%~dpnF.<span class="functions">log</span> )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; del *.<span class="functions">log</span> cd %CAYMAN_DEV% echo %CAYMAN_DEV% <span class="keyword">for</span> %%F in (*.mq?) <span class="keyword">do</span> ( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;%METAEDITOR% /compile:%%F /<span class="functions">log</span> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;type %%~dpnF.<span class="functions">log</span> ) del *.<span class="functions">log</span> endlocal echo. pause [/CODE]

用看板把MQL开发拆成可追踪的阶段

对个人开发者来说,一套轻量的任务系统比脑子记更靠谱,尤其是同时跑 MQL5 和网站这类多线项目时。我用的 ZenKit 对小型团队免费,核心就是一块可拖拽的 Kanban 板,不用来回切多个项目板导致看不见全局。 我把所有事收进一个板,按开发阶段分列:Legend 放项目说明和常链不动;Cayman 装 MQL5/MQL4 任务;Website 装个人站任务;Accepted 是进行中;Done 是已收口。发现 bug 或思路,建卡丢进对应列,开工就拖到 Accepted,测完拖去 Done。 板子跑起来后有个硬指标很好用——数每列的任务卡数。哪个列长期爆仓(overloaded),就是瓶颈所在。我的做法是优先从超载列捞活干,目标是让几个项目的待办量趋于接近,而不是某个坑越积越深。团队版常带 Testing 列, solo 开发用不上,去掉反而干净。

◍ 用批处理给单一品种抽日志

MT5 里 Print 的输出全堆在 MQL5\Logs\yyyyMMdd.log,一个文件里 EURUSD、XAUUSD、GBPJPY 全混着,翻某品种的信号像捞针。 写个 findLog.cmd 用系统 find 按品种名过滤就行:丢进日志文件名和品种关键字,它直接吐出「原文件名-品种名.log」。比如对 20200515.log 跑 gbpjpy,就得到 20200515-gbpjpy.log,只留该货币对的打印行。 外汇与贵金属波动剧烈、杠杆高风险大,这类日志筛选只帮你快速复盘某品种的历史打印,不预示任何方向。把脚本丢进 Logs 目录,双击或命令行调,比肉眼扫几千行实在。

MQL5 / C++
echo off
if "%class="num">2"=="" goto Help
find /I "%class="num">2" < %class="num">1 > "%~n1-%class="num">2.log"
goto Exit
:Help
echo.
echo Filter log-file
echo findLog.cmd logFile text
echo Example
echo findLog.cmd class="num">20200515.log gbpjpy
echo Result
echo class="num">20200515-gbpjpy.log
echo.
pause
:Exit
把多终端差异交给小布盯盘看
这些诊断小布盯盘的 AIGC 已内置,打开对应品种页即可看到不同终端 EA 加载状态与报错摘要,你只管决定哪条分支进实盘。

常见问题

通常只跟踪自己项目子目录(如 Experts/Cayman、Include/Cayman),忽略终端自动生成的缓存和日志文件,避免每次编译产生无意义 diff。
Windows 用 mklink /D,macOS 或 Linux 用 ln -s;核心都是让终端数据目录里的 MQL5 指向同一份项目源码,减少重复副本。
隔离日志与图表环境可避免调试脚本污染实盘配置,也方便一次性清掉 Dev 脚本而不动生产 EA。
目前小布盯盘聚合的是品种页层面的运行异常与信号状态,原生日志高亮仍需在终端里按本文配置,但异常摘要会自动进看板。
开启上下文搜索并在项目根做编译,错误信息里的相对路径配合 TotalCommander 搜关键字,比逐文件打开快得多。