English Русский 中文 Español 日本語 Português
Zeitreihen in der Bibliothek DoEasy (Teil 42): Abstrakte Objektklasse der Indikatorpuffer

Zeitreihen in der Bibliothek DoEasy (Teil 42): Abstrakte Objektklasse der Indikatorpuffer

MetaTrader 5Handelssysteme | 18 August 2020, 12:30
459 0
Artyom Trishkin
Artyom Trishkin

Inhalt


Konzept

Im vorigen Artikel habe ich einen Beispielindikator für die Arbeit mit den Zeitreihenobjekten der DoEasy-Bibliothek entwickelt. Um die Pufferdaten zuzuweisen und auf sie zuzugreifen, habe ich eine Pufferstruktur erstellt, die alle notwendigen Daten zur korrekten Identifizierung des zu einem Chartsymbol gehörenden Puffers und den Zeitraum zum Zeichnen der Indikatorlinien in Form von Kerzen enthält. Es wäre jedoch umständlich und unpraktisch, für jeden Indikator Strukturen zu erstellen, deren Felder der gewünschten Art des Linienzeichnens entsprechen. Viel bequemer ist es, die Objektklasse des Indikatorpuffers zu verwenden, die es uns erlaubt, auf einfache Weise beliebige Puffertypen nach Stil und Zeichenmethode zu erstellen.

Ich werde in diesem Artikel mit der Entwicklung eines solchen Werkzeugs beginnen.
Die Objektstruktur soll aus der grundlegenden Klasse der Indikatorpuffer (dem so genannten "abstrakten Pufferobjekt") bestehen, die alle allgemeinen Eigenschaften enthält, die allen Indikatorpuffern unabhängig von ihrem Zeichnungstyp eigen sind. Die Pufferobjektklassen, die die klärenden Daten zu einem bestimmten Puffertyp enthalten, sollen von diesem abstrakten Puffer abgeleitet werden. Diese abgeleiteten Klassen werden den Zeichnungstyp genau definieren und individuelle Eigenschaften aufweisen, die für diesen Indikatorpuffertyp einzigartig sind.

Im aktuellen Artikel werden wir die Objektklasse des abstrakten Indikatorpuffers schreiben. Das Objekt soll alle Indikatorpuffereigenschaften der Enumeration ENUM_PLOT_PROPERTY_INTEGER, ENUM_PLOT_PROPERTY_DOUBLE und ENUM_PLOT_PROPERTY_STRING enthalten, sowie einige zusätzliche Eigenschaften:

  • Zur Angabe eines Puffertyps:
    • Datenpuffer,
    • Berechnungspuffer;
  • Pufferstatus (Definition der Zeichnungsart der Indikatorlinien)
    Abgeleitete Objekte sind nach dem Pufferstatus zu sortieren — für jeden Status wird eine eigene, abgeleitete Klasse der abstrakten Pufferklasse angelegt;
  • Puffer-Arbeitssymbol:
    • aktuell,
    • strikt spezifiziert;
  • Pufferzeitrahmen:
    • aktuell,
    • strikt spezifiziert;
  • Die Seriennummer des gezeichneten Puffers ist eine Puffernummer, die im Datenfenster des Terminals angezeigt wird (diese Nummern stimmen nicht mit den Indizes der double-Arrays überein, die dem Puffer zugeordnet sind);
  • Der Indikator für die Puffernutzung — der Indikator soll es ermöglichen, die Anzeige von Pufferzeilen und -werte im Datenfenster durch Aktivieren/Deaktivieren des Indikators zu aktivieren/deaktivieren;
  • Der Index des Basisdatenpuffers — Hilfsdaten zum Index des ersten Arrays aus allen Arrays, die zum Zeichnen der Pufferzeilen verwendet werden;
  • Der Umfang der Pufferdaten — Hilfsdaten über die tatsächliche Menge der Arrays, die zum Zeichnen der Puffergrafiken verwendet wurden. Es ist notwendig, den Farbpufferindex und den Index des nächsten Arrays zu berechnen, dem der Index als Basisdatenpuffer zugeordnet werden kann;
  • Der Farbpufferindex ist ein Hilfsdatenwert für den Array-Index, der als Farbpuffer verwendet wird;
  • Der freie Array-Index für die Zuweisung als nächster Indikatorpuffer — Hilfsdaten über den berechneten Index des Basisdatenpuffers für das nächste Pufferobjekt.

Infolgedessen erhalten wir, nachdem wir alle notwendigen Klassen für die Arbeit mit den Indikatorpuffern erstellt haben, die Möglichkeit, unserem Programm einfach zu "sagen": "Erstelle den Puffer dieses Typs", und die Bibliothek wird den Puffer und alle nachfolgenden Puffer erstellen, ohne die Notwendigkeit, Arrays unabhängig zu deklarieren, ihre Eigenschaften und die Bindung an Indikatorpuffer zuzuweisen. Wir erhalten einfach die Pufferliste, von der aus wir auf alle zuvor erstellten Indikatorpuffer und Pufferdaten zugreifen werden.

Da MQL5 die Möglichkeit bietet, zwei ähnliche Zeichenstile — ein- und mehrfarbig — zu erstellen, sind alle von der Bibliothek erstellten Puffer farbig zu gestalten. Wenn Sie eine monochrome Linie erzeugen wollen, wird eine einzige Farbe für alle vom Puffer angezeigten Daten eingestellt.
Wenn mehrere Farben für die Kolorierung der Balken verwendet werden, wird die angegebene Anzahl von Farben verwendet, um die Linie auf jedem Balken darzustellen.


Abstrakte Pufferklasse CBuffer

Für den Klassenbetrieb benötigen wir Textnachrichten mit Beschreibungen der Puffereigenschaften.

Öffnen Sie \MQL5\Include\DoEasy\Datas.mqh und fügen Sie Indizes neuer Nachrichten hinzu:

   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

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

und Nachrichtentexte, die den neu hinzugefügten Indizes entsprechen:

   {"Ожидание","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"},
   
  };
//+---------------------------------------------------------------------+

Beim Erstellen von Bibliotheksobjekten, die in der Objektsammlung gespeichert werden sollen, wird jedem Objekt die ID der entsprechenden Sammlung zugewiesen. Dasselbe gilt für Pufferobjekte: Legen Sie eine ID für Pufferkollektion des Indikators an und weisen Sie sie dem abstrakten Pufferobjekt zu. Dementsprechend erhält jedes Objekt, das von einem abstrakten Puffer erbt, eine ID, die angibt, dass es zur Pufferkollektion gehört.
Um ein abstraktes Pufferobjekt zu erstellen, müssen wir alle seine Eigenschaften definieren und beschreiben. Mit Hilfe dieser Eigenschaften sind wir immer in der Lage, das benötigte Pufferobjekt für die weitere Arbeit in der Puffersammlung zu finden.

Öffnen Sie \MQL5\Include\DoEasy\Defines.mqh und und fügen Sie die ID der Pufferkollektion des Indikators hinzu:

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

Ganz am Ende der Datei fügen wir die Enumerationen des Pufferobjektstatus und seines Typs hinzu, definieren die ganzzahligen, reelen und Text-Eigenschaften des Objekts sowie mögliche Kriterien der Pufferobjektsortierung in ihre Liste der Kollektionen ein:

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

All diese Eigenschaften sowie ihre Definition, Zuweisung und Verwendung sind Standard für die Bibliothek. Wir haben sie viele Male besprochen, so dass es keinen Sinn macht, hier auf jede einzelne Enumeration und Makrosubstitution einzugehen. Ich hoffe, Sie sind mit ihrem Zweck bereits vertraut, und es sind keine Erklärungen erforderlich. Wenn Sie jedoch Fragen haben, können Sie diese gerne in den nachstehenden Kommentaren stellen.

Wir haben alle notwendigen Daten vorbereitet. Nun ist es an der Zeit, mit der Erstellung der abstrakten Pufferobjektklasse zu beginnen.

Erstellen Sie in \MQL5\Include\DoEasy\Objects\ den Ordner Indicators\, der die Datei Buffer.mqh der CBuffer-Klasse enthält.
Die Klasse des Basisobjekts aller Bibliotheksobjekte CBaseObj dient als Basisklasse für die Klasse des abstrakten Pufferobjekts.
Binden Sie die Klassendatei in die Klassendatei der Puffer ein
:

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

Die Menge der Basismethoden von Bibliotheksobjekten ist für jedes Objekt Standard. Sie ermöglicht es, mit den jedem Objekt innewohnenden Eigenschaften für jedes einzelne Objekt auf die gleiche Weise zu arbeiten. Ich habe die Objektkonstruktionsprinzipien ganz am Anfang der Bibliotheksbeschreibung besprochen.

Auch hier ist alles Standard: drei Objekt-Eigenschaftsfelder (ganzzahlige, reelle und Text-Eigenschaften), Methoden zur Rückgabe von reellen Indizes der reellen und Text-Eigenschaften , sowie Methoden zum Setzen , Empfangen und Abrufen der Beschreibung der angegebenen Eigenschaft aus diesen Feldern. Drei virtuelle Methoden, die die Flags der Verwendung spezifizierter Eigenschaften zurückgeben und zwei Vergleichsmethoden — zum Suchen und Sortieren in der Sammlung nach der spezifizierten Eigenschaft sowie zum Vergleich zweier Objekte auf Gleichheit. Zwei Konstruktoren — die voreingestellte und geschlossene parametrische Ein- und Zwei-Methoden zur Anzeige aller Eigenschaften des Pufferobjekts und seiner Kurzbeschreibung in der Zeitschrift :

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

Standarddaten und Methoden sind hier hervorgehoben.
Der geschützte parametrische Konstruktor sollte im Abschnitt über die geschützte Klasse vorhanden sein, aber im aktuellen Artikel wird der Konstruktor öffentlich gemacht, um die erzeugte Objektoperation zu überprüfen.
Deshalb wurde der 'protected' Zugriff auskommentiert.

Eine 'private' Methode zur Einstellung des graphischen Buffer-Konstruktionstyps, zwei 'public' Arrays für ihre Bindung als Datenarray und Farbarray des Indikatorpuffers sind unbeschrieben geblieben:

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

Abhängig vom Pufferstatus (geerbte Objekte sind an seinen Status "gebunden"), werden wir den Typ der grafischen Konstruktion des Puffers definieren.
Wenn wir uns die Enumerationskonstanten für den Pufferstatus genau ansehen

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

und vergleichen die Reihenfolge der Konstanten mit der Reihenfolge der fast gleichnamigen Konstanten in der Aufzählung ENUM_DRAW_TYPE mittels einer einfachen Schleife um die Anzahl der Konstanten in der Aufzählung,

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

werden wir sehen, dass die Aufträge mit der grafischen Konstruktionsart übereinstimmen.
Der Unterschied besteht darin, dass die Enumeration der Zeichenstile Konstanten für Monochrom- und Farbpuffer hat, und es gibt einen Stil, der keinen Farbpuffer benötigt (die Farbfüllung zwischen den beiden Ebenen).

Alle Puffer sollen farbig sein. Um den Zeichenstil festzulegen, überprüfen wir den Pufferstatus und den Zeichnungstyp, die an die Methode SetDrawType() übergeben werden, und setzen in Abhängigkeit davon entweder keine Zeichnung, oder setzen das Füllen des Raums zwischen den beiden Ebenen mit Farbe, oder verschieben den Status des Enumerationsindex um 8 Einheiten, so dass der konstante Wert dem des Farbpuffers aus der Enumeration der Zeichentypen entspricht.

Jenseits des Klassenkörpers, implementieren wir die Methode:

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

Wenn der Puffertyp BUFFER_TYPE_CALCULATE (0) oder BUFFER_STATUS_NONE (0) ist, wird der Zeichenstil auf "Nicht Zeichnen" gesetzt. Wenn der Pufferstatus BUFFER_STATUS_FILLING (Füllen mit Farbe) ist, wird der entsprechende Zeichenstil gesetzt. Alle übrigen Werte werden einfach um 8 erhöht. Diese Verschiebung gibt die Konstante des farbigen Zeichenstils an.

Unten sehen Sie ein Beispiel für die Erhöhung der Konstante der Enumeration ENUM_BUFFER_STATUS um 8 und den Wert in der Aufzählung ENUM_DRAW_TYPE, auf den sie in diesem Fall fällt:

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

Daher wird sein Zeichenstil basierend auf dem Pufferstatuswert festgelegt.

Fügen Sie alle übrigen Methoden zur Einstellung und Rückgabe der Puffereigenschaften und zur Anzeige der Beschreibung seiner Eigenschaften in der Zeitschrift zum öffentlichen Teil der Klasse hinzu:

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

Betrachten wir die Implementierung der deklarierten Methoden und des geschlossenen parametrischen Konstruktors.

Geschlossener parametrischer Konstruktor:

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

Die Konstruktoreingaben übergeben den Status und Typ des erzeugten Pufferobjekts, den Index der zu zeichnenden Puffer (Market Watch Index) und den Basis-Array-Index (das Basis-Array ist das allererste Array aus der allgemeinen Liste der Arrays, die zum Konstruieren des Puffers verwendet werden).

Weisen Sie dem Objekt den Typ der Zugehörigkeit zur Pufferobjektsammlung zu und füllen Sie Integer-, Real- und String-Objekteigenschaften mit Standardwerten aus.
Binden Sie als Nächstes die Indikatorpuffer mit den Arrays und setzen Sie Integer-, Real- und String-Eigenschaften aus den neu gefüllten Standardwerten der gleichartigen Pufferobjekteigenschaften auf den gezeichneten Puffer.

Diese Aktionen reichen aus, um einen einfarbigen Indikatorpuffer mit dem angegebenen Zeichnungstyp zu erstellen. Beim Erstellen eines solchen Puffers aus dem Indikator sollten keine Arrays deklariert, gesetzt und zugewiesen werden — alle erforderlichen Pufferobjekte sind bereits im Pufferobjekt vorhanden und (falls erforderlich) zugewiesen. Die Eigenschaft BUFFER_PROP_INDEX_PLOT enthält den gezeichneten Pufferindex, der zum Setzen und Empfangen der Pufferdaten von seinem Indikatorprogramm verwendet wird.

Ich werde hier die Standardmethoden erwähnen, ohne auf sie näher einzugehen. Ähnliche Methoden anderer Objekte habe ich bereits in allen früheren Artikeln beschrieben. Außerdem habe ich die Methoden bei der Erstellung des allerersten Bibliotheksobjekts im Detail besprochen:

Vergleichsmethoden zum Suchen und Sortieren, sowie zur Rückgabe der Flags der Gleichheit zweier verglichener Objekte:

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

Die Methode zur Anzeige aller Pufferobjekteigenschaften:

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

Die Methoden, die die Beschreibung der ganzzahligen, reellen und Text-Eigenschaften der Pufferobjekte zurückgeben:

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

Werfen wir einen Blick auf die Implementierung der verbleibenden hinzugefügten Methoden im 'public' Bereich der Klasse.

Die Methode, die die Beschreibung des Pufferstatus zurückgibt:

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

Da der Pufferstatus auch den Zeichenstil definiert, erhält die Methode das Flag, das angibt, wie die Beschreibung zurückgegeben werden soll:
— wenn der Pufferstatus angefordert wird (draw_type steht auffalse), wird der Pufferstatus in folgender Form zurückgegeben

Puffer-Status:  Indikatorpuffer bei grafischer Zeichnung vom Typ "Zeile"

— Wenn der Zeichnungstyp angefordert wird (draw_type steht auf true), wird der Zeichnungstyp in folgender Form zurückgegeben

Grafischer Zeichnung: Zeile

Alle Methoden, die Beschreibungen von Objekteigenschaften zurückgeben, sind einfach genug, überlassen wir sie dem unabhängigen Studium:

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

Die Methoden zum Einstellen verschiedener Pufferobjekteigenschaften:

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

Der an die Methode übergebene Wert wird zuerst in die entsprechende Eigenschaft des Pufferobjekts geschrieben, dann wird die Eigenschaft für den gezeichneten Puffer gesetzt durch seinen Index.

Dies ist derzeit alles, was für die Erstellung des abstrakten Indikatorpufferobjekts getan werden muss.

Prüfen der Erzeugung von Pufferobjekten im Indikator

Um die Operation des abstrakten Pufferobjekts zu überprüfen, verwenden wir den Indikator aus dem vorherigen Artikel und speichern ihn in \MQL5\Indikatoren\TestDoEasy\Part42\ als TestDoEasyPart42.mq5.

Entfernen wir alle unnötigen Dinge aus dem Indikator.
Wir benötigen keine Schaltflächen, keine Tastendruck-Ereignisfunktionen und keine Funktionen zum Füllen von Pufferdaten, also entfernen wir diese aus dem Code, so dass nur die Elemente übrig bleiben, die direkt mit der Bibliotheksoperation zusammenhängen.

Außerdem verschieben wir die Funktionen zum Kopieren von Daten aus OnCalculate() in die Bibliothekspreisstruktur vom Indikatorcode in die Datei der Bibliotheksservicefunktionen. Öffnen wir \MQL5\Include\DoEasy\Services\DELib.mqh und fügen zwei Funktionen hinzu:

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

Infolgedessen haben wir den Indikatorcode für die gegenwärtige Verifizierung und die künftige Verwendung bereinigt. Die beiden verschobenen Funktionen sind notwendig, um mit Indikatoren innerhalb der Bibliothek zu arbeiten, daher ist die Datei der Bibliotheks-Servicefunktionen der beste Ort für sie.

Die "Kopfzeilen" des Indikators ist wie folgt:

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

Hier ordnen wir dem Compiler an, den Indikator in einem separaten Fenster zu erstellen, und setzen vier Puffer dafür (zwei gezeichnete und zwei farbige).
Die übrigen Pufferparameter werden während und nach dem Anlegen von Indikatorpufferobjekten gesetzt.
Fügen wir das dynamische Array aus Zeigern CArrayObj als Indikatorpuffer hinzu. Es soll die erstellten Puffer speichern.

Wenn wir mit Pufferobjekten arbeiten, brauchen wir Arrays vom Typ double nicht zu deklarieren, um sie als Indikatorpuffer zuzuordnen. Alles befindet sich innerhalb der erstellten Pufferobjekte und wird in OnInit() des Indikators erstellt:

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

Hier habe ich zwei Objekte von abstrakten Indikatorpuffern erstellt.
Die Erste hat den Status "Zeichnung mit Pfeilen". Wir setzen 0 als den Index des zu zeichnenden Puffers und den Puffer-Basisarray-Index — dies ist der allererste Puffer, und alle Indizes sollten hier Anfangswerte haben.
Wir werden die Angabe von Array-Indizes bei der Erstellung von Pufferobjekten bei der Erstellung der Kollektion der Indikatorpuffer abschaffen — alle Indizes sollen dort automatisch gesetzt werden, es ist kein Nutzereingriff erforderlich.
Das zweite Objekt hat den Status "Linie". Setzen wir 1 (nach Null) als Index des zu zeichnenden Pufferindex. Setzen wir außerdem den vom ersten Pufferobjekt zurückgegebenen Wert als Basis-Array-Index. Dies ist der Wert, der den Index des nächsten freien Arrays angibt, um es als Basisarray für den nächsten Puffer zu spezifizieren.

Außerdem wird 0 (Null) dem zweiten erstellten Puffer als "leerer" Wert zugewiesen, während die Linienfarbe auf "Blau" gesetzt wird (um zu überprüfen, wie die Werte auf die Eigenschaften des Pufferobjekts gesetzt werden).
Fügen wir beide Puffer zu den zuvor deklarierten Liste list_buffers hinzu und senden alle Eigenschaften der beiden neu erstellten Puffer an die Zeitschrift.

Hier prüfen wir nicht, ob die Pufferobjekte erfolgreich erstellt und der Liste hinzugefügt wurden, da dies ein Testindikator ist, und es steht uns frei, die Kontrolle über die Objekterstellung und das Hinzufügen zur Liste im Interesse einer schnellen Überprüfung der Pufferobjekte zu vernachlässigen.

Lassen Sie uns OnCalculate() aus dem vorigen Artikel "löschen" und nur die notwendigsten Elemente für unseren Test übrig lassen: Wir brauchen nur die Ergebnisse der Erstellung von zwei Pufferobjekten und ihre korrekte Zuordnung als Indikatorpuffer zu überprüfen.

Wie können wir das erreichen?
Die Puffererstellung wird in OnInit() überprüft, wenn wir alle Eigenschaften jedes erstellten Puffers in das Journal drucken. Die erfolgreiche Zuweisung der erstellten Objekte als Indikatorpuffer kann nur in OnCalculate() überprüft werden. Dazu vergleichen wir einfach die Größe der in den Objekten als Indikatorpuffer verwendeten Arrays mit der Anzahl der Balken auf dem Symbol.

Sobald wir ein Array als Indikatorpuffer zuweisen, nimmt das ausgeführte Terminal-Subsystem diese Arrays unter seine Fittiche, weist ihnen Speicher zu und verwaltet die Array-Größe. Daher brauchen wir nur jedes der Objekte aus der Liste list_buffers zu holen und die Größe des als Puffer zugewiesenen Arrays mit dem Wert rates_totalin OnCalculate() zu vergleichen. Sind die Werte gleich hat das Terminal-Subsystem die Arrays aus den von ihm kontrollierten Pufferobjekten übernommen.

Um zu vermeiden, dass bei jedem Tick Einträge angezeigt werden, wird Zuweisung von Pufferobjekt-Arrays als Indikatorpuffer bei der allerersten Indikatorberechnung überprüft wenn der berechnete Grenzwert Wert einen Wert von eins überschreitet:

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

Den gesamten Code des Testindikators finden Sie in den unten angehängten Dateien.

Kompilieren Sie den Indikator und starten Sie ihn auf dem Chart, nachdem Sie die folgenden Parameter eingestellt haben:


Das Journal zeigt die folgenden Einträge an:

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

Nach den Bibliotheksmeldungen über die Erstellung von Zeitreihen wird der Block, der alle Eigenschaften jedes der beiden erstellten Pufferobjekte anzeigt, aus OnInit() gedruckt. Als Nächstes werden zwei Meldungen über die Zeichnungsart jedes der erstellten Puffer von OnCalculate() angezeigt, die Größe der Arrays von Pufferobjekten, die als Indikatorpuffer zugewiesen wurden, wird gedruckt und der rates_total Wert zum Zeitpunkt des Indikatorstarts wird angegeben.
Wie wir sehen können, ist die Größe der Arrays gleich rates_total. Das bedeutet, dass die Arrays der erstellten Pufferobjekte vom Terminal gesteuert werden und als Indikatorpuffer verwendet werden.

Um sich noch einmal zu vergewissern, öffnen Sie einfach die Indikatoreigenschaften (Strg+I) und gehen Sie auf die Registerkarte Farben:


Für beide Indikatorpuffer werden Namen und Farben festgelegt. Der Name und die Farbe wurden nicht angegeben, mit Ausnahme der im Konstruktor der Pufferobjektklasse festgelegten Standardwerte. Im Falle des zweiten Puffers haben wir die Farbe auf Blau zurückgesetzt, nachdem wir sie in OnInit() erstellt haben.

Alles funktioniert wie erwartet. Dies ist jedoch nur der Anfang. Um verschiedene Typen von Indikatorpuffern zu erstellen, müssen wir abgeleitete Klassen für jeden der grafischen Konstruktionstypen erstellen und mit diesen Klassen aus der Kollektion der Indikatorpuffer arbeiten.


Was kommt als Nächstes?

Im nächsten Artikel werden wir abgeleiteten Objekte der abstrakten Pufferklasse erstellen. Diese Objekte sollen von der Bibliothek für die Erstellung und Verwendung von Indikatorpuffern in Indikatorprogrammen auf der Grundlage der DoEasy-Bibliothek verwendet werden.

Alle Dateien der aktuellen Version der Bibliothek sind unten zusammen mit den Dateien der Test-EAs angehängt, die Sie testen und herunterladen können.
Hinterlassen Sie Ihre Fragen, Kommentare und Anregungen in den Kommentaren.
Bitte bedenken Sie, dass ich hier den MQL5-Testindikator für MetaTrader 5 entwickelt habe.
Die angehängten Dateien sind nur für MetaTrader 5 bestimmt. Die aktuelle Bibliotheksversion wurde nicht mit dem MetaTrader 4 getestet.
Nachdem ich alle Klassen von Indikatorpuffern und ihre Kollektionen erstellt habe, werde ich versuchen, einige MQL5-Funktionen in MetaTrader 4 zu implementieren.

Zurück zum Inhalt

Frühere Artikel dieser Serie:

Zeitreihen in der Bibliothek DoEasy (Teil 35): das Balkenobjekt und die Liste der Zeitreihen eines Symbols
Zeitreihen in der Bibliothek DoEasy (Teil 36): Objekt der Zeitreihe für alle verwendeten Symbolperioden
Zeitreihen in der Bibliothek DoEasy (Teil 37): Kollektion von Zeitreihen - Datenbank der Zeitreihen nach Symbolen und Zeitrahmen
Zeitreihen in der Bibliothek DoEasy (Teil 38): Kollektion von Zeitreihen - Aktualisierungen in Echtzeit und Datenzugriff aus dem Programm

Zeitreihen in der Bibliothek DoEasy (Teil 40): Bibliotheksbasierte Indikatoren - Aktualisierung der Daten in Echtzeit
Zeitreihen in der Bibliothek DoEasy (Teil 41): Beispiel eines Multisymbol- und Mehrperiodenindikators

Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/7821

Beigefügte Dateien |
MQL5.zip (3711.1 KB)
Die Handelssignale mehrerer Währungen überwachen (Teil 5): Signalkombinationen Die Handelssignale mehrerer Währungen überwachen (Teil 5): Signalkombinationen
Im fünften Artikel, der sich auf die Schaffung eines Handelssignalmonitors bezieht, werden wir zusammengesetzte Signale betrachten und die notwendige Funktionalität implementieren. In früheren Versionen verwendeten wir einfache Signale, wie RSI, WPR und CCI, und wir führten auch die Möglichkeit ein, nutzerdefinierte Indikatoren zu verwenden.
Zeitreihen in der Bibliothek DoEasy (Teil 41): Beispiel eines Multisymbol- und Mehrperiodenindikators Zeitreihen in der Bibliothek DoEasy (Teil 41): Beispiel eines Multisymbol- und Mehrperiodenindikators
In diesem Artikel entwickeln wir das Beispiel eines Multisymbol- und Mehrperiodenindikators, der die Zeitreihenklassen der DoEasy-Bibliothek verwendet und das Chart eines ausgewählten Währungspaares in einem ausgewählten Zeitrahmen als Kerzen in einem Unterfenster anzeigt. Ich werde die Bibliotheksklassen ein wenig modifizieren und eine separate Datei erstellen, zum Speichern von Enumerationen für die Programmeingaben und für die Auswahl einer Kompilierungssprache.
Zeitreihen in der Bibliothek DoEasy (Teil 43): Klassen der Objekte von Indikatorpuffern Zeitreihen in der Bibliothek DoEasy (Teil 43): Klassen der Objekte von Indikatorpuffern
Der Artikel beschäftigt sich mit der Entwicklung von Indikatorpuffer-Objektklassen, abgeleitet vom abstrakten Pufferobjekt, um die Deklaration zu vereinfachen und mit Indikatorpuffern zu arbeiten, während gleichzeitig nutzerdefinierte Indikatorprogramme auf der Grundlage der Bibliothek DoEasy erstellt werden.
Kontinuierliche Walk-Forward-Optimierung (Teil 7): Einbinden des logischen Teils des Auto-Optimizer mit Grafiken und Steuerung Kontinuierliche Walk-Forward-Optimierung (Teil 7): Einbinden des logischen Teils des Auto-Optimizer mit Grafiken und Steuerung
Dieser Artikel beschreibt die Verbindung des grafischen Teils des Auto-Optimizers mit seinem logischen Teil. Er betrachtet den Prozess des Optimierungsstarts, von einem Tastenklick bis zur Aufgabenumleitung zum Optimierungsmanager.