English Русский Español Deutsch 日本語 Português
preview
DoEasy.服务功能(第 2 部分):孕线形态

DoEasy.服务功能(第 2 部分):孕线形态

MetaTrader 5示例 | 11 十一月 2024, 12:17
324 0
Artyom Trishkin
Artyom Trishkin

目录


概念

我们继续开发基于时间序列数据形成的形态。在形态系列的第一篇文章中,我们创建了一个用于搜索和显示各种形态的工具包,并创建了从价格行为形态中搜索 Pin Bar 形态的功能。在本文中,我们将继续开发和完善在价格图表上搜索各种形态的功能,并创建价格行为 "Inside Bar" 形态搜索。

如果 "针形柱"(Pin Bar)形态是一个单柱形态,并通过一个柱形的比例进行搜索,那么 "孕线"(Inside Bar)就是一个由两个柱形组成的双柱形态 - 母柱形(左侧柱形)和界定柱形(右侧柱形):


在寻找这种形态时,仅仅比较一个柱的比例是不够的。在这里,我们需要比较附近的两个柱形。此外,这种形态可以排成一排,然后母柱将是所有相互嵌套的形态的母柱,并且是最左边的一条,而会有许多定义条 - 每个嵌套形态的每个右柱。最右边的柱形将是整个嵌套形态的最后一个定义柱形。为了搜索此类结构,我们将实现一个通用功能,并在形态属性集中增加一个属性 - 母柱的开启时间。根据柱条和定义柱的开启时间差,我们可以确定整个嵌套形态所包含的柱数。这对于在图表上绘制图案标签非常有用。换句话说,除了可以在图表上用一个简单的点来标记每个形态外,我们还可以通过在形态中包含的柱形周围画一个框架来直观地指示形态。因此,我们可以在图表上选择不同的形态显示方法。

此外,今天创建的功能将有助于我们创建其他形态类型。


改进库类

在开始执行下一个形态的代码之前,让我们先完成现成的文件和库类。

在 \MQL5\Include\DoEasy\Defines.mqh 中,将 "位图" 对象类型添加到库对象类型列表中

//+------------------------------------------------------------------+
//| List of library object types                                     |
//+------------------------------------------------------------------+
enum ENUM_OBJECT_DE_TYPE
  {
//--- Graphics
   OBJECT_DE_TYPE_GBASE =  COLLECTION_ID_LIST_END+1,              // "Base object of all library graphical objects" object type
   OBJECT_DE_TYPE_GELEMENT,                                       // "Graphical element" object type
   OBJECT_DE_TYPE_GFORM,                                          // Form object type
   OBJECT_DE_TYPE_GFORM_CONTROL,                                  // "Form for managing pivot points of graphical object" object type
   OBJECT_DE_TYPE_GSHADOW,                                        // Shadow object type
   OBJECT_DE_TYPE_GGLARE,                                         // Glare object type
   OBJECT_DE_TYPE_GBITMAP,                                        // Bitmap object type
   //--- WinForms
   OBJECT_DE_TYPE_GWF_BASE,                                       // WinForms Base object type (base abstract WinForms object)
   OBJECT_DE_TYPE_GWF_CONTAINER,                                  // WinForms container object type
   OBJECT_DE_TYPE_GWF_COMMON,                                     // WinForms standard control object type
   OBJECT_DE_TYPE_GWF_HELPER,                                     // WinForms auxiliary control object type
//--- Animation
//--- ...
//---...
 

OBJ_BITMAP 类型的对象可以附加一个bmp 资源,并在其上绘制各种基本元素。这种对象与柱的时间和价格挂钩。我们将用它们来勾勒出带有框架的形态柱。

除了形态对象会存储形成形态的柱形的时间外,我们还将在库的柱形对象中添加在其上发现的形态类型。由于形态类型是位标志,一个变量中可以存储多种不同类型的形态。然后,从这个变量的值中,我们可以随时提取出柱形上所有形态的类型和名称。

当从用户程序中搜索要处理的形态时,这样做非常方便:我们获取一个柱形对象,检查在其上找到的形态类型,然后处理那些标记被写入变量的模式。

在柱形对象的整数属性中再添加一个属性,将柱形对象的整数属性从 13 个增加到 14 个

//+------------------------------------------------------------------+
//| Bar integer properties                                           |
//+------------------------------------------------------------------+
enum ENUM_BAR_PROP_INTEGER
  {
   BAR_PROP_TIME = 0,                                       // Bar period start time
   BAR_PROP_TYPE,                                           // Bar type (from the ENUM_BAR_BODY_TYPE enumeration)
   BAR_PROP_PERIOD,                                         // Bar period (timeframe)
   BAR_PROP_SPREAD,                                         // Bar spread
   BAR_PROP_VOLUME_TICK,                                    // Bar tick volume
   BAR_PROP_VOLUME_REAL,                                    // Bar exchange volume
   BAR_PROP_TIME_DAY_OF_YEAR,                               // Bar day serial number in a year
   BAR_PROP_TIME_YEAR,                                      // A year the bar belongs to
   BAR_PROP_TIME_MONTH,                                     // A month the bar belongs to
   BAR_PROP_TIME_DAY_OF_WEEK,                               // Bar week day
   BAR_PROP_TIME_DAY,                                       // Bar day of month (number)
   BAR_PROP_TIME_HOUR,                                      // Bar hour
   BAR_PROP_TIME_MINUTE,                                    // Bar minute
   BAR_PROP_PATTERNS_TYPE,                                  // Pattern types on the bar (pattern flags from the ENUM_PATTERN_TYPE enumeration)
  }; 
#define BAR_PROP_INTEGER_TOTAL (14)                         // Total number of integer bar properties

在使用时间序列列表搜索形态并在柱形上找到形态时,我们会将找到的形态类型添加到柱形对象中的这个变量中。根据搜索不同类型形态的结果,可以在一个柱形中记录所发现的不同类型形态的标志。

在可能的柱形对象排序条件列表中添加按柱形上的形态类型排序:

//+------------------------------------------------------------------+
//| Possible bar sorting criteria                                    |
//+------------------------------------------------------------------+
#define FIRST_BAR_DBL_PROP          (BAR_PROP_INTEGER_TOTAL-BAR_PROP_INTEGER_SKIP)
#define FIRST_BAR_STR_PROP          (BAR_PROP_INTEGER_TOTAL-BAR_PROP_INTEGER_SKIP+BAR_PROP_DOUBLE_TOTAL-BAR_PROP_DOUBLE_SKIP)
enum ENUM_SORT_BAR_MODE
  {
//--- Sort by integer properties
   SORT_BY_BAR_TIME = 0,                                    // Sort by bar period start time
   SORT_BY_BAR_TYPE,                                        // Sort by bar type (from the ENUM_BAR_BODY_TYPE enumeration)
   SORT_BY_BAR_PERIOD,                                      // Sort by bar period (timeframe)
   SORT_BY_BAR_SPREAD,                                      // Sort by bar spread
   SORT_BY_BAR_VOLUME_TICK,                                 // Sort by bar tick volume
   SORT_BY_BAR_VOLUME_REAL,                                 // Sort by bar exchange volume
   SORT_BY_BAR_TIME_DAY_OF_YEAR,                            // Sort by bar day number in a year
   SORT_BY_BAR_TIME_YEAR,                                   // Sort by a year the bar belongs to
   SORT_BY_BAR_TIME_MONTH,                                  // Sort by a month the bar belongs to
   SORT_BY_BAR_TIME_DAY_OF_WEEK,                            // Sort by a bar week day
   SORT_BY_BAR_TIME_DAY,                                    // Sort by a bar day
   SORT_BY_BAR_TIME_HOUR,                                   // Sort by a bar hour
   SORT_BY_BAR_TIME_MINUTE,                                 // Sort by a bar minute
   SORT_BY_BAR_PATTERN_TYPE,                                // Sort by pattern types on the bar (pattern flags from the ENUM_PATTERN_TYPE enumeration)
//--- Sort by real properties
   SORT_BY_BAR_OPEN = FIRST_BAR_DBL_PROP,                   // Sort by bar open price
   SORT_BY_BAR_HIGH,                                        // Sort by the highest price for the bar period
   SORT_BY_BAR_LOW,                                         // Sort by the lowest price for the bar period
   SORT_BY_BAR_CLOSE,                                       // Sort by a bar close price
   SORT_BY_BAR_CANDLE_SIZE,                                 // Sort by a candle price
   SORT_BY_BAR_CANDLE_SIZE_BODY,                            // Sort by a candle body size
   SORT_BY_BAR_CANDLE_BODY_TOP,                             // Sort by a candle body top
   SORT_BY_BAR_CANDLE_BODY_BOTTOM,                          // Sort by a candle body bottom
   SORT_BY_BAR_CANDLE_SIZE_SHADOW_UP,                       // Sort by candle upper wick size
   SORT_BY_BAR_CANDLE_SIZE_SHADOW_DOWN,                     // Sort by candle lower wick size
//--- Sort by string properties
   SORT_BY_BAR_SYMBOL = FIRST_BAR_STR_PROP,                 // Sort by a bar symbol
  };


以前,在形态类型列表中为 Harami 形态指定的值为 0。这并不完全正确。如果 0 表示柱形上没有形态则更好。
让我们来解决这个问题,并添加一个宏替换,显示库中可供搜索的形态总数

//+------------------------------------------------------------------+
//| Pattern type                                                     |
//+------------------------------------------------------------------+
enum ENUM_PATTERN_TYPE
  {
//--- Candle formations
   PATTERN_TYPE_NONE                =  0x0,                 // None
   PATTERN_TYPE_HARAMI              =  0x1,                 // Harami
   PATTERN_TYPE_HARAMI_CROSS        =  0x2,                 // Harami Cross
   PATTERN_TYPE_TWEEZER             =  0x4,                 // Tweezer
   PATTERN_TYPE_PIERCING_LINE       =  0x8,                 // Piercing Line
   PATTERN_TYPE_DARK_CLOUD_COVER    =  0x10,                // Dark Cloud Cover
   PATTERN_TYPE_THREE_WHITE_SOLDIERS=  0x20,                // Three White Soldiers
   PATTERN_TYPE_THREE_BLACK_CROWS   =  0x40,                // Three Black Crows
   PATTERN_TYPE_SHOOTING_STAR       =  0x80,                // Shooting Star
   PATTERN_TYPE_HAMMER              =  0x100,               // Hammer
   PATTERN_TYPE_INVERTED_HAMMER     =  0x200,               // Inverted Hammer
   PATTERN_TYPE_HANGING_MAN         =  0x400,               // Hanging Man
   PATTERN_TYPE_DOJI                =  0x800,               // Doji
   PATTERN_TYPE_DRAGONFLY_DOJI      =  0x1000,              // Dragonfly Doji
   PATTERN_TYPE_GRAVESTONE_DOJI     =  0x2000,              // Gravestone Doji
   PATTERN_TYPE_MORNING_STAR        =  0x4000,              // Morning Star
   PATTERN_TYPE_MORNING_DOJI_STAR   =  0x8000,              // Morning Doji Star
   PATTERN_TYPE_EVENING_STAR        =  0x10000,             // Evening Star
   PATTERN_TYPE_EVENING_DOJI_STAR   =  0x20000,             // Evening Doji Star
   PATTERN_TYPE_THREE_STARS         =  0x40000,             // Three Stars
   PATTERN_TYPE_ABANDONED_BABY      =  0x80000,             // Abandoned Baby
//--- Price Action
   PATTERN_TYPE_PIVOT_POINT_REVERSAL=  0x100000,            // Price Action Reversal Pattern
   PATTERN_TYPE_OUTSIDE_BAR         =  0x200000,            // Price Action Outside Bar
   PATTERN_TYPE_INSIDE_BAR          =  0x400000,            // Price Action Inside Bar
   PATTERN_TYPE_PIN_BAR             =  0x800000,            // Price Action Pin Bar
   PATTERN_TYPE_RAILS               =  0x1000000,           // Price Action Rails
  };
#define PATTERNS_TOTAL              (26)                    // Total number of patterns (including the missing one)


在形态的整数属性列表中添加一个新属性,存储母柱的时间,并将形态整数属性的数量从 9 个增加到 10 个

//+------------------------------------------------------------------+
//| Pattern integer properties                                       |
//+------------------------------------------------------------------+
enum ENUM_PATTERN_PROP_INTEGER
  {
   PATTERN_PROP_CODE = 0,                                   // Unique pattern code (time + type + status + direction + timeframe + symbol)
   PATTERN_PROP_CTRL_OBJ_ID,                                // Pattern control object ID
   PATTERN_PROP_ID,                                         // Pattern ID
   PATTERN_PROP_TIME,                                       // Pattern defining bar time
   PATTERN_PROP_MOTHERBAR_TIME,                             // Pattern mother bar time
   PATTERN_PROP_STATUS,                                     // Pattern status (from the ENUM_PATTERN_STATUS enumeration)
   PATTERN_PROP_TYPE,                                       // Pattern type (from the ENUM_PATTERN_TYPE enumeration)
   PATTERN_PROP_DIRECTION,                                  // Pattern type by direction (from the ENUM_PATTERN_TYPE_DIRECTION enumeration)
   PATTERN_PROP_PERIOD,                                     // Pattern period (timeframe)
   PATTERN_PROP_CANDLES,                                    // Number of candles that make up the pattern
  }; 
#define PATTERN_PROP_INTEGER_TOTAL (10)                     // Total number of integer pattern properties


在可能的形态排序条件列表中添加新属性排序

//+------------------------------------------------------------------+
//| Possible pattern sorting criteria                                |
//+------------------------------------------------------------------+
#define FIRST_PATTERN_DBL_PROP      (PATTERN_PROP_INTEGER_TOTAL-PATTERN_PROP_INTEGER_SKIP)
#define FIRST_PATTERN_STR_PROP      (PATTERN_PROP_INTEGER_TOTAL-PATTERN_PROP_INTEGER_SKIP+PATTERN_PROP_DOUBLE_TOTAL-PATTERN_PROP_DOUBLE_SKIP)
enum ENUM_SORT_PATTERN_MODE
  {
//--- Sort by integer properties
   SORT_BY_PATTERN_CODE = 0,                                // Sort by unique pattern code (time + type + status + direction + timeframe)
   SORT_BY_PATTERN_CTRL_OBJ_ID,                             // Sort by pattern control object ID
   SORT_BY_PATTERN_ID,                                      // Sort by pattern ID
   SORT_BY_PATTERN_TIME,                                    // Sort by pattern defining bar time
   SORT_BY_PATTERN_MOTHERBAR_TIME,                          // Sort by pattern mother bar time
   SORT_BY_PATTERN_STATUS,                                  // Sort by pattern status (from the ENUM_PATTERN_STATUS enumeration)
   SORT_BY_PATTERN_TYPE,                                    // Sort by pattern type (from the ENUM_PATTERN_TYPE enumeration)
   SORT_BY_PATTERN_DIRECTION,                               // Sort by pattern type based on direction (from the ENUM_PATTERN_TYPE_DIRECTION enumeration)
   SORT_BY_PATTERN_PERIOD,                                  // Sort by pattern period (timeframe)
   SORT_BY_PATTERN_CANDLES,                                 // Sort by the number of candles that make up the pattern
   
//--- Sort by real properties
   SORT_BY_PATTERN_BAR_PRICE_OPEN = FIRST_PATTERN_DBL_PROP, // Sort by pattern defining bar Open price
   SORT_BY_PATTERN_BAR_PRICE_HIGH,                          // Sort by pattern defining bar High price
   SORT_BY_PATTERN_BAR_PRICE_LOW,                           // Sort by pattern defining bar Low price
   SORT_BY_PATTERN_BAR_PRICE_CLOSE,                         // Sort by pattern defining bar Close price
   SORT_BY_PATTERN_RATIO_BODY_TO_CANDLE_SIZE,               // Sort by percentage ratio of the candle body to the full size of the candle
   SORT_BY_PATTERN_RATIO_UPPER_SHADOW_TO_CANDLE_SIZE,       // Sort by percentage ratio of the upper shadow size to the candle size
   SORT_BY_PATTERN_RATIO_LOWER_SHADOW_TO_CANDLE_SIZE,       // Sort by percentage ratio of the lower shadow size to the candle size
   SORT_BY_PATTERN_RATIO_BODY_TO_CANDLE_SIZE_CRITERION,           // Sort by defined criterion of the ratio of the candle body to the full candle size in %
   SORT_BY_PATTERN_RATIO_LARGER_SHADOW_TO_CANDLE_SIZE_CRITERION,  // Sort by  defined criterion of the ratio of the maximum shadow to the candle size in %
   SORT_BY_PATTERN_RATIO_SMALLER_SHADOW_TO_CANDLE_SIZE_CRITERION, // Sort by  defined criterion of the ratio of the minimum shadow to the candle size in %
   
//--- Sort by string properties
   SORT_BY_PATTERN_SYMBOL = FIRST_BAR_STR_PROP,             // Sort by a pattern symbol
   SORT_BY_PATTERN_NAME,                                    // Sort by pattern name
  };


在图形元素类型列表中添加新类型(位图对象)

//+------------------------------------------------------------------+
//| The list of graphical element types                              |
//+------------------------------------------------------------------+
enum ENUM_GRAPH_ELEMENT_TYPE
  {
   GRAPH_ELEMENT_TYPE_STANDARD,                       // Standard graphical object
   GRAPH_ELEMENT_TYPE_STANDARD_EXTENDED,              // Extended standard graphical object
   GRAPH_ELEMENT_TYPE_SHADOW_OBJ,                     // Shadow object
   GRAPH_ELEMENT_TYPE_ELEMENT,                        // Element
   GRAPH_ELEMENT_TYPE_BITMAP,                         // Bitmap
   GRAPH_ELEMENT_TYPE_FORM,                           // Form
   GRAPH_ELEMENT_TYPE_WINDOW,                         // Window
   //--- WinForms
   GRAPH_ELEMENT_TYPE_WF_UNDERLAY,                    // Panel object underlay
   GRAPH_ELEMENT_TYPE_WF_BASE,                        // Windows Forms Base
   //--- 'Container' object types are to be set below
   GRAPH_ELEMENT_TYPE_WF_CONTAINER,                   // Windows Forms container base object
   GRAPH_ELEMENT_TYPE_WF_PANEL,                       // Windows Forms Panel
   GRAPH_ELEMENT_TYPE_WF_GROUPBOX,                    // Windows Forms GroupBox
   GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL,                 // Windows Forms TabControl
   GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER,             // Windows Forms SplitContainer
   //--- 'Standard control' object types are to be set below
   GRAPH_ELEMENT_TYPE_WF_COMMON_BASE,                 // Windows Forms base standard control
   GRAPH_ELEMENT_TYPE_WF_LABEL,                       // Windows Forms Label
   GRAPH_ELEMENT_TYPE_WF_BUTTON,                      // Windows Forms Button
   GRAPH_ELEMENT_TYPE_WF_CHECKBOX,                    // Windows Forms CheckBox
   GRAPH_ELEMENT_TYPE_WF_RADIOBUTTON,                 // Windows Forms RadioButton
   GRAPH_ELEMENT_TYPE_WF_ELEMENTS_LIST_BOX,           // Base list object of Windows Forms elements
   GRAPH_ELEMENT_TYPE_WF_LIST_BOX,                    // Windows Forms ListBox
   GRAPH_ELEMENT_TYPE_WF_CHECKED_LIST_BOX,            // Windows Forms CheckedListBox
   GRAPH_ELEMENT_TYPE_WF_BUTTON_LIST_BOX,             // Windows Forms ButtonListBox
   GRAPH_ELEMENT_TYPE_WF_TOOLTIP,                     // Windows Forms ToolTip
   GRAPH_ELEMENT_TYPE_WF_PROGRESS_BAR,                // Windows Forms ProgressBar
   //--- Auxiliary elements of WinForms objects
   GRAPH_ELEMENT_TYPE_WF_LIST_BOX_ITEM,               // Windows Forms ListBoxItem
   GRAPH_ELEMENT_TYPE_WF_TAB_HEADER,                  // Windows Forms TabHeader
   GRAPH_ELEMENT_TYPE_WF_TAB_FIELD,                   // Windows Forms TabField
   GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER_PANEL,       // Windows Forms SplitContainerPanel
   GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON,                // Windows Forms ArrowButton
   GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_UP,             // Windows Forms UpArrowButton
   GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_DOWN,           // Windows Forms DownArrowButton
   GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_LEFT,           // Windows Forms LeftArrowButton
   GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_RIGHT,          // Windows Forms RightArrowButton
   GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTONS_UD_BOX,        // Windows Forms UpDownArrowButtonsBox
   GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTONS_LR_BOX,        // Windows Forms LeftRightArrowButtonsBox
   GRAPH_ELEMENT_TYPE_WF_SPLITTER,                    // Windows Forms Splitter
   GRAPH_ELEMENT_TYPE_WF_HINT_BASE,                   // Windows Forms HintBase
   GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_LEFT,              // Windows Forms HintMoveLeft
   GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_RIGHT,             // Windows Forms HintMoveRight
   GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_UP,                // Windows Forms HintMoveUp
   GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_DOWN,              // Windows Forms HintMoveDown
   GRAPH_ELEMENT_TYPE_WF_BAR_PROGRESS_BAR,            // Windows Forms BarProgressBar
   GRAPH_ELEMENT_TYPE_WF_GLARE_OBJ,                   // Glare object
   GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_THUMB,            // Windows Forms ScrollBarThumb
   GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR,                  // Windows Forms ScrollBar
   GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL,       // Windows Forms ScrollBarHorisontal
   GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL,         // Windows Forms ScrollBarVertical
  };

这是一种与价格/时间坐标绑定的新型图库图形对象,允许您以与图库图形用户界面元素相同的方式在其上绘图。因此,它被列入了这个列表。除了在价格图表上勾画形态柱形外,我们可能还会将其用于满足库的其他需求。


在 \MQL5\Include\DoEasy\Data.mqh 库文件中 ,添加新库消息的索引

//+------------------------------------------------------------------+
//| List of the library's text message indices                       |
//+------------------------------------------------------------------+
enum ENUM_MESSAGES_LIB
  {
   MSG_LIB_PARAMS_LIST_BEG=ERR_USER_ERROR_FIRST,      // Beginning of the parameter list
   MSG_LIB_PARAMS_LIST_END,                           // End of the parameter list
   MSG_LIB_PROP_NOT_SUPPORTED,                        // Property not supported
   MSG_LIB_PROP_NOT_SUPPORTED_MQL4,                   // Property not supported in MQL4
   MSG_LIB_PROP_NOT_SUPPORTED_MT5_LESS_2155,          // Property not supported in MetaTrader 5 versions lower than 2155
   MSG_LIB_PROP_NOT_SUPPORTED_MT5_LESS_3245,          // Property not supported in MetaTrader 5 versions lower than 3245
   MSG_LIB_PROP_NOT_SUPPORTED_MT5_LESS_3260,          // Property not supported in MetaTrader 5 versions lower than 3260
   MSG_LIB_PROP_NOT_SUPPORTED_POSITION,               // Property not supported for position
   MSG_LIB_PROP_NOT_SUPPORTED_PENDING,                // Property not supported for pending order
   MSG_LIB_PROP_NOT_SUPPORTED_MARKET,                 // Property not supported for market order
   MSG_LIB_PROP_NOT_SUPPORTED_MARKET_HIST,            // Property not supported for historical market order
   MSG_LIB_PROP_NOT_SET,                              // Value not set
   MSG_LIB_PROP_EMPTY,                                // Not set
   MSG_LIB_PROP_NOT_FOUND,                            // Not found
   MSG_LIB_PROP_AUTO,                                 // Generated by the terminal
   MSG_LIB_PROP_AS_IN_ORDER,                          // According to the order expiration mode

...

   MSG_LIB_TEXT_BAR_RATIO_BODY_TO_CANDLE_SIZE,        // Ratio of the candle body to the full size of the candle
   MSG_LIB_TEXT_BAR_RATIO_UPPER_SHADOW_TO_CANDLE_SIZE,// Ratio of the upper shadow size to the candle size
   MSG_LIB_TEXT_BAR_RATIO_LOWER_SHADOW_TO_CANDLE_SIZE,// Ratio of the lower shadow size to the candle size
   MSG_LIB_TEXT_BAR_PATTERNS_TYPE,                    // Types of patterns on the bar
  
//--- CTimeSeries

...

//--- CPattern
   MSG_LIB_TEXT_PATTERN_CODE,                         // Code
   MSG_LIB_TEXT_PATTERN_TIME,                         // Defining bar time
   MSG_LIB_TEXT_PATTERN_MOTHERBAR_TIME,               // "Mother" bar time
   MSG_LIB_TEXT_PATTERN_ID,                           // Pattern ID
   MSG_LIB_TEXT_PATTERN_CTRL_OBJ_ID,                  // Pattern control object ID

...

   MSG_GRAPH_ELEMENT_TYPE_STANDARD_EXTENDED,          // Extended standard graphical object
   MSG_GRAPH_ELEMENT_TYPE_ELEMENT,                    // Element
   MSG_GRAPH_ELEMENT_TYPE_BITMAP,                     // Bitmap
   MSG_GRAPH_ELEMENT_TYPE_SHADOW_OBJ,                 // Shadow object
   MSG_GRAPH_ELEMENT_TYPE_FORM,                       // Form

...

//--- String properties of graphical elements
   MSG_CANV_ELEMENT_PROP_NAME_OBJ,                    // Graphical element object name
   MSG_CANV_ELEMENT_PROP_NAME_RES,                    // Graphical resource name
   MSG_CANV_ELEMENT_PROP_TEXT,                        // Graphical element text
   MSG_CANV_ELEMENT_PROP_DESCRIPTION,                 // Graphical element description
   MSG_CANV_ELEMENT_PROP_TOOLTIP_TITLE,               // Element tooltip title
   MSG_CANV_ELEMENT_PROP_TOOLTIP_TEXT,                // Element tooltip text
   
//--- CGCnvBitmap
   MSG_ERR_FAILED_SET_BITMAP_OBJ_TIME,                // Failed to set the time value to the Bitmap object
   MSG_ERR_FAILED_SET_BITMAP_OBJ_PRICE,               // Failed to set the price value for the Bitmap object 
  };

与新增索引相对应的消息

string messages_library[][TOTAL_LANG]=
  {
   {"Начало списка параметров","The beginning of the parameter list"},
   {"Конец списка параметров","End of parameter list"},
   {"Свойство не поддерживается","Property not supported"},
   {"Свойство не поддерживается в MQL4","Property not supported in MQL4"},
   {"Свойство не поддерживается в MetaTrader5 версии ниже 2155","The property is not supported in MetaTrader5, build lower than 2155"},
   {"Свойство не поддерживается в MetaTrader5 версии ниже 3245","The property is not supported in MetaTrader5, build lower than 3245"},
   {"Свойство не поддерживается в MetaTrader5 версии ниже 3260","The property is not supported in MetaTrader5, build lower than 3260"},
   {"Свойство не поддерживается у позиции","Property not supported for position"},
   {"Свойство не поддерживается у отложенного ордера","The property is not supported for a pending order"},
   {"Свойство не поддерживается у маркет-ордера","The property is not supported for a market-order"},
   {"Свойство не поддерживается у исторического маркет-ордера","The property is not supported for a history market-order"},
   {"Значение не задано","Value not set"},
   {"Отсутствует","Not set"},
   {"Не найдено","Not found"},
   {"Формируется терминалом","Formed by the terminal"},
   {"В соответствии с режимом истечения ордера","In accordance with the order expiration mode"},

...

   {"Отношение тела свечи к полному размеру свечи","Ratio of candle body to full candle size"},
   {"Отношение размера верхней тени к размеру свечи","Ratio of the upper shadow size to the candle size"},
   {"Отношение размера нижней тени к размеру свечи","Ratio of the lower shadow size to the candle size"},
   {"Типы паттернов на баре","Types of patterns on the bar"},
   
//--- CTimeSeries

...

//--- CPattern
   {"Код","Code"},
   {"Время определяющего бара","Time of the defining bar"},
   {"Время \"материнского\" бара","Time open of the mother bar"},
   {"Идентификатор паттерна","Pattern ID"},
   {"Идентификатор объекта управления паттерном","Pattern Control object ID"},

...

   {"Расширенный стандартный графический объект","Extended standard graphic object"},
   {"Элемент","Element"},
   {"Рисунок","Bitmap"},
   {"Объект тени","Shadow object"},
   {"Форма","Form"},

...

//--- String properties of graphical elements
   {"Имя объекта-графического элемента","The name of the graphic element object"},
   {"Имя графического ресурса","Image resource name"},
   {"Текст графического элемента","Text of the graphic element"},
   {"Описание графического элемента","Description of the graphic element"},
   {"Заголовок подсказки элемента","Element tooltip header"},
   {"Текст подсказки элемента","Element tooltip title"},
   
//--- CGCnvBitmap
   {"Не удалось установить значение времени Bitmap-объекту","Failed to set time value to Bitmap object"},
   {"Не удалось установить значение цены Bitmap-объекту","Failed to set price value to Bitmap object"},
  };


通常需要检查传递给函数和方法的交易品种和图表周期值的有效性。为避免代码重复,请在 \MQL5\Include\DoEasy\Services\DELib.mqh中执行返回正确交易品种名称和图表周期的函数:

//+------------------------------------------------------------------+
//| Service functions                                                |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Correct and return a symbol name                                 |
//+------------------------------------------------------------------+
string CorrectSymbol(const string symbol) 
  {
   return(symbol==NULL || symbol=="" ? ::Symbol() : symbol);
  }
//+------------------------------------------------------------------+
//| Correct and return a timeframe name                              |
//+------------------------------------------------------------------+
ENUM_TIMEFRAMES CorrectTimeframe(const ENUM_TIMEFRAMES timeframe)
  {
   return(timeframe==PERIOD_CURRENT ? ::Period() : timeframe);
  }

如果传递的图表周期为NULL值、空字符串、0 或PERIOD_CURRENT,函数将返回当前交易品种或时间框架。在其他任何情况下,它们都会返回传递给函数的值。因此,我们将逐步用这些函数替换库中所有需要对传递给方法的值的有效性进行类似检查的代码。

我们还将在此添加返回形态说明的函数:

//+------------------------------------------------------------------+
//| Return pattern type description                                  |
//+------------------------------------------------------------------+
string PatternTypeDescription(const ENUM_PATTERN_TYPE type)
  {
   switch(type)
     {
      case PATTERN_TYPE_HARAMI               :  return CMessage::Text(MSG_LIB_TEXT_PATTERN_TYPE_HARAMI);
      case PATTERN_TYPE_HARAMI_CROSS         :  return CMessage::Text(MSG_LIB_TEXT_PATTERN_TYPE_HARAMI_CROSS);
      case PATTERN_TYPE_TWEEZER              :  return CMessage::Text(MSG_LIB_TEXT_PATTERN_TYPE_TWEEZER);
      case PATTERN_TYPE_PIERCING_LINE        :  return CMessage::Text(MSG_LIB_TEXT_PATTERN_TYPE_PIERCING_LINE);
      case PATTERN_TYPE_DARK_CLOUD_COVER     :  return CMessage::Text(MSG_LIB_TEXT_PATTERN_TYPE_DARK_CLOUD_COVER);
      case PATTERN_TYPE_THREE_WHITE_SOLDIERS :  return CMessage::Text(MSG_LIB_TEXT_PATTERN_TYPE_THREE_WHITE_SOLDIERS);
      case PATTERN_TYPE_THREE_BLACK_CROWS    :  return CMessage::Text(MSG_LIB_TEXT_PATTERN_TYPE_THREE_BLACK_CROWS);
      case PATTERN_TYPE_SHOOTING_STAR        :  return CMessage::Text(MSG_LIB_TEXT_PATTERN_TYPE_SHOOTING_STAR);
      case PATTERN_TYPE_HAMMER               :  return CMessage::Text(MSG_LIB_TEXT_PATTERN_TYPE_HAMMER);
      case PATTERN_TYPE_INVERTED_HAMMER      :  return CMessage::Text(MSG_LIB_TEXT_PATTERN_TYPE_INVERTED_HAMMER);
      case PATTERN_TYPE_HANGING_MAN          :  return CMessage::Text(MSG_LIB_TEXT_PATTERN_TYPE_HANGING_MAN);
      case PATTERN_TYPE_DOJI                 :  return CMessage::Text(MSG_LIB_TEXT_PATTERN_TYPE_DOJI);
      case PATTERN_TYPE_DRAGONFLY_DOJI       :  return CMessage::Text(MSG_LIB_TEXT_PATTERN_TYPE_DRAGONFLY_DOJI);
      case PATTERN_TYPE_GRAVESTONE_DOJI      :  return CMessage::Text(MSG_LIB_TEXT_PATTERN_TYPE_GRAVESTONE_DOJI);
      case PATTERN_TYPE_MORNING_STAR         :  return CMessage::Text(MSG_LIB_TEXT_PATTERN_TYPE_MORNING_STAR);
      case PATTERN_TYPE_MORNING_DOJI_STAR    :  return CMessage::Text(MSG_LIB_TEXT_PATTERN_TYPE_MORNING_DOJI_STAR);
      case PATTERN_TYPE_EVENING_STAR         :  return CMessage::Text(MSG_LIB_TEXT_PATTERN_TYPE_EVENING_STAR);
      case PATTERN_TYPE_EVENING_DOJI_STAR    :  return CMessage::Text(MSG_LIB_TEXT_PATTERN_TYPE_EVENING_DOJI_STAR);
      case PATTERN_TYPE_THREE_STARS          :  return CMessage::Text(MSG_LIB_TEXT_PATTERN_TYPE_THREE_STARS);
      case PATTERN_TYPE_ABANDONED_BABY       :  return CMessage::Text(MSG_LIB_TEXT_PATTERN_TYPE_ABANDONED_BABY);
      case PATTERN_TYPE_PIVOT_POINT_REVERSAL :  return CMessage::Text(MSG_LIB_TEXT_PATTERN_TYPE_PIVOT_POINT_REVERSAL);
      case PATTERN_TYPE_OUTSIDE_BAR          :  return CMessage::Text(MSG_LIB_TEXT_PATTERN_TYPE_OUTSIDE_BAR);
      case PATTERN_TYPE_INSIDE_BAR           :  return CMessage::Text(MSG_LIB_TEXT_PATTERN_TYPE_INSIDE_BAR);
      case PATTERN_TYPE_PIN_BAR              :  return CMessage::Text(MSG_LIB_TEXT_PATTERN_TYPE_PIN_BAR);
      case PATTERN_TYPE_RAILS                :  return CMessage::Text(MSG_LIB_TEXT_PATTERN_TYPE_RAILS);
      default                                :  return CMessage::Text(MSG_LIB_TEXT_FRAME_STYLE_NONE);
     }
  }

根据传递给函数的形态类型,将返回相应的文本描述。


返回 ulong 变量中形态的数量和列表的函数:

//+------------------------------------------------------------------+
//| Return the number and list of patterns in the ulong variable     |
//+------------------------------------------------------------------+
int ListPatternsInVar(const ulong var,ulong &array[])
  {
   int size=0;
   ulong x=1;
//--- In the loop from 1 to the number of patterns PATTERNS_TOTAL-1
   for(int i=1;i<PATTERNS_TOTAL;i++)
     {
      //--- set the value of the pattern flag to be checked from the ENUM_PATTERN_TYPE enumeration by the loop index
      x=(i>1 ? x*2 : 1);
      ENUM_PATTERN_TYPE type=(ENUM_PATTERN_TYPE)x;
      //--- If the value passed to the function contains the pattern flag with x value,
      bool res=(var & type)==type;
      if(res)
        {
         //--- increase the size of the pattern array
         size++;
         ArrayResize(array,size,PATTERNS_TOTAL-1);
         //--- write the pattern type to the array
         array[size-1]=type;
        }
     }
//--- Return the number of pattern types stored in the variable
   return size;
  }

该函数获取包含形态标志的变量和一个数组,从该变量中提取的形态类型将写入数组。由于每个标志的大小是前一个标志的两倍,因此很容易根据循环索引的值形成循环中的标志值,然后在变量值中查找是否存在这样的标志。如果将该标记写入变量,则形态类型将写入数组,数组先前增加 1,以写入新的形态类型。在按形态类型循环结束时,以标志形式写入变量的所有形态都将被输入数组,然后可在程序中使用。


向日志发送 ulong 变量中形态类型描述的函数:

//+------------------------------------------------------------------------+
//| Send a description of pattern types in a ulong variable to the journal |
//+------------------------------------------------------------------------+
void PatternsInVarDescriptionPrint(const ulong var,const bool dash=false)
  {
   ulong array[];
//--- Get the number of patterns in the value passed to the function
   int total=ListPatternsInVar(var,array);
//--- In the loop by the array of patterns, obtain a description of the next pattern and print it
   for(int i=0;i<total;i++)
      Print((dash ? " - " : ""),PatternTypeDescription((ENUM_PATTERN_TYPE)array[i]));
  }

代码注释中完整描述了方法逻辑。


返回对 ulong 变量中形态类型描述的函数:

//+------------------------------------------------------------------+
//| Return a description of pattern types in a ulong variable        |
//+------------------------------------------------------------------+
string PatternsInVarDescription(const ulong var,const bool dash=false)
  {
   ulong array[];
//--- Get the number of patterns in the value passed to the function
   int total=ListPatternsInVar(var,array);
   string txt="";
//--- In the loop by the array of patterns, obtain a description of the next pattern and add it to the text variable
   for(int i=0;i<total;i++)
      txt+=((dash ? " - " : "")+PatternTypeDescription((ENUM_PATTERN_TYPE)array[i]))+(i<total-1 ? "\n" : "");
//--- Return the obtained text
   return txt;
  }

所有这些函数都可以从程序的任何地方访问,用户可以轻松访问在一个柱形上检测到的形态列表。柱属性中现在有一个变量,用于存储找到的形态的标志。根据该属性的值并使用函数,我们可以随时提取柱形上的所有类型的形态,并在程序中进行处理。这就是我们在测试 EA 中要做的事情。


MQL5\Include\DoEasy\Objects\Graph\GCnvElement.mqh 文件中的图形元素对象类是创建更复杂图形用户界面元素的基础,但该类中的一些变量是派生类无法访问的。让我们把这些变量和方法从私有部分移到受保护部分:

//+------------------------------------------------------------------+
//| Class of the graphical element object                            |
//+------------------------------------------------------------------+
class CGCnvElement : public CGBaseObj
  {
protected:
   CGCnvElement     *m_element_main;                           // Pointer to the initial parent element within all the groups of bound objects
   CGCnvElement     *m_element_base;                           // Pointer to the parent element within related objects of the current group
   CCanvas           m_canvas;                                 // CCanvas class object
   CPause            m_pause;                                  // Pause class object
   bool              m_shadow;                                 // Shadow presence
   color             m_chart_color_bg;                         // Chart background color
   uint              m_duplicate_res[];                        // Array for storing resource data copy
   color             m_array_colors_bg[];                      // Array of element background colors
   color             m_array_colors_bg_dwn[];                  // Array of control background colors when clicking on the control
   color             m_array_colors_bg_ovr[];                  // Array of control background colors when hovering the mouse over the control
   bool              m_gradient_v;                             // Vertical gradient filling flag
   bool              m_gradient_c;                             // Cyclic gradient filling flag
   int               m_init_relative_x;                        // Initial relative X coordinate
   int               m_init_relative_y;                        // Initial relative Y coordinate
   color             m_array_colors_bg_init[];                 // Array of element background colors (initial color)
   int               m_shift_coord_x;                          // Offset of the X coordinate relative to the base object
   int               m_shift_coord_y;                          // Offset of the Y coordinate relative to the base object

//--- Create (1) the object structure and (2) the object from the structure

...

   long              m_long_prop[CANV_ELEMENT_PROP_INTEGER_TOTAL];   // Integer properties
   double            m_double_prop[CANV_ELEMENT_PROP_DOUBLE_TOTAL];  // Real properties
   string            m_string_prop[CANV_ELEMENT_PROP_STRING_TOTAL];  // String properties

   ENUM_FRAME_ANCHOR m_text_anchor;                            // Current text alignment
   int               m_text_x;                                 // Text last X coordinate
   int               m_text_y;                                 // Text last Y coordinate

protected:   
//--- Initialize property values
   void              Initialize(const ENUM_GRAPH_ELEMENT_TYPE element_type,
                                const int element_id,const int element_num,
                                const int x,const int y,const int w,const int h,
                                const string descript,const bool movable,const bool activity);
                                
private:   
//--- Return the index of the array the order's (1) double and (2) string properties are located at


在处理文本的方法部分,编写两个访问私有类属性设置的方法:

//+------------------------------------------------------------------+
//| Methods of working with text                                     |
//+------------------------------------------------------------------+
//--- Set the last text coordinate (1) X, (2) Y
   void              SetTextLastX(const int x)                    { this.m_text_x=x;                                                   }
   void              SetTextLastY(const int y)                    { this.m_text_y=y;                                                   }
//--- Return (1) alignment type (anchor method), the last (2) X and (3) Y text coordinate

这些方法在继承类的构造函数中非常有用,因为将这些变量放在类的受保护部分会对其他类造成更大的修改。目前,我们将使用这些方法,而无需重命名变量。

到目前为止,我们使用的对象都是基于OBJ_BITMAP_LABEL - "图形标签" 对象:


可以从 ENUM_ANCHOR_POINT 枚举中选择相对于标签的锚点位置。锚点坐标以像素为单位。

您还可以从 ENUM_BASE_CORNER 枚举中选择位图锚定角。

这些对象的屏幕坐标以像素为单位,适用于创建图形控件。

但是,如果我们需要将这样一个对象与价格/时间坐标绑定,同时在对象内部使用与在画布上完全相同的绘制可能性,那么 OBJ_BITMAP 图形对象就能帮上忙了:


这是完全相同的图形对象,它可以使用光栅图像文件或动态创建的资源作为图像,并在其中进行渲染。

CCanvas 类方法允许创建位图对象。因此,我们只需在图形元素类的基础上稍加修改,创建一个绘图对象类。


位图图形元素类

\MQL5\Include\DoEasy\Objects\Graph\ 库文件夹中,创建 CGCnvBitmap 类的新文件 GCnvBitmap.mqh。
该类应从图形元素类派生,其文件应包含在创建类的文件中

//+------------------------------------------------------------------+
//|                                                   GCnvBitmap.mqh |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict    // Necessary for mql4
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "GCnvElement.mqh"
//+------------------------------------------------------------------+
//| Class of the graphical element object                            |
//+------------------------------------------------------------------+
class CGCnvBitmap : public CGCnvElement
  {
  }


在类的主体中,我们只需要一些私有变量和处理这些变量的方法、一个创建对象的虚拟方法以及构造函数和析构函数。其他一切都已在父类中实现:

//+------------------------------------------------------------------+
//| Class of the graphical element object                            |
//+------------------------------------------------------------------+
class CGCnvBitmap : public CGCnvElement
  {
private:
   datetime          m_time;              // Time coordinate
   double            m_price;             // Price ccoordinate
protected:
//--- Protected constructor
                     CGCnvBitmap(const ENUM_GRAPH_ELEMENT_TYPE element_type,
                                 CGCnvElement *main_obj,CGCnvElement *base_obj,
                                 const long     chart_id,
                                 const int      wnd_num,
                                 const string   descript,
                                 const datetime time,
                                 const double   price,
                                 const int      w,
                                 const int      h);
public:
//--- Create Bitmap
   virtual bool      Create(const long chart_id, 
                            const int wnd_num,
                            const int x,
                            const int y,
                            const int w,
                            const int h,
                            const bool redraw=false);

//--- Parametric constructor
                     CGCnvBitmap(const ENUM_GRAPH_ELEMENT_TYPE element_type,
                                 CGCnvElement  *main_obj,CGCnvElement *base_obj,
                                 const int      element_id,
                                 const int      element_num,
                                 const long     chart_id,
                                 const int      wnd_num,
                                 const string   descript,
                                 const datetime time,
                                 const double   price,
                                 const int      w,
                                 const int      h,
                                 const color    colour,
                                 const uchar    opacity,
                                 const bool     movable=false,
                                 const bool     activity=true,
                                 const bool     redraw=false);
//--- Default constructor
                     CGCnvBitmap()
                        {
                         this.m_shadow=false;
                         this.m_chart_color_bg=(color)::ChartGetInteger(::ChartID(),CHART_COLOR_BACKGROUND);
                         this.m_type=OBJECT_DE_TYPE_GBITMAP;
                         this.m_element_main=NULL;
                         this.m_element_base=NULL;
                         this.m_shift_coord_x=0;
                         this.m_shift_coord_y=0;
                        }
//--- Destructor
                    ~CGCnvBitmap()
                        { this.m_canvas.Destroy();             }
     
//+------------------------------------------------------------------+
//| Methods of simplified access to object properties                |
//+------------------------------------------------------------------+
//--- Set the (1) time and (2) price coordinate or (3) both
   bool              SetTime(const datetime time);
   bool              SetPrice(const double price);
   bool              SetTimePrice(const datetime time,const double price);
   
//--- Return (1) time and (2) price coordinate
   datetime          Time(void)  const { return this.m_time;   }
   double            Price(void) const { return this.m_price;  }

  };


所有构造函数都是父类构造函数的副本,初始化时使用父类的默认构造函数:

//+------------------------------------------------------------------+
//| Parametric constructor                                           |
//+------------------------------------------------------------------+
CGCnvBitmap::CGCnvBitmap(const ENUM_GRAPH_ELEMENT_TYPE element_type,
                         CGCnvElement *main_obj,CGCnvElement *base_obj,
                         const int      element_id,
                         const int      element_num,
                         const long     chart_id,
                         const int      wnd_num,
                         const string   descript,
                         const datetime time,
                         const double   price,
                         const int      w,
                         const int      h,
                         const color    colour,
                         const uchar    opacity,
                         const bool     movable=false,
                         const bool     activity=true,
                         const bool     redraw=false)
  {
   this.SetTypeElement(element_type);
   this.m_type=OBJECT_DE_TYPE_GBITMAP; 
   this.m_element_main=main_obj;
   this.m_element_base=base_obj;
   this.m_chart_color_bg=(color)::ChartGetInteger((chart_id==NULL ? ::ChartID() : chart_id),CHART_COLOR_BACKGROUND);
   this.m_name=this.CreateNameGraphElement(element_type);
   this.m_chart_id=(chart_id==NULL || chart_id==0 ? ::ChartID() : chart_id);
   this.m_subwindow=wnd_num;
   this.SetFont(DEF_FONT,DEF_FONT_SIZE);
   this.SetTextAnchor(0);
   this.SetTextLastX(0);
   this.SetTextLastY(0);
   this.SetBackgroundColor(colour,true);
   this.SetOpacity(opacity);
   this.m_shift_coord_x=0;
   this.m_shift_coord_y=0;
   if(::ArrayResize(this.m_array_colors_bg,1)==1)
      this.m_array_colors_bg[0]=this.BackgroundColor();
   if(::ArrayResize(this.m_array_colors_bg_dwn,1)==1)
      this.m_array_colors_bg_dwn[0]=this.BackgroundColor();
   if(::ArrayResize(this.m_array_colors_bg_ovr,1)==1)
      this.m_array_colors_bg_ovr[0]=this.BackgroundColor();
   if(this.Create(chart_id,wnd_num,0,0,w,h,redraw))
     {
      this.Initialize(element_type,element_id,element_num,0,0,w,h,descript,movable,activity);
      this.SetVisibleFlag(false,false);
      this.SetTimePrice(time,price);
     }
   else
     {
      ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_FAILED_CREATE_ELM_OBJ),"\"",this.TypeElementDescription(element_type),"\" ",this.NameObj());
     }
  }
//+------------------------------------------------------------------+
//| Protected constructor                                            |
//+------------------------------------------------------------------+
CGCnvBitmap::CGCnvBitmap(const ENUM_GRAPH_ELEMENT_TYPE element_type,
                         CGCnvElement *main_obj,CGCnvElement *base_obj,
                         const long     chart_id,
                         const int      wnd_num,
                         const string   descript,
                         const datetime time,
                         const double   price,
                         const int      w,
                         const int      h)
  {
   this.m_type=OBJECT_DE_TYPE_GBITMAP; 
   this.m_element_main=main_obj;
   this.m_element_base=base_obj;
   this.m_chart_color_bg=(color)::ChartGetInteger((chart_id==NULL ? ::ChartID() : chart_id),CHART_COLOR_BACKGROUND);
   this.m_name=this.CreateNameGraphElement(element_type);
   this.m_chart_id=(chart_id==NULL || chart_id==0 ? ::ChartID() : chart_id);
   this.m_subwindow=wnd_num;
   this.m_type_element=element_type;
   this.SetFont(DEF_FONT,DEF_FONT_SIZE);
   this.SetTextAnchor(0);
   this.SetTextLastX(0);
   this.SetTextLastY(0);
   this.SetBackgroundColor(CLR_CANV_NULL,true);
   this.SetOpacity(0);
   this.m_shift_coord_x=0;
   this.m_shift_coord_y=0;
   this.m_shadow=false;
   if(::ArrayResize(this.m_array_colors_bg,1)==1)
      this.m_array_colors_bg[0]=this.BackgroundColor();
   if(::ArrayResize(this.m_array_colors_bg_dwn,1)==1)
      this.m_array_colors_bg_dwn[0]=this.BackgroundColor();
   if(::ArrayResize(this.m_array_colors_bg_ovr,1)==1)
      this.m_array_colors_bg_ovr[0]=this.BackgroundColor();
   if(this.Create(chart_id,wnd_num,0,0,w,h,false))
     {
      this.Initialize(element_type,0,0,0,0,w,h,descript,false,false);
      this.SetVisibleFlag(false,false);
      this.SetTimePrice(time,price);
     }
   else
     {
      ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_FAILED_CREATE_ELM_OBJ),"\"",this.TypeElementDescription(element_type),"\" ",this.NameObj());
     }
  }

在这里,我们使用父类的默认构造函数,因为所有对象参数都是在该构造函数中设置并创建的。为了不在构造函数中重新定义参数,也为了不删除和重新创建一个新类型的对象,我们在这些构造函数中使用父对象的默认构造函数来完成所有这些工作。


创建图形位图对象的虚拟方法:

//+------------------------------------------------------------------+
//| Create the graphical bitmap object                               |
//+------------------------------------------------------------------+
bool CGCnvBitmap::Create(const long chart_id,     // Chart ID
                         const int wnd_num,       // Chart subwindow
                         const int x,             // X coordinate
                         const int y,             // Y coordinate
                         const int w,             // Width
                         const int h,             // Height
                         const bool redraw=false) // Flag indicating the need to redraw
                         
  {
   ::ResetLastError();
   if(this.m_canvas.CreateBitmap((chart_id==NULL ? ::ChartID() : chart_id),wnd_num,this.m_name,x,y,w,h,COLOR_FORMAT_ARGB_NORMALIZE))
     {
      this.Erase(CLR_CANV_NULL);
      this.m_canvas.Update(redraw);
      this.m_shift_y=(int)::ChartGetInteger((chart_id==NULL ? ::ChartID() : chart_id),CHART_WINDOW_YDISTANCE,wnd_num);
      return true;
     }
   int err=::GetLastError();
   int code=(err==0 ? (w<1 ? MSG_CANV_ELEMENT_ERR_FAILED_SET_WIDTH : h<1 ? MSG_CANV_ELEMENT_ERR_FAILED_SET_HEIGHT : ERR_OBJECT_ERROR) : err);
   string subj=(w<1 ? "Width="+(string)w+". " : h<1 ? "Height="+(string)h+". " : "");
   CMessage::ToLog(DFUN_ERR_LINE+subj,code,true);
   return false;
  }

在这里,与父类的相同方法不同,该方法用于创建 CCanvas 类的 CreateBitmap() 方法,而不是 CreateBitmapLabel() 方法。这是该方法与父类方法的唯一区别。


为位图对象设置价格和时间坐标的方法:

//+------------------------------------------------------------------+
//| Set the time coordinate                                          |
//+------------------------------------------------------------------+
bool CGCnvBitmap::SetTime(const datetime time)
  {
   string name=this.NameObj();
   if(name==NULL || name=="")
      return false;
   ::ResetLastError();
   if(!::ObjectSetInteger(this.ChartID(),name,OBJPROP_TIME,time))
     {
      ::PrintFormat("%s%s. %s %s",DFUN,CMessage::Text(MSG_ERR_FAILED_SET_BITMAP_OBJ_TIME),CMessage::Text(MSG_LIB_SYS_ERROR),::GetLastError());
      return false;
     }
   this.m_time=time;
   return true;
  }
//+------------------------------------------------------------------+
//| Set the price coordinate                                         |
//+------------------------------------------------------------------+
bool CGCnvBitmap::SetPrice(const double price)
  {
   string name=this.NameObj();
   if(name==NULL || name=="")
      return false;
   ::ResetLastError();
   if(!::ObjectSetDouble(this.ChartID(),name,OBJPROP_PRICE,price))
     {
      ::PrintFormat("%s%s. %s %s",DFUN,CMessage::Text(MSG_ERR_FAILED_SET_BITMAP_OBJ_PRICE),CMessage::Text(MSG_LIB_SYS_ERROR),::GetLastError());
      return false;
     }
   this.m_price=price;
   return true;
  }
//+------------------------------------------------------------------+
//| Set both coordinates                                             |
//+------------------------------------------------------------------+
bool CGCnvBitmap::SetTimePrice(const datetime time,const double price)
  {
   if(!this.SetTime(time))
      return false;
   return this.SetPrice(price);
  }
//+------------------------------------------------------------------+

简而言之:如果无法在图形对象中设置属性,我们会在日志中显示相关信息并返回 false
当属性成功设置到对象时,新值将写入类变量并返回 true


在 \MQL5\Include\DoEasy\Objects\Graph\GraphElmControl.mqh 文件中的图形元素管理类中,声明创建位图对象的方法

//+------------------------------------------------------------------+
//| Class for managing graphical elements                            |
//+------------------------------------------------------------------+
class CGraphElmControl : public CObject
  {
private:
   int               m_type;                          // Object type
   int               m_type_node;                     // Type of the object the graphics is constructed for
//--- Set general parameters for standard graphical objects
   void              SetCommonParamsStdGraphObj(const long chart_id,const string name);
public:
//--- Return itself
   CGraphElmControl *GetObject(void)                  { return &this;               }
//--- Set a type of the object the graphics is constructed for
   void              SetTypeNode(const int type_node) { this.m_type_node=type_node; }
   
//--- Create a form object
   CForm            *CreateForm(const int form_id,const long chart_id,const int wnd,const string name,const int x,const int y,const int w,const int h);
   CForm            *CreateForm(const int form_id,const int wnd,const string name,const int x,const int y,const int w,const int h);
   CForm            *CreateForm(const int form_id,const string name,const int x,const int y,const int w,const int h);

//--- Create Bitmap object
   CGCnvBitmap      *CreateBitmap(const int obj_id,const long chart_id,const int wnd,const string name,const datetime time,const double price,const int w,const int h,const color clr);
   
//--- Creates the trend line standard graphical object


我们在类主体之外编写其实现:

//+------------------------------------------------------------------+
//| Create Bitmap object                                             |
//+------------------------------------------------------------------+
CGCnvBitmap *CGraphElmControl::CreateBitmap(const int obj_id,const long chart_id,const int wnd,const string name,const datetime time,const double price,const int w,const int h,const color clr)
  {
   CGCnvBitmap *obj=new CGCnvBitmap(GRAPH_ELEMENT_TYPE_BITMAP,NULL,NULL,obj_id,0,chart_id,wnd,name,time,price,w,h,clr,200);
   return obj;
  }

该方法将创建一个 CDCnvBitmap 类的新对象,参数传递给它,画布不透明度等于 200,并返回指向所创建对象的指针。


现在,在 CBaseObj 库的基础对象类中,即在 \MQL5\Include\DoEasy\Objects\BaseObj.mqh 文件中,编写用于创建位图对象的方法

//+------------------------------------------------------------------+
//| Methods for handling graphical elements                          |
//+------------------------------------------------------------------+
//--- Create a form object on a specified chart in a specified subwindow
   CForm            *CreateForm(const int form_id,const long chart_id,const int wnd,const string name,const int x,const int y,const int w,const int h)
                       { return this.m_graph_elm.CreateForm(form_id,chart_id,wnd,name,x,y,w,h);                }
//--- Create a form object on the current chart in a specified subwindow
   CForm            *CreateForm(const int form_id,const int wnd,const string name,const int x,const int y,const int w,const int h)
                       { return this.m_graph_elm.CreateForm(form_id,wnd,name,x,y,w,h);                         }
//--- Create the form object on the current chart in the main window
   CForm            *CreateForm(const int form_id,const string name,const int x,const int y,const int w,const int h)
                       { return this.m_graph_elm.CreateForm(form_id,name,x,y,w,h);                             }
   
//--- Create a bitmap object on a specified chart in a specified subwindow
   CGCnvBitmap      *CreateBitmap(const int obj_id,const long chart_id,const int wnd,const string name,const datetime time,const double price,const int w,const int h,const color clr)
                       { return this.m_graph_elm.CreateBitmap(obj_id,chart_id,wnd,name,time,price,w,h,clr);   }
//--- Create a bitmap object on the current chart in a specified subwindow
   CGCnvBitmap      *CreateBitmap(const int obj_id,const int wnd,const string name,const datetime time,const double price,const int w,const int h,const color clr)
                       { return this.m_graph_elm.CreateBitmap(obj_id,::ChartID(),wnd,name,time,price,w,h,clr);}
//--- Create the bitmap object on the current chart in the main window
   CGCnvBitmap      *CreateBitmap(const int obj_id,const string name,const datetime time,const double price,const int w,const int h,const color clr)
                       { return this.m_graph_elm.CreateBitmap(obj_id,::ChartID(),0,name,time,price,w,h,clr);  }
   
//--- Create a standard graphical trend line object in the specified subwindow of the specified chart

创建绘图对象的三种方法:(1) 在指定子窗口中的指定图表上创建;(2) 在指定子窗口中的当前图表上创建;(3) 在主窗口中的当前图表上创建。这些方法只是简单地返回调用创建 CGraphElmControl 类位图对象的方法的结果,该方法使用了上述指定的参数。

现在,我们可以从任何库对象中创建一个绘图对象,从而进行可视化设计。顺便提一下,以前我们已经可以从任何库对象中创建一些图形基本元素和图形用户界面元素。现在,一个位图对象已被添加到列表中。

图形表单对象的类继承自图形元素类。因此,图形元素文件与表单对象类文件相关联。由于我们现在有了另一个从图形元素继承而来的类 - 位图对象类,为了以最佳方式将所有这些类相互连接起来,我们将把位图对象类文件连接到窗体对象类文件。由于该类是从图形元素派生出来的,因此这两个类都可以在表单对象类中使用。

MQL5\Include\DoEasy\Objects\Graph\Form.mqh 表单对象类文件接收位图对象类文件,而不是图形元素文件:

//+------------------------------------------------------------------+
//|                                                         Form.mqh |
//|                                  Copyright 2022, MetaQuotes Ltd. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, MetaQuotes Ltd."
#property link      "https://mql5.com/en/users/artmedia70"
#property version   "1.00"
#property strict    // Necessary for mql4
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "GCnvBitmap.mqh"
#include "ShadowObj.mqh"
#include "Animations\Animations.mqh"
#include "..\..\Services\MouseState.mqh"
//+------------------------------------------------------------------+
//| Form object class                                                |
//+------------------------------------------------------------------+
class CForm : public CGCnvElement
  {

现在,元素对象和位图对象都可以在表单对象中使用。因此,在其他需要使用元素对象的文件中,这两个对象都可以使用。


将找到的对象输入到柱形对象中。
为此,在 \MQL5\Include\DoEasy\Objects\Series\Bar.mqh 柱形对象类文件的公共部分中,编写向柱形属性添加新模式类型的方法

//--- Return itself
   CBar             *GetObject(void)                                    { return &this;}
//--- Set (1) bar symbol, timeframe and time, (2) bar object parameters
   void              SetSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES timeframe,const datetime time);
   void              SetProperties(const MqlRates &rates);
//--- Add the pattern type on bar
   void              AddPattern(const ENUM_PATTERN_TYPE pattern_type)   { this.m_long_prop[BAR_PROP_PATTERNS_TYPE] |=pattern_type;           }

//--- Compare CBar objects by all possible properties (for sorting the lists by a specified bar object property)
   virtual int       Compare(const CObject *node,const int mode=0) const;
//--- Compare CBar objects by all properties (to search for equal bar objects)
   bool              IsEqual(CBar* compared_bar) const;
//--- Constructors
                     CBar(){ this.m_type=OBJECT_DE_TYPE_SERIES_BAR; }
                     CBar(const string symbol,const ENUM_TIMEFRAMES timeframe,const datetime time,const string source);
                     CBar(const string symbol,const ENUM_TIMEFRAMES timeframe,const MqlRates &rates);

该方法接收形态类型,其值(位掩码)被添加到 BAR_PROP_PATTERNS_TYPE 属性值中。通过使用逻辑 "或" 操作符,我们可以为变量添加不同的类型,而不会覆盖变量值。因此,一个变量中可以存储多个不同类型的形态。


在柱形属性描述部分 声明在传递的数组中返回形态列表的方法的方法,以及向日志输出柱形形态列表的方法

//+------------------------------------------------------------------+
//| Descriptions of bar object properties                            |
//+------------------------------------------------------------------+
//--- Get description of a bar's (1) integer, (2) real and (3) string properties
   string            GetPropertyDescription(ENUM_BAR_PROP_INTEGER property);
   string            GetPropertyDescription(ENUM_BAR_PROP_DOUBLE property);
   string            GetPropertyDescription(ENUM_BAR_PROP_STRING property);

//--- Return the bar type description
   string            BodyTypeDescription(void)  const;
//--- Display the description of the object properties in the journal (full_prop=true - all properties, false - supported ones only - implemented in descendant classes)
   virtual void      Print(const bool full_prop=false,const bool dash=false);
//--- Display a short description of the object in the journal
   virtual void      PrintShort(const bool dash=false,const bool symbol=false);
//--- Return the (1) short name, (2) description of bar object parameters and (3) a list of patterns in the passed array
   virtual string    Header(void);
   string            ParameterDescription(void);
   int               GetPatternsList(ulong &array[]);
//--- Display a list of patterns on the bar in the journal
   void              PatternTypeDescriptionPrint(const bool dash=false);
//---
  };


在设置柱形对象参数的方法中,将柱形的形态类型设置为不存在(变量值为零):

//+------------------------------------------------------------------+
//| Set bar object parameters                                        |
//+------------------------------------------------------------------+
void CBar::SetProperties(const MqlRates &rates)
  {
   this.SetProperty(BAR_PROP_SPREAD,rates.spread);
   this.SetProperty(BAR_PROP_VOLUME_TICK,rates.tick_volume);
   this.SetProperty(BAR_PROP_VOLUME_REAL,rates.real_volume);
   this.SetProperty(BAR_PROP_TIME,rates.time);
   this.SetProperty(BAR_PROP_TIME_YEAR,this.TimeYear());
   this.SetProperty(BAR_PROP_TIME_MONTH,this.TimeMonth());
   this.SetProperty(BAR_PROP_TIME_DAY_OF_YEAR,this.TimeDayOfYear());
   this.SetProperty(BAR_PROP_TIME_DAY_OF_WEEK,this.TimeDayOfWeek());
   this.SetProperty(BAR_PROP_TIME_DAY,this.TimeDay());
   this.SetProperty(BAR_PROP_TIME_HOUR,this.TimeHour());
   this.SetProperty(BAR_PROP_TIME_MINUTE,this.TimeMinute());
//---
   this.SetProperty(BAR_PROP_OPEN,rates.open);
   this.SetProperty(BAR_PROP_HIGH,rates.high);
   this.SetProperty(BAR_PROP_LOW,rates.low);
   this.SetProperty(BAR_PROP_CLOSE,rates.close);
   this.SetProperty(BAR_PROP_CANDLE_SIZE,this.CandleSize());
   this.SetProperty(BAR_PROP_CANDLE_SIZE_BODY,this.BodySize());
   this.SetProperty(BAR_PROP_CANDLE_BODY_TOP,this.BodyHigh());
   this.SetProperty(BAR_PROP_CANDLE_BODY_BOTTOM,this.BodyLow());
   this.SetProperty(BAR_PROP_CANDLE_SIZE_SHADOW_UP,this.ShadowUpSize());
   this.SetProperty(BAR_PROP_CANDLE_SIZE_SHADOW_DOWN,this.ShadowDownSize());
//---
   this.SetProperty(BAR_PROP_RATIO_BODY_TO_CANDLE_SIZE,this.CandleRatioBodyToCandleSize());
   this.SetProperty(BAR_PROP_RATIO_UPPER_SHADOW_TO_CANDLE_SIZE,this.CandleRatioUpperShadowToCandleSize());
   this.SetProperty(BAR_PROP_RATIO_LOWER_SHADOW_TO_CANDLE_SIZE,this.CandleRatioLowerShadowToCandleSize());
   this.SetProperty(BAR_PROP_PATTERNS_TYPE,0);
   this.SetProperty(BAR_PROP_TYPE,this.BodyType());
//--- Set the object type to the object of the graphical object management class
   this.m_graph_elm.SetTypeNode(this.m_type);
  }


在类主体之外,编写返回所传递数组中形态列表的方法:

//+------------------------------------------------------------------+
//| Return the list of patterns in the passed array                  |
//+------------------------------------------------------------------+
int CBar::GetPatternsList(ulong &array[])
  {
   return ListPatternsInVar(this.GetProperty(BAR_PROP_PATTERNS_TYPE),array);
  }

数组被传递给该方法,并返回执行上述 ListPatternsInVar() 函数的结果。在这种情况下,柱形上所有形态的列表会被放入由链接传递给该方法的数组中。


在日志中显示对柱形描述的方法:

//+------------------------------------------------------------------+
//| Display the description of patterns on the bar in the journal    |
//+------------------------------------------------------------------+
void CBar::PatternTypeDescriptionPrint(const bool dash=false)
  {
   ulong patt=this.GetProperty(BAR_PROP_PATTERNS_TYPE);
   ::Print(CMessage::Text(MSG_LIB_TEXT_BAR_PATTERNS_TYPE),": ",(patt>0 ? "" : CMessage::Text(MSG_LIB_PROP_EMPTY)));
   if(patt>0)
      ::Print(PatternsInVarDescription(patt,dash));
  }

在此之前,我们编写了 PatternsInVarDescription() 函数,该函数返回一个字符串,其中包含变量中所有标记的形态的描述。在此,我们将存储 BAR_PROP_PATTERNS_TYPE 柱形属性的变量值发送到该函数,并将从函数接收到的字符串打印到日志中。


在返回柱形整数属性描述的方法中,添加返回 BAR_PROP_PATTERNS_TYPE 属性值描述

//+------------------------------------------------------------------+
//| Return the description of the bar integer property               |
//+------------------------------------------------------------------+
string CBar::GetPropertyDescription(ENUM_BAR_PROP_INTEGER property)
  {
   return
     (
      property==BAR_PROP_TIME                ?  CMessage::Text(MSG_LIB_TEXT_BAR_TIME)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::TimeToString(this.GetProperty(property),TIME_DATE|TIME_MINUTES|TIME_SECONDS)
         )  :
      property==BAR_PROP_TYPE                ?  CMessage::Text(MSG_ORD_TYPE)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+this.BodyTypeDescription()
         )  :
      property==BAR_PROP_PERIOD              ?  CMessage::Text(MSG_LIB_TEXT_BAR_PERIOD)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+this.m_period_description
         )  :
      property==BAR_PROP_SPREAD              ?  CMessage::Text(MSG_LIB_TEXT_BAR_SPREAD)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==BAR_PROP_VOLUME_TICK         ?  CMessage::Text(MSG_LIB_TEXT_BAR_VOLUME_TICK)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==BAR_PROP_VOLUME_REAL         ?  CMessage::Text(MSG_LIB_TEXT_BAR_VOLUME_REAL)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==BAR_PROP_TIME_YEAR           ?  CMessage::Text(MSG_LIB_TEXT_BAR_TIME_YEAR)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.Year()
         )  :
      property==BAR_PROP_TIME_MONTH          ?  CMessage::Text(MSG_LIB_TEXT_BAR_TIME_MONTH)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+MonthDescription((int)this.Month())
         )  :
      property==BAR_PROP_TIME_DAY_OF_YEAR    ?  CMessage::Text(MSG_LIB_TEXT_BAR_TIME_DAY_OF_YEAR)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::IntegerToString(this.DayOfYear(),3,'0')
         )  :
      property==BAR_PROP_TIME_DAY_OF_WEEK    ?  CMessage::Text(MSG_LIB_TEXT_BAR_TIME_DAY_OF_WEEK)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+DayOfWeekDescription((ENUM_DAY_OF_WEEK)this.DayOfWeek())
         )  :
      property==BAR_PROP_TIME_DAY            ?  CMessage::Text(MSG_LIB_TEXT_BAR_TIME_DAY)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::IntegerToString(this.Day(),2,'0')
         )  :
      property==BAR_PROP_TIME_HOUR           ?  CMessage::Text(MSG_LIB_TEXT_BAR_TIME_HOUR)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::IntegerToString(this.Hour(),2,'0')
         )  :
      property==BAR_PROP_TIME_MINUTE         ?  CMessage::Text(MSG_LIB_TEXT_BAR_TIME_MINUTE)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::IntegerToString(this.Minute(),2,'0')
         )  :
      property==BAR_PROP_PATTERNS_TYPE       ?  CMessage::Text(MSG_LIB_TEXT_BAR_PATTERNS_TYPE)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property)==0 ? CMessage::Text(MSG_LIB_PROP_NOT_FOUND) : "\n"+PatternsInVarDescription(this.GetProperty(property),true))
         )  :
      ""
     );
  }


让我们对文件 MQL5\Include\DoEasy\Objects\Series\Patterns\Pattern.mqh 进行改进。

由于我们将把指向柱形对象的指针放在形态对象上,而柱形对象是在形态对象上找到的,因此我们需要在形态对象类文件中包含柱形对象类文件。该形态有一个基础柱和一个 "母" 柱。对于基础柱形,我们将使用指向柱形对象(形态所在的柱形)的指针。对于 "母" 柱,我们将创建 MqlRates 结构,柱形数据将存储在其中。这样,我们就能始终获得形态 "覆盖" 的所有柱形数据。顺便说一下,如果形态是单柱,那么母柱和基柱就是同一个单柱。我们将使用在此创建的位图对象来 "勾勒" 图案。我们将在抽象模式对象类的受保护部分声明指向类对象的指针。为了能够计算出覆盖形态柱形所需的尺寸,我们需要知道图表的尺寸和参数。声明变量,用于存储计算位图对象大小所需的图表参数。

//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "..\..\BaseObj.mqh"
#include "..\Bar.mqh"
//+------------------------------------------------------------------+
//| Abstract pattern class                                           |
//+------------------------------------------------------------------+
class CPattern : public CBaseObj
  {
private:
   CBar             *m_bar_pattern;                               // Pointer to the bar the pattern is formed on
   MqlRates          m_mother_bar_prop;                           // "Mother" bar parameters
   long              m_long_prop[PATTERN_PROP_INTEGER_TOTAL];     // Integer properties
   double            m_double_prop[PATTERN_PROP_DOUBLE_TOTAL];    // Real properties
   string            m_string_prop[PATTERN_PROP_STRING_TOTAL];    // String properties
   
//--- Return the index of the array the pattern (1) double and (2) string properties are located at
   int               IndexProp(ENUM_PATTERN_PROP_DOUBLE property) const { return(int)property-PATTERN_PROP_INTEGER_TOTAL;                          }
   int               IndexProp(ENUM_PATTERN_PROP_STRING property) const { return(int)property-PATTERN_PROP_INTEGER_TOTAL-PATTERN_PROP_DOUBLE_TOTAL;}

protected:
   CForm            *m_form;                                      // Pointer to form object
   CGCnvBitmap      *m_bitmap;                                    // Pointer to the bitmap object
   int               m_digits;                                    // Symbol's digits value
   ulong             m_symbol_code;                               // Symbol as a number (sum of name symbol codes)
   string            m_name_graph_obj;                            // Name of the graphical object displaying the pattern
   double            m_price;                                     // Price level the graphical object is placed at
   color             m_color_bullish;                             // Color of a graphical object set to the bullish pattern icon
   color             m_color_bearish;                             // Color of a graphical object set to the bearish pattern icon
   color             m_color_bidirect;                            // Color of a graphical object set to the bidirectional pattern icon
   color             m_color;                                     // Graphical object color
   color             m_color_panel_bullish;                       // Bullish pattern panel color
   color             m_color_panel_bearish;                       // Bearish pattern panel color
   color             m_color_panel_bidirect;                      // Bidirectional pattern panel color
   int               m_bars_formation;                            // Number of bars in the formation (nested pattern)
   bool              m_draw_dots;                                 // Draw on the chart with dots
   int               m_chart_scale;                               // Chart scale
   int               m_chart_height_px;                           // Height of the chart in pixels
   double            m_chart_price_max;                           // Chart maximum
   double            m_chart_price_min;                           // Chart minimum
   
public:


在类的公有部分,添加用于设置和返回新属性和指针的方法

public:
//--- Set pattern (1) integer, (2) real and (3) string properties
   void              SetProperty(ENUM_PATTERN_PROP_INTEGER property,long value) { this.m_long_prop[property]=value;                    }
   void              SetProperty(ENUM_PATTERN_PROP_DOUBLE property,double value){ this.m_double_prop[this.IndexProp(property)]=value;  }
   void              SetProperty(ENUM_PATTERN_PROP_STRING property,string value){ this.m_string_prop[this.IndexProp(property)]=value;  }
//--- Return (1) integer, (2) real and (3) string pattern properties from the property array
   long              GetProperty(ENUM_PATTERN_PROP_INTEGER property) const { return this.m_long_prop[property];                        }
   double            GetProperty(ENUM_PATTERN_PROP_DOUBLE property)  const { return this.m_double_prop[this.IndexProp(property)];      }
   string            GetProperty(ENUM_PATTERN_PROP_STRING property)  const { return this.m_string_prop[this.IndexProp(property)];      }

//--- Return the flag of the pattern supporting the specified property
   virtual bool      SupportProperty(ENUM_PATTERN_PROP_INTEGER property)   { return true;       }
   virtual bool      SupportProperty(ENUM_PATTERN_PROP_DOUBLE property)    { return true;       }
   virtual bool      SupportProperty(ENUM_PATTERN_PROP_STRING property)    { return true;       }
//--- Return itself
   CPattern         *GetObject(void)                                       { return &this;      }
   CForm            *GetForm(void)                                         { return this.m_form;}
   
//--- Compare CPattern objects by all possible properties (for sorting the lists by a specified pattern object property)
   virtual int       Compare(const CObject *node,const int mode=0) const;
//--- Compare CPattern objects with each other by all properties (to search equal pattern objects)
   bool              IsEqual(CPattern* compared_obj) const;
//--- Constructors
                     CPattern(){ this.m_type=OBJECT_DE_TYPE_SERIES_PATTERN; }
protected:
//--- Protected parametric constructor
                     CPattern(const ENUM_PATTERN_STATUS status,
                              const ENUM_PATTERN_TYPE type,
                              const uint id,
                              const ENUM_PATTERN_DIRECTION direction,
                              const string symbol,
                              const ENUM_TIMEFRAMES timeframe,MqlRates &rates);
public:                     
//--- Destructor
                    ~CPattern(void);
                    
//+------------------------------------------------------------------+ 
//| Methods of a simplified access to the pattern object properties  |
//+------------------------------------------------------------------+
//--- Return (1) type, (2) direction, (3) period, (4) status,
//--- (5) code, (6) pattern defining bar time,
//--- (7) number of candles forming the pattern
   ENUM_PATTERN_TYPE TypePattern(void)                               const { return (ENUM_PATTERN_TYPE)this.GetProperty(PATTERN_PROP_TYPE);           }
   ENUM_PATTERN_DIRECTION Direction(void)                            const { return (ENUM_PATTERN_DIRECTION)this.GetProperty(PATTERN_PROP_DIRECTION); }
   ENUM_TIMEFRAMES   Timeframe(void)                                 const { return (ENUM_TIMEFRAMES)this.GetProperty(PATTERN_PROP_PERIOD);           }
   ENUM_PATTERN_STATUS Status(void)                                  const { return (ENUM_PATTERN_STATUS)this.GetProperty(PATTERN_PROP_STATUS);       }
   ulong             Code(void)                                      const { return this.GetProperty(PATTERN_PROP_CODE);                              }
   uint              ID(void)                                        const { return (uint)this.GetProperty(PATTERN_PROP_ID);                          }
   ulong             ControlObjectID(void)                           const { return this.GetProperty(PATTERN_PROP_CTRL_OBJ_ID);                       }
   datetime          Time(void)                                      const { return (datetime)this.GetProperty(PATTERN_PROP_TIME);                    }
   uint              Candles(void)                                   const { return (uint)this.GetProperty(PATTERN_PROP_CANDLES);                     }
//--- Return pattern defining bar prices
   double            BarPriceOpen(void)                              const { return this.GetProperty(PATTERN_PROP_BAR_PRICE_OPEN);                    }
   double            BarPriceHigh(void)                              const { return this.GetProperty(PATTERN_PROP_BAR_PRICE_HIGH);                    }
   double            BarPriceLow(void)                               const { return this.GetProperty(PATTERN_PROP_BAR_PRICE_LOW);                     }
   double            BarPriceClose(void)                             const { return this.GetProperty(PATTERN_PROP_BAR_PRICE_CLOSE);                   }
//--- Return pattern (1) symbol and (2) name
   string            Symbol(void)                                    const { return this.GetProperty(PATTERN_PROP_SYMBOL);                            }
   string            Name(void)                                      const { return this.GetProperty(PATTERN_PROP_NAME);                              }
   
//--- Set the pointer to the (1) pattern bar, (2) "mother" bar data
   void              SetPatternBar(CBar *bar)                              { this.m_bar_pattern=bar;                                                  }
   void              SetMotherBarData(MqlRates &data);
//--- Set the (1) "mother" bar OHLC and (2) the number of bars in nested formations
   void              SetMotherBarOpen(const double open)                   { this.m_mother_bar_prop.open=open;                                        }
   void              SetMotherBarHigh(const double high)                   { this.m_mother_bar_prop.high=high;                                        }
   void              SetMotherBarLow(const double low)                     { this.m_mother_bar_prop.low=low;                                          }
   void              SetMotherBarClose(const double close)                 { this.m_mother_bar_prop.close=close;                                      }
   void              SetBarsInNestedFormations(const int bars)             { this.m_bars_formation=bars;                                              }
   
//--- Return the pointer to the (1) pattern bar, (2) time, (3 - 6) "mother" bar OHLC and (7) the number of bars in nested formations
   CBar             *PatternBar(void)                                const { return this.m_bar_pattern;                                               }
   datetime          MotherBarTime(void)                             const { return (datetime)this.GetProperty(PATTERN_PROP_MOTHERBAR_TIME);          }
   double            MotherBarOpen(void)                             const { return this.m_mother_bar_prop.open;                                      }
   double            MotherBarHigh(void)                             const { return this.m_mother_bar_prop.high;                                      }
   double            MotherBarLow(void)                              const { return this.m_mother_bar_prop.low;                                       }
   double            MotherBarClose(void)                            const { return this.m_mother_bar_prop.close;                                     }
   int               BarsInNestedFormations(void)                    const { return this.m_bars_formation;                                            }
   
//+------------------------------------------------------------------+
//| Descriptions of pattern object properties                        |
//+------------------------------------------------------------------+
//--- Get description of pattern (1) integer, (2) real and (3) string property
   string            GetPropertyDescription(ENUM_PATTERN_PROP_INTEGER property);
   string            GetPropertyDescription(ENUM_PATTERN_PROP_DOUBLE property);
   string            GetPropertyDescription(ENUM_PATTERN_PROP_STRING property);

//--- Return description of the pattern (1) status, (2) type and (3) direction
   virtual string    StatusDescription(void) const { return NULL; }
   virtual string    TypeDescription(void)   const { return NULL; }
   string            DirectDescription(void) const;
//--- Display the description of the object properties in the journal (full_prop=true - all properties, false - supported ones only - implemented in descendant classes)
   virtual void      Print(const bool full_prop=false,const bool dash=false);
//--- Display a short description of the object in the journal
   virtual void      PrintShort(const bool dash=false,const bool symbol=false);
//--- Return a short name of a pattern object
   virtual string    Header(void);
//+------------------------------------------------------------------+
//| Handle graphical display                                         |
//+------------------------------------------------------------------+
protected:
//--- Set graphical object display colors for the (1) bullish, (2) bearish and (3) bidirectional pattern
   void              SetColorBullish(const color clr)       { this.m_color_bullish=clr;         }
   void              SetColorBearish(const color clr)       { this.m_color_bearish=clr;         }
   void              SetColorBiDirect(const color clr)      { this.m_color_bidirect=clr;        }
//--- Create the (1) info panel and (2) Bitmap object
   bool              CreateInfoPanel(void);
   virtual bool      CreateBitmap(void);
//--- Create the info panel appearance
   virtual void      CreateInfoPanelView(void){}
//--- Calculate the bitmap object (1) width and (2) height
   int               GetBitmapWidth(void);
   int               GetBitmapHeight(void);
   
public:
//--- Remove a graphical object
   bool              DeleteGraphObj(bool redraw=false);
//--- Set graphical object display colors and pattern display color
   void              SetColors(const color color_bullish,const color color_bearish,const color color_bidirect,const bool redraw=false);
//--- Set the flag for drawing pattern labels as dots
   void              SetDrawAsDots(const bool flag)         { this.m_draw_dots=flag;            }
   
//--- Set the background color for the (1) bullish, (2) bearish and (3) bidirectional pattern panel
   void              SetColorPanelBullish(const color clr)  { this.m_color_panel_bullish=clr;   }
   void              SetColorPanelBearish(const color clr)  { this.m_color_panel_bearish=clr;   }
   void              SetColorPanelBiDirect(const color clr) { this.m_color_panel_bidirect=clr;  }
//--- Set the background color for the (1) bullish, (2) bearish and (3) bidirectional pattern panel by setting the values of the RGB color components
   void              SetColorPanelBullish(const uchar R,const uchar G,const uchar B);
   void              SetColorPanelBearish(const uchar R,const uchar G,const uchar B);
   void              SetColorPanelBiDirect(const uchar R,const uchar G,const uchar B);

//--- Draw the pattern icon on the chart
   virtual void      Draw(const bool redraw);
//--- (1) Display, (2) hide the pattern icon on the chart
   void              Show(const bool redraw=false);
   void              Hide(const bool redraw=false);
//--- (1) Display and (2) hide the info panel on the chart
   void              ShowInfoPanel(const int x,const int y,const bool redraw=true);
   void              HideInfoPanel(void);
   
//--- Change the bitmap object (1) width, (2) height and (3) size
   bool              BitmapSetWidth(const int width);
   bool              BitmapSetHeight(const int height);
   bool              BitmapResize(const int w,const int h);
   
//--- Set the (1) chart scale, (2) chart height in pixels, (3) chart maximum and (3) minimum
   void              SetChartScale(const int scale)            { this.m_chart_scale=scale;      }
   void              SetChartHeightInPixels(const int height)  { this.m_chart_height_px=height; }
   void              SetChartPriceMax(const double price)      { this.m_chart_price_max=price;  }
   void              SetChartPriceMin(const double price)      { this.m_chart_price_min=price;  }
//--- Return the (1) chart scale, (2) chart height in pixels, (3) chart maximum and (3) minimum
   int               ChartScale(void)                    const { return this.m_chart_scale;     }
   int               ChartHeightInPixels(void)           const { return this.m_chart_height_px; }
   double            ChartPriceMax(void)                 const { return this.m_chart_price_max; }
   double            ChartPriceMin(void)                 const { return this.m_chart_price_min; }
   
  };


在抽象形态类构造函数中,替换双向图案标签颜色,并设置图像对象指针(NULL)、点绘制标志(true)和嵌套形态数量默认值 为 1(无嵌套形态):

//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CPattern::CPattern(const ENUM_PATTERN_STATUS status,const ENUM_PATTERN_TYPE type,const uint id,const ENUM_PATTERN_DIRECTION direction,const string symbol,const ENUM_TIMEFRAMES timeframe,MqlRates &rates)
  {
//--- Set pattern object properties
   this.m_digits=(int)::SymbolInfoInteger(symbol,SYMBOL_DIGITS);
   this.m_type=OBJECT_DE_TYPE_SERIES_PATTERN; 
   this.SetProperty(PATTERN_PROP_STATUS,status);
   this.SetProperty(PATTERN_PROP_TYPE,type);
   this.SetProperty(PATTERN_PROP_ID,id);
   this.SetProperty(PATTERN_PROP_DIRECTION,direction);
   this.SetProperty(PATTERN_PROP_PERIOD,timeframe);
   this.SetProperty(PATTERN_PROP_TIME,rates.time);
   this.SetProperty(PATTERN_PROP_BAR_PRICE_OPEN,rates.open);
   this.SetProperty(PATTERN_PROP_BAR_PRICE_HIGH,rates.high);
   this.SetProperty(PATTERN_PROP_BAR_PRICE_LOW,rates.low);
   this.SetProperty(PATTERN_PROP_BAR_PRICE_CLOSE,rates.close);
   this.SetProperty(PATTERN_PROP_SYMBOL,symbol);
//--- Create symbol code
   this.m_symbol_code=0;
   for(int i=0;i<(int)symbol.Length();i++)
      this.m_symbol_code+=symbol.GetChar(i);
//--- Pattern code = defining bar time + type + status + pattern direction + timeframe + symbol code
   ulong code=(ulong)rates.time+type+status+direction+timeframe+this.m_symbol_code;
   this.SetProperty(PATTERN_PROP_CODE,code);
//--- Set pattern graphical objects parameters (chart labels)
   this.m_name_graph_obj=::StringFormat("%s_p%lu",this.m_name_program,code);
   this.m_color_bullish=clrBlue;
   this.m_color_bearish=clrRed;
   this.m_color_bidirect=clrMediumSeaGreen;
   if(this.Direction()==PATTERN_DIRECTION_BULLISH)
     {
      this.m_color=this.m_color_bullish;
      this.m_price=rates.low;
     }
   else if(this.Direction()==PATTERN_DIRECTION_BEARISH)
     {
      this.m_color=this.m_color_bearish;
      this.m_price=rates.high;
     }
   else
     {
      this.m_color=this.m_color_bidirect;
      this.m_price=(rates.open+rates.close)/2;
     }
//--- Set base colors of the pattern information panels
   this.m_color_panel_bullish=clrLightGray;
   this.m_color_panel_bearish=clrLightGray;
   this.m_color_panel_bidirect=clrLightGray;
   this.m_form=NULL;
   this.m_bitmap=NULL;
   this.m_draw_dots=true;
   this.m_bars_formation=1;
  }


在类的析构函数中,删除位图对象

//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CPattern::~CPattern(void)
  {
//--- Delete the form object and pattern label on the chart
   if(this.m_form!=NULL)
      delete this.m_form;
   if(this.m_bitmap!=NULL)
      delete this.m_bitmap;
   this.DeleteGraphObj();
  }


在返回整数模式属性描述的方法中,添加显示模式母柱的开启时间

//+------------------------------------------------------------------+
//| Return the description of the pattern integer property           |
//+------------------------------------------------------------------+
string CPattern::GetPropertyDescription(ENUM_PATTERN_PROP_INTEGER property)
  {
   return
     (
      property==PATTERN_PROP_CODE            ?  CMessage::Text(MSG_LIB_TEXT_PATTERN_CODE)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==PATTERN_PROP_TIME            ?  CMessage::Text(MSG_LIB_TEXT_PATTERN_TIME)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::TimeToString(this.GetProperty(property),TIME_DATE|TIME_MINUTES)
         )  :
      property==PATTERN_PROP_MOTHERBAR_TIME  ?  CMessage::Text(MSG_LIB_TEXT_PATTERN_MOTHERBAR_TIME)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::TimeToString(this.GetProperty(property),TIME_DATE|TIME_MINUTES)
         )  :
      property==PATTERN_PROP_STATUS          ?  CMessage::Text(MSG_ORD_STATUS)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+this.StatusDescription()
         )  :
      property==PATTERN_PROP_TYPE            ?  CMessage::Text(MSG_ORD_TYPE)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+this.TypeDescription()
         )  :
      property==PATTERN_PROP_ID              ?  CMessage::Text(MSG_LIB_TEXT_PATTERN_ID)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==PATTERN_PROP_CTRL_OBJ_ID     ?  CMessage::Text(MSG_LIB_TEXT_PATTERN_CTRL_OBJ_ID)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==PATTERN_PROP_DIRECTION       ?  CMessage::Text(MSG_LIB_TEXT_PATTERN_DIRECTION)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+this.DirectDescription()
         )  :
      property==PATTERN_PROP_PERIOD          ?  CMessage::Text(MSG_LIB_TEXT_BAR_PERIOD)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+TimeframeDescription((ENUM_TIMEFRAMES)this.GetProperty(property))
         )  :
      property==PATTERN_PROP_CANDLES         ?  CMessage::Text(MSG_LIB_TEXT_PATTERN_CANDLES)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      ""
     );
  }


实现设置 "母" 柱数据的方法:

//+------------------------------------------------------------------+
//| Set the "mother" bar data                                        |
//+------------------------------------------------------------------+
void CPattern::SetMotherBarData(MqlRates &data)
  {
   this.m_mother_bar_prop.open=data.open;
   this.m_mother_bar_prop.high=data.high;
   this.m_mother_bar_prop.low=data.low;
   this.m_mother_bar_prop.close=data.close;
   this.m_mother_bar_prop.time=data.time;
   this.SetProperty(PATTERN_PROP_MOTHERBAR_TIME,data.time);
  }

该方法接收柱形结构,并将必要的结构字段设置为 m_mother_bar_prop 类成员变量结构的相应结构字段。此外,通过的柱形结构中的时间会被写入母柱的时间属性 - 该值存在于对象属性中,应正确填写。

在图表上显示信息面板的方法接收输入时,需要重新绘制图表 。如果变量值设置为 true,图表将重新绘制

//+------------------------------------------------------------------+
//| Display the info panel on the chart                              |
//+------------------------------------------------------------------+
void CPattern::ShowInfoPanel(const int x,const int y,const bool redraw=true)
  {
//--- If there is no panel object yet, create it
   if(this.m_form==NULL)
      if(!this.CreateInfoPanel())
         return;
//--- Get the chart width and height
   int chart_w=(int)::ChartGetInteger(this.m_chart_id,CHART_WIDTH_IN_PIXELS);
   int chart_h=(int)::ChartGetInteger(this.m_chart_id,CHART_HEIGHT_IN_PIXELS);
//--- Calculate the X and Y coordinates of the panel so that it does not go beyond the chart
   int cx=(x+this.m_form.Width() >chart_w-1 ? chart_w-1-this.m_form.Width()  : x);
   int cy=(y+this.m_form.Height()>chart_h-1 ? chart_h-1-this.m_form.Height() : y);
//--- Set the calculated coordinates and display the panel
   if(this.m_form.SetCoordX(cx) && this.m_form.SetCoordY(cy))
      this.m_form.Show();
   if(redraw)
      ::ChartRedraw(this.m_chart_id);
  }

这样做的目的是,当鼠标光标悬停在有形态的柱形上时,带有形态描述的面板就会立即出现。如果该柱形上有多个形态,那么在图表上显示所有信息面板时,该变量的值都应设置为 false,只有最后一个形态的值设置为 true。在这种情况下,只有在显示最后一个面板(而不是每个面板)后才会重新绘制图表。

由于在图表上显示图案有两种方式 - 点和位图对象,因此让我们最终确定在图表上显示形态图标的方法:

//+------------------------------------------------------------------+
//| Display the pattern icon on the chart                            |
//+------------------------------------------------------------------+
void CPattern::Show(const bool redraw=false)
  {
   if(this.m_draw_dots)
     {
      ::ObjectSetInteger(this.m_chart_id,this.m_name_graph_obj,OBJPROP_TIMEFRAMES,OBJ_ALL_PERIODS);
      return;
     }
   if(this.m_bitmap!=NULL)
      this.m_bitmap.Show();
   if(redraw)
      ::ChartRedraw(this.m_chart_id);
  }

如果我们使用点,那么就像之前一样打开图形对象的可见性。如果我们使用位图对象,则调用其 Show() 方法(如果存在)。因此,如果设置了重绘标记,就会更新图表。

同样,改进隐藏图表上形态图标的方法:

//+------------------------------------------------------------------+
//| Hide the pattern icon on the chart                               |
//+------------------------------------------------------------------+
void CPattern::Hide(const bool redraw=false)
  {
   if(this.m_draw_dots)
     {
      ::ObjectSetInteger(this.m_chart_id,this.m_name_graph_obj,OBJPROP_TIMEFRAMES,OBJ_NO_PERIODS);
      return;
     }
   if(this.m_bitmap!=NULL)
      this.m_bitmap.Hide();
   if(redraw)
      ::ChartRedraw(this.m_chart_id);
  }


计算位图对象宽度的方法:

//+------------------------------------------------------------------+
//| Calculate the bitmap object width                                |
//+------------------------------------------------------------------+
int CPattern::GetBitmapWidth(void)
  {
//--- Calculate the width of the chart candles in pixels
   int px=int(1<<this.m_chart_scale);
//--- Calculate the number of bars that make up the pattern
   int num_bars=::Bars(this.Symbol(),this.Timeframe(),this.MotherBarTime(),this.Time());
   if(num_bars==0)
      num_bars=(int)this.Candles();
//--- Calculate and return the width of the bitmap object
   return (px*num_bars*2)-px+1;
  }

根据图表比例,我们以像素为单位计算柱形的宽度。然后,我们以柱数为单位获取形态的宽度,再根据这两个值计算并返回形态对象所需的宽度。


计算绘图对象高度的方法:

//+------------------------------------------------------------------+
//| Calculate the bitmap object height                               |
//+------------------------------------------------------------------+
int CPattern::GetBitmapHeight(void)
  {
//--- Calculate the chart price range and pattern price range
   double chart_price_range=this.m_chart_price_max-this.m_chart_price_min;
   double patt_price_range=this.MotherBarHigh()-this.MotherBarLow();
//--- Using the calculated price ranges, calculate and return the height of the bitmap object
   return (int)ceil(patt_price_range*this.m_chart_height_px/chart_price_range)+8;
  }

在这里,我们可以得到从图表最高价到最低价的图表价格范围,以及从高位母柱到低位母柱的形态价格范围。然后以像素为单位计算一个范围与另一个范围的比率,并返回得到的位图对象高度,在此基础上增加 8 个像素 - 顶部 4 个,底部 4 个。

在 "Pin Bar" 形态构造函数中,设置嵌套形态的数量等于形态柱的值(1):

//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CPatternPinBar::CPatternPinBar(const uint id,const string symbol,const ENUM_TIMEFRAMES timeframe,MqlRates &rates,const ENUM_PATTERN_DIRECTION direct) : 
   CPattern(PATTERN_STATUS_PA,PATTERN_TYPE_PIN_BAR,id,direct,symbol,timeframe,rates)
  {
   this.SetProperty(PATTERN_PROP_NAME,"Pin Bar");
   this.SetProperty(PATTERN_PROP_CANDLES,1);
   this.m_bars_formation=(int)this.GetProperty(PATTERN_PROP_CANDLES);
  }


现在,让我们为新的 "Inside Bar" 价格行为形态创建类。

"孕线"形态类

在编写抽象模式和 "Pin Bar" 形态类的同一文件中创建新的 Inside Bar 形态类。基本上,我们只需要编写(覆盖)形态的一些虚拟方法和属性值。该类应从抽象模式对象类派生

//+------------------------------------------------------------------+
//| "Inside Bar" pattern class                                       |
//+------------------------------------------------------------------+
class CPatternInsideBar : public CPattern
  {
protected:
//--- Create the (1) image object, the appearance of the (2) info panel and (3) the bitmap object
   virtual bool      CreateBitmap(void);
   virtual void      CreateInfoPanelView(void);
   void              CreateBitmapView(void);
public:
//--- Return the flag of the pattern supporting the specified property
   virtual bool      SupportProperty(ENUM_PATTERN_PROP_INTEGER property)   { return true; }
   virtual bool      SupportProperty(ENUM_PATTERN_PROP_DOUBLE property)    { return true; }
   virtual bool      SupportProperty(ENUM_PATTERN_PROP_STRING property)    { return true; }
   
//--- Return description of the pattern (1) status and (2) type
   virtual string    StatusDescription(void) const { return CMessage::Text(MSG_LIB_TEXT_PATTERN_STATUS_PA);       }
   virtual string    TypeDescription(void)   const { return CMessage::Text(MSG_LIB_TEXT_PATTERN_TYPE_INSIDE_BAR); }

//--- Draw the pattern icon on the chart
   virtual void      Draw(const bool redraw);

//--- Constructor
                     CPatternInsideBar(const uint id,const string symbol,const ENUM_TIMEFRAMES timeframe,MqlRates &rates,const ENUM_PATTERN_DIRECTION direct);
  };


在类构造函数中,设置形态名称、形态柱数(等于 2)以及嵌套构造的柱数(等于 2)- 无嵌套构造:

//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CPatternInsideBar::CPatternInsideBar(const uint id,const string symbol,const ENUM_TIMEFRAMES timeframe,MqlRates &rates,const ENUM_PATTERN_DIRECTION direct) : 
   CPattern(PATTERN_STATUS_PA,PATTERN_TYPE_INSIDE_BAR,id,direct,symbol,timeframe,rates)
  {
   this.SetProperty(PATTERN_PROP_NAME,"Inside Bar");
   this.SetProperty(PATTERN_PROP_CANDLES,2);
   this.m_bars_formation=(int)this.GetProperty(PATTERN_PROP_CANDLES);
  }


定义信息面板外观的虚拟方法:

//+------------------------------------------------------------------+
//| Create the info panel appearance                                 |
//+------------------------------------------------------------------+
void CPatternInsideBar::CreateInfoPanelView(void)
  {
//--- If the form object is not created, leave
   if(this.m_form==NULL)
      return;
//--- Declare the array for the initial and final colors of the gradient fill
   color clr[2]={this.m_form.ChangeColorLightness(this.m_color_panel_bidirect,-5),this.m_form.ChangeColorLightness(this.m_color_panel_bidirect,15)};
   
//--- Set the background and form frame colors
   this.m_form.SetBackgroundColor(this.m_color_panel_bidirect,true);
   this.m_form.SetBorderColor(clrGray,true);
//--- Create strings to describe the pattern, its parameters and search criteria
   string name=::StringFormat("Inside Bar (%lu bars)",int(this.Time()-this.MotherBarTime())/::PeriodSeconds(this.Timeframe())+1);
   string param=this.DirectDescription();//::StringFormat("%s (%.2f/%.2f/%.2f)",this.DirectDescription(),this.GetProperty(PATTERN_PROP_RATIO_BODY_TO_CANDLE_SIZE_CRITERION),this.GetProperty(PATTERN_PROP_RATIO_LARGER_SHADOW_TO_CANDLE_SIZE_CRITERION),this.GetProperty(PATTERN_PROP_RATIO_SMALLER_SHADOW_TO_CANDLE_SIZE_CRITERION));
//--- Set the coordinates of the panel and calculate its width and height depending on the size of the texts placed on the panel
   int x=3;
   int y=20;
   int w=4+(::fmax(20+this.m_form.TextWidth(name),::fmax(x+this.m_form.TextWidth(param),x+this.m_form.TextWidth(::TimeToString(this.Time())))));
   int h=2+(20+this.m_form.TextHeight(this.DirectDescription())+this.m_form.TextHeight(::TimeToString(this.Time())));
//--- Set the width and height of the panel according to the calculated values
   this.m_form.SetWidth(w);
   this.m_form.SetHeight(h);
//--- Depending on the chart size and coordinates, we calculate the coordinates of the panel so that it does not go beyond the chart
   int chart_w=(int)::ChartGetInteger(this.m_chart_id,CHART_WIDTH_IN_PIXELS);
   int chart_h=(int)::ChartGetInteger(this.m_chart_id,CHART_HEIGHT_IN_PIXELS);
   int cx=(this.m_form.RightEdge() >chart_w-1 ? chart_w-1-this.m_form.Width()  : this.m_form.CoordX());
   int cy=(this.m_form.BottomEdge()>chart_h-1 ? chart_h-1-this.m_form.Height() : this.m_form.CoordY());
   this.m_form.SetCoordX(cx);
   this.m_form.SetCoordY(cy);
//--- Fill the background with a gradient color
   this.m_form.Erase(clr,200,true,false);
//--- Draw the panel frame, an icon with (i), draw the header text with the proportions of a candle and separate the header with a horizontal line
   this.m_form.DrawFrameSimple(0,0,this.m_form.Width(),this.m_form.Height(),1,1,1,1,this.m_form.BorderColor(),200);
   this.m_form.DrawIconInfo(1,1,200);
   this.m_form.Text(20,3,name,clrBlack,200);
   this.m_form.DrawLine(1,18,this.m_form.Width()-1,18,clrDarkGray,250);
//--- Under the horizontal line, enter the pattern description with its search criteria and the date of the pattern-defining bar
   y=20;
   this.m_form.Text(x,y,param,clrBlack,200);
   y+=this.m_form.TextHeight(::TimeToString(this.Time()));
   this.m_form.Text(x,y,::TimeToString(this.Time()),clrBlack,200);
//--- Update the panel while redrawing the chart
   this.m_form.Update(true);
  }

对于每种形态,我们都将创建自己的虚拟方法来创建信息面板的外观,因为每种形态都有自己的一组重要参数,这些参数可以显示在面板上,以便对形态进行更直观的描述。


在图表上绘制形态图标的方法:

//+------------------------------------------------------------------+
//| Draw the pattern icon on the chart                               |
//+------------------------------------------------------------------+
void CPatternInsideBar::Draw(const bool redraw)
  {
//--- If the flag for drawing with dots is set, call the parent class method and leave
   if(this.m_draw_dots)
     {
      CPattern::Draw(redraw);
      return;
     }
//--- If the bitmap object has not yet been created, create it
   if(this.m_bitmap==NULL)
     {
      if(!this.CreateBitmap())
         return;
     }
//--- display
   this.Show(redraw);
  }

方法的逻辑在注释中有所描述。父类方法在图表上创建并绘制形态标签(点)。因此,如果设置了绘制点的标志,就会使用父类方法绘制点。
否则,将创建位图对象并显示在图表上。


创建位图对象的方法:

//+------------------------------------------------------------------+
//| Create the bitmap object                                         |
//+------------------------------------------------------------------+
bool CPatternInsideBar::CreateBitmap(void)
  {
//--- If the bitmap object has already been created earlier, return 'true'
   if(this.m_bitmap!=NULL)
      return true;
//--- Calculate the object coordinates and dimensions
   datetime time=this.MotherBarTime();
   double   price=(this.MotherBarHigh()+this.MotherBarLow())/2;
   int      w=this.GetBitmapWidth();
   int      h=this.GetBitmapHeight();
//--- Create the Bitmap object
   this.m_bitmap=this.CreateBitmap(this.ID(),this.GetChartID(),0,this.Name(),time,price,w,h,this.m_color_bidirect);
   if(this.m_bitmap==NULL)
      return false;
//--- Set the object origin to its center and remove the tooltip
   ::ObjectSetInteger(this.GetChartID(),this.m_bitmap.NameObj(),OBJPROP_ANCHOR,ANCHOR_CENTER);
   ::ObjectSetString(this.GetChartID(),this.m_bitmap.NameObj(),OBJPROP_TOOLTIP,"\n");
//--- Draw the bitmap object appearance
   this.CreateBitmapView();
   return true;
  }


创建位图对象外观的方法:

//+------------------------------------------------------------------+
//| Create the bitmap object appearance                              |
//+------------------------------------------------------------------+
void CPatternInsideBar::CreateBitmapView(void)
  {
   this.m_bitmap.Erase(CLR_CANV_NULL,0);
   int x=this.m_bitmap.Width()/2-int(1<<this.m_chart_scale)/2;
   this.m_bitmap.DrawRectangleFill(x,0,this.m_bitmap.Width()-1,this.m_bitmap.Height()-1,this.m_color_bidirect,80);
   this.m_bitmap.DrawRectangle(x,0,this.m_bitmap.Width()-1,this.m_bitmap.Height()-1,clrGray);
   this.m_bitmap.Update(false);
  }

在此,用透明色填充画布,计算勾勒形态柱的矩形的初始 X 坐标。然后,以计算出的 X 坐标为起点,用双向形态设置的颜色和 80 的不透明度填充矩形区域,并用灰色矩形勾勒出填充区域的轮廓。完成后,更新资源,无需重新绘制图表。


每个搜索到的形态及其参数都由形态管理类对象控制和处理。当权限被设置为搜索具有指定类型和指定形态搜索参数的形态时,就会创建一个这样的对象。在同一个类中,我们需要读取图表窗口的属性 - 这样就可以在创建控件对象时只读取一次,然后将读取的图表参数写入创建的形态对象。需要使用图表属性来确保每个单独形态的信息面板在显示时不会超出图表边缘。如果每次创建新的形态对象时都读取图表参数,将非常耗费资源,毕竟一个时间序列中有许多形态。此外,如果只需读取一次参数,然后在每个创建的形态中使用,为什么要每次都读取相同的参数呢?在创建勾勒形态柱的位图对象时,我们还需要图表参数。同样,每次都阅读相同的图表尺寸也不是最佳选择。因此,我们只有在创建形态控制对象时才会读取它们。但这里有一个细微差别:在改变图表尺寸时,所有先前读取的数据仍与已接收的数据相同。它们需要再次从图表中获取,并记录在每个形态的属性中。我们将在后续文章中完成这一点。

形态控制对象类位于 MQL5\Include\DoEasy\Objects\Series\SeriesDE.mqh 中。我们将对其进行必要的修改

//+------------------------------------------------------------------+
//| Abstract pattern control class                                   |
//+------------------------------------------------------------------+
class CPatternControl : public CBaseObjExt
  {
private:
   ENUM_TIMEFRAMES   m_timeframe;                                                // Pattern timeseries chart period
   string            m_symbol;                                                   // Pattern timeseries symbol
   double            m_point;                                                    // Symbol Point
   bool              m_used;                                                     // Pattern use flag
   bool              m_drawing;                                                  // Flag for drawing the pattern icon on the chart
   bool              m_draw_dots;                                                // Flag for drawing the pattern icon on the chart with dots
//--- Handled pattern
   ENUM_PATTERN_TYPE m_type_pattern;                                             // Pattern type
protected:
//--- Candle proportions
   double            m_ratio_body_to_candle_size;                                // Percentage ratio of the candle body to the full size of the candle
   double            m_ratio_larger_shadow_to_candle_size;                       // Percentage ratio of the size of the larger shadow to the size of the candle
   double            m_ratio_smaller_shadow_to_candle_size;                      // Percentage ratio of the size of the smaller shadow to the size of the candle
   ulong             m_object_id;                                                // Unique object code based on pattern search criteria
//--- List views
   CArrayObj        *m_list_series;                                              // Pointer to the timeseries list
   CArrayObj        *m_list_all_patterns;                                        // Pointer to the list of all patterns
   CPattern          m_pattern_instance;                                         // Pattern object for searching by property
   ulong             m_symbol_code;                                              // Chart symbol name as a number
   int               m_chart_scale;                                              // Chart scale
   int               m_chart_height_px;                                          // Height of the chart in pixels
   double            m_chart_price_max;                                          // Chart maximum
   double            m_chart_price_min;                                          // Chart minimum

//--- (1) Search for a pattern, return direction (or -1 if no pattern is found),
//--- (2) create a pattern with a specified direction,
//--- (3) create and return a unique pattern code,
//--- (4) return the list of patterns managed by the object
   virtual ENUM_PATTERN_DIRECTION FindPattern(const datetime series_bar_time,const uint min_body_size,MqlRates &mother_bar_data) const
                                    { return WRONG_VALUE;   }
   virtual CPattern *CreatePattern(const ENUM_PATTERN_DIRECTION direction,const uint id,CBar *bar){ return NULL;                       }
   virtual ulong     GetPatternCode(const ENUM_PATTERN_DIRECTION direction,const datetime time) const { return 0;                      }
   virtual CArrayObj*GetListPatterns(void)                                       { return NULL;                                        }

//--- Create object ID based on pattern search criteria
   virtual ulong     CreateObjectID(void)                                        { return 0;                                           }

//--- Write bar data to the structure
   void              SetBarData(CBar *bar,MqlRates &rates) const
                       {
                        if(bar==NULL)
                           return;
                        rates.open=bar.Open();
                        rates.high=bar.High();
                        rates.low=bar.Low();
                        rates.close=bar.Close();
                        rates.time=bar.Time();
                       }

public:
//--- Returns (1) itself, (2) pattern usage flag
   CPatternControl  *GetObject(void)                                             { return &this;                                       }
//--- (1) Set and (2) return the pattern usage flag
   void              SetUsed(const bool flag)                                    { this.m_used=flag;                                   }
   bool              IsUsed(void)                                          const { return this.m_used;                                 }
//--- (1) Set and (2) return the pattern drawing flag
   void              SetDrawing(const bool flag)                                 { this.m_drawing=flag;                                }
   bool              IsDrawing(void)                                       const { return this.m_drawing;                              }
//--- (1) Set and (2) return the flag for drawing pattern icons as dots
   void              SetDrawingAsDots(const bool flag,const bool redraw);
   bool              IsDrawingAsDots(void)                                 const { return this.m_draw_dots;                            }

//--- Set the necessary percentage ratio of the candle body to the full size of the candle,
//--- size of the (2) upper and (3) lower shadow to the candle size
   void              SetRatioBodyToCandleSizeValue(const double value)           { this.m_ratio_body_to_candle_size=value;             }
   void              SetRatioLargerShadowToCandleSizeValue(const double value)   { this.m_ratio_larger_shadow_to_candle_size=value;    }
   void              SetRatioSmallerShadowToCandleSizeValue(const double value)  { this.m_ratio_smaller_shadow_to_candle_size=value;   }
//--- Return the percentage ratio (1) of the candle body to the full size of the candle,
//--- size of the (2) upper and (3) lower shadow to the candle size
   double            RatioBodyToCandleSizeValue(void)                      const { return this.m_ratio_body_to_candle_size;            }
   double            RatioLargerShadowToCandleSizeValue(void)              const { return this.m_ratio_larger_shadow_to_candle_size;   }
   double            RatioSmallerShadowToCandleSizeValue(void)             const { return this.m_ratio_smaller_shadow_to_candle_size;  }

//--- Return object ID based on pattern search criteria
   virtual ulong     ObjectID(void)                                        const { return this.m_object_id;                            }

//--- Return pattern (1) type, (2) timeframe, (3) symbol, (4) symbol Point, (5) symbol code
   ENUM_PATTERN_TYPE TypePattern(void)                                     const { return this.m_type_pattern;                         }
   ENUM_TIMEFRAMES   Timeframe(void)                                       const { return this.m_timeframe;                            }
   string            Symbol(void)                                          const { return this.m_symbol;                               }
   double            Point(void)                                           const { return this.m_point;                                }
   ulong             SymbolCode(void)                                      const { return this.m_symbol_code;                          }
   
//--- Set the (1) chart scale, (2) chart height in pixels, (3) chart maximum and (3) minimum
   void              SetChartScale(const int scale)                              { this.m_chart_scale=scale;                           }
   void              SetChartHeightInPixels(const int height)                    { this.m_chart_height_px=height;                      }
   void              SetChartPriceMax(const double price)                        { this.m_chart_price_max=price;                       }
   void              SetChartPriceMin(const double price)                        { this.m_chart_price_min=price;                       }
//--- Return the (1) chart scale, (2) chart height in pixels, (3) chart maximum and (3) minimum
   int               ChartScale(void)                                      const { return this.m_chart_scale;                          }
   int               ChartHeightInPixels(void)                             const { return this.m_chart_height_px;                      }
   double            ChartPriceMax(void)                                   const { return this.m_chart_price_max;                      }
   double            ChartPriceMin(void)                                   const { return this.m_chart_price_min;                      }

//--- Compare CPatternControl objects by all possible properties
   virtual int       Compare(const CObject *node,const int mode=0) const;

//--- Search for patterns and add found ones to the list of all patterns
   virtual int       CreateAndRefreshPatternList(const uint min_body_size);
//--- Display patterns on the chart
   void              DrawPatterns(const bool redraw=false);
   
//--- Protected parametric constructor
protected:
                     CPatternControl(const string symbol,const ENUM_TIMEFRAMES timeframe,const ENUM_PATTERN_STATUS status,const ENUM_PATTERN_TYPE type,CArrayObj *list_series,CArrayObj *list_patterns);
  };

大多数方法无需介绍 - 其目的已在注释中说明,这些方法只设置或返回类对象的相应参数。现在,我们将把 MqlRates 结构的链接传递给形态搜索方法,并在其中设置母柱的数据。要设置这些数据,需要编写 SetBarData() 方法,该方法接收指向柱形对象的指针和指向 MqlRates 类型变量的链接。变量字段包含柱形对象的相应属性。CreateAndRefreshPatternList() 方法将接收最小烛体尺寸。随后,我将在形态控制对象中添加对该值的设置。该值将传递给形态搜索和更新方法。重点是在搜索形态时跳过尺寸小于该值的柱形。目前,我们将在此处传递 0,从而禁用该过滤器。


在类构造函数中,计算图表数据并将其写入新类变量

//+------------------------------------------------------------------+
//| CPatternControl::Protected parametric constructor                |
//+------------------------------------------------------------------+
CPatternControl::CPatternControl(const string symbol,const ENUM_TIMEFRAMES timeframe,const ENUM_PATTERN_STATUS status,const ENUM_PATTERN_TYPE type,CArrayObj *list_series,CArrayObj *list_patterns) :
  m_ratio_body_to_candle_size(30),m_ratio_larger_shadow_to_candle_size(60),m_ratio_smaller_shadow_to_candle_size(30),m_used(true),m_drawing(true)
  {
   this.m_type=OBJECT_DE_TYPE_SERIES_PATTERN_CONTROL;
   this.m_type_pattern=type;
   this.m_symbol=(symbol==NULL || symbol=="" ? ::Symbol() : symbol);
   this.m_timeframe=(timeframe==PERIOD_CURRENT ? ::Period() : timeframe);
   this.m_point=::SymbolInfoDouble(this.m_symbol,SYMBOL_POINT);
   this.m_object_id=0;
   this.m_list_series=list_series;
   this.m_list_all_patterns=list_patterns;
   for(int i=0;i<(int)this.m_symbol.Length();i++)
      this.m_symbol_code+=this.m_symbol.GetChar(i);
   this.m_chart_scale=(int)::ChartGetInteger(this.m_chart_id,CHART_SCALE);
   this.m_chart_height_px=(int)::ChartGetInteger(this.m_chart_id,CHART_HEIGHT_IN_PIXELS);
   this.m_chart_price_max=::ChartGetDouble(this.m_chart_id,CHART_PRICE_MAX);
   this.m_chart_price_min=::ChartGetDouble(this.m_chart_id,CHART_PRICE_MIN);
  }


对搜索形态并将找到的形态添加到所有形态列表中的方法进行必要的改进

//+------------------------------------------------------------------+
//| CPatternControl::Search for patterns and add                     |
//| found ones to the list of all patterns                           |
//+------------------------------------------------------------------+
int CPatternControl::CreateAndRefreshPatternList(const uint min_body_size)
  {
//--- If not used, leave
   if(!this.m_used)
      return 0;
//--- Reset the timeseries event flag and clear the list of all timeseries pattern events
   this.m_is_event=false;
   this.m_list_events.Clear();
//--- Get the opening date of the last (current) bar
   datetime time_open=0;
   if(!::SeriesInfoInteger(this.Symbol(),this.Timeframe(),SERIES_LASTBAR_DATE,time_open))
      return 0;
//--- Get a list of all bars in the timeseries except the current one
   CArrayObj *list=CSelect::ByBarProperty(this.m_list_series,BAR_PROP_TIME,time_open,LESS);
   if(list==NULL || list.Total()==0)
      return 0;
//--- "Mother" bar data structure
   MqlRates pattern_mother_bar_data={};
//--- Sort the resulting list by bar opening time
   list.Sort(SORT_BY_BAR_TIME);
//--- In a loop from the latest bar,
   for(int i=list.Total()-1;i>=0;i--)
     {
      //--- get the next bar object from the list
      CBar *bar=list.At(i);
      if(bar==NULL)
         continue;
      //--- look for a pattern relative to the received bar
      ENUM_PATTERN_DIRECTION direction=this.FindPattern(bar.Time(),min_body_size,pattern_mother_bar_data);
      //--- If there is no pattern, go to the next bar
      if(direction==WRONG_VALUE)
         continue;
         
      //--- Pattern found on the current bar of the loop
      //--- unique pattern code = candle opening time + type + status + pattern direction + timeframe + timeseries symbol
      ulong code=this.GetPatternCode(direction,bar.Time());
      //--- Set the pattern code to the sample
      this.m_pattern_instance.SetProperty(PATTERN_PROP_CODE,code);
      //--- Sort the list of all patterns by the unique pattern code
      this.m_list_all_patterns.Sort(SORT_BY_PATTERN_CODE);
      //--- search for a pattern in the list using a unique code
      int index=this.m_list_all_patterns.Search(&this.m_pattern_instance);
      //--- If there is no pattern equal to the sample in the list of all patterns
      if(index==WRONG_VALUE)
        {
         //--- Create the pattern object
         CPattern *pattern=this.CreatePattern(direction,this.m_list_all_patterns.Total(),bar);
         if(pattern==NULL)
            continue;
         //--- Sort the list of all patterns by time and insert the pattern into the list by its time
         this.m_list_all_patterns.Sort(SORT_BY_PATTERN_TIME);
         if(!this.m_list_all_patterns.InsertSort(pattern))
           {
            delete pattern;
            continue;
           }
         //--- Add the pattern to the list of bar object patterns
         bar.AddPattern(pattern.TypePattern());
         //--- Add the pointer to the bar the pattern object is found on, together with the mother bar data
         pattern.SetPatternBar(bar);
         pattern.SetMotherBarData(pattern_mother_bar_data);
         //--- set the chart data to the pattern object
         pattern.SetChartHeightInPixels(this.m_chart_height_px);
         pattern.SetChartScale(this.m_chart_scale);
         pattern.SetChartPriceMax(this.m_chart_price_max);
         pattern.SetChartPriceMin(this.m_chart_price_min);
         //--- If the drawing flag is set, draw the pattern label on the chart
         if(this.m_drawing)
            pattern.Draw(false);
        }
     }
//--- Sort the list of all patterns by time and return the total number of patterns in the list
   this.m_list_all_patterns.Sort(SORT_BY_PATTERN_TIME);
   return m_list_all_patterns.Total();
  }

现在,该方法接收到所需形态柱体的最小尺寸。将大小和母柱结构链接传递给形态搜索方法,母柱结构包含柱参数。如果找到了形态,则将找到的形态类型写入找到形态的柱形对象。同时,在柱形上找到的形态对象会接收柱形指针、母柱数据和图表数据。


设置将形态图标绘制为点的标志的方法:

//+------------------------------------------------------------------+
//| Set the flag for drawing pattern icons as dots                   |
//+------------------------------------------------------------------+
void CPatternControl::SetDrawingAsDots(const bool flag,const bool redraw)
  {
   this.m_draw_dots=flag;
//--- Get a list of patterns controlled by the control object
   CArrayObj *list=this.GetListPatterns();
   if(list==NULL || list.Total()==0)
      return;
//--- In a loop by the list of patterns,
   for(int i=list.Total()-1;i>=0;i--)
     {
      //--- get the next pattern object
      CPattern *obj=list.At(i);
      if(obj==NULL)
         continue;
      //--- Set the flag value. If 'false', remove the pattern dot object
      obj.SetDrawAsDots(flag);
      if(!flag)
         obj.DeleteGraphObj();
      //--- Display the pattern label on the chart if the flag is 'true'
      else
         obj.Draw(false);
     }
//--- At the end of the cycle, redraw the chart if the flag is set
   if(redraw)
      ::ChartRedraw(this.m_chart_id);
  }

方法逻辑已在代码注释中详细说明。在这里,我们可以获得由该控制对象管理的形态列表。在每个形态对象中,我们都要输入用点绘制的标志。如果标志重置,我们就需要删除之前绘制的点,如果标志设置,我们就应该绘制它。在处理列表中所有形态的循环结束时,如果向该方法传递了重绘标记,图表将被重绘。


接下来,我们需要修改 Pin Bar 形态控制类。在形态搜索方法中添加 MqlRates 变量,以设置母柱数据:

//+------------------------------------------------------------------+
//| Pin Bar pattern control class                                    |
//+------------------------------------------------------------------+
class CPatternControlPinBar : public CPatternControl
  {
protected:
//--- (1) Search for a pattern, return direction (or -1),
//--- (2) create a pattern with a specified direction,
//--- (3) create and return a unique pattern code
//--- (4) return the list of patterns managed by the object
   virtual ENUM_PATTERN_DIRECTION FindPattern(const datetime series_bar_time,const uint min_body_size,MqlRates &mother_bar_data) const;
   virtual CPattern *CreatePattern(const ENUM_PATTERN_DIRECTION direction,const uint id,CBar *bar);
   virtual ulong     GetPatternCode(const ENUM_PATTERN_DIRECTION direction,const datetime time) const
                       {
                        //--- unique pattern code = candle opening time + type + status + pattern direction + timeframe + timeseries symbol
                        return(time+PATTERN_TYPE_PIN_BAR+PATTERN_STATUS_PA+direction+this.Timeframe()+this.m_symbol_code);
                       }
   virtual CArrayObj*GetListPatterns(void);
//--- Create object ID based on pattern search criteria
   virtual ulong     CreateObjectID(void);

public:
//--- Parametric constructor
                     CPatternControlPinBar(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                           CArrayObj *list_series,CArrayObj *list_patterns,
                                           const double ratio_body_to_candle_size,
                                           const double ratio_larger_shadow_to_candle_size,
                                           const double ratio_smaller_shadow_to_candle_size) :
                        CPatternControl(symbol,timeframe,PATTERN_STATUS_PA,PATTERN_TYPE_PIN_BAR,list_series,list_patterns)
                       {
                        this.m_ratio_body_to_candle_size=ratio_body_to_candle_size;
                        this.m_ratio_larger_shadow_to_candle_size=ratio_larger_shadow_to_candle_size;
                        this.m_ratio_smaller_shadow_to_candle_size=ratio_smaller_shadow_to_candle_size;
                        this.m_object_id=this.CreateObjectID();
                       }
  };


在以指定方向创建形态的方法中,向 MqlRates 变量添加写入柱形数据

//+---------------------------------------------------------------------+
//| CPatternControlPinBar::Create a pattern with a specified direction  |
//+---------------------------------------------------------------------+
CPattern *CPatternControlPinBar::CreatePattern(const ENUM_PATTERN_DIRECTION direction,const uint id,CBar *bar)
  {
//--- If invalid indicator is passed to the bar object, return NULL
   if(bar==NULL)
      return NULL;
//--- Fill the MqlRates structure with bar data
   MqlRates rates={0};
   this.SetBarData(bar,rates);
//--- Create a new Pin Bar pattern
   CPatternPinBar *obj=new CPatternPinBar(id,this.Symbol(),this.Timeframe(),rates,direction);
   if(obj==NULL)
      return NULL;
//--- set the proportions of the candle the pattern was found on to the properties of the created pattern object
   obj.SetProperty(PATTERN_PROP_RATIO_BODY_TO_CANDLE_SIZE,bar.RatioBodyToCandleSize());
   obj.SetProperty(PATTERN_PROP_RATIO_LOWER_SHADOW_TO_CANDLE_SIZE,bar.RatioLowerShadowToCandleSize());
   obj.SetProperty(PATTERN_PROP_RATIO_UPPER_SHADOW_TO_CANDLE_SIZE,bar.RatioUpperShadowToCandleSize());
//--- set the search criteria of the candle the pattern was found on to the properties of the created pattern object
   obj.SetProperty(PATTERN_PROP_RATIO_BODY_TO_CANDLE_SIZE_CRITERION,this.RatioBodyToCandleSizeValue());
   obj.SetProperty(PATTERN_PROP_RATIO_LARGER_SHADOW_TO_CANDLE_SIZE_CRITERION,this.RatioLargerShadowToCandleSizeValue());
   obj.SetProperty(PATTERN_PROP_RATIO_SMALLER_SHADOW_TO_CANDLE_SIZE_CRITERION,this.RatioSmallerShadowToCandleSizeValue());
//--- Set the control object ID to the pattern object
   obj.SetProperty(PATTERN_PROP_CTRL_OBJ_ID,this.ObjectID());
//--- Return the pointer to a created object
   return obj;
  }

之前,我们在这里逐个输入数据元素。现在,SetBarData() 方法中执行了这种逐元素输入的操作,虽然方法相同,但代码更短。


在搜索形态的方法中,将输入数据添加到发现图案的母柱数据中:

//+------------------------------------------------------------------+
//| CPatternControlPinBar::Search for the pattern                    |
//+------------------------------------------------------------------+
ENUM_PATTERN_DIRECTION CPatternControlPinBar::FindPattern(const datetime series_bar_time,const uint min_body_size,MqlRates &mother_bar_data) const
  {
//--- Get data for one bar by time
   CArrayObj *list=CSelect::ByBarProperty(this.m_list_series,BAR_PROP_TIME,series_bar_time,EQUAL);
//--- If the list is empty, return -1
   if(list==NULL || list.Total()==0)
      return WRONG_VALUE;
//--- he size of the candle body should be less than or equal to RatioBodyToCandleSizeValue() (default 30%) of the entire candle size,
//--- in this case, the body size should not be less than min_body_size
   list=CSelect::ByBarProperty(list,BAR_PROP_RATIO_BODY_TO_CANDLE_SIZE,this.RatioBodyToCandleSizeValue(),EQUAL_OR_LESS);
   list=CSelect::ByBarProperty(list,BAR_PROP_RATIO_BODY_TO_CANDLE_SIZE,min_body_size,EQUAL_OR_MORE);
//--- If the list is empty - there are no patterns, return -1
   if(list==NULL || list.Total()==0)
      return WRONG_VALUE;
      
//--- Define the bullish pattern
//--- The lower shadow should be equal to or greater than RatioLargerShadowToCandleSizeValue() (default 60%) of the entire candle size
   CArrayObj *list_bullish=CSelect::ByBarProperty(list,BAR_PROP_RATIO_LOWER_SHADOW_TO_CANDLE_SIZE,this.RatioLargerShadowToCandleSizeValue(),EQUAL_OR_MORE);
//--- The upper shadow should be less than or equal to RatioSmallerShadowToCandleSizeValue() (default 30%) of the entire candle size
   list_bullish=CSelect::ByBarProperty(list_bullish,BAR_PROP_RATIO_UPPER_SHADOW_TO_CANDLE_SIZE,this.RatioSmallerShadowToCandleSizeValue(),EQUAL_OR_LESS);
//--- If a pattern is found on the bar
   if(list_bullish!=NULL && list_bullish.Total()>0)
     {
      CBar *bar=list.At(list_bullish.Total()-1);
      if(bar!=NULL)
        {
         this.SetBarData(bar,mother_bar_data);
         return PATTERN_DIRECTION_BULLISH;
        }
     }

//--- Define the bearish pattern
//--- The upper shadow should be equal to or greater than RatioLargerShadowToCandleSizeValue() (default 60%) of the entire candle size
   CArrayObj *list_bearish=CSelect::ByBarProperty(list,BAR_PROP_RATIO_UPPER_SHADOW_TO_CANDLE_SIZE,this.RatioLargerShadowToCandleSizeValue(),EQUAL_OR_MORE);
//--- The lower shadow should be less than or equal to RatioSmallerShadowToCandleSizeValue() (default 30%) of the entire candle size
   list_bearish=CSelect::ByBarProperty(list_bearish,BAR_PROP_RATIO_LOWER_SHADOW_TO_CANDLE_SIZE,this.RatioSmallerShadowToCandleSizeValue(),EQUAL_OR_LESS);
//--- If a pattern is found on the bar
   if(list_bearish!=NULL && list_bearish.Total()>0)
     {
      CBar *bar=list.At(list_bearish.Total()-1);
      if(bar!=NULL)
        {
         this.SetBarData(bar,mother_bar_data);
         return PATTERN_DIRECTION_BEARISH;
        }
     }
//--- No patterns found - return -1
   return WRONG_VALUE;
  }

由于 Pin Bar 是单柱形,因此母柱也是该形态的基础柱。


创建管理 Inside Bar 形态的类。该形态的结构是严格定义的,没有其他参数,只是基础柱(右侧)应完全位于母柱(左侧)的内部。没有其他参数。因此,任何 Inside Bar 形态都是一个时间序列上的唯一形态,而 Pin Bar 形态则不同,我们可以设置搜索参数,而且一个时间序列上可以有多个带有不同参数的 Pin Bar 形态。每种形态都有自己的控制对象。考虑到上述情况,对于 Inside Bar(孕线)形态,每个时间序列将始终只创建一个控制对象。

在 "Pin Bar" 控制类之后的同一文件中输入管理 "Inside Bar" 的新类:

//+------------------------------------------------------------------+
//| Inside Bar pattern control class                                 |
//+------------------------------------------------------------------+
class CPatternControlInsideBar : public CPatternControl
  {
private:
//--- Check and return the presence of a pattern on two adjacent bars
   bool              CheckInsideBar(const CBar *bar1,const CBar *bar0) const
                       {
                        //--- If empty bar objects are passed, return 'false'
                        if(bar0==NULL || bar1==NULL)
                           return false;
                        //--- Return the fact that the bar on the right is completely within the dimensions of the bar on the left
                        return(bar0.High()<bar1.High() && bar0.Low()>bar1.Low());
                       }
   bool              FindMotherBar(CArrayObj *list,MqlRates &rates) const
                       {
                        bool res=false;
                        if(list==NULL)
                           return false;
                        //--- In a loop through the list, starting from the bar to the left of the base one
                        for(int i=list.Total()-2;i>0;i--)
                          {
                           //--- Get the pointers to two consecutive bars 
                           CBar *bar0=list.At(i);
                           CBar *bar1=list.At(i-1);
                           if(bar0==NULL || bar1==NULL)
                              return false;
                           //--- If the obtained bars represent a pattern 
                           if(CheckInsideBar(bar1,bar0))
                             {
                              //--- set mother bar data to the MqlRates variable and set 'res' to 'true'
                              this.SetBarData(bar1,rates);
                              res=true;
                             }
                           //--- If there is no pattern, interrupt the loop
                           else
                              break;
                          }
                        //--- return the result
                        return res;
                       }
protected:
//--- (1) Search for a pattern, return direction (or -1),
//--- (2) create a pattern with a specified direction,
//--- (3) create and return a unique pattern code
//--- (4) return the list of patterns managed by the object
   virtual ENUM_PATTERN_DIRECTION FindPattern(const datetime series_bar_time,const uint min_body_size,MqlRates &mother_bar_data) const;
   virtual CPattern *CreatePattern(const ENUM_PATTERN_DIRECTION direction,const uint id,CBar *bar);
   virtual ulong     GetPatternCode(const ENUM_PATTERN_DIRECTION direction,const datetime time) const
                       {
                        //--- unique pattern code = candle opening time + type + status + pattern direction + timeframe + timeseries symbol
                        return(time+PATTERN_TYPE_INSIDE_BAR+PATTERN_STATUS_PA+PATTERN_DIRECTION_BOTH+this.Timeframe()+this.m_symbol_code);
                       }
   virtual CArrayObj*GetListPatterns(void);
//--- Create object ID based on pattern search criteria
   virtual ulong     CreateObjectID(void);

public:
//--- Parametric constructor
                     CPatternControlInsideBar(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                              CArrayObj *list_series,CArrayObj *list_patterns) :
                        CPatternControl(symbol,timeframe,PATTERN_STATUS_PA,PATTERN_TYPE_INSIDE_BAR,list_series,list_patterns)
                       {
                        this.m_ratio_body_to_candle_size=0;
                        this.m_ratio_larger_shadow_to_candle_size=0;
                        this.m_ratio_smaller_shadow_to_candle_size=0;
                        this.m_object_id=this.CreateObjectID();
                       }
  };

该类实际上是上一篇关于库形态的文章中提到的 Pin Bar 形态控制类的复制品。在类的构造函数中,将所有形态搜索条件设置为零,因为在这里不会用到它们。对象 ID 始终为 0,因为这是一个时间序列中的唯一对象:

//+------------------------------------------------------------------+
//| Create object ID based on pattern search criteria                |
//+------------------------------------------------------------------+
ulong CPatternControlInsideBar::CreateObjectID(void)
  {
   return 0;
  }


主要的形态搜索方法有:比较相邻两个柱形是否存在形态的方法搜索母柱的方法

//--- Check and return the presence of a pattern on two adjacent bars
   bool              CheckInsideBar(const CBar *bar1,const CBar *bar0) const
                       {
                        //--- If empty bar objects are passed, return 'false'
                        if(bar0==NULL || bar1==NULL)
                           return false;
                        //--- Return the fact that the bar on the right is completely within the dimensions of the bar on the left
                        return(bar0.High()<bar1.High() && bar0.Low()>bar1.Low());
                       }
   bool              FindMotherBar(CArrayObj *list,MqlRates &rates) const
                       {
                        bool res=false;
                        if(list==NULL)
                           return false;
                        //--- In a loop through the list, starting from the bar to the left of the base one
                        for(int i=list.Total()-2;i>0;i--)
                          {
                           //--- Get the pointers to two consecutive bars 
                           CBar *bar0=list.At(i);
                           CBar *bar1=list.At(i-1);
                           if(bar0==NULL || bar1==NULL)
                              return false;
                           //--- If the obtained bars represent a pattern 
                           if(CheckInsideBar(bar1,bar0))
                             {
                              //--- set mother bar data to the MqlRates variable and set 'res' to 'true'
                              this.SetBarData(bar1,rates);
                              res=true;
                             }
                           //--- If there is no pattern, interrupt the loop
                           else
                              break;
                          }
                        //--- return the result
                        return res;
                       }

形态搜索方法只是比较附近两个柱形的大小,然后返回右边柱形完全位于左边柱形内的标志。

在搜索母柱的方法中,我们在柱列表中循环搜索形态,如果找到形态,则将柱数据写入 MqlRates 变量,然后继续搜索下一对柱形。在循环的每次迭代中,搜索一直持续到遇到形态为止,母柱的数据会被写入每个连续柱的变量中。这样,我们就能找到所有嵌套形态,并最终从整个序列最左边的柱中获得母柱数据。


以指定方向创建形态的方法:

//+-----------------------------------------------------------------------+
//|CPatternControlInsideBar::Create a pattern with the specified direction|
//+-----------------------------------------------------------------------+
CPattern *CPatternControlInsideBar::CreatePattern(const ENUM_PATTERN_DIRECTION direction,const uint id,CBar *bar)
  {
//--- If invalid indicator is passed to the bar object, return NULL
   if(bar==NULL)
      return NULL;
//--- Fill the MqlRates structure with bar data
   MqlRates rates={0};
   this.SetBarData(bar,rates);
//--- Create a new Inside Bar pattern
   CPatternInsideBar *obj=new CPatternInsideBar(id,this.Symbol(),this.Timeframe(),rates,PATTERN_DIRECTION_BOTH);
   if(obj==NULL)
      return NULL;
//--- set the proportions of the candle the pattern was found on to the properties of the created pattern object
   obj.SetProperty(PATTERN_PROP_RATIO_BODY_TO_CANDLE_SIZE,bar.RatioBodyToCandleSize());
   obj.SetProperty(PATTERN_PROP_RATIO_LOWER_SHADOW_TO_CANDLE_SIZE,bar.RatioLowerShadowToCandleSize());
   obj.SetProperty(PATTERN_PROP_RATIO_UPPER_SHADOW_TO_CANDLE_SIZE,bar.RatioUpperShadowToCandleSize());
//--- set the search criteria of the candle the pattern was found on to the properties of the created pattern object
   obj.SetProperty(PATTERN_PROP_RATIO_BODY_TO_CANDLE_SIZE_CRITERION,this.RatioBodyToCandleSizeValue());
   obj.SetProperty(PATTERN_PROP_RATIO_LARGER_SHADOW_TO_CANDLE_SIZE_CRITERION,this.RatioLargerShadowToCandleSizeValue());
   obj.SetProperty(PATTERN_PROP_RATIO_SMALLER_SHADOW_TO_CANDLE_SIZE_CRITERION,this.RatioSmallerShadowToCandleSizeValue());
//--- Set the control object ID to the pattern object
   obj.SetProperty(PATTERN_PROP_CTRL_OBJ_ID,this.ObjectID());
//--- Return the pointer to a created object
   return obj;
  }

该方法只需创建一个 Inside Bar 形态类的新对象,并返回创建新对象的结果。在用于创建新对象的字符串下面的所有内容,仍然是对已在类构造函数中赋值的对象属性进行无用的 0 赋值。但现在这些都保留。之后,可能还需要使用一些参数来识别形态。如果没有,那我就直接删除多余的代码。


搜索形态的方法:

//+------------------------------------------------------------------+
//| CPatternControlInsideBar::Search for pattern                     |
//+------------------------------------------------------------------+
ENUM_PATTERN_DIRECTION CPatternControlInsideBar::FindPattern(const datetime series_bar_time,const uint min_body_size,MqlRates &mother_bar_data) const
  {
//--- Get bar data up to and including the specified time
   CArrayObj *list=CSelect::ByBarProperty(this.m_list_series,BAR_PROP_TIME,series_bar_time,EQUAL_OR_LESS);
//--- If the list is empty, return -1
   if(list==NULL || list.Total()==0)
      return WRONG_VALUE;
//--- Sort the list by bar opening time
   list.Sort(SORT_BY_BAR_TIME);
//--- Get the latest bar from the list (base bar)
   CBar *bar_patt=list.At(list.Total()-1);
   if(bar_patt==NULL)
      return WRONG_VALUE;
//--- In the loop from the next bar (mother),
   for(int i=list.Total()-2;i>=0;i--)
     {
      CBar *bar_prev=list.At(i);
      if(bar_prev==NULL)
         return WRONG_VALUE;
      //--- check that the resulting two bars are a pattern. If not, return -1
      if(!this.CheckInsideBar(bar_prev,bar_patt))
         return WRONG_VALUE;
      //--- If the pattern is found at the previous step, look for nested patterns.
      //--- The leftmost bar will be the mother bar for the entire chain of nested patterns
      //--- If the found pattern does not have nested ones, then its mother bar will be the current cycle bar (to the left of the base one)
      if(!this.FindMotherBar(list,mother_bar_data))
         SetBarData(bar_prev,mother_bar_data);
//--- Return the pattern direction (bidirectional)
      return PATTERN_DIRECTION_BOTH;
     }
//--- No patterns found - return -1
   return WRONG_VALUE;
  }

方法的逻辑在注释中有所描述。当前柱形的开启时间会传递给该方法。获取除当前柱形之外的所有柱形列表(我们不在零柱上查找形态)。在基于结果柱形列表的循环中,每隔两个附近的柱形检查它们是否符合形态标准。如果它们之间的关系是一种形态,我们就会寻找嵌套形态,即在额外的循环中寻找相邻的形态,直到找到为止。这样,我们就能找到整条相邻的形态链,其中最左边的柱形 - 它的左边柱形 - 将成为整条嵌套形态链的母柱。该柱、其时间和价格都被写入被发现形态的属性中。在图表上显示嵌套形态时,这些数据将使我们有机会完全框定整个嵌套形态链,这将在测试 EA 中可见。


返回对象管理的形态列表的方法:

//+------------------------------------------------------------------+
//| Returns the list of patterns managed by the object               |
//+------------------------------------------------------------------+
CArrayObj *CPatternControlInsideBar::GetListPatterns(void)
  {
   CArrayObj *list=CSelect::ByPatternProperty(this.m_list_all_patterns,PATTERN_PROP_PERIOD,this.Timeframe(),EQUAL);
   list=CSelect::ByPatternProperty(list,PATTERN_PROP_SYMBOL,this.Symbol(),EQUAL);
   list=CSelect::ByPatternProperty(list,PATTERN_PROP_TYPE,PATTERN_TYPE_INSIDE_BAR,EQUAL);
   return CSelect::ByPatternProperty(list,PATTERN_PROP_CTRL_OBJ_ID,this.ObjectID(),EQUAL);
  }


在形态管理类中,调整返回 Inside Bar 形态控制对象的方法:

//--- Return the Inside Bar pattern control object
   CPatternControl  *GetObjControlPatternInsideBar(void)
                       {
                        int total=this.m_list_controls.Total();
                        for(int i=0;i<total;i++)
                          {
                           CPatternControl *obj=this.m_list_controls.At(i);
                           if(obj==NULL)
                              continue;
                           //--- Check search conditions and return the result
                           if(obj.TypePattern()==PATTERN_TYPE_INSIDE_BAR)
                              return obj;
                          }
                        return NULL;
                       }

在此之前,该方法返回 NULL,因为该方法返回的对象类尚未创建。


让我们调整一下方法,该方法会设置使用 "Inside Bar" 形态的标记,并在控制对象不存在的情况下创建一个控制对象:

//--- Set the flag for using the Pattern Inside and create a control object if it does not already exist
   void              SetUsedPatternInsideBar(const bool flag)
                       {
                        //--- Get the pointer to the Inner Bar pattern control object 
                        CPatternControlInsideBar *obj=this.GetObjControlPatternInsideBar();
                        //--- If the pointer is received (the object exists), set the use flag 
                        if(obj!=NULL)
                           obj.SetUsed(flag);
                        //--- f there is no object and the flag is passed as 'true'
                        else if(flag)
                          {
                           //--- Create the new Inside Bar pattern control object
                           obj=new CPatternControlInsideBar(this.Symbol(),this.Timeframe(),this.m_list_series,this.m_list_all_patterns);
                           if(obj==NULL)
                              return;
                           //--- Add pointer to the created object to the list
                           if(!this.m_list_controls.Add(obj))
                             {
                              delete obj;
                              return;
                             }
                           //--- Set the usage flag and pattern parameters to the control object
                           obj.SetUsed(flag);
                           obj.SetRatioBodyToCandleSizeValue(0);
                           obj.SetRatioLargerShadowToCandleSizeValue(0);
                           obj.SetRatioSmallerShadowToCandleSizeValue(0);
                           obj.CreateAndRefreshPatternList(0);
                          }
                       }

此前,由于上面提到的原因,该方法是空的。方法逻辑已在代码中注释,无需额外解释。


让我们来编写设置标记的方法,以绘制带点的形态:

//+------------------------------------------------------------------+
//| Methods for setting the flag of drawing the pattern using dots   |
//+------------------------------------------------------------------+
//--- Set the flag for drawing the Harami pattern with dots
   void              SetDrawingAsDotsPatternHarami(const bool flag,const bool redraw)
                       {
                        
                       }
//--- Set the flag for drawing the Harami Cross pattern with dots
   void              SetDrawingAsDotsPatternHaramiCross(const bool flag,const bool redraw)
                       {
                        
                       }
//--- Set the flag for drawing the Tweezer pattern with dots
   void              SetDrawingAsDotsPatternTweezer(const bool flag,const bool redraw)
                       {
                       
                       }
//--- Set the flag for drawing the Piercing Line pattern with dots
   void              SetDrawingAsDotsPatternPiercingLine(const bool flag,const bool redraw)
                       {
                       
                       }
//--- Set the flag for drawing the Cloud Cover pattern with dots
   void              SetDrawingAsDotsPatternDarkCloudCover(const bool flag,const bool redraw)
                       {
                       
                       }
//--- Set the flag for drawing the Three White Soldiers pattern with dots
   void              SetDrawingAsDotsPatternThreeWhiteSoldiers(const bool flag,const bool redraw)
                       {
                       
                       }
//--- Set the flag for drawing the Three Black Crows pattern with dots
   void              SetDrawingAsDotsPatternThreeBlackCrows(const bool flag,const bool redraw)
                       {
                       
                       }
//--- Set the flag for drawing the Shooting Star pattern with dots
   void              SetDrawingAsDotsPatternShootingStar(const bool flag,const bool redraw)
                       {
                       
                       }
//--- Set the flag for drawing the Hammer pattern with dots
   void              SetDrawingAsDotsPatternHammer(const bool flag,const bool redraw)
                       {
                       
                       }
//--- Set the flag for drawing the Inverted Hammer pattern with dots
   void              SetDrawingAsDotsPatternInvertedHammer(const bool flag,const bool redraw)
                       {
                       
                       }
//--- Set the flag for drawing the Hanging Man pattern with dots
   void              SetDrawingAsDotsPatternHangingMan(const bool flag,const bool redraw)
                       {
                       
                       }
//--- Set the flag for drawing the Doji pattern with dots
   void              SetDrawingAsDotsPatternDoji(const bool flag,const bool redraw)
                       {
                       
                       }
//--- Set the flag for drawing the Dragonfly Doji pattern with dots
   void              SetDrawingAsDotsPatternDragonflyDoji(const bool flag,const bool redraw)
                       {
                       
                       }
//--- Set the flag for drawing the Gravestone Doji pattern with dots
   void              SetDrawingAsDotsPatternGravestoneDoji(const bool flag,const bool redraw)
                       {
                       
                       }
//--- Set the flag for drawing the Morning Star pattern with dots
   void              SetDrawingAsDotsPatternMorningStar(const bool flag,const bool redraw)
                       {
                       
                       }
//--- Set the flag for drawing the Morning Doji Star pattern with dots
   void              SetDrawingAsDotsPatternMorningDojiStar(const bool flag,const bool redraw)
                       {
                       
                       }
//--- Set the flag for drawing the Evening Star pattern with dots
   void              SetDrawingAsDotsPatternEveningStar(const bool flag,const bool redraw)
                       {
                       
                       }
//--- Set the flag for drawing the Evening Doji Star pattern with dots
   void              SetDrawingAsDotsPatternEveningDojiStar(const bool flag,const bool redraw)
                       {
                       
                       }
//--- Set the flag for drawing the Three Stars pattern with dots
   void              SetDrawingAsDotsPatternThreeStars(const bool flag,const bool redraw)
                       {
                       
                       }
//--- Set the flag for drawing the Abandoned Baby pattern with dots
   void              SetDrawingAsDotsPatternAbandonedBaby(const bool flag,const bool redraw)
                       {
                       
                       }
//--- Set the flag for drawing the Pivot Point Reversal pattern with dots
//--- Price Action
   void              SetDrawingAsDotsPatternPivotPointReversal(const bool flag,const bool redraw)
                       {
                       
                       }
//--- Set the flag for drawing the Outside Bar pattern with dots
   void              SetDrawingAsDotsPatternOutsideBar(const bool flag,const bool redraw)
                       {
                       
                       }
//--- Set the flag for drawing the Inside Bar pattern with dots
   void              SetDrawingAsDotsPatternInsideBar(const bool flag,const bool redraw)
                       {
                        //--- Get the pointer to the Inner Bar pattern control object 
                        CPatternControlInsideBar *obj=this.GetObjControlPatternInsideBar();
                        //--- If the pointer is received (the object exists), set the drawing flag
                        if(obj!=NULL)
                           obj.SetDrawingAsDots(flag,redraw);
                       }
//--- Set the flag for drawing the Pin Bar pattern with dots
   void              SetDrawingAsDotsPatternPinBar(const bool flag,const bool redraw,  // Flag of drawing with dots and Pin Bar Price Action redraw flag
                                          const double ratio_body=30,                  // Percentage ratio of the candle body to the full size of the candle
                                          const double ratio_larger_shadow=60,         // Percentage ratio of the size of the larger shadow to the size of the candle
                                          const double ratio_smaller_shadow=30)        // Percentage ratio of the size of the smaller shadow to the size of the candle
                       {
                        //--- Get the pointer to the Pin Bar pattern control object with the specified parameters
                        CPatternControlPinBar *obj=this.GetObjControlPatternPinBar(ratio_body,ratio_larger_shadow,ratio_smaller_shadow);
                        //--- If the pointer is received (the object exists), set the use flag 
                        if(obj!=NULL)
                           obj.SetDrawingAsDots(flag,redraw);
                       }
//--- Set the flag for drawing the Rails pattern with dots
   void              SetDrawingAsDotsPatternRails(const bool flag,const bool redraw)
                       {
                       
                       }

这些方法只针对两种形态编写。对于其余的形态,我们只需在编写新的形态对象类时填写模板。


写出返回点画标志的方法:

//+------------------------------------------------------------------+
//| Methods of returning the flag of drawing with dots               |
//+------------------------------------------------------------------+
//--- Candle formations
//--- Return the flag for drawing the Harami pattern with dots
   bool              IsDrawingAsDotsPatternHarami(void)
                       {
                        CPatternControl *obj=GetObjControlPatternHarami();
                        return(obj!=NULL ? obj.IsDrawingAsDots() : false);
                       }
//--- Return the flag for drawing the Harami Cross pattern with dots
   bool              IsDrawingAsDotsPatternHaramiCross(void)
                       {
                        CPatternControl *obj=GetObjControlPatternHaramiCross();
                        return(obj!=NULL ? obj.IsDrawingAsDots() : false);
                       }
//--- Return the flag for drawing the Tweezer pattern with dots
   bool              IsDrawingAsDotsPatternTweezer(void)
                       {
                        CPatternControl *obj=GetObjControlPatternTweezer();
                        return(obj!=NULL ? obj.IsDrawingAsDots() : false);
                       }
//--- Return the flag for drawing the Piercing Line pattern with dots
   bool              IsDrawingAsDotsPatternPiercingLine(void)
                       {
                        CPatternControl *obj=GetObjControlPatternPiercingLine();
                        return(obj!=NULL ? obj.IsDrawingAsDots() : false);
                       }
//--- Return the flag for drawing the Cloud Cover pattern with dots
   bool              IsDrawingAsDotsPatternDarkCloudCover(void)
                       {
                        CPatternControl *obj=GetObjControlPatternDarkCloudCover();
                        return(obj!=NULL ? obj.IsDrawingAsDots() : false);
                       }
//--- Return the flag for drawing the Three White Soldiers pattern with dots
   bool              IsDrawingAsDotsPatternThreeWhiteSoldiers(void)
                       {
                        CPatternControl *obj=GetObjControlPatternThreeWhiteSoldiers();
                        return(obj!=NULL ? obj.IsDrawingAsDots() : false);
                       }
//--- Return the flag for drawing the Three Black Crows pattern with dots
   bool              IsDrawingAsDotsPatternThreeBlackCrows(void)
                       {
                        CPatternControl *obj=GetObjControlPatternThreeBlackCrows();
                        return(obj!=NULL ? obj.IsDrawingAsDots() : false);
                       }
//--- Return the flag for drawing the Shooting Star pattern with dots
   bool              IsDrawingAsDotsPatternShootingStar(void)
                       {
                        CPatternControl *obj=GetObjControlPatternShootingStar();
                        return(obj!=NULL ? obj.IsDrawingAsDots() : false);
                       }
//--- Return the flag for drawing the Hammer pattern with dots
   bool              IsDrawingAsDotsPatternHammer(void)
                       {
                        CPatternControl *obj=GetObjControlPatternHammer();
                        return(obj!=NULL ? obj.IsDrawingAsDots() : false);
                       }
//--- Return the flag for drawing the Inverted Hammer pattern with dots
   bool              IsDrawingAsDotsPatternInvertedHammer(void)
                       {
                        CPatternControl *obj=GetObjControlPatternInvertedHammer();
                        return(obj!=NULL ? obj.IsDrawingAsDots() : false);
                       }
//--- Return the flag for drawing the Hanging Man pattern with dots
   bool              IsDrawingAsDotsPatternHangingMan(void)
                       {
                        CPatternControl *obj=GetObjControlPatternHangingMan();
                        return(obj!=NULL ? obj.IsDrawingAsDots() : false);
                       }
//--- Return the flag for drawing the Doji pattern with dots
   bool              IsDrawingAsDotsPatternDoji(void)
                       {
                        CPatternControl *obj=GetObjControlPatternDoji();
                        return(obj!=NULL ? obj.IsDrawingAsDots() : false);
                       }
//--- Return the flag for drawing the Dragonfly Doji pattern with dots
   bool              IsDrawingAsDotsPatternDragonflyDoji(void)
                       {
                        CPatternControl *obj=GetObjControlPatternDragonflyDoji();
                        return(obj!=NULL ? obj.IsDrawingAsDots() : false);
                       }
//--- Return the flag for drawing the Gravestone Doji pattern with dots
   bool              IsDrawingAsDotsPatternGravestoneDoji(void)
                       {
                        CPatternControl *obj=GetObjControlPatternGravestoneDoji();
                        return(obj!=NULL ? obj.IsDrawingAsDots() : false);
                       }
//--- Return the flag for drawing the Morning Star pattern with dots
   bool              IsDrawingAsDotsPatternMorningStar(void)
                       {
                        CPatternControl *obj=GetObjControlPatternMorningStar();
                        return(obj!=NULL ? obj.IsDrawingAsDots() : false);
                       }
//--- Return the flag for drawing the Morning Doji Star pattern with dots
   bool              IsDrawingAsDotsPatternMorningDojiStar(void)
                       {
                        CPatternControl *obj=GetObjControlPatternMorningDojiStar();
                        return(obj!=NULL ? obj.IsDrawingAsDots() : false);
                       }
//--- Return the flag for drawing the Evening Star pattern with dots
   bool              IsDrawingAsDotsPatternEveningStar(void)
                       {
                        CPatternControl *obj=GetObjControlPatternEveningStar();
                        return(obj!=NULL ? obj.IsDrawingAsDots() : false);
                       }
//--- Return the flag for drawing the Evening Doji Star pattern with dots
   bool              IsDrawingAsDotsPatternEveningDojiStar(void)
                       {
                        CPatternControl *obj=GetObjControlPatternEveningDojiStar();
                        return(obj!=NULL ? obj.IsDrawingAsDots() : false);
                       }
//--- Return the flag for drawing the Three Stars pattern with dots
   bool              IsDrawingAsDotsPatternThreeStars(void)
                       {
                        CPatternControl *obj=GetObjControlPatternThreeStars();
                        return(obj!=NULL ? obj.IsDrawingAsDots() : false);
                       }
//--- Return the flag for drawing the Abandoned Baby pattern with dots
   bool              IsDrawingAsDotsPatternAbandonedBaby(void)
                       {
                        CPatternControl *obj=GetObjControlPatternAbandonedBaby();
                        return(obj!=NULL ? obj.IsDrawingAsDots() : false);
                       }
//--- Price Action
//--- Return the flag for drawing the Pivot Point Reversal pattern with dots
   bool              IsDrawingAsDotsPatternPivotPointReversal(void)
                       {
                        CPatternControl *obj=GetObjControlPatternPivotPointReversal();
                        return(obj!=NULL ? obj.IsDrawingAsDots() : false);
                       }
//--- Return the flag for drawing the Outside Bar pattern with dots
   bool              IsDrawingAsDotsPatternOutsideBar(void)
                       {
                        CPatternControl *obj=GetObjControlPatternOutsideBar();
                        return(obj!=NULL ? obj.IsDrawingAsDots() : false);
                       }
//--- Return the flag for drawing the Inside Bar pattern with dots
   bool              IsDrawingAsDotsPatternInsideBar(void)
                       {
                        CPatternControl *obj=GetObjControlPatternInsideBar();
                        return(obj!=NULL ? obj.IsDrawingAsDots() : false);
                       }
//--- Return the flag for drawing the Pin Bar pattern with dots
   bool              IsDrawingAsDotsPatternPinBar(const double ratio_body=30,             // Percentage ratio of the candle body to the full size of the candle
                                                  const double ratio_larger_shadow=60,    // Percentage ratio of the size of the larger shadow to the size of the candle
                                                  const double ratio_smaller_shadow=30)   // Percentage ratio of the size of the smaller shadow to the size of the candle
                       {
                        //--- Get the pattern control object based on its parameters
                        CPatternControl *obj=this.GetObjControlPatternPinBar(ratio_body,ratio_larger_shadow,ratio_smaller_shadow);
                        //--- Return the pattern use flag, or 'false' if the object is not found 
                        return(obj!=NULL ? obj.IsDrawingAsDots() : false);
                       }
//--- Return the flag for drawing the Rails pattern with dots
   bool              IsDrawingAsDotsPatternRails(void)
                       {
                        CPatternControl *obj=GetObjControlPatternRails();
                        return(obj!=NULL ? obj.IsDrawingAsDots() : false);
                       }

输入是为返回绘制带点的 Pin Bar 形态的方法而实现的,因为所有处理形态的方法都有它们。其余方法目前返回的是不带任何参数的点绘制标志。如果某些形态需要参数,我们稍后将把它们写入此类方法中。


现在,需要为位于同一文件中的时间序列类编写完全相同的方法:

//--- Set the flag for using the Pattern Inside and create a control object if it does not already exist
   void              SetUsedPatternInsideBar(const bool flag)
                       {
                        if(this.m_patterns_control==NULL)
                           return;
                        this.m_patterns_control.SetUsedPatternInsideBar(flag);
                       }

...

//+------------------------------------------------------------------+
//| Methods for setting the flag of drawing the pattern using dots   |
//+------------------------------------------------------------------+
//--- Set the flag for drawing the Harami pattern with dots
   void              SetDrawingAsDotsPatternHarami(const bool flag,const bool redraw)
                       {
                        if(this.m_patterns_control==NULL)
                           return;
                        this.m_patterns_control.SetDrawingAsDotsPatternHarami(flag,redraw);
                       }
//--- Set the flag for drawing the Harami Cross pattern with dots
   void              SetDrawingAsDotsPatternHaramiCross(const bool flag,const bool redraw)
                       {
                        if(this.m_patterns_control==NULL)
                           return;
                        this.m_patterns_control.SetDrawingAsDotsPatternHaramiCross(flag,redraw);
                       }
//--- Set the flag for drawing the Tweezer pattern with dots
   void              SetDrawingAsDotsPatternTweezer(const bool flag,const bool redraw)
                       {
                        if(this.m_patterns_control==NULL)
                           return;
                        this.m_patterns_control.SetDrawingAsDotsPatternTweezer(flag,redraw);
                       }
//--- Set the flag for drawing the Piercing Line pattern with dots
   void              SetDrawingAsDotsPatternPiercingLine(const bool flag,const bool redraw)
                       {
                        if(this.m_patterns_control==NULL)
                           return;
                        this.m_patterns_control.SetDrawingAsDotsPatternPiercingLine(flag,redraw);
                       }
//--- Set the flag for drawing the Cloud Cover pattern with dots
   void              SetDrawingAsDotsPatternDarkCloudCover(const bool flag,const bool redraw)
                       {
                        if(this.m_patterns_control==NULL)
                           return;
                        this.m_patterns_control.SetDrawingAsDotsPatternDarkCloudCover(flag,redraw);
                       }
//--- Set the flag for drawing the Three White Soldiers pattern with dots
   void              SetDrawingAsDotsPatternThreeWhiteSoldiers(const bool flag,const bool redraw)
                       {
                        if(this.m_patterns_control==NULL)
                           return;
                        this.m_patterns_control.SetDrawingAsDotsPatternThreeWhiteSoldiers(flag,redraw);
                       }
//--- Set the flag for drawing the Three Black Crows pattern with dots
   void              SetDrawingAsDotsPatternThreeBlackCrows(const bool flag,const bool redraw)
                       {
                        if(this.m_patterns_control==NULL)
                           return;
                        this.m_patterns_control.SetDrawingAsDotsPatternThreeBlackCrows(flag,redraw);
                       }
//--- Set the flag for drawing the Shooting Star pattern with dots
   void              SetDrawingAsDotsPatternShootingStar(const bool flag,const bool redraw)
                       {
                        if(this.m_patterns_control==NULL)
                           return;
                        this.m_patterns_control.SetDrawingAsDotsPatternShootingStar(flag,redraw);
                       }
//--- Set the flag for drawing the Hammer pattern with dots
   void              SetDrawingAsDotsPatternHammer(const bool flag,const bool redraw)
                       {
                        if(this.m_patterns_control==NULL)
                           return;
                        this.m_patterns_control.SetDrawingAsDotsPatternHammer(flag,redraw);
                       }
//--- Set the flag for drawing the Inverted Hammer pattern with dots
   void              SetDrawingAsDotsPatternInvertedHammer(const bool flag,const bool redraw)
                       {
                        if(this.m_patterns_control==NULL)
                           return;
                        this.m_patterns_control.SetDrawingAsDotsPatternInvertedHammer(flag,redraw);
                       }
//--- Set the flag for drawing the Hanging Man pattern with dots
   void              SetDrawingAsDotsPatternHangingMan(const bool flag,const bool redraw)
                       {
                        if(this.m_patterns_control==NULL)
                           return;
                        this.m_patterns_control.SetDrawingAsDotsPatternHangingMan(flag,redraw);
                       }
//--- Set the flag for drawing the Doji pattern with dots
   void              SetDrawingAsDotsPatternDoji(const bool flag,const bool redraw)
                       {
                        if(this.m_patterns_control==NULL)
                           return;
                        this.m_patterns_control.SetDrawingAsDotsPatternDoji(flag,redraw);
                       }
//--- Set the flag for drawing the Dragonfly Doji pattern with dots
   void              SetDrawingAsDotsPatternDragonflyDoji(const bool flag,const bool redraw)
                       {
                        if(this.m_patterns_control==NULL)
                           return;
                        this.m_patterns_control.SetDrawingAsDotsPatternDragonflyDoji(flag,redraw);
                       }
//--- Set the flag for drawing the Gravestone Doji pattern with dots
   void              SetDrawingAsDotsPatternGravestoneDoji(const bool flag,const bool redraw)
                       {
                        if(this.m_patterns_control==NULL)
                           return;
                        this.m_patterns_control.SetDrawingAsDotsPatternGravestoneDoji(flag,redraw);
                       }
//--- Set the flag for drawing the Morning Star pattern with dots
   void              SetDrawingAsDotsPatternMorningStar(const bool flag,const bool redraw)
                       {
                        if(this.m_patterns_control==NULL)
                           return;
                        this.m_patterns_control.SetDrawingAsDotsPatternMorningStar(flag,redraw);
                       }
//--- Set the flag for drawing the Morning Doji Star pattern with dots
   void              SetDrawingAsDotsPatternMorningDojiStar(const bool flag,const bool redraw)
                       {
                        if(this.m_patterns_control==NULL)
                           return;
                        this.m_patterns_control.SetDrawingAsDotsPatternMorningDojiStar(flag,redraw);
                       }
//--- Set the flag for drawing the Evening Star pattern with dots
   void              SetDrawingAsDotsPatternEveningStar(const bool flag,const bool redraw)
                       {
                        if(this.m_patterns_control==NULL)
                           return;
                        this.m_patterns_control.SetDrawingAsDotsPatternEveningStar(flag,redraw);
                       }
//--- Set the flag for drawing the Evening Doji Star pattern with dots
   void              SetDrawingAsDotsPatternEveningDojiStar(const bool flag,const bool redraw)
                       {
                        if(this.m_patterns_control==NULL)
                           return;
                        this.m_patterns_control.SetDrawingAsDotsPatternEveningDojiStar(flag,redraw);
                       }
//--- Set the flag for drawing the Three Stars pattern with dots
   void              SetDrawingAsDotsPatternThreeStars(const bool flag,const bool redraw)
                       {
                        if(this.m_patterns_control==NULL)
                           return;
                        this.m_patterns_control.SetDrawingAsDotsPatternThreeStars(flag,redraw);
                       }
//--- Set the flag for drawing the Abandoned Baby pattern with dots
   void              SetDrawingAsDotsPatternAbandonedBaby(const bool flag,const bool redraw)
                       {
                        if(this.m_patterns_control==NULL)
                           return;
                        this.m_patterns_control.SetDrawingAsDotsPatternAbandonedBaby(flag,redraw);
                       }
//--- Set the flag for drawing the Pivot Point Reversal pattern with dots
//--- Price Action
   void              SetDrawingAsDotsPatternPivotPointReversal(const bool flag,const bool redraw)
                       {
                        if(this.m_patterns_control==NULL)
                           return;
                        this.m_patterns_control.SetDrawingAsDotsPatternPivotPointReversal(flag,redraw);
                       }
//--- Set the flag for drawing the Outside Bar pattern with dots
   void              SetDrawingAsDotsPatternOutsideBar(const bool flag,const bool redraw)
                       {
                        if(this.m_patterns_control==NULL)
                           return;
                        this.m_patterns_control.SetDrawingAsDotsPatternOutsideBar(flag,redraw);
                       }
//--- Set the flag for drawing the Inside Bar pattern with dots
   void              SetDrawingAsDotsPatternInsideBar(const bool flag,const bool redraw)
                       {
                        if(this.m_patterns_control==NULL)
                           return;
                        this.m_patterns_control.SetDrawingAsDotsPatternInsideBar(flag,redraw);
                       }
//--- Set the flag for drawing the Pin Bar pattern with dots
   void              SetDrawingAsDotsPatternPinBar(const bool flag,const bool redraw,     // Flag of drawing with dots and Pin Bar Price Action redraw flag
                                                   const double ratio_body=30,            // Percentage ratio of the candle body to the full size of the candle
                                                   const double ratio_larger_shadow=60,   // Percentage ratio of the size of the larger shadow to the size of the candle
                                                   const double ratio_smaller_shadow=30)  // Percentage ratio of the size of the smaller shadow to the size of the candle
                       {
                        if(this.m_patterns_control==NULL)
                           return;
                        this.m_patterns_control.SetDrawingAsDotsPatternPinBar(flag,redraw,ratio_body,ratio_larger_shadow,ratio_smaller_shadow);
                       }
//--- Set the flag for drawing the Rails pattern with dots
   void              SetDrawingAsDotsPatternRails(const bool flag,const bool redraw)
                       {
                        if(this.m_patterns_control==NULL)
                           return;
                        this.m_patterns_control.SetDrawingAsDotsPatternRails(flag,redraw);
                       }
                       
//+------------------------------------------------------------------+
//| Methods of returning the flag of drawing with dots               |
//+------------------------------------------------------------------+
//--- Candle formations
//--- Return the flag for drawing the Harami pattern with dots
   bool              IsDrawingAsDotsPatternHarami(void)
                       {
                        return(this.m_patterns_control!=NULL ? this.m_patterns_control.IsDrawingAsDotsPatternHarami() : false);
                       }
//--- Return the flag for drawing the Harami Cross pattern with dots
   bool              IsDrawingAsDotsPatternHaramiCross(void)
                       {
                        return(this.m_patterns_control!=NULL ? this.m_patterns_control.IsDrawingAsDotsPatternHaramiCross() : false);
                       }
//--- Return the flag for drawing the Tweezer pattern with dots
   bool              IsDrawingAsDotsPatternTweezer(void)
                       {
                        return(this.m_patterns_control!=NULL ? this.m_patterns_control.IsDrawingAsDotsPatternTweezer() : false);
                       }
//--- Return the flag for drawing the Piercing Line pattern with dots
   bool              IsDrawingAsDotsPatternPiercingLine(void)
                       {
                        return(this.m_patterns_control!=NULL ? this.m_patterns_control.IsDrawingAsDotsPatternPiercingLine() : false);
                       }
//--- Return the flag for drawing the Cloud Cover pattern with dots
   bool              IsDrawingAsDotsPatternDarkCloudCover(void)
                       {
                        return(this.m_patterns_control!=NULL ? this.m_patterns_control.IsDrawingAsDotsPatternDarkCloudCover() : false);
                       }
//--- Return the flag for drawing the Three White Soldiers pattern with dots
   bool              IsDrawingAsDotsPatternThreeWhiteSoldiers(void)
                       {
                        return(this.m_patterns_control!=NULL ? this.m_patterns_control.IsDrawingAsDotsPatternThreeWhiteSoldiers() : false);
                       }
//--- Return the flag for drawing the Three Black Crows pattern with dots
   bool              IsDrawingAsDotsPatternThreeBlackCrows(void)
                       {
                        return(this.m_patterns_control!=NULL ? this.m_patterns_control.IsDrawingAsDotsPatternThreeBlackCrows() : false);
                       }
//--- Return the flag for drawing the Shooting Star pattern with dots
   bool              IsDrawingAsDotsPatternShootingStar(void)
                       {
                        return(this.m_patterns_control!=NULL ? this.m_patterns_control.IsDrawingAsDotsPatternShootingStar() : false);
                       }
//--- Return the flag for drawing the Hammer pattern with dots
   bool              IsDrawingAsDotsPatternHammer(void)
                       {
                        return(this.m_patterns_control!=NULL ? this.m_patterns_control.IsDrawingAsDotsPatternHammer() : false);
                       }
//--- Return the flag for drawing the Inverted Hammer pattern with dots
   bool              IsDrawingAsDotsPatternInvertedHammer(void)
                       {
                        return(this.m_patterns_control!=NULL ? this.m_patterns_control.IsDrawingAsDotsPatternInvertedHammer() : false);
                       }
//--- Return the flag for drawing the Hanging Man pattern with dots
   bool              IsDrawingAsDotsPatternHangingMan(void)
                       {
                        return(this.m_patterns_control!=NULL ? this.m_patterns_control.IsDrawingAsDotsPatternHangingMan() : false);
                       }
//--- Return the flag for drawing the Doji pattern with dots
   bool              IsDrawingAsDotsPatternDoji(void)
                       {
                        return(this.m_patterns_control!=NULL ? this.m_patterns_control.IsDrawingAsDotsPatternDoji() : false);
                       }
//--- Return the flag for drawing the Dragonfly Doji pattern with dots
   bool              IsDrawingAsDotsPatternDragonflyDoji(void)
                       {
                        return(this.m_patterns_control!=NULL ? this.m_patterns_control.IsDrawingAsDotsPatternDragonflyDoji() : false);
                       }
//--- Return the flag for drawing the Gravestone Doji pattern with dots
   bool              IsDrawingAsDotsPatternGravestoneDoji(void)
                       {
                        return(this.m_patterns_control!=NULL ? this.m_patterns_control.IsDrawingAsDotsPatternGravestoneDoji() : false);
                       }
//--- Return the flag for drawing the Morning Star pattern with dots
   bool              IsDrawingAsDotsPatternMorningStar(void)
                       {
                        return(this.m_patterns_control!=NULL ? this.m_patterns_control.IsDrawingAsDotsPatternMorningStar() : false);
                       }
//--- Return the flag for drawing the Morning Doji Star pattern with dots
   bool              IsDrawingAsDotsPatternMorningDojiStar(void)
                       {
                        return(this.m_patterns_control!=NULL ? this.m_patterns_control.IsDrawingAsDotsPatternMorningDojiStar() : false);
                       }
//--- Return the flag for drawing the Evening Star pattern with dots
   bool              IsDrawingAsDotsPatternEveningStar(void)
                       {
                        return(this.m_patterns_control!=NULL ? this.m_patterns_control.IsDrawingAsDotsPatternEveningStar() : false);
                       }
//--- Return the flag for drawing the Evening Doji Star pattern with dots
   bool              IsDrawingAsDotsPatternEveningDojiStar(void)
                       {
                        return(this.m_patterns_control!=NULL ? this.m_patterns_control.IsDrawingAsDotsPatternEveningDojiStar() : false);
                       }
//--- Return the flag for drawing the Three Stars pattern with dots
   bool              IsDrawingAsDotsPatternThreeStars(void)
                       {
                        return(this.m_patterns_control!=NULL ? this.m_patterns_control.IsDrawingAsDotsPatternThreeStars() : false);
                       }
//--- Return the flag for drawing the Abandoned Baby pattern with dots
   bool              IsDrawingAsDotsPatternAbandonedBaby(void)
                       {
                        return(this.m_patterns_control!=NULL ? this.m_patterns_control.IsDrawingAsDotsPatternAbandonedBaby() : false);
                       }
//--- Price Action
//--- Return the flag for drawing the Pivot Point Reversal pattern with dots
   bool              IsDrawingAsDotsPatternPivotPointReversal(void)
                       {
                        return(this.m_patterns_control!=NULL ? this.m_patterns_control.IsDrawingAsDotsPatternPivotPointReversal() : false);
                       }
//--- Return the flag for drawing the Outside Bar pattern with dots
   bool              IsDrawingAsDotsPatternOutsideBar(void)
                       {
                        return(this.m_patterns_control!=NULL ? this.m_patterns_control.IsDrawingAsDotsPatternOutsideBar() : false);
                       }
//--- Return the flag for drawing the Inside Bar pattern with dots
   bool              IsDrawingAsDotsPatternInsideBar(void)
                       {
                        return(this.m_patterns_control!=NULL ? this.m_patterns_control.IsDrawingAsDotsPatternInsideBar() : false);
                       }
//--- Return the flag for drawing the Pin Bar pattern with dots
   bool              IsDrawingAsDotsPatternPinBar(const double ratio_body=30,             // Percentage ratio of the candle body to the full size of the candle
                                                  const double ratio_larger_shadow=60,    // Percentage ratio of the size of the larger shadow to the size of the candle
                                                  const double ratio_smaller_shadow=30)   // Percentage ratio of the size of the smaller shadow to the size of the candle
                       {
                        return(this.m_patterns_control!=NULL ? this.m_patterns_control.IsDrawingAsDotsPatternPinBar(ratio_body,ratio_larger_shadow,ratio_smaller_shadow) : false);
                       }
//--- Return the flag for drawing the Rails pattern with dots
   bool              IsDrawingAsDotsPatternRails(void)
                       {
                        return(this.m_patterns_control!=NULL ? this.m_patterns_control.IsDrawingAsDotsPatternRails() : false);
                       }


同样的方法也需要写入交易品种时间序列类的 \MQL5\Include\DoEasy\Objects\Series\TimeSeriesDE.mqh文件中:

在公有部分声明以下方法:

//+------------------------------------------------------------------+
//| Methods for setting the flag of drawing the pattern using dots   |
//+------------------------------------------------------------------+
//--- Set the flag for using the Harami pattern and create a control object if it does not already exist
   void              SetDrawingAsDotsPatternHarami(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Harami Cross pattern and create a control object if it does not already exist
   void              SetDrawingAsDotsPatternHaramiCross(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Tweezer pattern and create a control object if it does not already exist
   void              SetDrawingAsDotsPatternTweezer(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Piercing Line pattern and create a control object if it does not already exist
   void              SetDrawingAsDotsPatternPiercingLine(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Cloud Cover pattern and create a control object if it does not already exist
   void              SetDrawingAsDotsPatternDarkCloudCover(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Three White Soldiers pattern and create a control object if it does not already exist
   void              SetDrawingAsDotsPatternThreeWhiteSoldiers(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Three Black Crows pattern and create a control object if it does not already exist
   void              SetDrawingAsDotsPatternThreeBlackCrows(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Shooting Star pattern and create a control object if it does not already exist
   void              SetDrawingAsDotsPatternShootingStar(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Hammer pattern and create a control object if it does not already exist
   void              SetDrawingAsDotsPatternHammer(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Inverted Hammer pattern and create a control object if it does not already exist
   void              SetDrawingAsDotsPatternInvertedHammer(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Hanging Man pattern and create a control object if it does not already exist
   void              SetDrawingAsDotsPatternHangingMan(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Doji pattern and create a control object if it does not already exist
   void              SetDrawingAsDotsPatternDoji(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Dragonfly Doji pattern and create a control object if it does not already exist
   void              SetDrawingAsDotsPatternDragonflyDoji(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Doji Gravestone pattern and create a control object if it does not already exist
   void              SetDrawingAsDotsPatternGravestoneDoji(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Morning Star pattern and create a control object if it does not already exist
   void              SetDrawingAsDotsPatternMorningStar(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Morning Doji Star pattern and create a control object if it does not already exist
   void              SetDrawingAsDotsPatternMorningDojiStar(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Evening Star pattern and create a control object if it does not already exist
   void              SetDrawingAsDotsPatternEveningStar(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Evening Doji Star pattern and create a control object if it does not already exist
   void              SetDrawingAsDotsPatternEveningDojiStar(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Three Stars pattern and create a control object if it does not already exist
   void              SetDrawingAsDotsPatternThreeStars(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Abandoned Baby pattern and create a control object if it does not already exist
   void              SetDrawingAsDotsPatternAbandonedBaby(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Pivot Point Reversal pattern and create a control object if it does not already exist
//--- Price Action
   void              SetDrawingAsDotsPatternPivotPointReversal(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Pattern Outside and create a control object if it does not already exist
   void              SetDrawingAsDotsPatternOutsideBar(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Pattern Inside and create a control object if it does not already exist
   void              SetDrawingAsDotsPatternInsideBar(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Pin Bar pattern and create a control object if it does not already exist
   void              SetDrawingAsDotsPatternPinBar(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw,  // Flag of drawing with dots and Pin Bar Price Action redraw flag
                                          const double ratio_body=30,                  // Percentage ratio of the candle body to the full size of the candle
                                          const double ratio_larger_shadow=60,         // Percentage ratio of the size of the larger shadow to the size of the candle
                                          const double ratio_smaller_shadow=30);       // Percentage ratio of the size of the smaller shadow to the size of the candle
//--- Set the flag for using the Rails pattern and create a control object if it does not already exist
   void              SetDrawingAsDotsPatternRails(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
                       
//+------------------------------------------------------------------+
//| Methods of returning the flag of drawing with dots               |
//+------------------------------------------------------------------+
//--- Candle formations
//--- Return the flag of using the Harami pattern
   bool              IsDrawingAsDotsPatternHarami(const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Harami Cross pattern
   bool              IsDrawingAsDotsPatternHaramiCross(const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Tweezer pattern
   bool              IsDrawingAsDotsPatternTweezer(const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Piercing Line pattern
   bool              IsDrawingAsDotsPatternPiercingLine(const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Cloud Cover pattern
   bool              IsDrawingAsDotsPatternDarkCloudCover(const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Three White Soldiers pattern
   bool              IsDrawingAsDotsPatternThreeWhiteSoldiers(const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Three Black Crows pattern
   bool              IsDrawingAsDotsPatternThreeBlackCrows(const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Shooting Star pattern
   bool              IsDrawingAsDotsPatternShootingStar(const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Hammer pattern
   bool              IsDrawingAsDotsPatternHammer(const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Inverted Hammer pattern
   bool              IsDrawingAsDotsPatternInvertedHammer(const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Hanging Man pattern
   bool              IsDrawingAsDotsPatternHangingMan(const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Doji pattern
   bool              IsDrawingAsDotsPatternDoji(const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Dragonfly Doji pattern
   bool              IsDrawingAsDotsPatternDragonflyDoji(const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Gravestone Doji pattern
   bool              IsDrawingAsDotsPatternGravestoneDoji(const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Morning Star pattern
   bool              IsDrawingAsDotsPatternMorningStar(const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Morning Doji Star pattern
   bool              IsDrawingAsDotsPatternMorningDojiStar(const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Evening Star pattern
   bool              IsDrawingAsDotsPatternEveningStar(const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Evening Doji Star pattern
   bool              IsDrawingAsDotsPatternEveningDojiStar(const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Three Stars pattern
   bool              IsDrawingAsDotsPatternThreeStars(const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Abandoned Baby pattern
   bool              IsDrawingAsDotsPatternAbandonedBaby(const ENUM_TIMEFRAMES timeframe);
//--- Price Action
//--- Return the flag of using the Pivot Point Reversal pattern
   bool              IsDrawingAsDotsPatternPivotPointReversal(const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Pattern Outside
   bool              IsDrawingAsDotsPatternOutsideBar(const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Inside Bar pattern
   bool              IsDrawingAsDotsPatternInsideBar(const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Pin Bar pattern
   bool              IsDrawingAsDotsPatternPinBar(const ENUM_TIMEFRAMES timeframe,double ratio_body=30,    // Percentage ratio of the candle body to the full size of the candle
                                         const double ratio_larger_shadow=60,    // Percentage ratio of the size of the larger shadow to the size of the candle
                                         const double ratio_smaller_shadow=30);  // Percentage ratio of the size of the smaller shadow to the size of the candle
//--- Return the flag of using the Rails pattern
   bool              IsDrawingAsDotsPatternRails(const ENUM_TIMEFRAMES timeframe);
   
//+------------------------------------------------------------------+
//| Methods for drawing patterns on a chart                          |
//+------------------------------------------------------------------+


在类主体之外实现所声明的方法:

//+------------------------------------------------------------------+
//| Methods for setting the flag of drawing the pattern using dots   |
//+------------------------------------------------------------------+
//--- Set the flag for drawing the Harami pattern with dots
void CTimeSeriesDE::SetDrawingAsDotsPatternHarami(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   if(series!=NULL)
      series.SetDrawingAsDotsPatternHarami(flag,redraw);
  }
//--- Set the flag for drawing the Harami Cross pattern with dots
void CTimeSeriesDE::SetDrawingAsDotsPatternHaramiCross(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   if(series!=NULL)
      series.SetDrawingAsDotsPatternHaramiCross(flag,redraw);
  }
//--- Set the flag for drawing the Tweezer pattern with dots
void CTimeSeriesDE::SetDrawingAsDotsPatternTweezer(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   if(series!=NULL)
      series.SetDrawingAsDotsPatternTweezer(flag,redraw);
  }
//--- Set the flag for drawing the Piercing Line pattern with dots
void CTimeSeriesDE::SetDrawingAsDotsPatternPiercingLine(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   if(series!=NULL)
      series.SetDrawingAsDotsPatternPiercingLine(flag,redraw);
  }
//--- Set the flag for drawing the Cloud Cover pattern with dots
void CTimeSeriesDE::SetDrawingAsDotsPatternDarkCloudCover(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   if(series!=NULL)
      series.SetDrawingAsDotsPatternDarkCloudCover(flag,redraw);
  }
//--- Set the flag for drawing the Three White Soldiers pattern with dots
void CTimeSeriesDE::SetDrawingAsDotsPatternThreeWhiteSoldiers(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   if(series!=NULL)
      series.SetDrawingAsDotsPatternThreeWhiteSoldiers(flag,redraw);
  }
//--- Set the flag for drawing the Three Black Crows pattern with dots
void CTimeSeriesDE::SetDrawingAsDotsPatternThreeBlackCrows(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   if(series!=NULL)
      series.SetDrawingAsDotsPatternThreeBlackCrows(flag,redraw);
  }
//--- Set the flag for drawing the Shooting Star pattern with dots
void CTimeSeriesDE::SetDrawingAsDotsPatternShootingStar(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   if(series!=NULL)
      series.SetDrawingAsDotsPatternShootingStar(flag,redraw);
  }
//--- Set the flag for drawing the Hammer pattern with dots
void CTimeSeriesDE::SetDrawingAsDotsPatternHammer(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   if(series!=NULL)
      series.SetDrawingAsDotsPatternHammer(flag,redraw);
  }
//--- Set the flag for drawing the Inverted Hammer pattern with dots
void CTimeSeriesDE::SetDrawingAsDotsPatternInvertedHammer(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   if(series!=NULL)
      series.SetDrawingAsDotsPatternInvertedHammer(flag,redraw);
  }
//--- Set the flag for drawing the Hanging Man pattern with dots
void CTimeSeriesDE::SetDrawingAsDotsPatternHangingMan(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   if(series!=NULL)
      series.SetDrawingAsDotsPatternHangingMan(flag,redraw);
  }
//--- Set the flag for drawing the Doji pattern with dots
void CTimeSeriesDE::SetDrawingAsDotsPatternDoji(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   if(series!=NULL)
      series.SetDrawingAsDotsPatternDoji(flag,redraw);
  }
//--- Set the flag for drawing the Dragonfly Doji pattern with dots
void CTimeSeriesDE::SetDrawingAsDotsPatternDragonflyDoji(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   if(series!=NULL)
      series.SetDrawingAsDotsPatternDragonflyDoji(flag,redraw);
  }
//--- Set the flag for drawing the Gravestone Doji pattern with dots
void CTimeSeriesDE::SetDrawingAsDotsPatternGravestoneDoji(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   if(series!=NULL)
      series.SetDrawingAsDotsPatternGravestoneDoji(flag,redraw);
  }
//--- Set the flag for drawing the Morning Star pattern with dots
void CTimeSeriesDE::SetDrawingAsDotsPatternMorningStar(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   if(series!=NULL)
      series.SetDrawingAsDotsPatternMorningStar(flag,redraw);
  }
//--- Set the flag for drawing the Morning Doji Star pattern with dots
void CTimeSeriesDE::SetDrawingAsDotsPatternMorningDojiStar(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   if(series!=NULL)
      series.SetDrawingAsDotsPatternMorningDojiStar(flag,redraw);
  }
//--- Set the flag for drawing the Evening Star pattern with dots
void CTimeSeriesDE::SetDrawingAsDotsPatternEveningStar(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   if(series!=NULL)
      series.SetDrawingAsDotsPatternEveningStar(flag,redraw);
  }
//--- Set the flag for drawing the Evening Doji Star pattern with dots
void CTimeSeriesDE::SetDrawingAsDotsPatternEveningDojiStar(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   if(series!=NULL)
      series.SetDrawingAsDotsPatternEveningDojiStar(flag,redraw);
  }
//--- Set the flag for drawing the Three Stars pattern with dots
void CTimeSeriesDE::SetDrawingAsDotsPatternThreeStars(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   if(series!=NULL)
      series.SetDrawingAsDotsPatternThreeStars(flag,redraw);
  }
//--- Set the flag for drawing the Abandoned Baby pattern with dots
void CTimeSeriesDE::SetDrawingAsDotsPatternAbandonedBaby(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   if(series!=NULL)
      series.SetDrawingAsDotsPatternAbandonedBaby(flag,redraw);
  }
//--- Set the flag for drawing the Pivot Point Reversal pattern with dots
//--- Price Action
void CTimeSeriesDE::SetDrawingAsDotsPatternPivotPointReversal(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   if(series!=NULL)
      series.SetDrawingAsDotsPatternPivotPointReversal(flag,redraw);
  }
//--- Set the flag for drawing the Outside Bar pattern with dots
void CTimeSeriesDE::SetDrawingAsDotsPatternOutsideBar(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   if(series!=NULL)
      series.SetDrawingAsDotsPatternOutsideBar(flag,redraw);
  }
//--- Set the flag for drawing the Inside Bar pattern with dots
void CTimeSeriesDE::SetDrawingAsDotsPatternInsideBar(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   if(series!=NULL)
      series.SetDrawingAsDotsPatternInsideBar(flag,redraw);
  }
//--- Set the flag for drawing the Pin Bar pattern with dots
void CTimeSeriesDE::SetDrawingAsDotsPatternPinBar(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw,  // Flag of drawing with dots and Pin Bar Price Action redraw flag
                                                  const double ratio_body=30,                  // Percentage ratio of the candle body to the full size of the candle
                                                  const double ratio_larger_shadow=60,         // Percentage ratio of the size of the larger shadow to the size of the candle
                                                  const double ratio_smaller_shadow=30)        // Percentage ratio of the size of the smaller shadow to the size of the candle
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   if(series!=NULL)
      series.SetDrawingAsDotsPatternPinBar(flag,redraw,ratio_body,ratio_larger_shadow,ratio_smaller_shadow);
  }
//--- Set the flag for drawing the Rails pattern with dots
void CTimeSeriesDE::SetDrawingAsDotsPatternRails(const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   if(series!=NULL)
      series.SetDrawingAsDotsPatternRails(flag,redraw);
  }
  
//+------------------------------------------------------------------+
//| Methods of returning the flag of drawing with dots               |
//+------------------------------------------------------------------+
//--- Candle formations
//--- Return the flag for drawing the Harami pattern with dots
bool CTimeSeriesDE::IsDrawingAsDotsPatternHarami(const ENUM_TIMEFRAMES timeframe)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   return(series!=NULL ? series.IsDrawingAsDotsPatternHarami() : false);
  }
//--- Return the flag for drawing the Harami Cross pattern with dots
bool CTimeSeriesDE::IsDrawingAsDotsPatternHaramiCross(const ENUM_TIMEFRAMES timeframe)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   return(series!=NULL ? series.IsDrawingAsDotsPatternHaramiCross() : false);
  }
//--- Return the flag for drawing the Tweezer pattern with dots
bool CTimeSeriesDE::IsDrawingAsDotsPatternTweezer(const ENUM_TIMEFRAMES timeframe)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   return(series!=NULL ? series.IsDrawingAsDotsPatternTweezer() : false);
  }
//--- Return the flag for drawing the Piercing Line pattern with dots
bool CTimeSeriesDE::IsDrawingAsDotsPatternPiercingLine(const ENUM_TIMEFRAMES timeframe)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   return(series!=NULL ? series.IsDrawingAsDotsPatternPiercingLine() : false);
  }
//--- Return the flag for drawing the Cloud Cover pattern with dots
bool CTimeSeriesDE::IsDrawingAsDotsPatternDarkCloudCover(const ENUM_TIMEFRAMES timeframe)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   return(series!=NULL ? series.IsDrawingAsDotsPatternDarkCloudCover() : false);
  }
//--- Return the flag for drawing the Three White Soldiers pattern with dots
bool CTimeSeriesDE::IsDrawingAsDotsPatternThreeWhiteSoldiers(const ENUM_TIMEFRAMES timeframe)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   return(series!=NULL ? series.IsDrawingAsDotsPatternThreeWhiteSoldiers() : false);
  }
//--- Return the flag for drawing the Three Black Crows pattern with dots
bool CTimeSeriesDE::IsDrawingAsDotsPatternThreeBlackCrows(const ENUM_TIMEFRAMES timeframe)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   return(series!=NULL ? series.IsDrawingAsDotsPatternThreeBlackCrows() : false);
  }
//--- Return the flag for drawing the Shooting Star pattern with dots
bool CTimeSeriesDE::IsDrawingAsDotsPatternShootingStar(const ENUM_TIMEFRAMES timeframe)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   return(series!=NULL ? series.IsDrawingAsDotsPatternShootingStar() : false);
  }
//--- Return the flag for drawing the Hammer pattern with dots
bool CTimeSeriesDE::IsDrawingAsDotsPatternHammer(const ENUM_TIMEFRAMES timeframe)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   return(series!=NULL ? series.IsDrawingAsDotsPatternHammer() : false);
  }
//--- Return the flag for drawing the Inverted Hammer pattern with dots
bool CTimeSeriesDE::IsDrawingAsDotsPatternInvertedHammer(const ENUM_TIMEFRAMES timeframe)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   return(series!=NULL ? series.IsDrawingAsDotsPatternInvertedHammer() : false);
  }
//--- Return the flag for drawing the Hanging Man pattern with dots
bool CTimeSeriesDE::IsDrawingAsDotsPatternHangingMan(const ENUM_TIMEFRAMES timeframe)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   return(series!=NULL ? series.IsDrawingAsDotsPatternHangingMan() : false);
  }
//--- Return the flag for drawing the Doji pattern with dots
bool CTimeSeriesDE::IsDrawingAsDotsPatternDoji(const ENUM_TIMEFRAMES timeframe)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   return(series!=NULL ? series.IsDrawingAsDotsPatternDoji() : false);
  }
//--- Return the flag for drawing the Dragonfly Doji pattern with dots
bool CTimeSeriesDE::IsDrawingAsDotsPatternDragonflyDoji(const ENUM_TIMEFRAMES timeframe)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   return(series!=NULL ? series.IsDrawingAsDotsPatternDragonflyDoji() : false);
  }
//--- Return the flag for drawing the Gravestone Doji pattern with dots
bool CTimeSeriesDE::IsDrawingAsDotsPatternGravestoneDoji(const ENUM_TIMEFRAMES timeframe)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   return(series!=NULL ? series.IsDrawingAsDotsPatternGravestoneDoji() : false);
  }
//--- Return the flag for drawing the Morning Star pattern with dots
bool CTimeSeriesDE::IsDrawingAsDotsPatternMorningStar(const ENUM_TIMEFRAMES timeframe)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   return(series!=NULL ? series.IsDrawingAsDotsPatternMorningStar() : false);
  }
//--- Return the flag for drawing the Morning Doji Star pattern with dots
bool CTimeSeriesDE::IsDrawingAsDotsPatternMorningDojiStar(const ENUM_TIMEFRAMES timeframe)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   return(series!=NULL ? series.IsDrawingAsDotsPatternMorningDojiStar() : false);
  }
//--- Return the flag for drawing the Evening Star pattern with dots
bool CTimeSeriesDE::IsDrawingAsDotsPatternEveningStar(const ENUM_TIMEFRAMES timeframe)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   return(series!=NULL ? series.IsDrawingAsDotsPatternEveningStar() : false);
  }
//--- Return the flag for drawing the Evening Doji Star pattern with dots
bool CTimeSeriesDE::IsDrawingAsDotsPatternEveningDojiStar(const ENUM_TIMEFRAMES timeframe)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   return(series!=NULL ? series.IsDrawingAsDotsPatternEveningDojiStar() : false);
  }
//--- Return the flag for drawing the Three Stars pattern with dots
bool CTimeSeriesDE::IsDrawingAsDotsPatternThreeStars(const ENUM_TIMEFRAMES timeframe)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   return(series!=NULL ? series.IsDrawingAsDotsPatternThreeStars() : false);
  }
//--- Return the flag for drawing the Abandoned Baby pattern with dots
bool CTimeSeriesDE::IsDrawingAsDotsPatternAbandonedBaby(const ENUM_TIMEFRAMES timeframe)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   return(series!=NULL ? series.IsDrawingAsDotsPatternAbandonedBaby() : false);
  }
//--- Price Action
//--- Return the flag for drawing the Pivot Point Reversal pattern with dots
bool CTimeSeriesDE::IsDrawingAsDotsPatternPivotPointReversal(const ENUM_TIMEFRAMES timeframe)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   return(series!=NULL ? series.IsDrawingAsDotsPatternPivotPointReversal() : false);
  }
//--- Return the flag for drawing the Outside Bar pattern with dots
bool CTimeSeriesDE::IsDrawingAsDotsPatternOutsideBar(const ENUM_TIMEFRAMES timeframe)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   return(series!=NULL ? series.IsDrawingAsDotsPatternOutsideBar() : false);
  }
//--- Return the flag for drawing the Inside Bar pattern with dots
bool CTimeSeriesDE::IsDrawingAsDotsPatternInsideBar(const ENUM_TIMEFRAMES timeframe)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   return(series!=NULL ? series.IsDrawingAsDotsPatternInsideBar() : false);
  }
//--- Return the flag for drawing the Pin Bar pattern with dots
bool CTimeSeriesDE::IsDrawingAsDotsPatternPinBar(const ENUM_TIMEFRAMES timeframe,const double ratio_body=30,   // Percentage ratio of the candle body to the full size of the candle
                                                 const double ratio_larger_shadow=60,                          // Percentage ratio of the size of the larger shadow to the size of the candle
                                                 const double ratio_smaller_shadow=30)                         // Percentage ratio of the size of the smaller shadow to the size of the candle
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   return(series!=NULL ? series.IsDrawingAsDotsPatternPinBar(ratio_body,ratio_larger_shadow,ratio_smaller_shadow) : false);
  }
//--- Return the flag for drawing the Rails pattern with dots
bool CTimeSeriesDE::IsDrawingAsDotsPatternRails(const ENUM_TIMEFRAMES timeframe)
  {
   CSeriesDE *series=this.GetSeries(timeframe);
   return(series!=NULL ? series.IsDrawingAsDotsPatternRails() : false);
  }


在后续文章中,我们将跟踪图表参数,以重置用于绘制形态图标的时间序列对象中的图表属性。在终端中打开的所有图表的所有属性都包含在图表库的图表集合中。为了从所有交易品种的时间序列集合中访问该集合的数据,我们需要将图表集合的指针传递给时间序列集合。
为此,\MQL5\Include\DoEasy\Collections\TimeSeriesCollection.mqh 交易品种时间序列集合文件接收图表集合文件。同时,在私有部分声明指向图表集合的指针

//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "ListObj.mqh"
#include "..\Objects\Series\TimeSeriesDE.mqh"
#include "..\Objects\Symbols\Symbol.mqh"
#include "ChartObjCollection.mqh"
//+------------------------------------------------------------------+
//| Symbol timeseries collection                                     |
//+------------------------------------------------------------------+
class CTimeSeriesCollection : public CBaseObjExt
  {
private:
   CListObj                m_list;                    // List of applied symbol timeseries
   CListObj                m_list_all_patterns;       // List of all patterns of all used symbol timeseries
   CChartObjCollection    *m_charts;                  // Pointer to the chart collection
   
//--- Return the timeseries index by symbol name
   int                     IndexTimeSeries(const string symbol);
public:


在类的公有部分声明新方法,即处理时间序列形态的方法:

//+------------------------------------------------------------------+
//| Methods for setting the flag of drawing the pattern using dots   |
//+------------------------------------------------------------------+
//--- Set the flag for using the Harami pattern and create a control object if it does not already exist
   void                    SetDrawingAsDotsPatternHarami(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Harami Cross pattern and create a control object if it does not already exist
   void                    SetDrawingAsDotsPatternHaramiCross(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Tweezer pattern and create a control object if it does not already exist
   void                    SetDrawingAsDotsPatternTweezer(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Piercing Line pattern and create a control object if it does not already exist
   void                    SetDrawingAsDotsPatternPiercingLine(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Cloud Cover pattern and create a control object if it does not already exist
   void                    SetDrawingAsDotsPatternDarkCloudCover(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Three White Soldiers pattern and create a control object if it does not already exist
   void                    SetDrawingAsDotsPatternThreeWhiteSoldiers(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Three Black Crows pattern and create a control object if it does not already exist
   void                    SetDrawingAsDotsPatternThreeBlackCrows(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Shooting Star pattern and create a control object if it does not already exist
   void                    SetDrawingAsDotsPatternShootingStar(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Hammer pattern and create a control object if it does not already exist
   void                    SetDrawingAsDotsPatternHammer(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Inverted Hammer pattern and create a control object if it does not already exist
   void                    SetDrawingAsDotsPatternInvertedHammer(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Hanging Man pattern and create a control object if it does not already exist
   void                    SetDrawingAsDotsPatternHangingMan(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Doji pattern and create a control object if it does not already exist
   void                    SetDrawingAsDotsPatternDoji(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Dragonfly Doji pattern and create a control object if it does not already exist
   void                    SetDrawingAsDotsPatternDragonflyDoji(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Doji Gravestone pattern and create a control object if it does not already exist
   void                    SetDrawingAsDotsPatternGravestoneDoji(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Morning Star pattern and create a control object if it does not already exist
   void                    SetDrawingAsDotsPatternMorningStar(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Morning Doji Star pattern and create a control object if it does not already exist
   void                    SetDrawingAsDotsPatternMorningDojiStar(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Evening Star pattern and create a control object if it does not already exist
   void                    SetDrawingAsDotsPatternEveningStar(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Evening Doji Star pattern and create a control object if it does not already exist
   void                    SetDrawingAsDotsPatternEveningDojiStar(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Three Stars pattern and create a control object if it does not already exist
   void                    SetDrawingAsDotsPatternThreeStars(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Abandoned Baby pattern and create a control object if it does not already exist
   void                    SetDrawingAsDotsPatternAbandonedBaby(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Pivot Point Reversal pattern and create a control object if it does not already exist
//--- Price Action
   void                    SetDrawingAsDotsPatternPivotPointReversal(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Pattern Outside and create a control object if it does not already exist
   void                    SetDrawingAsDotsPatternOutsideBar(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Pattern Inside and create a control object if it does not already exist
   void                    SetDrawingAsDotsPatternInsideBar(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
//--- Set the flag for using the Pin Bar pattern and create a control object if it does not already exist
   void                    SetDrawingAsDotsPatternPinBar(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw, // Flag of drawing with dots and Pin Bar Price Action redraw flag
                                                         const double ratio_body=30,                                                            // Percentage ratio of the candle body to the full size of the candle
                                                         const double ratio_larger_shadow=60,                                                   // Percentage ratio of the size of the larger shadow to the size of the candle
                                                         const double ratio_smaller_shadow=30);                                                 // Percentage ratio of the size of the smaller shadow to the size of the candle
//--- Set the flag for using the Rails pattern and create a control object if it does not already exist
   void                    SetDrawingAsDotsPatternRails(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw);
                       
//+------------------------------------------------------------------+
//| Methods of returning the flag of drawing with dots               |
//+------------------------------------------------------------------+
//--- Candle formations
//--- Return the flag of using the Harami pattern
   bool                    IsDrawingAsDotsPatternHarami(const string symbol,const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Harami Cross pattern
   bool                    IsDrawingAsDotsPatternHaramiCross(const string symbol,const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Tweezer pattern
   bool                    IsDrawingAsDotsPatternTweezer(const string symbol,const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Piercing Line pattern
   bool                    IsDrawingAsDotsPatternPiercingLine(const string symbol,const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Cloud Cover pattern
   bool                    IsDrawingAsDotsPatternDarkCloudCover(const string symbol,const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Three White Soldiers pattern
   bool                    IsDrawingAsDotsPatternThreeWhiteSoldiers(const string symbol,const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Three Black Crows pattern
   bool                    IsDrawingAsDotsPatternThreeBlackCrows(const string symbol,const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Shooting Star pattern
   bool                    IsDrawingAsDotsPatternShootingStar(const string symbol,const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Hammer pattern
   bool                    IsDrawingAsDotsPatternHammer(const string symbol,const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Inverted Hammer pattern
   bool                    IsDrawingAsDotsPatternInvertedHammer(const string symbol,const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Hanging Man pattern
   bool                    IsDrawingAsDotsPatternHangingMan(const string symbol,const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Doji pattern
   bool                    IsDrawingAsDotsPatternDoji(const string symbol,const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Dragonfly Doji pattern
   bool                    IsDrawingAsDotsPatternDragonflyDoji(const string symbol,const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Gravestone Doji pattern
   bool                    IsDrawingAsDotsPatternGravestoneDoji(const string symbol,const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Morning Star pattern
   bool                    IsDrawingAsDotsPatternMorningStar(const string symbol,const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Morning Doji Star pattern
   bool                    IsDrawingAsDotsPatternMorningDojiStar(const string symbol,const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Evening Star pattern
   bool                    IsDrawingAsDotsPatternEveningStar(const string symbol,const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Evening Doji Star pattern
   bool                    IsDrawingAsDotsPatternEveningDojiStar(const string symbol,const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Three Stars pattern
   bool                    IsDrawingAsDotsPatternThreeStars(const string symbol,const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Abandoned Baby pattern
   bool                    IsDrawingAsDotsPatternAbandonedBaby(const string symbol,const ENUM_TIMEFRAMES timeframe);
//--- Price Action
//--- Return the flag of using the Pivot Point Reversal pattern
   bool                    IsDrawingAsDotsPatternPivotPointReversal(const string symbol,const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Pattern Outside
   bool                    IsDrawingAsDotsPatternOutsideBar(const string symbol,const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Inside Bar pattern
   bool                    IsDrawingAsDotsPatternInsideBar(const string symbol,const ENUM_TIMEFRAMES timeframe);
//--- Return the flag of using the Pin Bar pattern
   bool                    IsDrawingAsDotsPatternPinBar(const string symbol,const ENUM_TIMEFRAMES timeframe,double ratio_body=30,   // Percentage ratio of the candle body to the full size of the candle
                                                        const double ratio_larger_shadow=60,                                        // Percentage ratio of the size of the larger shadow to the size of the candle
                                                        const double ratio_smaller_shadow=30);                                      // Percentage ratio of the size of the smaller shadow to the size of the candle
//--- Return the flag of using the Rails pattern
   bool                    IsDrawingAsDotsPatternRails(const string symbol,const ENUM_TIMEFRAMES timeframe);


在类主体的末尾,实现初始化方法,将传递给该方法的指针赋值给上面声明的图表集合指针:

//--- Draw Rails pattern labels on the chart
   void                    DrawPatternRails(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool redraw=false);
                                                
//--- Initialization
   void                    OnInit(CChartObjCollection *charts) { this.m_charts=charts; }
   
//--- Constructor
                           CTimeSeriesCollection(void);
  };


在类主体之外实现已声明的方法,以处理时间序列形态:

//+------------------------------------------------------------------+
//| Methods for setting the flag of drawing the pattern using dots   |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Set the flag for drawing the Harami pattern with dots            |
//+------------------------------------------------------------------+
void CTimeSeriesCollection::SetDrawingAsDotsPatternHarami(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   if(timeseries!=NULL)
      timeseries.SetDrawingAsDotsPatternHarami(timeframe,flag,redraw);
  }
//+------------------------------------------------------------------+
//| Set the flag for drawing the Harami Cross pattern with dots      |
//+------------------------------------------------------------------+
void CTimeSeriesCollection::SetDrawingAsDotsPatternHaramiCross(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   if(timeseries!=NULL)
      timeseries.SetDrawingAsDotsPatternHaramiCross(timeframe,flag,redraw);
  }
//+------------------------------------------------------------------+
//| Set the flag for drawing the Tweezer pattern with dots           |
//+------------------------------------------------------------------+
void CTimeSeriesCollection::SetDrawingAsDotsPatternTweezer(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   if(timeseries!=NULL)
      timeseries.SetDrawingAsDotsPatternTweezer(timeframe,flag,redraw);
  }
//+------------------------------------------------------------------+
//| Set the flag for drawing the Piercing Line pattern with dots     |
//+------------------------------------------------------------------+
void CTimeSeriesCollection::SetDrawingAsDotsPatternPiercingLine(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   if(timeseries!=NULL)
      timeseries.SetDrawingAsDotsPatternPiercingLine(timeframe,flag,redraw);
  }
//+----------------------------------------------------------------------+
//|Set the flag for drawing the Cloud Cover pattern with dots            |
//+----------------------------------------------------------------------+
void CTimeSeriesCollection::SetDrawingAsDotsPatternDarkCloudCover(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   if(timeseries!=NULL)
      timeseries.SetDrawingAsDotsPatternDarkCloudCover(timeframe,flag,redraw);
  }
//+--------------------------------------------------------------------+
//| Set the flag for drawing the Three White Soldiers pattern with dots|
//+--------------------------------------------------------------------+
void CTimeSeriesCollection::SetDrawingAsDotsPatternThreeWhiteSoldiers(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   if(timeseries!=NULL)
      timeseries.SetDrawingAsDotsPatternThreeWhiteSoldiers(timeframe,flag,redraw);
  }
//+------------------------------------------------------------------+
//| Set the flag for drawing the Three Black Crows pattern with dots |
//+------------------------------------------------------------------+
void CTimeSeriesCollection::SetDrawingAsDotsPatternThreeBlackCrows(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   if(timeseries!=NULL)
      timeseries.SetDrawingAsDotsPatternThreeBlackCrows(timeframe,flag,redraw);
  }
//+------------------------------------------------------------------+
//| Set the flag for drawing the Shooting Star pattern with dots     |
//+------------------------------------------------------------------+
void CTimeSeriesCollection::SetDrawingAsDotsPatternShootingStar(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   if(timeseries!=NULL)
      timeseries.SetDrawingAsDotsPatternShootingStar(timeframe,flag,redraw);
  }
//+------------------------------------------------------------------+
//| Set the flag for drawing the Hammer pattern with dots            |
//+------------------------------------------------------------------+
void CTimeSeriesCollection::SetDrawingAsDotsPatternHammer(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   if(timeseries!=NULL)
      timeseries.SetDrawingAsDotsPatternHammer(timeframe,flag,redraw);
  }
//+------------------------------------------------------------------+
//| Set the flag for drawing the Inverted Hammer pattern with dots   |
//+------------------------------------------------------------------+
void CTimeSeriesCollection::SetDrawingAsDotsPatternInvertedHammer(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   if(timeseries!=NULL)
      timeseries.SetDrawingAsDotsPatternInvertedHammer(timeframe,flag,redraw);
  }
//+------------------------------------------------------------------+
//| Set the flag for drawing the Hanging Man pattern with dots       |
//+------------------------------------------------------------------+
void CTimeSeriesCollection::SetDrawingAsDotsPatternHangingMan(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   if(timeseries!=NULL)
      timeseries.SetDrawingAsDotsPatternHangingMan(timeframe,flag,redraw);
  }
//+------------------------------------------------------------------+
//| Set the flag for drawing the Doji pattern with dots              |
//+------------------------------------------------------------------+
void CTimeSeriesCollection::SetDrawingAsDotsPatternDoji(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   if(timeseries!=NULL)
      timeseries.SetDrawingAsDotsPatternDoji(timeframe,flag,redraw);
  }
//+------------------------------------------------------------------+
//| Set the flag for drawing the Dragonfly Doji pattern with dots    |
//+------------------------------------------------------------------+
void CTimeSeriesCollection::SetDrawingAsDotsPatternDragonflyDoji(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   if(timeseries!=NULL)
      timeseries.SetDrawingAsDotsPatternDragonflyDoji(timeframe,flag,redraw);
  }
//+------------------------------------------------------------------+
//| Set the flag for drawing the Gravestone Doji pattern with dots   |
//+------------------------------------------------------------------+
void CTimeSeriesCollection::SetDrawingAsDotsPatternGravestoneDoji(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   if(timeseries!=NULL)
      timeseries.SetDrawingAsDotsPatternGravestoneDoji(timeframe,flag,redraw);
  }
//+------------------------------------------------------------------+
//| Set the flag for drawing the Morning Star pattern with dots      |
//+------------------------------------------------------------------+
void CTimeSeriesCollection::SetDrawingAsDotsPatternMorningStar(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   if(timeseries!=NULL)
      timeseries.SetDrawingAsDotsPatternMorningStar(timeframe,flag,redraw);
  }
//+-------------------------------------------------------------------+
//|Set the flag for drawing the Morning Doji Star pattern with dots   |
//+-------------------------------------------------------------------+
void CTimeSeriesCollection::SetDrawingAsDotsPatternMorningDojiStar(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   if(timeseries!=NULL)
      timeseries.SetDrawingAsDotsPatternMorningDojiStar(timeframe,flag,redraw);
  }
//+------------------------------------------------------------------+
//| Set the flag for drawing the Evening Star pattern with dots      |
//+------------------------------------------------------------------+
void CTimeSeriesCollection::SetDrawingAsDotsPatternEveningStar(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   if(timeseries!=NULL)
      timeseries.SetDrawingAsDotsPatternEveningStar(timeframe,flag,redraw);
  }
//+-------------------------------------------------------------------+
//|Set the flag for drawing the Evening Doji Star pattern with dots   |
//+-------------------------------------------------------------------+
void CTimeSeriesCollection::SetDrawingAsDotsPatternEveningDojiStar(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   if(timeseries!=NULL)
      timeseries.SetDrawingAsDotsPatternEveningDojiStar(timeframe,flag,redraw);
  }
//+------------------------------------------------------------------+
//| Set the flag for drawing the Three Stars pattern with dots       |
//+------------------------------------------------------------------+
void CTimeSeriesCollection::SetDrawingAsDotsPatternThreeStars(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   if(timeseries!=NULL)
      timeseries.SetDrawingAsDotsPatternThreeStars(timeframe,flag,redraw);
  }
//+------------------------------------------------------------------+
//| Set the flag for drawing the Abandoned Baby pattern with dots    |
//+------------------------------------------------------------------+
void CTimeSeriesCollection::SetDrawingAsDotsPatternAbandonedBaby(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   if(timeseries!=NULL)
      timeseries.SetDrawingAsDotsPatternAbandonedBaby(timeframe,flag,redraw);
  }
//--- Price Action
//+------------------------------------------------------------------+
//|Set the flag for drawing the Pivot Point Reversal pattern with dots|
//+------------------------------------------------------------------+
void CTimeSeriesCollection::SetDrawingAsDotsPatternPivotPointReversal(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   if(timeseries!=NULL)
      timeseries.SetDrawingAsDotsPatternPivotPointReversal(timeframe,flag,redraw);
  }
//+----------------------------------------------------------------------+
//|Set the flag for drawing the Outside Bar pattern with dots            |
//+----------------------------------------------------------------------+
void CTimeSeriesCollection::SetDrawingAsDotsPatternOutsideBar(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   if(timeseries!=NULL)
      timeseries.SetDrawingAsDotsPatternOutsideBar(timeframe,flag,redraw);
  }
//+------------------------------------------------------------------+
//| Set the flag for drawing the Inside Bar pattern with dots        |
//+------------------------------------------------------------------+
void CTimeSeriesCollection::SetDrawingAsDotsPatternInsideBar(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   if(timeseries!=NULL)
      timeseries.SetDrawingAsDotsPatternInsideBar(timeframe,flag,redraw);
  }
//+------------------------------------------------------------------+
//| Set the flag for drawing the Pin Bar pattern with dots           |
//+------------------------------------------------------------------+
void CTimeSeriesCollection::SetDrawingAsDotsPatternPinBar(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                                          const bool flag,const bool redraw,                   // Flag of drawing with dots and Pin Bar Price Action redraw flag
                                                          const double ratio_body=30,                          // Percentage ratio of the candle body to the full size of the candle
                                                          const double ratio_larger_shadow=60,                 // Percentage ratio of the size of the larger shadow to the size of the candle
                                                          const double ratio_smaller_shadow=30)                // Percentage ratio of the size of the smaller shadow to the size of the candle
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   if(timeseries!=NULL)
      timeseries.SetDrawingAsDotsPatternPinBar(timeframe,flag,redraw,ratio_body,ratio_larger_shadow,ratio_smaller_shadow);
  }
//+------------------------------------------------------------------+
//| Set the flag for drawing the Rails pattern with dots             |
//+------------------------------------------------------------------+
void CTimeSeriesCollection::SetDrawingAsDotsPatternRails(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   if(timeseries!=NULL)
      timeseries.SetDrawingAsDotsPatternRails(timeframe,flag,redraw);
  }
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Methods of returning the flag of drawing with dots               |
//+------------------------------------------------------------------+
//--- Candle formations
//+------------------------------------------------------------------+
//| Return the flag for drawing the Harami pattern with dots         |
//+------------------------------------------------------------------+
bool CTimeSeriesCollection::IsDrawingAsDotsPatternHarami(const string symbol,const ENUM_TIMEFRAMES timeframe)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   return(timeseries!=NULL ? timeseries.IsDrawingAsDotsPatternHarami(timeframe) : false);
  }
//+------------------------------------------------------------------+
//| Return the flag for drawing the Harami Cross pattern with dots   |
//+------------------------------------------------------------------+
bool CTimeSeriesCollection::IsDrawingAsDotsPatternHaramiCross(const string symbol,const ENUM_TIMEFRAMES timeframe)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   return(timeseries!=NULL ? timeseries.IsDrawingAsDotsPatternHaramiCross(timeframe) : false);
  }
//+------------------------------------------------------------------+
//| Return the flag for drawing the Tweezer pattern with dots        |
//+------------------------------------------------------------------+
bool CTimeSeriesCollection::IsDrawingAsDotsPatternTweezer(const string symbol,const ENUM_TIMEFRAMES timeframe)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   return(timeseries!=NULL ? timeseries.IsDrawingAsDotsPatternTweezer(timeframe) : false);
  }
//+------------------------------------------------------------------+
//| Return the flag for drawing the Piercing Line pattern with dots  |
//+------------------------------------------------------------------+
bool CTimeSeriesCollection::IsDrawingAsDotsPatternPiercingLine(const string symbol,const ENUM_TIMEFRAMES timeframe)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   return(timeseries!=NULL ? timeseries.IsDrawingAsDotsPatternPiercingLine(timeframe) : false);
  }
//+-------------------------------------------------------------------+
//|Return the flag for drawing the Cloud Cover pattern with dots      |
//+-------------------------------------------------------------------+
bool CTimeSeriesCollection::IsDrawingAsDotsPatternDarkCloudCover(const string symbol,const ENUM_TIMEFRAMES timeframe)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   return(timeseries!=NULL ? timeseries.IsDrawingAsDotsPatternDarkCloudCover(timeframe) : false);
  }
//+-----------------------------------------------------------------------+
//| Return the flag for drawing the Three White Soldiers pattern with dots|
//+-----------------------------------------------------------------------+
bool CTimeSeriesCollection::IsDrawingAsDotsPatternThreeWhiteSoldiers(const string symbol,const ENUM_TIMEFRAMES timeframe)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   return(timeseries!=NULL ? timeseries.IsDrawingAsDotsPatternThreeWhiteSoldiers(timeframe) : false);
  }
//+--------------------------------------------------------------------+
//| Return the flag for drawing the Three Black Crows pattern with dots|
//+--------------------------------------------------------------------+
bool CTimeSeriesCollection::IsDrawingAsDotsPatternThreeBlackCrows(const string symbol,const ENUM_TIMEFRAMES timeframe)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   return(timeseries!=NULL ? timeseries.IsDrawingAsDotsPatternThreeBlackCrows(timeframe) : false);
  }
//+------------------------------------------------------------------+
//| Return the flag for drawing the Shooting Star pattern with dots  |
//+------------------------------------------------------------------+
bool CTimeSeriesCollection::IsDrawingAsDotsPatternShootingStar(const string symbol,const ENUM_TIMEFRAMES timeframe)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   return(timeseries!=NULL ? timeseries.IsDrawingAsDotsPatternShootingStar(timeframe) : false);
  }
//+------------------------------------------------------------------+
//| Return the flag for drawing the Hammer pattern with dots         |
//+------------------------------------------------------------------+
bool CTimeSeriesCollection::IsDrawingAsDotsPatternHammer(const string symbol,const ENUM_TIMEFRAMES timeframe)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   return(timeseries!=NULL ? timeseries.IsDrawingAsDotsPatternHammer(timeframe) : false);
  }
//+------------------------------------------------------------------+
//| Return the flag for drawing the Inverted Hammer pattern with dots|
//+------------------------------------------------------------------+
bool CTimeSeriesCollection::IsDrawingAsDotsPatternInvertedHammer(const string symbol,const ENUM_TIMEFRAMES timeframe)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   return(timeseries!=NULL ? timeseries.IsDrawingAsDotsPatternInvertedHammer(timeframe) : false);
  }
//+------------------------------------------------------------------+
//| Return the flag for drawing the Hanging Man pattern with dots    |
//+------------------------------------------------------------------+
bool CTimeSeriesCollection::IsDrawingAsDotsPatternHangingMan(const string symbol,const ENUM_TIMEFRAMES timeframe)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   return(timeseries!=NULL ? timeseries.IsDrawingAsDotsPatternHangingMan(timeframe) : false);
  }
//+------------------------------------------------------------------+
//| Return the flag for drawing the Doji pattern with dots           |
//+------------------------------------------------------------------+
bool CTimeSeriesCollection::IsDrawingAsDotsPatternDoji(const string symbol,const ENUM_TIMEFRAMES timeframe)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   return(timeseries!=NULL ? timeseries.IsDrawingAsDotsPatternDoji(timeframe) : false);
  }
//+------------------------------------------------------------------+
//| Return the flag for drawing the Dragonfly Doji pattern with dots |
//+------------------------------------------------------------------+
bool CTimeSeriesCollection::IsDrawingAsDotsPatternDragonflyDoji(const string symbol,const ENUM_TIMEFRAMES timeframe)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   return(timeseries!=NULL ? timeseries.IsDrawingAsDotsPatternDragonflyDoji(timeframe) : false);
  }
//+------------------------------------------------------------------+
//| Return the flag for drawing the Gravestone Doji pattern with dots|
//+------------------------------------------------------------------+
bool CTimeSeriesCollection::IsDrawingAsDotsPatternGravestoneDoji(const string symbol,const ENUM_TIMEFRAMES timeframe)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   return(timeseries!=NULL ? timeseries.IsDrawingAsDotsPatternGravestoneDoji(timeframe) : false);
  }
//+------------------------------------------------------------------+
//| Return the flag for drawing the Morning Star pattern with dots   |
//+------------------------------------------------------------------+
bool CTimeSeriesCollection::IsDrawingAsDotsPatternMorningStar(const string symbol,const ENUM_TIMEFRAMES timeframe)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   return(timeseries!=NULL ? timeseries.IsDrawingAsDotsPatternMorningStar(timeframe) : false);
  }
//+---------------------------------------------------------------------+
//| Return the flag for drawing the Morning Doji Star pattern with dots |
//+---------------------------------------------------------------------+
bool CTimeSeriesCollection::IsDrawingAsDotsPatternMorningDojiStar(const string symbol,const ENUM_TIMEFRAMES timeframe)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   return(timeseries!=NULL ? timeseries.IsDrawingAsDotsPatternMorningDojiStar(timeframe) : false);
  }
//+------------------------------------------------------------------+
//| Return the flag for drawing the Evening Star pattern with dots   |
//+------------------------------------------------------------------+
bool CTimeSeriesCollection::IsDrawingAsDotsPatternEveningStar(const string symbol,const ENUM_TIMEFRAMES timeframe)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   return(timeseries!=NULL ? timeseries.IsDrawingAsDotsPatternEveningStar(timeframe) : false);
  }
//+---------------------------------------------------------------------+
//| Return the flag for drawing the Evening Doji Star pattern with dots |
//+---------------------------------------------------------------------+
bool CTimeSeriesCollection::IsDrawingAsDotsPatternEveningDojiStar(const string symbol,const ENUM_TIMEFRAMES timeframe)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   return(timeseries!=NULL ? timeseries.IsDrawingAsDotsPatternEveningDojiStar(timeframe) : false);
  }
//+------------------------------------------------------------------+
//| Return the flag for drawing the Three Stars pattern with dots    |
//+------------------------------------------------------------------+
bool CTimeSeriesCollection::IsDrawingAsDotsPatternThreeStars(const string symbol,const ENUM_TIMEFRAMES timeframe)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   return(timeseries!=NULL ? timeseries.IsDrawingAsDotsPatternThreeStars(timeframe) : false);
  }
//+------------------------------------------------------------------+
//| Return the flag for drawing the Abandoned Baby pattern with dots |
//+------------------------------------------------------------------+
bool CTimeSeriesCollection::IsDrawingAsDotsPatternAbandonedBaby(const string symbol,const ENUM_TIMEFRAMES timeframe)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   return(timeseries!=NULL ? timeseries.IsDrawingAsDotsPatternAbandonedBaby(timeframe) : false);
  }
//--- Price Action
//+-------------------------------------------------------------------------+
//| Return the flag for drawing the Pivot Point Reversal pattern with dots  |
//+-------------------------------------------------------------------------+
bool CTimeSeriesCollection::IsDrawingAsDotsPatternPivotPointReversal(const string symbol,const ENUM_TIMEFRAMES timeframe)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   return(timeseries!=NULL ? timeseries.IsDrawingAsDotsPatternPivotPointReversal(timeframe) : false);
  }
//+-------------------------------------------------------------------+
//|Return the flag for drawing the Outside Bar pattern with dots      |
//+-------------------------------------------------------------------+
bool CTimeSeriesCollection::IsDrawingAsDotsPatternOutsideBar(const string symbol,const ENUM_TIMEFRAMES timeframe)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   return(timeseries!=NULL ? timeseries.IsDrawingAsDotsPatternOutsideBar(timeframe) : false);
  }
//+------------------------------------------------------------------+
//| Return the flag for drawing the Inside Bar pattern with dots     |
//+------------------------------------------------------------------+
bool CTimeSeriesCollection::IsDrawingAsDotsPatternInsideBar(const string symbol,const ENUM_TIMEFRAMES timeframe)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   return(timeseries!=NULL ? timeseries.IsDrawingAsDotsPatternInsideBar(timeframe) : false);
  }
//+------------------------------------------------------------------+
//| Return the flag for drawing the Pin Bar pattern with dots        |
//+------------------------------------------------------------------+
bool CTimeSeriesCollection::IsDrawingAsDotsPatternPinBar(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                                         const double ratio_body=30,                        // Percentage ratio of the candle body to the full size of the candle
                                                         const double ratio_larger_shadow=60,               // Percentage ratio of the size of the larger shadow to the size of the candle
                                                         const double ratio_smaller_shadow=30)              // Percentage ratio of the size of the smaller shadow to the size of the candle
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   return(timeseries!=NULL ? timeseries.IsDrawingAsDotsPatternPinBar(timeframe,ratio_body,ratio_larger_shadow,ratio_smaller_shadow) : false);
  }
//+------------------------------------------------------------------+
//| Return the flag for drawing the Rails pattern with dots          |
//+------------------------------------------------------------------+
bool CTimeSeriesCollection::IsDrawingAsDotsPatternRails(const string symbol,const ENUM_TIMEFRAMES timeframe)
  {
   CTimeSeriesDE *timeseries=this.GetTimeseries(symbol);
   return(timeseries!=NULL ? timeseries.IsDrawingAsDotsPatternRails(timeframe) : false);
  }

在上一篇文章中,我创建了类似的方法,并对其进行了更详细的介绍。基本上,一切都很简单:我们获取指向所需的交易品种时间序列的指针,并返回所获取的时间序列上的同名方法的结果。反过来,也可以通过完全相同的方法获得所需的图表周期的时间序列指针。从时间序列模式控制对象中调用必要的控制方法,该方法返回指针,再从上述时间序列中调用指针 - 如此循环往复,直到得到所需的结果。就相同代码的数量而言,这种设计是嵌套式的,很不方便。稍后,我将尝试以不同的方式访问必要的对象,从而缩短它。

同样的事情也需要在 \MT5\MQL5\Include\DoEasy\Engine.mqh 中的 CEngine 库主类中完成。

在所有形态处理方法中,替换相同或相似的输入字符串

CArrayObj *list=this.GetListPatterns(symbol,timeframe);

使用下面的方法:

CArrayObj *list=this.GetListPatterns(CorrectSymbol(symbol),CorrectTimeframe(timeframe));

在这里,我们用文章开头的调整这些参数的函数替换了方法参数中传递的交易品种和图表周期。


在涉及形态处理方法的章节中,实现新的方法来处理作为点的图案绘制标记

//--- Set the flag for using the Rails pattern and create a control object if it does not already exist
   void                 SeriesSetUsedPatternRails(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag)
                          {
                           this.m_time_series.SetUsedPatternRails(CorrectSymbol(symbol),CorrectTimeframe(timeframe),flag);
                          }

//--- Set the flag for drawing the Harami pattern with dots
   void                 SeriesSetDrawingAsDotsPatternHarami(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw=false)
                          {
                           this.m_time_series.SetDrawingAsDotsPatternHarami(CorrectSymbol(symbol),CorrectTimeframe(timeframe),flag,redraw);
                          }
//--- Set the flag for drawing the Harami Cross pattern with dots
   void                 SeriesSetDrawingAsDotsPatternHaramiCross(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw=false)
                          {
                           this.m_time_series.SetDrawingAsDotsPatternHaramiCross(CorrectSymbol(symbol),CorrectTimeframe(timeframe),flag,redraw);
                          }
//--- Set the flag for drawing the Tweezer pattern with dots
   void                 SeriesSetDrawingAsDotsPatternTweezer(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw=false)
                          {
                           this.m_time_series.SetDrawingAsDotsPatternTweezer(CorrectSymbol(symbol),CorrectTimeframe(timeframe),flag,redraw);
                          }
//--- Set the flag for drawing the Piercing Line pattern with dots
   void                 SeriesSetDrawingAsDotsPatternPiercingLine(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw=false)
                          {
                           this.m_time_series.SetDrawingAsDotsPatternPiercingLine(CorrectSymbol(symbol),CorrectTimeframe(timeframe),flag,redraw);
                          }
//--- Set the flag for drawing the Cloud Cover pattern with dots
   void                 SeriesSetDrawingAsDotsPatternDarkCloudCover(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw=false)
                          {
                           this.m_time_series.SetDrawingAsDotsPatternDarkCloudCover(CorrectSymbol(symbol),CorrectTimeframe(timeframe),flag,redraw);
                          }
//--- Set the flag for drawing the Three White Soldiers pattern with dots
   void                 SeriesSetDrawingAsDotsPatternThreeWhiteSoldiers(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw=false)
                          {
                           this.m_time_series.SetDrawingAsDotsPatternThreeWhiteSoldiers(CorrectSymbol(symbol),CorrectTimeframe(timeframe),flag,redraw);
                          }
//--- Set the flag for drawing the Three Black Crows pattern with dots
   void                 SeriesSetDrawingAsDotsPatternThreeBlackCrows(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw=false)
                          {
                           this.m_time_series.SetDrawingAsDotsPatternThreeBlackCrows(CorrectSymbol(symbol),CorrectTimeframe(timeframe),flag,redraw);
                          }
//--- Set the flag for drawing the Shooting Star pattern with dots
   void                 SeriesSetDrawingAsDotsPatternShootingStar(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw=false)
                          {
                           this.m_time_series.SetDrawingAsDotsPatternShootingStar(CorrectSymbol(symbol),CorrectTimeframe(timeframe),flag,redraw);
                          }
//--- Set the flag for drawing the Hammer pattern with dots
   void                 SeriesSetDrawingAsDotsPatternHammer(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw=false)
                          {
                           this.m_time_series.SetDrawingAsDotsPatternHammer(CorrectSymbol(symbol),CorrectTimeframe(timeframe),flag,redraw);
                          }
//--- Set the flag for drawing the Inverted Hammer pattern with dots
   void                 SeriesSetDrawingAsDotsPatternInvertedHammer(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw=false)
                          {
                           this.m_time_series.SetDrawingAsDotsPatternInvertedHammer(CorrectSymbol(symbol),CorrectTimeframe(timeframe),flag,redraw);
                          }
//--- Set the flag for drawing the Hanging Man pattern with dots
   void                 SeriesSetDrawingAsDotsPatternHangingMan(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw=false)
                          {
                           this.m_time_series.SetDrawingAsDotsPatternHangingMan(CorrectSymbol(symbol),CorrectTimeframe(timeframe),flag,redraw);
                          }
//--- Set the flag for drawing the Doji pattern with dots
   void                 SeriesSetDrawingAsDotsPatternDoji(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw=false)
                          {
                           this.m_time_series.SetDrawingAsDotsPatternDoji(CorrectSymbol(symbol),CorrectTimeframe(timeframe),flag,redraw);
                          }
//--- Set the flag for drawing the Dragonfly Doji pattern with dots
   void                 SeriesSetDrawingAsDotsPatternDragonflyDoji(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw=false)
                          {
                           this.m_time_series.SetDrawingAsDotsPatternDragonflyDoji(CorrectSymbol(symbol),CorrectTimeframe(timeframe),flag,redraw);
                          }
//--- Set the flag for drawing the Gravestone Doji pattern with dots
   void                 SeriesSetDrawingAsDotsPatternGravestoneDoji(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw=false)
                          {
                           this.m_time_series.SetDrawingAsDotsPatternGravestoneDoji(CorrectSymbol(symbol),CorrectTimeframe(timeframe),flag,redraw);
                          }
//--- Set the flag for drawing the Morning Star pattern with dots
   void                 SeriesSetDrawingAsDotsPatternMorningStar(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw=false)
                          {
                           this.m_time_series.SetDrawingAsDotsPatternMorningStar(CorrectSymbol(symbol),CorrectTimeframe(timeframe),flag,redraw);
                          }
//--- Set the flag for drawing the Morning Doji Star pattern with dots
   void                 SeriesSetDrawingAsDotsPatternMorningDojiStar(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw=false)
                          {
                           this.m_time_series.SetDrawingAsDotsPatternMorningDojiStar(CorrectSymbol(symbol),CorrectTimeframe(timeframe),flag,redraw);
                          }
//--- Set the flag for drawing the Evening Star pattern with dots
   void                 SeriesSetDrawingAsDotsPatternEveningStar(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw=false)
                          {
                           this.m_time_series.SetDrawingAsDotsPatternEveningStar(CorrectSymbol(symbol),CorrectTimeframe(timeframe),flag,redraw);
                          }
//--- Set the flag for drawing the Evening Doji Star pattern with dots
   void                 SeriesSetDrawingAsDotsPatternEveningDojiStar(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw=false)
                          {
                           this.m_time_series.SetDrawingAsDotsPatternEveningDojiStar(CorrectSymbol(symbol),CorrectTimeframe(timeframe),flag,redraw);
                          }
//--- Set the flag for drawing the Three Stars pattern with dots
   void                 SeriesSetDrawingAsDotsPatternThreeStars(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw=false)
                          {
                           this.m_time_series.SetDrawingAsDotsPatternThreeStars(CorrectSymbol(symbol),CorrectTimeframe(timeframe),flag,redraw);
                          }
//--- Set the flag for drawing the Abandoned Baby pattern with dots
   void                 SeriesSetDrawingAsDotsPatternAbandonedBaby(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw=false)
                          {
                           this.m_time_series.SetDrawingAsDotsPatternAbandonedBaby(CorrectSymbol(symbol),CorrectTimeframe(timeframe),flag,redraw);
                          }
//--- Set the flag for drawing the Pivot Point Reversal pattern with dots
//--- Price Action
   void                 SeriesSetDrawingAsDotsPatternPivotPointReversal(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw=false)
                          {
                           this.m_time_series.SetDrawingAsDotsPatternPivotPointReversal(CorrectSymbol(symbol),CorrectTimeframe(timeframe),flag,redraw);
                          }
//--- Set the flag for drawing the Outside Bar pattern with dots
   void                 SeriesSetDrawingAsDotsPatternOutsideBar(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw=false)
                          {
                           this.m_time_series.SetDrawingAsDotsPatternOutsideBar(CorrectSymbol(symbol),CorrectTimeframe(timeframe),flag,redraw);
                          }
//--- Set the flag for drawing the Inside Bar pattern with dots
   void                 SeriesSetDrawingAsDotsPatternInsideBar(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw=false)
                          {
                           this.m_time_series.SetDrawingAsDotsPatternInsideBar(CorrectSymbol(symbol),CorrectTimeframe(timeframe),flag,redraw);
                          }
//--- Set the flag for drawing the Pin Bar pattern with dots
   void                 SeriesSetDrawingAsDotsPatternPinBar(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                                            const bool flag,const bool redraw=false,  // Flag of drawing with dots and Pin Bar Price Action redraw flag
                                                            const double ratio_body=30,               // Percentage ratio of the candle body to the full size of the candle
                                                            const double ratio_larger_shadow=60,      // Percentage ratio of the size of the larger shadow to the size of the candle
                                                            const double ratio_smaller_shadow=30)     // Percentage ratio of the size of the smaller shadow to the size of the candle
                          {
                           this.m_time_series.SetDrawingAsDotsPatternPinBar(CorrectSymbol(symbol),CorrectTimeframe(timeframe),flag,redraw,ratio_body,ratio_larger_shadow,ratio_smaller_shadow);
                          }
//--- Set the flag for drawing the Rails pattern with dots
   void                 SeriesSetDrawingAsDotsPatternRails(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool flag,const bool redraw=false)
                          {
                           this.m_time_series.SetDrawingAsDotsPatternRails(CorrectSymbol(symbol),CorrectTimeframe(timeframe),flag,redraw);
                          }

//--- Draw Harami pattern labels on the chart
   void                 SeriesDrawPatternHarami(const string symbol,const ENUM_TIMEFRAMES timeframe,const bool redraw=false)
                          {
                           this.m_time_series.DrawPatternHarami(CorrectSymbol(symbol),CorrectTimeframe(timeframe),redraw);
                          }

这些方法会调用上述时间序列集合类的相应方法。


在同一部分中,执行隐藏所有形态信息面板的方法,但位于指定柱形时间的形态除外

//--- Hides info panels of all patterns except the specified one
   void                 SeriesPatternHideAllInfoPanelsExceptOne(const ulong pattern_code,const bool redraw=false)
                          {
                           CArrayObj *list=CSelect::ByPatternProperty(this.GetListAllPatterns(),PATTERN_PROP_CODE,pattern_code,NO_EQUAL);
                           if(list==NULL)
                              return;
                           for(int i=list.Total()-1;i>=0;i--)
                             {
                              CPattern *obj=list.At(i);
                              if(obj!=NULL)
                                 obj.HideInfoPanel();
                             }
                           if(redraw)
                              ::ChartRedraw();
                          }
//--- Hide info panels of all patterns except those at the specified time of the bar
   void                 SeriesPatternHideAllInfoPanelsExceptBarTime(const datetime bar_time,const bool redraw=false)
                          {
                           CArrayObj *list=CSelect::ByPatternProperty(this.GetListAllPatterns(),PATTERN_PROP_TIME,bar_time,NO_EQUAL);
                           if(list==NULL)
                              return;
                           for(int i=list.Total()-1;i>=0;i--)
                             {
                              CPattern *obj=list.At(i);
                              if(obj!=NULL)
                                 obj.HideInfoPanel();
                             }
                           if(redraw)
                              ::ChartRedraw();
                          }

在这里,我们只从所有形态列表中获取未出现在指定开启时间柱形上的形态。然后,在循环中,我们使用生成的列表获取下一个形态对象的指针,并隐藏其信息面板。在周期结束时,如果设置了重绘标志,则重绘图表。


在将指向所有必要集合的指针传递给交易类和集合类的方法中添加传递到图表集合的指针:

//--- Play a sound by its description
   bool                 PlaySoundByDescription(const string sound_description);

//--- Pass the pointers to all the necessary collections to the trading class and the indicator buffer collection class
   void                 CollectionOnInit(void)
                          {
                           this.m_trading.OnInit(this.GetAccountCurrent(),this.m_symbols.GetObject(),this.m_market.GetObject(),this.m_history.GetObject(),this.m_events.GetObject());
                           this.m_buffers.OnInit(this.m_time_series.GetObject(),this.m_indicators.GetObject());
                           this.m_time_series.OnInit(this.GetChartObjCollection());
                          }
//--- Set the spread multiplier for symbol trading objects in the symbol collection
   void                 SetSpreadMultiplier(const uint value=1,const string symbol=NULL)  { this.m_trading.SetSpreadMultiplier(value,symbol);   }


在 DoEasy 库事件处理程序中,创建一个用于处理图表收集事件的空挡

//--- Handling market watch window events
   else if(idx>MARKET_WATCH_EVENT_NO_EVENT && idx<SYMBOL_EVENTS_NEXT_CODE)
     {
      //--- Market Watch window event
      string descr=this.GetMWEventDescription((ENUM_MW_EVENT)idx);
      string name=(idx==MARKET_WATCH_EVENT_SYMBOL_SORT ? "" : ": "+sparam);
      Print(TimeMSCtoString(lparam)," ",descr,name);
     }

//--- Handle chart events
   else if(idx>CHART_OBJ_EVENT_NO_EVENT && idx<CHART_OBJ_EVENTS_NEXT_CODE)
     {
      
     }
     
//--- Handling timeseries events
   else if(idx>SERIES_EVENTS_NO_EVENT && idx<SERIES_EVENTS_NEXT_CODE)
     {

随后,我将在这里添加处理程序,用于调整图表大小,将新值传递给时间序列集合,并从中传递给模式对象。

现在一切准备就绪,可以测试结果了。



测试

要执行测试,让我们使用上一篇文章中的 EA,并将其保存到新创建的 \MQL5\Experts\TestDoEasy\Part135\ 文件夹中,命名为 TestDoEasy135.mq5

在输入列表中添加变量,设置绘制带点形态的标志

//--- input variables
input    ushort            InpMagic             =  123;  // Magic number
input    double            InpLots              =  0.1;  // Lots
input    uint              InpStopLoss          =  150;  // StopLoss in points
input    uint              InpTakeProfit        =  150;  // TakeProfit in points
input    uint              InpDistance          =  50;   // Pending orders distance (points)
input    uint              InpDistanceSL        =  50;   // StopLimit orders distance (points)
input    uint              InpDistancePReq      =  50;   // Distance for Pending Request's activate (points)
input    uint              InpBarsDelayPReq     =  5;    // Bars delay for Pending Request's activate (current timeframe)
input    uint              InpSlippage          =  5;    // Slippage in points
input    uint              InpSpreadMultiplier  =  1;    // Spread multiplier for adjusting stop-orders by StopLevel
input    uchar             InpTotalAttempts     =  5;    // Number of trading attempts
sinput   double            InpWithdrawal        =  10;   // Withdrawal funds (in tester)

sinput   uint              InpButtShiftX        =  0;    // Buttons X shift 
sinput   uint              InpButtShiftY        =  10;   // Buttons Y shift 

input    uint              InpTrailingStop      =  50;   // Trailing Stop (points)
input    uint              InpTrailingStep      =  20;   // Trailing Step (points)
input    uint              InpTrailingStart     =  0;    // Trailing Start (points)
input    uint              InpStopLossModify    =  20;   // StopLoss for modification (points)
input    uint              InpTakeProfitModify  =  60;   // TakeProfit for modification (points)

sinput   ENUM_SYMBOLS_MODE InpModeUsedSymbols   =  SYMBOLS_MODE_CURRENT;            // Mode of used symbols list
sinput   string            InpUsedSymbols       =  "EURUSD,AUDUSD,EURAUD,EURCAD,EURGBP,EURJPY,EURUSD,GBPUSD,NZDUSD,USDCAD,USDJPY";  // List of used symbols (comma - separator)
sinput   ENUM_TIMEFRAMES_MODE InpModeUsedTFs    =  TIMEFRAMES_MODE_CURRENT;         // Mode of used timeframes list
sinput   string            InpUsedTFs           =  "M1,M5,M15,M30,H1,H4,D1,W1,MN1"; // List of used timeframes (comma - separator)

sinput   double            InpPinBarRatioBody   =  30.0;                            // Pin Bar Ratio Body to Candle size
sinput   double            InpPinBarRatioLarger =  60.0;                            // Pin Bar Ratio Larger shadow to Candle size
sinput   double            InpPinBarRatioSmaller=  30.0;                            // Pin Bar Ratio Smaller shadow to Candle size
sinput   bool              InpDrawPatternsAsDots=  true;                            // Draw Patterns as dots

sinput   ENUM_INPUT_YES_NO InpUseBook           =  INPUT_NO;                        // Use Depth of Market
sinput   ENUM_INPUT_YES_NO InpUseMqlSignals     =  INPUT_NO;                        // Use signal service
sinput   ENUM_INPUT_YES_NO InpUseCharts         =  INPUT_NO;                        // Use Charts control
sinput   ENUM_INPUT_YES_NO InpUseSounds         =  INPUT_YES;                       // Use sounds

//--- global variables

如果为 "true",则所有找到的形态都会在图表上画成点。如果为 "false",则将使用位图对象绘制 "Inside Bar" 形态 - 形态柱形将用彩色矩形勾勒。


在 EA 的 OnInit() 处理函数中,配置形态的搜索和显示

//--- Clear the list of all patterns
   engine.GetListAllPatterns().Clear();
//--- Set the flag of using the Pin Bar pattern with the parameters specified in the settings
   engine.SeriesSetUsedPatternPinBar(NULL,PERIOD_CURRENT,true,InpPinBarRatioBody,InpPinBarRatioLarger,InpPinBarRatioSmaller);
//--- Set the flag of using the Inside Bar pattern
   engine.SeriesSetUsedPatternInsideBar(NULL,PERIOD_CURRENT,true);
//--- Set the flag for drawing the Inside Bar as dots from the inputs
   engine.SeriesSetDrawingAsDotsPatternInsideBar(NULL,PERIOD_CURRENT,InpDrawPatternsAsDots);
   
//--- Display the Pin Bar pattern icons with the parameters, specified in the settings, on the chart
   engine.SeriesDrawPatternPinBar(NULL,PERIOD_CURRENT,InpPinBarRatioBody,InpPinBarRatioLarger,InpPinBarRatioSmaller);
//--- Display the Inside Bar pattern icons on the chart
   engine.SeriesDrawPatternInsideBar(NULL,PERIOD_CURRENT,true);
//---
   return(INIT_SUCCEEDED);
  }


在 EA 的 OnChartEvent() 处理函数中,执行代码块以显示模式信息面板:

//--- Check ChartXYToTimePrice()
   if(id==CHARTEVENT_MOUSE_MOVE)
     {
      //--- Get the chart object of the current (main) program chart
      CChartObj *chart=engine.ChartGetMainChart();
      if(chart==NULL)
         return;
      //--- Get the index of a subwindow the cursor is located at
      int wnd_num=chart.XYToTimePrice(lparam,dparam);
      if(wnd_num==WRONG_VALUE)
         return;
      //--- Get the calculated cursor location time and price
      datetime time=chart.TimeFromXY();
      double price=chart.PriceFromXY();
      //--- Get the window object of the chart the cursor is located in by the subwindow index
      CChartWnd *wnd=chart.GetWindowByNum(wnd_num);
      if(wnd==NULL)
         return;
      //--- If X and Y coordinates are calculated by time and price (make a reverse conversion),
      if(wnd.TimePriceToXY(time,price))
        {
         //--- in the comment, show the time, price and index of the window that are calculated by X and Y cursor coordinates,
         //--- as well as the cursor X and Y coordinates converted back from the time and price
         //Comment
         //  (
         //   DFUN,"time: ",TimeToString(time),", price: ",DoubleToString(price,Digits()),
         //   ", win num: ",(string)wnd_num,": x: ",(string)wnd.XFromTimePrice(),
         //   ", y: ",(string)wnd.YFromTimePrice()," (",(string)wnd.YFromTimePriceRelative(),")"
         //  );
         
         //--- Get the bar open time on the chart using the cursor time
         datetime bar_time=GetStartTimeOfBarFast(PERIOD_CURRENT,time);
         //--- Get the pointer to the bar whose opening time was obtained 
         CBar *bar=engine.SeriesGetBar(Symbol(),PERIOD_CURRENT,bar_time);
         if(bar!=NULL && price>=bar.Low() && price<=bar.High())
           {
            //--- From the bar object, get the list of patterns found in it into the 'array'
            ulong array[]={};
            int total=bar.GetPatternsList(array);
            //--- If patterns are found on the bar,
            if(total>0)
              {
               //--- display descriptions of all patterns found on the bar in the journal
               bar.PatternTypeDescriptionPrint(true);
               //--- In the loop based on the number of patterns found on the bar,
               for(int i=0;i<(int)array.Size();i++)
                 {
                  //--- get the type of the next pattern from the 'array', as well as the pointer to it
                  ENUM_PATTERN_TYPE type=(ENUM_PATTERN_TYPE)array[i];
                  CPattern *pattern=engine.GetPattern(Symbol(),PERIOD_CURRENT,bar_time,type);
                  
                  //--- Print a short description of the pattern in the journal
                  if(pattern==NULL)
                     continue;
                  pattern.PrintShort(true);
                  //pattern.Print(false,true);
                  //--- Get the chart coordinates where you want to display the information panel
                  int x=wnd.XFromTimePrice();
                  int y=wnd.YFromTimePrice();
                  //--- Hide all panels except those belonging to patterns found on the bar under the cursor
                  engine.SeriesPatternHideAllInfoPanelsExceptBarTime(bar_time);
                  //--- calculate the Y coordinate of the information panel from the loop index
                  static int shift=0;
                  int cy=y+shift*i;
                  //--- Display the information panel on the chart
                  pattern.ShowInfoPanel(x,cy);
                  CForm *form=pattern.GetForm();
                  //--- If the pointer to the panel is received, calculate the size of the Y coordinate offset (panel height + 1)
                  if(form!=NULL)
                     shift=form.Height()+1;
                 }
              }
           }
        }
     }

代码的逻辑已在注释中说明。我们需要获取鼠标光标所在柱形的开启时间。根据开启时间,我们获得柱形对象,并从中 "提取" 出检测到的形态列表。
然后,我们只需在屏幕上显示每个找到的形态的信息面板。

编译 EA,并在图表上启动它:


正如我们所看到的,一切正常。将形态绘制成图像容易出现延迟。我稍后再处理这个问题。

我们可以看到嵌套形态大致位于屏幕中央。当我们悬停光标并显示信息面板时,就会显示形态链中包含的柱形总数。

在屏幕右侧,一根横杠上会形成两种形态 - Pin Bar 和 Inside Bar。两种图案的信息面板一上一下显示。


接下来做什么?

在下一篇文章中,我将继续开发时间序列形态。

所有创建的文件都附在文章之后,可下载用于自学和测试。


返回内容目录

本文由MetaQuotes Ltd译自俄文
原文地址: https://www.mql5.com/ru/articles/14479

附加的文件 |
MQL5.zip (9582.12 KB)
两样本Kolmogorov-Smirnov检验作为时间序列非平稳性的指标 两样本Kolmogorov-Smirnov检验作为时间序列非平稳性的指标
本文探讨了最著名的非参数同质性检验之一——两样本柯尔莫哥洛夫-斯米尔诺夫(Kolmogorov-Smirnov)检验。文章对模型数据和实际价格都进行了分析。此外,本文还给出了构建非平稳性指标(iSmirnovDistance)的一个示例。
开发回放系统(第 42 部分):图表交易项目(I) 开发回放系统(第 42 部分):图表交易项目(I)
我们来创建一些更有趣的东西。我不想毁掉惊喜,故此紧随本文以便更好地理解。自本系列开发回放/模拟器系统的最开始,我就一直说,我们的意图是按相同的方式使用 MetaTrader 5 平台,无论正在开发的系统中,亦或真实市场中。重点是要正确完成。没有人愿意在训练和学习时用一种工具,而在战斗时不得不换另一种工具。
DoEasy.控件(第 33 部分):垂直滚动条 DoEasy.控件(第 33 部分):垂直滚动条
在本文中,我们将继续开发 DoEasy 库的图形元素,并添加表单对象控件的垂直滚动功能,以及将来需要的一些实用函数和方法。
自定义指标(第一部份):在MQL5中逐步开发简单自定义指标的入门指南 自定义指标(第一部份):在MQL5中逐步开发简单自定义指标的入门指南
学习如何使用MQL5创建自定义指标。这篇入门文章将指引您了解创建简单自定义指标的基础知识,并向初次接触这一有趣话题的MQL5程序员展示编写各种自定义指标的方法。