在MQL5中实现基于抛物线转向指标(Parabolic SAR)和简单移动平均线(SMA)的快速交易策略算法(基础篇)
「用 SAR 叠加 SMA 搭一个快速进出框架」
在 MT5 里把抛物线转向(Parabolic SAR)和简单移动平均(SMA)拼到一起,可以构成一个偏短线的快速交易判定骨架:SAR 负责捕捉趋势拐点,SMA 负责过滤反向噪音。 具体落地时,常见做法是取一根周期偏短的 SMA(例如 20)作为方向滤网——价格站上 SMA 且 SAR 点落到价格下方,倾向只做多;反之价格跌破 SMA 且 SAR 点在上方,倾向只做空。外汇与贵金属杠杆高,这种组合仍可能在震荡段连续挨巴掌,实盘前务必用策略测试器跑一遍。 该思路在 2025-04-14 发布的示例中被 1,211 次查看、10 条讨论,说明社区对轻量双指标组合仍有稳定需求;你可以直接开 MT5 新建 EA,先把 SAR 步长 0.02、最大值 0.2 与 SMA(20) 写进去验证信号密度。
回测与绩效指标到底在测什么
这一节先说清楚我们要干的事:用 MT5 自带策略测试器,拿历史数据跑 EA 回测,把算法在过去行情里的表现和实际市场条件对照。目的不是证明策略「能赚」,而是看它在不同段行情里到底怎么反应。 读回测报告时,重点看三个数:盈利因子(总盈利/总亏损)、最大回撤、胜率。盈利因子 > 1.5 说明盈亏结构还行;回撤超过本金 20% 就要警惕杠杆和止损逻辑;胜率单独看没意义,得和平均盈利/亏损比一起看。外汇和贵金属波动大,回测好看不代表 live 能复现,实盘前务必用模拟账户跑至少两周。 快速交易策略靠短时间内多次进出,持仓通常不超过一小时,吃的是小波动而不是大趋势。它和长期趋势跟踪相反,依赖几乎即时的数据响应,所以必须上 EA 自动执行。抛物线 SAR 负责抓趋势反转点,SMA 负责把价格噪声磨平,两个指标嵌进高频逻辑里,才能既快又少出错。
◍ SAR 与 SMA 双指标的底層分工
抛物线 SAR 本质是一个随趋势滑动的止损反转点阵,它在 K 线外侧打出一系列点:价格在点上方属多头倾向,在点下方属空头倾向。它的灵敏性来自逐根 K 线重算止损距离,所以往往比价格拐点提前冒头,适合做“趋势可能要变”的即时提示。 简单移动平均线(SMA)则是把指定周期内的收盘价做算术平均后连成的平滑线。周期拉长到 60 之后,它过滤掉了短期噪音,只留下大方向——线向上就只看多、向下就只看空,价格贴着线晃就干脆不做。它在这里扮演趋势过滤器的角色。 把两者叠在一起用,SAR 负责抓“变”,SMA(60) 负责认“势”。实操上可以开 MT5 把 SAR 默认参数挂上、再加一条 Period=60 的 SMA,肉眼就能验证:SAR 点翻越价格当口,常发生在 SMA 走平转折之前,但真正进场必须等 SMA 方向确认,否则外汇/贵金属这种高波动品种里假突破概率不低。
「把快速策略塞进 MT5 的 EA 骨架」
在 MT5 里落地快速交易策略,第一步是打开 MetaEditor:终端按 F4,或点工具栏 IDE 图标。新建文档用 CTRL+N 调出 MQL 向导,选 EA(模板)一路下一步,文件名前加反斜杠可指定子目录,比如默认落在 Experts\ 下。 EA 头部先用 #include <Trade/Trade.mqh> 引入 CTrade 类,再声明对象 obj_Trade 才能下单。指标句柄必须提前建:handleSMA 与 handleSAR 初始化为 INVALID_HANDLE,避免引用到空句柄。这两个整数变量是 iMA / iSAR 返回的唯一 ID,全程序靠它们调非绘制指标。 OnInit 里 iMA 建 1 分钟、60 根收盘价的 SMA 句柄;iSAR 建步长 0.02、最大值 0.2 的抛物线 SAR 句柄。MQL5 句柄默认从 10 起跳、步进 1,所以两个句柄打印出来大概率是 10 和 11。若任一等于 INVALID_HANDLE,打印错误并返回 INIT_FAILED,拦住不安全启动。数组 sma_data / sar_data 用 ArraySetAsSeries(..., true) 设为时间序列,索引 0 是最新值。 [CODE] #include <Trade/Trade.mqh> CTrade obj_Trade; int handleSMA = INVALID_HANDLE; int handleSAR = INVALID_HANDLE; double sma_data[]; double sar_data[]; int OnInit() { handleSMA = iMA(_Symbol, PERIOD_M1, 60, 0, MODE_SMA, PRICE_CLOSE); handleSAR = iSAR(_Symbol, PERIOD_M1, 0.02, 0.2);
| if(handleSMA == INVALID_HANDLE | handleSAR == INVALID_INVALID) |
|---|
{ Print("ERROR: FAILED TO CREATE SMA/SAR HANDLE. REVERTING NOW."); return INIT_FAILED; } ArraySetAsSeries(sma_data, true); ArraySetAsSeries(sar_data, true); return INIT_SUCCEEDED; } [/CODE] OnDeinit 用 IndicatorRelease(handleSMA) 和 IndicatorRelease(handleSAR) 逆序释放,否则长跑多 EA 会占内存。OnTick 中 SymbolInfoDouble 取 Ask/Bid 并 NormalizeDouble 到 _Digits;CopyBuffer 抓 SMA 与 SAR 各 3 个值进数组,失败就打印并 return。 每根 K 线只交易一次靠 static datetime signalTime:currTime0 = iTime(_Symbol, PERIOD_M1, 0),不等旧值才放行。买入信号条件:sar_data[0] < low0 且 sar_data[1] > high1,同时 sma_data[0] < Ask,且 PositionsTotal == 0。外汇与贵金属杠杆高,tick 级策略滑点和连亏风险偏大,以上逻辑仅作 MT5 验证用,不预示胜率。 开仓直接 obj_Trade.Buy(0.1, _Symbol, Ask, 0, 0, "SMA_SAR_Long"),手数按账户风险自调。跑之前用 ArrayPrint(sma_data, _Digits, ", ") 把数组打到日志,回测里确认抓到的是 3 个值再实盘挂。
class="macro">#include <Trade/Trade.mqh> CTrade obj_Trade; class="type">int handleSMA = INVALID_HANDLE; class="type">int handleSAR = INVALID_HANDLE; class="type">class="kw">double sma_data[]; class="type">class="kw">double sar_data[]; class="type">int OnInit() { handleSMA = iMA(_Symbol, PERIOD_M1, class="num">60, class="num">0, MODE_SMA, PRICE_CLOSE); handleSAR = iSAR(_Symbol, PERIOD_M1, class="num">0.02, class="num">0.2); if(handleSMA == INVALID_HANDLE || handleSAR == INVALID_HANDLE) { Print("ERROR: FAILED TO CREATE SMA/SAR HANDLE. REVERTING NOW."); class="kw">return INIT_FAILED; } ArraySetAsSeries(sma_data, true); ArraySetAsSeries(sar_data, true); class="kw">return INIT_SUCCEEDED; }