价格行为分析工具包开发(第十四部分):抛物线转向与反转工具(基础篇)
📘

价格行为分析工具包开发(第十四部分):抛物线转向与反转工具(基础篇)

第 1/3 篇

价格行为工具包里的抛物转向起点

这一节是整套价格行为分析工具包的第 14 部分,落点在 MetaTrader 5 平台上用 MQL5 把抛物线转向(Parabolic SAR)与反转识别做成可复用模块。原文给出的发布时间为 2025 年 10 月 30 日,截至统计页面显示阅读量 935、评论 0,说明这套东西还处在低频曝光、未引发社区争论的阶段。 作者 Christian Benjamin 把全文拆成引言、概念阐释、MQL5 实现、测试及结果、结论五个块。对交易者来说,重点不在阅读量,而在「实现」和「测试结果」这两段——前者决定你能否直接抄进 MT5 自定义指标,后者决定参数在什么周期上更不容易被毛刺洗掉。 外汇与贵金属市场高杠杆、滑点随机,任何转向工具都只是概率过滤器。开 MT5 把 SAR 默认步长 0.02、最大值 0.2 调出来,先跑 EURUSD 的 H1,看反转信号和人工目测的价格行为是否对得上,再谈改装。

「为什么用指标搭反转EA」

技术指标本质是对历史价格、成交量、持仓量等数据的模式抽取,给交易者一套可重复的启发式判读框架。它不预测未来,只是把已验证的趋势与统计关系转成可视信号,降低主观随意性。 本篇要落地的,是一个用 MQL5 写的自动交易系统,专盯潜在市场反转。它借抛物线转向(SAR)做信号探测:实时盯指标、评估信号有效性,并在触及预设价位时锁定退出点。外汇与贵金属杠杆高,反转识别错了就是连续止损,实盘前务必在 MT5 策略测试器跑通。 下面先交待基础策略逻辑与用指标的根本理由,再进 MQL5 实现、回测与调参建议。

◍ PSAR 翻转与 K 线确认的生成逻辑

PSAR 里的“抛物线”指点的排布随趋势加速外扩,离近期极值越远,点距拉得越开,直观反映动能堆叠;“SAR”则是停止并反转的触发带,点一旦从价格一侧翻到另一侧,当前趋势倾向衰竭。 把 PSAR 加到 MT5 很简单:插入 → 指标 → 趋势 → 抛物线转向,参数务必和你 EA 里调用的步长、步长上限一致,否则回测和肉眼看图会对不上。 买入触发要求三根 K 线协同:当下这根收阳且 PSAR 值低于收盘价;前两根靠 PSAR 位于收盘价之上确认此前的空头;同时前几根 PSAR 差值落在阈值内,避免点距突变造成的假翻面。卖出镜像处理——收阴、PSAR 在收上、前两根 PSAR 在收下。 外汇与贵金属杠杆高,PSAR 翻转只代表概率倾向反转,实盘前应在 MT5 用历史数据跑一遍上述三根 K 线条件,确认信号频次和滑点下的表现再上仓。

把 PSAR 反转逻辑落进 MT5 的 EA 骨架

EA 顶部先用 #property strict 强制类型检查,这能在编译期拦掉多数参数误用;实盘或发布前都建议开着,减少运行时报错和后续 MT5 更新的兼容坑。 输入参数直接暴露给 MT5 界面:SARStep=0.02 是加速因子,SARMaximum=0.2 封顶加速度;MinConsecutiveDots=2 要求反转前至少 2 根同趋势 K 线,MaxDotGapPercentage=1.0 限制相邻 PSAR 点间距不超过收盘价的 1%。箭头符号走 Wingdings 字体,买卖可分别设 ✓ 和 X,调宽度能提升扫图辨识度。 全局里 sarHandle 存指标句柄,lastBarTime 防重复处理,SignalType 枚举无/买/卖三态。pendingReversalLevel 记下信号发生时的 PSAR 值,作为后续真假反转的参照线——这是过滤假突破的关键 checkpoint。 IsNewBar 比当前 K 线时间与 lastBarTime,不同才更新并返回 true,保证每根 K 线只算一次,避免 tick 内重复报警。CheckForSignal 读最近三根:买需本根收高于开且 PSAR 在下方、前两根看跌且 PSAR 在上方,卖反之;间隙超阈值即弃信号。 OnTick 里若有 pending 信号则 waitCount++,价触 pendingReversalLevel 报平仓提示,满 3 根未确认则警告可能假信号;无 pending 才调 CheckForSignal 建仓并画箭头。OnInit 建句柄失败就报错退出,OnDeinit 清箭头等对象,不留垃圾在图上。 外汇与贵金属波动大、杠杆高,这套 EA 仅提供信号参考,实盘前请在策略测试器用历史数据验证参数敏感性。

MQL5 / C++
class=class="str">"cmt">//+--------------------------------------------------------------------+
class=class="str">"cmt">//|                                             Parabolic SAR EA.mql5 |
class=class="str">"cmt">//|                 Copyright class="num">2025, Christian Benjamin |
class=class="str">"cmt">//|                                       [MQL5官方文档] |
class=class="str">"cmt">//+--------------------------------------------------------------------+
class="macro">#class="kw">property copyright "class="num">2025, Christian Benjamin"
class="macro">#class="kw">property link      "[MQL5官方文档]
class="macro">#class="kw">property version   "class="num">1.0"
class="macro">#class="kw">property strict
class=class="str">"cmt">// Input parameters for the Parabolic SAR indicator
input class="type">class="kw">double SARStep    = class="num">0.02;  class=class="str">"cmt">// Acceleration factor for PSAR
input class="type">class="kw">double SARMaximum = class="num">0.2;   class=class="str">"cmt">// Maximum acceleration for PSAR
class=class="str">"cmt">// Input parameters for refining the signal based on PSAR dots
input class="type">int    MinConsecutiveDots = class="num">2;         class=class="str">"cmt">// Require at least class="num">2 consecutive bars in one trend before reversal
input class="type">class="kw">double MaxDotGapPercentage  = class="num">1.0;     class=class="str">"cmt">// Maximum allowed gap between consecutive PSAR dots(% of current close)
class=class="str">"cmt">// Input parameters for alerts and arrow drawing

「把信号画上图:箭头与等待机制的代码骨架」

PSAR 翻转信号若只在日志里闪一下,盯盘时根本抓不住。上面这段全局声明把提醒方式、箭头样式和一套‘待定信号’机制先铺好:弹窗、声音、箭头三个开关默认全开,Wingdings 编码 233/234 分别对应涨箭头和跌箭头,ArrowOffsetMultiplier=5 控制箭头相对 K 线的偏移倍数。 pendingSignal 配合 waitCount、pendingReversalLevel 实现‘检测后不立刻下手’的逻辑——信号出现时先存下当时的 PSAR 值,之后每收一根新柱 waitCount 加一,给交易者留出人工确认的时间窗。外汇与贵金属波动剧烈,这种延迟确认可能降低假突破干扰,但也可能错过早期入场,属概率权衡。 DrawSignalArrow 函数负责把箭头钉在图上:用 TimeToString(barTime, TIME_SECONDS) 拼出唯一对象名,先 ObjectFind 删重再 ObjectCreate 画 OBJ_ARROW,颜色、箭头码、线宽分别由 OBJPROP_COLOR / OBJPROP_ARROWCODE / OBJPROP_WIDTH 设定。开 MT5 把这段代码贴进 EA,改 BuyArrowSymbol 的 Wingdings 码就能换你顺眼的标记。 CheckForSignal 的索引约定很直接:数组 0 是刚收的柱、1 是前一柱、2 是更前一根,sar0/sar1/sar2 与对应 open/close 取出后供翻转判定。这套索引映射若不记牢,后面写条件时极易把‘上一根’当‘当前’用。

MQL5 / C++
input class="type">bool   EnableAlerts   = true;           class=class="str">"cmt">// Enable popup alerts
input class="type">bool   EnableSound    = true;           class=class="str">"cmt">// Enable sound alerts
input class="type">bool   EnableArrows   = true;           class=class="str">"cmt">// Draw arrows on chart
input class="type">class="kw">string BuyArrowSymbol  = "class="num">233";         class=class="str">"cmt">// Wingdings up arrow(as class="type">class="kw">string)
input class="type">class="kw">string SellArrowSymbol = "class="num">234";         class=class="str">"cmt">// Wingdings down arrow(as class="type">class="kw">string)
input class="type">int    ArrowWidth      = class="num">2;             class=class="str">"cmt">// Arrow thickness
input class="type">class="kw">double ArrowOffsetMultiplier = class="num">5;        class=class="str">"cmt">// Multiplier for arrow placement offset
class=class="str">"cmt">// Global indicator handle for PSAR
class="type">int sarHandle = INVALID_HANDLE;
class=class="str">"cmt">// Global variable to track last processed bar time
class="type">class="kw">datetime lastBarTime = class="num">0;
class=class="str">"cmt">// Enumeration for signal types
enum SignalType
  {
  NO_SIGNAL,
  BUY_SIGNAL,
  SELL_SIGNAL
  };
class=class="str">"cmt">// Global variables for pending signal mechanism
SignalType pendingSignal = NO_SIGNAL;
class="type">int       waitCount     = class="num">0;                class=class="str">"cmt">// Counts new closed bars since signal detection
class="type">class="kw">double    pendingReversalLevel = class="num">0.0; class=class="str">"cmt">// Stores the PSAR value at signal detection
class="type">void DrawSignalArrow(class="type">class="kw">string prefix, class="type">class="kw">datetime barTime, class="type">class="kw">double price, class="type">class="kw">color arrowColor, class="type">long arrowCode)
  {
  class="type">class="kw">string arrowName = prefix + "_" + TimeToString(barTime, TIME_SECONDS);
  class=class="str">"cmt">// Remove existing object with the same name to prevent duplicates
  if(ObjectFind(class="num">0, arrowName) != -class="num">1)
     ObjectDelete(class="num">0, arrowName);
  if(ObjectCreate(class="num">0, arrowName, OBJ_ARROW, class="num">0, barTime, price))
     {
       ObjectSetInteger(class="num">0, arrowName, OBJPROP_COLOR, arrowColor);
       ObjectSetInteger(class="num">0, arrowName, OBJPROP_ARROWCODE, arrowCode);
       ObjectSetInteger(class="num">0, arrowName, OBJPROP_WIDTH, ArrowWidth);
     }
  else
     {
       Print("Failed to create arrow object: ", arrowName);
     }
  }
SignalType CheckForSignal(const class="type">class="kw">double &sarArray[], const class="type">class="kw">double &openArray[], const class="type">class="kw">double &closeArray)
  {
  class=class="str">"cmt">// Mapping indices:
  class=class="str">"cmt">// Index class="num">0: Last closed bar(current candidate)
  class=class="str">"cmt">// Index class="num">1: Previous bar
  class=class="str">"cmt">// Index class="num">2: Bar before previous

  class="type">class="kw">double sar0 = sarArray[class="num">0], sar1 = sarArray[class="num">1], sar2 = sarArray[class="num">2];
  class="type">class="kw">double open0 = openArray[class="num">0], close0 = closeArray[class="num">0];
  class="type">class="kw">double open1 = openArray[class="num">1], close1 = closeArray[class="num">1];
  }

常见问题

默认用 0.02 步长、0.2 最大步长、起始 3 根 K 线;实盘前先在对应品种 1 小时图回看 3 个月翻转密度再微调。
单纯 PSAR 翻转在震荡市假突破多;用吞没或实体破前高/低做二次确认,能过滤掉约三成以上毛刺信号。
可以。小布盯盘已内置抛物转向叠加价格行为诊断,打开对应品种页即可看到实时翻转与等待状态,不用自己写 EA。
等待机制是留一根 K 线看收盘是否守住突破;能避开影线诱多/诱空,代价是偶尔慢半根 K 线进场。
黄金等贵金属波幅大、跳空多,PSAR 在亚盘流动性薄时翻转频率偏高,建议加 Spread 与时段过滤再上实盘。