DoEasyライブラリでの価格(第61部): 銘柄ティックシリーズのコレクション

Artyom Trishkin | 4 5月, 2021

内容


概念

前回の記事で、指定された日数の間銘柄ティックを収集して保存するティックデータリストオブジェクトクラスを作成しました。プログラムでは作業に異なる銘柄を使用する可能性があるため、それぞれに個別のリストを作成する必要があります。本稿では、そのようなリストを組み合わせてティックデータコレクションにします。これは、CObjectクラスインスタンスへのポインタの動的配列および標準ライブラリの子孫に基づく通常のリストになります。このリストは、各銘柄に対して作成されたティックデータリストへのポインタを格納するためのものです。そのオブジェクトクラスは前の記事で準備しました。

概念は、ライブラリ内の以前のコレクションクラスを構築する概念と同じです。これにより、ライブラリデータベースに存在する銘柄のティックデータを統計分析で保存、格納、更新、受信、使用できるようになります。


ティックデータのクラスコレクション

\MQL5\Include\DoEasy\Collections\で、TickSeriesCollection.mqhという名前の新しいティックデータコレクションクラスファイルを作成します。

このクラスは、すべてのライブラリオブジェクトの基本オブジェクトのクラスの子孫になります。

クラス本体を見て、その変数とメソッドを分析してみましょう。

//+------------------------------------------------------------------+
//|                                         TickSeriesCollection.mqh |
//|                        Copyright 2021, MetaQuotes Software Corp. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Software Corp."
#property link      "https://mql5.com/en/users/artmedia70"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "ListObj.mqh"
#include "..\Objects\Ticks\TickSeries.mqh"
#include "..\Objects\Symbols\Symbol.mqh"
//+------------------------------------------------------------------+
//| Collection of symbol tick series                                 |
//+------------------------------------------------------------------+
class CTickSeriesCollection : public CBaseObj
  {
private:
   CListObj                m_list;                                   // List of used symbol tick series
//--- Return the tick series index by symbol name
   int                     IndexTickSeries(const string symbol);
public:
//--- Return (1) itself and (2) tick series collection list and (3) the number of tick series in the list
   CTickSeriesCollection  *GetObject(void)                              { return &this;               }
   CArrayObj              *GetList(void)                                { return &this.m_list;        }
   int                     DataTotal(void)                        const { return this.m_list.Total(); }
//--- Return the pointer to the tick series object (1) by symbol and (2) by index in the list
   CTickSeries            *GetTickseries(const string symbol);
   CTickSeries            *GetTickseries(const int index);
//--- Create a collection list of symbol tick series
   bool                    CreateCollection(const CArrayObj *list_symbols,const uint required=0);
//--- Set the flag of using the tick series of (1) a specified symbol and (2) all symbols
   void                    SetAvailableTickSeries(const string symbol,const bool flag=true);
   void                    SetAvailableTickSeries(const bool flag=true);
//--- Return the flag of using the tick series of (1) a specified symbol and (2) all symbols
   bool                    IsAvailableTickSeries(const string symbol);
   bool                    IsAvailableTickSeries(void);

//--- Set the number of days of the tick history of (1) a specified symbol and (2) all symbols
   bool                    SetRequiredUsedDays(const string symbol,const uint required=0);
   bool                    SetRequiredUsedDays(const uint required=0);

//--- Return the last tick object of a specified symbol (1) by index, (2) by time and (4) by time in milliseconds
   CDataTick              *GetTick(const string symbol,const int index);
   CDataTick              *GetTick(const string symbol,const datetime tick_time);
   CDataTick              *GetTick(const string symbol,const long tick_time_msc);

//--- Return the new tick flag of a specified symbol
   bool                    IsNewTick(const string symbol);

//--- Create a tick series of (1) a specified symbol and (2) all symbols
   bool                    CreateTickSeries(const string symbol,const uint required=0);
   bool                    CreateTickSeriesAll(const uint required=0);
//--- Update (1) a tick series of a specified symbol and (2) all symbols
   void                    Refresh(const string symbol);
   void                    Refresh(void);

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

m_listクラスのメンバー変数はCListObj型です。これは、ライブラリで作成された他の多くのリストと同様に、標準ライブラリのCArrayObjクラスの子孫です。CListObjクラスの唯一の目的は、標準ライブラリオブジェクトの基本クラスであるCObjectクラスのType()仮想メソッドの作業を実装することです。メソッドはクラスタイプIDを返す必要があります。この場合、それは配列タイプIDです。
Type()仮想メソッドは、かなり前にライブラリに追加されたCListObjクラスに実装されています。

//+------------------------------------------------------------------+
//|                                                      ListObj.mqh |
//|                        Copyright 2019, MetaQuotes Software Corp. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, MetaQuotes Software Corp."
#property link      "https://mql5.com/en/users/artmedia70"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include <Arrays\ArrayObj.mqh>
//+------------------------------------------------------------------+
//| Class of collection lists                                        |
//+------------------------------------------------------------------+
class CListObj : public CArrayObj
  {
private:
   int               m_type;                    // List type
public:
   void              Type(const int type)       { this.m_type=type;     }
   virtual int       Type(void)           const { return(this.m_type);  }
                     CListObj()                 { this.m_type=0x7778;   }
  };
//+------------------------------------------------------------------+

ここで、Type()メソッドは渡された値をm_type変数に設定し、Type()仮想メソッドはこの変数によって設定された値を返します 。

デフォルトでは(クラスコンストラクタ内)、変数はCArrayObjの場合と同じ配列型IDの値(0x7778)を受け取ります。

すべてのクラスメソッドの目的は、コードコメントに記載されています。これらのメソッドの実装については、以下で説明します。

クラスコンストラクタリストをクリアし、並び替え済みリストフラグを設定し、ティックデータコレクションリストIDを定義します

//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CTickSeriesCollection::CTickSeriesCollection()
  {
   this.m_list.Clear();
   this.m_list.Sort();
   this.m_list.Type(COLLECTION_TICKSERIES_ID);
  }
//+------------------------------------------------------------------+

IndexTickSeries()privateメソッドは、銘柄名によってティックシリーズインデックスを返します。

//+------------------------------------------------------------------+
//| Return the tick series index by symbol name                      |
//+------------------------------------------------------------------+
int CTickSeriesCollection::IndexTickSeries(const string symbol)
  {
   const CTickSeries *obj=new CTickSeries(symbol==NULL || symbol=="" ? ::Symbol() : symbol);
   if(obj==NULL)
      return WRONG_VALUE;
   this.m_list.Sort();
   int index=this.m_list.Search(obj);
   delete obj;
   return index;
  }
//+------------------------------------------------------------------+

このメソッドは、ティックシリーズインデックスをリストから返す必要がある銘柄の名前を受け取ります。
次に、ティックシリーズの一時的な空のオブジェクトを作成します。これには、メソッドに渡される銘柄の名前が備わります
並び替え済みリストフラグを設定
してリスト内のオブジェクトインデックスを検索します
次に、一時オブジェクトを削除し、取得したインデックスを返します。オブジェクトが見つからないまたは一時オブジェクトの作成に失敗した場合、メソッドはNULLを返します。

以下は、銘柄によってティックシリーズオブジェクトへのポインタを返すメソッドです。

//+------------------------------------------------------------------+
//| Return the object of tick series of a specified symbol           |
//+------------------------------------------------------------------+
CTickSeries *CTickSeriesCollection::GetTickseries(const string symbol)
  {
   int index=this.IndexTickSeries(symbol);
   return this.m_list.At(index);
  }
//+------------------------------------------------------------------+

このメソッドは、ティックシリーズオブジェクトをリストから返す必要がある銘柄の名前を受け取ります。
今説明したメソッドを使用してリスト内のティックシリーズオブジェクトのインデックスを検索して、見つかったインデックスによってオブジェクトへのポインタを取得し、それを返します。インデックスが見つからなかった場合、インデックスは-1に等しくなり、CArrayObjクラスのAt()メソッドNULLを返します。

以下は、指定された銘柄のティックシリーズを使用するフラグを設定するメソッドです。

//+------------------------------------------------------------------+
//| Set the flag of using the tick series of a specified symbol      |
//+------------------------------------------------------------------+
void CTickSeriesCollection::SetAvailableTickSeries(const string symbol,const bool flag=true)
  {
   CTickSeries *tickseries=this.GetTickseries(symbol);
   if(tickseries==NULL)
      return;
   tickseries.SetAvailable(flag);
  }
//+------------------------------------------------------------------+

このメソッドは、ティックシリーズオブジェクトが使用フラグを受け取る必要がある銘柄の名前を受け取ります。
上記のGetTickseries()メソッドを使用して、リストからティックシリーズオブジェクトへのポインタを取得し、メソッドに渡されるフラグを設定します

以下は、すべてのコレクション銘柄のティックシリーズの使用フラグを設定するメソッドです。

//+------------------------------------------------------------------+
//| Set the flag of using the tick series of all symbols             |
//+------------------------------------------------------------------+
void CTickSeriesCollection::SetAvailableTickSeries(const bool flag=true)
  {
   for(int i=0;i<this.m_list.Total();i++)
     {
      CTickSeries *tickseries=this.m_list.At(i);
      if(tickseries==NULL)
         continue;
      tickseries.SetAvailable(flag);
     }
  }
//+------------------------------------------------------------------+

リスト内のティックシリーズの総数によるループで、ループインデックスによって次のティックシリーズオブジェクトを取得し、メソッドに渡されるフラグを設定します

以下は、指定された銘柄のティックシリーズを使用するフラグを返すメソッドです。

//+------------------------------------------------------------------+
//| Return the flag of using the tick series of a specified symbol   |
//+------------------------------------------------------------------+
bool CTickSeriesCollection::IsAvailableTickSeries(const string symbol)
  {
   CTickSeries *tickseries=this.GetTickseries(symbol);
   if(tickseries==NULL)
      return false;
   return tickseries.IsAvailable();
  }
//+------------------------------------------------------------------+

このメソッドは、ティックシリーズオブジェクト使用フラグを返す必要がある銘柄の名前を受け取ります。
GetTickseries()メソッドを使用して、必要な銘柄のティックシリーズオブジェクトへのポインタを取得しこのオブジェクトに設定された使用フラグを返します。リストからオブジェクトを取得できなかった場合、メソッドはfalseを返します。

以下は、すべての銘柄のティックシリーズを使用するフラグを返すメソッドです。

//+------------------------------------------------------------------+
//| Return the flag of using tick series of all symbols              |
//+------------------------------------------------------------------+
bool CTickSeriesCollection::IsAvailableTickSeries(void)
  {
   bool res=true;
   int total=this.m_list.Total();
   for(int i=0;i<total;i++)
     {
      CTickSeries *tickseries=this.m_list.At(i);
      if(tickseries==NULL)
         continue;
      res &=tickseries.IsAvailable();
     }
   return res;
  }
//+------------------------------------------------------------------+

res変数を宣言し、true値を使用して初期化します。
次に、リスト内のオブジェクトの総数によるループで次のティックシリーズオブジェクトへのポインタを取得し、現在のオブジェクトに定義されている使用フラグをres変数に追加します
ループが完了したら、取得したresの値を返します

リスト内のオブジェクトの少なくとも1つに使用フラグが設定されていない場合(false)、ループの完了時にresfalseを格納します。したがって、このメソッドでは、すべてのティックシリーズに使用フラグが設定されているかどうかを知ることができます。Trueは、コレクション内のティックシリーズオブジェクトごとに使用フラグがtrueに設定されている場合にのみ返されます。

以下は、指定された銘柄のティック履歴の日数を設定するメソッドです。

//+------------------------------------------------------------------+
//| Set the number of days of the tick history of a specified symbol |
//+------------------------------------------------------------------+
bool CTickSeriesCollection::SetRequiredUsedDays(const string symbol,const uint required=0)
  {
   CTickSeries *tickseries=this.GetTickseries(symbol);
   if(tickseries==NULL)
      return false;
   tickseries.SetRequiredUsedDays(required);
   return true;
  }
//+------------------------------------------------------------------+

このメソッドは、ティックデータの日数を設定する必要がある銘柄の名前を受け取ります。
以前に検討した方法を使用してティックシリーズオブジェクトへのポインタを取得し、オブジェクトの日数を設定し、trueを返します
リストからティックシリーズオブジェクトへのポインタを取得できなかった場合、メソッドはfalseを返します。

以下は、すべての銘柄のティック履歴の日数を設定するメソッドです。

//+------------------------------------------------------------------+
//| Set the number of days of the tick history of all symbols        |
//+------------------------------------------------------------------+
bool CTickSeriesCollection::SetRequiredUsedDays(const uint required=0)
  {
   bool res=true;
   for(int i=0;i<this.m_list.Total();i++)
     {
      CTickSeries *tickseries=this.m_list.At(i);
      if(tickseries==NULL)
        {
         res &=false;
         continue;
        }
      tickseries.SetRequiredUsedDays(required);
     }
   return res;
  }
//+------------------------------------------------------------------+

res変数を宣言し、true値を使用して初期化します。
次に、リスト内のオブジェクトの総数によるループ内で次のティックシリーズオブジェクトへのポインタを取得してオブジェクトへのポインタの取得に失敗した場合、res変数はfalseを取得します。次に、コレクションリストの次のオブジェクトに移動します
それ以外の場合は、現在のオブジェクトのティックデータの日数を設定します
ループが完了したら、取得したresの値を返します

リスト内のオブジェクトの少なくとも1つにティックデータの日数が設定されていない場合、resはループの完了時にfalseを格納します。したがって、このメソッドでは、コレクション内のすべてのティックシリーズの日数を設定でき、リストに格納されている各ティックデータオブジェクトに日数が設定されている場合にのみ、正常に実行されます。

以下は、指定された銘柄のティックオブジェクトをティックシリーズリストのインデックスで返すメソッドです。

//+------------------------------------------------------------------+
//| Return the tick object of the specified symbol by index          |
//+------------------------------------------------------------------+
CDataTick *CTickSeriesCollection::GetTick(const string symbol,const int index)
  {
   CTickSeries *tickseries=this.GetTickseries(symbol);
   if(tickseries==NULL)
      return NULL;
   return tickseries.GetTickByListIndex(index);
  }
//+------------------------------------------------------------------+

このメソッドは、CTickSeriesクラスのティックシリーズ銘柄とティックシリーズリストに格納されている必要なティックオブジェクトのインデックスを渡します。
前述したGetTickseries()メソッドを使用して銘柄コレクションからティックシリーズオブジェクトへのポインタを取得し、前回の記事で検討したGetTickByListIndex()メソッドを使用してティックシリーズリストからティックオブジェクトへのポインタを返します

ティックシリーズオブジェクトの取得に失敗した場合、メソッドはNULLを返します。CTickSeriesクラスのGetTickByListIndex()メソッドもNULLを返す場合があります。

以下は、指定された銘柄の最後のティックオブジェクトをティックシリーズリストから時間によって返すメソッドです。

//+------------------------------------------------------------------+
//| Return the last tick object of the specified symbol by time      |
//+------------------------------------------------------------------+
CDataTick *CTickSeriesCollection::GetTick(const string symbol,const datetime tick_time)
  {
   CTickSeries *tickseries=this.GetTickseries(symbol);
   if(tickseries==NULL)
      return NULL;
   return tickseries.GetTick(tick_time);
  }
//+------------------------------------------------------------------+

このメソッドは、CTickSeriesクラスのティックシリーズ銘柄と、ティックシリーズリストに格納されている必要なティックオブジェクトの時刻を渡します。
前述したGetTickseries()メソッドを使用して銘柄コレクションからティックシリーズオブジェクトへのポインタを取得し、前回の記事で検討したGetTick()メソッドを使用してティックシリーズリストからティックオブジェクトへのポインタを返します

ティックシリーズオブジェクトの取得に失敗した場合、メソッドはNULLを返します。さらに、CTickSeriesクラスのGetTick(メソッドもNULLを返す場合があります。

以下は、指定された銘柄の最後のティックオブジェクトを、ティックシリーズリストからミリ秒単位の時間で返すメソッドです。

//+------------------------------------------------------------------+
//| Return the last tick object of the specified symbol              |
//| by time in milliseconds                                          |
//+------------------------------------------------------------------+
CDataTick *CTickSeriesCollection::GetTick(const string symbol,const long tick_time_msc)
  {
   CTickSeries *tickseries=this.GetTickseries(symbol);
   if(tickseries==NULL)
      return NULL;
   return tickseries.GetTick(tick_time_msc);
  }
//+------------------------------------------------------------------+

このメソッドは、CTickSeriesクラスのティックシリーズ銘柄と、ティックシリーズリストに格納されている必要なティックオブジェクトの時間をミリ秒単位で受け取ります。
前述したGetTickseries()メソッドを使用して銘柄コレクションからティックシリーズオブジェクトへのポインタを取得し、前回の記事で検討したGetTick()メソッドを使用してティックシリーズリストからティックオブジェクトへのポインタを返します

ティックシリーズオブジェクトの取得に失敗した場合、メソッドはNULLを返します。さらに、CTickSeriesクラスのGetTick(メソッドもNULLを返す場合があります。

ティックオブジェクトを時間ごとに返す最後の2つのメソッドには、同じ時間のティックがいくつかある可能性があるため、CTickSeriesクラスのGetTick()メソッドは、それらの最後(最新の時間)を最も関連性の高いものとして返します。

以下は、指定された銘柄の新しいティックフラグを返すメソッドです。

//+------------------------------------------------------------------+
//| Return the new tick flag of a specified symbol                   |
//+------------------------------------------------------------------+
bool CTickSeriesCollection::IsNewTick(const string symbol)
  {
   CTickSeries *tickseries=this.GetTickseries(symbol);
   if(tickseries==NULL)
      return false;
   return tickseries.IsNewTick();
  }
//+------------------------------------------------------------------+

このメソッドは、新しいティックの出現フラグを返す必要がある銘柄の名前を受け取ります。
前述したGetTickseries()メソッドを使用して銘柄コレクションからティックシリーズオブジェクトへのポインタを取得し、前回の記事で検討したCTickSeriesクラスのIsNewTick()メソッドを使用してティックシリーズの新しいティックのフラグを返します。
ティックシリーズオブジェクトの取得に失敗した場合、メソッドはfalseを返します。

この機能は、CTickSeriesクラスにはまだ実装されていません。これは、今後の記事で行われます。

以下は、指定された銘柄のティックシリーズを作成するメソッドです。

//+------------------------------------------------------------------+
//| Create a tick series of a specified symbol                       |
//+------------------------------------------------------------------+
bool CTickSeriesCollection::CreateTickSeries(const string symbol,const uint required=0)
  {
   CTickSeries *tickseries=this.GetTickseries(symbol);
   if(tickseries==NULL)
      return false;
   return(tickseries.Create(required)>0);
  }
//+------------------------------------------------------------------+

このメソッドは、ティックシリーズを作成する必要がある銘柄の名前とティックデータの日数を受け取ります。
前述のGetTickseries()メソッドを使用して銘柄コレクションからティックシリーズオブジェクトへのポインタを取得しCTickSeriesクラスのCreate()メソッドがゼロより大きい値を返したことを示すフラグを返します(作成されたティックオブジェクトの数はゼロではありません)。

以下は、使用されているすべての銘柄のティックシリーズを作成するメソッドです。

//+------------------------------------------------------------------+
//| Create tick series of all symbols                                |
//+------------------------------------------------------------------+
bool CTickSeriesCollection::CreateTickSeriesAll(const uint required=0)
  {
   bool res=true;
   int total=this.m_list.Total();
   for(int i=0;i<total;i++)
     {
      CTickSeries *tickseries=this.m_list.At(i);
      if(tickseries==NULL)
         continue;
      res &=(tickseries.Create(required)>0);
     }
   return res;
  }
//+------------------------------------------------------------------+

このメソッドは、ティックデータの日数を受け取ります。
res変数を宣言し、true値を使用して初期化します。
次に、リスト内のオブジェクトの総数によるループで、次のティックシリーズオブジェクトへのポインタを取得してCTickSeriesクラスのCreate()メソッドによって返される値がゼロより大きい(ティックシリーズが作成されている)ことを示すフラグをres変数に追加します。
ループが完了したら、取得したresの値を返します

リスト内のオブジェクトの少なくとも1つに対してティックシリーズが作成されていない場合、resはループの完了時にfalseを格納します。したがって、このメソッドでは、すべての銘柄のティックシリーズコレクションを作成でき、リストに格納されているティックデータオブジェクトごとにティックシリーズが作成された場合にのみ、正常な実行を返します。

以下は、指定された銘柄のティックシリーズを更新するメソッドです。

//+------------------------------------------------------------------+
//| Update a tick series of a specified symbol                       |
//+------------------------------------------------------------------+
void CTickSeriesCollection::Refresh(const string symbol)
  {
   CTickSeries *tickseries=this.GetTickseries(symbol);
   if(tickseries==NULL)
      return;
   tickseries.Refresh();
  }
//+------------------------------------------------------------------+

メソッドは、ティックシリーズを更新する必要がある銘柄名を受け取ります。
前述のGetTickseries()メソッドを使用して銘柄コレクションからティックシリーズオブジェクトへのポインタを取得し、CTickSeriesクラスのRefresh()メソッドを使用して更新します

以下は、すべての銘柄のティックシリーズを更新するメソッドです。

//+------------------------------------------------------------------+
//| Update tick series of all symbols                                |
//+------------------------------------------------------------------+
void CTickSeriesCollection::Refresh(void)
  {
   for(int i=0;i<this.m_list.Total();i++)
     {
      CTickSeries *tickseries=this.m_list.At(i);
      if(tickseries==NULL)
         continue;
      tickseries.Refresh();
     }
  }
//+------------------------------------------------------------------+

リスト内のオブジェクトの総数によるループで、ループインデックスによって次のティックシリーズオブジェクトへのポインタを取得して、CTickSeriesクラスのRefresh()メソッドを使用してシリーズを更新します

ティックシリーズの更新は、CTickSeriesクラスにはまだ実装されていません。これは、今後の記事で行われます。

以下は、完全なコレクションリストを操作ログに返すメソッドです。

//+------------------------------------------------------------------+
//| Display complete collection description to the journal           |
//+------------------------------------------------------------------+
void CTickSeriesCollection::Print(void)
  {
   for(int i=0;i<this.m_list.Total();i++)
     {
      CTickSeries *tickseries=this.m_list.At(i);
      if(tickseries==NULL)
         continue;
      tickseries.Print();
     }
  }
//+------------------------------------------------------------------+

リスト内のオブジェクトの総数によるループで、ループインデックスによって次のティックシリーズオブジェクトへのポインタを取得して操作ログのティックシリーズの完全な説明を表示します

以下は、短いコレクションリストを操作ログに返すメソッドです。

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

リスト内のオブジェクトの総数によるループで、 ループインデックスによって次のティックシリーズオブジェクトへのポインタを取得して操作ログのティックシリーズの完全な説明を表示します

上記で検討したメソッドは、さまざまな銘柄のティックデータオブジェクトへのポインタの作成済みコレクションリストを使用するためのものです。私たちのプログラムは異なる銘柄を使用する場合があります。次のメソッドを使用して、コレクションオブジェクト自体を作成し、必要なすべてのティックシリーズをその中に配置し、コレクションリストから適切なポインタを取得して使用します。

以下は、銘柄ティックシリーズのコレクションリストを作成するメソッドです。

//+------------------------------------------------------------------+
//| Create a collection list of symbol tick series                   |
//+------------------------------------------------------------------+
bool CTickSeriesCollection::CreateCollection(const CArrayObj *list_symbols,const uint required=0)
  {
//--- If an empty list of symbol objects is passed, exit
   if(list_symbols==NULL)
      return false;
//--- Get the number of symbol objects in the passed list
   int total=list_symbols.Total();
//--- Clear the tick series collection list
   this.m_list.Clear();
//--- In a loop by all symbol objects
   for(int i=0;i<total;i++)
     {
      //--- get the next symbol object
      CSymbol *symbol_obj=list_symbols.At(i);
      //--- if failed to get a symbol object, move on to the next one in the list
      if(symbol_obj==NULL)
         continue;
      //--- Create a new empty tick series object
      CTickSeries *tickseries=new CTickSeries();
      //--- If failed to create the tick series object, move on to the next symbol in the list
      if(tickseries==NULL)
         continue;
      //--- Set a symbol name for a tick series object
      tickseries.SetSymbol(symbol_obj.Name());
      //--- Set the sorted list flag for the tick series collection list
      this.m_list.Sort();
      //--- If the object with the same symbol name is already present in the tick series collection list, remove the tick series object
      if(this.m_list.Search(tickseries)>WRONG_VALUE)
         delete tickseries;
      //--- otherwise, there is no object with such a symbol name in the collection yet
      else
        {
         //--- Set the number of tick data days for a tick series object
         tickseries.SetRequiredUsedDays(required);
         //--- if failed to add the tick series object to the collection list, remove the tick series object
         if(!this.m_list.Add(tickseries))
            delete tickseries;
        } 
     }
//--- Return the flag indicating that the created collection list has a size greater than zero
   return this.m_list.Total()>0;
  }
//+------------------------------------------------------------------+

このメソッドは非常に単純です。プログラムで使用される銘柄のリストを受け取ります(リストはすでにかなり長い間存在しており、銘柄の時系列コレクションを作成するときに使用されます)。次に、銘柄の総数によるループで、新しいティックシリーズオブジェクトを作成し、現在のループ位置にある銘柄のリストからその銘柄名を設定します。このような銘柄が付いたティックシリーズオブジェクトがまだリストに存在しない場合は、メソッドに渡されるティックデータの日数を設定し、オブジェクトをコレクションリストに追加します。これは、リスト内の銘柄ごとに実行する必要があります。ここでは、システムの概要を簡単に説明しました。さらに深く掘り下げると、作成が成功したかどうかのチェックが表示され、ティックシリーズオブジェクトがリストに追加され、必要に応じて不要なオブジェクトが削除されます。メソッドロジック全体は、そのリストで詳細に説明されています。分析はお任せします。

CEngineメインライブラリクラスは、作成されたコレクションを「外の世界」に接続するために使用されます。
クラスは\MQL5\Include\DoEasy\Engine.mqhに保存されます。

新しく作成されたクラスのファイルをそれに接続します

//+------------------------------------------------------------------+
//|                                                       Engine.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 "Services\TimerCounter.mqh"
#include "Collections\HistoryCollection.mqh"
#include "Collections\MarketCollection.mqh"
#include "Collections\EventsCollection.mqh"
#include "Collections\AccountsCollection.mqh"
#include "Collections\SymbolsCollection.mqh"
#include "Collections\ResourceCollection.mqh"
#include "Collections\TimeSeriesCollection.mqh"
#include "Collections\BuffersCollection.mqh"
#include "Collections\IndicatorsCollection.mqh"
#include "Collections\TickSeriesCollection.mqh"
#include "TradingControl.mqh"
//+------------------------------------------------------------------+

クラスのprivateセクションでティックシリーズコレクションクラスオブジェクトを宣言します

//+------------------------------------------------------------------+
//| Library basis class                                              |
//+------------------------------------------------------------------+
class CEngine
  {
private:
   CHistoryCollection   m_history;                       // Collection of historical orders and deals
   CMarketCollection    m_market;                        // Collection of market orders and deals
   CEventsCollection    m_events;                        // Event collection
   CAccountsCollection  m_accounts;                      // Account collection
   CSymbolsCollection   m_symbols;                       // Symbol collection
   CTimeSeriesCollection m_time_series;                  // Timeseries collection
   CBuffersCollection   m_buffers;                       // Collection of indicator buffers
   CIndicatorsCollection m_indicators;                   // Indicator collection
   CTickSeriesCollection m_tick_series;                  // Collection of tick series
   CResourceCollection  m_resource;                      // Resource list
   CTradingControl      m_trading;                       // Trading management object
   CPause               m_pause;                         // Pause object
   CArrayObj            m_list_counters;                 // List of timer counters

このクラスは、SetUsedSymbols()メソッドを備えており、プログラムで使用する銘柄のリストを設定できます。
ライブラリにティックデータが必要な日数を渡すようにします。

//--- Set the list of used symbols in the symbol collection and create the collection of symbol timeseries
   bool                 SetUsedSymbols(const string &array_symbols[],const uint required=0);

デフォルトでは、ゼロが渡され(1日を意味します)、TICKSERIES_DEFAULT_DAYS_COUNT定数によって\MQL5\Include\DoEasy\Defines.mqhに設定されます。

メソッドの実装で、ティックシリーズのコレクションの作成を追加します。

//+------------------------------------------------------------------+
//| Set the list of used symbols in the symbol collection            |
//| and create the symbol timeseries collection                      |
//+------------------------------------------------------------------+
bool CEngine::SetUsedSymbols(const string &array_symbols[],const uint required=0)
  {
   bool res=this.m_symbols.SetUsedSymbols(array_symbols);
   CArrayObj *list=this.GetListAllUsedSymbols();
   if(list==NULL)
      return false;
   res&=this.m_time_series.CreateCollection(list);
   res&=this.m_tick_series.CreateCollection(list,required);
   return res;
  }
//+------------------------------------------------------------------+

これで、プログラムからメソッドを呼び出すときに2つのコレクション(時系列コレクションとティックシリーズコレクション)が作成されます。

クラスのpublicセクションに、カスタムプログラムからティックシリーズコレクションクラスにアクセスするためのメソッドを追加します

//--- Copy the specified double property of the specified timeseries of the specified symbol to the array
//--- Regardless of the array indexing direction, copying is performed the same way as copying to a timeseries array
   bool                 SeriesCopyToBufferAsSeries(const string symbol,const ENUM_TIMEFRAMES timeframe,const ENUM_BAR_PROP_DOUBLE property,
                                                   double &array[],const double empty=EMPTY_VALUE)
                          { return this.m_time_series.CopyToBufferAsSeries(symbol,timeframe,property,array,empty);}


//--- Return (1) the tick series collection, (2) the list of tick series from the tick series collection
   CTickSeriesCollection *GetTickSeriesCollection(void)                       { return &this.m_tick_series;                                     }
   CArrayObj           *GetListTickSeries(void)                               { return this.m_tick_series.GetList();                            }


//--- Return (1) the buffer collection and (2) the buffer list from the collection 

今のところ、ティックシリーズコレクションオブジェクト自体そこからのコレクションリストをプログラムに返すだけで十分です。

現在、ティックシリーズコレクションを作成するために必要なのはこれだけです。


検証

銘柄プログラム操作のためのティックシリーズコレクションの作成をテストするために、前の記事からEAを取得して\MQL5\Experts\TestDoEasy\Part61\TestDoEasyPart61.mq5として保存します。

これで、すべてのティックシリーズがライブラリ自体から利用できるようになったので、プログラムからクラスファイルのインクルードを削除しましょう。

//+------------------------------------------------------------------+
//|                                             TestDoEasyPart60.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\Ticks\TickSeries.mqh>
//--- enums

プログラムグローバル変数の領域で、「新しいティック」オブジェクト変数と現在の銘柄のティックシリーズデータオブジェクトを削除します

//--- global variables
CEngine        engine;
SDataButt      butt_data[TOTAL_BUTT];
string         prefix;
double         lot;
double         withdrawal=(InpWithdrawal<0.1 ? 0.1 : InpWithdrawal);
ushort         magic_number;
uint           stoploss;
uint           takeprofit;
uint           distance_pending;
uint           distance_stoplimit;
uint           distance_pending_request;
uint           bars_delay_pending_request;
uint           slippage;
bool           trailing_on;
bool           pressed_pending_buy;
bool           pressed_pending_buy_limit;
bool           pressed_pending_buy_stop;
bool           pressed_pending_buy_stoplimit;
bool           pressed_pending_close_buy;
bool           pressed_pending_close_buy2;
bool           pressed_pending_close_buy_by_sell;
bool           pressed_pending_sell;
bool           pressed_pending_sell_limit;
bool           pressed_pending_sell_stop;
bool           pressed_pending_sell_stoplimit;
bool           pressed_pending_close_sell;
bool           pressed_pending_close_sell2;
bool           pressed_pending_close_sell_by_buy;
bool           pressed_pending_delete_all;
bool           pressed_pending_close_all;
bool           pressed_pending_sl;
bool           pressed_pending_tp;
double         trailing_stop;
double         trailing_step;
uint           trailing_start;
uint           stoploss_to_modify;
uint           takeprofit_to_modify;
int            used_symbols_mode;
string         array_used_symbols[];
string         array_used_periods[];
bool           testing;
uchar          group1;
uchar          group2;
double         g_point;
int            g_digits;

//--- "New tick" object
CNewTickObj    check_tick;
//--- Object of the current symbol tick series data
CTickSeries    tick_series;
//+------------------------------------------------------------------+

OnInit()ハンドラの最後で、「新しいティック」オブジェクトの現在の銘柄の設定を削除します

//--- Wait for 600 milliseconds
   engine.Pause(600);
   engine.PlaySoundByDescription(TextByLanguage("Звук упавшей монетки 2","Falling coin 2"));

//--- Set the current symbol for "New tick" object
   check_tick.SetSymbol(Symbol());
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+

コードブロックを削除して、OnInitDoEasy()関数から現在の銘柄のティックシリーズの作成を確認します。

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

//--- Code block for checking the tick list creation and working with it
   Print("");
//--- Since the tick series object is created with the default constructor,
//--- set a symbol, usage flag and the number of days (the default is 1) to copy the ticks
//--- Create the tick series and printed data in the journal
   tick_series.SetSymbol(Symbol());
   tick_series.SetAvailable(true);
   tick_series.SetRequiredUsedDays();
   tick_series.Create();
   tick_series.Print();
   
   Print("");
//--- Get and display in the journal the data of an object with the highest Ask price in the daily price range
   int index_max=CSelect::FindTickDataMax(tick_series.GetList(),TICK_PROP_ASK);
   CDataTick *tick_max=tick_series.GetList().At(index_max);
   if(tick_max!=NULL)
      tick_max.Print();
//--- Get and display in the journal the data of an object with the lowest Bid price in the daily price range
   int index_min=CSelect::FindTickDataMin(tick_series.GetList(),TICK_PROP_BID);
   CDataTick *tick_min=tick_series.GetList().At(index_min);
   if(tick_min!=NULL)
      tick_min.Print();

//--- Create resource text files

次に、ここで作成されたティックデータコレクションのすべての銘柄のティックシリーズの作成を設定する必要があります。

//--- 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 tick series of all used symbols
   engine.GetTickSeriesCollection().CreateTickSeriesAll();
//--- Check created tick series - display descriptions of all created tick series in the journal
   engine.GetTickSeriesCollection().Print();

//--- Create resource text files

OnTick()ハンドラで、新しいティックが到着したら、各銘柄のティックデータリストで売呼値が最も高く買呼値が最も低いティックオブジェクトを見つけ、検出された各ティックのパラメータを操作ログで表示します

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

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

//--- If the trailing flag is set
   if(trailing_on)
     {
      TrailingPositions();          // Trailing positions
      TrailingOrders();             // Trailing pending orders
     }
     
//--- Check created tick data on the first tick
//--- Get and display in the journal the data of an object with the highest Ask price and the lowest Bid price in the daily price range
   static bool check=false;
   if(!check)
     {
      Print("");
      //--- Get the pointer to the list of tick data of all symbols from the tick collection
      CArrayObj* list=engine.GetTickSeriesCollection().GetList();
      int total=engine.GetTickSeriesCollection().DataTotal();
      //--- In the loop by the number of tick series in the collection
      for(int i=0;i<list.Type();i++)
        {
         //--- Get the next tick series from the collection by index
         CTickSeries *tick_series=engine.GetTickSeriesCollection().GetTickseries(i);
         if(tick_series!=NULL)
           {
            //--- In the obtained tick series, find the indices of tick objects with the highest Ask and the lowest Bid
            int index_max=CSelect::FindTickDataMax(tick_series.GetList(),TICK_PROP_ASK);
            int index_min=CSelect::FindTickDataMin(tick_series.GetList(),TICK_PROP_BID);
            //--- Display the data of the tick objects obtained from the tick series in the journal
            engine.GetTickSeriesCollection().GetTick(tick_series.Symbol(),index_max).Print();
            engine.GetTickSeriesCollection().GetTick(tick_series.Symbol(),index_min).Print();
           }
        }
      check=true;
     }
  }
//+------------------------------------------------------------------+

EAをコンパイルし、任意の銘柄のチャートで起動します。その前に、事前定義されたリストから現在の時間枠と銘柄を有効にしてください。ここでは、提案された銘柄全体から最初の2つの銘柄のみが除外されています。


OnInit()ハンドラーで使用される2つの銘柄のティックデータを作成するために必要な短い時間の後、操作ログはプログラムパラメータ、作成された時系列、作成されたティックデータに関するデータを受信します。新しいティックが到着すると、操作ログは、2つの銘柄のそれぞれについて最高の売呼値と最低の買呼値を持つ4つの検出されたティックに関するデータを受信します

Account 8550475: Artyom Trishkin (MetaQuotes Software Corp.) 10426.13 USD, 1:100, Hedge, MetaTrader 5 demo
--- Initializing "DoEasy" library ---
Working with predefined symbol list. The number of used symbols: 2
"AUDUSD" "EURUSD"
Working with the current timeframe only: H1
AUDUSD symbol timeseries: 
- Timeseries "AUDUSD" H1: Requested: 1000, Actual: 1000, Created: 1000, On the server: 6194
EURUSD symbol timeseries: 
- Timeseries "EURUSD" H1: Requested: 1000, Actual: 1000, Created: 1000, On the server: 5675
Tick series "AUDUSD": Requested number of days: 1, Historical data created: 142712
Tick series "EURUSD": Requested number of days: 1, Historical data created: 113985
Library initialization time: 00:00:06.156
 
============= Beginning of parameter list (Tick "AUDUSD" 2021.01.19 10:06:53.387) =============
Last price update time in milliseconds: 2021.01.19 10:06:53.387
Last price update time: 2021.01.19 10:06:53
Volume for the current Last price: 0
Flags: 6
Changed data on the tick:
 - Ask price change
 - Bid price change
------
Bid price: 0.77252
Ask price: 0.77256
Last price: 0.00000
Volume for the current Last price with greater accuracy: 0.00
Spread: 0.00004
------
Symbol: "AUDUSD"
============= End of parameter list (Tick "AUDUSD" 2021.01.19 10:06:53.387) =============
 
============= Beginning of parameter list (Tick "AUDUSD" 2021.01.18 11:51:48.662) =============
Last price update time in milliseconds: 2021.01.18 11:51:48.662
Last price update time: 2021.01.18 11:51:48
Volume for the current Last price: 0
Flags: 130
Changed data on the tick:
 - Bid price change
------
Bid price: 0.76589
Ask price: 0.76593
Last price: 0.00000
Volume for the current Last price with greater accuracy: 0.00
Spread: 0.00004
------
Symbol: "AUDUSD"
============= End of parameter list (Tick "AUDUSD" 2021.01.18 11:51:48.662) =============
 
============= Beginning of parameter list (Tick "EURUSD" 2021.01.19 10:05:07.246) =============
Last price update time in milliseconds: 2021.01.19 10:05:07.246
Last price update time: 2021.01.19 10:05:07
Volume for the current Last price: 0
Flags: 6
Changed data on the tick:
 - Ask price change
 - Bid price change
------
Bid price: 1.21189
Ask price: 1.21189
Last price: 0.00000
Volume for the current Last price with greater accuracy: 0.00
Spread: 0.00000
------
Symbol: "EURUSD"
============= End of parameter list (Tick "EURUSD" 2021.01.19 10:05:07.246) =============

============= Beginning of parameter list (Tick "EURUSD" 2021.01.18 14:57:53.847) =============
Last price update time in milliseconds: 2021.01.18 14:57:53.847
Last price update time: 2021.01.18 14:57:53
Volume for the current Last price: 0
Flags: 134
Changed data on the tick:
 - Ask price change
 - Bid price change
------
Bid price: 1.20536
Ask price: 1.20536
Last price: 0.00000
Volume for the current Last price with greater accuracy: 0.00
Spread: 0.00000
------
Symbol: "EURUSD"
============= End of parameter list (Tick "EURUSD" 2021.01.18 14:57:53.847) =============

操作ログによると、ライブラリの初期化とティックデータリストの作成には16秒かかりました。新しいティックが到着すると、当日使用された銘柄ごとに、最高の売呼値と最低の買呼値を持つ2つのティックが見つかりました。

次の段階

次の記事では、本日作成されたティックコレクションのデータイベントのリアルタイム更新と制御の作成を開始します。

ライブラリの現在のバージョンのすべてのファイルは、テストおよびダウンロードできるように、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部): カスタム指標オブジェクト、コレクション内指標オブジェクトからのデータ取得
DoEasyライブラリの時系列(第57部): 指標バッファデータオブジェクト
DoEasyライブラリの時系列(第58部): 指標バッファデータの時系列
DoEasyライブラリの時系列(第59部): 単一ティックのデータを格納するオブジェクト
DoEasyライブラリでの価格(第60部): 銘柄ティックデータのシリーズリスト