GridMasterDynamic.mq5 交易逻辑分析 一、策略定位 这是一套 顺势入场 + 逆势加仓(马丁式温和倍投)+ 篓子移动止盈 + 总浮亏熔断 的网格 EA。核心思想: 1. 用 EMA200 + RSI 决定"首单"方向(只顺大势开首单); 2. 首单进场后,价格每逆向走一个 ATR 动态步长就加一层,手数按 1.3 倍递增; 3. 不给单笔 SL/TP,而是以同方向所有持仓的合计浮盈为标的做移动止盈; 4. 多空合计浮亏触及 InpMaxDrawdownLoss 时一键全平。 状态完全由持仓重建(层数、最深价都是每次遍历持仓算出来的),因此 EA 重启后能无缝接管原有网格,这是设计上的一个优点。 二、执行流程(UpdateUIAndGrid,由 OnTick 与每秒 OnTimer 双重驱动) 步骤 逻辑 说明 1-2 读 Bid/Ask,CopyBuffer 取 上一根已收盘 K 线(shift=1)的 EMA/RSI/ATR 用收盘值避免重绘,合理 3 遍历本品种 + 本 Magic 持仓,按方向统计层数、手数、浮盈,并记录"最深"开仓价(多单最低价 / 空单最高价) 正确的无状态重建 4 total_profit <= -MaxLoss → Alert + 全平 + return 全局熔断 5 方向许可:Bid > EMA 只允许多,反之只允许空;RSI>70 禁多,RSI<30 禁空 仅约束首单,加仓不受过滤 6 加仓间距 = max(20, ATR×1.5/point) 点;ATR 不可用时退回固定 150 点 每个 tick 重算,间距随波动率浮动 7A/7B 无持仓且方向允许 → 立即开首单;有持仓且 < MaxLevels 且 Ask <= 最深多单价 - 间距 → 加仓,手数 0.01 × 1.3^n,上限 0.5 手 逆势摊平 8 同向合计浮盈 ≥ 10$ 启动追踪,记录峰值;峰值回撤 ≥ 2$ 或浮盈 ≤ 0 → 平掉该方向全部 篓子移动止盈 9 刷新面板 — 三、优点 - 逻辑闭环清晰:入场过滤 → 加仓 → 止盈 → 熔断,各环节独立,可读性好。 - 持仓驱动的状态重建:不依赖全局变量记忆层数/价格,重启、断线后自动恢复。 - ATR 自适应间距:波动大时拉开间距,避免震荡期被快速加满。 - 温和乘数 1.3 + 0.5 手硬顶:比 2.0 倍的经典马丁温和得多。 - 移动止盈:比固定 TP 能多吃一段趋势,同时 profit <= 0 兜底。 - 使用收盘 K 线指标值,无重绘问题;UI 对象带 GM_ 前缀,卸载时只删自己的对象。 四、关键问题与风险(按严重程度排序) 🔴 1. 指标未就绪时趋势过滤被"静默绕过" double current_ema = (copied_ema > 0) ? ema_val[0] : 0.0; ... if(InpUseTrendFilter && current_ema > 0.0) { ...过滤... } OnInit 末尾直接调用了 UpdateUIAndGrid()。EA 刚挂载时 CopyBuffer 很可能返回 0(EMA200 尤其需要时间),此时 current_ema = 0,过滤器整个跳过,buy_allowed 和 sell_allowed 都为 true → 在 BOTH 模式下会立即同时开一多一空首单,与"顺势开首单"的设计相悖,还白付两份点差。 建议:任一 CopyBuffer 失败直接 return,并且不要在 OnInit 中执行交易逻辑。 🔴 2. 熔断后无冷却,立即重新入场 → 亏损循环 第 4 步全平后 return,但下一个 tick/秒 buy_count == 0,只要趋势允许就马上再开首单。若行情继续单边,可能每隔一段时间就再亏一个 -150$。此外若平仓失败(市场关闭、拒单),Alert 会每秒弹一次。 建议:加一个 g_halted/冷却时间戳(或直接 ExpertRemove()),并对 Alert 加节流。 🔴 3. 熔断用的是多空合并浮盈,对冲会掩盖单边风险 total_profit = buy_profit + sell_profit。BOTH 模式下(尤其关掉趋势过滤时)多头浮亏 -200$、空头浮盈 +80$,合计 -120$ 不触发,而实际一边已经深套且在持续加仓。 建议:按方向分别熔断,或改用 AccountInfoDouble(ACCOUNT_EQUITY) 相对余额的回撤。 🟠 4. 未区分对冲/净额账户 代码注释写了 "Hedging 模型",但没有检查 ACCOUNT_MARGIN_MODE。在净额账户上,BOTH 模式的 Sell 会直接对冲掉 Buy,buy_count/sell_count 统计和整套网格逻辑失效。 建议:OnInit 中若非 ACCOUNT_MARGIN_MODE_RETAIL_HEDGING 且 InpGridType == GRID_TYPE_BOTH,返回 INIT_PARAMETERS_INCORRECT。 🟠 5. 手数规范化硬编码 next_lot = NormalizeDouble(MathMin(0.50, next_lot), 2); - 没用 SYMBOL_VOLUME_STEP/SYMBOL_VOLUME_MAX,对 step=0.1、1.0 或 0.001 的品种会被拒单; - 0.5 手上限是魔术数字,应做成 input; - 加仓前没有做保证金检查(OrderCalcMargin / ACCOUNT_MARGIN_FREE),临近爆仓时只会不停被拒并刷日志。 🟠 6. 风险收益极不对称(网格通病,需量化认知) - 10 层、1.3 倍 → 总手数约 0.01 × (1.3¹⁰−1)/0.3 ≈ 0.43 手,是首单的 43 倍; - 止盈目标固定 10$,回撤 2$;而单边最大允许亏损 150$。盈亏比约 1:15,意味着需要极高胜率才能长期正期望; - 粗算:EURUSD H1 ATR≈10 pips → 间距 15 pips,跌满 10 层浮亏约 160$,刚好贴着熔断线;换成 XAUUSD(ATR≈8$,间距≈12$)满层浮亏约 1300$,熔断会在第 5~6 层就触发——同一组参数在不同品种上行为差异巨大,目标止盈应该随手数/间距缩放,而不是固定美元数。 🟡 7. 加仓不受趋势过滤约束 / 趋势翻转后双边同时持仓 - 首单顺势,但一旦入场,后续加仓完全逆势摊平,趋势过滤实际只决定"什么时候开始亏"; - BOTH 模式下价格跨越 EMA200 后,旧方向网格仍在摊平,新方向又开首单,两边同时累积。 🟡 8. 浮盈口径与实际不一致 POSITION_PROFIT 不含 swap 和手续费。多层隔夜持仓的 swap 可观,"10$ 止盈"平出来可能只有几美元甚至为负。建议加上 POSITION_SWAP 并估算佣金。 🟡 9. OnTick + OnTimer 双重驱动交易逻辑 每秒定时器也会下单,与 tick 重复;而且没有对失败下单做冷却,拒单时每秒重试并打印。建议只在 OnTick 中交易,OnTimer 仅刷 UI;下单前检查 TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)、SYMBOL_TRADE_MODE。 🟡 10. 移动止盈的小瑕疵 - ClosePositionsOfDirection 不检查返回值;部分平仓失败时 trailing 状态已被重置,剩余仓位要重新等到 ≥10$ 才会再次追踪; - 追踪峰值存在全局变量,重启后丢失(虽然会在浮盈仍 ≥ 目标时重新启动,影响不大)。 ⚪ 11. 代码层面 - long magic == ulong InpMagicNumber 有符号/无符号比较,会出编译警告; - trade.SetDeviationInPoints(100)、最小间距 20 点、0.5 手上限均为硬编码; - GM_Suggest_Text_L3/L4 创建了但从未使用; - 面板拖拽逻辑正常,CHART_MOUSE_SCROLL 有还原。 五、改进建议(优先级) 1. 指标未就绪即返回,OnInit 中不触发交易; 2. 熔断后暂停/冷却(或 ExpertRemove),Alert 节流; 3. 按方向分别熔断,或改用账户净值回撤; 4. 校验账户对冲模式; 5. 手数按 SYMBOL_VOLUME_STEP/MIN/MAX 规范并做保证金预检; 6. 止盈目标与最大亏损改为 随总手数或以 ATR 点数计 而非固定美元; 7. 浮盈计入 swap/佣金; 8. 交易只放在 OnTick,加入点差上限过滤与下单失败冷却; 9. 把 0.5 手上限、20 点最小间距、100 点滑点做成 input。 六、结论 这套代码结构规范、可读性好,"顺势首单 + ATR 间距 + 篓子移动止盈 + 熔断"的框架是网格策略里相对稳健的一类。但目前存在两个会在实盘直接暴露的逻辑缺陷(指标未就绪绕过过滤、熔断后无冷却),以及网格策略固有的"小赢多次、一次大亏"的尾部风险特征。它不是无风险策略——在单边行情中,1.3 倍乘数下 10 层网格的浮亏可达首单的数十倍,请务必先在 Strategy Tester 里用多品种、多年度、含点差/佣金/swap 的真实 tick 数据回测,并以最大回撤而非收益率作为主要评判指标;回测结果也不代表未来表现。 如果需要,我可以按上面的优先级直接修改源码并编译验证。