如何利用 MQL5 检测蜡烛形态·综合运用
🕯️

如何利用 MQL5 检测蜡烛形态·综合运用

(3/3)·把十字星、吞没、晨星等形态写成可复用函数,让你的终端自己报信号

含代码示例实战向 第 3/3 篇

很多交易者盯着图表手动数蜡烛,漏看一根就可能错过关键反转。把形态识别写进 MQL5,终端会在跳价时自动判定,你只需要在信号出现时做决策。本文是系列收尾篇,聚焦单烛、双烛、三烛形态的综合检测实现。

◍ 三烛形态

在这一部分中,我们将看到混合形态中的两种形态,它们是星形(Star)形态(晨星、暮星),和三个内部形态(向上、向下)。 星形(Star)形态: 晨星: 它与我们提过的三根蜡烛结构相同。 它由两根蜡烛之间的小蜡烛形成,第一根是较长看跌,第二根是较长看涨。 下图是它的图例: 取决于其显著性,它表明推动力从卖出转向买入,因为自卖方控制下的压低后,买方控制市场,并推高价格。 暮星形态: 它与我们提过的三根蜡烛结构相同。 它由两根蜡烛之间的小蜡烛形成,第一根是较长看涨,第二根是较长看跌。 下图是它的图例: 取决于其显著性,它表明推动力从买入转向卖出,因为自买方控制下的推高后,卖方控制市场,并压低价格。 当我们想要创建一个可检测这种形态的程序时,我们需要定义最后一根蜡烛的时间和价格,以及最后一根蜡烛之前两根蜡烛的价格数据,之前第三根蜡烛的大小,并将它们相互比较,以便判定它们彼此的相对位置,从而根据特定条件获得特定信号。 以下是创建此程序的完整代码: 此代码的不同之处 依据 middleCandleRatio 参数,创建(getStar) 创建变量保存最后一根蜡烛时间和价格数据(open、high、low、close),和最后三根蜡烛的大小(candlesize、candleSize2 和  candleSize3 ) 形态的条件 若为晨星形态的情况: 如果最后一根蜡烛看涨(open<close),第三根蜡烛看跌(open3>close3),candleSize2<candleSize 的 middleCandleRatio 0.5,同时 candleSize2<candleSize3 的 middleCandleRatio,我们需要程序在形态低点下方返回一个绿色箭头对象,和 “Morning Star” 文本, 然后终止函数。 若为暮星形态的情况: 如果最后一根蜡烛看跌(open>close), 第三根蜡烛看涨(open3<close3) ,candleSize2<candleSize 的 middleCandleRatio 0.5,同时 candleSize2<candleSize3 的 middleCandleRatio,我们需要程序在形态低点下方返回一个红色箭头对象,和 “Evening Star” 文本, 然后终止函数。 在编译此代码,且没有错误,并执行其 EA 后,我们可从测试中获得与以下示例相同的信号: 晨星: 如我们所见,我们在检测到的形态下方的图表上得到所需对象的期望信号。 暮星: 如我们所见,我们在检测到的形态下方的图表上得到所需对象的期望信号。 作为星形形态的注解,相同的形态形成与中间的小蜡烛有间隙,如果您想获得相同的形态,可以将其作为附加条件添加到代码之中。 三内含形态: 三内含向上: 这也是三根蜡烛形态,第一根蜡烛是较长看跌,第二根是较短看涨蜡烛,且全部在第一根蜡烛内部,第三根是较长看涨蜡烛,收于第一根高点上方。 以下是此形态的图例。 取决于其显著性,它表明买方控制的潜在看涨。 三内含向下: 这也是三根蜡烛形态,第一根蜡烛是较长看涨,第二根是较短看跌蜡烛,且全部在第一根蜡烛内部,第三根是较长看跌蜡烛,收于第一根低点下方。 以下是此形态的图例。 取决于其显著性,它表明卖方控制的潜在看跌。 如果我们想创建一个可检测此类形态的程序,我们还需定义最后一根蜡烛的时间和最后三根蜡烛的价格数据,程序会在每次跳价时检查这些数值,并判定其彼此的相对位置,以便根据形态返回相应的信号作为图表上的对象。 以下是该程序的完整代码: 此代码中的不同之处在于形态的

「晨星与暮星的信号判定和图形标注」

这段逻辑用三根 K 线识别经典反转形态:当前根(索引1)为阳线且三根前(索引3)为阴线时,若中间根(索引2)的实体振幅同时小于左右两根乘以 middleCandleRatio,就判定为晨星并回传 1;反之为暮星回传 -1,都不满足回传 0。 middleCandleRatio 是形态有效性的核心阈值,实盘里常取 0.3~0.5,值越小代表中间十字星越萎缩、信号越苛刻。外汇与贵金属波动剧烈,此类形态仅代表概率倾斜,不代表后续必反转,请先在 MT5 策略测试器用历史数据验证。 createObj 负责把信号画到图上:晨星用箭头代码 217 配 clrGreen 锚定在 K 线顶部,暮星用 218 配 clrRed 锚定底部,同时用 OBJ_TEXT 在同级坐标写出 "Morning Star" 或 "Evening Star" 字样,方便肉眼复核。 下面这段是判定与标注的 MQL5 原文,逐行看逻辑比读说明更快:先取 close3 与前三根收盘比对阴阳,再比实体大小,最后调 createObj 落图形。

MQL5 / C++
class="type">class="kw">double close3=iClose(_Symbol,PERIOD_CURRENT,class="num">3);
 class="type">class="kw">double candleSize=high-low;
 class="type">class="kw">double candleSize2=high2-low2;
 class="type">class="kw">double candleSize3=high3-low3;
 if(open<close)
   {
     if(open3>close3)
       {
        if(candleSize2<candleSize*middleCandleRatio && candleSize2<candleSize3*middleCandleRatio)
          {
           createObj(time,low,class="num">217, clrGreen,"Morning Star");
             {
              class="kw">return class="num">1;
             }
          }
       }
   }
 if(open>close)
   {
     if(open3<close3)
       {
        if(candleSize2<candleSize*middleCandleRatio && candleSize2<candleSize3*middleCandleRatio)
          {
           createObj(time,high,class="num">218, clrRed,"Evening Star");
             {
              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">int getStar(class="type">class="kw">double middleCandleRatio)
  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);

三K线星型形态的MT5判定逻辑

晨星与暮星这类三K线反转形态,核心不在于名字,而在于中间那根K线相对两侧的'萎缩'。下面这段代码直接取当前周期最近三根K线(索引1/2/3,即倒数第二、三、四根已完成K线)的 OHLC 与实体高度,用 middleCandleRatio 做中间根的尺寸过滤。 double high=iHigh(_Symbol,PERIOD_CURRENT,1); // 取倒数第二根最高价 double low=iLow(_Symbol,PERIOD_CURRENT,1); // 取倒数第二根最低价 double close=iClose(_Symbol,PERIOD_CURRENT,1);// 取倒数第二根收盘价 double open2=iOpen(_Symbol,PERIOD_CURRENT,2); // 取倒数第三根开盘价 double high2=iHigh(_Symbol,PERIOD_CURRENT,2); // 取倒数第三根最高价 double low2=iLow(_Symbol,PERIOD_CURRENT,2); // 取倒数第三根最低价 double close2=iClose(_Symbol,PERIOD_CURRENT,2);// 取倒数第三根收盘价 double open3=iOpen(_Symbol,PERIOD_CURRENT,3); // 取倒数第四根开盘价 double high3=iHigh(_Symbol,PERIOD_CURRENT,3); // 取倒数第四根最高价 double low3=iLow(_Symbol,PERIOD_CURRENT,3); // 取倒数第四根最低价 double close3=iClose(_Symbol,PERIOD_CURRENT,3);// 取倒数第四根收盘价 double candleSize=high-low; // 倒数第二根实体+影线总高度 double candleSize2=high2-low2; // 倒数第三根总高度 double candleSize3=high3-low3; // 倒数第四根总高度 if(open<close) // 倒数第二根为阳线 { if(open3>close3) // 倒数第四根为阴线 { if(candleSize2<candleSize*middleCandleRatio && candleSize2<candleSize3*middleCandleRatio) // 中间根显著小于两侧 { createObj(time,low,217, clrGreen,"Morning Star"); // 在低点画绿色标记,编码217 return 1; // 返回多头信号 } } } if(open>close) // 倒数第二根为阴线 { if(open3<close3) // 倒数第四根为阳线 { if(candleSize2<candleSize*middleCandleRatio && candleSize2<candleSize3*middleCandleRatio) { createObj(time,high,218, clrRed,"Evening Star"); // 在高点画红色标记,编码218 return -1; // 返回空头信号 } } } 判定只依赖已收盘K线,因此信号在每根K线收线后才会固定,盘中闪现不算数。middleCandleRatio 若设为 0.5,意味着中间根高度必须不到两侧任一根的一半才触发,参数调小则形态更苛刻、信号更少。 外汇与贵金属杠杆高、滑点大,星型形态只是概率倾向反转,实盘须结合更大周期结构过滤,切勿单独据此重仓。

MQL5 / C++
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);
class="type">class="kw">double open3=iOpen(_Symbol,PERIOD_CURRENT,class="num">3);
class="type">class="kw">double high3=iHigh(_Symbol,PERIOD_CURRENT,class="num">3);
class="type">class="kw">double low3=iLow(_Symbol,PERIOD_CURRENT,class="num">3);
class="type">class="kw">double close3=iClose(_Symbol,PERIOD_CURRENT,class="num">3);
class="type">class="kw">double candleSize=high-low;
class="type">class="kw">double candleSize2=high2-low2;
class="type">class="kw">double candleSize3=high3-low3;
if(open<close)
  {
   if(open3>close3)
     {
      if(candleSize2<candleSize*middleCandleRatio && candleSize2<candleSize3*middleCandleRatio)
        {
         createObj(time,low,class="num">217, clrGreen,"Morning Star");
         {
          class="kw">return class="num">1;
         }
        }
     }
  }
if(open>close)
  {
   if(open3<close3)
     {
      if(candleSize2<candleSize*middleCandleRatio && candleSize2<candleSize3*middleCandleRatio)
        {
         createObj(time,high,class="num">218, clrRed,"Evening Star");
         {
          class="kw">return -class="num">1;
         }
        }
     }
  }

◍ 三内部形态在MT5里的裸写识别

三内部(Three Inside)是价格行为里典型的反转确认形态,分向上和向下两类。向上三内部要求第3根阴线、第2根阳线完全包在第3根实体内、第1根阳线再突破第3根高点;向下则对称反转。下面这段代码在每笔报价时抓取最近3根当前周期K线并做条件判定,命中即在K线低位画标记。 外汇与贵金属杠杆高,形态失效是常态,这段代码只做识别不替你下单,信号出现后仍需人工确认上下文。 代码逐行看:iTime/iOpen/iHigh/iLow/iClose 分别取1、2、3号K线(序号从0当前往回数)的时间与OHLC;先判 open3>close3 即第3根收阴,再看 open2<close2 第2根收阳且被第3根实体容纳(open2>low3 && close2<high3),最后第1根收阳且实体处于第2根内部、收盘价破第3根高点,则画绿色『3 Inside Up』对象,编号217是箭头样式。向下分支逻辑镜像,判第3根阳、第2根阴、第1根阴破第3根低点。

MQL5 / C++
class="macro">#class="kw">property link      "[MQL5官方文档]
class="macro">#class="kw">property version   "class="num">1.00"
class="type">void OnTick()
  {
   getthreeInside();
  }
class="type">int getthreeInside()
  {
   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);
   class="type">class="kw">double open3=iOpen(_Symbol,PERIOD_CURRENT,class="num">3);
   class="type">class="kw">double high3=iHigh(_Symbol,PERIOD_CURRENT,class="num">3);
   class="type">class="kw">double low3=iLow(_Symbol,PERIOD_CURRENT,class="num">3);
   class="type">class="kw">double close3=iClose(_Symbol,PERIOD_CURRENT,class="num">3);
   if(open3>close3)
     {
      if(open2<close2)
        {
         if(open2>low3&&close2<high3)
           {
            if(open<close&&open>open2&&open<close2)
              {
               if(close>high3)
                 {
                  createObj(time,low,class="num">217, clrGreen,"class="num">3 Inside Up");
                  {
                   class="kw">return class="num">1;
                  }
                 }
              }
           }
        }
     }
   if(open3<close3)
     {
      if(open2>close2)
        {
         if(open2<high3&&close2>low3)
           {
            if(open>close&&open<open2&&open>close2)
              {
               if(close<low3)
                 {

「三内升跌形态的信号标注函数」

这段逻辑把「三内跌」(3 Inside Down) 与「三内升」(3 Inside Up) 的识别结果直接画到 MT5 主图。前面判断出三内跌时调用 createObj(time,high,218,clrRed,"3 Inside Down"),箭头代码 218 对应红色向下标记,锚点落在 K 线底部;三内升则传 217 与 clrGreen,锚点置顶。 createObj 本身先拼出唯一对象名:Signal@+时间+at+价格(按 _Digits 精度)+括号里箭头码,再用 OBJ_ARROW 建箭头、OBJ_TEXT 建文字标签。绿色走 ANCHOR_TOP,红色走 ANCHOR_BOTTOM,肉眼上涨信号压在最高上方、下跌信号贴在最低下方,不挡实体。 识别嵌套很直白:以三内升为例,第3根须为阴线(open3>close3),第2根为阳线且实体被第3根吞没(open2<close2 且高低在第3根范围内),第1根阳线开盘介于第2根实体内部且收盘突破第3根高点(close>high3)才确认。外汇与贵金属波动大,这种形态只提示概率倾向反转,实盘须自验。

MQL5 / C++
createObj(time,high,class="num">218, clrRed,"class="num">3 Inside Down");
{
 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);
  }
 }
  if(open3>close3)
   {
    if(open2<close2)
     {
      if(open2>low3&&close2<high3)
       {
        if(open<close&&open>open2&&open<close2)
         {
          if(close>high3)
           {
            createObj(time,low,class="num">217, clrGreen,"class="num">3 Inside Up");
             {
              class="kw">return class="num">1;
             }
           }
         }
       }
     }
   }
  if(open3<close3)
   {
    if(open2>close2)
     {
      if(open2<high3&&close2>low3)
       {

三内向下破位的代码判定

在 MT5 的 K 线扫描逻辑里,三内跌(3 Inside Down)并非靠肉眼数蜡烛,而是用三根前置 K 线加当前 K 线做联立条件。上面这段代码片段只负责「确认并标记」环节,前置的 inside bar 结构已在更早分支里筛过。 判定核心是:当前 K 线为阴线(open>close),且其实体开盘价低于前一根开盘价(open<open2)、却高于前一根收盘价(open>close2);在此基础上,若收盘价跌破再前一根低点 low3,则视为向下破位。 破位成立后调用 createObj 在 time 位置、high 价位画一个编号 218、红色标签为「3 Inside Down」的对象,并返回 -1 终止后续同帧判断。外汇与贵金属品种上,这种形态出现后价格惯性下破的概率偏高,但杠杆市场随时反向,实盘前务必用策略测试器跑一遍近 3 个月数据。

MQL5 / C++
if(open>close&&open<open2&&open>close2)
  {
   if(close<low3)
     {
      createObj(time,high,class="num">218, clrRed,"class="num">3 Inside Down");
       {
        class="kw">return -class="num">1;
       }
     }
  }

◍ 别急着下结论

前面六节把单烛、双烛、三烛的识别程序都拆完了:十字星与锤形归在 Doji_pattern_detector.mq5(1.42 KB)和 Hammer_pattern_detector.mq5(2.75 KB);吞噬、刺透、乌云盖顶共用 Engulfing_pattern_detector.mq5(2.37 KB)和 Piercing_ss_Dark_Cloud_pattern_detector.mq5(2.44 KB);星状与三内含则由 Star_pattern_detector.mq5(3.32 KB)、Three_inside_pattern_detector.mq5(2.88 KB)承载。 这些脚本只是把形态从图表里抓出来,不代表出现信号就该动手。外汇和贵金属杠杆高、滑点跳空频繁,同一组吞噬形态在欧美盘与亚盘的成功概率可能差出两三成。 拿 Adams.16 在讨论区的反馈说,他把矩形标记换成信号后指标跑得快了,却卡在「无法把当前信号时间定为上一信号起点的斐波终点」——这说明形态识别只是流水线第一环,后续的位置量化才是真麻烦。 开 MT5 把六个文件逐一挂上 EURUSD 的 M15,先观察两周再谈改动参数,比直接信任何现成结论都稳妥。

把形态扫描交给小布盯盘
这些诊断小布盯盘的 AIGC 已内置,打开对应品种页即可看到自动标注的十字星与吞没形态,你专注判断位置是否配合关键位。

常见问题

三烛形态如晨星依赖先后三根的相对位置关系,需分别用 iOpen/iClose 等取前两根与当前根比对,单根无法判定结构。
可定义实体长度小于下影线三分之一且上影线极短为条件,结合收盘位于区间上部返回信号,减少噪音。
可以,小布盯盘品种页已内置常见烛形识别,无需自行部署 EA 也能看到实时标注与统计。
形态单独出现概率信号弱,需配合支撑阻力;杠杆市场波动剧烈,假突破频繁,任何信号都只是倾向而非确定。
十字星在大周期代表博弈平衡,常作转折预警;吞没代表动能反转,二者叠加可提高信号质量,但都要结合上下文。