研究烛条分析技术(第一部分):检查现存形态

Alexander Fedosov | 26 三月, 2019

内容目录

概述

烛条分析出现在 20 多年前,从此后变得非常流行。众多交易者认为日本烛条是最方便、易懂的资产价格可视化形式。 类似的柱线格式无法提供足够的直观数据。 日本烛条在实体颜色的设置和显示方面更加方便,因此其展现的市场发展更直观。

当前各种烛条分析方法过于泛滥,这些方法大多是各种烛条分类或烛条组合(形态),也许它暗含可能的市场变化。 一些形态指示当前趋势延续,而其他形态则指示趋势逆转和窄幅振荡走势。

然而,烛条分析的年龄和流行程度可能会对那些盲目追捧它的人造成伤害。 市场不会驻足不前。 不仅 20 年后市场动态发生了变化,而且影响市场走势的因素也在不断变化。 一些市场参与者开始怀疑烛条分析普及性,并抵制它。

这就是我们将在本文中要做的事情。 我们考察一些众所周知的判定行情走势的方法,并检验它们在当今的现实中是否仍然具有相关性和有效性。 


定义问题

为了评估形态的效能,我们来开发一套评估其绩效的通用算法。 图例 1 展示一般的行动规划。 我们仔细查看它。


图例1 形态绩效评估算法

步骤 1. 选择一种流行的烛条形态来比较其预期含义和实际结果。 为清楚起见,该算法所提供的示例为烛条形态 Harami 交叉(看涨模型)的形式,即预期上行趋势。 

步骤 2. 定义历史记录间隔和时间帧。 这将有助于更深入地判断和确认形态效率。 这也有助于发现所分析历史深度的依赖性,或判断形态有效或根本不起作用的时间帧。

步骤 3. 在所选间隔内计算形态发生次数。 该次数将用于累积评估,稍后将对此进行讨论。

步骤 4. 分析每个形态匹配的上行趋势,下行趋势或横盘。 在此,我们需要定义预测的准确性,即价格在预期方向上移动了多少点。 假设,趋势是价格走势在一个方向或另一个方向上移动了至少 50 点。 如果未达到指定的移动阈值,则认为在形态之后趋势形成失败。   

步骤 5. 如何判断趋势走势的品质? 形态形成后,价格可以超过 50 点的阈值,但需要多长时间? 这可在所分析时间帧的一根或十根烛条中完成。 所以,趋势必须是有效的,因为找到形态并依据形态信号入场之后等待获利风险极大且低效。 为此目的,引入了以下趋势效率类别。

这种趋势结果的分类能够更客观地评估当前形态的效率。

步骤 6. 计算以下变量:

图例 2 展示的示例涵盖了查找、计算以及从所发现烛条形态的总样本中归类上行趋势和下行趋势。


图例 2 趋势检测和分类的算法和示例。

在这个示例中,我们分析了 H1 时间帧上的 2000 根烛条样本(图例 1),并发现与我们的形态匹配 50 次。 在该形态之后,设定价格移动的阈值为 50 点,则向上 20 次,向下 10 次。 在所有 20 个向上移动的案例中,价格达到阈值 50 点的时间在一根烛条内的 5 次,在 2 根烛条内的 7 次,在 3 根烛条内达到的 8 次。

下行趋势也是如此。 从图例 2 中可以看出,上行趋势的机会和速度更高。 不过,并非总能一目了然地判断状态。 这种直观检验可能会骗人。 特别是,当依据不同样本和时间帧分析形态时,您很容易混淆。

这就是为什么我决定引入累积系数来对给定趋势方向上的任意形态效率进行一般评估。 它看起来如下:

此处的 E 是趋势效率,P 是趋势的概率。 我们来看看趋势效率公式:


此处的 A, B 和 C 展示其中一个类别中发现的趋势次数。k1,k2,k3 是权重系数,因为落在这些类别当中的重要性是不同的。 在一根烛条内达到阈值的 A 类趋势,比在 3 根烛条内达到阈值时更重要。 默认优先级如下:k1 = 1,k2 = 0.5,k3 = 0.25。 这是一种主观感受,因此您可以自行设置首选值。 S 是已发现的给定类型趋势的总数。

趋势出现的概率 P 是某种已发现趋势类型(A,B 或 C)的次数与给定样本中所发现烛条形态总数的比率。 这实际上是基于历史中的先前行为,价格往某个方向移动的概率。

我们从图例 2 的示例中计算上行趋势和下行趋势的效率。  


图例 3 效率计算结果。

从计算中获得以下结果:

  • 趋势效率 E 在上行趋势中更高,这也是能够直观觉察到的。 然而现在我们进行了定量评估。
  • 在这种形态形成的情况下,趋势出现概率 P 对于上行趋势为 40%,对于下行趋势为 20%。
  • 因此,上行趋势预测形态的一般效率高出两倍多。 

为了进一步研究形态相关性,我们将关注两个主要参数:价格移动到烛条形态预测方向的概率,和计算出的效率评估系数。 

这能够为我们的研究提供三个主要结论:

  1. 该形态是否适用于当今的市场条件?
  2. 如果它有效,那么在形态出现时预测得以兑现会有多少机会?
  3. 在这种情况下,我们可以赚取多少以及多快?

 

为烛条形态分析开发原型界面

为了研究所提议模型中的现有形态,基于所定义的任务设计一个便利的图形界面是很有必要的。 为此目的,我们将使用现成的函数库 EasyAndFastGUI 来创建图形界面。

在继续实施之前,我们需要定义外部结构,并创建未来图形应用程序的原型。 然后我们将用软件实现填充它。

一般结构将包含两个选项卡。 第一个选项卡将用于分析现有形态,第二个选项卡将包含所需的设置元素。 我们来更详尽地检视第一个选项卡。


图例 4 “分析”选项卡的结构。

它由五个关键交互对象组成:

  1. 在两个选项卡之间切换,“分析” 和 “设置”。
  2. 搜索需要分析的货币产品的工具。
  3. 结果表格,包括正在分析的形态的名称,在采样范围上发现的匹配次数,形态在研究中出现的频率,上行趋势和下行趋势的概率,以及此形态的上、下行趋势效率评估系数。 此信息将有助于我们了解形态绩效对应于期望的预测特征,以及结果是否与预测相符。
  4. 探索烛条形态的时间帧。
  5. 采样范围。 指定时间帧内的烛条数量,形态将在其内测试。

然后考察第二个选项卡 “设置”。 


图例 5 “设置” 选项卡的结构。

本节介绍影响形态分析结果的参数设置。

  1. 在形态形成时会用到的基本烛条列表。 
  2. 对话窗口。 只需点击齿轮图标即可打开。 该窗口含有参与形态形成时的基本烛条参数的单独设置。
  3. 设置用于计算分析形态效率的权重系数。
  4. 以点为单位的趋势阈值 - 如果价格达到此阈值,则趋势走势确认,并且该形态将被视为成功。

工具实现

在定义理论基础并创建原型之后,我们需要确定应用程序元素的构建顺序。 从图例 5 中可以看出,我们有两个独立的窗口。 第一个内含两个选项卡,“分析” 和 “设置”,而第二个内含烛条类型的其他独立设置。 所以,两种主要的构造方法如下所示:

//+------------------------------------------------------------------+
//| 创建程序的图形界面                                                  |
//+------------------------------------------------------------------+
bool CProgram::CreateGUI(void)
  {
//--- 创建一个面板
   if(!CreateWindow("Pattern Analyzer"))
      return(false);
//--- 创建一个对话窗口
   if(!CreateWindowSetting("Settings"))
      return(false);
//--- 完成 GUI 的创建
   CWndEvents::CompletedGUI();
   return(true);
  }
//+-----------------------------------------------------------------

现在,我们仔细看看每种方法包含的内容。 我们不会详细介绍每种方法,但我们将详细介绍与烛条分析方法直接相关的关键功能。 因此,创建主应用程序窗口 CreateWindow() 的每个方法都包含以下方法,这些方法实现了接口元素:

  • CreateTabs() — 实现 “分析” 和 “设置” 选项卡。
  • CreateSymbolsFilter() — 输入字段和用于搜索所需品种的复选框。
  • CreateRequest() — 按钮,通过单击启动搜索。
  • CreateRange() — 用于指定样本范围的输入字段。
  • CreateComboBoxTF() — 选择执行分析所在时间帧的下拉列表。
  • CreateSymbTable() — 为品种搜索结果创建一个表格。
  • CreateTable() — 含烛条形态分析结果的表格。
  • CreateStatusBar() — 状态栏,显示当前选择的用于分析的品种; 或者,以品种未选择替代。

 此方法列表实现 “分析” 选项卡中的图形元素。 以下是 “设置” 选项卡的方法。

  • CreateCandle() — 用于创建复合元素的方法,其由烛条类型图像和齿轮按钮(图例 4 中的位置 1)组成。 
  • CreateTextLabel() — 在系数组(图例 4 中的位置 3)之前可视化文本标题的方法。
  • CreateCoef() — 该方法显示权重系数的输入字段。
  • CreateThresholdValue() — 该方法显示以点为单位的利润阈值的输入字段。

现在,我们研究第二个窗口的结构,它是由 CreateWindowSetting() 方法实现的附加设置。

我们已创建了一个交互界面。 现在我们继续实现计算和评估方法,在任务定义相关章节的最开始部分,已描述过这些方法。 我们来定义开发阶段和输入条件,这些将用于烛条形态的分析。


图例 6 图形界面创建结果。

如您所知,有些形态是由某种类型的一根、两根、三根和更多根烛条组成。 我们列举一下基本的烛条类型,在我们的烛条形态中会用到它们:

  • 长烛条。 烛条实体 > (过去 5 天的平均实体)*K1,其中 K1 是可调系数(图例 4)。
  • 短逐条。 烛条实体 < (过去 5 天的平均实体)*K1。
  • 尖顶。 下影线 > 实体*K1,以及上影线 > 实体*K1。
  • 十字星。 十字星实体 < (从最高价到最低价的范围)*K1。
  • Marubozu。 下影线 < 实体*K1,或上影线 < 实体*K1。
  • 锤头。 下影线 > 实体*K1,以及上影线 < 实体*K2。

现在,我们研究将众所周知的烛条形态应用在我们的分析方法之上。 我们将使用两种形态类别:由一根烛条和两根烛条组成的形态类别。

一根烛条形态:

  • 锤头 (多头形态)。
  • 吊挂 (空头形态)。
  • 倒锤头 (多头形态)。

两根烛条形态:

  • 射击之星 (空头形态)。
  • 吞噬 (多头形态)。
  • 吞噬 (空头形态)。
  • Harami 交叉 (多头形态)。
  • Harami 交叉 (空头形态)。
  • Harami (多头形态)。
  • Harami (空头形态)。
  • 十字星 (多头形态)。
  • 十字星 (空头形态)。
  • 穿孔 (多头形态)。
  • 乌云盖顶 (空头形态)。

这些类型的烛条和识别它们的方法在 烛条形态调查(模型) 一文中有详述。 这些方法已针对烛条分析算法进行了调整。

算法本身如下:

1. CandleType() 判定基本烛条类型。

//--- 判定烛条类型   
   res.type=CAND_NONE;
//--- 长烛条 
   if(res.bodysize>sum*m_long_coef)
      res.type=CAND_LONG;
//--- 短烛条 
   if(res.bodysize<sum*m_short_coef)
      res.type=CAND_SHORT;
//--- 十字星
   if(res.bodysize<HL*m_doji_coef)
      res.type=CAND_DOJI;
//--- maribozu
   if((shade_low<res.bodysize*m_maribozu_coef || shade_high<res.bodysize*m_maribozu_coef) && res.bodysize>0)
      res.type=CAND_MARIBOZU;
//--- 锤头
   if(shade_low>res.bodysize*m_hummer_coef2 && shade_high<res.bodysize*m_hummer_coef1)
      res.type=CAND_HAMMER;
//--- 倒锤头
   if(shade_low<res.bodysize*m_hummer_coef1 && shade_high>res.bodysize*m_hummer_coef2)
      res.type=CAND_INVERT_HAMMER;
//--- 尖顶
   if(res.type==CAND_SHORT && shade_low>res.bodysize*m_spin_coef && shade_high>res.bodysize*m_spin_coef)
      res.type=CAND_SPIN_TOP;

2. CandleType() 分析出自上述形态之一的一根烛条或两根烛条,并为 PatternType() 方法判定形态类型提供依据数据。

for(int i=m_range_total;i>3;i--)
     {
      CandleType(symbol,cand2,i);                                                      // 之前的烛条
      CandleType(symbol,cand1,i-1);                                                    // 当前烛条

      //--- 倒锤头,多头模型
      if(cand2.trend==DOWN &&                                                             // 检查趋势方向
         cand2.type==CAND_INVERT_HAMMER)                                                  // 检查 "倒锤头"
        {
         m_invert_hummer_total++;
         GetCategory(symbol,i-3,invert_hummer_coef);
        }

      //--- 吊挂,空头
      if(cand2.trend==UPPER &&                                                            // 检查趋势方向
         cand2.type==CAND_HAMMER)                                                         // 检查 "锤头"
        {
         m_handing_man_total++;
         GetCategory(symbol,i-3,handing_man_coef);
        }
      //--- 锤头,多头模型
      if(cand2.trend==DOWN &&                                                             // 检查趋势方向
         cand2.type==CAND_HAMMER)                                                         // 检查 "锤头"
        {
         m_hummer_total++;
         GetCategory(symbol,i-3,hummer_coef);
        }
      //---
      //--- 射击之星,空头模型
      if(cand1.trend==UPPER && cand2.trend==UPPER &&                                      // 检查趋势方向
         cand2.type==CAND_INVERT_HAMMER && cand1.close<=cand2.open)                       // 检查 "倒锤头"
        {
         m_shooting_star_total++;
         GetCategory(symbol,i-4,shooting_star_coef);
        }

      //--- 吞噬,多头模型
      if(cand1.trend==DOWN && cand1.bull && cand2.trend==DOWN && !cand2.bull && // 检查趋势方向和烛条方向
         cand1.bodysize>cand2.bodysize &&
         cand1.close>=cand2.open && cand1.open<cand2.close)
        {
         m_engulfing_bull_total++;
         GetCategory(symbol,i-4,engulfing_bull_coef);
        }

      //--- 吞噬,空头模型
      if(cand1.trend==UPPER && cand1.bull && cand2.trend==UPPER && !cand2.bull && // 检查趋势方向和烛条方向
         cand1.bodysize<cand2.bodysize &&
         cand1.close<=cand2.open && cand1.open>cand2.close)
        {
         m_engulfing_bear_total++;
         GetCategory(symbol,i-4,engulfing_bear_coef);
        }

      //--- Harami 交叉,多头
      if(cand2.trend==DOWN && !cand2.bull &&                                              // 检查趋势方向和烛条方向
         (cand2.type==CAND_LONG || cand2.type==CAND_MARIBOZU) && cand1.type==CAND_DOJI && // 检查 "长烛条" 的第一根烛条和十字星烛条
         cand1.close<cand2.open && cand1.open>=cand2.close)                               // 十字星在第一根烛条实体内
        {
         m_harami_cross_bull_total++;
         GetCategory(symbol,i-4,harami_cross_bull_coef);
        }

      //--- Harami 交叉,空头模型
      if(cand2.trend==UPPER && cand2.bull &&                                              // 检查趋势方向和烛条方向
         (cand2.type==CAND_LONG || cand2.type==CAND_MARIBOZU) && cand1.type==CAND_DOJI && // 检查 "长烛条" 和十字星
         cand1.close>cand2.open && cand1.open<=cand2.close)                               // 十字星在第一根烛条实体内
        {
         m_harami_cross_bear_total++;
         GetCategory(symbol,i-4,harami_cross_bear_coef);
        }

      //--- Harami, 多头
      if(cand1.trend==DOWN && cand1.bull && !cand2.bull &&                                // 检查趋势方向和烛条方向
         (cand2.type==CAND_LONG || cand2.type==CAND_MARIBOZU)  &&                         // 检查 "长烛条" 的第一根烛条
         cand1.type!=CAND_DOJI && cand1.bodysize<cand2.bodysize &&                        // 第二根烛条不是十字星,第一根烛条实体比第二根烛条实体更大
         cand1.close<cand2.open && cand1.open>=cand2.close)                               // 第二根烛条实体位于第一根烛条实体内
        {
         m_harami_bull_total++;
         GetCategory(symbol,i-4,harami_bull_coef);
        }

      //--- Harami, 空头
      if(cand1.trend==UPPER && !cand1.bull && cand2.bull &&                               // 检查趋势方向和烛条方向
         (cand2.type==CAND_LONG || cand2.type==CAND_MARIBOZU) &&                          // 检查 "长烛条" 的第一根烛条
         cand1.type!=CAND_DOJI && cand1.bodysize<cand2.bodysize &&                        // 第二根烛条不是十字星,第一根烛条实体比第二根烛条实体更大
         cand1.close>cand2.open && cand1.open<=cand2.close)                               // 第二根烛条实体位于第一根烛条实体内
        {
         m_harami_bear_total++;
         GetCategory(symbol,i-4,harami_bear_coef);
        }

      //--- 十字星,多头
      if(cand1.trend==DOWN && !cand2.bull && // 检查趋势方向和烛条方向
         (cand2.type==CAND_LONG || cand2.type==CAND_MARIBOZU) && cand1.type==CAND_DOJI && // 检查第一个 "长" 烛条和第二个十字星
         cand1.close<=cand2.open)                                                         // 十字星的开盘价低于或等于第一根烛条的收盘价 
        {
         m_doji_star_bull_total++;
         GetCategory(symbol,i-4,doji_star_bull_coef);
        }

      //--- 十字星,空头
      if(cand1.trend==UPPER && cand2.bull && // 检查趋势方向和烛条方向
         (cand2.type==CAND_LONG || cand2.type==CAND_MARIBOZU) && cand1.type==CAND_DOJI && // 检查第一个 "长" 烛条和第二个十字星
         cand1.open>=cand2.close)                                                         //十字星的开盘价高于或等于第一根烛条的收盘价
        {
         m_doji_star_bear_total++;
         GetCategory(symbol,i-4,doji_star_bear_coef);
        }

      //--- 穿孔,多头模型
      if(cand1.trend==DOWN && cand1.bull && !cand2.bull && // 检查趋势方向和烛条方向
         (cand1.type==CAND_LONG || cand1.type==CAND_MARIBOZU) && (cand2.type==CAND_LONG || cand2.type==CAND_MARIBOZU) && // 检查 "长" 烛条
         cand1.close>(cand2.close+cand2.open)/2 && // 第二根烛条收盘价高于第一根烛条的中部
         cand2.open>cand1.close && cand2.close>=cand1.open)
        {
         m_piercing_line_total++;
         GetCategory(symbol,i-4,piercing_line_coef);
        }

      //--- 乌云盖顶,空头
      if(cand1.trend==UPPER && !cand1.bull && cand2.bull && // 检查趋势方向和烛条方向
         (cand1.type==CAND_LONG || cand1.type==CAND_MARIBOZU) && (cand2.type==CAND_LONG || cand2.type==CAND_MARIBOZU) && // 检查 "长" 烛条
         cand1.close<(cand2.close+cand2.open)/2 && // 第二根烛条收盘价低于第一根烛条的中部
         cand1.close<cand2.open && cand2.close<=cand1.open)
        {
         m_dark_cloud_cover_total++;
         GetCategory(symbol,i-4,dark_cloud_cover_coef);
        }
     }

3. 从上面的代码当中可以看出,在判定指定形态之一时,使用 GetCategory() 方法检查历史记录。 顾名思义,信号出现检查之后的价格方向。 也就是说,价格走势类别可由每个发现的形态来判定,如图例 1 所述。

//+------------------------------------------------------------------+
//| 判定盈利类别                                                       |
//+------------------------------------------------------------------+
bool CProgram::GetCategory(const string symbol,const int shift,int &category[])
  {
   MqlRates rt[];
   int copied=CopyRates(symbol,m_timeframe,shift,4,rt);
   int rating=0;
//--- 获取前一根烛条的详细信息
   if(copied<4)
      return(false);
   double high1,high2,high3,low1,low2,low3,close0,point;
   close0=rt[0].close;
   high1=rt[1].high;
   high2=rt[2].high;
   high3=rt[3].high;
   low1=rt[1].low;
   low2=rt[2].low;
   low3=rt[3].low;
   if(!SymbolInfoDouble(symbol,SYMBOL_POINT,point))
      return(false);

//--- 检查它是否为上行趋势
   if((int)((high1-close0)/point)>=m_threshold_value)
     {
      category[0]++;
     }
   else if((int)((high2-close0)/point)>=m_threshold_value)
     {
      category[1]++;
     }
   else if((int)((high3-close0)/point)>=m_threshold_value)
     {
      category[2]++;
     }

//--- 检查它是否为下行趋势

   if((int)((close0-low1)/point)>=m_threshold_value)
     {
      category[3]++;
     }
   else if((int)((close0-low2)/point)>=m_threshold_value)
     {
      category[4]++;
     }
   else if((int)((close0-low3)/point)>=m_threshold_value)
     {
      category[5]++;
     }
   return(true);
  }

4. 在判定类别并计算“形态检测后价格移动的次数和方向”之后,计算其他参数,例如发生、上行趋势和下行趋势概率,以及该形态的 上、下行趋势效率评估系数。 该计算由 CoefCalculation() 方法执行。

//+------------------------------------------------------------------+
//| 计算效率评估系数                                                    |
//+------------------------------------------------------------------+
bool CProgram::CoefCalculation(const int row,int &category[],int found)
  {
   double p1,p2,k1,k2;
   int sum1=0,sum2=0;
   for(int i=0;i<3;i++)
     {
      sum1+=category[i];
      sum2+=category[i+3];
     }
//---
   p1=(found>0)?NormalizeDouble((double)sum1/found*100,2):0;
   p2=(found>0)?NormalizeDouble((double)sum2/found*100,2):0;
   k1=(found>0)?NormalizeDouble((m_k1*category[0]+m_k2*category[1]+m_k3*category[2])/found,3):0;
   k2=(found>0)?NormalizeDouble((m_k1*category[3]+m_k2*category[4]+m_k3*category[5])/found,3):0;

   m_table.SetValue(3,row,(string)p1,2);
   m_table.SetValue(4,row,(string)p2,2);
   m_table.SetValue(5,row,(string)k1,2);
   m_table.SetValue(6,row,(string)k2,2);
//--- 更新表格
   m_table.Update(true);
   m_table.GetScrollVPointer().Update(true);
   m_table.GetScrollHPointer().Update(true);
   return(true);
  }

依据这些计算,我们可以评估形态是否与预期的走势特征相对应。


研究结果

为了分析烛条形态,我们利用 MetaTrader 5 终端中 forex.major 类别的一套品种。 为了避免逐一输入,添加了一个特殊的单词以便提供整个列表。 当您键入单词 Major 时,将显示如图例 7 所示的所需列表。


图例 7 快速选择主要品种。

我们不会针对烛条形态执行任何其他设置。 唯一可编辑的参数是以点为单位的趋势阈值。 应调整不同时间帧内的利润目标,因为在较小的时间帧内设定的目标过大会导致零成功结果,而在较高时间帧上设定的目标太小会导致相反的结果。 

为了测试上述假设,我们选择两个时间帧并更改阈值。 这将令会我们看到参数的效果。 我决定考察一组较小的测试样本,因为若我们在所提议的 21 个时间帧上考察每个货币对,并更改参数,那么将会有很多令人困惑的信息。 您可以选择所需的货币对,时间帧和历史记录范围,以便自行测试各种阈值。

此处是第一组非默认参数:

所有七对的测试结果如图例 8 所示。



图例 8 时间帧 M15 分析结果。

我们仔细查看 EURUSD,并使用它的示例来检查烛条形态是否与给定条件相关。 上图中的形态以特定颜色高亮显示,指示其走势特征。 红色用于示意可能下行趋势的形态,而绿色用于示意上行趋势的形态。 我们看看颜色是否符合结果。


图例 9 EURUSD 分析结果。

正在分析的第一个形态是锤头。 根据形态特征,它预测上行走势。 在我们的测试中,有 30% 的案例中观察到上行走势,有 10% 的案例中发生下行走势。 注意,这是指定阈值不小于 100 点的走势。 考虑到在历史样本中,该形态之后有超过三分之一的情况会是上行走势,我们可以推断出它确认了这个烛条形态示意上行趋势的假设。

然而,此观察结果不能自动应用于所有其他时间帧和样本。 这是针对特定案例和结果。

现在我们研究一下吞噬空头形态。 该形态被认为是一个下行趋势,所以在它之后你应该执行一笔做空交易。 然而,结果表明,在大多数情况下,这种烛条形态的行为完全不同:在 20% 的情况下,形态出现后,价格上涨了至少 100 点,而下行走势的占比只是所有案例的 9%,少了两倍以上。 因此,测试表明该形态的行为颠倒。

第三个分析的形态是多头 Harami。 正如名称和绿色标签所暗示的那样,这种形态是买入信号。 然而,下行和上行的情况几乎相等:17% 和 19%。 我们能说这种形态透露出确定信号吗? 我表示怀疑,因为任何一侧都没有明显的普遍性。 因此,测试结果表明您最好在 15 分钟的时间帧内避免使用此形态来交易 EURUSD。


发现

根据获得的结果,可以进行以下观察:很难清晰地解释烛条形态。 结果很大程度上取决于它们出现的条件。 因此,贯穿整个市场, 形态不仅难以表现相同,而且甚至同一货币对在不同时间帧的行为也不尽相同。 您应该始终重新验证形态信号。


结束语

附加的存档包含所有列出的文件,这些文件位于相应的文件夹中。 为了正常操作它们,您只需将 MQL5 文件夹保存到终端文件夹中。

本文中用到的程序

#
 名称
类型
注解
1
PatternAnalyzer.mq5 图形界面
 用于分析烛条形态的工具栏
2 MainWindow.mqh 代码库  GUI 函数库
3 Program.mqh 代码库  用于创建界面和计算元素的函数库