DoEasyライブラリの時系列(第55部): 指標コレクションクラス

13 1月 2021, 07:59
Artyom Trishkin
0
105

目次


概念

本稿では、前の記事で開発を開始した抽象指標基本オブジェクトの子孫クラスを完成します。
ライブラリオブジェクト構築の一般的な概念に従い、指標オブジェクトの構成が他のライブラリオブジェクトと変わらないように、指標オブジェクトに説明を追加する必要があります。その過程で、コレクション内のこれらのオブジェクトのストレージを改善します。つまり、指標コレクションを作成し、コレクションにオブジェクトを追加する際に前の記事で作成された欠点を排除します。

抽象指標基本オブジェクトとこのオブジェクトの子孫である指標オブジェクトは独立したオブジェクトであり、以前にライブラリを使用したカスタム指標の作成用に作成した複数銘柄・複数期間指標とは混合できません。

抽象指標オブジェクトとその子孫は、指標EAや、さまざまな指標値のデータとステータスのさまざまな組み合わせを検索するために使用する必要がある指標オブジェクトです。


ライブラリクラスの改善

いつものように、ライブラリオブジェクトクラスを開発するときはまず、説明が表示されるときにオブジェクトが使用する必要なテキストメッセージを追加します。指標オブジェクトの場合、すべての標準指標のすべての可能なパラメータを表示するためのメッセージが必要です。
\MQL5\Include\DoEasy\Data.mqhファイルに新しいメッセージのインデックスを追加します。

   MSG_LIB_TEXT_IND_TEXT_EMPTY_VALUE,                 // Empty value for plotting where nothing will be drawn
   MSG_LIB_TEXT_IND_TEXT_SYMBOL,                      // Indicator symbol
   MSG_LIB_TEXT_IND_TEXT_NAME,                        // Indicator name
   MSG_LIB_TEXT_IND_TEXT_SHORTNAME,                   // Indicator short name
   
   MSG_LIB_TEXT_IND_TEXT_IND_PARAMETERS,              // Indicator parameters
   MSG_LIB_TEXT_IND_TEXT_APPLIED_VOLUME,              // Volume type for calculation
   MSG_LIB_TEXT_IND_TEXT_PERIOD,                      // Averaging period
   MSG_LIB_TEXT_IND_TEXT_FAST_PERIOD,                 // Fast MA period
   MSG_LIB_TEXT_IND_TEXT_SLOW_PERIOD,                 // Slow MA period
   MSG_LIB_TEXT_IND_TEXT_SIGNAL,                      // Difference averaging period
   MSG_LIB_TEXT_IND_TEXT_TENKAN_PERIOD,               // Tenkan-sen period
   MSG_LIB_TEXT_IND_TEXT_KIJUN_PERIOD,                // Kijun-sen period
   MSG_LIB_TEXT_IND_TEXT_SPANB_PERIOD,                // Senkou Span B period
   MSG_LIB_TEXT_IND_TEXT_JAW_PERIOD,                  // Period for jaw line calculation
   MSG_LIB_TEXT_IND_TEXT_TEETH_PERIOD,                // Period for teeth line calculation
   MSG_LIB_TEXT_IND_TEXT_LIPS_PERIOD,                 // Period for lips line calculation
   MSG_LIB_TEXT_IND_TEXT_JAW_SHIFT,                   // Horizontal shift of jaws line
   MSG_LIB_TEXT_IND_TEXT_TEETH_SHIFT,                 // Horizontal shift of teeth line
   MSG_LIB_TEXT_IND_TEXT_LIPS_SHIFT,                  // Horizontal shift of lips line
   MSG_LIB_TEXT_IND_TEXT_SHIFT,                       // Horizontal shift of the indicator
   MSG_LIB_TEXT_IND_TEXT_MA_METHOD,                   // Smoothing type
   MSG_LIB_TEXT_IND_TEXT_APPLIED_PRICE,               // Price type or handle
   MSG_LIB_TEXT_IND_TEXT_STD_DEVIATION,               // Number of standard deviations
   MSG_LIB_TEXT_IND_TEXT_DEVIATION,                   // Deviation of channel borders from the central line
   MSG_LIB_TEXT_IND_TEXT_STEP,                        // Price change step — acceleration factor
   MSG_LIB_TEXT_IND_TEXT_MAXIMUM,                     // Maximum step
   MSG_LIB_TEXT_IND_TEXT_KPERIOD,                     // K-period (number of bars for calculation)
   MSG_LIB_TEXT_IND_TEXT_DPERIOD,                     // D-period (primary smoothing period)
   MSG_LIB_TEXT_IND_TEXT_SLOWING,                     // Final smoothing
   MSG_LIB_TEXT_IND_TEXT_PRICE_FIELD,                 // Stochastic calculation method
   MSG_LIB_TEXT_IND_TEXT_CMO_PERIOD,                  // Chande Momentum period
   MSG_LIB_TEXT_IND_TEXT_SMOOTHING_PERIOD,            // Smoothing factor period
   
//--- CIndicatorsCollection
   MSG_LIB_SYS_FAILED_ADD_IND_TO_LIST,                // Error. Failed to add indicator object to the list
   
  };
//+------------------------------------------------------------------+

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

   {"Empty value for plotting, for which there is no drawing"},
   {"Indicator symbol"},
   {"Indicator name"},
   {"Indicator shortname"},
   
   {"Indicator parameters"},
   {"Volume type for calculation"},
   {"Averaging period"},
   {"Fast MA period"},
   {"Slow MA period"},
   {"Averaging period for their difference"},
   {"Tenkan-sen period"},
   {"Kijun-sen period"},
   {"Senkou Span B period"},
   {"Period for the calculation of jaws"},
   {"Period for the calculation of teeth"},
   {"Period for the calculation of lips"},
   {"Horizontal shift of jaws"},
   {"Horizontal shift of teeth"},
   {"Horizontal shift of lips"},
   {"Horizontal shift of the indicator"},
   {"Smoothing type"},
   {"Price type or handle"},
   {"Number of standard deviations"},
   {"Deviation of boundaries from the midline"},
   {"Price increment step - acceleration factor"},
   {"Maximum value of step"},
   {"K-period (number of bars for calculations)"},
   {"D-period (period of first smoothing)"},
   {"Final smoothing"},
   {"Stochastic calculation method"},
   {"Chande Momentum period"},
   {"Smoothing factor period"},
   
   {"Error. Failed to add indicator object to list"},
   
  };
//+---------------------------------------------------------------------+

平均化の方法、価格の種類、計算する量などの特定の指標パラメータを表示するには、\MQL5\Include\DoEasy\Services\DELib.mqhにある ライブラリのサービス関数のファイルにいくつかの関数を追加します 。

//+------------------------------------------------------------------+
//| Return timeframe description                                   |
//+------------------------------------------------------------------+
string TimeframeDescription(const ENUM_TIMEFRAMES timeframe)
  {
   return StringSubstr(EnumToString((timeframe>PERIOD_CURRENT ? timeframe : (ENUM_TIMEFRAMES)Period())),7);
  }
//+------------------------------------------------------------------+
//| Return volume description for calculation                           |
//+------------------------------------------------------------------+
string AppliedVolumeDescription(const ENUM_APPLIED_VOLUME volume)
  {
   return StringSubstr(EnumToString(volume),7);
  }
//+------------------------------------------------------------------+
//| Return indicator type description                              |
//+------------------------------------------------------------------+
string IndicatorTypeDescription(const ENUM_INDICATOR indicator)
  {
   return StringSubstr(EnumToString(indicator),4);
  }
//+------------------------------------------------------------------+
//| Return averaging method description                            |
//+------------------------------------------------------------------+
string AveragingMethodDescription(const ENUM_MA_METHOD method)
  {
   return StringSubstr(EnumToString(method),5);
  }
//+------------------------------------------------------------------+
//| Return applied price description                            |
//+------------------------------------------------------------------+
string AppliedPriceDescription(const ENUM_APPLIED_PRICE price)
  {
   return StringSubstr(EnumToString(price),6);
  }
//+------------------------------------------------------------------+
//| Return stochastic price calculation description                      |
//+------------------------------------------------------------------+
string StochPriceDescription(const ENUM_STO_PRICE price)
  {
   return StringSubstr(EnumToString(price),4);
  }
//+------------------------------------------------------------------+

これは簡単で、列挙値のテキスト表現の必要な位置から部分文字列を取得し、最後に指標の名前、計算方法、またはボリュームと価格のタイプを取得します。

各指標には、明確なパラメータのセットがあります。これらのパラメータは、指標パラメータ構造体の配列MqlParamを使用して指標に設定できます。これは、各指標オブジェクトの作成中に行うことです。それぞれ、各指標について、これらの構造体の配列のすべての値が操作ログに表示される場合があります。この指標タイプにのみ固有のパラメータの値のデータは、各配列セルでさまざまな指標で利用できます。ただし、同じタイプのいくつかの指標の場合、目的が等しく、値のみが異なるプロパティは、各配列セルで指定されます。
したがって、各指標について、設定された値を有する指標パラメータのセットを操作ログに表示するメソッドを書くことができます。これは標準指標にのみ当てはまります。標準指標については、特定の各指標のパラメータのセットが確実にわかるからです。

これは仮想メソッドになります。\MQL5\Include\DoEasy\Objects\Indicators\IndicatorDE.mqhの抽象指標オブジェクトクラスに記述します。

//--- Display the description of indicator object properties in the journal (full_prop=true - all properties, false - supported ones only)
   void              Print(const bool full_prop=false);
//--- Display (1) a short description, (2) description of indicator object parameters in the journal (implementation in the descendants)
   virtual void      PrintShort(void) {;}
   virtual void      PrintParameters(void) {;}

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

このクラスでは、このメソッドは何もしません。また、操作ログで指標データを表示するメソッドは、子孫オブジェクトで実装されます。
独自のパラメータセットが各指標に固有であるため、各子孫クラスは独自のメソッドを所有します。

クローズドパラメトリックコンストラクタで、指標タイプの説明を取得する文字列を

   this.m_ind_type=::StringSubstr(::EnumToString(ind_type),4);

で置き換えます。これには、上記の新しいサービス関数を使用して説明を取得します。

//+------------------------------------------------------------------+
//| Closed parametric constructor                             |
//+------------------------------------------------------------------+
CIndicatorDE::CIndicatorDE(ENUM_INDICATOR ind_type,
                           string symbol,
                           ENUM_TIMEFRAMES timeframe,
                           ENUM_INDICATOR_STATUS status,
                           ENUM_INDICATOR_GROUP group,
                           string name,
                           string shortname,
                           MqlParam &mql_params[])
  {
//--- Set collection ID for the object
   this.m_type=COLLECTION_INDICATORS_ID;
//--- Write description of indicator type
   this.m_ind_type_description=IndicatorTypeDescription(ind_type);
//--- If parameter array size passed to constructor is more than zero
//--- fill in the array of object parameters with data from the array passed to constructor
   int count=::ArrayResize(this.m_mql_param,::ArraySize(mql_params));
   for(int i=0;i<count;i++)
     {
      this.m_mql_param[i].type         = mql_params[i].type;
      this.m_mql_param[i].double_value = mql_params[i].double_value;
      this.m_mql_param[i].integer_value= mql_params[i].integer_value;
      this.m_mql_param[i].string_value = mql_params[i].string_value;
     }
//--- Create indicator handle
   int handle=::IndicatorCreate(symbol,timeframe,ind_type,count,this.m_mql_param);
   
//--- Save integer properties
   this.m_long_prop[INDICATOR_PROP_STATUS]                     = status;
   this.m_long_prop[INDICATOR_PROP_TYPE]                       = ind_type;
   this.m_long_prop[INDICATOR_PROP_GROUP]                      = group;
   this.m_long_prop[INDICATOR_PROP_TIMEFRAME]                  = timeframe;
   this.m_long_prop[INDICATOR_PROP_HANDLE]                     = handle;
   
//--- Save real properties
   this.m_double_prop[this.IndexProp(INDICATOR_PROP_EMPTY_VALUE)]=EMPTY_VALUE;
//--- Save string properties
   this.m_string_prop[this.IndexProp(INDICATOR_PROP_SYMBOL)]   = (symbol==NULL || symbol=="" ? ::Symbol() : symbol);
   this.m_string_prop[this.IndexProp(INDICATOR_PROP_NAME)]     = name;
   this.m_string_prop[this.IndexProp(INDICATOR_PROP_SHORTNAME)]= shortname;
  }
//+------------------------------------------------------------------+

操作ログに指標プロパティを表示するメソッドで、すべての指標オブジェクトプロパティを表示した後のリストの最後に、操作ログに指標パラメータのセットとそれらに設定された値を表示するメソッドの呼び出しを追加します

//+------------------------------------------------------------------+
//| Display indicator properties in the journal                             |
//+------------------------------------------------------------------+
void CIndicatorDE::Print(const bool full_prop=false)
  {
   ::Print("============= ",CMessage::Text(MSG_LIB_PARAMS_LIST_BEG),": \"",this.GetStatusDescription(),"\" =============");
   int beg=0, end=INDICATOR_PROP_INTEGER_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_INDICATOR_PROP_INTEGER prop=(ENUM_INDICATOR_PROP_INTEGER)i;
      if(!full_prop && !this.SupportProperty(prop)) continue;
      ::Print(this.GetPropertyDescription(prop));
     }
   ::Print("------");
   beg=end; end+=INDICATOR_PROP_DOUBLE_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_INDICATOR_PROP_DOUBLE prop=(ENUM_INDICATOR_PROP_DOUBLE)i;
      if(!full_prop && !this.SupportProperty(prop)) continue;
      ::Print(this.GetPropertyDescription(prop));
     }
   ::Print("------");
   beg=end; end+=INDICATOR_PROP_STRING_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_INDICATOR_PROP_STRING prop=(ENUM_INDICATOR_PROP_STRING)i;
      if(!full_prop && !this.SupportProperty(prop)) continue;
      ::Print(this.GetPropertyDescription(prop));
     }
   this.PrintParameters();
   ::Print("================== ",CMessage::Text(MSG_LIB_PARAMS_LIST_END),": \"",this.GetStatusDescription(),"\" ==================\n");
  }
//+------------------------------------------------------------------+

ここで、PrintPatameters()メソッドが抽象指標基本オブジェクトの子孫クラスに存在する場合、Print()メソッドが呼び出されると、PrintPatameters()仮想メソッドが子孫クラスから呼び出され、操作ログでの指標パラメータの表示が実装されます。

各指標タイプには独自のパラメータセットがあるため、各子孫クラスで独自のPrintPatameters()メソッドを実装する必要があります。このようなメソッドは、指標オブジェクトごとにすでに作成されています。論理的にはすべて同じタイプですが、内容が異なります。メソッドはすべての指標に対して記述されますが、カスタム指標は例外です。すべての標準指標とは対照的に、カスタム指標のパラメータのセットは事前に知ることができないため、メソッドの実装が異なるためです。
子孫オブジェクトごとにこれらのメソッドを分析してみましょう。

以下は、指標オブジェクトAccelerator Oscillatorのクラスです。

//+------------------------------------------------------------------+
//|                                                        IndAC.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"
//+------------------------------------------------------------------+
//| Include files                                                 |
//+------------------------------------------------------------------+
#include "..\\IndicatorDE.mqh"
//+------------------------------------------------------------------+
//| Standard indicator Accelerator Oscillator                     |
//+------------------------------------------------------------------+
class CIndAC : public CIndicatorDE
  {
private:

public:
   //--- Constructor
                     CIndAC(const string symbol,const ENUM_TIMEFRAMES timeframe,MqlParam &mql_param[]) : 
                        CIndicatorDE(IND_AC,symbol,timeframe,
                                     INDICATOR_STATUS_STANDART,
                                     INDICATOR_GROUP_OSCILLATOR,
                                     "Accelerator Oscillator",
                                     "AC("+symbol+","+TimeframeDescription(timeframe)+")",mql_param) {}
   //--- Supported indicator properties (1) real, (2) integer
   virtual bool      SupportProperty(ENUM_INDICATOR_PROP_DOUBLE property);
   virtual bool      SupportProperty(ENUM_INDICATOR_PROP_INTEGER property);

//--- Display (1) a short description, (2) description of indicator object parameters in the journal
   virtual void      PrintShort(void);
   virtual void      PrintParameters(void) {;}
  };
//+------------------------------------------------------------------+
//| Return 'true' if indicator supports a passed        |
//| integer property, otherwise return 'false'       |
//+------------------------------------------------------------------+
bool CIndAC::SupportProperty(ENUM_INDICATOR_PROP_INTEGER property)
  {
   return true;
  }
//+------------------------------------------------------------------+
//| Return 'true' if indicator supports a passed        |
//| real property, otherwise return 'false'        |
//+------------------------------------------------------------------+
bool CIndAC::SupportProperty(ENUM_INDICATOR_PROP_DOUBLE property)
  {
   return true;
  }
//+------------------------------------------------------------------+
//| Display a short description of indicator object in the journal             |
//+------------------------------------------------------------------+
void CIndAC::PrintShort(void)
  {
   ::Print(GetStatusDescription()," ",this.Name()," ",this.Symbol()," ",TimeframeDescription(this.Timeframe())," [",this.Handle(),"]");
  }
//+------------------------------------------------------------------+

ここでは、パラメータを表示する仮想メソッドは宣言されているだけで、AC指標には入力がないため、空です。子孫クラスの仮想メソッドが欠落している場合、親クラスの仮想メソッドが呼び出されるため、ここでは省略できます。ただし、ここでは、すべての子孫クラスがメソッドの構造が同じになるように記述しました。
指標の簡単な説明を表示するメソッドで、このオブジェクト用に作成された指標ハンドルの表示を追加します。このメソッドのこのような変更は、すべての指標オブジェクトに対して行われます。これらについてはこれ以上分析しません。代わりに、指標パラメータの説明の表示メソッドのみを分析します。

以下は、指標オブジェクトAccumulation/Distributionのクラスとその指標パラメータ説明を表示するメソッドです。

//+------------------------------------------------------------------+
//|                                                        IndAD.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"
//+------------------------------------------------------------------+
//| Include files                                                 |
//+------------------------------------------------------------------+
#include "..\\IndicatorDE.mqh"
//+------------------------------------------------------------------+
//| Standard indicator Accumulation/Distribution                  |
//+------------------------------------------------------------------+
class CIndAD : public CIndicatorDE
  {
private:

public:
   //--- Constructor
                     CIndAD(const string symbol,const ENUM_TIMEFRAMES timeframe,MqlParam &mql_param[]) :
                        CIndicatorDE(IND_AD,symbol,timeframe,
                                     INDICATOR_STATUS_STANDART,
                                     INDICATOR_GROUP_VOLUMES,
                                     "Accumulation/Distribution",
                                     "AD("+symbol+","+TimeframeDescription(timeframe)+")",mql_param) {}
   //--- Supported indicator properties (1) real, (2) integer
   virtual bool      SupportProperty(ENUM_INDICATOR_PROP_DOUBLE property);
   virtual bool      SupportProperty(ENUM_INDICATOR_PROP_INTEGER property);
   
//--- Display (1) a short description, (2) description of indicator object parameters in the journal
   virtual void      PrintShort(void);
   virtual void      PrintParameters(void);
  };
//+------------------------------------------------------------------+
//| Return 'true' if indicator supports a passed        |
//| integer property, otherwise return 'false'       |
//+------------------------------------------------------------------+
bool CIndAD::SupportProperty(ENUM_INDICATOR_PROP_INTEGER property)
  {
   return true;
  }
//+------------------------------------------------------------------+
//| Return 'true' if indicator supports a passed        |
//| real property, otherwise return 'false'        |
//+------------------------------------------------------------------+
bool CIndAD::SupportProperty(ENUM_INDICATOR_PROP_DOUBLE property)
  {
   return true;
  }
//+------------------------------------------------------------------+
//| Display a short description of indicator object in the journal             |
//+------------------------------------------------------------------+
void CIndAD::PrintShort(void)
  {
   ::Print(GetStatusDescription()," ",this.Name()," ",this.Symbol()," ",TimeframeDescription(this.Timeframe())," [",this.Handle(),"]");
  }
//+------------------------------------------------------------------+
//| Display parameter description of indicator object in the journal          |
//+------------------------------------------------------------------+
void CIndAD::PrintParameters(void)
  {
   ::Print(" --- ",CMessage::Text(MSG_LIB_TEXT_IND_TEXT_IND_PARAMETERS)," --- ");
   //--- applied_volume
   ::Print(" - ",CMessage::Text(MSG_LIB_TEXT_IND_TEXT_APPLIED_VOLUME),": ",AppliedVolumeDescription((ENUM_APPLIED_VOLUME)m_mql_param[0].integer_value));
  }
//+------------------------------------------------------------------+

Accumulation/Distribution指標には、計算用のボリュームタイプの1つの入力しかありません。したがって、入力構造体の配列には、このパラメータを格納するセルが1つだけあります。それぞれ、操作ログに表示するために、構造体の整数データからインデックス0で配列から取得し、上記のサービス関数を使用して操作ログに送信しますパラメータ値を表示する前に、ライブラリの以前に作成されたテキストメッセージからパラメータ値を説明してください

さらに、指標入力説明の表示メソッドのみを分析します。

以下は、指標オブジェクトAverage Directional Indexのクラス指標パラメータの説明の表示メソッドです。

//+------------------------------------------------------------------+
//| Display parameter description of indicator object in the journal          |
//+------------------------------------------------------------------+
void CIndADX::PrintParameters(void)
  {
   ::Print(" --- ",CMessage::Text(MSG_LIB_TEXT_IND_TEXT_IND_PARAMETERS)," --- ");
   //--- adx_period
   ::Print(" - ",CMessage::Text(MSG_LIB_TEXT_IND_TEXT_PERIOD),": ",(string)m_mql_param[0].integer_value);
  }
//+------------------------------------------------------------------+

ADX指標には、計算期間という1つの入力があります。したがって、同じように、構造体の整数データからインデックス0で1つの配列セルのみの説明を表示します

以下は、指標オブジェクトAlligatorのクラス指標パラメータの説明の表示メソッドです。

//+------------------------------------------------------------------+
//| Display parameter description of indicator object in the journal          |
//+------------------------------------------------------------------+
void CIndAlligator::PrintParameters(void)
  {
   ::Print(" --- ",CMessage::Text(MSG_LIB_TEXT_IND_TEXT_IND_PARAMETERS)," --- ");
   //--- jaw_period
   ::Print(" - ",CMessage::Text(MSG_LIB_TEXT_IND_TEXT_JAW_PERIOD),": ",(string)m_mql_param[0].integer_value);
   //--- jaw_shift
   ::Print(" - ",CMessage::Text(MSG_LIB_TEXT_IND_TEXT_JAW_SHIFT),": ",(string)m_mql_param[1].integer_value);
   //--- teeth_period
   ::Print(" - ",CMessage::Text(MSG_LIB_TEXT_IND_TEXT_TEETH_PERIOD),": ",(string)m_mql_param[2].integer_value);
   //--- teeth_shift
   ::Print(" - ",CMessage::Text(MSG_LIB_TEXT_IND_TEXT_TEETH_SHIFT),": ",(string)m_mql_param[3].integer_value);
   //--- lips_period
   ::Print(" - ",CMessage::Text(MSG_LIB_TEXT_IND_TEXT_LIPS_PERIOD),": ",(string)m_mql_param[4].integer_value);
   //--- lips_shift
   ::Print(" - ",CMessage::Text(MSG_LIB_TEXT_IND_TEXT_LIPS_SHIFT),": ",(string)m_mql_param[5].integer_value);
   //--- ma_method
   ::Print(" - ",CMessage::Text(MSG_LIB_TEXT_IND_TEXT_MA_METHOD),": ",AveragingMethodDescription((ENUM_MA_METHOD)m_mql_param[6].integer_value));
   //--- applied_price
   ::Print(
           " - ",CMessage::Text(MSG_LIB_TEXT_IND_TEXT_APPLIED_PRICE),": ",
           (m_mql_param[7].integer_value<10 ? AppliedPriceDescription((ENUM_APPLIED_PRICE)m_mql_param[7].integer_value) : (string)m_mql_param[7].integer_value)
          );
  }
//+------------------------------------------------------------------+

指標Alligatorには8つの入力があるため、指標の作成時のシーケンス順序に対応して1つずつ表示します。

  • 「顎」ライン計算期間 - 配列内インデックス0
  • 「顎」ラインの横シフト - 配列内インデックス1
  • 「歯」ライン計算期間 - 配列内インデックス2
  • 「歯」ラインの横シフト - 配列内インデックス3
  • 「唇」ライン計算期間 - 配列内インデックス4
  • 「唇」ラインの横シフト - 配列内インデックス5
  • 平滑化の種類 - 配列内インデックス6
  • 価格の種類または指標ハンドル - 配列内インデックス7

すべてのデータは整数型を持っているため、対応する配列セルからの構造整数データの説明を表示します。
最後のパラメータは、指標が作成される価格のタイプまたはAlligatorが作成されるデータの指標ハンドルのいずれかを格納できます。したがって、まず配列セルの値を確認します。値が10未満の場合は、指標が可能な価格タイプの1つに基づいて構築されているので、価格タイプの説明を表示します。値が10以上の場合は、配列にハンドルが書き込まれている別の指標のデータに基づいて指標が作成されているので、この指標のハンドル値を表示します。

以下は、指標オブジェクトEnvelopesのクラス指標パラメータの説明の表示メソッドです。

//+------------------------------------------------------------------+
//| Display parameter description of indicator object in the journal          |
//+------------------------------------------------------------------+
void CIndEnvelopes::PrintParameters(void)
  {
   ::Print(" --- ",CMessage::Text(MSG_LIB_TEXT_IND_TEXT_IND_PARAMETERS)," --- ");
   //--- ma_period
   ::Print(" - ",CMessage::Text(MSG_LIB_TEXT_IND_TEXT_PERIOD),": ",(string)m_mql_param[0].integer_value);
   //--- ma_shift
   ::Print(" - ",CMessage::Text(MSG_LIB_TEXT_IND_TEXT_SHIFT),": ",(string)m_mql_param[1].integer_value);
   //--- ma_method
   ::Print(" - ",CMessage::Text(MSG_LIB_TEXT_IND_TEXT_MA_METHOD),": ",AveragingMethodDescription((ENUM_MA_METHOD)m_mql_param[2].integer_value));
   //--- applied_price
   ::Print(
           " - ",CMessage::Text(MSG_LIB_TEXT_IND_TEXT_APPLIED_PRICE),": ",
           (m_mql_param[3].integer_value<10 ? AppliedPriceDescription((ENUM_APPLIED_PRICE)m_mql_param[3].integer_value) : (string)m_mql_param[3].integer_value)
          );
   //--- deviation
   ::Print(" - ",CMessage::Text(MSG_LIB_TEXT_IND_TEXT_DEVIATION),": ",::DoubleToString(m_mql_param[4].double_value,3));
   
  }
//+------------------------------------------------------------------+

Envelopes指標には、5つの入力があります。最後のパラメータ「中心線からのチャネル境界の偏差」は実数型です。したがって、このパラメータの説明を表示するには、入力構造体の実数データから値を取得します

指標オブジェクトクラスの残りのすべてのメソッドは上記で検討したもののロジックを繰り返すので、ここでは分析しません。本稿に添付されたファイルをご覧ください。

作成されたすべての指標オブジェクトを指標のコレクションリストに配置します。ターミナルでは、同じパラメータで任意の数の指標を作成すると、実際には1つの指標が作成され、すべての呼び出しがそれに進みます。したがって、指標オブジェクトを作成してコレクションリストに配置するには、コレクションリストに、リストに配置するものと同じタイプ、銘柄/時間枠、およびパラメータを持つ同じ指標があるかどうかを制御する必要があります。これは、まったく同じ指標オブジェクトはすべて、作成された指標の同じハンドル持つためです。これは、これが1つの同じ指標オブジェクトであることを意味します。

\MQL5\Include\DoEasy\Collections\IndicatorsCollection.mqhファイルで、前の記事で実装を始めた指標オブジェクトコレクションクラスに必要な変更を加えます。2つの指標オブジェクトを検索して比較するために、CObjectクラスのインスタンスと標準配布されたライブラリからのその子孫へのポインタの動的配列のクラスのSearch()メソッドを使用しました。しかし、このメソッドでは、構造体を含む2つのオブジェクトの同等性を明確に判断することはできません。このメソッドの目的は、2つの同じ型のオブジェクトの1つの指定されたプロパティを比較することです。指標オブジェクトでは、MqlParam指標のパラメータ構造体の配列を積極的に使用します。この配列では、配列内の構造の各プロパティを要素ごとに比較する必要があります。 幸い、すべてのライブラリオブジェクトには、2つの同じ型のオブジェクトを正確に比較するためのデフォルトのメソッドIsEqual()があります。 2つの同じ型のオブジェクトが等しいかどうかを比較するには、このメソッドを使用します。

クラスのprivateセクションで、コレクションリスト内の指標オブジェクトインデックスを返すメソッドを宣言します

//+------------------------------------------------------------------+
//| Indicator collection                                            |
//+------------------------------------------------------------------+
class CIndicatorsCollection : public CObject
  {
private:
   CListObj                m_list;                       // Indicator object list
   MqlParam                m_mql_param[];                // Array of indicator parameters

//--- Create a new indicator object
   CIndicatorDE           *CreateIndicator(const ENUM_INDICATOR ind_type,MqlParam &mql_param[],const string symbol_name=NULL,const ENUM_TIMEFRAMES period=PERIOD_CURRENT);
//--- Return the indicator index in the list
   int                     Index(CIndicatorDE *compared_obj);

public:

クラス本体の最後で、コレクションリストにある指標オブジェクトの完全な説明と短い説明を表示する2つのpublicメソッドを宣言します

//--- Display (1) the complete and (2) short collection description in the journal
   void                    Print(void);
   void                    PrintShort(void);

//--- Constructor
                           CIndicatorsCollection();

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

宣言されたメソッドをクラス本体の外側に実装します。

以下は、操作ログにコレクションの完全な説明を表示するメソッドです。

//+------------------------------------------------------------------+
//| Display full collection description in the journal                       |
//+------------------------------------------------------------------+
void CIndicatorsCollection::Print(void)
  {
   int total=this.m_list.Total();
   for(int i=0;i<total;i++)
     {
      CIndicatorDE *ind=m_list.At(i);
      if(ind==NULL)
         continue;
      ind.Print();
     }
  }
//+------------------------------------------------------------------+

コレクションリストによるループであと1つの指標オブジェクトを取得して操作ログでその完全な説明を表示します

以下は、操作ログにコレクションの短い説明を表示するメソッドです。

//+------------------------------------------------------------------+
//| Display the short collection description in the journal                      |
//+------------------------------------------------------------------+
void CIndicatorsCollection::PrintShort(void)
  {
   int total=this.m_list.Total();
   for(int i=0;i<total;i++)
     {
      CIndicatorDE *ind=m_list.At(i);
      if(ind==NULL)
         continue;
      ind.PrintShort();
     }
  }
//+------------------------------------------------------------------+

コレクションリストによるループであと1つの指標オブジェクトを取得して操作ログでその短い説明を表示します

以下はコレクションリストの指標オブジェクトインデックスを返すメソッドです。
:

//+------------------------------------------------------------------+
//| Return the indicator index in the list                            |
//+------------------------------------------------------------------+
int CIndicatorsCollection::Index(CIndicatorDE *compared_obj)
  {
   int total=this.m_list.Total();
   for(int i=0;i<total;i++)
     {
      CIndicatorDE *indicator=m_list.At(i);
      if(indicator==NULL)
         continue;
      if(indicator.IsEqual(compared_obj))
         return i;
     }
   return WRONG_VALUE;
  }
//+------------------------------------------------------------------+

コレクションリストによるループであと1つの指標オブジェクトを取得して指標オブジェクトと比較し、そのポインタをメソッドに渡して、オブジェクトが等しい場合はループインデックスを返します。ループの終了時には(すべてのオブジェクトが不平等)-1を返します

新しい指標オブジェクトを作成するメソッドとコレクションリストに配置するメソッドのすべてで同じ変更が行われました。<分節138663¶>これは、オブジェクトの作成に失敗したとき、またはリストへの配置に失敗したときに発生する可能性のあるメモリリークを除外するために行われます。

例として、Accelerator Oscillator指標を作成するメソッドを使用してみましょう。

//+------------------------------------------------------------------+
//| Create a new indicator object Accelerator Oscillator            |
//| and place it to the collection list                                |
//+------------------------------------------------------------------+
int CIndicatorsCollection::CreateAC(const string symbol,const ENUM_TIMEFRAMES timeframe)
  {
//--- AC indicator possesses no parameters - resize the array of parameter structures
   ::ArrayResize(this.m_mql_param,0);
//--- Create indicator object
   CIndicatorDE *indicator=this.CreateIndicator(IND_AC,this.m_mql_param,symbol,timeframe);
   if(indicator==NULL)
      return INVALID_HANDLE;
//--- If such indicator is already in the list
   int index=this.Index(indicator);
   if(index!=WRONG_VALUE)
     {
      //--- Remove created object, get indicator object from the list and return indicator handle
      delete indicator;
      indicator=this.m_list.At(index);
      return indicator.Handle();
     }
//--- If such indicator is not in the list
   else
     {
      //--- If failed to add indicator object to the list
      //--- display the appropriate message, remove object and return INVALID_HANDLE
      if(!this.m_list.Add(indicator))
        {
         ::Print(CMessage::Text(MSG_LIB_SYS_FAILED_ADD_IND_TO_LIST));
         delete indicator;
         return INVALID_HANDLE;
        }
      //--- Return the handle of a new indicator added to the list
      return indicator.Handle();
     }
//--- Return INVALID_HANDLE
   return INVALID_HANDLE;
  }
//+------------------------------------------------------------------+

インデックスでリスト内の指標オブジェクトの可用性を確認します
インデックスが-1を超える場合は
リストに含まれているので、新しく作成されたオブジェクトを削除する必要があります
そのような指標がリストになく、何らかの理由でコレクションリストに追加できなかった場合
新しく作成されたオブジェクトを削除します
これにより、コレクションリストへの新しいオブジェクトの配置に失敗した場合のメモリリークが除外されます。

このような変更はすべての指標オブジェクト作成メソッドで行われていますが、ここでは分析しません。本稿に添付されたファイルをご覧ください。

コレクションリスト内の指標オブジェクトを検索し、このリストからそのオブジェクトへのポインタを取得するには、必要なオブジェクトへのポインタを返すメソッドが必要です。メソッドに、必要な指標のタイプ、その銘柄、時間枠、およびパラメータを渡します(各指標のパラメータは指標タイプに対応します)。最後に、リストにある指標オブジェクトへのポインタを受け取る必要があります。

前回の記事では、Accelerator Oscillator指標へのポインタを取得するためにこのようなメソッドを作成しました。AC指標には入力がなく、銘柄と時間枠で必要なオブジェクトを見つけるだけでよいため、これは最も単純です。

//+------------------------------------------------------------------+
//| Return pointer to indicator object Accelerator Oscillator  |
//+------------------------------------------------------------------+
CIndicatorDE *CIndicatorsCollection::GetIndAC(const string symbol,const ENUM_TIMEFRAMES timeframe)
  {
   CArrayObj *list=GetListAC(symbol,timeframe);
   return(list==NULL || list.Total()==0 ? NULL : list.At(0));
  }
//+------------------------------------------------------------------+

入力を持つ指標を検索するには、一時的な指標オブジェクトを作成してパラメータを設定し、コレクションリストで一致を検索します

//+------------------------------------------------------------------+
//| Return pointer to indicator object                         |
//| Accumulation/Distribution                                        |
//+------------------------------------------------------------------+
CIndicatorDE *CIndicatorsCollection::GetIndAD(const string symbol,const ENUM_TIMEFRAMES timeframe,const ENUM_APPLIED_VOLUME applied_volume)
  {
   MqlParam param[1];
   param[0].type=TYPE_INT;
   param[0].integer_value=applied_volume;
   CIndicatorDE *tmp=this.CreateIndicator(IND_AD,param,symbol,timeframe);
   if(tmp==NULL)
      return NULL;
   int index=this.Index(tmp);
   delete tmp;
   return(index>WRONG_VALUE ? this.m_list.At(index) : NULL);
  }
//+------------------------------------------------------------------+

そのようなオブジェクトがリストに見つかった場合は、そのインデックスが返されます。それ以外の場合は、-1が返されます。

リスト内の指標オブジェクトポインタを返す残りのメソッドは、上記で検討したものと同じですが、指標オブジェクトを作成するための他のパラメータを持っています。たとえば、Alligator指標オブジェクトへのポインタを返すには、8つのパラメータで構成される配列を作成します。

//+------------------------------------------------------------------+
//| Return pointer to indicator object Alligator               |
//+------------------------------------------------------------------+
CIndicatorDE *CIndicatorsCollection::GetIndAlligator(const string symbol,const ENUM_TIMEFRAMES timeframe,
                                                     const int jaw_period,
                                                     const int jaw_shift,
                                                     const int teeth_period,
                                                     const int teeth_shift,
                                                     const int lips_period,
                                                     const int lips_shift,
                                                     const ENUM_MA_METHOD ma_method,
                                                     const ENUM_APPLIED_PRICE applied_price)
  {
   MqlParam param[8];
   param[0].type=TYPE_INT;
   param[0].integer_value=jaw_period;
   param[1].type=TYPE_INT;
   param[1].integer_value=jaw_shift;
   param[2].type=TYPE_INT;
   param[2].integer_value=teeth_period;
   param[3].type=TYPE_INT;
   param[3].integer_value=teeth_shift;
   param[4].type=TYPE_INT;
   param[4].integer_value=lips_period;
   param[5].type=TYPE_INT;
   param[5].integer_value=lips_shift;
   param[6].type=TYPE_INT;
   param[6].integer_value=ma_method;
   param[7].type=TYPE_INT;
   param[7].integer_value=applied_price;
   CIndicatorDE *tmp=this.CreateIndicator(IND_ALLIGATOR,param,symbol,timeframe);
   if(tmp==NULL)
      return NULL;
   int index=this.Index(tmp);
   delete tmp;
   return(index>WRONG_VALUE ? this.m_list.At(index) : NULL);
  }
//+------------------------------------------------------------------+

残りのすべては、指標オブジェクトAccumulation/Distributionへのポインタを返す上記のメソッドと同じです。
各メソッドでは、一時的な指標オブジェクトが削除されます。これは必須です。これは、コレクションリストで一致するものを検索するための参照として機能します。

残りの同様の方法は分析しません。これらは、今検討した2つのメソッドと同じです。

これで、この記事の枠内でのクラスの改善は終わりです。


テストEA

EAで指標作成のテストを実行するには、EAを第39部からとり、
新しい\MQL5\Experts\TestDoEasy\Part55\フォルダで新しくTestDoEasyPart55.mq5として保存します。

主に、改善は軽微です。以前の記事の1つで、テスターのイベント処理関数EventsHandling()をライブラリ(ファイルEngine.mqh)に移動しました。したがって、この関数をEAコードから削除し、ハンドラOnTick()で以下のEAファイルからの呼び出し

//--- If work in the tester
   if(MQLInfoInteger(MQL_TESTER))
     {
      engine.OnTimer(rates_data);   // Work in the timer
      PressButtonsControl();        // Button press control
      EventsHandling();             // Work with events
     }

を以下のライブラリからの呼び出しで置き換えます。

//--- If work in the tester
   if(MQLInfoInteger(MQL_TESTER))
     {
      engine.OnTimer(rates_data);   // Work in the timer
      PressButtonsControl();        // Button press control
      engine.EventsHandling();      // Work with events
     }

グラフの現在のバーにデータを含むコメントを表示するコードブロックをハンドラOnTick()から削除します。

//--- Get the zero bar of the current timeseries
   CBar *bar=engine.SeriesGetBar(NULL,PERIOD_CURRENT,0);
   if(bar==NULL)
      return;
//--- Create parameters string of the current bar similar to the one
//--- displayed by the bar object description:
//--- bar.Header()+": "+bar.ParameterDescription()
   string parameters=
     (TextByLanguage("Bar \"")+Symbol()+"\" "+TimeframeDescription((ENUM_TIMEFRAMES)Period())+"[0]: "+TimeToString(bar.Time(),TIME_DATE|TIME_MINUTES|TIME_SECONDS)+
      ", O: "+DoubleToString(engine.SeriesOpen(NULL,PERIOD_CURRENT,0),Digits())+
      ", H: "+DoubleToString(engine.SeriesHigh(NULL,PERIOD_CURRENT,0),Digits())+
      ", L: "+DoubleToString(engine.SeriesLow(NULL,PERIOD_CURRENT,0),Digits())+
      ", C: "+DoubleToString(engine.SeriesClose(NULL,PERIOD_CURRENT,0),Digits())+
      ", V: "+(string)engine.SeriesTickVolume(NULL,PERIOD_CURRENT,0)+
      ", Real: "+(string)engine.SeriesRealVolume(NULL,PERIOD_CURRENT,0)+
      ", Spread: "+(string)engine.SeriesSpread(NULL,PERIOD_CURRENT,0)
     );
//--- Display the data received from the bar object in the first line of the chart comment,
//--- while the second line contains the methods of receiving timeseries price data
   Comment(bar.Header(),": ",bar.ParameterDescription(),"\n",parameters);

「新ティック」イベントハンドラは次のようになります。

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

//--- If work in the tester
   if(MQLInfoInteger(MQL_TESTER))
     {
      engine.OnTimer(rates_data);   // Work in the timer
      PressButtonsControl();        // Button press control
      engine.EventsHandling();      // Work with events
     }

//--- If the trailing flag is set
   if(trailing_on)
     {
      TrailingPositions();          // Trailing positions
      TrailingOrders();             // Trailing of pending orders
     }
  }
//+------------------------------------------------------------------+

ライブラリ初期化関数OnInitDoEasy()の使用済み銘柄リストを表示するブロックで、値で設定された銘柄数

//--- Implement displaying the list of used symbols only for MQL5 - MQL4 has no ArrayPrint() function
#ifdef __MQL5__
   if(InpModeUsedSymbols!=SYMBOLS_MODE_CURRENT)
     {
      string array_symbols[];
      CArrayObj* list_symbols=engine.GetListAllUsedSymbols();
      for(int i=0;i<list_symbols.Total();i++)
        {
         CSymbol *symbol=list_symbols.At(i);
         if(symbol==NULL)
            continue;
         ArrayResize(array_symbols,ArraySize(array_symbols)+1,1000);
         array_symbols[ArraySize(array_symbols)-1]=symbol.Name();
        }
      ArrayPrint(array_symbols);
     }
#endif   

マクロ置き換えで指定された銘柄数で置き換えます。

//--- Implement displaying the list of used symbols only for MQL5 - MQL4 has no ArrayPrint() function
#ifdef __MQL5__
   if(InpModeUsedSymbols!=SYMBOLS_MODE_CURRENT)
     {
      string array_symbols[];
      CArrayObj* list_symbols=engine.GetListAllUsedSymbols();
      for(int i=0;i<list_symbols.Total();i++)
        {
         CSymbol *symbol=list_symbols.At(i);
         if(symbol==NULL)
            continue;
         ArrayResize(array_symbols,ArraySize(array_symbols)+1,SYMBOLS_COMMON_TOTAL);
         array_symbols[ArraySize(array_symbols)-1]=symbol.Name();
        }
      ArrayPrint(array_symbols);
     }
#endif   

MetaTrader 5バージョン2430以降、作業銘柄の総数が変更されています。この数はライブラリによって確認され、ファイル\MQL5\Include\DoEasy\Defines.mqhで宣言されたマクロ置換SYMBOLS_COMMON_TOTALに自動的に設定されます。

一時的かつ指標オブジェクトの作成を確認するためにのみ、同じタイプでパラメータが異なる2つの指標を作成します。プログラムでの指標の通常の作成が実装されない限り、単にライブラリ初期化関数で指標を作成します。

//+------------------------------------------------------------------+
//| Initializing DoEasy library                                  |
//+------------------------------------------------------------------+
void OnInitDoEasy()
  {
//--- Check if working with the full list is selected
   used_symbols_mode=InpModeUsedSymbols;
   if((ENUM_SYMBOLS_MODE)used_symbols_mode==SYMBOLS_MODE_ALL)
     {
      int total=SymbolsTotal(false);
      string ru_n="\nКоличество символов на сервере "+(string)total+".\nМаксимальное количество: "+(string)SYMBOLS_COMMON_TOTAL+" символов.";
      string en_n="\nThe number of symbols on server "+(string)total+".\nMaximal number: "+(string)SYMBOLS_COMMON_TOTAL+" symbols.";
      string caption=TextByLanguage("Attention!");
      string ru="Выбран режим работы с полным списком.\nВ этом режиме первичная подготовка списков коллекций символов и таймсерий может занять длительное время."+ru_n+"\nПродолжить?\n\"Нет\" - работа с текущим символом \""+Symbol()+"\"";
      string en="Full list mode selected.\nIn this mode, the initial preparation of lists of symbol collections and timeseries can take a long time."+en_n+"\nContinue?\n\"No\" - working with the current symbol \""+Symbol()+"\"";
      string message=TextByLanguage(ru,en);
      int flags=(MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2);
      int mb_res=MessageBox(message,caption,flags);
      switch(mb_res)
        {
         case IDNO : 
           used_symbols_mode=SYMBOLS_MODE_CURRENT; 
           break;
         default:
           break;
        }
     }
//--- Set the counter start point to measure the approximate library initialization time
   ulong begin=GetTickCount();
   Print(TextByLanguage("--- Initializing the \"DoEasy\" library ---"));
//--- Fill in the array of used symbols
   CreateUsedSymbolsArray((ENUM_SYMBOLS_MODE)used_symbols_mode,InpUsedSymbols,array_used_symbols);
//--- Set the type of the used symbol list in the symbol collection and fill in the list of symbol timeseries
   engine.SetUsedSymbols(array_used_symbols);
//--- Displaying the selected mode of working with the symbol object collection in the journal
   string num=
     (
      used_symbols_mode==SYMBOLS_MODE_CURRENT ? ": \""+Symbol()+"\"" : 
      TextByLanguage(". Number of used symbols: ",". The number of symbols used: ")+(string)engine.GetSymbolsCollectionTotal()
     );
   Print(engine.ModeSymbolsListDescription(),num);
//--- Implement displaying the list of used symbols only for MQL5 - MQL4 has no ArrayPrint() function
#ifdef __MQL5__
   if(InpModeUsedSymbols!=SYMBOLS_MODE_CURRENT)
     {
      string array_symbols[];
      CArrayObj* list_symbols=engine.GetListAllUsedSymbols();
      for(int i=0;i<list_symbols.Total();i++)
        {
         CSymbol *symbol=list_symbols.At(i);
         if(symbol==NULL)
            continue;
         ArrayResize(array_symbols,ArraySize(array_symbols)+1,SYMBOLS_COMMON_TOTAL);
         array_symbols[ArraySize(array_symbols)-1]=symbol.Name();
        }
      ArrayPrint(array_symbols);
     }
#endif   
//--- Set used timeframes
   CreateUsedTimeframesArray(InpModeUsedTFs,InpUsedTFs,array_used_periods);
//--- Display the selected mode of working with the timeseries object collection
   string mode=
     (
      InpModeUsedTFs==TIMEFRAMES_MODE_CURRENT   ? 
         TextByLanguage("Work only with the current Period: ")+TimeframeDescription((ENUM_TIMEFRAMES)Period())   :
      InpModeUsedTFs==TIMEFRAMES_MODE_LIST      ? 
         TextByLanguage("Work with a predefined list of Periods:")                                              :
      TextByLanguage("Work with the full list of all Periods:")
     );
   Print(mode);
//--- Implement displaying the list of used timeframes only for MQL5 - MQL4 has no ArrayPrint() function
#ifdef __MQL5__
   if(InpModeUsedTFs!=TIMEFRAMES_MODE_CURRENT)
      ArrayPrint(array_used_periods);
#endif 
//--- Create timeseries of all used symbols
   engine.SeriesCreateAll(array_used_periods);
//--- Check created timeseries - display descriptions of all created timeseries in the journal
//--- (true - only created ones, false - created and declared ones)
   engine.GetTimeSeriesCollection().PrintShort(false); // Short descriptions
   //engine.GetTimeSeriesCollection().Print(true);      // Full descriptions

//--- Create indicators
   engine.GetIndicatorsCollection().CreateAMA(Symbol(),Period(),9,2,30,0,PRICE_CLOSE);
   engine.GetIndicatorsCollection().CreateAMA(Symbol(),Period(),10,3,32,5,PRICE_CLOSE);
   engine.GetIndicatorsCollection().Print();
   engine.GetIndicatorsCollection().PrintShort();

//--- Create resource text files
   engine.CreateFile(FILE_TYPE_WAV,"sound_array_coin_01",TextByLanguage("The sound of a falling coin 1"),sound_array_coin_01);
   engine.CreateFile(FILE_TYPE_WAV,"sound_array_coin_02",TextByLanguage("Sound fallen coins"),sound_array_coin_02);
   engine.CreateFile(FILE_TYPE_WAV,"sound_array_coin_03",TextByLanguage("Sound of coins"),sound_array_coin_03);
   engine.CreateFile(FILE_TYPE_WAV,"sound_array_coin_04",TextByLanguage("The sound of a falling coin 2"),sound_array_coin_04);
   engine.CreateFile(FILE_TYPE_WAV,"sound_array_click_01",TextByLanguage("Click on the button sound 1"),sound_array_click_01);
   engine.CreateFile(FILE_TYPE_WAV,"sound_array_click_02",TextByLanguage("Click on the button sound 1"),sound_array_click_02);
   engine.CreateFile(FILE_TYPE_WAV,"sound_array_click_03",TextByLanguage("Click on the button sound 1"),sound_array_click_03);
   engine.CreateFile(FILE_TYPE_WAV,"sound_array_cash_machine_01",TextByLanguage("The sound of the cash machine"),sound_array_cash_machine_01);
   engine.CreateFile(FILE_TYPE_BMP,"img_array_spot_green",TextByLanguage("Image \"Green Spot lamp\""),img_array_spot_green);
   engine.CreateFile(FILE_TYPE_BMP,"img_array_spot_red",TextByLanguage("Image \"Red Spot lamp\""),img_array_spot_red);

//--- Pass all existing collections to the main library class
   engine.CollectionOnInit();

//--- Set the default magic number for all used symbols
   engine.TradingSetMagic(engine.SetCompositeMagicNumber(magic_number));
//--- Set synchronous passing of orders for all used symbols
   engine.TradingSetAsyncMode(false);
//--- Set the number of trading attempts in case of an error
   engine.TradingSetTotalTry(InpTotalAttempts);
//--- Set correct order expiration and filling types to all trading objects
   engine.TradingSetCorrectTypeExpiration();
   engine.TradingSetCorrectTypeFilling();

//--- Set standard sounds for trading objects of all used symbols
   engine.SetSoundsStandart();
//--- Set the general flag of using sounds
   engine.SetUseSounds(InpUseSounds);
//--- Set the spread multiplier for symbol trading objects in the symbol collection
   engine.SetSpreadMultiplier(InpSpreadMultiplier);
      
//--- Set controlled values for symbols
   //--- Get the list of all collection symbols
   CArrayObj *list=engine.GetListAllUsedSymbols();
   if(list!=NULL && list.Total()!=0)
     {
      //--- In a loop by the list, set the necessary values for tracked symbol properties
      //--- By default, the LONG_MAX value is set to all properties, which means "Do not track this property” 
      //--- It can be enabled or disabled (set the value less than LONG_MAX or vice versa - set the LONG_MAX value) at any time and anywhere in the program
      /*
      for(int i=0;i<list.Total();i++)
        {
         CSymbol* symbol=list.At(i);
         if(symbol==NULL)
            continue;
        //--- Set control of the symbol price increase to 100 points
         symbol.SetControlBidInc(100000*symbol.Point());
        //--- Set control of the symbol price decrease to 100 points
         symbol.SetControlBidDec(100000*symbol.Point());
        //--- Set control of the symbol spread increase to 40 points
         symbol.SetControlSpreadInc(400);
        //--- Set control of the symbol spread decrease to 40 points
         symbol.SetControlSpreadDec(400);
        //--- Set control of the current spread by the value of 40 points
         symbol.SetControlSpreadLevel(400);
        }
      */
     }
//--- Set controlled values for the current account
   CAccount* account=engine.GetAccountCurrent();
   if(account!=NULL)
     {
      //--- Set control of the profit increase to 10
      account.SetControlledValueINC(ACCOUNT_PROP_PROFIT,10.0);
      //--- Set control of the funds increase to 15
      account.SetControlledValueINC(ACCOUNT_PROP_EQUITY,15.0);
      //--- Set profit control level to 20
      account.SetControlledValueLEVEL(ACCOUNT_PROP_PROFIT,20.0);
     }
//--- Get the end of the library initialization time counting and display it in the journal
   ulong end=GetTickCount();
   Print(TextByLanguage("Library initialization time: "),TimeMSCtoString(end-begin,TIME_MINUTES|TIME_SECONDS));
  }
//+------------------------------------------------------------------+

ここでは、現在の銘柄と時間枠で入力値が異なる適応移動平均の2つの指標を作成しました。

EAをコンパイルして、ターミナルのチャート上で起動します。
初期化後、「エキスパート」操作ログには、初期化に関するライブラリメッセージが表示されます。それらの中には、作成された2つの指標のパラメータの完全リストと短縮リストがあります。

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 with a predefined list of Periods:
"H1" "H4"
Symbol time series EURUSD: 
- Timeseries "EURUSD" H1: Required: 1000, Actual: 1000, Created: 1000, On server: 6350
- Timeseries "EURUSD" H4: Required: 1000, Actual: 1000, Created: 1000, On server: 6255
============= The beginning of the event parameter list: "Standard indicator" =============
Indicator status: Standard indicator
Indicator type: AMA
Indicator timeframe: H1
Indicator handle: 10
Indicator group: Trend indicator
------
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 event parameter list: "Standard indicator" =============
Indicator status: Standard indicator
Indicator type: AMA
Indicator timeframe: H1
Indicator handle: 11
Indicator group: Trend indicator
------
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: 10
- Fast MA period: 3
- Slow MA period: 32
- Horizontal shift of the indicator: 5
- Price type or handle: CLOSE
================== End of the parameter list: "Standard indicator" ==================
 
Standard indicator Adaptive Moving Average EURUSD H1 [10]
Standard indicator Adaptive Moving Average EURUSD H1 [11]
Library initialization time: 00:00:00.000

指標の種類は1つ(AMA)ですが、作成された指標のパラメータが異なるため、この指標の2つのハンドルが作成されます。したがって、これらはそれぞれにハンドルがある2つの異なる指標です。それぞれ、2つの指標オブジェクトが作成され、指標コレクションに配置されます。

一方、異なるパラメータで異なる指標を作成することしかできません。ただし、EAに適用するには、データを保存するための領域を用意する必要があります。その領域から、パラメータの必要な組み合わせのデータを受信し、プログラムで使用して、意思決定を行ったり、統計データを取得したりできます。次の記事からこれらすべてのことを始めます。

次の段階

次の記事では、EAでのデータストレージの実装と指標オブジェクトからの受信を開始します。

ライブラリの現在のバージョンのすべてのファイルは、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部): 抽象基本指標の子孫クラス

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

添付されたファイル |
MQL5.zip (3856.21 KB)
DoEasyライブラリの時系列(第54部): 抽象基本指標の子孫クラス DoEasyライブラリの時系列(第54部): 抽象基本指標の子孫クラス

本稿では、基本抽象指標の子孫オブジェクトのクラスの作成について検討しています。このようなオブジェクトは、指標EAを作成し、さまざまな指標と価格のデータ値統計を収集および取得する機能へのアクセスを備えています。また、プログラムで作成された各指標のプロパティとデータにアクセスできる指標オブジェクトコレクションを作成します。

パターン検索への総当たり攻撃アプローチ パターン検索への総当たり攻撃アプローチ

本稿では、市場パターンを検索し、特定されたパターンに基づいてエキスパートアドバイザーを作成し、これらのパターンが有効であるかどうかを確認します。

DoEasyライブラリの時系列(第56部):カスタム指標オブジェクト、コレクション内指標オブジェクトからのデータ取得 DoEasyライブラリの時系列(第56部):カスタム指標オブジェクト、コレクション内指標オブジェクトからのデータ取得

本稿では、EAで使用するためのカスタム指標オブジェクトの作成について検討します。ライブラリクラスを少し改善し、EAの指標オブジェクトからデータを取得するメソッドを追加しましょう。

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

本稿では、1つの指標に対して1つのバッファのすべてのデータを含むオブジェクトを開発します。このようなオブジェクトは、指標バッファのシリアルデータを格納するために必要になります。その助けを借りて、任意の指標のバッファデータ、および他の同様のデータを相互に並べ替えて比較できるようになります。