DoEasyライブラリの時系列(第42部): 抽象指標バッファオブジェクトクラス

7 9月 2020, 09:04
Artyom Trishkin
0
189

内容


概念

前の記事では、DoEasyライブラリの時系列オブジェクトを使用して指標例を開発しました。バッファデータを格納してアクセスするために、チャート銘柄に属するバッファを正しく識別するために必要なすべてのデータとローソク足の形で指標ラインをプロットおよび描画するための期間を備えたバッファ構造体を作成しました。ただし、各指標に対して、フィールドが必要な線画のタイプに対応する構造体を作成するのは、不便で実用的ではありません。指標バッファのオブジェクトクラスを使用すると、スタイルや描画方法によって任意のタイプのバッファを簡単に作成できるので、はるかに便利です。

本稿では、そのようなツールの開発を開始します。
オブジェクト構造体は、描画タイプに関係なく、すべての指標バッファに固有のすべての一般プロパティを含む基本的な指標バッファクラス(いわゆる「抽象バッファオブジェクト」)で構成されています。特定のバッファタイプに関する明確化データを含むバッファオブジェクトクラスは、この抽象バッファから継承されます。これらの子孫クラスは、描画タイプを正確に定義し、このタイプの指標バッファに固有の個々のプロパティを備えています。

本稿では、抽象指標バッファのオブジェクトクラスを記述します。オブジェクトには、ENUM_PLOT_PROPERTY_INTEGERENUM_PLOT_PROPERTY_DOUBLE、ENUM_PLOT_PROPERTY_STRING列挙からのすべての指標バッファプロパティといくつかの追加プロパティが含まれます。

  • バッファタイプ:
    • データバッファ
    • 計算バッファ
  • バッファステータス(指標の線の描画タイプを定義)子孫オブジェクトは、バッファステータスによって並び替えされます。抽象バッファクラスの個別の子孫クラスが、ステータスごとに作成されます。
  • バッファ銘柄:
    • 現在
    • 厳密に指定
  • バッファ時間枠:
    • 現在
    • 厳密に指定
  • 描画されたバッファのシリアル番号は、ターミナルのデータウィンドウに表示されるバッファ番号です(これらの番号は、バッファに割り当てられたdouble配列のインデックスと一致しません)。
  • バッファ使用フラグ — フラグをオンまたはオフにすることにより、データウィンドウでのバッファ行と値の表示を有効または無効にできます。
  • ベースデータバッファのインデックス — バッファラインの描画に使用されるすべての配列の最初の配列のインデックスに関する補助データ。
  • バッファデータの量 — バッファグラフィックの描画に使用される実際の配列量に関する補助データ。カラーバッファインデックスと、インデックスをベースデータバッファとして割り当てることができる次の配列のインデックスを計算する必要があります。
  • カラーバッファインデックスは、カラーバッファとして使用される配列インデックスに関する補助データです。
  • 次の指標バッファとして割り当てるための空き配列インデックス — 次のバッファオブジェクトの基本データバッファの計算されたインデックスに関する補助データ。

その結果、指標バッファを操作するために必要なすべてのクラスを作成した後、プログラムに「このタイプのバッファを作成する」ように単純に「伝える」機能が得られ、ライブラリは、配列を個別に宣言し、そのプロパティを割り当て、指標バッファにバインドする必要があります。バッファリストを取得するだけで、以前に作成した指標バッファとバッファデータにアクセスできます。

MQL5には、2つの類似した描画スタイル(モノクロとカラーの2つ)を作成する機能があるため、ライブラリによって作成されるすべてのバッファはカラーになります。モノクロの線を作成する場合は、バッファによって表示されるすべてのデータに単一の色が設定されます。
バーを着色するために異なる色を使用する場合、指定された数の色が各バーの線を表示するために使用されます。


CBuffer抽象バッファクラス

クラスの操作には、バッファプロパティの説明を含むテキストメッセージが必要です。

\MQL5\Include\DoEasy\Datas.mqhを開いて新しいメッセージのインデックスを追加します

   MSG_LIB_TEXT_WAIT,                                 // Wait
   MSG_LIB_TEXT_END,                                  // End
   MSG_LIB_TEXT_PERIOD_CURRENT,                       // Current chart period
   

...

   MSG_LIB_TEXT_TS_TEXT_ATTEMPT,                      // Attempt:
   MSG_LIB_TEXT_TS_TEXT_WAIT_FOR_SYNC,                // Waiting for data synchronization ...

//--- CBuffer
   MSG_LIB_TEXT_BUFFER_TEXT_INDEX_BASE,               // Base data buffer index
   MSG_LIB_TEXT_BUFFER_TEXT_INDEX_PLOT,               // Plotted buffer serial number
   MSG_LIB_TEXT_BUFFER_TEXT_INDEX_COLOR,              // Color buffer index
   MSG_LIB_TEXT_BUFFER_TEXT_NUM_DATAS,                // Number of data buffers
   MSG_LIB_TEXT_BUFFER_TEXT_INDEX_NEXT,               // Index of the free array to be assigned as the next indicator buffer
   MSG_LIB_TEXT_BUFFER_TEXT_TIMEFRAME,                // Buffer (timeframe) data period
   MSG_LIB_TEXT_BUFFER_TEXT_STATUS,                   // Buffer status
   MSG_LIB_TEXT_BUFFER_TEXT_TYPE,                     // Buffer type
   MSG_LIB_TEXT_BUFFER_TEXT_ACTIVE,                   // Active
   MSG_LIB_TEXT_BUFFER_TEXT_ARROW_CODE,               // Arrow code
   MSG_LIB_TEXT_BUFFER_TEXT_ARROW_SHIFT,              // The vertical shift of the arrows
   MSG_LIB_TEXT_BUFFER_TEXT_DRAW_BEGIN,               // The number of initial bars that are not drawn and values in DataWindow
   MSG_LIB_TEXT_BUFFER_TEXT_DRAW_TYPE,                // Graphical construction type
   MSG_LIB_TEXT_BUFFER_TEXT_SHOW_DATA,                // Display construction values in DataWindow
   MSG_LIB_TEXT_BUFFER_TEXT_SHIFT,                    // Indicator graphical construction shift by time axis in bars
   MSG_LIB_TEXT_BUFFER_TEXT_LINE_STYLE,               // Line style
   MSG_LIB_TEXT_BUFFER_TEXT_LINE_WIDTH,               // Line width
   MSG_LIB_TEXT_BUFFER_TEXT_COLOR_NUM,                // Number of colors
   MSG_LIB_TEXT_BUFFER_TEXT_COLOR,                    // Drawing color
   MSG_LIB_TEXT_BUFFER_TEXT_EMPTY_VALUE,              // Empty value for plotting where nothing will be drawn
   MSG_LIB_TEXT_BUFFER_TEXT_SYMBOL,                   // Buffer symbol
   MSG_LIB_TEXT_BUFFER_TEXT_LABEL,                    // Name of the graphical indicator series displayed in DataWindow
   MSG_LIB_TEXT_BUFFER_TEXT_STATUS_NAME,              // Indicator buffer with graphical construction type 

   MSG_LIB_TEXT_BUFFER_TEXT_STATUS_NONE,              // No drawing
   MSG_LIB_TEXT_BUFFER_TEXT_STATUS_FILLING,           // Color filling between two levels
   MSG_LIB_TEXT_BUFFER_TEXT_STATUS_LINE,              // Line
   MSG_LIB_TEXT_BUFFER_TEXT_STATUS_HISTOGRAM,         // Histogram from the zero line
   MSG_LIB_TEXT_BUFFER_TEXT_STATUS_ARROW,             // Drawing with arrows
   MSG_LIB_TEXT_BUFFER_TEXT_STATUS_SECTION,           // Segments
   MSG_LIB_TEXT_BUFFER_TEXT_STATUS_HISTOGRAM2,        // Histogram on two indicator buffers
   MSG_LIB_TEXT_BUFFER_TEXT_STATUS_ZIGZAG,            // Zigzag
   MSG_LIB_TEXT_BUFFER_TEXT_STATUS_BARS,              // Display as bars
   MSG_LIB_TEXT_BUFFER_TEXT_STATUS_CANDLES,           // Display as candles
   
   MSG_LIB_TEXT_BUFFER_TEXT_TYPE_CALCULATE,           // Calculated buffer
   MSG_LIB_TEXT_BUFFER_TEXT_TYPE_DATA,                // Colored data buffer
   
   MSG_LIB_TEXT_BUFFER_TEXT_STYLE_SOLID,              // Solid line
   MSG_LIB_TEXT_BUFFER_TEXT_STYLE_DASH,               // Dashed line
   MSG_LIB_TEXT_BUFFER_TEXT_STYLE_DOT,                // Dotted line
   MSG_LIB_TEXT_BUFFER_TEXT_STYLE_DASHDOT,            // Dot-dash line
   MSG_LIB_TEXT_BUFFER_TEXT_STYLE_DASHDOTDOT,         // Dash - two dots

  };
//+------------------------------------------------------------------+

また、新しく追加したインデックスに対応するメッセージテキストも追加します。

   {"Ожидание","Wait"},
   {"Окончание","End"},
   {"Текущий период графика","Current chart period"},
   

...

   {"Попытка: ","Attempt: "},
   {"Ожидание синхронизации данных ...","Waiting for data synchronization ..."},
   
   {"Индекс базового буфера данных","Index of Base data buffer"},
   {"Порядковый номер рисуемого буфера","Plot buffer sequence number"},
   {"Индекс буфера цвета","Color buffer index"},
   {"Количество буферов данных","Number of data buffers"},
   {"Индекс массива для назначения следующим индикаторным буфером","Array index for assignment as the next indicator buffer"},
   {"Период данных буфера (таймфрейм)","Buffer data Period (Timeframe)"},
   {"Статус буфера","Buffer status"},
   {"Тип буфера","Buffer type"},
   {"Активен","Active"},
   {"Код стрелки","Arrow code"},
   {"Смещение стрелок по вертикали","Vertical shift of arrows"},
   {"Количество начальных баров без отрисовки и значений в DataWindow","Number of initial bars without drawing and values in the DataWindow"},
   {"Тип графического построения","Type of graphical construction"},
   {"Отображение значений построения в окне DataWindow","Display construction values in the DataWindow"},
   {"Сдвиг графического построения индикатора по оси времени в барах","Shift of indicator plotting along the time axis in bars"},
   {"Стиль линии отрисовки","Drawing line style "},
   {"Толщина линии отрисовки","The thickness of the drawing line"},
   {"Количество цветов","The number of colors"},
   {"Цвет отрисовки","The index of a buffer containing the drawing color"},
   {"Пустое значение для построения, для которого нет отрисовки","An empty value for plotting, for which there is no drawing"},
   {"Символ буфера","Buffer Symbol"},
   {"Имя индикаторной графической серии, отображаемое в окне DataWindow","The name of the indicator graphical series to display in the DataWindow"},
   {"Индикаторный буфер с типом графического построения","Indicator buffer with graphic plot type"},
   
   {"Нет отрисовки","No drawing"},
   {"Цветовая заливка между двумя уровнями","Color fill between the two levels"},
   {"Линия","Line"},
   {"Гистограмма от нулевой линии","Histogram from the zero line"},
   {"Отрисовка стрелками","Drawing arrows"},
   {"Отрезки","Section"},
   {"Гистограмма на двух индикаторных буферах","Histogram of the two indicator buffers"},
   {"Зигзаг","Zigzag"},
   {"Отображение в виде баров","Display as a sequence of bars"},
   {"Отображение в виде свечей","Display as a sequence of candlesticks"},
   
   {"Расчётный буфер","Calculated buffer"},
   {"Цветной буфер данных","Colored Data buffer"},
   
   {"Сплошная линия","Solid line"},
   {"Прерывистая линия","Broken line"},
   {"Пунктирная линия","Dotted line"},
   {"Штрих-пунктирная линия","Dash-dot line"},
   {"Штрих - две точки","Dash - two points"},
   
  };
//+---------------------------------------------------------------------+

オブジェクトコレクションに格納するライブラリオブジェクトを作成すると、適切なコレクションのIDが各オブジェクトに割り当てられます。同じことがバッファオブジェクトに対しても行われます。指標バッファコレクションIDを作成し、それを抽象バッファオブジェクトに割り当てます。したがって、抽象バッファから継承する各オブジェクトには、そのバッファコレクションに属していることを示すIDが割り当てられます。
抽象バッファオブジェクトを作成するには、そのすべてのプロパティを定義して説明する必要があります。これらのプロパティを使用すると、今後の作業のために必要なバッファオブジェクトをバッファコレクションでいつでも見つけることができます。

\MQL5\Include\DoEasy\Defines.mqhを開いて指標バッファコレクションIDを追加します

//--- Collection list IDs
#define COLLECTION_HISTORY_ID          (0x777A)                   // Historical collection list ID
#define COLLECTION_MARKET_ID           (0x777B)                   // Market collection list ID
#define COLLECTION_EVENTS_ID           (0x777C)                   // Event collection list ID
#define COLLECTION_ACCOUNT_ID          (0x777D)                   // Account collection list ID
#define COLLECTION_SYMBOLS_ID          (0x777E)                   // Symbol collection list ID
#define COLLECTION_SERIES_ID           (0x777F)                   // Timeseries collection list ID
#define COLLECTION_BUFFERS_ID          (0x7780)                   // Indicator buffer collection list ID
//--- Data parameters for file operations

ファイルの最後に、バッファオブジェクトステータスの列挙そのタイプを追加、整数実数文字列オブジェクトのプロパティを追加し、コレクションリストにバッファオブジェクトの並び替えの可能な基準を書き込みます

//+------------------------------------------------------------------+
//| Data for working with indicator buffers                          |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Abstract buffer status (by drawing style)                        |
//+------------------------------------------------------------------+
enum ENUM_BUFFER_STATUS
  {
   BUFFER_STATUS_NONE,                                         // No drawing
   BUFFER_STATUS_FILLING,                                      // Color filling between two levels (MQL5)
   BUFFER_STATUS_LINE,                                         // Line
   BUFFER_STATUS_HISTOGRAM,                                    // Histogram from the zero line
   BUFFER_STATUS_ARROW,                                        // Drawing with arrows
   BUFFER_STATUS_SECTION,                                      // Segments
   BUFFER_STATUS_HISTOGRAM2,                                   // Histogram on two indicator buffers
   BUFFER_STATUS_ZIGZAG,                                       // Zigzag style
   BUFFER_STATUS_BARS,                                         // Display as bars (MQL5)
   BUFFER_STATUS_CANDLES,                                      // Display as candles (MQL5)
  };
//+------------------------------------------------------------------+
//| Buffer type                                                      |
//+------------------------------------------------------------------+
enum ENUM_BUFFER_TYPE
  {
   BUFFER_TYPE_CALCULATE,                                      // Calculated buffer
   BUFFER_TYPE_DATA,                                           // Colored data buffer
  };
//+------------------------------------------------------------------+
//| Buffer integer properties                                        |
//+------------------------------------------------------------------+
enum ENUM_BUFFER_PROP_INTEGER
  {
   BUFFER_PROP_INDEX_PLOT = 0,                                 // Plotted buffer serial number
   BUFFER_PROP_STATUS,                                         // Buffer status (by drawing style) from the ENUM_BUFFER_STATUS enumeration
   BUFFER_PROP_TYPE,                                           // Buffer type (from the ENUM_BUFFER_TYPE enumeration)
   BUFFER_PROP_TIMEFRAME,                                      // Buffer period data (timeframe)
   BUFFER_PROP_ACTIVE,                                         // Buffer usage flag
   BUFFER_PROP_ARROW_CODE,                                     // Arrow code for DRAW_ARROW style
   BUFFER_PROP_ARROW_SHIFT,                                    // The vertical shift of the arrows for DRAW_ARROW style
   BUFFER_PROP_DRAW_BEGIN,                                     // The number of initial bars that are not drawn and values in DataWindow
   BUFFER_PROP_SHOW_DATA,                                      // Flag of displaying construction values in DataWindow
   BUFFER_PROP_DRAW_TYPE,                                      // Graphical construction type (from the ENUM_DRAW_TYPE enumeration)
   BUFFER_PROP_SHIFT,                                          // Indicator graphical construction shift by time axis in bars
   BUFFER_PROP_LINE_STYLE,                                     // Line style
   BUFFER_PROP_LINE_WIDTH,                                     // Line width
   BUFFER_PROP_COLOR_INDEXES,                                  // Number of colors
   BUFFER_PROP_COLOR,                                          // Drawing color
   BUFFER_PROP_NUM_DATAS,                                      // Number of data buffers
   BUFFER_PROP_INDEX_BASE,                                     // Base data buffer index
   BUFFER_PROP_INDEX_COLOR,                                    // Color buffer index
   BUFFER_PROP_INDEX_NEXT,                                     // Index of the free array to be assigned as the next indicator buffer
  }; 
#define BUFFER_PROP_INTEGER_TOTAL (19)                         // Total number of integer bar properties
#define BUFFER_PROP_INTEGER_SKIP  (6)                          // Number of buffer properties not used in sorting
//+------------------------------------------------------------------+
//| Buffer real properties                                           |
//+------------------------------------------------------------------+
enum ENUM_BUFFER_PROP_DOUBLE
  {
   BUFFER_PROP_EMPTY_VALUE = BUFFER_PROP_INTEGER_TOTAL,        // Empty value for plotting where nothing will be drawn
  }; 
#define BUFFER_PROP_DOUBLE_TOTAL  (1)                          // Total number of real buffer properties
#define BUFFER_PROP_DOUBLE_SKIP   (0)                          // Number of buffer properties not used in sorting
//+------------------------------------------------------------------+
//| Buffer string properties                                         |
//+------------------------------------------------------------------+
enum ENUM_BUFFER_PROP_STRING
  {
   BUFFER_PROP_SYMBOL = (BUFFER_PROP_INTEGER_TOTAL+BUFFER_PROP_DOUBLE_TOTAL), // Buffer symbol
   BUFFER_PROP_LABEL,                                          // Name of the graphical indicator series displayed in DataWindow
  };
#define BUFFER_PROP_STRING_TOTAL  (2)                          // Total number of string buffer properties
//+------------------------------------------------------------------+
//| Possible buffer sorting criteria                                 |
//+------------------------------------------------------------------+
#define FIRST_BUFFER_DBL_PROP          (BUFFER_PROP_INTEGER_TOTAL-BUFFER_PROP_INTEGER_SKIP)
#define FIRST_BUFFER_STR_PROP          (BUFFER_PROP_INTEGER_TOTAL-BUFFER_PROP_INTEGER_SKIP+BUFFER_PROP_DOUBLE_TOTAL-BUFFER_PROP_DOUBLE_SKIP)
enum ENUM_SORT_BUFFER_MODE
  {
//--- Sort by integer properties
   SORT_BY_BUFFER_INDEX_PLOT = 0,                              // Sort by the plotted buffer serial number
   SORT_BY_BUFFER_STATUS,                                      // Sort by buffer drawing style (status) from the ENUM_BUFFER_STATUS enumeration
   SORT_BY_BUFFER_TYPE,                                        // Sort by buffer type (from the ENUM_BUFFER_TYPE enumeration)
   SORT_BY_BUFFER_TIMEFRAME,                                   // Sort by the buffer data period (timeframe)
   SORT_BY_BUFFER_ACTIVE,                                      // Sort by the buffer usage flag
   SORT_BY_BUFFER_ARROW_CODE,                                  // Sort by the arrow code for DRAW_ARROW style
   SORT_BY_BUFFER_ARROW_SHIFT,                                 // Sort by the vertical shift of the arrows for DRAW_ARROW style
   SORT_BY_BUFFER_DRAW_BEGIN,                                  // Sort by the number of initial bars that are not drawn and values in DataWindow
   SORT_BY_BUFFER_SHOW_DATA,                                   // Sort by the flag of displaying construction values in DataWindow
   SORT_BY_BUFFER_DRAW_TYPE,                                   // Sort by graphical construction type (from the ENUM_DRAW_TYPE enumeration)
   SORT_BY_BUFFER_SHIFT,                                       // Sort by the indicator graphical construction shift by time axis in bars
   SORT_BY_BUFFER_LINE_STYLE,                                  // Sort by the line style
   SORT_BY_BUFFER_LINE_WIDTH,                                  // Sort by the line width
   SORT_BY_BUFFER_COLOR_INDEXES,                               // Sort by a number of attempts
   SORT_BY_BUFFER_COLOR,                                       // Sort by the drawing color
//--- Sort by real properties
   SORT_BY_BUFFER_EMPTY_VALUE = FIRST_BUFFER_DBL_PROP,         // Sort by the empty value for plotting where nothing will be drawn
//--- Sort by string properties
   SORT_BY_BUFFER_SYMBOL = FIRST_BUFFER_STR_PROP,              // Sort by the buffer symbol
   SORT_BY_BUFFER_LABEL,                                       // Sort by the name of the graphical indicator series displayed in DataWindow
  };
//+------------------------------------------------------------------+

これらのすべてのプロパティ、およびそれらの定義、割り当て、使用法は、ライブラリの標準です。これらは何度も検討してきたので、ここでは個々の列挙とマクロ置換を詳しく調べても意味がありません。すでにそれらの目的に精通していて、説明が必要ないことを願っていますが、質問があったら、下のコメント欄から気軽に質問してください。

必要なデータをすべて用意しました。次に、抽象バッファオブジェクトクラスの作成を開始します。

\MQL5\Include\DoEasy\Objects\で、CBufferクラスのBuffer.mqhファイルを含むIndicators\フォルダを作成します。
すべてのCBaseObjライブラリオブジェクトの基本オブジェクトのクラスは、抽象バッファオブジェクトクラスの基本クラスとして機能します。
クラスファイルをバッファクラスファイルにインクルードします

//+------------------------------------------------------------------+
//|                                                       Buffer.mqh |
//|                        Copyright 2020, MetaQuotes Software Corp. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, MetaQuotes Software Corp."
#property link      "https://mql5.com/en/users/artmedia70"
#property version   "1.00"
#property strict    // Necessary for mql4
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "..\..\Objects\BaseObj.mqh"
//+------------------------------------------------------------------+
//| Abstract indicator buffer class                                  |
//+------------------------------------------------------------------+
class CBuffer : public CBaseObj
  {

ライブラリオブジェクトの基本メソッドのセットは、各オブジェクトの標準です。個々のオブジェクトごとに同じ方法で、各オブジェクトに固有のプロパティを操作できます。オブジェクト構築体の原則はライブラリ記述の最初で検討しました。

ここでもすべてが標準的です。3つのオブジェクトプロパティ配列(整数、実数、文字列)、実数および文字列プロパティの本当のインデックスを返すメソッド、および設定メソッド受信メソッドこれらの配列から指定されたプロパティの説明を取得するメソッドがあります。指定されたプロパティを使用するフラグを返す3つの仮想メソッドおよび2つの比較メソッド - これらは、指定されたプロパティによるコレクション内の検索と並べ替え、および2つのオブジェクトの比較平等のためのものです。2つのコンストラクタ — 操作ログにすべてのバッファオブジェクトのプロパティとその短い説明を表示するためのデフォルトおよびクローズドパラメトリック1および2メソッド

//+------------------------------------------------------------------+
//| Abstract indicator buffer class                                  |
//+------------------------------------------------------------------+
class CBuffer : public CBaseObj
  {
private:
   long              m_long_prop[BUFFER_PROP_INTEGER_TOTAL];                     // Integer properties
   double            m_double_prop[BUFFER_PROP_DOUBLE_TOTAL];                    // Real properties
   string            m_string_prop[BUFFER_PROP_STRING_TOTAL];                    // String properties
//--- Return the index of the array the buffer's (1) double and (2) string properties are located at
   int               IndexProp(ENUM_BUFFER_PROP_DOUBLE property)           const { return(int)property-BUFFER_PROP_INTEGER_TOTAL;                           }
   int               IndexProp(ENUM_BUFFER_PROP_STRING property)           const { return(int)property-BUFFER_PROP_INTEGER_TOTAL-BUFFER_PROP_DOUBLE_TOTAL;  }
//--- Set the graphical construction type
   void              SetDrawType(void);
   
public:
//--- Array of the (1) drawn indicator buffer and (2) color buffer
   double            DataArray[];
   double            ColorArray[];

//--- Set buffer's (1) integer, (2) real and (3) string properties
   void              SetProperty(ENUM_BUFFER_PROP_INTEGER property,long value)   { this.m_long_prop[property]=value;                                        }
   void              SetProperty(ENUM_BUFFER_PROP_DOUBLE property,double value)  { this.m_double_prop[this.IndexProp(property)]=value;                      }
   void              SetProperty(ENUM_BUFFER_PROP_STRING property,string value)  { this.m_string_prop[this.IndexProp(property)]=value;                      }
//--- Return (1) integer, (2) real and (3) string buffer properties from the properties array
   long              GetProperty(ENUM_BUFFER_PROP_INTEGER property)        const { return this.m_long_prop[property];                                       }
   double            GetProperty(ENUM_BUFFER_PROP_DOUBLE property)         const { return this.m_double_prop[this.IndexProp(property)];                     }
   string            GetProperty(ENUM_BUFFER_PROP_STRING property)         const { return this.m_string_prop[this.IndexProp(property)];                     }
//--- Get description of buffer's (1) integer, (2) real and (3) string properties
   string            GetPropertyDescription(ENUM_BUFFER_PROP_INTEGER property);
   string            GetPropertyDescription(ENUM_BUFFER_PROP_DOUBLE property);
   string            GetPropertyDescription(ENUM_BUFFER_PROP_STRING property);
//--- Return the flag of the buffer supporting the property
   virtual bool      SupportProperty(ENUM_BUFFER_PROP_INTEGER property)          { return true; }
   virtual bool      SupportProperty(ENUM_BUFFER_PROP_DOUBLE property)           { return true; }
   virtual bool      SupportProperty(ENUM_BUFFER_PROP_STRING property)           { return true; }

//--- Compare CBuffer objects by all possible properties (for sorting the lists by a specified buffer object property)
   virtual int       Compare(const CObject *node,const int mode=0) const;
//--- Compare CBuffer objects by all properties (to search for equal buffer objects)
   bool              IsEqual(CBuffer* compared_obj) const;
                     
//--- Default constructor
                     CBuffer(void){;}
//protected:
//--- Protected parametric constructor
                     CBuffer(ENUM_BUFFER_STATUS status_buffer,ENUM_BUFFER_TYPE buffer_type,const uint index_plot,const uint index_base_array);
public:  
//--- Send description of buffer properties to the journal (full_prop=true - all properties, false - only supported ones)
   void              Print(const bool full_prop=false);
//--- Display a short buffer description in the journal (implementation in the descendants)
   virtual void      PrintShort(void) {;}
   

ここでは、標準的なデータとメソッドが強調表示されています。
protectedパラメトリックコンストラクタはクラスのprotectedセクションに存在する必要がありますが、現在の記事では、作成されたオブジェクト操作を確認するためにコンストラクタはpublicになります。
これがprotected: アクセス指定子をコメント化した理由です。

バッファのグラフィック構築タイプを設定するprivateメソッド1つデータ配列およびカラー配列としてバインドするための2つのpublic配列は説明されていないままです。

//--- Set the graphical construction type
   void              SetDrawType(void);
   
public:
//--- Array of the (1) drawn indicator buffer and (2) color buffer
   double            DataArray[];
   double            ColorArray[];

バッファのステータスに応じて(継承されたオブジェクトはそのステータスに「バインド」されます)、バッファのグラフィック構造体のタイプを定義します。
バッファステータス列挙定数を詳しく見て

//+------------------------------------------------------------------+
//| Abstract buffer status (by drawing style)                        |
//+------------------------------------------------------------------+
enum ENUM_BUFFER_STATUS
  {
   BUFFER_STATUS_NONE,                                         // No drawing
   BUFFER_STATUS_FILLING,                                      // Color filling between two levels (MQL5)
   BUFFER_STATUS_LINE,                                         // Line
   BUFFER_STATUS_HISTOGRAM,                                    // Histogram from the zero line
   BUFFER_STATUS_ARROW,                                        // Drawing with arrows
   BUFFER_STATUS_SECTION,                                      // Segments
   BUFFER_STATUS_HISTOGRAM2,                                   // Histogram on two indicator buffers
   BUFFER_STATUS_ZIGZAG,                                       // Zigzag style
   BUFFER_STATUS_BARS,                                         // Display as bars (MQL5)
   BUFFER_STATUS_CANDLES,                                      // Display as candles (MQL5)
  };
//+------------------------------------------------------------------+

列挙内の定数の数による単純なループを使用して、定数の順序をENUM_DRAW_TYPE列挙内のほぼ同じ名前の定数の順序と比較すると、

for(int i=0;i<18;i++)
   Print(EnumToString((ENUM_DRAW_TYPE)i)," = ",i);

2020.04.15 12:51:53.725 DRAW_NONE = 0
2020.04.15 12:51:53.725 DRAW_LINE = 1
2020.04.15 12:51:53.725 DRAW_HISTOGRAM = 2
2020.04.15 12:51:53.725 DRAW_ARROW = 3
2020.04.15 12:51:53.725 DRAW_SECTION = 4
2020.04.15 12:51:53.725 DRAW_HISTOGRAM2 = 5
2020.04.15 12:51:53.725 DRAW_ZIGZAG = 6
2020.04.15 12:51:53.725 DRAW_FILLING = 7
2020.04.15 12:51:53.725 DRAW_BARS = 8
2020.04.15 12:51:53.725 DRAW_CANDLES = 9
2020.04.15 12:51:53.725 DRAW_COLOR_LINE = 10
2020.04.15 12:51:53.725 DRAW_COLOR_HISTOGRAM = 11
2020.04.15 12:51:53.725 DRAW_COLOR_ARROW = 12
2020.04.15 12:51:53.725 DRAW_COLOR_SECTION = 13
2020.04.15 12:51:53.725 DRAW_COLOR_HISTOGRAM2 = 14
2020.04.15 12:51:53.725 DRAW_COLOR_ZIGZAG = 15
2020.04.15 12:51:53.725 DRAW_COLOR_BARS = 16
2020.04.15 12:51:53.725 DRAW_COLOR_CANDLES = 17

注文がグラフィック構築タイプで一致していることがわかります。
違いは、描画スタイルの列挙にモノクロバッファとカラーバッファの定数があり、カラーバッファ(2つのレベル間の色の塗りつぶし)を必要としないスタイルがあることです。

すべてのバッファはカラーです。描画スタイルを設定するには、SetDrawType()メソッドに渡されたバッファステータスと描画タイプを確認し、それらに応じて、描画を設定しないか、2つのレベル間のスペースを色で塗りつぶします。 または、ステータス列挙インデックスを8単位シフトして、定数値が描画スタイル列挙のカラーバッファの定数に対応するようにします。

クラス本体の外で、メソッドを実装します。

//+------------------------------------------------------------------+
//| Set the graphical construction type                              |
//+------------------------------------------------------------------+
void CBuffer::SetDrawType(void)
  {
   ENUM_DRAW_TYPE type=(!this.TypeBuffer() || !this.Status() ? DRAW_NONE : this.Status()==BUFFER_STATUS_FILLING ? DRAW_FILLING : ENUM_DRAW_TYPE(this.Status()+8));
   this.SetProperty(BUFFER_PROP_DRAW_TYPE,type);
   ::PlotIndexSetInteger((int)this.GetProperty(BUFFER_PROP_INDEX_PLOT),PLOT_DRAW_TYPE,type);
  }
//+------------------------------------------------------------------+

バッファタイプがBUFFER_TYPE_CALCULATE(0)またはBUFFER_STATUS_NONE(0)の場合、描画スタイルは「描画なし」に設定されますバッファステータスがBUFFER_STATUS_FILLING(色で塗りつぶされている)の場合、適切な描画スタイルが設定されます残りのすべての値は単に8ずつ増加します。このシフトは、カラー描画スタイルの定数を示します。

以下は、ENUM_BUFFER_STATUS列挙定数の値を8ずつ増やす例と、この場合のENUM_DRAW_TYPE列挙の値です。

enum ENUM_BUFFER_STATUS
  {
   BUFFER_STATUS_NONE,       //     0           // No drawing
   BUFFER_STATUS_FILLING,    //     1           // Color filling between two levels (MQL5)
   BUFFER_STATUS_LINE,       //     2 +8 = 10   // Line
   BUFFER_STATUS_HISTOGRAM,  //     3 +8 = 11   // Histogram from the zero line
   BUFFER_STATUS_ARROW,      //     4 +8 = 12   // Drawing with arrows
   BUFFER_STATUS_SECTION,    //     5 +8 = 13   // Segments
   BUFFER_STATUS_HISTOGRAM2, //     6 +8 = 14   // Histogram on two indicator buffers
   BUFFER_STATUS_ZIGZAG,     //     7 +8 = 15   // Zigzag style
   BUFFER_STATUS_BARS,       //     8 +8 = 16   // Display as bars (MQL5)
   BUFFER_STATUS_CANDLES,    //     9 +8 = 17   // Display as candles (MQL5)
  };
2020.04.15 12:51:53.725 DRAW_NONE = 0
2020.04.15 12:51:53.725 DRAW_LINE = 1
2020.04.15 12:51:53.725 DRAW_HISTOGRAM = 2
2020.04.15 12:51:53.725 DRAW_ARROW = 3
2020.04.15 12:51:53.725 DRAW_SECTION = 4
2020.04.15 12:51:53.725 DRAW_HISTOGRAM2 = 5
2020.04.15 12:51:53.725 DRAW_ZIGZAG = 6
2020.04.15 12:51:53.725 DRAW_FILLING = 7
2020.04.15 12:51:53.725 DRAW_BARS = 8
2020.04.15 12:51:53.725 DRAW_CANDLES = 9
2020.04.15 12:51:53.725 DRAW_COLOR_LINE = 10
2020.04.15 12:51:53.725 DRAW_COLOR_HISTOGRAM = 11
2020.04.15 12:51:53.725 DRAW_COLOR_ARROW = 12
2020.04.15 12:51:53.725 DRAW_COLOR_SECTION = 13
2020.04.15 12:51:53.725 DRAW_COLOR_HISTOGRAM2 = 14
2020.04.15 12:51:53.725 DRAW_COLOR_ZIGZAG = 15
2020.04.15 12:51:53.725 DRAW_COLOR_BARS = 16
2020.04.15 12:51:53.725 DRAW_COLOR_CANDLES = 17

したがって、その描画スタイルはバッファステータス値に基づいて設定されます。

バッファプロパティを設定して返すための残りのすべてのメソッドを追加し、そのプロパティの説明を操作ログに表示して、クラスのpublicセクションに追加します。

public:  
   
//--- Set (1) the arrow code, (2) vertical shift of arrows, (3) symbol, (4) timeframe, (5) buffer activity flag
//--- (6) number of initial bars without drawing, (7) flag of displaying construction values in DataWindow,
//--- (8) shift of the indicator graphical construction along the time axis, (9) line style, (10) line width,
//--- (11) number of colors, (12) drawing color, (13) empty value and (14) graphical series name displayed in DataWindow
   virtual void      SetArrowCode(const uchar code)                  { return;                                                            }
   virtual void      SetArrowShift(const int shift)                  { return;                                                            }
   void              SetSymbol(const string symbol)                  { this.SetProperty(BUFFER_PROP_SYMBOL,symbol);                       }
   void              SetTimeframe(const ENUM_TIMEFRAMES timeframe)   { this.SetProperty(BUFFER_PROP_TIMEFRAME,timeframe);                 }
   void              SetActive(const bool flag)                      { this.SetProperty(BUFFER_PROP_ACTIVE,flag);                         }
   void              SetDrawBegin(const int value);
   void              SetShowData(const bool flag);
   void              SetShift(const int shift);
   void              SetStyle(const ENUM_LINE_STYLE style);
   void              SetWidth(const int width);
   void              SetColorNumbers(const int number);
   void              SetColor(const color colour);
   void              SetEmptyValue(const double value);
   void              SetLabel(const string label);

//--- Return (1) the serial number of the drawn buffer, (2) bound array index, (3) color buffer index,
//--- (4) index of the first free bound array, (5) buffer data period (timeframe) (6) buffer status,
//--- (7) buffer type, (8) buffer usage flag, (9) arrow code, (10) arrow shift for DRAW_ARROW style,
//--- (11) Number of initial bars that are not drawn and values in DataWindow, (12) graphical construction type,
//--- (13) flag of displaying construction values in DataWindow, (14) indicator graphical construction shift along the time axis,
//--- (15) drawing line style, (16) drawing line width, (17) number of colors, (18) drawing color,
//--- (19) set empty value, (20) buffer symbol and (21) name of the indicator graphical series displayed in DataWindow
   int               IndexPlot(void)                           const { return (int)this.GetProperty(BUFFER_PROP_INDEX_PLOT);              }
   int               IndexBase(void)                           const { return (int)this.GetProperty(BUFFER_PROP_INDEX_BASE);              }
   int               IndexColor(void)                          const { return (int)this.GetProperty(BUFFER_PROP_INDEX_COLOR);             }
   int               IndexNextBuffer(void)                     const { return (int)this.GetProperty(BUFFER_PROP_INDEX_NEXT);              }
   ENUM_TIMEFRAMES   Timeframe(void)                           const { return (ENUM_TIMEFRAMES)this.GetProperty(BUFFER_PROP_TIMEFRAME);   }
   ENUM_BUFFER_STATUS Status(void)                             const { return (ENUM_BUFFER_STATUS)this.GetProperty(BUFFER_PROP_STATUS);   }
   ENUM_BUFFER_TYPE  TypeBuffer(void)                          const { return (ENUM_BUFFER_TYPE)this.GetProperty(BUFFER_PROP_TYPE);       }
   bool              IsActive(void)                            const { return (bool)this.GetProperty(BUFFER_PROP_ACTIVE);                 }
   uchar             ArrowCode(void)                           const { return (uchar)this.GetProperty(BUFFER_PROP_ARROW_CODE);            }
   int               ArrowShift(void)                          const { return (int)this.GetProperty(BUFFER_PROP_ARROW_SHIFT);             }
   int               DrawBegin(void)                           const { return (int)this.GetProperty(BUFFER_PROP_DRAW_BEGIN);              }
   ENUM_DRAW_TYPE    DrawType(void)                            const { return (ENUM_DRAW_TYPE)this.GetProperty(BUFFER_PROP_DRAW_TYPE);    }
   bool              IsShowData(void)                          const { return (bool)this.GetProperty(BUFFER_PROP_SHOW_DATA);              }
   int               Shift(void)                               const { return (int)this.GetProperty(BUFFER_PROP_SHIFT);                   }
   ENUM_LINE_STYLE   LineStyle(void)                           const { return (ENUM_LINE_STYLE)this.GetProperty(BUFFER_PROP_LINE_STYLE);  }
   int               LineWidth(void)                           const { return (int)this.GetProperty(BUFFER_PROP_LINE_WIDTH);              }
   int               NumberColors(void)                        const { return (int)this.GetProperty(BUFFER_PROP_COLOR_INDEXES);           }
   color             Color(void)                               const { return (color)this.GetProperty(BUFFER_PROP_COLOR);                 }
   double            EmptyValue(void)                          const { return this.GetProperty(BUFFER_PROP_EMPTY_VALUE);                  }
   string            Symbol(void)                              const { return this.GetProperty(BUFFER_PROP_SYMBOL);                       }
   string            Label(void)                               const { return this.GetProperty(BUFFER_PROP_LABEL);                        }
   
//--- Return descriptions of the (1) buffer status, (2) buffer type, (3) buffer usage flag, (4) flag of displaying construction values in DataWindow,
//--- (5) drawing line style, (6) set empty value, (7) graphical construction type and (8) used timeframe
   string            GetStatusDescription(bool draw_type=false)const;
   string            GetTypeBufferDescription(void)            const;
   string            GetActiveDescription(void)                const;
   string            GetShowDataDescription(void)              const;
   string            GetLineStyleDescription(void)             const;
   string            GetEmptyValueDescription(void)            const;
   string            GetDrawTypeDescription(void)              const;
   string            GetTimeframeDescription(void)             const;

//--- Return the size of the data buffer array
   int               GetDataTotal(void)                        const { return ::ArraySize(this.DataArray);                                }
   
  };
//+------------------------------------------------------------------+

宣言されたメソッドとClosedパラメトリックコンストラクタの実装について考えてみましょう。

以下はClosedパラメトリックコンストラクタです。

//+------------------------------------------------------------------+
//| Closed parametric constructor                                    |
//+------------------------------------------------------------------+
CBuffer::CBuffer(ENUM_BUFFER_STATUS buffer_status,ENUM_BUFFER_TYPE buffer_type,const uint index_plot,const uint index_base_array)
  {
   this.m_type=COLLECTION_BUFFERS_ID;
//--- Save integer properties
   this.m_long_prop[BUFFER_PROP_STATUS]                        = buffer_status;
   this.m_long_prop[BUFFER_PROP_TYPE]                          = buffer_type;
   this.m_long_prop[BUFFER_PROP_TIMEFRAME]                     = PERIOD_CURRENT;
   this.m_long_prop[BUFFER_PROP_ACTIVE]                        = false;
   this.m_long_prop[BUFFER_PROP_ARROW_CODE]                    = 0xFB;
   this.m_long_prop[BUFFER_PROP_ARROW_SHIFT]                   = 0;
   this.m_long_prop[BUFFER_PROP_DRAW_BEGIN]                    = 0;
   this.m_long_prop[BUFFER_PROP_SHOW_DATA]                     = (buffer_type>BUFFER_TYPE_CALCULATE ? true : false);
   this.m_long_prop[BUFFER_PROP_SHIFT]                         = 0;
   this.m_long_prop[BUFFER_PROP_LINE_STYLE]                    = STYLE_SOLID;
   this.m_long_prop[BUFFER_PROP_LINE_WIDTH]                    = 1;
   this.m_long_prop[BUFFER_PROP_COLOR_INDEXES]                 = 1;
   this.m_long_prop[BUFFER_PROP_COLOR]                         = clrRed;
   this.m_long_prop[BUFFER_PROP_NUM_DATAS]                     = 1;
   this.m_long_prop[BUFFER_PROP_INDEX_PLOT]                    = index_plot;
   this.m_long_prop[BUFFER_PROP_INDEX_BASE]                    = index_base_array;
   this.m_long_prop[BUFFER_PROP_INDEX_COLOR]                   = this.GetProperty(BUFFER_PROP_INDEX_BASE)+this.GetProperty(BUFFER_PROP_NUM_DATAS);
   this.m_long_prop[BUFFER_PROP_INDEX_NEXT]                    = this.GetProperty(BUFFER_PROP_INDEX_COLOR)+1;
   this.SetDrawType();
//--- Save real properties
   this.m_double_prop[this.IndexProp(BUFFER_PROP_EMPTY_VALUE)] = EMPTY_VALUE;
//--- Save string properties
   this.m_string_prop[this.IndexProp(BUFFER_PROP_SYMBOL)]      = ::Symbol();
   this.m_string_prop[this.IndexProp(BUFFER_PROP_LABEL)]       = (this.TypeBuffer()>BUFFER_TYPE_CALCULATE ? "Buffer "+(string)this.IndexPlot() : NULL);

//--- Bind indicator buffers with arrays
   ::SetIndexBuffer((int)this.GetProperty(BUFFER_PROP_INDEX_BASE),this.DataArray,INDICATOR_DATA);
   ::SetIndexBuffer((int)this.GetProperty(BUFFER_PROP_INDEX_COLOR),this.ColorArray,INDICATOR_COLOR_INDEX);

//--- Set integer buffer parameters
   ::PlotIndexSetInteger((int)this.GetProperty(BUFFER_PROP_INDEX_PLOT),PLOT_DRAW_TYPE,(ENUM_PLOT_PROPERTY_INTEGER)this.GetProperty(BUFFER_PROP_DRAW_TYPE));
   ::PlotIndexSetInteger((int)this.GetProperty(BUFFER_PROP_INDEX_PLOT),PLOT_ARROW,(ENUM_PLOT_PROPERTY_INTEGER)this.GetProperty(BUFFER_PROP_ARROW_CODE));
   ::PlotIndexSetInteger((int)this.GetProperty(BUFFER_PROP_INDEX_PLOT),PLOT_ARROW_SHIFT,(ENUM_PLOT_PROPERTY_INTEGER)this.GetProperty(BUFFER_PROP_ARROW_SHIFT));
   ::PlotIndexSetInteger((int)this.GetProperty(BUFFER_PROP_INDEX_PLOT),PLOT_DRAW_BEGIN,(ENUM_PLOT_PROPERTY_INTEGER)this.GetProperty(BUFFER_PROP_DRAW_BEGIN));
   ::PlotIndexSetInteger((int)this.GetProperty(BUFFER_PROP_INDEX_PLOT),PLOT_SHOW_DATA,(ENUM_PLOT_PROPERTY_INTEGER)this.GetProperty(BUFFER_PROP_SHOW_DATA));
   ::PlotIndexSetInteger((int)this.GetProperty(BUFFER_PROP_INDEX_PLOT),PLOT_SHIFT,(ENUM_PLOT_PROPERTY_INTEGER)this.GetProperty(BUFFER_PROP_SHIFT));
   ::PlotIndexSetInteger((int)this.GetProperty(BUFFER_PROP_INDEX_PLOT),PLOT_LINE_STYLE,(ENUM_PLOT_PROPERTY_INTEGER)this.GetProperty(BUFFER_PROP_LINE_STYLE));
   ::PlotIndexSetInteger((int)this.GetProperty(BUFFER_PROP_INDEX_PLOT),PLOT_LINE_WIDTH,(ENUM_PLOT_PROPERTY_INTEGER)this.GetProperty(BUFFER_PROP_LINE_WIDTH));
   ::PlotIndexSetInteger((int)this.GetProperty(BUFFER_PROP_INDEX_PLOT),PLOT_COLOR_INDEXES,(ENUM_PLOT_PROPERTY_INTEGER)this.GetProperty(BUFFER_PROP_COLOR_INDEXES));
   ::PlotIndexSetInteger((int)this.GetProperty(BUFFER_PROP_INDEX_PLOT),PLOT_LINE_COLOR,(ENUM_PLOT_PROPERTY_INTEGER)this.GetProperty(BUFFER_PROP_COLOR));
//--- Set real buffer parameters
   ::PlotIndexSetDouble((int)this.GetProperty(BUFFER_PROP_INDEX_PLOT),PLOT_EMPTY_VALUE,this.GetProperty(BUFFER_PROP_EMPTY_VALUE));
//--- Set string buffer parameters
   ::PlotIndexSetString((int)this.GetProperty(BUFFER_PROP_INDEX_PLOT),PLOT_LABEL,this.GetProperty(BUFFER_PROP_LABEL));
  }
//+------------------------------------------------------------------+

コンストラクタの入力は、作成されたバッファオブジェクトのステータスとタイプ、描画されたバッファインデックス(気配値表示インデックス)、および基本配列インデックス(基本配列は、バッファの構築に使用される配列の一般的なリストの最初の配列です)を渡します。

バッファオブジェクトコレクションに属するタイプをオブジェクトに割り当て、整数、実数、文字列のオブジェクトプロパティにデフォルト値を入力します。
次に、指標バッファを配列にバインドし、整数型、実数型、文字列型のプロパティを、同じタイプのバッファオブジェクトプロパティの新しく満たされたデフォルト値から、描画されたバッファに設定します。

これらのアクションは、指定された描画タイプで1色の指標バッファを作成するのに十分です。指標からそのようなバッファを作成するときに、配列を宣言、設定、割り当てする必要はありません。必要なすべてのバッファオブジェクトが既に存在し、(必要に応じて)バッファオブジェクトに割り当てられています。BUFFER_PROP_INDEX_PLOTプロパティには、指標プログラムからのバッファデータの設定と受信に使用される描画バッファインデックスが含まれています。

これは標準的なメソッドです。他のオブジェクトの同様のメソッドについては、これまでのすべての記事ですでに説明してきました。さらに、最初のライブラリオブジェクトを作成するときには、メソッドを詳細に検討しました。

以下は、検索と並べ替えのための比較メソッド、および比較された2つのオブジェクトの同等性のフラグを返すメソッドです。

//+------------------------------------------------------------------+
//| Class methods                                                    |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Compare CBuffer objects by all possible properties               |
//+------------------------------------------------------------------+
int CBuffer::Compare(const CObject *node,const int mode=0) const
  {
   const CBuffer *compared_obj=node;
//--- compare integer properties of two buffers
   if(mode<BUFFER_PROP_INTEGER_TOTAL)
     {
      long value_compared=compared_obj.GetProperty((ENUM_BUFFER_PROP_INTEGER)mode);
      long value_current=this.GetProperty((ENUM_BUFFER_PROP_INTEGER)mode);
      return(value_current>value_compared ? 1 : value_current<value_compared ? -1 : 0);
     }
//--- compare real properties of two buffers
   else if(mode<BUFFER_PROP_INTEGER_TOTAL+BUFFER_PROP_DOUBLE_TOTAL)
     {
      double value_compared=compared_obj.GetProperty((ENUM_BUFFER_PROP_DOUBLE)mode);
      double value_current=this.GetProperty((ENUM_BUFFER_PROP_DOUBLE)mode);
      return(value_current>value_compared ? 1 : value_current<value_compared ? -1 : 0);
     }
//--- compare string properties of two buffers
   else if(mode<BUFFER_PROP_INTEGER_TOTAL+BUFFER_PROP_DOUBLE_TOTAL+BUFFER_PROP_STRING_TOTAL)
     {
      string value_compared=compared_obj.GetProperty((ENUM_BUFFER_PROP_STRING)mode);
      string value_current=this.GetProperty((ENUM_BUFFER_PROP_STRING)mode);
      return(value_current>value_compared ? 1 : value_current<value_compared ? -1 : 0);
     }
   return 0;
  }
//+------------------------------------------------------------------+
//| Compare CBuffer objects by all properties                        |
//+------------------------------------------------------------------+
bool CBuffer::IsEqual(CBuffer *compared_obj) const
  {
   int beg=0, end=BUFFER_PROP_INTEGER_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_BUFFER_PROP_INTEGER prop=(ENUM_BUFFER_PROP_INTEGER)i;
      if(this.GetProperty(prop)!=compared_obj.GetProperty(prop)) return false; 
     }
   beg=end; end+=BUFFER_PROP_DOUBLE_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_BUFFER_PROP_DOUBLE prop=(ENUM_BUFFER_PROP_DOUBLE)i;
      if(this.GetProperty(prop)!=compared_obj.GetProperty(prop)) return false; 
     }
   beg=end; end+=BUFFER_PROP_STRING_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_BUFFER_PROP_STRING prop=(ENUM_BUFFER_PROP_STRING)i;
      if(this.GetProperty(prop)!=compared_obj.GetProperty(prop)) return false; 
     }
   return true;
  }
//+------------------------------------------------------------------+

以下は、すべてのバッファオブジェクトプロパティを表示するメソッドです。

//+------------------------------------------------------------------+
//| Display buffer properties in the journal                         |
//+------------------------------------------------------------------+
void CBuffer::Print(const bool full_prop=false)
  {
   ::Print("============= ",
           CMessage::Text(MSG_LIB_PARAMS_LIST_BEG),": ",
           this.GetTypeBufferDescription(),"[",(string)this.IndexPlot(),"] \"",this.GetStatusDescription(true),"\"",
           " =================="
          );
   int beg=0, end=BUFFER_PROP_INTEGER_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_BUFFER_PROP_INTEGER prop=(ENUM_BUFFER_PROP_INTEGER)i;
      if(!full_prop && !this.SupportProperty(prop)) continue;
      ::Print(this.GetPropertyDescription(prop));
     }
   ::Print("------");
   beg=end; end+=BUFFER_PROP_DOUBLE_TOTAL;
   for(int i=beg; i<end; i++)
     {

      ENUM_BUFFER_PROP_DOUBLE prop=(ENUM_BUFFER_PROP_DOUBLE)i;
      if(!full_prop && !this.SupportProperty(prop)) continue;
      ::Print(this.GetPropertyDescription(prop));
     }
   ::Print("------");
   beg=end; end+=BUFFER_PROP_STRING_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_BUFFER_PROP_STRING prop=(ENUM_BUFFER_PROP_STRING)i;
      if(!full_prop && !this.SupportProperty(prop)) continue;
      ::Print(this.GetPropertyDescription(prop));
     }
   ::Print("================== ",
           CMessage::Text(MSG_LIB_PARAMS_LIST_END),": ",
           this.GetTypeBufferDescription(),"[",(string)this.IndexPlot(),"] \"",this.GetStatusDescription(true),"\"",
           " ==================\n"
          );
  }
//+------------------------------------------------------------------+

以下は、整数実数文字列バッファオブジェクトプロパティの説明を返すメソッドです。

//+------------------------------------------------------------------+
//| Return description of a buffer's integer property                |
//+------------------------------------------------------------------+
string CBuffer::GetPropertyDescription(ENUM_BUFFER_PROP_INTEGER property)
  {
   return
     (
      property==BUFFER_PROP_INDEX_PLOT    ?  CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_INDEX_PLOT)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==BUFFER_PROP_NUM_DATAS     ?  CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_NUM_DATAS)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==BUFFER_PROP_INDEX_NEXT    ?  CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_INDEX_NEXT)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==BUFFER_PROP_TIMEFRAME     ?  CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_TIMEFRAME)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+this.GetTimeframeDescription()
         )  :
      property==BUFFER_PROP_STATUS        ?  CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_STATUS)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+this.GetStatusDescription()
         )  :
      property==BUFFER_PROP_TYPE          ?  CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_TYPE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+this.GetTypeBufferDescription()
         )  :
      property==BUFFER_PROP_ACTIVE        ?  CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_ACTIVE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+this.GetActiveDescription()
         )  :
      property==BUFFER_PROP_ARROW_CODE    ?  CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_ARROW_CODE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==BUFFER_PROP_ARROW_SHIFT   ?  CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_ARROW_SHIFT)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==BUFFER_PROP_DRAW_BEGIN    ?  CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_DRAW_BEGIN)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==BUFFER_PROP_DRAW_TYPE     ?  CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_DRAW_TYPE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+this.GetDrawTypeDescription()
         )  :
      property==BUFFER_PROP_SHOW_DATA     ?  CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_SHOW_DATA)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+this.GetShowDataDescription()
         )  :
      property==BUFFER_PROP_SHIFT         ?  CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_SHIFT)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==BUFFER_PROP_LINE_STYLE    ?  CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_LINE_STYLE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+this.GetLineStyleDescription()
         )  :
      property==BUFFER_PROP_LINE_WIDTH    ?  CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_LINE_WIDTH)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==BUFFER_PROP_COLOR_INDEXES ?  CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_COLOR_NUM)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==BUFFER_PROP_COLOR         ?  CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_COLOR)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+ColorToString(this.Color(),true)
         )  :
      property==BUFFER_PROP_INDEX_BASE    ?  CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_INDEX_BASE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==BUFFER_PROP_NUM_DATAS ?  CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_NUM_DATAS)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==BUFFER_PROP_INDEX_COLOR   ?  CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_INDEX_COLOR)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==BUFFER_PROP_INDEX_NEXT         ?  CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_INDEX_NEXT)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+ColorToString(this.Color(),true)
         )  :
      ""
     );
  }
//+------------------------------------------------------------------+
//| Return description of a buffer's real property                   |
//+------------------------------------------------------------------+
string CBuffer::GetPropertyDescription(ENUM_BUFFER_PROP_DOUBLE property)
  {
   return
     (
      property==BUFFER_PROP_EMPTY_VALUE    ?  CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_EMPTY_VALUE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+this.GetEmptyValueDescription()
         )  :
      ""
     );
  }
//+------------------------------------------------------------------+
//| Return description of a buffer's string property                 |
//+------------------------------------------------------------------+
string CBuffer::GetPropertyDescription(ENUM_BUFFER_PROP_STRING property)
  {
   return
     (
      property==BUFFER_PROP_SYMBOL    ?  CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_SYMBOL)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+this.Symbol()
         )  :
      property==BUFFER_PROP_LABEL    ?  CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_LABEL)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.Label()==NULL || this.Label()=="" ? CMessage::Text(MSG_LIB_PROP_NOT_SET) : this.Label())
         )  :
      ""
     );
  }
//+------------------------------------------------------------------+

クラスpublicセクションに追加された残りのメソッドの実装を見てみましょう。

以下は、バッファステータスの説明を返すメソッドです。

//+------------------------------------------------------------------+
//| Return the buffer status description                             |
//+------------------------------------------------------------------+
string CBuffer::GetStatusDescription(bool draw_type=false) const
  {
   string type=
     (
      this.Status()==BUFFER_STATUS_NONE         ? CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_STATUS_NONE)         :
      this.Status()==BUFFER_STATUS_ARROW        ? CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_STATUS_ARROW)        :
      this.Status()==BUFFER_STATUS_BARS         ? CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_STATUS_BARS)         :
      this.Status()==BUFFER_STATUS_CANDLES      ? CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_STATUS_CANDLES)      :
      this.Status()==BUFFER_STATUS_FILLING      ? CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_STATUS_FILLING)      :
      this.Status()==BUFFER_STATUS_HISTOGRAM    ? CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_STATUS_HISTOGRAM)    :
      this.Status()==BUFFER_STATUS_HISTOGRAM2   ? CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_STATUS_HISTOGRAM2)   :
      this.Status()==BUFFER_STATUS_LINE         ? CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_STATUS_LINE)         :
      this.Status()==BUFFER_STATUS_SECTION      ? CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_STATUS_SECTION)      :
      this.Status()==BUFFER_STATUS_ZIGZAG       ? CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_STATUS_ZIGZAG)       :
      "Unknown"
     );
   return(!draw_type ? CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_STATUS_NAME)+" \""+type+"\"" : type);
  }
//+------------------------------------------------------------------+

バッファステータスもまた描画スタイルを定義するため、メソッドは説明を返す方法を指定するフラグを受け取ります。
— バッファステータスが要求された場合(draw_typefalseに設定)、バッファステータスは次の形式で返されます。

バッファステータス: グラフィカル構築タイプがLineの指標バッファ

— 描画タイプが要求された場合(draw_typetrueに設定)、描画タイプは次の形式で返されます。

グラフィカル構築タイプ: Line

すべてのオブジェクトプロパティの説明を返すメソッドは非常に単純なので、ご自身でご覧ください。

//+------------------------------------------------------------------+
//| Return the buffer type description                               |
//+------------------------------------------------------------------+
string CBuffer::GetTypeBufferDescription(void) const
  {
   return
     (
      this.TypeBuffer()==BUFFER_TYPE_DATA       ? CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_TYPE_DATA)        :
      this.TypeBuffer()==BUFFER_TYPE_CALCULATE  ? CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_TYPE_CALCULATE)   :
      "Unknown"
     );
  }
//+------------------------------------------------------------------+
//| Return description of the buffer usage flag                      |
//+------------------------------------------------------------------+
string CBuffer::GetActiveDescription(void) const
  {
   return(this.IsActive() ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO));
  }
//+---------------------------------------------------------------------+
//|Return description of displaying construction values in DataWindow   |
//+---------------------------------------------------------------------+
string CBuffer::GetShowDataDescription(void) const
  {
   return(this.IsShowData() ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO));
  }
//+------------------------------------------------------------------+
//| Return description of the drawing line style                     |
//+------------------------------------------------------------------+
string CBuffer::GetLineStyleDescription(void) const
  {
   return
     (
      this.LineStyle()==STYLE_SOLID       ? CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_STYLE_SOLID)      :
      this.LineStyle()==STYLE_DASH        ? CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_STYLE_DASH)       :
      this.LineStyle()==STYLE_DOT         ? CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_STYLE_DOT)        :
      this.LineStyle()==STYLE_DASHDOT     ? CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_STYLE_DASHDOT)    :
      this.LineStyle()==STYLE_DASHDOTDOT  ? CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_STYLE_DASHDOTDOT) :
      "Unknown"
     );
  }
//+------------------------------------------------------------------+
//| Return description of the set empty value                        |
//+------------------------------------------------------------------+
string CBuffer::GetEmptyValueDescription(void) const
  {
   return(this.EmptyValue()<EMPTY_VALUE ? ::DoubleToString(this.EmptyValue(),(this.EmptyValue()==0 ? 1 : 8)) : "EMPTY_VALUE");
  }
//+------------------------------------------------------------------+
//| Return description of the graphical construction type            |
//+------------------------------------------------------------------+
string CBuffer::GetDrawTypeDescription(void) const
  {
   return this.GetStatusDescription(true);
  } 
//+------------------------------------------------------------------+
//| Return description of the used timeframe                         |
//+------------------------------------------------------------------+
string CBuffer::GetTimeframeDescription(void) const
  {
   string timeframe=TimeframeDescription(this.Timeframe());
   return(this.Timeframe()==PERIOD_CURRENT ? CMessage::Text(MSG_LIB_TEXT_PERIOD_CURRENT)+" ("+timeframe+")" : timeframe);
  } 
//+------------------------------------------------------------------+

以下は、さまざまなバッファオブジェクトプロパティを設定するためのメソッドです。

//+------------------------------------------------------------------+
//| Set the number of initial bars                                   |
//| without drawing and values in DataWindow                         |
//+------------------------------------------------------------------+
void CBuffer::SetDrawBegin(const int value)
  {
   this.SetProperty(BUFFER_PROP_DRAW_BEGIN,value);
   ::PlotIndexSetInteger((int)this.GetProperty(BUFFER_PROP_INDEX_PLOT),PLOT_DRAW_BEGIN,value);
  }
//+------------------------------------------------------------------+
//| Set the flag of displaying                                       |
//| construction values in DataWindow                                |
//+------------------------------------------------------------------+
void CBuffer::SetShowData(const bool flag)
  {
   this.SetProperty(BUFFER_PROP_SHOW_DATA,flag);
   ::PlotIndexSetInteger((int)this.GetProperty(BUFFER_PROP_INDEX_PLOT),PLOT_SHOW_DATA,flag);
  }
//+------------------------------------------------------------------+
//| Set the indicator graphical construction shift                   |
//+------------------------------------------------------------------+
void CBuffer::SetShift(const int shift)
  {
   this.SetProperty(BUFFER_PROP_SHIFT,shift);
   ::PlotIndexSetInteger((int)this.GetProperty(BUFFER_PROP_INDEX_PLOT),PLOT_SHIFT,shift);
  }
//+------------------------------------------------------------------+
//| Set the line style                                               |
//+------------------------------------------------------------------+
void CBuffer::SetStyle(const ENUM_LINE_STYLE style)
  {
   this.SetProperty(BUFFER_PROP_LINE_STYLE,style);
   ::PlotIndexSetInteger((int)this.GetProperty(BUFFER_PROP_INDEX_PLOT),PLOT_LINE_STYLE,style);
  }
//+------------------------------------------------------------------+
//| Set the line width                                               |
//+------------------------------------------------------------------+
void CBuffer::SetWidth(const int width)
  {
   this.SetProperty(BUFFER_PROP_LINE_WIDTH,width);
   ::PlotIndexSetInteger((int)this.GetProperty(BUFFER_PROP_INDEX_PLOT),PLOT_LINE_WIDTH,width);
  }
//+------------------------------------------------------------------+
//| Set the number of colors                                         |
//+------------------------------------------------------------------+
void CBuffer::SetColorNumbers(const int number)
  {
   this.SetProperty(BUFFER_PROP_COLOR_INDEXES,number);
   ::PlotIndexSetInteger((int)this.GetProperty(BUFFER_PROP_INDEX_PLOT),PLOT_COLOR_INDEXES,number);
  }
//+------------------------------------------------------------------+
//| Set the drawing color                                            |
//+------------------------------------------------------------------+
void CBuffer::SetColor(const color colour)
  {
   this.SetProperty(BUFFER_PROP_COLOR,colour);
   ::PlotIndexSetInteger((int)this.GetProperty(BUFFER_PROP_INDEX_PLOT),PLOT_LINE_COLOR,colour);
  }
//+------------------------------------------------------------------+
//| Set the "empty" value for construction                           |
//| without drawing                                                  |
//+------------------------------------------------------------------+
void CBuffer::SetEmptyValue(const double value)
  {
   this.SetProperty(BUFFER_PROP_EMPTY_VALUE,value);
   ::PlotIndexSetDouble((int)this.GetProperty(BUFFER_PROP_INDEX_PLOT),PLOT_EMPTY_VALUE,value);
  }
//+------------------------------------------------------------------+
//| Set the drawing color                                            |
//+------------------------------------------------------------------+
void CBuffer::SetLabel(const string label)
  {
   this.SetProperty(BUFFER_PROP_LABEL,label);
   ::PlotIndexSetString((int)this.GetProperty(BUFFER_PROP_INDEX_PLOT),PLOT_LABEL,label);
  }
//+------------------------------------------------------------------+

メソッドに渡された値は、最初に適切なバッファオブジェクトプロパティに書き込まれます、次にプロパティは、描画されたバッファにそのインデックスによって設定されます

現在、抽象指標バッファオブジェクトを作成するために必要なのはこれですべてです。

指標でのバッファオブジェクト作成の確認

抽象バッファオブジェクトの動作を確認するには、前の記事の指標を\MQL5\Indicators\TestDoEasy\Part42\TestDoEasyPart42.mq5として保存します。

不要なものは全部削除します。
ボタン、ボタン押下処理関数やバッファデータ入力関数は必要ないため、ライブラリの操作に直接関連する要素のみを残して、コードから削除します。

さらに、OnCalculate()からライブラリの価格構造にデータをコピーするための関数を、指標コードからライブラリサービス関数のファイルに移動しましょう。\MQL5\Include\DoEasy\Services\DELib.mqhを開いて2つの関数を追加します。

//+------------------------------------------------------------------+
//| Copy data from the first OnCalculate() form to the structure     |
//+------------------------------------------------------------------+
void CopyData(const int rates_total,
              const int prev_calculated,
              const int begin,
              const double &price[])
  {
//--- Get the array indexing flag as in the timeseries. If failed,
//--- set the indexing direction for the array as in the timeseries
   bool as_series_price=ArrayGetAsSeries(price);
   if(!as_series_price)
      ArraySetAsSeries(price,true);
//--- Copy the array zero bar to the OnCalculate() SDataCalculate data structure
   rates_data.rates_total=rates_total;
   rates_data.prev_calculated=prev_calculated;
   rates_data.begin=begin;
   rates_data.price=price[0];
//--- Return the array's initial indexing direction
   if(!as_series_price)
      ArraySetAsSeries(price,false);
  }
//+------------------------------------------------------------------+
//| Copy data from the second OnCalculate() form to the structure    |
//+------------------------------------------------------------------+
void CopyData(const int rates_total,
              const int prev_calculated,
              const datetime &time[],
              const double &open[],
              const double &high[],
              const double &low[],
              const double &close[],
              const long &tick_volume[],
              const long &volume[],
              const int &spread[])
  {
//--- Get the array indexing flags as in the timeseries. If failed,
//--- set the indexing direction or the arrays as in the timeseries
   bool as_series_time=ArrayGetAsSeries(time);
   if(!as_series_time)
      ArraySetAsSeries(time,true);
   bool as_series_open=ArrayGetAsSeries(open);
   if(!as_series_open)
      ArraySetAsSeries(open,true);
   bool as_series_high=ArrayGetAsSeries(high);
   if(!as_series_high)
      ArraySetAsSeries(high,true);
   bool as_series_low=ArrayGetAsSeries(low);
   if(!as_series_low)
      ArraySetAsSeries(low,true);
   bool as_series_close=ArrayGetAsSeries(close);
   if(!as_series_close)
      ArraySetAsSeries(close,true);
   bool as_series_tick_volume=ArrayGetAsSeries(tick_volume);
   if(!as_series_tick_volume)
      ArraySetAsSeries(tick_volume,true);
   bool as_series_volume=ArrayGetAsSeries(volume);
   if(!as_series_volume)
      ArraySetAsSeries(volume,true);
   bool as_series_spread=ArrayGetAsSeries(spread);
   if(!as_series_spread)
      ArraySetAsSeries(spread,true);
//--- Copy the arrays' zero bar to the OnCalculate() SDataCalculate data structure
   rates_data.rates_total=rates_total;
   rates_data.prev_calculated=prev_calculated;
   rates_data.rates.time=time[0];
   rates_data.rates.open=open[0];
   rates_data.rates.high=high[0];
   rates_data.rates.low=low[0];
   rates_data.rates.close=close[0];
   rates_data.rates.tick_volume=tick_volume[0];
   rates_data.rates.real_volume=(#ifdef __MQL5__ volume[0] #else 0 #endif);
   rates_data.rates.spread=(#ifdef __MQL5__ spread[0] #else 0 #endif);
//--- Return the arrays' initial indexing direction
   if(!as_series_time)
      ArraySetAsSeries(time,false);
   if(!as_series_open)
      ArraySetAsSeries(open,false);
   if(!as_series_high)
      ArraySetAsSeries(high,false);
   if(!as_series_low)
      ArraySetAsSeries(low,false);
   if(!as_series_close)
      ArraySetAsSeries(close,false);
   if(!as_series_tick_volume)
      ArraySetAsSeries(tick_volume,false);
   if(!as_series_volume)
      ArraySetAsSeries(volume,false);
   if(!as_series_spread)
      ArraySetAsSeries(spread,false);
  }
//+------------------------------------------------------------------+

結果的に、現在の検証と将来の使用に役立つように指標コードをきれいにしました。移動された2つの関数は、ライブラリ内の指標を操作するために必要であるため、ライブラリサービス関数のファイルが最適です。

指標の「ヘッダ」は次のとおりです。

//+------------------------------------------------------------------+
//|                                             TestDoEasyPart42.mq5 |
//|                        Copyright 2020, MetaQuotes Software Corp. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, MetaQuotes Software Corp."
#property link      "https://mql5.com/en/users/artmedia70"
#property version   "1.00"
//--- includes
#include <DoEasy\Engine.mqh>
#include <DoEasy\Objects\Indicators\Buffer.mqh>
//--- properties
#property indicator_chart_window
#property indicator_buffers 4
#property indicator_plots   2

//--- classes

//--- enums

//--- defines

//--- structures

//--- input variables
/*sinput*/ ENUM_SYMBOLS_MODE  InpModeUsedSymbols=  SYMBOLS_MODE_DEFINES;            // Mode of used symbols list
sinput   string               InpUsedSymbols    =  "EURUSD,AUDUSD,EURAUD,EURGBP,EURCAD,EURJPY,EURUSD,GBPUSD,NZDUSD,USDCAD,USDJPY";  // List of used symbols (comma - separator)
sinput   ENUM_TIMEFRAMES_MODE InpModeUsedTFs    =  TIMEFRAMES_MODE_LIST;            // Mode of used timeframes list
sinput   string               InpUsedTFs        =  "M1,M5,M15,M30,H1,H4,D1,W1,MN1"; // List of used timeframes (comma - separator)
sinput   bool                 InpUseSounds      =  true; // Use sounds
//--- indicator buffers
CArrayObj      list_buffers;                    // Temporary list for storing two buffer objects
//--- global variables
CEngine        engine;                          // CEngine library main object
string         prefix;                          // Prefix of graphical object names
int            min_bars;                        // The minimum number of bars for the indicator calculation
int            used_symbols_mode;               // Mode of working with symbols
string         array_used_symbols[];            // The array for passing used symbols to the library
string         array_used_periods[];            // The array for passing used timeframes to the library
//+------------------------------------------------------------------+

ここで、別のウィンドウで指標を作成し、4つのバッファを設定するようにコンパイラーに命令します(2つは描画され、2つはカラー)。
残りのバッファパラメータは、指標バッファオブジェクトの作成中および作成後に設定されます。
CArrayObjポインタの動的配列を指標バッファとして追加します。作成されたバッファを保存するためのものです。

バッファオブジェクトを使用する場合、指標バッファとして割り当てるためにdouble配列を宣言する必要はありません。すべては作成されたバッファオブジェクト内にあり、指標のOnInit()ハンドラで作成されるときに割り当てられます

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Initialize DoEasy library
   OnInitDoEasy();

//--- Set indicator global variables
   prefix=engine.Name()+"_";
   //--- Get the index of the maximum used timeframe in the array,
   //--- calculate the number of bars of the current period fitting in the maximum used period
   //--- Use the obtained value if it exceeds 2, otherwise use 2
   int index=ArrayMaximum(ArrayUsedTimeframes);
   int num_bars=NumberBarsInTimeframe(ArrayUsedTimeframes[index]);
   min_bars=(index>WRONG_VALUE ? (num_bars>2 ? num_bars : 2) : 2);

//--- Check and remove remaining indicator graphical objects
   if(IsPresentObectByPrefix(prefix))
      ObjectsDeleteAll(0,prefix);

//--- Create the button panel


//--- Check playing a standard sound using macro substitutions
   engine.PlaySoundByDescription(SND_OK);
//--- Wait for 600 milliseconds
   engine.Pause(600);
   engine.PlaySoundByDescription(SND_NEWS);

//--- indicator buffers mapping
  
//--- Create two buffer objects
   CBuffer *buffer0=new CBuffer(BUFFER_STATUS_ARROW,BUFFER_TYPE_DATA, 0, 0);
   CBuffer *buffer1=new CBuffer(BUFFER_STATUS_LINE,BUFFER_TYPE_DATA, 1, buffer0.IndexNextBuffer());
//--- Set non-default values for the second buffer's "empty" value and color 
   buffer1.SetEmptyValue(0);
   buffer1.SetColor(clrBlue);
//--- Add both buffers to the list of indicator buffers
   list_buffers.Add(buffer0);
   list_buffers.Add(buffer1);
//--- Print data of the created buffers
   buffer0.Print();
   buffer1.Print();
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+

ここでは、抽象指標バッファの2つのオブジェクトを作成しました。
最初のオブジェクトのステータスは「矢印で描画」です。これは最初のバッファであり、すべてのインデックスはここで初期値を持つ必要があるので、描画バッファインデックスおよびバッファベース配列インデックスを0に設定します。
指標バッファコレクションを作成するときには、バッファオブジェクトの作成時に配列インデックスを指定しません。すべてのインデックスは自動的に設定され、介入は必要ありません。
2番目のオブジェクトのステータスは「ライン」です。描画バッファインデックスとして1(ゼロに続く)を設定します。また、最初のバッファオブジェクトから返された値を基本配列インデックスとして設定します。これは、次のバッファの基本配列として指定するための、次の空き配列のインデックスを示す値です。

さらに、2番目に作成されたバッファには「空」の値として0が割り当てられ、線の色は「青」に設定されます(値がバッファオブジェクトのプロパティにどのように設定されているかを確認するため)。
以前に宣言したlist_buffersリストに両方のバッファを追加し、新しく作成した両方のバッファのすべてのプロパティを操作ログに送信します。

これは、テスト指標であるため、バッファオブジェクトが正常に作成されてリストに追加されているかどうかは確認しません。また、バッファオブジェクトを手早く検証するために、オブジェクトの作成とリストへの追加の制御を無視できます。

前の記事のOnCalculate()ハンドラを「消去」してテストに最も必要な要素のみを残し、2つのバッファオブジェクトを作成した結果と指標バッファとしての正しい割り当てを確認するだけにします。

どのようにすればいいでしょうか。
バッファの作成は、作成された各バッファのすべてのプロパティを操作ログに出力するときに、OnCalculate()で確認されます。指標バッファとして作成されたオブジェクトの正常な割り当ては、OnCalculate()でのみ確認できます。これを行うには、指標バッファとしてオブジェクトで使用される配列のサイズと銘柄のバーの数を比較します。

配列を指標バッファとして割り当てるとすぐに、実行されているターミナルサブシステムはこれらの配列を獲得し、それらにメモリを割り当てて配列サイズを管理します。したがって、必要なのは、list_buffersリストから各オブジェクトを取得し、バッファとして割り当てられた配列のサイズをOnCalculate()のrates_total値と比較することだけです。それらが等しいことは、ターミナルサブシステムがその制御下にあるバッファオブジェクトから配列を取得したことを示します。

各ティックでエントリを表示しないために、指標バッファとしてのバッファオブジェクト配列の割り当ては、計算されたlimit値が1を超える 最初の指標の計算中に検証されます。

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//+------------------------------------------------------------------+
//| OnCalculate code block for working with the library:             |
//+------------------------------------------------------------------+
   
//--- Pass the current symbol data from OnCalculate() to the price structure
   CopyData(rates_total,prev_calculated,time,open,high,low,close,tick_volume,volume,spread);

//--- Check for the minimum number of bars for calculation
   if(rates_total<min_bars || Point()==0) return 0;
   
//--- Handle the Calculate event in the library
//--- If the OnCalculate() method of the library returns zero, not all timeseries are ready - leave till the next tick
   if(engine.0)
      return 0;
   
//--- If working in the tester
   if(MQLInfoInteger(MQL_TESTER)) 
     {
      engine.OnTimer(rates_data);   // Working in the library timer
      EventsHandling();             // Working with library events
     }
//+------------------------------------------------------------------+
//| OnCalculate code block for working with the indicator:           |
//+------------------------------------------------------------------+
//--- Set OnCalculate arrays as timeseries
   ArraySetAsSeries(open,true);
   ArraySetAsSeries(high,true);
   ArraySetAsSeries(low,true);
   ArraySetAsSeries(close,true);
   ArraySetAsSeries(time,true);
   ArraySetAsSeries(tick_volume,true);
   ArraySetAsSeries(volume,true);
   ArraySetAsSeries(spread,true);

//--- Check and calculate the number of calculated bars
//--- If limit = 0, there are no new bars - calculate the current one
//--- If limit = 1, a new bar has appeared - calculate the first and the current ones
//--- limit > 1 means the first launch or changes in history - the full recalculation of all data
   int limit=rates_total-prev_calculated;
   
//--- Recalculate the entire history
   if(limit>1)
     {
      //--- In a loop by the number of buffers in the list
      for(int i=0;i<list_buffers.Total();i++)
        {
         //--- get the next buffer and display the type of its graphical construction to the journal
         //--- together with the double array assigned to the buffer (if all is correct, the size is equal to rates_total)
         CBuffer *buff=list_buffers.At(i);
         Print(buff.Label()," type = ",EnumToString(buff.DrawType()),", data total = ",buff.GetDataTotal(),", rates_total=",rates_total);
        }
      
      limit=rates_total-1;
     }
//--- Prepare data

//--- Calculate the indicator
   for(int i=limit; i>WRONG_VALUE && !IsStopped(); i--)
     {
      CalculateSeries(i,time[i]);
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

テスト指標のコード全体は下に添付されているファイルにあります。

以下のパラメータを設定した後、指標をコンパイルしてチャート上で起動します。


操作ログには次のエントリが表示されます。

Account 8550475: Artyom Trishkin (MetaQuotes Software Corp.) 10425.23 USD, 1:100, Hedge, MetaTrader 5 demo
--- Initializing "DoEasy" library ---
Working with the current symbol only. The number of used symbols: 1
"EURUSD"
Working with the specified timeframe list:
"M5"  "M15" "M30" "H1" 
EURUSD symbol timeseries: 
- Timeseries "EURUSD" M5: Requested: 1000, Actual: 1000, Created: 1000, On the server: 3684
- Timeseries "EURUSD" M15: Requested: 1000, Actual: 1000, Created: 1000, On the server: 3042
- Timeseries "EURUSD" M30: Requested: 1000, Actual: 0, Created: 0, On the server: 0
- Timeseries "EURUSD" H1: Requested: 1000, Actual: 1000, Created: 1000, On the server: 6240
Library initialization time: 00:00:00.156
 
============= Parameter list start: Colored data buffer[0] "Drawing with arrows" ==================
Plotted buffer serial number: 0
Buffer status: Indicator buffer with graphical construction type "Drawing with arrows"
Buffer type: Colored data buffer
Buffer data period (timeframe): Current chart period (M30)
Active: No
Arrow code: 251
The vertical shift of the arrows: 0
The number of initial bars that are not drawn and values in DataWindow: 0
Display construction values in DataWindow: Yes
Graphical construction type: Drawing with arrows
Indicator graphical construction shift by time axis in bars: 0
Line style: Solid line
Line width: 1
Number of colors: 1
Drawing color: clrRed
Number of data buffers: 1
Base data buffer index: 0
Color buffer index: 1
Index of the array to be assigned as the next indicator buffer: 2
------
Empty value for plotting where nothing will be drawn: EMPTY_VALUE
------
Buffer symbol: EURUSD
Name of the graphical indicator series displayed in DataWindow: Buffer 0
================== Parameter list end: Colored data buffer[0] "Drawing with arrows" ==================
 
============= Parameter list start: Colored data buffer[1] "Line" ==================
Plotted buffer serial number: 1
Buffer status: Indicator buffer with graphical construction type "Line"
Buffer type: Colored data buffer
Buffer data period (timeframe): Current chart period (M30)
Active: No
Arrow code: 251
The vertical shift of the arrows: 0
The number of initial bars that are not drawn and values in DataWindow: 0
Display construction values in DataWindow: Yes
Graphical construction type: Line
Indicator graphical construction shift by time axis in bars: 0
Line style: Solid line
Line width: 1
Number of colors: 1
Drawing color: clrBlue
Number of data buffers: 1
Base data buffer index: 2
Color buffer index: 3
Index of the array to be assigned as the next indicator buffer: 4
------
Empty value for plotting where nothing will be drawn: 0.0
------
Buffer symbol: EURUSD
Name of the graphical indicator series displayed in DataWindow: Buffer 1
================== Parameter list end: Colored data buffer[1] "Line" ==================
 
"EURUSD" M30 timeseries created successfully:
- Timeseries "EURUSD" M30: Requested: 1000, Actual: 1000, Created: 1000, On the server: 5111

Buffer 0 type = DRAW_COLOR_ARROW, data total = 5111, rates_total=5111
Buffer 1 type = DRAW_COLOR_LINE, data total = 5111, rates_total=5111

時系列の作成に関するライブラリメッセージの後に、作成された2つのバッファオブジェクトそれぞれのすべてのプロパティを表示するブロックがOnInit()から出力されます。次に、作成された各バッファの描画タイプに関する2つのメッセージがOnCalculate()から表示され、指標バッファとして割り当てられたバッファオブジェクトからの配列のサイズが出力され、指標の起動の瞬間のrates_totalの値が指定されます
ご覧のとおり、配列のサイズとrates_totalは一致しています。これは、作成されたバッファオブジェクトの配列がターミナルによって制御され、指標バッファとして使用されることを意味します。

もう一度確認するには、指標のプロパティを開き(Ctrl + I)、[色]タブに移動します。


名前と色は両方の指標バッファに設定されます。名前と色は、バッファオブジェクトクラスコンストラクタで設定されたデフォルトのものを除いて、指定されていません。2番目のバッファの場合は、OnInit()で作成した後に青にリセットています。

すべてが期待どおりに機能します。ただし、これはほんの始まりにすぎません。さまざまなタイプの指標バッファを作成するには、グラフィカル構築タイプごとに継承クラスを作成し、指標バッファコレクションからこれらのクラスを操作する必要があります。


次の段階

次回の記事では、抽象バッファクラスの子孫オブジェクトを作成します。これらのオブジェクトは、DoEasyライブラリに基づく指標プログラムで指標バッファを作成および使用するために、ライブラリによって使用されます。

現在のバージョンのライブラリのすべてのファイルは、テスト用EAファイルと一緒に以下に添付されているので、テストするにはダウンロードしてください。
質問、コメント、提案はコメント欄にお願いします。テスト指標はMQL5向けに開発されたのでご注意ください
添付ファイルはMetaTrader 5のみを対象としています。現在のライブラリバージョンはMetaTrader 4ではテストされていません。
指標バッファとそれらのコレクションのすべてのクラスを作成した後、MetaTrader 4にいくつかのMQL5機能を実装してみます。

目次に戻る

シリーズのこれまでの記事:

DoEasyライブラリの時系列(第35部): バーオブジェクトと銘柄の時系列リスト
DoEasyライブラリの時系列(第36部): すべての使用銘柄期間の時系列オブジェクト
DoEasyライブラリの時系列(第37部): すべての使用銘柄期間の時系列オブジェクト
DoEasyライブラリの時系列(第38部): 時系列コレクション-リアルタイムの更新とプログラムからのデータへのアクセス
DoEasyライブラリの時系列(第39部): ライブラリに基づいた指標 - データイベントと時系列イベントの準備
DoEasyライブラリの時系列(第40部): ライブラリに基づいた指標 - 実時間でのデータ更新
DoEasyライブラリの時系列(第41部): 複数銘柄・複数期間指標の例

MetaQuotes Software Corp.によりロシア語から翻訳された
元の記事: https://www.mql5.com/ru/articles/7821

添付されたファイル |
MQL5.zip (3707.09 KB)
トレードシグナルの多通貨監視(その5: 複合シグナル トレードシグナルの多通貨監視(その5: 複合シグナル

トレーディングシグナルモニターの作成に関連する第5回の記事では、コンポジットシグナルについて考え、必要な関数を実装していきます。 以前のバージョンでは、RSI、WPR、CCIなどのシンプルなシグナルを使用していましたが、カスタムインジケータを使用する可能性も考慮します。

DoEasyライブラリの時系列(第41部): 複数銘柄・複数期間指標の例 DoEasyライブラリの時系列(第41部): 複数銘柄・複数期間指標の例

本稿では、DoEasyライブラリの時系列クラスを使用して、選択された時間枠で選択された通貨ペアのチャートをサブウィンドウでローソク足として表示する複数銘柄・複数期間指標の例を検討します。ライブラリクラスを少し変更し、プログラム入力の列挙を格納してコンパイル言語を選択するための別のファイルを作成します。

DoEasyライブラリの時系列(第43部): 指標バッファオブジェクトクラス DoEasyライブラリの時系列(第43部): 指標バッファオブジェクトクラス

この記事では、DoEasyライブラリに基づくカスタム指標プログラムを作成しながら、抽象バッファオブジェクトの子孫としての指標バッファオブジェクトクラスの開発を考察し、宣言を簡略化して指標バッファを操作します。

MQLプログラムをグラフィカルに表示するためのマークアップツールとしてのMQL(その3)。 フォームデザイナー MQLプログラムをグラフィカルに表示するためのマークアップツールとしてのMQL(その3)。 フォームデザイナー

本論文では、MQLの構造を利用してMQLプログラムのウィンドウインタフェースを構築する概念の説明をします。 特殊なグラフィカル・エディタでは、GUI要素の基本クラスで構成されるレイアウトをインタラクティブに設定し、MQLにエクスポートしてMQLプロジェクトで使用することができます。 本論文では、エディタの内部設計とユーザーガイドを紹介します。 ソースコードも添付します。