来自专业程序员的提示(第一部分):代码存储、调试和编译。 操控项目和日志·进阶篇
(2/3)· 当 EA 跨模拟与实盘反复拷贝出错,是时候把项目结构和日志当成生产系统来管
用 Git 管住你的 MQL5 代码
写 EA 和指标的人常忽略一件事:MT5 里的 .mq5 和 .mqh 跟普通源码一样会越改越乱,尤其是你同时在测多个版本策略时。团队开发更不用说,没有版本控制,回滚一次旧逻辑能折腾半天。Git 是目前最直接的选择,本地仓库加实验分支,切版本基本是一键的事。 实操上,装 Git 命令行加 TortoiseGit 图形壳就够了。在 D:\Project\MQL5 下放一个 .gitignore,决定哪些文件进版本库、哪些永远不跟踪。上面那段忽略规则里,*.ex4/*.ex5 编译产物直接排除,Experts/* 这类目录内容全忽略,但 !Experts/Cayman 又把你自己写的 Cayman 策略目录拉回来——这套白名单式写法能避免把平台自带库全传上云。 云端用 Bitbucket 个人仓免费,仓名跟项目对齐(比如 CaymanMQL5)就行。本地首提交后 Push 上去,硬盘坏掉也不丢代码。平时改完一段逻辑就 Commit 并写清备注,日后查历史比翻聊天记录靠谱得多。 下面是该 .gitignore 的完整内容,复制进文件即可生效:
# 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 目录,防止把调试态配置覆盖进实盘。 外汇与贵金属杠杆高,模拟与实盘即使同策略,滑点和点差也可能让结果偏移,同步后务必在实盘观察前几单的执行日志。
@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> ( %METAEDITOR% /compile:%%F /<span class="functions">log</span> type %%~dpnF.<span class="functions">log</span> ) 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> ( %METAEDITOR% /compile:%%F /<span class="functions">log</span> 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 目录,双击或命令行调,比肉眼扫几千行实在。
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