MQL5 交易策略自动化(第十部分):开发趋势盘整动量策略·综合运用
(3/3)·从指标配置到回测优化,把趋势盘整动量策略一次性封装成可跑的MQL5程序
◍ 卖单触发时的止损与下单逻辑
当所有卖单条件通过校验后,脚本先尝试用前高摆动点作为止损位。GetPivotHigh(PivotLeft, PivotRight) 会回看左侧与右侧 K 线数量定位摆动高点,若返回小于等于 0 说明当前品种没扫到有效前高,就退而求其次用实时卖价 SYMBOL_ASK 兜底。 入场价直接取 SYMBOL_BID 即当前买价,止盈按固定点数算:tp = entryPrice - InpTakeProfitPoints * _Point。比如 InpTakeProfitPoints 设为 200、_Point 是 0.00001 时,止盈距离就是 2 个点,外汇与贵金属杠杆高,实际盈亏会被倍数放大,需自测风险。 Print 会把用作止损的摆动高点打印到日志,方便你回看信号质量。随后 obj_Trade.Sell 带着仓位、入场、止损、止盈去发单,成功就打印成交价,失败则输出 ResultRetcodeDescription 的错误描述,处理完直接 return 不再往下走;条件不满足时仅留一条未执行的提示。 把这段接进 EA 后,开 MT5 用策略测试器跑 EURUSD 的 M15,重点看日志里 Swing High 的取值是否落在可见前高,能立刻验证止损逻辑有没有塌。
conditionsOk = class="kw">false; class=class="str">"cmt">//--- Mark the conditions as not met. } if (conditionsOk) { class=class="str">"cmt">//--- If all Sell conditions are met... class=class="str">"cmt">//--- Get stop loss from previous swing high. class="type">class="kw">double stopLoss = GetPivotHigh(PivotLeft, PivotRight); class=class="str">"cmt">//--- Use pivot high as the stop loss. if (stopLoss <= class="num">0) { class=class="str">"cmt">//--- If no valid pivot high is found... stopLoss = SymbolInfoDouble(_Symbol, SYMBOL_ASK); class=class="str">"cmt">//--- Fallback to current ask price. } class="type">class="kw">double entryPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID); class=class="str">"cmt">//--- Determine entry price as current bid price. class="type">class="kw">double tp = entryPrice - InpTakeProfitPoints * _Point; class=class="str">"cmt">//--- Calculate take profit based on fixed points. class=class="str">"cmt">//--- Print the swing point(pivot high) used as stop loss. Print("Sell signal: Swing High used as Stop Loss = ", stopLoss); class=class="str">"cmt">//--- Notify the user of the pivot high used. if (obj_Trade.Sell(InpLotSize, NULL, entryPrice, stopLoss, tp, "Sell Order")) { class=class="str">"cmt">//--- Attempt to open a Sell order. Print("Sell order opened at ", entryPrice); class=class="str">"cmt">//--- Notify the user if the order is opened successfully. } else { Print("Sell order failed: ", obj_Trade.ResultRetcodeDescription()); class=class="str">"cmt">//--- Notify the user if the order fails. } class="kw">return; class=class="str">"cmt">//--- Exit after processing a valid Sell signal. } else { Print("Sell signal not executed due to failed condition(s)."); class=class="str">"cmt">//--- Notify the user if Sell conditions failed. } }
时间序列翻转消除无效波段顶点
密集回测里暴露过一个隐蔽问题:找波段顶点时若先拿最旧数据比,极少数情况下会识别出无效顶点,连带把止损位算歪,订单直接被拒。 根子在数组方向。用 ArraySetAsSeries 把价格数组设为时间序列后,索引 0 变成最新一根 K 线,分析逻辑自然从近往远走,无效顶点的概率被压下去。
- 至 2024 年跨年回测对照显示,修正后抓到的近期波段低点与实际拐点吻合,此前那种“无效止损”报错不再出现,策略不再莫名错过入场。
下面这段是修正版取最近摆动低点的骨架,关键就在黄色那行把数组翻成时间序列。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Function to find the most recent swing low(pivot low) | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">class="kw">double GetPivotLow(class="type">int left, class="type">int right) { class="type">MqlRates rates[]; class=class="str">"cmt">//--- Declare an array to store rate data. ArraySetAsSeries(rates, true); class=class="str">"cmt">//--- }
「把工具请下神坛」
这套趋势盘整动量 EA 把多指标交叉和阈值检查写进同一套逻辑,入场出场靠市场结构触发,不是拍脑袋下单。MT5 策略测试器里跑一遍 Trend_Flat_Momentum_EA.mq5,你能直接看到 18.36 KB 的源码如何把信号过滤成可执行的订单。 外汇和贵金属杠杆高、跳空频繁,任何自动化系统都只是把人的规则翻译成机器语言,回测漂亮不代表实盘能活。先把 ZIP 里的文件拖进 MetaEditor 编译,用历史数据过一遍再谈参数微调。 代码归代码,盘感归盘感。能让小布替你跑这套验证,比信任何‘结构化方法’的漂亮话都实在。