如何利用 MQL5 检测蜡烛形态·进阶篇
🕯️

如何利用 MQL5 检测蜡烛形态·进阶篇

(2/3)· 手动盯形态漏信号?用 MQL5 把单烛、双烛、三烛的判定写成可复用的函数

含代码示例 第 2/3 篇
很多交易者只在肉眼看到锤子线时才反应过来,但更大时间帧里的十字星往往提前半天就出现了。把形态判定交给代码,你只需要决定怎么用信号。本文接着上篇基础概念,直接进函数层面的实现。

◍ 倒锤子形态的判定与标记逻辑

这段片段在做一件事:当K线满足特定影线比例时,在图表上标出'Inverted Hammer'(倒锤子)并直接返回 -1 终止后续判断。 对于阳线(close>=open),若 high-close 大于 candleSize*longShadowRatio,就在 low 位置创建编号217、绿色的对象并写'Inverted Hammer',随后 return -1。阴线分支里,先要求 close-low 小于 candleSize*smallShadowRatio(下影极小),且 high-open 大于 candleSize*longShadowRatio,才在 high 处创建编号218、红色对象并同样 return -1。 末尾根据颜色设置锚点:绿色对象 ANCHOR_TOP 贴顶,红色对象 ANCHOR_BOTTOM 贴底,避免文字压住影线。外汇与贵金属波动大,这类形态只提示概率倾向,需结合更高周期确认,杠杆交易高风险。 直接把这段代码贴进 MT5 的 K 线扫描函数里,把 longShadowRatio 设成 0.6、smallShadowRatio 设成 0.1,能在 EURUSD 的 M15 上肉眼验证标记位置是否如预期。

MQL5 / C++
if(high-close>candleSize*longShadowRatio)
      createObj(time,low,class="num">217, clrGreen,"Inverted Hammer");
   {
      class="kw">return -class="num">1;
   }
  }
 }
 if(open>close)
 {
   if(close-low < candleSize*smallShadowRatio)
    {
     if(high-open>candleSize*longShadowRatio)
       createObj(time,high,class="num">218, clrRed,"Inverted Hammer");
    {
       class="kw">return -class="num">1;
    }
   }
 }
    if(clr==clrGreen)
       ObjectSetInteger(class="num">0,objName,OBJPROP_ANCHOR,ANCHOR_TOP);
    if(clr==clrRed)
       ObjectSetInteger(class="num">0,objName,OBJPROP_ANCHOR,ANCHOR_BOTTOM);

「两根K线怎么喂给EA做形态识别」

双烛结构里最常被拿来自动化的两类是吞噬与刺透/乌云。吞噬要求后一根实体完全包住前一根:看涨吞噬是前一根阴线、后一根阳线且 high>high2、low<low2、close>open2、open<close2;看跌吞噬反过来,close<open2 且 open>close2。刺透线则是前阴后阳、开盘低于前低、收盘冲过前一根中点(close>candleMidPoint2 且 close<high2);乌云盖顶为前阳后阴、开盘高于前低、收盘跌破前中点。 把这些关系写成判定并不难,关键是取数对。以吞噬为例,EA 在 OnTick 里只需拉出最近两根蜡烛的 time、open、high、low、close(索引 1 和 2),逐条件比对即可。识别成功后用 Wingdings 箭头标:看涨吞用 code 217 绿色置于低点下,看跌吞用 code 218 红色置于高点上方。 外汇与贵金属杠杆高,形态只是概率信号,吞没成立不代表反向一定反转,实盘前请在 MT5 策略测试器跑 EURUSD 15 分钟样本验证箭头位置是否与肉眼一致。 刺透和乌云多了两个派生量:candleSize2 与前一根中点 candleMidPoint2。若 close 落在中点另一侧且缺口开盘,才返 'Piercing' 或 'Dark Cloud' 文本。下面这段是吞噬检测核心,逐行看就是怎么把 K 线坐标抓进变量再走 if 分支。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
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; Engulfing pattern detector.mq5 |
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">2023, MetaQuotes Ltd. |
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官方文档] |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnTick()
  {
   getEngulfing();
  }
class="type">int getEngulfing()
  {
   class="type">class="kw">datetime time=iTime(_Symbol,PERIOD_CURRENT,class="num">1);
   class="type">class="kw">double open=iOpen(_Symbol,PERIOD_CURRENT,class="num">1);
   class="type">class="kw">double high=iHigh(_Symbol,PERIOD_CURRENT,class="num">1);
   class="type">class="kw">double low=iLow(_Symbol,PERIOD_CURRENT,class="num">1);
   class="type">class="kw">double close=iClose(_Symbol,PERIOD_CURRENT,class="num">1);
   class="type">class="kw">double open2=iOpen(_Symbol,PERIOD_CURRENT,class="num">2);
   class="type">class="kw">double high2=iHigh(_Symbol,PERIOD_CURRENT,class="num">2);
   class="type">class="kw">double low2=iLow(_Symbol,PERIOD_CURRENT,class="num">2);
   class="type">class="kw">double close2=iClose(_Symbol,PERIOD_CURRENT,class="num">2);
   if(open<close)
     {
      if(open2>close2)
        {
         if(high>high2&&low<low2)
           {

吞没形态的信号标注与对象绘制

这段代码实现的是经典看涨/看跌吞没形态(Engulfing)的识别与图表标注。逻辑上先比对前一根(索引2)与当前根(索引1)的阴阳与高低:当前收高于开、且前根收低于开,同时当前高低完全包住前根,才判定为 Bullish Engulfing,返回 1;反向条件满足则标 Bearish Engulfing,返回 -1。 createObj 函数负责把信号画到图上。箭头代码 217 对应 clrGreen 的看涨箭头,218 对应 clrRed 的看跌箭头;绿色锚定在 K 线上方(ANCHOR_TOP),红色锚定在下方(ANCHOR_BOTTOM),并用 OBJ_TEXT 在同位置写出形态名称。 在 MT5 里直接挂这段到自定义指标,EURUSD 的 H1 周期回看,吞没信号出现频率约每 80~120 根 K 线一次,但后续 20 根内反向回吐的概率不低,外汇与贵金属杠杆品种高风险,仅作形态参考而非入场保证。 别把箭头当圣杯 信号函数只解决“画出来”,没过滤震荡市。建议你在 iTime/iOpen 取数后加一道 ATR 阈值判断,波幅不够时直接 return 0,能砍掉一批假吞没。

MQL5 / C++
if(close>open2&&open<close2)
      {
       createObj(time,low,class="num">217, clrGreen,"Bullish Engulfing");
         {
           class="kw">return class="num">1;
         }
       }
     }
   }
 }
  if(open>close)
  {
   if(open2<close2)
     {
     if(high>high2&&low<low2)
       {
       if(close<open2&&open>close2)
         {
          createObj(time,high,class="num">218, clrRed,"Bearish Engulfing");
           {
             class="kw">return -class="num">1;
           }
         }
       }
     }
  }
  class="kw">return class="num">0;
 }
class="type">void createObj(class="type">class="kw">datetime time, class="type">class="kw">double price, class="type">int arrawCode, class="type">class="kw">color clr, class="type">class="kw">string txt)
  {
  class="type">class="kw">string objName=" ";
  StringConcatenate(objName, "Signal@",time, "at",DoubleToString(price,_Digits),"(",arrawCode,")");
  if(ObjectCreate(class="num">0,objName,OBJ_ARROW,class="num">0,time,price))
    {
     ObjectSetInteger(class="num">0,objName,OBJPROP_ARROWCODE,arrawCode);
     ObjectSetInteger(class="num">0,objName,OBJPROP_COLOR,clr);
     if(clr==clrGreen)
       ObjectSetInteger(class="num">0,objName,OBJPROP_ANCHOR,ANCHOR_TOP);
     if(clr==clrRed)
       ObjectSetInteger(class="num">0,objName,OBJPROP_ANCHOR,ANCHOR_BOTTOM);
    }
  class="type">class="kw">string candleName=objName+txt;
  if(ObjectCreate(class="num">0,candleName,OBJ_TEXT,class="num">0,time,price))
    {
     ObjectSetString(class="num">0,candleName,OBJPROP_TEXT," "+txt);
     ObjectSetInteger(class="num">0,candleName,OBJPROP_COLOR,clr);
    }
  }
   class="type">class="kw">datetime time=iTime(_Symbol,PERIOD_CURRENT,class="num">1);
   class="type">class="kw">double open=iOpen(_Symbol,PERIOD_CURRENT,class="num">1);
   class="type">class="kw">double high=iHigh(_Symbol,PERIOD_CURRENT,class="num">1);

◍ 吞没形态的检测逻辑与代码拆解

在 MT5 里识别看涨/看跌吞没,核心是先抓前一根与当前根的 OHLC。下面这段代码用 iLow、iClose、iOpen、iHigh 分别取当前根(索引1)和前一根(索引2)的价位,注意 PERIOD_CURRENT 代表当前图表周期,换周期不用改代码。 判断分支很直白:若当前根收大于开(阳线),且前一根收小于开(阴线),同时当前高低点完全包住前一根(high>high2 && low<low2),并且当前收盘穿透前一根开盘、当前开盘低于前一根收盘,就判定为 Bullish Engulfing,标记色 217(绿)、返回 1。对称地,当前根阴线吞没前一根阳线则返回 -1、标红 218。 实盘验证时把这段接进 OnTick,每笔报价都会跑一次 getPiercing()。外汇与贵金属杠杆高,形态成立只代表反转概率倾向上升,不代表一定反转,建议先开 MT5 用 EURUSD 的 M15 回看近 3 个月信号密度再决定是否上实盘。

MQL5 / C++
class="type">class="kw">double low=iLow(_Symbol,PERIOD_CURRENT,class="num">1);
class="type">class="kw">double close=iClose(_Symbol,PERIOD_CURRENT,class="num">1);
class="type">class="kw">double open2=iOpen(_Symbol,PERIOD_CURRENT,class="num">2);
class="type">class="kw">double high2=iHigh(_Symbol,PERIOD_CURRENT,class="num">2);
class="type">class="kw">double low2=iLow(_Symbol,PERIOD_CURRENT,class="num">2);
class="type">class="kw">double close2=iClose(_Symbol,PERIOD_CURRENT,class="num">2);
if(open<close)
  {
   if(open2>close2)
     {
      if(high>high2&&low<low2)
        {
         if(close>open2&&open<close2)
           {
            createObj(time,low,class="num">217, clrGreen,"Bullish Engulfing");
             {
               class="kw">return class="num">1;
             }
           }
        }
     }
  }
if(open>close)
  {
   if(open2<close2)
     {
      if(high>high2&&low<low2)
        {
         if(close<open2&&open>close2)
           {
            createObj(time,high,class="num">218, clrRed,"Bearish Engulfing");
             {
               class="kw">return -class="num">1;
             }
           }
        }
     }
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//|                     Piercing && Dark Cloud pattern detector.mq5 |
class=class="str">"cmt">//|                     Copyright class="num">2023, MetaQuotes Ltd. |
class=class="str">"cmt">//|                                [MQL5官方文档] |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnTick()
  {
   getPiercing();  
  }
class="type">int getPiercing()
  {
   class="type">class="kw">datetime time=iTime(_Symbol,PERIOD_CURRENT,class="num">1);
   class="type">class="kw">double open=iOpen(_Symbol,PERIOD_CURRENT,class="num">1);
   class="type">class="kw">double high=iHigh(_Symbol,PERIOD_CURRENT,class="num">1);

「刺透与乌云盖顶的判定落地」

这段逻辑在抓两根 K 线的反转组合:前一根是阴线、当前是阳线且开盘低于前根最低,收在前面实体半位之上但没破前高,就判为刺透(Piercing),标记码 217 返回 1;反过来前阳后阴、开盘高于前高、收在半位之下但不破前低,就是乌云盖顶(Dark Cloud),标记码 218 返回 -1。 具体取值上,candleMidPoint2 用 high2 - (high2-low2)/2 算出前一根实体中点,close 必须跨过这条线才满足反转强度,避免碰到影线就误报。外汇和贵金属波动大、影线多,这种半位过滤能砍掉一批假信号,但仍可能漏掉跳空缺口形成的极端反转。 createObj 负责把信号画到图上:用 ObjectCreate 建 OBJ_ARROW,箭码直接写死 217/218,绿箭锚定 ANCHOR_TOP 放在 K 线下方。你在 MT5 里把这段挂上 EURUSD 的 M15,能看到刺透自动标绿箭、乌云标红箭,回看最近 200 根大概能抓到 10~20 次这类组合,自己数一下胜率再决定跟不跟。

MQL5 / C++
class="type">class="kw">double low=iLow(_Symbol,PERIOD_CURRENT,class="num">1);
class="type">class="kw">double close=iClose(_Symbol,PERIOD_CURRENT,class="num">1);
class="type">class="kw">double open2=iOpen(_Symbol,PERIOD_CURRENT,class="num">2);
class="type">class="kw">double high2=iHigh(_Symbol,PERIOD_CURRENT,class="num">2);
class="type">class="kw">double low2=iLow(_Symbol,PERIOD_CURRENT,class="num">2);
class="type">class="kw">double close2=iClose(_Symbol,PERIOD_CURRENT,class="num">2);
class="type">class="kw">double candleSize2=high2-low2;
class="type">class="kw">double candleMidPoint2=high2-(candleSize2/class="num">2);
if(open<close)
  {
   if(open2>close2)
     {
      if(open<low2)
        {
         if(close>candleMidPoint2&&close<high2)
           {
            createObj(time,low,class="num">217, clrGreen,"Piercing");
             {
               class="kw">return class="num">1;
             }
           }
        }
     }
  }
if(open>close)
  {
   if(open2<close2)
     {
      if(open>high2)
        {
         if(close<candleMidPoint2&&close>low2)
           {
            createObj(time,high,class="num">218, clrRed,"Dark Cloud");
             {
               class="kw">return -class="num">1;
             }
           }
        }
     }
  }
class="kw">return class="num">0;
}
class="type">void createObj(class="type">class="kw">datetime time, class="type">class="kw">double price, class="type">int arrawCode, class="type">class="kw">color clr, class="type">class="kw">string txt)
  {
   class="type">class="kw">string objName=" ";
   StringConcatenate(objName, "Signal@",time, "at",DoubleToString(price,_Digits),"(",arrawCode,")");
   if(ObjectCreate(class="num">0,objName,OBJ_ARROW,class="num">0,time,price))
     {
      ObjectSetInteger(class="num">0,objName,OBJPROP_ARROWCODE,arrawCode);
      ObjectSetInteger(class="num">0,objName,OBJPROP_COLOR,clr);
      if(clr==clrGreen)
        ObjectSetInteger(class="num">0,objName,OBJPROP_ANCHOR,ANCHOR_TOP);

刺透与乌云盖顶的判定收口

这段逻辑接在前面两根 K 线的属性计算之后,专门处理阴阳反转形态的收尾判定。先看刺透形态:当前根若为阳线(open<close),前一根为阴线(open2>close2),且当前开盘低于前根最低价(open<low2),当收盘价切入前根实体上半部(close>candleMidPoint2 且 close<high2)时,调用 createObj 在最低价挂绿色「Piercing」标记,函数返回 1,倾向提示多头反扑概率上升。 对称地,乌云盖顶要求当前为阴线、前根为阳线,当前开盘高于前根最高价,且收盘价跌入前根实体下半部(close<candleMidPoint2 且 close>low2),此时在最高价标红色「Dark Cloud」并返回 -1,可能意味着上行受阻。外汇与贵金属品种上这类形态失效频繁,实盘前务必在 MT5 历史数据里跑一遍验证触发频率。 代码里 createObj 的第三参数 217 / 218 是对象类型或样式标识,配合 clrGreen / clrRed 控制锚点与颜色;若你改了画线样式,这两个数字也要同步核对,否则标记可能不显示。

MQL5 / C++
  if(clr==clrRed)
     ObjectSetInteger(class="num">0,objName,OBJPROP_ANCHOR,ANCHOR_BOTTOM);
   }
  class="type">class="kw">string candleName=objName+txt;
  if(ObjectCreate(class="num">0,candleName,OBJ_TEXT,class="num">0,time,price))
   {
    ObjectSetString(class="num">0,candleName,OBJPROP_TEXT," "+txt);
    ObjectSetInteger(class="num">0,candleName,OBJPROP_COLOR,clr);
   }
  }
  class="type">class="kw">double candleSize2=high2-low2;
  class="type">class="kw">double candleMidPoint2=high2-(candleSize2/class="num">2);
  if(open<close)
   {
    if(open2>close2)
     {
     if(open<low2)
      {
      if(close>candleMidPoint2&&close<high2)
       {
       createObj(time,low,class="num">217, clrGreen,"Piercing");
        {
         class="kw">return class="num">1;
        }
       }
      }
     }
   }
  if(open>close)
   {
    if(open2<close2)
     {
     if(open>high2)
      {
      if(close<candleMidPoint2&&close>low2)
       {
       createObj(time,high,class="num">218, clrRed,"Dark Cloud");
        {
         class="kw">return -class="num">1;
        }
       }
      }
     }
   }
把形态扫描交给小布盯盘
这些诊断小布盯盘的 AIGC 已内置,打开对应品种页即可看到实时形态标记,你专注判断位置而非逐根数蜡烛。

常见问题

点差和跳价时刻会影响返回值,建议在 OnTick 之外用当前柱收盘后的一次性校验,避免中途毛刺触发误判。
可以,小布盯盘的品种页已内置常见三烛形态的识别,无需自己写 CI 函数也能在图表上看到提示。
比较两根的 open/close 边界,第二根 open 高于第一根 close 且 close 低于第一根 open 即为看跌吞没,反之看涨。
中间线实体最短代表犹豫区间,配合前后两根方向反转才构成概率较高的晨星,漏掉这步会把普通回调误标成信号。