使用MQL5实现抛物线SAR趋势策略的自动化交易:打造高效的EA·综合运用
(3/3)·前两步铺好指标与下单,这一篇把仓位、滑点和异常收口一次讲透
「用抛物线 SAR 给无持仓时挂向」
在 MT5 里做信号触发,第一步往往是确认当前品种有没有敞口。下面这段逻辑只在同一品种无持仓时才去读 SAR 并决定多空,避免重复加仓把账户风险叠厚。 核心判断很直白:取前一根收盘价比对 iSAR 算出的停损点。若收盘价在 SAR 上方,倾向开多;若在下方,倾向开空。外汇与贵金属波动大,这种裸信号在震荡市可能频繁反向,实盘前务必用策略测试器跑历史数据。 IsPositionOpen 用 PositionsTotal 遍历所有持仓,比对 PositionGetSymbol 与当前图表的 _Symbol,命中即返回 true。把它放在下单前,等于给 EA 加了一道「同品种不重复进场」的闸。 OpenBuyOrder 里 trade.Buy 的滑点、止损、止盈三参都传了 0,意味着先用市价不挂防护单;这种写法方便验证信号,但真上 XAUUSD 这类高滑点品种前,建议至少把止损参数字段填上。
class="type">class="kw">double sar = iSAR(_Symbol, _Period, SAR_Step, SAR_Maximum); class=class="str">"cmt">// 计算抛物线SAR当前值 class="type">class="kw">double lastPrice = iClose(_Symbol, _Period, class="num">1); class=class="str">"cmt">// 取上一根K线收盘价 class=class="str">"cmt">//--- 检查是否已有持仓 if(!IsPositionOpen(_Symbol)) { class=class="str">"cmt">//--- 根据SAR判断方向 if(lastPrice > sar) { OpenBuyOrder(); class=class="str">"cmt">// 收盘价在SAR之上,开多 } else if(lastPrice < sar) { OpenSellOrder(); class=class="str">"cmt">// 收盘价在SAR之下,开空 } } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//|检查指定品种是否有持仓 | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">bool IsPositionOpen(class="type">class="kw">string symbol) { class="type">uint total=PositionsTotal(); class=class="str">"cmt">// 获取当前总持仓数 for(class="type">uint i=class="num">0; i<total; i++) { class="type">class="kw">string POSITION_SYMBOL=PositionGetSymbol(i); class=class="str">"cmt">// 取第i个持仓的品种名 if(POSITION_SYMBOL == _Symbol) class=class="str">"cmt">// 比对是否为当前图表品种 { class="kw">return true; } } class="kw">return class="kw">false; } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| 开多单 | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OpenBuyOrder() { if(trade.Buy(LotSize, NULL, class="num">0, class="num">0, class="num">0, "Buy Order")) { Print("Buy order placed successfully"); } else { Print("Error placing buy order: ", GetLastError()); } }
用 Sell 接口把空单真正发出去
上面这段函数就是把做空逻辑落到 MT5 执行层的最后一步。CTrade 对象的 Sell 方法在市价直接丢单,LotSize 是外部传进来的手数,第二参 NULL 表示用当前品种,后面三个 0 分别代表滑点、止损、止盈全部不预设,尾串只是订单备注。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Open a Sell order | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OpenSellOrder() { if(trade.Sell(LotSize, NULL, class="num">0, class="num">0, class="num">0, "Sell Order")) { Print("Sell order placed successfully"); } else { Print("Error placing sell order: ", GetLastError()); } }
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Open a Sell order | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OpenSellOrder() { if(trade.Sell(LotSize, NULL, class="num">0, class="num">0, class="num">0, "Sell Order")) { Print("Sell order placed successfully"); } else { Print("Error placing sell order: ", GetLastError()); } }
◍ M1 tick 回测暴露的币种适应性
在 MT5 策略测试器中跑了一组基于 M1 图表、逐 tick 撮合的回测,标的选 USDJPY,样本区间锁定 2024-01-01 至 2024-08-05。这种粒度能逼出策略在极小波动下的真实反应,比仅用收盘价回放更接近实盘滑点环境。 反复换参数在 USDJPY 的 M1 上跑了几次后,倾向认为该逻辑对 USDJPY 与 EURUSD 都还能吃得开,进场信号在这两个直盘上的触发频率与回撤形态相对可控。 但把同一套搬到 GBPUSD 就明显水土不服,英镑的跳空与伦敦时段脉冲容易把止损扫在不利位置,实测胜率与回撤比都弱于前两个币种。外汇及贵金属杠杆交易高风险,上述结论仅基于特定区间回测,换周期或换年份可能失效,请自行在 MT5 用 tick 数据重跑验证。
「画得少,看得清」
把 SAR 步长和最大值调顺,再挂上跟踪止损,这个朴素 EA 才有从 demo 回测走到实盘的可能。原文给出的修正版 mq5 仅 4.08 KB,说明策略骨架极轻,重活都在参数优化与多轮测试上。 外汇与贵金属波动剧烈,自动化只是替你挡掉疲劳和手误,不挡亏损;任何回测亮眼的数字都不构成未来收益承诺,概率倾向比保证更诚实。 下面这段 OnTick 是整套逻辑的眼:只取当前品种周期的 SAR 值,没加任何过滤。你想验证,直接开 MT5 把 SAR_Step、SAR_Maximum 改成 0.01 / 0.2 跑一遍 EURUSD 小时图就懂。 真正能用的系统,是你在上面叠了风控和确认条件之后的东西,不是这个 23 KB 的 ex5 本身。
class="type">void OnTick() { class=class="str">"cmt">//--- 获取抛物线 SAR 值 class="type">class="kw">double sar = iSAR(_Symbol, _Period, SAR_Step, SAR_Maximum); class=class="str">"cmt">// 计算抛物线 SAR 值