English Русский Deutsch Português
preview
DoEasy - サービス関数(第2回):はらみ線パターン

DoEasy - サービス関数(第2回):はらみ線パターン

MetaTrader 5 | 9 9月 2024, 10:43
201 0
Artyom Trishkin
Artyom Trishkin

内容


概念

引き続き時系列データに基づいて形成されたパターンを開発します。パターン連載の最初の記事では、様々なパターンを検索表示するツールキットを作成し、プライスアクションのフォーメーションからピンバーパターンを検索する機能を作成しました。今回は、プライスチャートの様々なパターンを検索する機能の開発と改良を続け、プライスアクションの「はらみ線」パターンの検索を作成します。

ピンバーパターンが1バーのフォーメーションであり、1バーの比率で検索される場合、はらみ線は2つのバー(母足(左側のバー)と定義バー(右側のバー)から構成される2バーのフォーメーションです。


このようなフォーメーションを探す場合、単に1本のバーの比率を比較するだけでは不十分です。ここでは、近くの2本のバーを比較する必要があります。さらに、このようなフォーメーションは一列に並ぶことができ、その場合、母足は互いに入れ子になっているすべてのフォーメーションに対して1本となり、一番左のバーとなります。一番右のバーは、ネストしたフォーメーション全体の定義バーの最後になります。このような構造を検索するために、普遍的な機能を実装し、パターンプロパティのセットにもう一つプロパティを追加します。母足の開始時間です。母足と定義バーの開始時間の差に基づいて、ネストしたフォーメーション全体に含まれるバーの数を判定することができます。これはチャートにパターンラベルを描くのに便利です。言い換えれば、各パターンをチャート上の単純な点でマークできることに加え、フォーメーションに含まれるバーの周囲に枠を描くことによって、パターンを視覚的に示すことができるようにします。そこで、チャート上のパターン表示方法を選択できるようにします。

さらに、今日作成した機能は、他のパターンタイプを作成する際にも役立つでしょう。


ライブラリクラスの改善

次のパターンのコードを実装し始める前に、既成のファイルとライブラリクラスを確定しておきましょう。

\MQL5\Include\DoEasy\Defines.mqhで、ライブラリオブジェクト型の列挙にbitmapオブジェクト型を追加します

//+------------------------------------------------------------------+
//| 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リソースをアタッチし、その上に様々なプリミティブを描画することができます。このようなオブジェクトは、バーの時間と価格に関連付けられています。それを使って、パターンバーの輪郭を枠で囲みます。

パターンオブジェクトは、それが形成されたバーの時間を保存するという事実に加えて、その上で見つかったパターンの種類もライブラリのバーオブジェクトに追加します。パターンタイプはビットフラグなので、1つの変数に多くの異なるタイプのパターンを格納することができます。そして、この変数の値から、バーで見つかったすべてのパターンの種類と、それに応じた名前を常に抽出することができます。

これは、ユーザープログラムから作業するパターンを検索するときに便利です。バーオブジェクトを取得し、そこで見つかったパターンの種類を確認し、フラグが変数に書き込まれたパターンを作業します。

バーオブジェクトの整数プロパティに1つプロパティを追加し、バーオブジェクトの整数プロパティの数を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

時系列のリストを使ってパターンを検索し、バー上のパターンを見つけるとき、見つかったパターンのタイプをバーオブジェクトのまさにこの変数に追加します。異なるタイプのパターンを検索した結果に基づいて、見つかった異なるタイプのパターンのフラグを、この変数に1つのバーで記録することができます。

可能なバーオブジェクトの並び替え基準のリストに、バーのパターンタイプによる並び替えを追加します

//+------------------------------------------------------------------+
//| 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
  };


以前は、パターンタイプのリストでハラミパターンに値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
  };

これは、価格/時間座標に結びついたライブラリの新しいタイプのグラフィカルオブジェクトで、ライブラリのGUI要素と同じように描画することができます。そのため、このリストに加えました。おそらく、価格チャートのパターンバーのアウトライン化だけでなく、ライブラリの他のニーズにも使うことになるでしょう。


\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;
  }

この関数は、パターンフラグを含む変数と、この変数から抽出されたパターンタイプを書き込む配列を取得します。各フラグは前のフラグの2倍の大きさなので、ループ内のフラグの値をループインデックスの値から形成し、変数値にそのようなフラグがあるかどうかを探すのは簡単です。このようなフラグが変数に書き込まれた場合、パターンタイプは、新しいパターンタイプを書き込むために、あらかじめ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;
  }

これらの機能はすべて、プログラムのどこからでもアクセスでき、1つのバーで検出されたパターンのリストに簡単にアクセスできます。バープロパティには、見つかったパターンのフラグを格納する変数が追加されました。このプロパティの値に基づき、関数を使用することで、常にバー上のあらゆる種類のパターンを抽出し、プログラム内で処理することができます。これがテストEAでおこなうことです。


\MQL5\Include\DoEasy\Objects\Graph\GCnvElement.mqhファイル内のグラフィカル要素オブジェクトクラスは、より複雑なGUI要素を作成するための基礎として機能しますが、このクラスには派生クラスからアクセスできない変数がいくつかあります。これらの変数とメソッドをprivateセクションからprotectedセクションに移してみましょう。

//+------------------------------------------------------------------+
//| 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


テキストを操作するメソッドのセクションで、privateクラスのプロパティの設定にアクセスするメソッドを2つ書きます。

//+------------------------------------------------------------------+
//| 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

これらの変数をクラスのprotectedセクションに配置すると、他のクラスにさらに大きな変更が加えられるため、これらのメソッドは継承されたクラスのコンストラクタで役立ちます。当面は、変数名を変更することなく、これらのメソッドでやりくりすることにしましょう。

これまでは、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
  {
  }


クラス本体で必要なのは、いくつかのprivate変数とそれを扱うメソッド、オブジェクトを生成する仮想メソッド、コンストラクタとデストラクタだけです。それ以外はすべて、親クラスですでに実装されています。

//+------------------------------------------------------------------+
//| 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;
  }

ここでは、親クラスの同じメソッドとは対照的に、CreateBitmapLabel()メソッドの代わりにCCanvasクラスのCreateBitmap()メソッドを使用しています。このメソッドと親クラスのメソッドの違いはこれだけです。


以下は、ビットマップオブジェクトに価格と時間座標を設定するメソッドです。

//+------------------------------------------------------------------+
//| 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;
  }

このメソッドは、渡されたパラメータとキャンバスの不透明度が200に等しいCDCnvBitmapクラスの新しいオブジェクトを作成し、作成されたオブジェクトへのポインタを返します。


ここで、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)メインウィンドウの現在のチャート上に描画オブジェクトを作成する3つのメソッドは、CGraphElmControlクラスのビットマップオブジェクトを作成するためのメソッドを、上記で実装された指定されたパラメータで呼び出した結果を返すだけです。

これで、任意のライブラリオブジェクトから描画オブジェクトを作成し、何かを視覚的にデザインできるようになりました。ところで、以前はすでにいくつかのグラフィカルプリミティブやGUI要素を任意のライブラリオブジェクトから作成することができました。これでビットマップオブジェクトがリストに加わりました。

グラフィカルフォームオブジェクトのクラスは、グラフィカル要素クラスから継承されます。従って、グラフィカル要素ファイルはフォームオブジェクトクラスファイルに接続されています。グラフィカル要素から継承されたもう1つのクラス、ビットマップオブジェクトクラスがあるので、これらすべてのクラスを互いに最適に接続するために、ビットマップオブジェクトクラスファイルとフォームオブジェクトクラスファイルを接続します。このクラスはグラフィカル要素から派生しているので、これらのクラスは両方ともフォームオブジェクトクラスで利用できます。

\MQL5\Include\DoEasy\Objects\Graph\Form.mqhフォームオブジェクトクラスファイルは、グラフィカル要素ファイルの代わりにビットマップオブジェクトクラスファイルを受け取ります。

//+------------------------------------------------------------------+
//|                                                         Form.mqh |
//|                                  Copyright 2022, MetaQuotes Ltd. |
//|                             https://mql5.com/ja/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, MetaQuotes Ltd."
#property link      "https://mql5.com/ja/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バーオブジェクトクラスファイルのpublicセクションに、バープロパティに新しいパターンタイプを追加するメソッドを記述します。

//--- 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プロパティ値に追加されます。論理演算子orを使えば、変数の値を上書きすることなく、異なる型を変数に追加することができます。したがって、1つの変数に複数の異なるタイプのパターンを格納することができます。


バープロパティの説明セクションで、渡された配列内のパターンのリストを返すメソッドと、バー上のパターンのリストを操作ログに出力するメソッドを宣言します。

//+------------------------------------------------------------------+
//| 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);
//---
  };


バーオブジェクトのパラメータを設定するメソッドで、バーのパターンタイプをabsent(変数値はゼロ)に設定します

//+------------------------------------------------------------------+
//| 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構造体を作成します。こうすることで、パターンによってカバーされているバーに関するすべてのデータを常に得ることができます。ちなみに、パターンが1バーの場合、母足と基本バーは同じ1バーとなります。ここで作成したクラスのビットマップオブジェクトを使って、パターンの輪郭を描きます。抽象パターンオブジェクトクラスのprotectedセクションで、クラスオブジェクトへのポインタを宣言します。パターンのバーをカバーするパターンの必要なサイズを計算できるようにするためには、チャートの寸法とパラメータを知る必要があります。ビットマップオブジェクトのサイズを計算するために必要なチャートパラメータを格納する変数を宣言します

//+------------------------------------------------------------------+
//| 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セクションに、新しいプロパティとポインタを設定するメソッドと返すメソッドを追加します

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クラスメンバー変数構造体の対応する構造体フィールドに設定されます。さらに、渡されたバー構造の時刻は、母足のtimeプロパティに書き込まれます。この値はオブジェクトのプロパティに存在するため、正しく入力する必要があります。

チャート上に情報パネルを表示するメソッドはチャートを再描画する必要がある入力を受け取ります。変数値が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);
  }

これは、マウスカーソルを模様のあるバーの上に置くと、模様の説明のパネルが滞りなく表示されるようにするためです。このバー上に複数のパターンがある場合、それらがチャート上に表示されるとき、trueに設定される最後のパターンを除いて、すべての情報パネルに対してこの変数の値をfalseに設定しなければなりません。この場合、チャートは(各パネルではなく)最後のパネルが表示された後にのみ再描画されます。

チャート上にパターンを表示するには、点とビットマップオブジェクトの2つの方法があります。チャート上にパターンアイコンを表示するメソッドを完成させましょう。

//+------------------------------------------------------------------+
//| 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;
  }

チャートのスケールに応じて、ローソクの幅をピクセル単位で計算します。次に、パターンの幅をバー単位で取得し、この2つの値からパターンオブジェクトの必要な幅を計算して返します。


以下は、描画オブジェクトの高さを計算するメソッドです。

//+------------------------------------------------------------------+
//| 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ピクセル)を加えて返します。

ピンバーパターンコンストラクタで、ネストされたパターンの数をパターンバーの値(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" 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で塗りつぶし、塗りつぶされた領域の輪郭を灰色の矩形で囲みます。完了したら、チャートを再描画せずにリソースを更新します。


検索された各パターンとそのパラメータは、パターン管理クラスのオブジェクトによって制御され、処理されます。このようなオブジェクトは、指定されたタイプと指定されたパターン検索パラメータでパターンを検索するようにパーミッションが設定されたときに一度だけ作成されます。同じクラスで、チャートウィンドウのプロパティを読み込む必要があります。コントロールオブジェクトを作成するときに一度だけ読み込めるようにし、その後、読み込んだチャートパラメータを作成したパターンオブジェクトに書き込みます。チャートプロパティは、各パターンの情報パネルが表示時にチャートの端からはみ出さないようにするために必要です。新しいパターンオブジェクトを作成するたびにチャートパラメータを読み込むと、非常にリソースが必要になります。それに、一度読み取って、作成された各パターンで使用できる場合、同じパラメータを毎回読み取る必要はないでしょう。また、パターンバーの輪郭を描くビットマップオブジェクトを作成する際には、チャートパラメータが必要になります。繰り返しになりますが、毎回同じチャートサイズを読むのは最適ではありません。したがって、パターンコントロールオブジェクトを作成するときにのみ、それらを読み込むことにします。しかし、ここで1つ微妙なニュアンスがあります。チャートサイズを変更しても、以前に読み取ったデータはすべて、すでに受信したものと同じままです。それらはチャートから再度要求し、各パターンのプロパティに記録する必要があります。これについては、次回以降で説明します。

パターンコントロールオブジェクトクラスは、\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()メソッドは、ローソク足の実体サイズの最小値を受け取ります。その後、この値をパターンコントロールオブジェクトに追加します。この値はパターン検索と更新メソッドに渡されます。重要なのは、パターンを検索するときに、サイズがこの値より小さいバーをスキップすることです。当面、ここにゼロを渡し、このフィルタを無効にします。


クラスのコンストラクタでチャートデータを計算し、新しいクラスの変数に書き込みます

//+------------------------------------------------------------------+
//| 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);
  }

メソッドのロジックは、コードコメントで詳しく説明されています。ここでは、このコントロールオブジェクトが管理するパターンのリストを取得します。各パターンオブジェクトには、点で描画するためのフラグを入力します。もしフラグがリセットされていれば、以前に描画した点を削除する必要があり、もしフラグがセットされていれば、描画する必要があります。リスト内の全パターンのループ処理の最後に、再描画フラグがメソッドに渡された場合、チャートは再描画されます。


次に、ピンバーパターンコントロールクラスを修正する必要があります。パターン検索メソッドに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;
  }

ピンバーは1本のバーで形成されるため、母足はパターンが発見された基本バーでもあります。


はらみ線パターンを管理するクラスを作成します。このパターンの構造は厳密に定義されており、基本バー(右側)が母足(左側)の内側に完全に配置されていること以外のパラメータはありません。したがって、どのはらみ線パターンも1つの時系列上の唯一のパターンとなります。ピンバーパターンとは異なり、検索のためのパラメータを設定することができ、1つの時系列上に異なるパラメータを持つ複数のピンバーパターンが存在する可能性があります。そのようなパターンごとに、独自のコントロールオブジェクトが作成されます。上記を考慮すると、はらみ線パターンでは、各時系列に対して常に1つのコントロールオブジェクトのみが作成されます。

はらみ線パターンを管理する新しいクラスを、ピンバーパターンコントロールクラスの後に同じファイルに入力します。

//+------------------------------------------------------------------+
//| 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();
                       }
  };

このクラスは、ライブラリパターンに関する前回の記事で検討したピンバーパターンコントロールクラスの実質的なコピーです。クラスのコンストラクタでは、パターン検索条件は私用されていないのですべてゼロに設定しますオブジェクトIDは常に0であり、これは1つの時系列における唯一のオブジェクトだからです。

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


主なパターン検索メソッドは、隣接する2つのバーを比較してパターンの有無を確認するメソッドと母足を検索するメソッドです。

//--- 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;
                       }

パターン検索メソッドは、単純に近接する2つのバーのサイズを比較し、右のバーが左のバーの中にすっぽり入っているというフラグを返します。

母足を検索するメソッドでは、バーのリストをループしてパターンを検索し、パターンが見つかれば、バーのデータを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;
  }

このメソッドは、単にはらみ線パターンクラスの新しいオブジェクトを作成し、新しいオブジェクトの作成結果を返します。新しいオブジェクトを作成するための文字列以下はすべて、クラスのコンストラクタですでに割り当てられているオブジェクトのプロパティにゼロを割り当てるだけの無駄なものです。しかし、今はこれがすべてです。後に、パターンを特定するために、いくつかのパラメータの使用を追加する必要があるかもしれません。そうでなければ、余計なコードを削除するだけです。


以下は、パターンを検索するメソッドです。

//+------------------------------------------------------------------+
//| 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;
  }

メソッドロジックはコメントで説明されています。現在のバーの開始時刻がメソッドに渡されます。現在のバーを除くすべてのバーのリストを取得します(ゼロバーのパターンは探さない)。出来上がったバーのリストに基づくループで、近接する2つのバーごとに、それらがパターン基準に合致するかどうかを確認します。もしそれらの関係がパターンであれば、入れ子になったパターンを探します。つまり、追加のループで、隣接するパターンを見つかるまで探します。こうして、隣接するパターンの連鎖全体を見つけ、そのうちの一番左のバーが、入れ子になったパターンの連鎖全体の母足となります。このバー、その時間と価格は、見つかったパターンのプロパティに書き込まれます。このデータによって、ネストされたパターンの連鎖全体を、チャート上に表示する際に完全に枠で囲むことができるようになります。これはテスト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);
  }


パターン管理クラスで、はらみ線パターンコントロールオブジェクトを返すメソッドを調整します。

//--- 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を返していました。


はらみ線パターンを使用するフラグを設定し、コントロールオブジェクトがまだ存在しない場合はそれを作成するメソッドを調整しましょう。

//--- 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)
                       {
                       
                       }

メソッドは2つのパターンに対してのみ完全に書かれています。残りのパターンについては、パターンオブジェクトの新しいクラスを書くときに埋めていくテンプレートがあるだけです。


点描画のフラグを返すメソッドを書きます。

//+------------------------------------------------------------------+
//| 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);
                       }

パターンを操作するためのすべてのメソッドに入力があるため、点で描画されたピンバーパターンを返すメソッドに対して入力が実装されます。残りのメソッドは現在、パラメータなしで点描画用のフラグを返します。あるパターンがパラメータを必要とする場合は、後でそのようなメソッドに書き込むことになります。


今度は、同じファイルにある時系列クラスに対して、まったく同じメソッドを書く必要があります。

//--- 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ファイルに記述する必要があります:

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 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銘柄時系列コレクションファイルはチャートコレクションファイルを受け取ります。また、privateセクションでチャートコレクションへのポインタを宣言します

//+------------------------------------------------------------------+
//| 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:


クラスの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で同じことをする必要があります。

すべてのパターン処理メソッドで、同じまたは類似の入力文字列を置き換えます。

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を使用し、新しく作成したTestDoEasyフォルダに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の場合、はらみ線パターンはBitmapオブジェクトを使って描画されます。パターンバーは色付きの矩形で囲まれます。


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をコンパイルし、チャート上で起動します。


ご覧のとおり、すべてが想定どおりに機能します。パターンを画像として描画することには遅延が伴いがちです。これについては後で扱います。

画面のほぼ中央に入れ子模様が見えます。カーソルを合わせると情報パネルが表示され、パターンチェーンに含まれるバーの総数が表示されます。

画面右側では、ピンバーとはらみ線という2つのパターンが1つのバーに形成されています。両パターンの情報パネルが1つずつ上に表示されます。


次の段階

次回は、引き続き時系列パターンを開発します。

作成されたファイルはすべて記事に添付されており、自習やテスト用にダウンロードすることができます。


目次に戻る

MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/14479

添付されたファイル |
MQL5.zip (9582.12 KB)
ニューラルネットワークが簡単に(第82回):常微分方程式モデル(NeuralODE) ニューラルネットワークが簡単に(第82回):常微分方程式モデル(NeuralODE)
この記事では、環境状態のダイナミクスを研究することを目的とした別のタイプのモデルについて説明します。
リプレイシステムの開発(第44回):Chart Tradeプロジェクト(III) リプレイシステムの開発(第44回):Chart Tradeプロジェクト(III)
前回の記事では、OBJ_CHARTで使用するテンプレートデータの操作方法について解説しました。ただし、あの記事ではトピックの概要に焦点を当て、詳細な部分には触れていませんでした。これは、説明をよりシンプルにするために、非常に簡略化された手法を用いたからです。物事は一見シンプルに見えることが多いですが、実際にはそうではないケースもあり、全体を正確に理解するためには、まず最も基本的な部分をしっかり押さえる必要があります。
因果推論における時系列クラスタリング 因果推論における時系列クラスタリング
機械学習におけるクラスタリングアルゴリズムは、元データを類似した観察結果を持つグループに分けることができる重要な教師なし学習法です。これらのクラスタを用いることで、特定の市場クラスタを分析したり、新しいデータを基に最も安定したクラスタを探索したり、因果関係を推定したりすることが可能です。本稿では、Pythonによる時系列クラスタリングのための独自の手法を提案します。
行列分解:基本 行列分解:基本
ここでの目的は教訓を得ることなので、できるだけシンプルに話を進めたいと思います。具体的には、必要な行列の乗算だけを実装します。行列とスカラーの乗算をシミュレートするにはこれで十分であることが今日わかるでしょう。行列分解を実装する際に多くの人が直面する最大の課題は、スカラーの分解と異なり、因子の順序が結果に影響を与えるため、行列の場合はその点に注意が必要だということです。