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

Artyom Trishkin | 18 1月, 2021

目次


概念

ライブラリ内のデータの構築と保存のすべての概念は、同じ型のデータのセットを含むコレクションリストに基づいています。それらは、必要な順序で選択、並び替え、フィルタリングできます。これにより、さらに比較および分析するために必要なデータのセットを取得できます。指標バッファの構造は以前に作成されたシリアルオブジェクトと大きく異なることはなく、コレクションリストに含めることができます。ここでは、データを使用して必要なオブジェクトをすばやく見つけることができます。ただし、コレクションを作成できるようにするには、そのコレクションのデータオブジェクトが必要です。これらのデータの完全なセットはコレクションリストに保存されます。
今日は、1つのバーの指標バッファに関するすべての情報を含むデータオブジェクトを作成します。それぞれ、バッファが属する指標に関する情報を含み、その1つのバーのデータは作成中のオブジェクトによって記述されます。

1つの指標の個別のバッファごと、および時系列の各バーごとに、独自のデータオブジェクトが作成され、その指標の銘柄と時間枠に属するコレクションリストに編成されます。したがって、指標の1つのコピーに対して、その指標の各バッファの時系列の各バーのデータセットがあります。

現時点では、指標からの直接リクエストを使用して指標バッファ時系列の必要なバーの必要なデータを常に取得できるため、このようなデータストレージの概念は過剰に思えます。しかし後に、これらのデータのコレクションが作成されると(次の記事で)、コレクションが作成される指標の必要なデータをすばやく見つけることができます。同様に、ベンチマーク分析を実行できます。このような状況では、コレクションキャッシュにデータを保存するのが適切と思われます。


ライブラリクラスの改善

まず、いつものように新しいライブラリメッセージを追加します。
\MQL5\Include\DoEasy\Data.mqhファイルに、新しいメッセージインデックスを追加します

//--- CIndicatorsCollection
   MSG_LIB_SYS_FAILED_ADD_IND_TO_LIST,                // Error. Failed to add indicator object to the list
   MSG_LIB_SYS_INVALID_IND_POINTER,                   // Error. Invalid pointer to indicator object is passed
   MSG_LIB_SYS_IND_ID_EXIST,                          // Error. Indicator object with ID already exists
   
//--- CDataInd
   MSG_LIB_TEXT_IND_DATA_IND_BUFFER_NUM,              // Indicator buffer number
   MSG_LIB_TEXT_IND_DATA_BUFFER_VALUE,                // Indicator buffer value
   
  };
//+------------------------------------------------------------------+

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

   {"Error. Failed to add indicator object to list"},
   {"Error. Invalid pointer to indicator object passed"},
   {"Error. There is already exist an indicator object with ID"},
   
   {"Indicator buffer number"},
   {"Indicator buffer value"},
   
  };
//+---------------------------------------------------------------------+

指標バッファデータオブジェクトはコレクションリストに保存されるため、このオブジェクトを検索して並べ替えるには、リストに保存されている他のライブラリオブジェクトに固有のすべてのプロパティを受け取る必要があります。ファイル\MQL5\Include\DoEasy\Defines.mqhで、新しいオブジェクトに必要なすべてのプロパティを記述します。まずは、オブジェクトの整数プロパティです。

//+------------------------------------------------------------------+
//|  Data for working with indicator data                            |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Integer properties of indicator data                             |
//+------------------------------------------------------------------+
enum ENUM_IND_DATA_PROP_INTEGER
  {
   IND_DATA_PROP_TIME = 0,                                  // Start time of indicator data bar period
   IND_DATA_PROP_PERIOD,                                    // Indicator data period (timeframe)
   IND_DATA_PROP_INDICATOR_TYPE,                            // Indicator type
   IND_DATA_PROP_IND_BUFFER_NUM,                            // Indicator data buffer number
   IND_DATA_PROP_IND_ID,                                    // Indicator ID
  }; 
#define IND_DATA_PROP_INTEGER_TOTAL (5)                     // Total number of indicator data integer properties
#define IND_DATA_PROP_INTEGER_SKIP  (0)                     // Number of indicator data properties not used in sorting
//+------------------------------------------------------------------+

オブジェクトの実数プロパティです。

//+------------------------------------------------------------------+
//| Indicator data real properties                                   |
//+------------------------------------------------------------------+
enum ENUM_IND_DATA_PROP_DOUBLE
  {
//--- bar data
   IND_DATA_PROP_BUFFER_VALUE = IND_DATA_PROP_INTEGER_TOTAL,// Indicator data value
  }; 
#define IND_DATA_PROP_DOUBLE_TOTAL  (1)                     // Total number of indicator data real properties
#define IND_DATA_PROP_DOUBLE_SKIP   (0)                     // Number of indicator data properties not used in sorting
//+------------------------------------------------------------------+

ここでは、1つのプロパティのみを使用できます。指標データオブジェクトが作成されるバーに対応する指標バッファの値です。

オブジェクト文字列プロパティです。

//+------------------------------------------------------------------+
//| Indicator data string properties                                 |
//+------------------------------------------------------------------+
enum ENUM_IND_DATA_PROP_STRING
  {
   IND_DATA_PROP_SYMBOL = (IND_DATA_PROP_INTEGER_TOTAL+IND_DATA_PROP_DOUBLE_TOTAL), // Indicator data symbol
   IND_DATA_PROP_IND_NAME,                                  // Indicator name
   IND_DATA_PROP_IND_SHORTNAME,                             // Indicator short name
  };
#define IND_DATA_PROP_STRING_TOTAL  (3)                     // Total number of string properties of indicator data
//+------------------------------------------------------------------+

これらのプロパティの値によって、指標が計算される銘柄、および指標名と短い名前でコレクションデータを選択し、並べ替えることができます。

次に、オブジェクトの作成されたすべてのプロパティを、可能な並び替え基準の列挙に追加します。

//+------------------------------------------------------------------+
//| Possible criteria for indicator data sorting                     |
//+------------------------------------------------------------------+
#define FIRST_IND_DATA_DBL_PROP          (IND_DATA_PROP_INTEGER_TOTAL-IND_DATA_PROP_INTEGER_SKIP)
#define FIRST_IND_DATA_STR_PROP          (IND_DATA_PROP_INTEGER_TOTAL-IND_DATA_PROP_INTEGER_SKIP+IND_DATA_PROP_DOUBLE_TOTAL-IND_DATA_PROP_DOUBLE_SKIP)
enum ENUM_SORT_IND_DATA_MODE
  {
//--- Sort by integer properties
   SORT_BY_IND_DATA_TIME = 0,                               // Sort by bar period start time of indicator data
   SORT_BY_IND_DATA_PERIOD,                                 // Sort by indicator data period (timeframe)
   SORT_BY_IND_DATA_INDICATOR_TYPE,                         // Sort by indicator type
   SORT_BY_IND_DATA_IND_BUFFER_NUM,                         // Sort by indicator data buffer number
   SORT_BY_IND_DATA_IND_ID,                                 // Sort by indicator ID
//--- Sort by real properties
   SORT_BY_IND_DATA_BUFFER_VALUE = FIRST_IND_DATA_DBL_PROP, // Sort by indicator data value
//--- Sort by string properties
   SORT_BY_IND_DATA_SYMBOL = FIRST_IND_DATA_STR_PROP,       // Sort by indicator data symbol
   SORT_BY_IND_DATA_IND_NAME,                               // Sort by indicator name
   SORT_BY_IND_DATA_IND_SHORTNAME,                          // Sort by indicator short name
  };
//+------------------------------------------------------------------+

指標バッファデータオブジェクト

オブジェクトプロパティの準備ができました。次に、1つの指標に対して1つのバッファのデータを格納する新しいオブジェクトを作成します。

ライブラリフォルダ\MQL5\Include\DoEasyの\Objects\Indicators\フォルダで、ファイルDataInd.mqhに新しいクラスCDataIndを作成します。

このクラスは、CBaseObjライブラリのすべてのオブジェクトの基本オブジェクトから派生しています。

実際、オブジェクトにはライブラリオブジェクトの標準のフィールドとメソッドが含まれており、第35部で分析されたbarオブジェクトと同じですが、barオブジェクトとは対照的に、プロパティが少なくなっています。(オブジェクト指標バッファデータのすべてのプロパティは上記の列挙で説明されています。)

指標バッファデータオブジェクトのクラス本体を分析してみましょう。

//+------------------------------------------------------------------+
//|                                                      DataInd.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 "..\BaseObj.mqh"
//+------------------------------------------------------------------+
//| Indicator data class                                             |
//+------------------------------------------------------------------+
class CDataInd : public CBaseObj
  {
private:
   int               m_digits;                                    // Digits value of indicator data
   int               m_index;                                     // Bar index
   string            m_period_description;                        // Timeframe string description
   long              m_long_prop[IND_DATA_PROP_INTEGER_TOTAL];    // Integer properties
   double            m_double_prop[IND_DATA_PROP_DOUBLE_TOTAL];   // Real properties
   string            m_string_prop[IND_DATA_PROP_STRING_TOTAL];   // String properties

//--- Return the index of the array the object's (1) double and (2) string properties are located at
   int               IndexProp(ENUM_IND_DATA_PROP_DOUBLE property)   const { return(int)property-IND_DATA_PROP_INTEGER_TOTAL;                            }
   int               IndexProp(ENUM_IND_DATA_PROP_STRING property)   const { return(int)property-IND_DATA_PROP_INTEGER_TOTAL-IND_DATA_PROP_DOUBLE_TOTAL; }

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

//--- Return the flag of the object supporting this property
   virtual bool      SupportProperty(ENUM_IND_DATA_PROP_INTEGER property)     { return true; }
   virtual bool      SupportProperty(ENUM_IND_DATA_PROP_DOUBLE property)      { return true; }
   virtual bool      SupportProperty(ENUM_IND_DATA_PROP_STRING property)      { return true; }
//--- Return itself
   CDataInd         *GetObject(void)                                          { return &this;}
//--- Set (1) symbol, timeframe and time for the object, (2) indicator type, (3) number of buffers, (4) number of data buffer,
//--- (5) ID, (6) data value, (7) name, (8) indicator short name
   void              SetSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES timeframe,const datetime time);
   void              SetIndicatorType(const ENUM_INDICATOR type)              { this.SetProperty(IND_DATA_PROP_INDICATOR_TYPE,type);               }
   void              SetBufferNum(const int num)                              { this.SetProperty(IND_DATA_PROP_IND_BUFFER_NUM,num);                }
   void              SetIndicatorID(const int id)                             { this.SetProperty(IND_DATA_PROP_IND_ID,id);                         }
   void              SetBufferValue(const double value)                       { this.SetProperty(IND_DATA_PROP_BUFFER_VALUE,value);                }
   void              SetIndicatorName(const string name)                      { this.SetProperty(IND_DATA_PROP_IND_NAME,name);                     }
   void              SetIndicatorShortname(const string shortname)            { this.SetProperty(IND_DATA_PROP_IND_SHORTNAME,shortname);           }
   
//--- Compare CDataInd objects with each other by all possible properties (for sorting the lists by a specified object property)
   virtual int       Compare(const CObject *node,const int mode=0) const;
//--- Compare CDataInd objects with each other by all properties (to search equal objects)
   bool              IsEqual(CDataInd* compared_data) const;
//--- Constructors
                     CDataInd(){;}
                     CDataInd(const ENUM_INDICATOR ind_type,
                              const int ind_id,
                              const int buffer_num,
                              const string symbol,
                              const ENUM_TIMEFRAMES timeframe,
                              const datetime time);
                     
//+------------------------------------------------------------------+ 
//| Methods of simplified access to object properties                |
//+------------------------------------------------------------------+
//--- Return (1) bar period start time, (2) timeframe, (3) indicator type, (4) number of buffers, (5) buffer number, (6) indicator ID
   datetime          Time(void)                                         const { return (datetime)this.GetProperty(IND_DATA_PROP_TIME);                   }
   ENUM_TIMEFRAMES   Timeframe(void)                                    const { return (ENUM_TIMEFRAMES)this.GetProperty(IND_DATA_PROP_PERIOD);          }
   ENUM_INDICATOR    IndicatorType(void)                                const { return (ENUM_INDICATOR)this.GetProperty(IND_DATA_PROP_INDICATOR_TYPE);   }
   int               BufferNum(void)                                    const { return (ENUM_INDICATOR)this.GetProperty(IND_DATA_PROP_IND_BUFFER_NUM);   }
   int               IndicatorID(void)                                  const { return (ENUM_INDICATOR)this.GetProperty(IND_DATA_PROP_IND_ID);           }

//--- Return the price of indicator buffer data
   double            PriceValue(void)                                   const { return this.GetProperty(IND_DATA_PROP_BUFFER_VALUE);                     }
   
//--- Return (1) data symbol, (2) name, (3) indicator short name
   string            Symbol(void)                                       const { return this.GetProperty(IND_DATA_PROP_SYMBOL);                           }
   string            IndicatorName(void)                                const { return this.GetProperty(IND_DATA_PROP_IND_NAME);                         }
   string            IndicatorShortName(void)                           const { return this.GetProperty(IND_DATA_PROP_IND_SHORTNAME);                    }
//--- Return bar index on the specified timeframe the object bar time falls into
   int               Index(const ENUM_TIMEFRAMES timeframe)  const
                       { return ::iBarShift(this.Symbol(),(timeframe==PERIOD_CURRENT ? ::Period() : timeframe),this.Time());                             }
//--- Return Digits set for the object
   int               Digits(void)                                       const { return this.m_digits;                                                    }
//+------------------------------------------------------------------+
//| Description of properties of the object - indicator data         |
//+------------------------------------------------------------------+
//--- Return description of object's (1) integer, (2) real and (3) string property
   string            GetPropertyDescription(ENUM_IND_DATA_PROP_INTEGER property);
   string            GetPropertyDescription(ENUM_IND_DATA_PROP_DOUBLE property);
   string            GetPropertyDescription(ENUM_IND_DATA_PROP_STRING property);

//--- Return indicator type description
   string            IndicatorTypeDescription(void)                     const { return ::IndicatorTypeDescription(this.IndicatorType());                 }
//--- Display the description of object properties in the journal (full_prop=true - all properties, false - supported ones only)
   void              Print(const bool full_prop=false);
//--- Display a short description of the object in the journal
   virtual void      PrintShort(void);
//---
  };
//+------------------------------------------------------------------+

クラスの内容を簡単に分析しましょう。

クラスのprivateセクションには以下があります。

対応するオブジェクトプロパティ(整数、実数、文字列)を格納する3つの配列
適切な配列内のオブジェクトプロパティの真のインデックスを計算するメソッド

変数。追加のオブジェクトプロパティの値を格納するクラスメンバー

クラスのpublicセクションの機能には以下があります。

渡されたオブジェクトプロパティ値を整数、実数、文字列プロパティの配列に書き込むメソッド。
配列から要求された整数、実数、または文字列のプロパティの値を返すメソッド
各プロパティのオブジェクトによってプロパティをサポートするフラグを返す仮想メソッド。メソッドは、オブジェクトの子孫オブジェクトに実装されることを意図しており、子孫オブジェクトが指定されたプロパティをサポートしていない場合は、falseを返す必要があります。指標バッファデータのオブジェクトでは、すべてのプロパティがサポートされており、メソッドはtrueを返します。

最初の記事でライブラリオブジェクトの構造全体について説明したので、ここでは、残りのクラスメソッドの実装について簡単に説明します。

オブジェクトプロパティを設定および返すためのすべての追加メソッドは、プログラムを作成する場合にのみ追加の利便性を提供します。 メソッドの設定オブジェクトプロパティの受信のアクションを複製するだけです。そのため、ライブラリユーザーは、オブジェクトプロパティの列挙から定数の名前を覚えておく必要はなく、 これらの追加メソッドの名前に基づいてプロパティを設定および受信します。

Compare()仮想メソッドは、指定したプロパティで2つのオブジェクトを比較するためのものです。これは、標準ライブラリのCObject基本オブジェクトクラスで定義されており、値が等しい場合は0を返し、比較される値のいずれかが高いまたは低い場合は1または-1を返します。これは、標準ライブラリのSearch()メソッドで検索と並べ替えに使用されます。メソッドは、子孫クラスで再定義する必要があります。

//+-------------------------------------------------------------------+
//| Compare CDataInd objects with each other by the specified property|
//+-------------------------------------------------------------------+
int CDataInd::Compare(const CObject *node,const int mode=0) const
  {
   const CDataInd *obj_compared=node;
//--- compare integer properties of two objects
   if(mode<IND_DATA_PROP_INTEGER_TOTAL)
     {
      long value_compared=obj_compared.GetProperty((ENUM_IND_DATA_PROP_INTEGER)mode);
      long value_current=this.GetProperty((ENUM_IND_DATA_PROP_INTEGER)mode);
      return(value_current>value_compared ? 1 : value_current<value_compared ? -1 : 0);
     }
//--- compare real properties of two objects
   else if(mode<IND_DATA_PROP_DOUBLE_TOTAL+IND_DATA_PROP_INTEGER_TOTAL)
     {
      double value_compared=obj_compared.GetProperty((ENUM_IND_DATA_PROP_DOUBLE)mode);
      double value_current=this.GetProperty((ENUM_IND_DATA_PROP_DOUBLE)mode);
      return(value_current>value_compared ? 1 : value_current<value_compared ? -1 : 0);
     }
//--- compare string properties of two objects
   else if(mode<IND_DATA_PROP_DOUBLE_TOTAL+IND_DATA_PROP_INTEGER_TOTAL+IND_DATA_PROP_STRING_TOTAL)
     {
      string value_compared=obj_compared.GetProperty((ENUM_IND_DATA_PROP_STRING)mode);
      string value_current=this.GetProperty((ENUM_IND_DATA_PROP_STRING)mode);
      return(value_current>value_compared ? 1 : value_current<value_compared ? -1 : 0);
     }
   return 0;
  }
//+------------------------------------------------------------------+

指標バッファデータの2つの同一のオブジェクトを決定するメソッドは、2つのデータオブジェクトを比較するのに役立ち、2つの比較されたオブジェクトのすべてのフィールドが等しい場合にのみtrueを返します。

//+------------------------------------------------------------------+
//|Compare CDataInd objects with each other by all properties        |
//+------------------------------------------------------------------+
bool CDataInd::IsEqual(CDataInd *compared_obj) const
  {
   int beg=0, end=BAR_PROP_INTEGER_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_IND_DATA_PROP_INTEGER prop=(ENUM_IND_DATA_PROP_INTEGER)i;
      if(this.GetProperty(prop)!=compared_obj.GetProperty(prop)) return false; 
     }
   beg=end; end+=IND_DATA_PROP_DOUBLE_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_IND_DATA_PROP_DOUBLE prop=(ENUM_IND_DATA_PROP_DOUBLE)i;
      if(this.GetProperty(prop)!=compared_obj.GetProperty(prop)) return false; 
     }
   beg=end; end+=IND_DATA_PROP_STRING_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_IND_DATA_PROP_STRING prop=(ENUM_IND_DATA_PROP_STRING)i;
      if(this.GetProperty(prop)!=compared_obj.GetProperty(prop)) return false; 
     }
   return true;
  }
//+------------------------------------------------------------------+

以下は、時系列に銘柄、時間枠、データオブジェクトインデックスを配置するメソッドです。

//+------------------------------------------------------------------+
//| Set symbol, timeframe and object bar start time                  |
//+------------------------------------------------------------------+
void CDataInd::SetSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES timeframe,const datetime time)
  {
   this.SetProperty(IND_DATA_PROP_TIME,time);
   this.SetProperty(IND_DATA_PROP_SYMBOL,symbol);
   this.SetProperty(IND_DATA_PROP_PERIOD,timeframe);
  }
//+------------------------------------------------------------------+

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

//+------------------------------------------------------------------+
//| Display object properties in the journal                         |
//+------------------------------------------------------------------+
void CDataInd::Print(const bool full_prop=false)
  {
   ::Print("============= ",CMessage::Text(MSG_LIB_PARAMS_LIST_BEG)," (",this.IndicatorShortName(),") =============");
   int beg=0, end=IND_DATA_PROP_INTEGER_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_IND_DATA_PROP_INTEGER prop=(ENUM_IND_DATA_PROP_INTEGER)i;
      if(!full_prop && !this.SupportProperty(prop)) continue;
      ::Print(this.GetPropertyDescription(prop));
     }
   ::Print("------");
   beg=end; end+=IND_DATA_PROP_DOUBLE_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_IND_DATA_PROP_DOUBLE prop=(ENUM_IND_DATA_PROP_DOUBLE)i;
      if(!full_prop && !this.SupportProperty(prop)) continue;
      ::Print(this.GetPropertyDescription(prop));
     }
   ::Print("------");
   beg=end; end+=IND_DATA_PROP_STRING_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_IND_DATA_PROP_STRING prop=(ENUM_IND_DATA_PROP_STRING)i;
      if(!full_prop && !this.SupportProperty(prop)) continue;
      ::Print(this.GetPropertyDescription(prop));
     }
   ::Print("============= ",CMessage::Text(MSG_LIB_PARAMS_LIST_END)," (",this.IndicatorShortName(),") =============\n");
  }
//+------------------------------------------------------------------+

次の各プロパティの説明は、3つのループのオブジェクトプロパティ配列によって表示されます。プロパティがサポートされていない場合、full_propメソッドの入力がfalse(デフォルト)であれば、操作ログには表示されません。

以下は、操作ログに短いオブジェクトの説明を表示する仮想メソッドです。

//+------------------------------------------------------------------+
//| Display a short description of the object in the journal         |
//+------------------------------------------------------------------+
void CDataInd::PrintShort(void)
  {
   ::Print
     (
      this.IndicatorShortName(),
      " [",CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_BUFFER)," ",this.BufferNum(),
      ", ",CMessage::Text(MSG_SYM_STATUS_INDEX)," ",this.Index(this.Timeframe()),"]"
     );
  }
//+------------------------------------------------------------------+

このメソッドは、標準指標バッファデータの説明を次の形式で表示します。

AMA(EURUSD,H1) [Buffer 0, Index 0]

カスタム指標の場合:

Examples\Custom Moving Average.ex5(EURUSD,H1) [Buffer 0, Index 1]

バッファデータの説明に含まれる指標の短い名前は、SetIndicatorShortname()メソッドを使用して変更できます。子孫オブジェクトでメソッドを変更して、子孫オブジェクトに実装されたデータに対応するデータオブジェクトの他の説明を表示することができます。

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

//+------------------------------------------------------------------+
//| Return description of object's integer property                  |
//+------------------------------------------------------------------+
string CDataInd::GetPropertyDescription(ENUM_IND_DATA_PROP_INTEGER property)
  {
   return
     (
      property==IND_DATA_PROP_TIME           ?  CMessage::Text(MSG_LIB_TEXT_BAR_TIME)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::TimeToString(this.GetProperty(property),TIME_DATE|TIME_MINUTES|TIME_SECONDS)
         )  :
      property==IND_DATA_PROP_PERIOD         ?  CMessage::Text(MSG_LIB_TEXT_IND_TEXT_TIMEFRAME)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+this.m_period_description
         )  :
      property==IND_DATA_PROP_INDICATOR_TYPE ?  CMessage::Text(MSG_LIB_TEXT_IND_TEXT_TYPE)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+this.IndicatorTypeDescription()
         )  :
      property==IND_DATA_PROP_IND_BUFFER_NUM ?  CMessage::Text(MSG_LIB_TEXT_IND_DATA_IND_BUFFER_NUM)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==IND_DATA_PROP_IND_ID         ?  CMessage::Text(MSG_LIB_TEXT_IND_TEXT_ID)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      ""
     );
  }
//+------------------------------------------------------------------+
//| Return description of object's real property                     |
//+------------------------------------------------------------------+
string CDataInd::GetPropertyDescription(ENUM_IND_DATA_PROP_DOUBLE property)
  {
   int dg=(this.m_digits>0 ? this.m_digits : 1);
   return
     (
      property==IND_DATA_PROP_BUFFER_VALUE   ?  CMessage::Text(MSG_LIB_TEXT_IND_DATA_BUFFER_VALUE)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::DoubleToString(this.GetProperty(property),dg)
         )  :
      ""
     );
  }
//+------------------------------------------------------------------+
//| Return description of object's string property                   |
//+------------------------------------------------------------------+
string CDataInd::GetPropertyDescription(ENUM_IND_DATA_PROP_STRING property)
  {
   return
     (
      property==IND_DATA_PROP_SYMBOL         ? CMessage::Text(MSG_LIB_TEXT_IND_TEXT_SYMBOL)+": \""+this.GetProperty(property)+"\""     : 
      property==IND_DATA_PROP_IND_NAME       ? CMessage::Text(MSG_LIB_TEXT_IND_TEXT_NAME)+": \""+this.GetProperty(property)+"\""       : 
      property==IND_DATA_PROP_IND_SHORTNAME  ? CMessage::Text(MSG_LIB_TEXT_IND_TEXT_SHORTNAME)+": \""+this.GetProperty(property)+"\""  : 
      ""
     );
  }
//+------------------------------------------------------------------+

メソッドは対応するプロパティを受け取り、その値に応じて、上記で追加されたDatas.mqhファイルに設定されているテキストの説明が返されます。

クラスには2つのコンストラクタがあります。

最初のコンストラクタはデフォルトであり、作成後に必要なすべてのデータを入力する必要がある空のデータオブジェクトを作成します。

2番目のコンストラクタはパラメトリックで、指定された基本プロパティを持つオブジェクトの作成に必要なデータを受け取ります。

//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CDataInd::CDataInd(const ENUM_INDICATOR ind_type,
                   const int ind_id,
                   const int buffer_num,
                   const string symbol,
                   const ENUM_TIMEFRAMES timeframe,
                   const datetime time)
  {
   this.m_type=COLLECTION_INDICATORS_ID;
   this.m_digits=(int)::SymbolInfoInteger(symbol,SYMBOL_DIGITS)+1;
   this.m_period_description=TimeframeDescription(timeframe);
   this.SetSymbolPeriod(symbol,timeframe,time);
   this.SetIndicatorType(ind_type);
   this.SetBufferNum(buffer_num);
   this.SetIndicatorID(ind_id);
  }
//+------------------------------------------------------------------+

一度に、オブジェクトに、指標タイプ - オブジェクトによって記述されるバッファデータ、指標ID - このプロパティにより、以前に作成された指標オブジェクトのバッファデータを取得できます。 作成された他の指標オブジェクト間でクイック検索するためのIDが設定されています。データがオブジェクトによって記述される指標バッファ番号、指標オブジェクトが作成される銘柄と時間枠、作成されたオブジェクトによって記述されるバーの開始時間を指定します。

上記の指定されたパラメータの追加とは別に、コンストラクタは、指標バッファ値(銘柄の桁数+ 1桁)を表示するためのデフォルトの小数点以下の桁数を設定し、時間枠の説明を変数m_period_descriptionに追加します。説明はオブジェクトの作成時に1回設定できます。標準ライブラリのCObject親クラスで宣言されている変数m_typeに、指標コレクションのIDを一時的に書き込みます。さらに、指標バッファのデータコレクションを作成するときに、この新しいコレクションのIDをこの変数に追加します。

これで、コレクション内のデータオブジェクトを並べ替えることができるようになります(次の記事からコレクションの作成を開始します)。ファイル\MQL5\Include\DoEasy\Services\Select.mqhに、選択してそのプロパティで並べ替える新しいオブジェクトの作業メソッドを追加します。

作成したばかりの指標バッファデータオブジェクトのクラスをファイルに含めます

//+------------------------------------------------------------------+
//|                                                       Select.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"
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include <Arrays\ArrayObj.mqh>
#include "..\Objects\Orders\Order.mqh"
#include "..\Objects\Events\Event.mqh"
#include "..\Objects\Accounts\Account.mqh"
#include "..\Objects\Symbols\Symbol.mqh"
#include "..\Objects\PendRequest\PendRequest.mqh"
#include "..\Objects\Series\SeriesDE.mqh"
#include "..\Objects\Indicators\Buffer.mqh"
#include "..\Objects\Indicators\IndicatorDE.mqh"
#include "..\Objects\Indicators\DataInd.mqh"
//+------------------------------------------------------------------+

クラス本体の最後に、作成されたばかりの指標データオブジェクトのクラスを使用して作業メソッドを宣言します。

//+------------------------------------------------------------------+
//| Methods of work with indicator data                              |
//+------------------------------------------------------------------+
   //--- Return the list of indicator data with one out of (1) integer, (2) real and (3) string properties meeting a specified criterion
   static CArrayObj *ByIndicatorDataProperty(CArrayObj *list_source,ENUM_IND_DATA_PROP_INTEGER property,long value,ENUM_COMPARER_TYPE mode);
   static CArrayObj *ByIndicatorDataProperty(CArrayObj *list_source,ENUM_IND_DATA_PROP_DOUBLE property,double value,ENUM_COMPARER_TYPE mode);
   static CArrayObj *ByIndicatorDataProperty(CArrayObj *list_source,ENUM_IND_DATA_PROP_STRING property,string value,ENUM_COMPARER_TYPE mode);
   //--- Return the indicator data index in the list with the maximum value of (1) integer, (2) real and (3) string property of data
   static int        FindIndDataMax(CArrayObj *list_source,ENUM_IND_DATA_PROP_INTEGER property);
   static int        FindIndDataMax(CArrayObj *list_source,ENUM_IND_DATA_PROP_DOUBLE property);
   static int        FindIndDataMax(CArrayObj *list_source,ENUM_IND_DATA_PROP_STRING property);
   //--- Return the indicator data index in the list with the minimum value of (1) integer, (2) real and (3) string property of data
   static int        FindIndDataMin(CArrayObj *list_source,ENUM_IND_DATA_PROP_INTEGER property);
   static int        FindIndDataMin(CArrayObj *list_source,ENUM_IND_DATA_PROP_DOUBLE property);
   static int        FindIndDataMin(CArrayObj *list_source,ENUM_IND_DATA_PROP_STRING property);
//---
  };
//+------------------------------------------------------------------+

そして、宣言されたすべてのメソッドをファイルの終わりに実装します。

//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Methods of work with indicator data lists                        |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Return the list of indicators data with one of integer           |
//| properties meeting the specified criterion                       |
//+------------------------------------------------------------------+
CArrayObj *CSelect::ByIndicatorDataProperty(CArrayObj *list_source,ENUM_IND_DATA_PROP_INTEGER property,long value,ENUM_COMPARER_TYPE mode)
  {
   if(list_source==NULL) return NULL;
   CArrayObj *list=new CArrayObj();
   if(list==NULL) return NULL;
   list.FreeMode(false);
   ListStorage.Add(list);
   int total=list_source.Total();
   for(int i=0; i<total; i++)
     {
      CDataInd *obj=list_source.At(i);
      if(!obj.SupportProperty(property)) continue;
      long obj_prop=obj.GetProperty(property);
      if(CompareValues(obj_prop,value,mode)) list.Add(obj);
     }
   return list;
  }
//+------------------------------------------------------------------+
//| Return the list of indicators data with one of real              |
//| properties meeting the specified criterion                       |
//+------------------------------------------------------------------+
CArrayObj *CSelect::ByIndicatorDataProperty(CArrayObj *list_source,ENUM_IND_DATA_PROP_DOUBLE property,double value,ENUM_COMPARER_TYPE mode)
  {
   if(list_source==NULL) return NULL;
   CArrayObj *list=new CArrayObj();
   if(list==NULL) return NULL;
   list.FreeMode(false);
   ListStorage.Add(list);
   for(int i=0; i<list_source.Total(); i++)
     {
      CDataInd *obj=list_source.At(i);
      if(!obj.SupportProperty(property)) continue;
      double obj_prop=obj.GetProperty(property);
      if(CompareValues(obj_prop,value,mode)) list.Add(obj);
     }
   return list;
  }
//+------------------------------------------------------------------+
//| Return the list of indicators data with one of string            |
//| properties meeting the specified criterion                       |
//+------------------------------------------------------------------+
CArrayObj *CSelect::ByIndicatorDataProperty(CArrayObj *list_source,ENUM_IND_DATA_PROP_STRING property,string value,ENUM_COMPARER_TYPE mode)
  {
   if(list_source==NULL) return NULL;
   CArrayObj *list=new CArrayObj();
   if(list==NULL) return NULL;
   list.FreeMode(false);
   ListStorage.Add(list);
   for(int i=0; i<list_source.Total(); i++)
     {
      CDataInd *obj=list_source.At(i);
      if(!obj.SupportProperty(property)) continue;
      string obj_prop=obj.GetProperty(property);
      if(CompareValues(obj_prop,value,mode)) list.Add(obj);
     }
   return list;
  }
//+------------------------------------------------------------------+
//| Return the indicator data index in the list                      |
//| with the maximum integer property value                          |
//+------------------------------------------------------------------+
int CSelect::FindIndDataMax(CArrayObj *list_source,ENUM_IND_DATA_PROP_INTEGER property)
  {
   if(list_source==NULL) return WRONG_VALUE;
   int index=0;
   CDataInd *max_obj=NULL;
   int total=list_source.Total();
   if(total==0) return WRONG_VALUE;
   for(int i=1; i<total; i++)
     {
      CDataInd *obj=list_source.At(i);
      long obj1_prop=obj.GetProperty(property);
      max_obj=list_source.At(index);
      long obj2_prop=max_obj.GetProperty(property);
      if(CompareValues(obj1_prop,obj2_prop,MORE)) index=i;
     }
   return index;
  }
//+------------------------------------------------------------------+
//| Return the indicator data index in the list                      |
//| with the maximum real property value                             |
//+------------------------------------------------------------------+
int CSelect::FindIndDataMax(CArrayObj *list_source,ENUM_IND_DATA_PROP_DOUBLE property)
  {
   if(list_source==NULL) return WRONG_VALUE;
   int index=0;
   CDataInd *max_obj=NULL;
   int total=list_source.Total();
   if(total==0) return WRONG_VALUE;
   for(int i=1; i<total; i++)
     {
      CDataInd *obj=list_source.At(i);
      double obj1_prop=obj.GetProperty(property);
      max_obj=list_source.At(index);
      double obj2_prop=max_obj.GetProperty(property);
      if(CompareValues(obj1_prop,obj2_prop,MORE)) index=i;
     }
   return index;
  }
//+------------------------------------------------------------------+
//| Return the indicator data index in the list                      |
//| with the maximum string property value                           |
//+------------------------------------------------------------------+
int CSelect::FindIndDataMax(CArrayObj *list_source,ENUM_IND_DATA_PROP_STRING property)
  {
   if(list_source==NULL) return WRONG_VALUE;
   int index=0;
   CDataInd *max_obj=NULL;
   int total=list_source.Total();
   if(total==0) return WRONG_VALUE;
   for(int i=1; i<total; i++)
     {
      CDataInd *obj=list_source.At(i);
      string obj1_prop=obj.GetProperty(property);
      max_obj=list_source.At(index);
      string obj2_prop=max_obj.GetProperty(property);
      if(CompareValues(obj1_prop,obj2_prop,MORE)) index=i;
     }
   return index;
  }
//+------------------------------------------------------------------+
//| Return the indicator data index in the list                      |
//| with the minimum integer property value                          |
//+------------------------------------------------------------------+
int CSelect::FindIndDataMin(CArrayObj* list_source,ENUM_IND_DATA_PROP_INTEGER property)
  {
   int index=0;
   CDataInd *min_obj=NULL;
   int total=list_source.Total();
   if(total==0) return WRONG_VALUE;
   for(int i=1; i<total; i++)
     {
      CDataInd *obj=list_source.At(i);
      long obj1_prop=obj.GetProperty(property);
      min_obj=list_source.At(index);
      long obj2_prop=min_obj.GetProperty(property);
      if(CompareValues(obj1_prop,obj2_prop,LESS)) index=i;
     }
   return index;
  }
//+------------------------------------------------------------------+
//| Return the indicator data index in the list                      |
//| with the minimum real property value                             |
//+------------------------------------------------------------------+
int CSelect::FindIndDataMin(CArrayObj* list_source,ENUM_IND_DATA_PROP_DOUBLE property)
  {
   int index=0;
   CDataInd *min_obj=NULL;
   int total=list_source.Total();
   if(total== 0) return WRONG_VALUE;
   for(int i=1; i<total; i++)
     {
      CDataInd *obj=list_source.At(i);
      double obj1_prop=obj.GetProperty(property);
      min_obj=list_source.At(index);
      double obj2_prop=min_obj.GetProperty(property);
      if(CompareValues(obj1_prop,obj2_prop,LESS)) index=i;
     }
   return index;
  }
//+------------------------------------------------------------------+
//| Return the indicator data index in the list                      |
//| with the minimum string property value                           |
//+------------------------------------------------------------------+
int CSelect::FindIndDataMin(CArrayObj* list_source,ENUM_IND_DATA_PROP_STRING property)
  {
   int index=0;
   CDataInd *min_obj=NULL;
   int total=list_source.Total();
   if(total==0) return WRONG_VALUE;
   for(int i=1; i<total; i++)
     {
      CDataInd *obj=list_source.At(i);
      string obj1_prop=obj.GetProperty(property);
      min_obj=list_source.At(index);
      string obj2_prop=min_obj.GetProperty(property);
      if(CompareValues(obj1_prop,obj2_prop,LESS)) index=i;
     }
   return index;
  }
//+------------------------------------------------------------------+

これらのメソッドの機能は、第3部で詳細に分析されました。

新しい指標バッファデータオブジェクトが作成され、テストできます。


テスト

テストを実行するには、前の記事のEAを使用して、新しいフォルダ\MQL5\Experts\TestDoEasy\Part57\に新しい名前TestDoEasyPart57.mq5で保存します。

以前のEAでは、4つの指標オブジェクト(2つの標準オブジェクトと2つのカスタムオブジェクト)を作成しました。同一の指標は、他のパラメータによってのみ互いに異なりました。ここでは、同じ4つの指標を作成しますが、それらのデータを表示するには、時系列の現在(ゼロ)と前(最初)のバーに対して2つのバッファデータオブジェクトを作成します。すべてのオブジェクトのデータは、銘柄チャートのコメントに表示されます。

指標バッファデータコレクションが作成されるまで、作成されたクラスへのアクセスをEAから直接整理しましょう。
これを行うには、このクラスをEAファイルに含めます

//+------------------------------------------------------------------+
//|                                             TestDoEasyPart57.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\DataInd.mqh>
//--- enums

同じ場所で、プログラムのグローバル変数の領域で、指標データオブジェクトへのポインタ変数を追加します

//--- Arrays of custom indicator parameters
MqlParam       param_ma1[];
MqlParam       param_ma2[];
//--- Pointers to indicator data objects
CDataInd      *data_ma1_0=NULL;
CDataInd      *data_ma1_1=NULL;
CDataInd      *data_ma2_0=NULL;
CDataInd      *data_ma2_1=NULL;
CDataInd      *data_ama1_0=NULL;
CDataInd      *data_ama1_1=NULL;
CDataInd      *data_ama2_0=NULL;
CDataInd      *data_ama2_1=NULL;
//+------------------------------------------------------------------+

新しいデータオブジェクトを作成するときは、それらの変数に新しく作成したオブジェクトへのポインタを保存して、後でそれらにアクセスできるようにします。

すべてのオブジェクトは演算子newを使用して作成されるため、すべてを個別に削除する必要があります。EAのOnDeinit()ハンドラでそれを行います(指標バッファデータのコレクションの作成後、EAでのこれらのアクションは必要ありません)。

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- Remove EA graphical objects by an object name prefix
   ObjectsDeleteAll(0,prefix);
   Comment("");
//--- Remove created data objects of MA indicators
   if(CheckPointer(data_ma1_0)==POINTER_DYNAMIC)
      delete data_ma1_0;
   if(CheckPointer(data_ma1_1)==POINTER_DYNAMIC)
      delete data_ma1_1;
   if(CheckPointer(data_ma2_0)==POINTER_DYNAMIC)
      delete data_ma2_0;
   if(CheckPointer(data_ma2_1)==POINTER_DYNAMIC)
      delete data_ma2_1;
//--- Remove created data objects of AMA indicators
   if(CheckPointer(data_ama1_0)==POINTER_DYNAMIC)
      delete data_ama1_0;
   if(CheckPointer(data_ama1_1)==POINTER_DYNAMIC)
      delete data_ama1_1;
   if(CheckPointer(data_ama2_0)==POINTER_DYNAMIC)
      delete data_ama2_0;
   if(CheckPointer(data_ama2_1)==POINTER_DYNAMIC)
      delete data_ama2_1;
//--- Deinitialize library
   engine.OnDeinit();
  }
//+------------------------------------------------------------------+

OnTick()ハンドラで新しいオブジェクトを作成し(既に作成されている場合を除く)、必要なすべてのデータと値を入力し、操作ログ内のオブジェクトの説明を表示します。 一方、オブジェクトによって記述された指標のバッファ値をチャートに表示します

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- Handle the NewTick event in the library
   engine.OnTick(rates_data);

//--- If work in tester
   if(MQLInfoInteger(MQL_TESTER))
     {
      engine.OnTimer(rates_data);   // Work in timer
      PressButtonsControl();        // Button press control
      engine.EventsHandling();      // Work with events
     }
//--- Get custom indicator objects
   CIndicatorDE *ma1=engine.GetIndicatorsCollection().GetIndByID(MA1);
   CIndicatorDE *ma2=engine.GetIndicatorsCollection().GetIndByID(MA2);
   CIndicatorDE *ama1=engine.GetIndicatorsCollection().GetIndByID(AMA1);
   CIndicatorDE *ama2=engine.GetIndicatorsCollection().GetIndByID(AMA2);
   
//--- Write bar start time 0 and 1 to specify it in properties of further created objects
   datetime time0=iTime(ma1.Symbol(),ma1.Timeframe(),0);
   datetime time1=iTime(ma1.Symbol(),ma1.Timeframe(),1);
   if(time0==0 || time1==0)
      return;
      
//--- Create data objects of МА1 and МА2 for bars 0 and 1 (unless the objects are created)
   if(data_ma1_0==NULL) data_ma1_0=new CDataInd(ma1.TypeIndicator(),ma1.ID(),0,ma1.Symbol(),ma1.Timeframe(),time0);
   if(data_ma1_1==NULL) data_ma1_1=new CDataInd(ma1.TypeIndicator(),ma1.ID(),0,ma1.Symbol(),ma1.Timeframe(),time1);
   if(data_ma2_0==NULL) data_ma2_0=new CDataInd(ma2.TypeIndicator(),ma2.ID(),0,ma2.Symbol(),ma2.Timeframe(),time0);
   if(data_ma2_1==NULL) data_ma2_1=new CDataInd(ma2.TypeIndicator(),ma2.ID(),0,ma2.Symbol(),ma2.Timeframe(),time1);
   if(data_ma1_0==NULL || data_ma1_1==NULL || data_ma2_0==NULL || data_ma2_1==NULL) return;
   
//--- Set parameters of data object of indicator МА1, bar 0
//--- and add indicator buffer data to the object
   data_ma1_0.SetIndicatorType(ma1.TypeIndicator());
   data_ma1_0.SetIndicatorName(ma1.Name());
   data_ma1_0.SetIndicatorShortname(ma1.ShortName());
   data_ma1_0.SetBufferValue(ma1.GetDataBuffer(0,time0));
//--- Set parameters of data object of indicator МА1, bar 1
//--- and add indicator buffer data to the object
   data_ma1_1.SetIndicatorType(ma1.TypeIndicator());
   data_ma1_1.SetIndicatorName(ma1.Name());
   data_ma1_1.SetIndicatorShortname(ma1.ShortName());
   data_ma1_1.SetBufferValue(ma1.GetDataBuffer(0,time1));
//--- Set parameters of data object of indicator МА2, bar 0
//--- and add indicator buffer data to the object
   data_ma2_0.SetIndicatorType(ma2.TypeIndicator());
   data_ma2_0.SetIndicatorName(ma2.Name());
   data_ma2_0.SetIndicatorShortname(ma2.ShortName());
   data_ma2_0.SetBufferValue(ma2.GetDataBuffer(0,time0));
//--- Set parameters of data object of indicator МА2, bar 1
//--- and add indicator buffer data to the object
   data_ma2_1.SetIndicatorType(ma2.TypeIndicator());
   data_ma2_1.SetIndicatorName(ma2.Name());
   data_ma2_1.SetIndicatorShortname(ma2.ShortName());
   data_ma2_1.SetBufferValue(ma2.GetDataBuffer(0,time1));
   
//--- Create data objects of АМА1 and АМА2 for bars 0 and 1 (unless the objects are already created)
   if(data_ama1_0==NULL) data_ama1_0=new CDataInd(ama1.TypeIndicator(),ama1.ID(),0,ama1.Symbol(),ama1.Timeframe(),time0);
   if(data_ama1_1==NULL) data_ama1_1=new CDataInd(ama1.TypeIndicator(),ama1.ID(),0,ama1.Symbol(),ama1.Timeframe(),time1);
   if(data_ama2_0==NULL) data_ama2_0=new CDataInd(ama2.TypeIndicator(),ama2.ID(),0,ama2.Symbol(),ama2.Timeframe(),time0);
   if(data_ama2_1==NULL) data_ama2_1=new CDataInd(ama2.TypeIndicator(),ama2.ID(),0,ama2.Symbol(),ama2.Timeframe(),time1);
   if(data_ama1_0==NULL || data_ama1_1==NULL || data_ama2_0==NULL || data_ama2_1==NULL) return;
//--- Set parameters of data object of indicator АМА1, bar 0
//--- and add indicator buffer data to the object
   data_ama1_0.SetIndicatorType(ama1.TypeIndicator());
   data_ama1_0.SetIndicatorName(ama1.Name());
   data_ama1_0.SetIndicatorShortname(ama1.ShortName());
   data_ama1_0.SetBufferValue(ama1.GetDataBuffer(0,time0));
//--- Set parameters of data object of indicator АМА1, bar 1
//--- and add indicator buffer data to the object
   data_ama1_1.SetIndicatorType(ama1.TypeIndicator());
   data_ama1_1.SetIndicatorName(ama1.Name());
   data_ama1_1.SetIndicatorShortname(ama1.ShortName());
   data_ama1_1.SetBufferValue(ama1.GetDataBuffer(0,time1));
//--- Set parameters of data object of indicator АМА2, bar 0
//--- and add indicator buffer data to the object
   data_ama2_0.SetIndicatorType(ama2.TypeIndicator());
   data_ama2_0.SetIndicatorName(ama2.Name());
   data_ama2_0.SetIndicatorShortname(ama2.ShortName());
   data_ama2_0.SetBufferValue(ama2.GetDataBuffer(0,time0));
//--- Set parameters of data object of indicator АМА2, bar 1
//--- and add indicator buffer data to the object
   data_ama2_1.SetIndicatorType(ama2.TypeIndicator());
   data_ama2_1.SetIndicatorName(ama2.Name());
   data_ama2_1.SetIndicatorShortname(ama2.ShortName());
   data_ama2_1.SetBufferValue(ama2.GetDataBuffer(0,time1));

//--- During the first launch, print full and short data of created indicator data objects
   static bool first_start=true;
   if(first_start)
     {
      //--- Full data of buffers МА1 and МА2
      data_ma1_0.Print();
      data_ma1_1.Print();
      data_ma2_0.Print();
      data_ma2_1.Print();
      //--- Full data of buffers АМА1 and АМА2
      data_ama1_0.Print();
      data_ama1_1.Print();
      data_ama2_0.Print();
      data_ama2_1.Print();
      //--- Short data of buffers МА1 and МА2
      data_ma1_0.PrintShort();
      data_ma1_1.PrintShort();
      data_ma2_0.PrintShort();
      data_ma2_1.PrintShort();
      //--- Short data of buffers АМА1 and АМА2
      data_ama1_0.PrintShort();
      data_ama1_1.PrintShort();
      data_ama2_0.PrintShort();
      data_ama2_1.PrintShort();
      //---
      first_start=false;
     }
//--- Display the values of indicator buffers to comment on the chart from data objects
   Comment
     (
      "ma1(1)=",DoubleToString(data_ma1_1.PriceValue(),6),", ma1(0)=",DoubleToString(data_ma1_0.PriceValue(),data_ma1_0.Digits()),", ",
      "ma2(1)=",DoubleToString(data_ma2_1.PriceValue(),6),", ma2(0)=",DoubleToString(data_ma2_0.PriceValue(),data_ma2_0.Digits()),"\n",
      "ama1(1)=",DoubleToString(data_ama1_1.PriceValue(),6),", ama1(0)=",DoubleToString(data_ama1_0.PriceValue(),data_ama1_0.Digits()),", ",
      "ama2(1)=",DoubleToString(data_ama2_1.PriceValue(),6),", ama2(0)=",DoubleToString(data_ama2_0.PriceValue(),data_ama2_0.Digits())
     );
   
//--- If the trailing flag is set
   if(trailing_on)
     {
      TrailingPositions();          // Trailing positions
      TrailingOrders();             // Trailing of pending orders
     }
  }
//+------------------------------------------------------------------+

さらに、オブジェクトの作成とそのプロパティへの値の入力に関するすべてのアクションは、指標バッファデータのコレクションクラスで実行されます。一方、今日作成されたオブジェクトの機能を簡単に確認する必要があります。

EAをコンパイルし、現在の銘柄と期間のみを使用するように設定が事前に設定されているチャートで起動します。操作ログには、すべての作成された指標オブジェクトのデータデータオブジェクトが表示されます。

Account 8550475: Artyom Trishkin (MetaQuotes Software Corp.) 10425.23 USD, 1:100, Hedge, Demo account MetaTrader 5
--- Initializing the "DoEasy" library ---
Work only with the current symbol: "EURUSD"
Work only with the current Period: H1
Symbol time series EURUSD: 
- Timeseries "EURUSD" H1: Required: 1000, Actual: 1000, Created: 1000, On server: 6351
Library initialization time: 00:00:00.000
============= The beginning of the parameter list: "Custom indicator" =============
Indicator status: Custom indicator
Indicator type: CUSTOM
Indicator timeframe: H1
Indicator handle: 10
Indicator group: Trend indicator
Indicator ID: 1
------
Empty value for plotting, for which there is no drawing: EMPTY_VALUE
------
Indicator symbol: EURUSD
Indicator name: "Examples\Custom Moving Average.ex5"
Indicator shortname: "Examples\Custom Moving Average.ex5(EURUSD,H1)"
 --- Indicator parameters --- 
 - [1] Type int: 13
 - [2] Type int: 0
 - [3] Type int: 0
================== End of the parameter list: "Custom indicator" ==================

============= The beginning of the parameter list: "Custom indicator" =============
Indicator status: Custom indicator
Indicator type: CUSTOM
Indicator timeframe: H1
Indicator handle: 11
Indicator group: Trend indicator
Indicator ID: 2
------
Empty value for plotting, for which there is no drawing: EMPTY_VALUE
------
Indicator symbol: EURUSD
Indicator name: "Examples\Custom Moving Average.ex5"
Indicator shortname: "Examples\Custom Moving Average.ex5(EURUSD,H1)"
 --- Indicator parameters --- 
 - [1] Type int: 13
 - [2] Type int: 0
 - [3] Type int: 0
 - [4] Type int: 2
================== End of the parameter list: "Custom indicator" ==================
 
============= The beginning of the parameter list: "Standard indicator" =============
Indicator status: Standard indicator
Indicator type: AMA
Indicator timeframe: H1
Indicator handle: 12
Indicator group: Trend indicator
Indicator ID: 3
------
Empty value for plotting, for which there is no drawing: EMPTY_VALUE
------
Indicator symbol: EURUSD
Indicator name: "Adaptive Moving Average"
Indicator shortname: "AMA(EURUSD,H1)"
 --- Indicator parameters --- 
 - Averaging period: 9
 - Fast MA period: 2
 - Slow MA period: 30
 - Horizontal shift of the indicator: 0
 - Price type or handle: CLOSE
================== End of the parameter list: "Standard indicator" ==================

============= The beginning of the parameter list: "Standard indicator" =============
Indicator status: Standard indicator
Indicator type: AMA
Indicator timeframe: H1
Indicator handle: 13
Indicator group: Trend indicator
Indicator ID: 4
------
Empty value for plotting, for which there is no drawing: EMPTY_VALUE
------
Indicator symbol: EURUSD
Indicator name: "Adaptive Moving Average"
Indicator shortname: "AMA(EURUSD,H1)"
 --- Indicator parameters --- 
 - Averaging period: 14
 - Fast MA period: 2
 - Slow MA period: 30
 - Horizontal shift of the indicator: 0
 - Price type or handle: CLOSE
================== End of the parameter list: "Standard indicator" ==================

Custom indicator Examples\Custom Moving Average.ex5 EURUSD H1 [handle 10, id #1]
Custom indicator Examples\Custom Moving Average.ex5 EURUSD H1 [handle 11, id #2]
Standard indicator Adaptive Moving Average EURUSD H1 [handle 12, id #3]
Standard indicator Adaptive Moving Average EURUSD H1 [handle 13, id #4]

============= The beginning of the parameter list (Examples\Custom Moving Average.ex5(EURUSD,H1)) =============
Period start time: 2020.11.18 10:00:00
Indicator timeframe: H1
Indicator type: CUSTOM
Indicator buffer number: 0
Indicator ID: 1
------
Indicator buffer value: 1.186694
------
Indicator symbol: "EURUSD"
Indicator name: "Examples\Custom Moving Average.ex5"
Indicator shortname: "Examples\Custom Moving Average.ex5(EURUSD,H1)"
============= End of the parameter list (Examples\Custom Moving Average.ex5(EURUSD,H1)) =============

============= The beginning of the parameter list (Examples\Custom Moving Average.ex5(EURUSD,H1)) =============
Period start time: 2020.11.18 09:00:00
Indicator timeframe: H1
Indicator type: CUSTOM
Indicator buffer number: 0
Indicator ID: 1
------
Indicator buffer value: 1.186535
------
Indicator symbol: "EURUSD"
Indicator name: "Examples\Custom Moving Average.ex5"
Indicator shortname: "Examples\Custom Moving Average.ex5(EURUSD,H1)"
============= End of the parameter list (Examples\Custom Moving Average.ex5(EURUSD,H1)) =============

============= The beginning of the parameter list (Examples\Custom Moving Average.ex5(EURUSD,H1)) =============
Period start time: 2020.11.18 10:00:00
Indicator timeframe: H1
Indicator type: CUSTOM
Indicator buffer number: 0
Indicator ID: 2
------
Indicator buffer value: 1.186552
------
Indicator symbol: "EURUSD"
Indicator name: "Examples\Custom Moving Average.ex5"
Indicator shortname: "Examples\Custom Moving Average.ex5(EURUSD,H1)"
============= End of the parameter list (Examples\Custom Moving Average.ex5(EURUSD,H1)) =============

============= The beginning of the parameter list (Examples\Custom Moving Average.ex5(EURUSD,H1)) =============
Period start time: 2020.11.18 09:00:00
Indicator timeframe: H1
Indicator type: CUSTOM
Indicator buffer number: 0
Indicator ID: 2
------
Indicator buffer value: 1.186438
------
Indicator symbol: "EURUSD"
Indicator name: "Examples\Custom Moving Average.ex5"
Indicator shortname: "Examples\Custom Moving Average.ex5(EURUSD,H1)"
============= End of the parameter list (Examples\Custom Moving Average.ex5(EURUSD,H1)) =============

============= The beginning of the parameter list (AMA(EURUSD,H1)) =============
Period start time: 2020.11.18 10:00:00
Indicator timeframe: H1
Indicator type: AMA
Indicator buffer number: 0
Indicator ID: 3
------
Indicator buffer value: 1.186992
------
Indicator symbol: "EURUSD"
Indicator name: "Adaptive Moving Average"
Indicator shortname: "AMA(EURUSD,H1)"
============= End of the parameter list (AMA(EURUSD,H1)) =============

============= The beginning of the parameter list (AMA(EURUSD,H1)) =============
Period start time: 2020.11.18 09:00:00
Indicator timeframe: H1
Indicator type: AMA
Indicator buffer number: 0
Indicator ID: 3
------
Indicator buffer value: 1.186725
------
Indicator symbol: "EURUSD"
Indicator name: "Adaptive Moving Average"
Indicator shortname: "AMA(EURUSD,H1)"
============= End of the parameter list (AMA(EURUSD,H1)) =============

============= The beginning of the parameter list (AMA(EURUSD,H1)) =============
Period start time: 2020.11.18 10:00:00
Indicator timeframe: H1
Indicator type: AMA
Indicator buffer number: 0
Indicator ID: 4
------
Indicator buffer value: 1.186548
------
Indicator symbol: "EURUSD"
Indicator name: "Adaptive Moving Average"
Indicator shortname: "AMA(EURUSD,H1)"
============= End of the parameter list (AMA(EURUSD,H1)) =============

============= The beginning of the parameter list (AMA(EURUSD,H1)) =============
Period start time: 2020.11.18 09:00:00
Indicator timeframe: H1
Indicator type: AMA
Indicator buffer number: 0
Indicator ID: 4
------
Indicator buffer value: 1.186403
------
Indicator symbol: "EURUSD"
Indicator name: "Adaptive Moving Average"
Indicator shortname: "AMA(EURUSD,H1)"
============= End of the parameter list (AMA(EURUSD,H1)) =============

Examples\Custom Moving Average.ex5(EURUSD,H1) [Buffer 0, Index 0]
Examples\Custom Moving Average.ex5(EURUSD,H1) [Buffer 0, Index 1]
Examples\Custom Moving Average.ex5(EURUSD,H1) [Buffer 0, Index 0]
Examples\Custom Moving Average.ex5(EURUSD,H1) [Buffer 0, Index 1]
AMA(EURUSD,H1) [Buffer 0, Index 0]
AMA(EURUSD,H1) [Buffer 0, Index 1]
AMA(EURUSD,H1) [Buffer 0, Index 0]
AMA(EURUSD,H1) [Buffer 0, Index 1]

一方、チャート(コメント内)には、最初のバーとゼロバーの指標バッファのデータに対応するデータが表示されます。


次の段階

次の記事では、指標バッファデータのコレクションクラスを作成します。

現在のライブラリバージョンのすべてのファイルは、MQL5のテストEAファイルと一緒に以下に添付されています。ダウンロードし、すべてを検証することが可能です。
指標コレクションクラスは現在開発中であるため、プログラムは絶対使用しないでください。
質問や提案は記事のコメント欄にお願いします。

目次に戻る

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

DoEasyライブラリの時系列(第35部): バーオブジェクトと銘柄の時系列リスト
DoEasyライブラリの時系列(第36部): すべての使用銘柄期間の時系列オブジェクト
DoEasyライブラリの時系列(第37部): すべての使用銘柄期間の時系列オブジェクト
DoEasyライブラリの時系列(第38部): 時系列コレクション-リアルタイムの更新とプログラムからのデータへのアクセス
DoEasyライブラリの時系列(第39部): ライブラリに基づいた指標 - データイベントと時系列イベントの準備
DoEasyライブラリの時系列(第40部): ライブラリに基づいた指標 - 実時間でのデータ更新
DoEasyライブラリの時系列(第41部): 複数銘柄・複数期間指標の例
DoEasyライブラリの時系列(第42部): 抽象指標バッファオブジェクトクラス
DoEasyライブラリの時系列(第43部): 指標バッファオブジェクトクラス
DoEasyライブラリの時系列(第44部): 指標バッファオブジェクトのコレクションクラス
DoEasyライブラリの時系列(第45部): 複数期間指標バッファ
DoEasyライブラリの時系列(第46部): 複数銘柄・複数期間指標バッファ
DoEasyライブラリの時系列(第47部): 複数銘柄・複数期間標準指標
DoEasyライブラリの時系列(第48部): 単一サブウィンドウでの単一バッファ複数銘柄・複数期間指標
DoEasyライブラリの時系列(第49部): 複数銘柄・複数期間の複数バッファ標準指標
DoEasyライブラリの時系列(第50部): シフト付き複数銘柄・複数期間標準指標
DoEasyライブラリの時系列(第51部): 複数銘柄・複数期間の複合標準指標
DoEasyライブラリの時系列(第52部): 複数銘柄・複数期間の単一バッファ標準指標のクロスプラットフォーム化
DoEasyライブラリの時系列(第53部): 抽象基本指標クラス
DoEasyライブラリの時系列(第54部): 抽象基本指標の子孫クラス
DoEasyライブラリの時系列(第55部): 指標コレクションクラス
DoEasyライブラリの時系列(第56部):カスタム指標オブジェクト、コレクション内指標オブジェクトからのデータ取得