价格行为分析工具包开发(第七部分):信号脉冲智能交易系统(EA)·进阶篇
⚙️

价格行为分析工具包开发(第七部分):信号脉冲智能交易系统(EA)·进阶篇

(2/3)· 当M15、M30、H1三线共振时才出手,这套MQL5多周期EA把虚假信号压到最低

实战向进阶 第 2/3 篇
很多手动交易者只看单一周期布林带下轨就抄底,结果在高波动里连吃假突破。把随机震荡器超卖状态叠上M15/M30/H1三重确认,信号可信度会明显不同。

「三周期布林带叠随机的入场箭头逻辑」

这段核心片段干的事很直接:先抓三个周期(Timeframe1/2/3)的布林带下轨 lower1~3、上轨 upper1~3,以及各自的随机指标 K 值 k1~k3;任意一项取数失败就 Print 报错并 return,不往下走。 close1~3 用 iClose 取当前柱收盘价,买信号要求是三个周期收盘价同时≤各自下轨,且 k1、k2、k3 全部 < 5(超卖);卖信号反过来,收盘价≥上轨且 K 值全 > 95(超买)。 箭头落盘前用 ArrowExists(close1) 挡重:同一价位区域已有箭头就不再画。买箭头 arrowcode=241 绿色宽2,卖箭头 arrowcode=242 红色,名字拼了 TimeCurrent() 做去重。 信号一旦成立,除了画对象,还顺手把时间、价格、方向塞进三个动态数组(signalTimes/Prices/BuySignals)留底。外汇与贵金属杠杆高,这种多周期共振只在概率上倾向过滤假突破,实盘请先在 MT5 策略测试器跑一遍。

MQL5 / C++
Print("Error retrieving Bollinger Bands data.");
   class="kw">return;
   }
 if(!GetStochastic(Timeframe1, k1, d1) ||
    !GetStochastic(Timeframe2, k2, d2) ||
    !GetStochastic(Timeframe3, k3, d3))
   {
    Print("Error retrieving Stochastic data.");
    class="kw">return;
   }
class=class="str">"cmt">// Retrieve the close prices
 close1 = iClose(Symbol(), Timeframe1, class="num">0);
 close2 = iClose(Symbol(), Timeframe2, class="num">0);
 close3 = iClose(Symbol(), Timeframe3, class="num">0);
 class="type">bool buySignal = (close1 <= lower1 && close2 <= lower2 && close3 <= lower3) &&
                   (k1 < class="num">5 && k2 < class="num">5 && k3 < class="num">5); class=class="str">"cmt">// Oversold condition
 class="type">bool sellSignal = (close1 >= upper1 && close2 >= upper2 && close3 >= upper3) &&
                   (k1 > class="num">95 && k2 > class="num">95 && k3 > class="num">95); class=class="str">"cmt">// Overbought condition
class=class="str">"cmt">// Check if an arrow already exists in the same region before placing a new one
 if(buySignal && !ArrowExists(close1))
   {
    Print("Buy signal detected on all timeframes with Stochastic confirmation!");
    class="type">class="kw">string arrowName = "BuySignal" + IntegerToString(TimeCurrent());
    ObjectCreate(class="num">0, arrowName, OBJ_ARROW, class="num">0, TimeCurrent(), close1);
    ObjectSetInteger(class="num">0, arrowName, OBJPROP_ARROWCODE, class="num">241);
    ObjectSetInteger(class="num">0, arrowName, OBJPROP_COLOR, clrGreen);
    ObjectSetInteger(class="num">0, arrowName, OBJPROP_WIDTH, class="num">2);
    class=class="str">"cmt">// Store signal data
    ArrayResize(signalTimes, ArraySize(signalTimes) + class="num">1);
    ArrayResize(signalPrices, ArraySize(signalPrices) + class="num">1);
    ArrayResize(signalBuySignals, ArraySize(signalBuySignals) + class="num">1);
    signalTimes[ArraySize(signalTimes) - class="num">1] = TimeCurrent();
    signalPrices[ArraySize(signalPrices) - class="num">1] = close1;
    signalBuySignals[ArraySize(signalBuySignals) - class="num">1] = true;
   }
 if(sellSignal && !ArrowExists(close1))
   {
    Print("Sell signal detected on all timeframes with Stochastic confirmation!");
    class="type">class="kw">string arrowName = "SellSignal" + IntegerToString(TimeCurrent());
    ObjectCreate(class="num">0, arrowName, OBJ_ARROW, class="num">0, TimeCurrent(), close1);
    ObjectSetInteger(class="num">0, arrowName, OBJPROP_ARROWCODE, class="num">242);
    ObjectSetInteger(class="num">0, arrowName, OBJPROP_COLOR, clrRed);

信号落库与同区箭头去重的实现细节

信号触发后,先把箭头线宽设为 2,再把时间、价格、方向三个数组各扩容 1 个元素,用 ArraySize-1 下标写入当前时间、收盘价和 false 标记(此处为卖向信号)。这种动态扩容写法在 MT5 脚本里常见,但每来一个信号就 Resize 一次,高频 tick 下可能有轻微开销,实盘前建议在策略测试器里跑一轮看内存曲线。 ArrowExists 函数用 MathAbs(signalPrices[i] - price) <= MinArrowDistance 判断同价位区域是否已有箭头。MinArrowDistance 是外部定义的容差,若设为 0 则只在完全同价时拦截,设大一点(比如 10 点)就能避免密集成交区里箭头叠成一坨。 OnTick 只做一件事:调用 CheckAndGenerateSignal,逻辑极薄,方便你后续把信号函数换成别的指标组合。OnDeinit 里用 ObjectsTotal 倒序遍历,凡名字含 "Signal" 的对象全部删除,防止切换周期或重加载时旧箭头残留——外汇与贵金属波动剧烈,这类残留物容易误导肉眼判势,属高风险环境下的基础卫生。

MQL5 / C++
   ObjectSetInteger(class="num">0, arrowName, OBJPROP_WIDTH, class="num">2);
   class=class="str">"cmt">// Store signal data
   ArrayResize(signalTimes, ArraySize(signalTimes) + class="num">1);
   ArrayResize(signalPrices, ArraySize(signalPrices) + class="num">1);
   ArrayResize(signalBuySignals, ArraySize(signalBuySignals) + class="num">1);
   signalTimes[ArraySize(signalTimes) - class="num">1] = TimeCurrent();
   signalPrices[ArraySize(signalPrices) - class="num">1] = close1;
   signalBuySignals[ArraySize(signalBuySignals) - class="num">1] = false;
   }
}
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Check if an arrow already exists within the MinArrowDistance       |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">bool ArrowExists(class="type">class="kw">double price)
  {
   for(class="type">int i = class="num">0; i < ArraySize(signalPrices); i++)
     {
      if(MathAbs(signalPrices[i] - price) <= MinArrowDistance)
        {
         class="kw">return true; class=class="str">"cmt">// Arrow exists in the same price region
        }
     }
   class="kw">return false; class=class="str">"cmt">// No arrow exists in the same region
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| OnTick Event                                                      |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnTick()
  {
   CheckAndGenerateSignal();
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| OnDeinit Function                                                 |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnDeinit(class="kw">const class="type">int reason)
  {
class=class="str">"cmt">// Clean up the objects
   class="type">long chart_id = class="num">0;
   for(class="type">int i = ObjectsTotal(chart_id) - class="num">1; i >= class="num">0; i--)
     {
      class="type">class="kw">string name = ObjectName(chart_id, i);
      if(StringFind(name, "Signal") != -class="num">1)
        {
         ObjectDelete(chart_id, name);
        }
     }
   Print("Multitimeframe Bollinger-Stochastic Analyzer deinitialized.");
  }
class=class="str">"cmt">//+------------------------------------------------------------------+

◍ 信号脉冲EA的模块拆解与触发阈值

这套EA把多周期布林带与随机震荡器拧成一条信号线,输入参数里写死了 M15、M30、H1 三个周期,布林带周期 20、偏差 2.0,随机%K 周期 14、%D 周期 3、Slowing 3。交易者直接改这几个数,就能把策略从激进调到保守。 SignalInfo 结构体配 signalTimes、signalPrices、signalBuySignals 三个动态数组,负责把每次信号的时间、价格、方向记下来。好处是图表上叠再多发散信号也不会乱,回测时也能逐条翻。 GetBollingerBands() 和 GetStochastic() 都是先建指标句柄、查错、再把轨值和%K/%D拷进数组。句柄创建失败就直接断流,不会拿空数据去跑逻辑——这点比很多开源EA粗糙的容错稳。 核心在 CheckAndGenerateSignal():它把三个周期的最新收盘价都取一遍。买入要同时满足价格≤布林下轨且随机%K<5;卖出要价格≥布林上轨且%K>95。阈值卡到 5 和 95,意味着只在极端超卖/超买才动手,盘整期基本不吐箭头。 ArrowExists() 拿新信号价和 signalPrices 里的旧价比距离,重叠就不画。OnTick 每次报价重算信号,OnDeinit 撤掉所有箭头对象。外汇和贵金属波动大、滑点狠,这种极端阈值也只是降低假信号概率,实盘仍属高风险。 下面这段是头部与输入参数的原码,逐行看: // 版权与链接信息,仅元数据,不影响逻辑 #property copyright "Christian Benjamin" // 作者主页链接 #property link "[MQL5官方文档] // EA版本号 #property version "1.00" // 三个可调周期:M15/M30/H1 input ENUM_TIMEFRAMES Timeframe1 = PERIOD_M15; input ENUM_TIMEFRAMES Timeframe2 = PERIOD_M30; input ENUM_TIMEFRAMES Timeframe3 = PERIOD_H1; // 布林周期20、偏差2.0 input int BB_Period = 20; input double BB_Deviation = 2.0; // 随机%K14、%D3、Slowing3 input int K_Period = 14; input int D_Period = 3; input int Slowing = 3; // 箭头偏移10点,避免贴着K线 input double SignalOffset = 10.0;

MQL5 / C++
<span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span>
<span class="comment">class=class="str">"cmt">//|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Signal Pulse EA.mq5 |</span>
<span class="comment">class=class="str">"cmt">//|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Copyright class="num">2024, MetaQuotes Ltd. |</span>
<span class="comment">class=class="str">"cmt">//|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [MQL5官方文档] |</span>
<span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span>
<span class="preprocessor">class="macro">#class="kw">property </span><span class="macro">copyright</span> <span class="class="type">class="kw">string">"Christian Benjamin"</span>
<span class="preprocessor">class="macro">#class="kw">property </span><span class="macro">link</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="class="type">class="kw">string">"[MQL5官方文档]
<span class="preprocessor">class="macro">#class="kw">property </span><span class="macro">version</span>&nbsp;&nbsp; <span class="class="type">class="kw">string">"class="num">1.00"</span>
<span class="comment">class=class="str">"cmt">// Input parameters</span>
<span class="keyword">input</span> <span class="macro">ENUM_TIMEFRAMES</span> Timeframe1 = <span class="macro">PERIOD_M15</span>; <span class="comment">class=class="str">"cmt">// M15 timeframe</span>
<span class="keyword">input</span> <span class="macro">ENUM_TIMEFRAMES</span> Timeframe2 = <span class="macro">PERIOD_M30</span>; <span class="comment">class=class="str">"cmt">// M30 timeframe</span>
<span class="keyword">input</span> <span class="macro">ENUM_TIMEFRAMES</span> Timeframe3 = <span class="macro">PERIOD_H1</span>;&nbsp;&nbsp;<span class="comment">class=class="str">"cmt">// H1 timeframe</span>
<span class="keyword">input</span> <span class="keyword">class="type">int</span> BB_Period = <span class="number">class="num">20</span>;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">class=class="str">"cmt">// Bollinger Bands period</span>
<span class="keyword">input</span> <span class="keyword">class="type">class="kw">double</span> BB_Deviation = <span class="number">class="num">2.0</span>;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="comment">class=class="str">"cmt">// Bollinger Bands deviation</span>
<span class="keyword">input</span> <span class="keyword">class="type">int</span> K_Period = <span class="number">class="num">14</span>;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="comment">class=class="str">"cmt">// Stochastic %K period</span>
<span class="keyword">input</span> <span class="keyword">class="type">int</span> D_Period = <span class="number">class="num">3</span>;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">class=class="str">"cmt">// Stochastic %D period</span>
<span class="keyword">input</span> <span class="keyword">class="type">int</span> Slowing = <span class="number">class="num">3</span>;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="comment">class=class="str">"cmt">// Stochastic slowing</span>
<span class="keyword">input</span> <span class="keyword">class="type">class="kw">double</span> SignalOffset = <span class="number">class="num">10.0</span>;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">class=class="str">"cmt">// Offset in points for signal arrow</span>

「把布林与随机指标拉进同一函数」

多周期共振策略里,最烦的就是每个时间框架都手写一遍指标读取。这段代码的做法是用两个独立函数把布林带和随机指标分别封装,入参只给时间框架,出参用引用把数值带出来。 TestBars=10 意味着信号出现后只观察随后 10 根 K 线内的胜负;MinArrowDistance=5.0 则点明箭头间距至少 5 个点,避免视觉重叠。这两个 input 直接决定你回测时的判定窗口和图表干净度。 GetBollingerBands 里 iBands 取 BB_Period 和 BB_Deviation,CopyBuffer 分别拷 1/0/2 号缓冲得到上轨、中轨、下轨,任何一步失败就释放句柄返回 false。GetStochastic 同理,iStochastic 用 K_Period、D_Period、Slowing 三参数,拷 0 和 1 号缓冲拿 %K 与 %D。外汇与贵金属杠杆高,这类跨周期调用若周期选错可能频繁重绘,实盘前务必在 MT5 用不同品种跑一遍句柄返回。 下方代码逐行拆开看,能直接抄进 EA 的自定义模块里改周期用。

MQL5 / C++
input class="type">int TestBars = class="num">10; class=class="str">"cmt">// Number of bars after signal to test win condition
input class="type">class="kw">double MinArrowDistance = class="num">5.0; class=class="str">"cmt">// Minimum distance in points between arrows to avoid overlapping
class=class="str">"cmt">// Signal tracking structure
class="kw">struct SignalInfo {
  class="type">class="kw">datetime time;
  class="type">class="kw">double price;
  class="type">bool isBuySignal;
};
class=class="str">"cmt">// Arrays to store signal information
class="type">class="kw">datetime signalTimes[];
class="type">class="kw">double signalPrices[];
class="type">bool signalBuySignals[];
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Retrieve Bollinger Band Levels                                  |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">bool GetBollingerBands(ENUM_TIMEFRAMES timeframe, class="type">class="kw">double &upper, class="type">class="kw">double &lower, class="type">class="kw">double &middle) {
  class="type">int handle = iBands(Symbol(), timeframe, BB_Period, class="num">0, BB_Deviation, PRICE_CLOSE);
  if(handle == INVALID_HANDLE) {
    Print("Error creating iBands for timeframe: ", timeframe);
    class="kw">return false;
  }
  class="type">class="kw">double upperBand[], middleBand[], lowerBand[];
  if(!CopyBuffer(handle, class="num">1, class="num">0, class="num">1, upperBand) ||
     !CopyBuffer(handle, class="num">0, class="num">0, class="num">1, middleBand) ||
     !CopyBuffer(handle, class="num">2, class="num">0, class="num">1, lowerBand)) {
    Print("Error copying iBands buffer for timeframe: ", timeframe);
    IndicatorRelease(handle);
    class="kw">return false;
  }
  upper = upperBand[class="num">0];
  middle = middleBand[class="num">0];
  lower = lowerBand[class="num">0];
  IndicatorRelease(handle);
  class="kw">return true;
}
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Retrieve Stochastic Levels                                      |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">bool GetStochastic(ENUM_TIMEFRAMES timeframe, class="type">class="kw">double &k_value, class="type">class="kw">double &d_value) {
  class="type">int handle = iStochastic(Symbol(), timeframe, K_Period, D_Period, Slowing, MODE_SMA, STO_CLOSECLOSE);
  if(handle == INVALID_HANDLE) {
    Print("Error creating iStochastic for timeframe: ", timeframe);
    class="kw">return false;
  }
  class="type">class="kw">double kBuffer[], dBuffer[];
  if(!CopyBuffer(handle, class="num">0, class="num">0, class="num">1, kBuffer) ||  class=class="str">"cmt">// %K line
     !CopyBuffer(handle, class="num">1, class="num">0, class="num">1, dBuffer)) { class=class="str">"cmt">// %D line
    Print("Error copying iStochastic buffer for timeframe: ", timeframe);
    IndicatorRelease(handle);

三周期布林带与随机指标共振的信号落地

把多周期数据收口后,真正产生交易提示的环节在 CheckAndGenerateSignal 里。它先并行抓取三个周期(Timeframe1/2/3)的布林带上下轨与中轨,以及随机指标的 K、D 值;任意一项取数失败就直接 Print 报错并退出,避免用脏数据画信号。 close 价格用 iClose 取当前柱收盘价,随后定义 buySignal:三个周期收盘价同时 ≤ 各自下轨,且三个周期的 K 值均 < 5,属于极端超卖共振;sellSignal 则反过来,收盘价 ≥ 上轨且 K 值全部 > 95。这两个阈值(5 与 95)是原文硬写死的,调参时可直接改数字观察触发频率变化。 信号不是无脑画:buySignal 成立还需 ArrowExists(close1) 为假,即在同价位区域没有旧箭头才允许新建。创建时用 OBJ_ARROW、箭头代码 241、绿色、宽度 2,并以 TimeCurrent 拼接名称防重名。 落地的同时把信号时间、价格、方向写进动态数组(ArrayResize 逐个加长),这部分结构让后续做统计或接小布分析有了原始流水。外汇与贵金属杠杆高,这类共振只表示概率倾斜,实盘前请在 MT5 策略测试器跑多周期样本核验触发密度。

MQL5 / C++
class="type">void CheckAndGenerateSignal() {
   class="type">class="kw">double upper1, lower1, middle1, close1;
   class="type">class="kw">double upper2, lower2, middle2, close2;
   class="type">class="kw">double upper3, lower3, middle3, close3;
   class="type">class="kw">double k1, d1, k2, d2, k3, d3;
   if(!GetBollingerBands(Timeframe1, upper1, lower1, middle1) ||
      !GetBollingerBands(Timeframe2, upper2, lower2, middle2) ||
      !GetBollingerBands(Timeframe3, upper3, lower3, middle3)) {
      Print("Error retrieving Bollinger Bands data.");
      class="kw">return;
   }
   if(!GetStochastic(Timeframe1, k1, d1) ||
      !GetStochastic(Timeframe2, k2, d2) ||
      !GetStochastic(Timeframe3, k3, d3)) {
      Print("Error retrieving Stochastic data.");
      class="kw">return;
   }
   class=class="str">"cmt">// Retrieve the close prices
   close1 = iClose(Symbol(), Timeframe1, class="num">0);
   close2 = iClose(Symbol(), Timeframe2, class="num">0);
   close3 = iClose(Symbol(), Timeframe3, class="num">0);
   class="type">bool buySignal = (close1 <= lower1 && close2 <= lower2 && close3 <= lower3) &&
                   (k1 < class="num">5 && k2 < class="num">5 && k3 < class="num">5); class=class="str">"cmt">// Oversold condition
   class="type">bool sellSignal = (close1 >= upper1 && close2 >= upper2 && close3 >= upper3) &&
                    (k1 > class="num">95 && k2 > class="num">95 && k3 > class="num">95); class=class="str">"cmt">// Overbought condition
   class=class="str">"cmt">// Check if an arrow already exists in the same region before placing a new one
   if(buySignal && !ArrowExists(close1)) {
      Print("Buy signal detected on all timeframes with Stochastic confirmation!");
      class="type">class="kw">string arrowName = "BuySignal" + IntegerToString(TimeCurrent());
      ObjectCreate(class="num">0, arrowName, OBJ_ARROW, class="num">0, TimeCurrent(), close1);
      ObjectSetInteger(class="num">0, arrowName, OBJPROP_ARROWCODE, class="num">241);
      ObjectSetInteger(class="num">0, arrowName, OBJPROP_COLOR, clrGreen);
      ObjectSetInteger(class="num">0, arrowName, OBJPROP_WIDTH, class="num">2);
      class=class="str">"cmt">// Store signal data
      ArrayResize(signalTimes, ArraySize(signalTimes) + class="num">1);
      ArrayResize(signalPrices, ArraySize(signalPrices) + class="num">1);
      ArrayResize(signalBuySignals, ArraySize(signalBuySignals) + class="num">1);
      signalTimes[ArraySize(signalTimes) - class="num">1] = TimeCurrent();
让小布替你跑这套
这些多周期信号汇聚的判定逻辑,小布盯盘的AIGC已内置,打开对应品种页即可看到三周期布林带与随机震荡器的同步状态,不必自己切图核对。

常见问题

布林带提供波动性与动态支撑阻力,随机震荡器识别超买超卖并作确认,二者叠加能在高波动期过滤掉相当一部分虚假信号,概率上更稳妥。
原文示例采用这三档周期做共振,但MQL5代码里时间框架参数通常可配置,改成其他周期需同步校验指标缓冲与信号等待逻辑,否则可能漏信号。
小布盯盘已内置多周期布林带与随机震荡器汇聚的看板,可用于诊断而非自动下单;外汇贵金属属高风险,信号仅作辅助参考。
由于本EA依赖多周期确认后入场,入场时机相对集中,滑点会侵蚀部分盈利,建议在测试里按经纪商实际点差与滑点区间做 sensitivity 检查。