让手动回测变得简单:为MQL5策略测试器构建自定义工具包(基础篇)
「给MT5策略测试器攒一套手动回放装备」
MT5自带的策略测试器默认走的是历史数据自动优化,但做价格行为研究的人往往更想自己一帧帧拨K线。原生界面里没有顺手的“手动回放+标注”入口,每次要切周期、拖光标、记点位,很碎。 社区里已有开发者把这类需求做成了自定义脚本工具包,挂在测试器面板上就能逐根推进行情,并实时写入注释。根据2025年12月9日发布的公开讨论帖,该工具包发布后约一周内获得881次查看、6条反馈,说明手动回测这个小众痛点确实有真实用户群。 对外汇与贵金属这类高杠杆品种,手动回测能帮你把止损位卡在结构边缘而不是凭感觉;但历史重放不等于未来概率,任何从回测得到的偏好都只是“可能”更优,实盘仍需小仓位验证。
把手动盘感塞进 MT5 测试器
手动回测常卡在两个极端:要么全自动化把思路锁死,要么纯手工缺乏统一精度。MT5 策略测试器本是为 EA 设计的,但借助自定义 MQL5 程序,可以把人工下单逻辑也跑进去。 这套思路的核心,是用一个轻量 EA 在测试器里模拟你手动操作的节奏——开仓、止损、平仓都由你预设规则触发,而非黑盒优化。 原文给出的落地路径分四步:先规划工具包结构,再用 MQL5 实现,接着在测试器里实战回测,最后收尾。读完你该做的只有一件事:打开 MT5,新建一个 EA 把手动条件写成代码,跑一遍自己最熟的那套贵金属策略,外汇与贵金属杠杆高,回测结果仅代表历史概率,实盘仍可能大幅偏离。
◍ 用图表按钮把手动交易塞进策略测试器
传统手动回测最头疼的是实时报价太慢,一根根等 K 线根本测不完一个策略。MetaTrader 5 的策略测试器能加速跑历史,但它原生不支持你边看边手动下单。我们的做法是写一个 EA,在图表上挂一排按钮:触发买、触发卖、改手数、设 SL/TP,再配一个一键清仓的 Panic 按钮。 这套东西不挑策略,指标、K线形态、纯价格行为都能接。你在测试器里以加速速度跑行情,遇到信号点按钮模拟进场,相当于把人的判断和机器的回放速度揉在一起。外汇与贵金属杠杆高、滑点跳空频繁,模拟结果仅代表历史概率,不等于实盘表现。 实机上验证很简单:开 MT5 → 策略测试器选任意品种 → 加载这个 EA → 切到「逐笔」或加速模式 → 看图表按钮是否实时响应。能跑通,你的手动验证效率至少提升一个数量级。
「在MT5里搭一个可手动回测的下单面板」
想在策略测试器里做手动回测,核心是先定义一组图表按钮和几个可调参数,再把交易执行交给 CTrade 类。初始手数写死成 0.03,止损止盈的步进用 slow_pts=10、fast_pts=100 两个点值档位,这样后面能随时微调,不用改代码重编译。 按钮不是一个个硬写,而是封装成 CreateBtn 函数:传 objName、xD/yD(左上角起算的像素坐标)、xS/yS(宽高)、txt(标签)就行。内部用 ObjectCreate 建 OBJ_BUTTON,基准锚在 (0,0,0),再用 ObjectSetInteger 把 XDISTANCE/YDISTANCE/XSIZE/YSIZE 和 CORNER_LEFT_UPPER 设好,字体默认 Calibri 13号,最后 ChartRedraw(0) 刷新。OnInit 里调用它摆出 BTN_BUY(绿底110,70)、BTN_SELL(红底220,70)、BTN_CLOSE(黑底110,100 写 PANIC BUTTON (X)),以及手数加减箭头 BTN_P(150,45 上箭头)、BTN_M(250,45 下箭头)。 测试器不支持 OnChartEvent,所以按钮状态全靠 OnTick 轮询。GetState 用 ObjectGetInteger 读 OBJPROP_STATE 判断是否被点;GetValue 读 OBJPROP_TEXT;GetValueHL 读 OBJPROP_PRICE 拿水平线价格。点下 BTN_BUY/BTN_SELL 就把 tradeInAction 置真,随后 CreateTradeLevels 用 Bid±100_Point / Ask±100_Point 画出红绿虚点线 HL_SL、HL_TP,并生成 BTN_SL1M 这类加减按钮和 BTN_YES/BTN_NO 确认键。 真正下单时,BTN_BUY+BTN_YES 为真就 obj_Trade.Buy(double(GetValue(BTN_LOT)), _Symbol, Ask, GetValueHL(HL_SL), GetValueHL(HL_TP));卖单对称换 Bid。完事 DeleteObjects_SLTP 清掉十几个对象,tradeInAction 和 isHaveTradeLevels 复位。手数调整由 BTN_P/BTN_M 触发,以 SYMBOL_VOLUME_STEP 为步长加减,上限锁 0.1、下限不低于步长,归一两位小数。外汇和贵金属杠杆高,面板只是回测辅助,实盘映射前务必先在策略测试器跑通逻辑。
一键清仓的循环逻辑与按钮复位
closeAllPositions 的核心是从持仓末尾倒序清扫:用 PositionsTotal 拿到总数,索引从“总数减1”一路降到 0,对每个 i 调用 PositionGetTicket 取 ticket。ticket 有效后先用 PositionSelectByTicket 选中,再用 PositionGetString 读 POSITION_SYMBOL,只当它与 _Symbol 一致时才通过 obj_Trade.PositionClose(ticket) 平仓,避免误杀其他图表品种的仓位。 恐慌按钮的触发端靠 GetState 轮询 BTN_CLOSE 是否为真。一旦为真就跑 closeAllPositions,随后用 ObjectSetInteger 把 BTN_CLOSE 的 OBJPROP_STATE 写回 false,并 ChartRedraw(0) 强制重绘,按钮视觉状态才归位。 编译进 MT5 策略测试器后,动态开仓与分级平仓的目标已经跑通;剩下的是把这套手动回测工具放到多品种、多周期里反复压。外汇与贵金属杠杆高,清仓函数若符号判断漏写一行,可能把跨品种持仓全平,实盘前务必在演示账户验三遍以上。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Manual backtest toolkit in Strategy Tester | class=class="str">"cmt">//| Copyright class="num">2025, Forex Algo-Trader, Allan. | class=class="str">"cmt">//| "https://t.me/Forex_Algo_Trader" | class=class="str">"cmt">//+------------------------------------------------------------------+ class="macro">#class="kw">property copyright "Forex Algo-Trader, Allan" class="macro">#class="kw">property link "https:class=class="str">"cmt">//t.me/Forex_Algo_Trader" class="macro">#class="kw">property version "class="num">1.00" class="macro">#class="kw">property description "This EA Enables manual backtest in the strategy tester" class="macro">#class="kw">property strict class=class="str">"cmt">//--- Enforce strict coding rules to class="kw">catch errors early class="macro">#define BTN_BUY "BTN BUY" class=class="str">"cmt">//--- Define the name for the Buy button class="macro">#define BTN_SELL "BTN SELL" class=class="str">"cmt">//--- Define the name for the Sell button class="macro">#define BTN_P "BTN P" class=class="str">"cmt">//--- Define the name for the button that increase lot size class="macro">#define BTN_M "BTN M" class=class="str">"cmt">//--- Define the name for the button that decrease lot size class="macro">#define BTN_LOT "BTN LOT" class=class="str">"cmt">//--- Define the name for the lot size display button class="macro">#define BTN_CLOSE "BTN CLOSE" class=class="str">"cmt">//--- Define the name for the button that close all positions class="macro">#define BTN_SL "BTN SL" class=class="str">"cmt">//--- Define the name for the Stop Loss display button class="macro">#define BTN_SL1M "BTN SL1M" class=class="str">"cmt">//--- Define the name for the button that slightly lower Stop Loss class="macro">#define BTN_SL2M "BTN SL2M" class=class="str">"cmt">//--- Define the name for the button that greatly lower Stop Loss class="macro">#define BTN_SL1P "BTN SL1P" class=class="str">"cmt">//--- Define the name for the button that slightly raise Stop Loss class="macro">#define BTN_SL2P "BTN SL2P" class=class="str">"cmt">//--- Define the name for the button that greatly raise Stop Loss class="macro">#define BTN_TP "BTN TP" class=class="str">"cmt">//--- Define the name for the Take Profit display button class="macro">#define BTN_TP1M "BTN TP1M" class=class="str">"cmt">//--- Define the name for the button that slightly lower Take Profit class="macro">#define BTN_TP2M "BTN TP2M" class=class="str">"cmt">//--- Define the name for the button that greatly lower Take Profit class="macro">#define BTN_TP1P "BTN TP1P" class=class="str">"cmt">//--- Define the name for the button that slightly raise Take Profit class="macro">#define BTN_TP2P "BTN TP2P" class=class="str">"cmt">//--- Define the name for the button that greatly raise Take Profit class="macro">#define BTN_YES "BTN YES" class=class="str">"cmt">//--- Define the name for the button that confirm a trade class="macro">#define BTN_NO "BTN NO" class=class="str">"cmt">//--- Define the name for the button that cancel a trade class="macro">#define BTN_IDLE "BTN IDLE" class=class="str">"cmt">//--- Define the name for the idle button between Yes and No class="macro">#define HL_SL "HL SL" class=class="str">"cmt">//--- Define the name for the Stop Loss horizontal line class="macro">#define HL_TP "HL TP" class=class="str">"cmt">//--- Define the name for the Take Profit horizontal line