MQL5交易策略自动化(第十七部分):借助动态仪表盘精通网格马丁格尔(Grid-Mart)短线交易策略(基础篇)
◍ 用动态仪表盘接管网格马丁短线单
网格马丁(Grid-Mart)在 MT5 上做短线,最怕的是浮亏层叠时肉眼盯不住。把每一层的开仓价、当前浮亏、累计持仓手数实时画到动态仪表盘上,比翻交易池直观得多。
原文给出的基础结构里,用 CHARTEVENT_CUSTOM 把 EA 内部状态推到独立面板,刷新频率建议设在 200~500 毫秒,过低会拖慢回测、过高在实盘容易掉帧。外汇与贵金属杠杆高,网格逆势加仓浮亏扩张速度可能远超预期,仪表盘只是让你早半秒发现,不等于风险可控。
跑通这套,第一步是在 MT5 的 EA 里挂一个自定义指标窗口做渲染容器,再把网格层数组序列化后发过去。能立刻验证的一件事:开 MT5 新建 EA,把下面这段状态推送骨架塞进 OnChartEvent,编译后拖动到图表,看右下角是否吐出第一层网格坐标。
class="type">void OnChartEvent(const class="type">int id, const class="type">long &lparam, const class="type">class="kw">double &dparam, const class="type">class="kw">string &sparam) { if(id==CHARTEVENT_CUSTOM) { class=class="str">"cmt">// 自定义事件:EA 向仪表盘推送网格状态 class="type">class="kw">string state=(class="type">class="kw">string)sparam; class=class="str">"cmt">// 序列化的网格层数据 Comment(state); class=class="str">"cmt">// 临时渲染到图表角落 } }
从结构突破切到网格马丁
前一篇我们用结构突破抓住了午夜区间的破位机会,那种逻辑偏「等信号」,而这回要做的 EA 换了一条路:网格 + 马丁格尔,靠密集挂单和加仓去吃短线波动。 这套系统跑在 MT5 里,核心不是预测方向,而是用分层网格把价格来回的价差榨出来,同时配一块动态仪表盘,把持仓层数、浮亏、加仓距离实时画在图上。 本篇会拆清楚策略意图、MQL5 落地方式以及回测该看什么。等你跟完,本地就能编译出一个带监控面板的 EA,直接挂 XAUUSD 或欧美十五分钟去验。外汇与贵金属杠杆高,马丁加仓在极端单边里会放大回撤,实盘前务必用历史数据先压一遍。
「网格马丁格尔是怎么吃波动的」
网格马丁格尔短线策略本质是「固定间距挂单 + 亏损加倍仓」的组合。以 2.0 点作为网格间隔,在现价上下每隔这个距离预置买入或卖出单,靠市场来回扫单吃 4 点左右的小目标利润。 亏损后头寸规模按指数增长补仓,意图用一次回本覆盖前面所有小亏。但这正是风险源:连亏 5 层后仓位已是首仓的 32 倍,账户在单边趋势里会被快速拖垮。 实战中必须卡死两层阀门——最大网格层级(比如不超过 8 层)和每日回撤阈值(例如 5%)。外汇与贵金属杠杆高,这类策略在震荡市盈利概率偏大,碰到强趋势则大幅回撤概率陡增,只适合用闲余资金的小仓位验证。 我们的 MQL5 EA 思路是:程序算好网格间距、管理加倍仓位、按预设止盈止损执行;再挂一个动态仪表盘,把点差、活跃仓量、账户权益用颜色标出来,回撤和网格数超限就自动停手。
◍ MT5里搭一个带仪表盘的网格马丁框架
打开 MetaEditor,在导航器「指标」目录点新建,生成文件后先声明全局变量,这一步决定后面网格马丁和动态面板能不能跑起来。核心交易对象用 #include <Trade/Trade.mqh> 挂一个 CTrade 实例 obj_Trade,再配 dailyBalance 盯余额、lastBarTime 用 iTime 存K线时间,hasBuyPosition / hasSellPosition 标记双向持仓,activeOrders 数未平头寸。 输入参数直接定调策略激进度:GRID_DISTANCE=3.0 点网格间距、LOT_MULTIPLIER=1.3 手数递增、TAKE_PROFIT_PIPS=3 止盈,MAGIC=1234567890 做单识别。风控侧开 ENABLE_DAILY_DRAWDOWN 配合 DRAWDOWN_LIMIT,cycleCount 与 MAX_CYCLES 卡交易周期数;面板侧 DASHBOARD_WIDTH=300、FONT_SIZE_METRIC=9、VALUE_POSITIVE_COLOR=clrLimeGreen,pipValue 管报价精度。 辅助函数先把账户和持仓属性拆干净:GetAccountBalance 套 AccountInfoDouble 抓余额;GetPositionMagic / OpenPrice / SL / TP 分别包 PositionGetInteger 和 PositionGetDouble;GetPositionSymbol 验品种、GetPositionTicket 和 GetPositionOpenTime 跟标识符与时间、GetPositionType 判多空。面板绘制靠 CreateRectangle(ObjectCreate+ObjectSetInteger 画背景标题)、CreateTextLabel(ObjectCreate+ObjectSetString 写点差手数)、CreateButton 做关闭键带悬停。 CalculateTotalProfit 用 PositionsTotal 配 PositionSelectByTicket 遍历,借 GetPositionSymbol+GetPositionMagic 过滤后累加 PositionGetDouble 的盈利。UpdateDashboard 只在 dashboardVisible 真时重绘:主面板和标题栏按 headerHovered 切 BACKGROUND_COLOR / HEADER_NORMAL_COLOR / HEADER_HOVER_COLOR;点差用 SymbolInfoDouble 算买卖价差,≤2.0 点绿、2.1–5.0 点黄、>5.0 点红,你可自调阈值;关闭键随 closeButtonHovered 切 CLOSE_BUTTON_NORMAL_BG / HOVER_BG,末尾 ChartRedraw 刷新。 OnInit 里 Point() 算 pipValue、SetExpertMagicNumber 写 MAGIC、开 dashboardVisible,用 PANEL_X/Y 定位后调 UpdateDashboard,ChartSetInteger 开鼠标交互返 INIT_SUCCEEDED;OnDeInit 直接 ObjectsDeleteAll 清场。OnChartEvent 管交互:点关闭区设 dashboardVisible=false 并删对象;鼠标移运用 mouseX/Y 改悬停色;拖动用静态 prevMouseState 抓按下,存 panelDragX/Y 后按位移改 panelStartX/Y 并禁图表滚动,松手复原。 手数三模式在 CalculateLotSize:BASE_LOT 固定、MathPow(LOT_MULTIPLIER,activeOrders) 马丁指数增、亏单动态调整则 HistorySelect 拉24h 记录,HistoryDealsTotal 遍历,亏则调 lotSize 盈则重置 BASE_LOT,NormalizeDouble 修精度。CountActiveOrders 用 PositionsTotal 循环过 GetPositionSymbol+Magic+Type 统计,给马丁倍数和面板显示供数。外汇与贵金属杠杆高,马丁加仓在单边行情中回撤可能远超 DRAWDOWN_LIMIT,实盘前务必在 MT5 策略测试器用历史数据验参数。
持仓手数面板与下单函数怎么写
仪表盘上想一眼看清当前活跃仓的手数,核心在 GetActiveLotSizes 这个函数。它先判 activeOrders:若为零直接回 "[Waiting]";否则用 ArrayResize 开数组,PositionsTotal 跑循环,PositionGetTicket 拿 ticket,PositionGetDouble 取每笔手数进 lotSizes,再 ArraySort 升序。DoubleToString 按 LOT_PRECISION 转字符串,≤3 笔全显,>3 笔只显前 3 加省略号,最后方括号包裹。 开仓靠 PlaceOrder 调 obj_Trade.PositionOpen,入参 lot、price,IntegerToString(gridLevel) 写进订单备注。失败不立即放弃:GetLastError 拿错误码,Sleep 暂停后重试,应对滑点跟网络延迟更稳。 止损止盈分开算。CalculateSL 用 slPrice 减 STOP_LOSS_PIPS*pipValue;CalculateTP 看 orderType,买单加 TAKE_PROFIT_PIPS*pipValue、卖单减。GetLatestBuyPrice / GetLatestSellPrice 都遍历持仓,用 GetPositionSymbol、Magic、Type 过滤,取最大 ticket 对应的开仓价返回,网格基准价就不会乱。 IsTradingAllowed 现在直接 return 1,等于解除限制跑高频,实盘前你大概率要改成自己的风控开关。整套函数集在 OnTick 里组装:SymbolInfoDouble 取买卖价、NormalizeDouble 修精度,iTime 比对 lastBarTime 防同根 K 线重复触发。 新仓信号示例很朴素——小时数落进 START_HOUR~END_HOUR、cycleCount<MAX_CYCLES、无持仓且 closePrev 与 closePrev 反向突破,就按 CalculateLotSize 出手。这套信号随便换,框架才是重点。外汇与贵金属杠杆高,回测前别真金白银跑。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| GridMart Scalper MT5 EA.mq5 | class=class="str">"cmt">//| Copyright class="num">2025, Allan Munene Mutiiria. | class=class="str">"cmt">//| https://t.me/Forex_Algo_Trader | class=class="str">"cmt">//+------------------------------------------------------------------+ class="macro">#class="kw">property copyright "Copyright class="num">2025, Allan Munene Mutiiria." 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">#include <Trade/Trade.mqh>
「盯盘面板的全局变量与状态机骨架」
EA 启动时先声明一个 CTrade 实例 obj_Trade,后续所有下单、改单、平仓都走它,不自己拼 OrderSend。下面这堆全局变量就是整个策略的“记忆体”:dailyBalance 记每天起始权益用于回撤监控,dailyResetTime 判断跨天重置,tradingEnabled 在触及回撤上限后关门。 持仓与信号类变量很直白:hasBuyPosition / hasSellPosition 标记有无单向持仓,openNewTrade 是开仓触发旗标,activeOrders 数挂单,latestBuyPrice / latestSellPrice 存最近一单成交价,calculatedLot 放算好的手数。加权成本 related 的 weightedPrice、totalVolume、cycleCount 用来做网格或均价拉平逻辑。 面板交互部分别忽略:panelDragging 配 panelDragX/Y 和 panelStartX/Y 实现鼠标拖拽悬浮窗,closeButtonHovered / headerHovered 做按钮热区反馈,dashboardVisible 控制显隐。外汇与贵金属波动大、杠杆高,这类状态变量若初始化遗漏,可能在 MT5 实时行情下出现重复开仓或拖拽卡死。 input group "Main EA Settings" 是参数分组入口,把主设置收进 MT5 属性框同一栏目。开 MT5 新建 EA 时,先把上面这些变量照抄进全局区,再逐行填逻辑,能省掉大半调试时间。
class=class="str">"cmt">//--- Declare trade object to execute trading operations CTrade obj_Trade; class=class="str">"cmt">//--- Trading state variables class="type">class="kw">double dailyBalance = class="num">0; class=class="str">"cmt">//--- Store the daily starting balance for drawdown monitoring class="type">class="kw">datetime dailyResetTime = class="num">0; class=class="str">"cmt">//--- Track the last daily reset time class="type">bool tradingEnabled = true; class=class="str">"cmt">//--- Indicate if trading is allowed based on drawdown limits class="type">class="kw">datetime lastBarTime = class="num">0; class=class="str">"cmt">//--- Store the timestamp of the last processed bar class="type">bool hasBuyPosition = false; class=class="str">"cmt">//--- Flag if there is an active buy position class="type">bool hasSellPosition = false; class=class="str">"cmt">//--- Flag if there is an active sell position class="type">bool openNewTrade = false; class=class="str">"cmt">//--- Signal when a new trade should be opened class="type">int activeOrders = class="num">0; class=class="str">"cmt">//--- Count the number of active orders class="type">class="kw">double latestBuyPrice = class="num">0; class=class="str">"cmt">//--- Store the price of the latest buy order class="type">class="kw">double latestSellPrice = class="num">0; class=class="str">"cmt">//--- Store the price of the latest sell order class="type">class="kw">double calculatedLot = class="num">0; class=class="str">"cmt">//--- Hold the calculated lot size for new orders class="type">bool modifyPositions = false; class=class="str">"cmt">//--- Indicate if position SL/TP need modification class="type">class="kw">double weightedPrice = class="num">0; class=class="str">"cmt">//--- Track the weighted average price of open positions class="type">class="kw">double targetTP = class="num">0; class=class="str">"cmt">//--- Store the target take-profit price class="type">class="kw">double targetSL = class="num">0; class=class="str">"cmt">//--- Store the target stop-loss price class="type">bool updateSLTP = false; class=class="str">"cmt">//--- Signal when SL/TP updates are needed class="type">int cycleCount = class="num">0; class=class="str">"cmt">//--- Count the number of trading cycles class="type">class="kw">double totalVolume = class="num">0; class=class="str">"cmt">//--- Accumulate the total volume of open positions class="type">bool dashboardVisible = true; class=class="str">"cmt">//--- Control visibility of the dashboard class=class="str">"cmt">//--- Dashboard dragging and hover state variables class="type">bool panelDragging = false; class=class="str">"cmt">//--- Indicate if the dashboard is being dragged class="type">int panelDragX = class="num">0; class=class="str">"cmt">//--- Store the X-coordinate of the mouse during dragging class="type">int panelDragY = class="num">0; class=class="str">"cmt">//--- Store the Y-coordinate of the mouse during dragging class="type">int panelStartX = class="num">0; class=class="str">"cmt">//--- Store the initial X-position of the dashboard class="type">int panelStartY = class="num">0; class=class="str">"cmt">//--- Store the initial Y-position of the dashboard class="type">bool closeButtonHovered = false; class=class="str">"cmt">//--- Track if the close button is hovered class="type">bool headerHovered = false; class=class="str">"cmt">//--- Track if the header is hovered input group "Main EA Settings"