DoEasyライブラリの時系列(第59部): 単一ティックのデータを格納するオブジェクト
目次
概念
本稿からは、ティックデータを処理するライブラリ機能を開発します。
ティックデータの保存と使用の概念は、最小データ単位がバーである時系列データの保存の概念に似ています。バーオブジェクトは、対応する時間枠に属するリストに格納され、対応する時間枠は、銘柄に属するリストに格納されます。
ティックデータストレージの概念では、データ量の最小単位は1ティックの価格構造の値でなければなりません。このような値は、最後の価格を銘柄ごとに保存するMqlTick構造体を使用して記述されます。このような値を格納するオブジェクトには、スプレッド(売り気配値と買い気配値の差)、およびオブジェクトによって1ティックが記述されているデータの銘柄の追加のプロパティがあります。
リスト構造をより便利にするために、ティックデータを含むオブジェクトの独自のリストが銘柄ごとに作成されます。もちろん、ティックデータオブジェクトの各リストは自動的に更新され、新しく受信したティックの新しいデータが追加されます。一方、リストのサイズは、ライブラリユーザーが決定したボリュームでサポートされます。
ライブラリ内のデータストレージの概念には、リストに保存されているオブジェクトプロパティのいずれかによる検索と並べ替えが備わっており、後で使用したり分析調査を実行したりするために必要なデータを受け取ることができます。したがって、ティックデータは同じ機能を持ちます。これによりティックデータフローをすばやく分析し、発生の性質の変化またはセットパターンの検索などを追跡できます。
データの準備
他のライブラリオブジェクトと同様に、パラメータの説明を表示し、オブジェクトプロパティの列挙を作成して、リストでの検索やこれらのプロパティによるオブジェクトの並べ替えを可能にするテキストメッセージを追加する必要があります。
\MQL5\Include\DoEasy\Data.mqhファイルに、新しいメッセージインデックスを追加します。
//--- CSeriesDataInd MSG_LIB_TEXT_METHOD_NOT_FOR_INDICATORS, // The method is not intended to work with indicator programs MSG_LIB_TEXT_IND_DATA_FAILED_GET_SERIES_DATA, // Failed to get indicator data timeseries MSG_LIB_TEXT_IND_DATA_FAILED_GET_CURRENT_DATA, // Failed to get current data of indicator buffer MSG_LIB_SYS_FAILED_CREATE_IND_DATA_OBJ, // Failed to create indicator data object MSG_LIB_TEXT_IND_DATA_FAILED_ADD_TO_LIST, // Failed to add indicator data object to list //--- CTick MSG_TICK_TEXT_TICK, // Tick MSG_TICK_TIME_MSC, // Time of the last update of prices in milliseconds MSG_TICK_TIME, // Time of the last update of prices MSG_TICK_VOLUME, // Volume for the current Last price MSG_TICK_FLAGS, // Flags MSG_TICK_VOLUME_REAL, // Volume for the current Last price with greater accuracy MSG_TICK_SPREAD, // Spread MSG_LIB_TEXT_TICK_CHANGED_DATA, // Changed data on tick: MSG_LIB_TEXT_TICK_FLAG_BID, // Bid price change MSG_LIB_TEXT_TICK_FLAG_ASK, // Ask price change MSG_LIB_TEXT_TICK_FLAG_LAST, // Last deal price change MSG_LIB_TEXT_TICK_FLAG_VOLUME, // Volume change }; //+------------------------------------------------------------------+
新しく追加したインデックスに対応するメッセージテキストも追加します。
//--- CSeriesDataInd {"The method is not intended for working with indicator programs"}, {"Failed to get indicator data timeseries"}, {"Failed to get the current data of the indicator buffer"}, {"Failed to create indicator data object"}, {"Failed to add indicator data object to the list"}, //--- CTick {"Tick"}, {"Last price update time in milliseconds"}, {"Last price update time"}, {"Volume for the current Last price"}, {"Flags"}, {"Volume for the current \"Last\" price with increased accuracy"}, {"Spread"}, {"Changed data on a tick:"}, {"Bid price change"}, {"Ask price change"}, {"Last price change"}, {"Volume change"}, }; //+---------------------------------------------------------------------+
\MQL5\Include\DoEasy\Defines.mqhファイルに、ティックデータオブジェクトの整数、実数、および文字列プロパティを指定するための列挙を追加します。
//+------------------------------------------------------------------+ //| Data for working with tick data | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Tick integer properties | //+------------------------------------------------------------------+ enum ENUM_TICK_PROP_INTEGER { TICK_PROP_TIME_MSC = 0, // Time of the last price update in milliseconds TICK_PROP_TIME, // Time of the last update TICK_PROP_VOLUME, // Volume for the current Last price TICK_PROP_FLAGS, // Tick flags }; #define TICK_PROP_INTEGER_TOTAL (4) // Total number of tick integer properties #define TICK_PROP_INTEGER_SKIP (0) // Number of tick properties not used in sorting //+------------------------------------------------------------------+ //| Real tick properties | //+------------------------------------------------------------------+ enum ENUM_TICK_PROP_DOUBLE { TICK_PROP_BID = TICK_PROP_INTEGER_TOTAL, // Tick Bid price TICK_PROP_ASK, // Tick Ask price TICK_PROP_LAST, // Current price of the last trade (Last) TICK_PROP_VOLUME_REAL, // Volume for the current Last price with greater accuracy TICK_PROP_SPREAD, // Tick spread (Ask - Bid) }; #define TICK_PROP_DOUBLE_TOTAL (5) // Total number of real tick properties #define TICK_PROP_DOUBLE_SKIP (0) // Number of tick properties not used in sorting //+------------------------------------------------------------------+ //| String tick properties | //+------------------------------------------------------------------+ enum ENUM_TICK_PROP_STRING { TICK_PROP_SYMBOL = (TICK_PROP_INTEGER_TOTAL+TICK_PROP_DOUBLE_TOTAL), // Tick symbol }; #define TICK_PROP_STRING_TOTAL (1) // Total number of string tick properties //+------------------------------------------------------------------+
列挙ごとに、並べ替えで使用および未使用のプロパティの総数を指定します。
上記で指定されたプロパティによる検索と並べ替えを有効にするには、ティックデータの並べ替えの可能な基準が指定されるさらに別の列挙を追加します。
//+------------------------------------------------------------------+ //| Possible tick sorting criteria | //+------------------------------------------------------------------+ #define FIRST_TICK_DBL_PROP (TICK_PROP_INTEGER_TOTAL-TICK_PROP_INTEGER_SKIP) #define FIRST_TICK_STR_PROP (TICK_PROP_INTEGER_TOTAL-TICK_PROP_INTEGER_SKIP+TICK_PROP_DOUBLE_TOTAL-TICK_PROP_DOUBLE_SKIP) enum ENUM_SORT_TICK_MODE { //--- Sort by integer properties SORT_BY_TICK_TIME_MSC = 0, // Sort by the time of the last price update in milliseconds SORT_BY_TICK_TIM, // Sort by the time of the last price update SORT_BY_TICK_VOLUME, // Sort by volume for the current Last price SORT_BY_TICK_FLAGS, // Sort by tick flags //--- Sort by real properties SORT_BY_TICK_BID = FIRST_TICK_DBL_PROP, // Sort by tick Bid price SORT_BY_TICK_ASK, // Sort by tick Ask price SORT_BY_TICK_LAST, // Sort by current price of the last trade (Last) SORT_BY_TICK_VOLUME_REAL, // Sort by volume for the current Last price with greater accuracy SORT_BY_TICK_SPREAD, // Sort by tick spread //--- Sort by string properties SORT_BY_TICK_SYMBOL = FIRST_TICK_STR_PROP, // Sort by tick symbol }; //+------------------------------------------------------------------+
以前、第38部で、指定した銘柄への新しいティックの到着を追跡するための「新しいティック」オブジェクトを作成しました。
オブジェクトは、ライブラリディレクトリの\MQL5\Include\DoEasy\Objects\Ticks\フォルダのファイルNewTickObj.mqhにあります。
オブジェクトの現在の銘柄を指定するための銘柄設定メソッドにNULL値(または空の文字列)を渡すことができるように、オブジェクトクラスを改善します。
//--- Set a symbol void SetSymbol(const string symbol) { this.m_symbol=(symbol==NULL || symbol=="" ? ::Symbol() : symbol); }
また、クラスコンストラクタの初期化リストで、新しいティックフラグを格納するm_new_tick変数にfalse値を設定します。
//+------------------------------------------------------------------+ //| Parametric constructor CNewTickObj | //+------------------------------------------------------------------+ CNewTickObj::CNewTickObj(const string symbol) : m_symbol(symbol),m_new_tick(false) { //--- Reset the structures of the new and previous ticks ::ZeroMemory(this.m_tick); ::ZeroMemory(this.m_tick_prev); //--- If managed to get the current prices to the tick structure - //--- copy data of the obtained tick to the previous tick data and reset the first launch flag if(::SymbolInfoTick(this.m_symbol,this.m_tick)) { this.m_tick_prev=this.m_tick; this.m_first_start=false; } } //+------------------------------------------------------------------+
以前は、この変数はどこでも初期値で初期化されていませんでした。これは正しくありません。
ティックデータオブジェクトクラス
「新規ティック」オブジェクトのクラスのフォルダ\MQL5\Include\DoEasy\Objects\Ticks\に、ティックデータオブジェクトクラス新しいファイルDataTick.mqhを作成します。
このオブジェクトは、ライブラリクラスにとって新しいものではありません。すべてが標準です。クラス本体を分析してみましょう。
//+------------------------------------------------------------------+ //| DataTick.mqh | //| Copyright 2020, MetaQuotes Software Corp. | //| https://mql5.com/ru/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2020, MetaQuotes Software Corp." #property link "https://mql5.com/ru/users/artmedia70" #property version "1.00" #property strict // Necessary for mql4 //+------------------------------------------------------------------+ //| Include files | //+------------------------------------------------------------------+ #include "..\BaseObj.mqh" #include "..\..\Services\DELib.mqh" //+------------------------------------------------------------------+ //| “Tick” class | //+------------------------------------------------------------------+ class CDataTick : public CBaseObj { private: MqlTick m_tick; // Structure for obtaining current prices int m_digits; // Symbol's digits value long m_long_prop[TICK_PROP_INTEGER_TOTAL]; // Integer properties double m_double_prop[TICK_PROP_DOUBLE_TOTAL]; // Real properties string m_string_prop[TICK_PROP_STRING_TOTAL]; // String properties //--- Return the index of the array the tick’s (1) double and (2) string properties are actually located at int IndexProp(ENUM_TICK_PROP_DOUBLE property) const { return(int)property-TICK_PROP_INTEGER_TOTAL; } int IndexProp(ENUM_TICK_PROP_STRING property) const { return(int)property-TICK_PROP_INTEGER_TOTAL-TICK_PROP_DOUBLE_TOTAL;} public: //--- Set tick’s (1) integer, (2) real and (3) string property void SetProperty(ENUM_TICK_PROP_INTEGER property,long value) { this.m_long_prop[property]=value; } void SetProperty(ENUM_TICK_PROP_DOUBLE property,double value) { this.m_double_prop[this.IndexProp(property)]=value; } void SetProperty(ENUM_TICK_PROP_STRING property,string value) { this.m_string_prop[this.IndexProp(property)]=value; } //--- Return tick’s (1) integer, (2) real and (3) string property from the properties array long GetProperty(ENUM_TICK_PROP_INTEGER property) const { return this.m_long_prop[property]; } double GetProperty(ENUM_TICK_PROP_DOUBLE property) const { return this.m_double_prop[this.IndexProp(property)]; } string GetProperty(ENUM_TICK_PROP_STRING property) const { return this.m_string_prop[this.IndexProp(property)]; } //--- Return the flag of the tick supporting this property virtual bool SupportProperty(ENUM_TICK_PROP_INTEGER property) { return true; } virtual bool SupportProperty(ENUM_TICK_PROP_DOUBLE property) { return true; } virtual bool SupportProperty(ENUM_TICK_PROP_STRING property) { return true; } //--- Return itself CDataTick *GetObject(void) { return &this;} //--- Compare CDataTick objects with each other by the specified property (for sorting the lists by a specified object property) virtual int Compare(const CObject *node,const int mode=0) const; //--- Compare CDataTick objects with each other by all properties (to search equal objects) bool IsEqual(CDataTick* compared_obj) const; //--- Constructors CDataTick(){;} CDataTick(const string symbol,const MqlTick &tick); //+------------------------------------------------------------------+ //| Descriptions of object tick data properties | //+------------------------------------------------------------------+ //--- Return description of tick's (1) integer, (2) real and (3) string property string GetPropertyDescription(ENUM_TICK_PROP_INTEGER property); string GetPropertyDescription(ENUM_TICK_PROP_DOUBLE property); string GetPropertyDescription(ENUM_TICK_PROP_STRING property); //--- Display the description of tick properties in the journal (full_prop=true - all properties, false - supported ones only) void Print(const bool full_prop=false); //--- Display a short description of the tick in the journal virtual void PrintShort(void); //--- Return the (1) short name and (2) description of tick data object flags virtual string Header(void); string FlagsDescription(void); //+------------------------------------------------------------------+ //| Methods of simplified access to tick data object properties | //+------------------------------------------------------------------+ //--- Return tick’s (1) Time, (2) time in milliseconds, (3) volume, (4) flags datetime Time(void) const { return (datetime)this.GetProperty(TICK_PROP_TIME); } long TimeMSC(void) const { return this.GetProperty(TICK_PROP_TIME_MSC); } long Volume(void) const { return this.GetProperty(TICK_PROP_VOLUME); } uint Flags(void) const { return (uint)this.GetProperty(TICK_PROP_FLAGS); } //--- Return tick’s (1) Bid, (2) Ask, (3) Last price, (4) volume with greater accuracy, (5) spread of the tick //--- size of the (9) candle upper, (10) lower wick double Bid(void) const { return this.GetProperty(TICK_PROP_BID); } double Ask(void) const { return this.GetProperty(TICK_PROP_ASK); } double Last(void) const { return this.GetProperty(TICK_PROP_LAST); } double VolumeReal(void) const { return this.GetProperty(TICK_PROP_VOLUME_REAL); } double Spread(void) const { return this.GetProperty(TICK_PROP_SPREAD); } //--- Return tick symbol string Symbol(void) const { return this.GetProperty(TICK_PROP_SYMBOL); } //--- Return bar (1) time, (2) index on the specified timeframe the tick time falls into datetime TimeBar(const ENUM_TIMEFRAMES timeframe)const { return ::iTime(this.Symbol(),timeframe,this.Index(timeframe)); } int Index(const ENUM_TIMEFRAMES timeframe) const { return ::iBarShift(this.Symbol(),(timeframe==PERIOD_CURRENT ? ::Period() : timeframe),this.Time()); } //--- Return the flag of (1) Bid, (2) Ask, (3) Last price, (4) volume change; (5) buy and (6) sell trades bool IsChangeBid() const { return((this.Flags() & TICK_FLAG_BID)==TICK_FLAG_BID); } bool IsChangeAsk() const { return((this.Flags() & TICK_FLAG_ASK)==TICK_FLAG_ASK); } bool IsChangeLast() const { return((this.Flags() & TICK_FLAG_LAST)==TICK_FLAG_LAST); } bool IsChangeVolume() const { return((this.Flags() & TICK_FLAG_VOLUME)==TICK_FLAG_VOLUME); } bool IsChangeBuy() const { return((this.Flags() & TICK_FLAG_BUY)==TICK_FLAG_BUY); } bool IsChangeSell() const { return((this.Flags( )& TICK_FLAG_SELL)==TICK_FLAG_SELL); } //--- }; //+------------------------------------------------------------------+
ライブラリオブジェクトの構成とその作成については、最初の記事で詳しく説明されています。主な変数とメソッドを調べて、クラスでの実装をさらに分析しましょう。
クラスのprivateセクションには、補助変数、オブジェクトの整数、実数、および文字列プロパティの値を格納するための配列が含まれています。また、配列内に物理的に配置されている実際のプロパティインデックスを返すメソッドもあります。
クラスのpublicセクションには、指定されたプロパティの値を設定して、対応するオブジェクトプロパティ配列に返すためのメソッド、1つまたは別のプロパティをサポートするオブジェクトのフラグを返すメソッド。オブジェクトを検索、比較、並び替えするためのメソッド、およびクラスコンストラクタが含まれています。
オブジェクトプロパティの説明を表示するメソッドとオブジェクトプロパティへのアクセスを簡素化するメソッドもあります。
それでは、クラスメソッドの実装を見てみましょう。
パラメトリッククラスコンストラクタに、銘柄および現在のティックデータが入力された構造体が渡されます。
//+------------------------------------------------------------------+ //| Parametric constructor | //+------------------------------------------------------------------+ CDataTick::CDataTick(const string symbol,const MqlTick &tick) { //--- Save symbol’s Digits this.m_digits=(int)::SymbolInfoInteger(symbol,SYMBOL_DIGITS); //--- Save integer tick properties this.SetProperty(TICK_PROP_TIME,tick.time); this.SetProperty(TICK_PROP_TIME_MSC,tick.time_msc); this.SetProperty(TICK_PROP_VOLUME,tick.volume); this.SetProperty(TICK_PROP_FLAGS,tick.flags); //--- Save real tick properties this.SetProperty(TICK_PROP_BID,tick.bid); this.SetProperty(TICK_PROP_ASK,tick.ask); this.SetProperty(TICK_PROP_LAST,tick.last); this.SetProperty(TICK_PROP_VOLUME_REAL,tick.volume_real); //--- Save additional tick properties this.SetProperty(TICK_PROP_SPREAD,tick.ask-tick.bid); this.SetProperty(TICK_PROP_SYMBOL,(symbol==NULL || symbol=="" ? ::Symbol() : symbol)); } //+------------------------------------------------------------------+
コンストラクタ内で、ティック構造からの対応する値とティックデータの取得元の銘柄をオブジェクトプロパティに入力するだけです。
以下は、指定されたプロパティによってオブジェクトの2つのパラメータを比較するメソッドです。
//+----------------------------------------------------------------------+ //| Compare CDataTick objects with each other by the specified property | //+----------------------------------------------------------------------+ int CDataTick::Compare(const CObject *node,const int mode=0) const { const CDataTick *obj_compared=node; //--- compare integer properties of two objects if(mode<TICK_PROP_INTEGER_TOTAL) { long value_compared=obj_compared.GetProperty((ENUM_TICK_PROP_INTEGER)mode); long value_current=this.GetProperty((ENUM_TICK_PROP_INTEGER)mode); return(value_current>value_compared ? 1 : value_current<value_compared ? -1 : 0); } //--- compare real properties of two objects else if(mode<TICK_PROP_DOUBLE_TOTAL+TICK_PROP_INTEGER_TOTAL) { double value_compared=obj_compared.GetProperty((ENUM_TICK_PROP_DOUBLE)mode); double value_current=this.GetProperty((ENUM_TICK_PROP_DOUBLE)mode); return(value_current>value_compared ? 1 : value_current<value_compared ? -1 : 0); } //--- compare string properties of two objects else if(mode<TICK_PROP_DOUBLE_TOTAL+TICK_PROP_INTEGER_TOTAL+TICK_PROP_STRING_TOTAL) { string value_compared=obj_compared.GetProperty((ENUM_TICK_PROP_STRING)mode); string value_current=this.GetProperty((ENUM_TICK_PROP_STRING)mode); return(value_current>value_compared ? 1 : value_current<value_compared ? -1 : 0); } return 0; } //+------------------------------------------------------------------+
現在のオブジェクトを比較する必要があるオブジェクトへのポインタと、2つのオブジェクトを比較するプロパティのタイプを、メソッドに渡す必要があります。
渡されたオブジェクト比較のモードに応じて、2つのオブジェクトのこれらのプロパティを比較し、現在のオブジェクトのプロパティの値が、比較されたオブジェクトのプロパティの値よりも多い/少ない場合は、それぞれ1 / -1 / 0を返します。
以下は、同一性のために2つのオブジェクトを比較するメソッドです。
//+------------------------------------------------------------------+ //| Compare CDataTick objects with each other by all properties | //+------------------------------------------------------------------+ bool CDataTick::IsEqual(CDataTick *compared_obj) const { int beg=0, end=TICK_PROP_INTEGER_TOTAL; for(int i=beg; i<end; i++) { ENUM_TICK_PROP_INTEGER prop=(ENUM_TICK_PROP_INTEGER)i; if(this.GetProperty(prop)!=compared_obj.GetProperty(prop)) return false; } beg=end; end+=TICK_PROP_DOUBLE_TOTAL; for(int i=beg; i<end; i++) { ENUM_TICK_PROP_DOUBLE prop=(ENUM_TICK_PROP_DOUBLE)i; if(this.GetProperty(prop)!=compared_obj.GetProperty(prop)) return false; } beg=end; end+=TICK_PROP_STRING_TOTAL; for(int i=beg; i<end; i++) { ENUM_TICK_PROP_STRING prop=(ENUM_TICK_PROP_STRING)i; if(this.GetProperty(prop)!=compared_obj.GetProperty(prop)) return false; } return true; } //+------------------------------------------------------------------+
ここでは、比較のためのオブジェクトへのポインタがメソッドに渡されます。次に、各プロパティグループによる3つのループで、2つのオブジェクトの連続する各プロパティを比較します。比較されたオブジェクトの同じプロパティとプロパティの少なくとも1つが等しくない場合は、falseを返します。3つのループすべてが完了すると、trueが返されます(2つのオブジェクトのすべてのプロパティは同じです)。これは、オブジェクトが同一であることを意味します。
以下は、操作ログにすべてのオブジェクトプロパティを表示するメソッドです。
//+------------------------------------------------------------------+ //| Display tick properties in the journal | //+------------------------------------------------------------------+ void CDataTick::Print(const bool full_prop=false) { ::Print("============= ",CMessage::Text(MSG_LIB_PARAMS_LIST_BEG)," (",this.Header(),") ============="); int beg=0, end=TICK_PROP_INTEGER_TOTAL; for(int i=beg; i<end; i++) { ENUM_TICK_PROP_INTEGER prop=(ENUM_TICK_PROP_INTEGER)i; if(!full_prop && !this.SupportProperty(prop)) continue; ::Print(this.GetPropertyDescription(prop)); } ::Print("------"); beg=end; end+=TICK_PROP_DOUBLE_TOTAL; for(int i=beg; i<end; i++) { ENUM_TICK_PROP_DOUBLE prop=(ENUM_TICK_PROP_DOUBLE)i; if(!full_prop && !this.SupportProperty(prop)) continue; ::Print(this.GetPropertyDescription(prop)); } ::Print("------"); beg=end; end+=TICK_PROP_STRING_TOTAL; for(int i=beg; i<end; i++) { ENUM_TICK_PROP_STRING prop=(ENUM_TICK_PROP_STRING)i; if(!full_prop && !this.SupportProperty(prop)) continue; ::Print(this.GetPropertyDescription(prop)); } ::Print("============= ",CMessage::Text(MSG_LIB_PARAMS_LIST_END)," (",this.Header(),") =============\n"); } //+------------------------------------------------------------------+
ここでは、各オブジェクトプロパティグループによる3つのループで、対応するメソッドGetPropertyDescription()を使用して、連続する各プロパティの説明が操作ログに表示されます。メソッドパラメータでfalse値がfull_prop変数に渡された場合、オブジェクトでサポートされているプロパティのみが表示されます。サポートされていないプロパティの場合、操作ログには、プロパティがサポートされていないことが表示されますが、このオブジェクトではすべてのプロパティがサポートされています。ただし、これはクラスの子孫オブジェクトで変更できます。
以下は、指定されたオブジェクトの整数、実数、および文字列プロパティの説明を返すメソッドです。
//+------------------------------------------------------------------+ //| Return description of tick's integer property | //+------------------------------------------------------------------+ string CDataTick::GetPropertyDescription(ENUM_TICK_PROP_INTEGER property) { return ( property==TICK_PROP_TIME_MSC ? CMessage::Text(MSG_TICK_TIME_MSC)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+TimeMSCtoString(this.GetProperty(property),TIME_DATE|TIME_MINUTES|TIME_SECONDS) ) : property==TICK_PROP_TIME ? CMessage::Text(MSG_TICK_TIME)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+::TimeToString(this.GetProperty(property),TIME_DATE|TIME_MINUTES|TIME_SECONDS) ) : property==TICK_PROP_VOLUME ? CMessage::Text(MSG_TICK_VOLUME)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==TICK_PROP_FLAGS ? CMessage::Text(MSG_TICK_FLAGS)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property)+"\n"+CMessage::Text(MSG_LIB_TEXT_TICK_CHANGED_DATA)+this.FlagsDescription() ) : "" ); } //+------------------------------------------------------------------+ //| Return description of tick's real property | //+------------------------------------------------------------------+ string CDataTick::GetPropertyDescription(ENUM_TICK_PROP_DOUBLE property) { int dg=(this.m_digits>0 ? this.m_digits : 1); return ( property==TICK_PROP_BID ? CMessage::Text(MSG_LIB_PROP_BID)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+::DoubleToString(this.GetProperty(property),dg) ) : property==TICK_PROP_ASK ? CMessage::Text(MSG_LIB_PROP_ASK)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+::DoubleToString(this.GetProperty(property),dg) ) : property==TICK_PROP_LAST ? CMessage::Text(MSG_LIB_PROP_LAST)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+::DoubleToString(this.GetProperty(property),dg) ) : property==TICK_PROP_VOLUME_REAL ? CMessage::Text(MSG_TICK_VOLUME_REAL)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+::DoubleToString(this.GetProperty(property),2) ) : property==TICK_PROP_SPREAD ? CMessage::Text(MSG_TICK_SPREAD)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+::DoubleToString(this.GetProperty(property),dg) ) : "" ); } //+------------------------------------------------------------------+ //| Return description of tick's string property | //+------------------------------------------------------------------+ string CDataTick::GetPropertyDescription(ENUM_TICK_PROP_STRING property) { return(property==TICK_PROP_SYMBOL ? CMessage::Text(MSG_LIB_PROP_SYMBOL)+": \""+this.GetProperty(property)+"\"" : ""); } //+------------------------------------------------------------------+
ここでは、メソッドに渡されたプロパティに応じて、その文字列の説明が返されます。
以下は、ティックのすべてのフラグの説明を含む文字列を返すメソッドです。
//+------------------------------------------------------------------+ //| Display the description of flags | //+------------------------------------------------------------------+ string CDataTick::FlagsDescription(void) { string flags= ( (this.IsChangeAsk() ? "\n - "+CMessage::Text(MSG_LIB_TEXT_TICK_FLAG_ASK) : "")+ (this.IsChangeBid() ? "\n - "+CMessage::Text(MSG_LIB_TEXT_TICK_FLAG_BID) : "")+ (this.IsChangeLast() ? "\n - "+CMessage::Text(MSG_LIB_TEXT_TICK_FLAG_LAST) : "")+ (this.IsChangeVolume() ? "\n - "+CMessage::Text(MSG_LIB_TEXT_TICK_FLAG_VOLUME) : "")+ (this.IsChangeBuy() ? "\n - "+CMessage::Text(MSG_DEAL_TO_BUY) : "")+ (this.IsChangeSell() ? "\n - "+CMessage::Text(MSG_DEAL_TO_SELL) : "") ); return flags; } //+------------------------------------------------------------------+
プロパティには、各ティックに一連のフラグを含む変数があります。これらのフラグは、このティックが発生したイベントを示しています。
MqlTickユーザガイドから
現在のティックで変更された特定のデータを見つけるには、そのフラグを分析します。
- TICK_FLAG_BID — 買呼値が変更
- TICK_FLAG_ASK — 売呼値が変更
- TICK_FLAG_LAST — 最終取引価格が変更
- TICK_FLAG_VOLUME — 取引量が変更
- TICK_FLAG_BUY — 買い取引から生じたティック
- TICK_FLAG_SELL — 売り取引から生じたティック
各フラグの変数内にプレゼンスフラグを返す(フラグの数による)6つのメソッドがあります。
//--- Return the flag of (1) Bid, (2) Ask, (3) Last price, (4) volume change; (5) buy and (6) sell trades bool IsChangeBid() const { return((this.Flags() & TICK_FLAG_BID)==TICK_FLAG_BID); } bool IsChangeAsk() const { return((this.Flags() & TICK_FLAG_ASK)==TICK_FLAG_ASK); } bool IsChangeLast() const { return((this.Flags() & TICK_FLAG_LAST)==TICK_FLAG_LAST); } bool IsChangeVolume() const { return((this.Flags() & TICK_FLAG_VOLUME)==TICK_FLAG_VOLUME); } bool IsChangeBuy() const { return((this.Flags() & TICK_FLAG_BUY)==TICK_FLAG_BUY); } bool IsChangeSell() const { return((this.Flags() & TICK_FLAG_SELL)==TICK_FLAG_SELL); }
説明されているメソッドでは、最初に変数内のフラグの存在のフラグが確認されます。そのような変更が利用可能かどうかに応じて、結果のテキスト文字列は、改行文字+フラグの説明または空の文字列で追加されます。すべてのフラグを確認した後、最終的に、変数に存在するフラグの説明を含むコンパイル済みの文字列が得られます。複数のフラグが使用可能な場合、各フラグの説明は操作ログの新しい行から始まります。
以下は、操作ログ内のティックデータオブジェクトの簡単な説明を表示するメソッドです。
//+------------------------------------------------------------------+ //| Display a short description of the tick in the journal | //+------------------------------------------------------------------+ void CDataTick::PrintShort(void) { ::Print(this.Header()); } //+------------------------------------------------------------------+
このメソッドは、操作ログに次のメソッドによって返される短い名前を表示するだけです。
//+------------------------------------------------------------------+ //| Return a short name of tick data object | //+------------------------------------------------------------------+ string CDataTick::Header(void) { return ( CMessage::Text(MSG_TICK_TEXT_TICK)+" \""+this.Symbol()+"\" "+TimeMSCtoString(TimeMSC()) ); } //+------------------------------------------------------------------+
このフェーズで、ティックデータオブジェクトの作成は完成です。
ティックデータオブジェクトのテスト
テストを実行するには、前の記事のEAを使用して、 \MQL5\Experts\TestDoEasy\Part59\でTestDoEasyPart59.mq5として保存します。
このEAでは、指標とその時系列を含むデータは不要になりました。ここでは、ティックデータオブジェクトを作成し、その完全な説明を操作ログに表示し、簡単な説明をチャートのコメントに表示します。新しいティックごとに、チャート上の説明が変わります。 操作ログでは、EAのローンチ後に最初のティックが表示されます。
EAとこの新しいライブラリオブジェクトとの接続はまだないので、そのクラスのファイルをEAに接続します。
//+------------------------------------------------------------------+ //| TestDoEasyPart59.mq5 | //| Copyright 2020, MetaQuotes Software Corp. | //| https://mql5.com/ru/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2020, MetaQuotes Software Corp." #property link "https://mql5.com/ru/users/artmedia70" #property version "1.00" //--- includes #include <DoEasy\Engine.mqh> #include <DoEasy\Objects\Ticks\DataTick.mqh>
EAのグローバル変数の領域でカスタム指標パラメータ配列の代わりに
//--- Arrays of custom indicator parameters MqlParam param_ma1[]; MqlParam param_ma2[]; //+------------------------------------------------------------------+
「新規ティック」クラスのオブジェクトを宣言します。これは、ライブラリティックデータの将来のコレクションクラス内での作業をシミュレートするために必要になります。
//--- 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; //+------------------------------------------------------------------+
In OnInit() handler remove the indicator creation block:
//--- Create indicators
ArrayResize(param_ma1,4);
//--- Name of indicator 1
param_ma1[0].type=TYPE_STRING;
param_ma1[0].string_value="Examples\\Custom Moving Average.ex5";
//--- Calculation period
param_ma1[1].type=TYPE_INT;
param_ma1[1].integer_value=13;
//--- Horizontal shift
param_ma1[2].type=TYPE_INT;
param_ma1[2].integer_value=0;
//--- Smoothing method
param_ma1[3].type=TYPE_INT;
param_ma1[3].integer_value=MODE_SMA;
//--- Create indicator 1
engine.GetIndicatorsCollection().CreateCustom(NULL,PERIOD_CURRENT,MA1,1,INDICATOR_GROUP_TREND,param_ma1);
ArrayResize(param_ma2,5);
//--- Name of indicator 2
param_ma2[0].type=TYPE_STRING;
param_ma2[0].string_value="Examples\\Custom Moving Average.ex5";
//--- Calculation period
param_ma2[1].type=TYPE_INT;
param_ma2[1].integer_value=13;
//--- Horizontal shift
param_ma2[2].type=TYPE_INT;
param_ma2[2].integer_value=0;
//--- Smoothing method
param_ma2[3].type=TYPE_INT;
param_ma2[3].integer_value=MODE_SMA;
//--- Calculation price
param_ma2[4].type=TYPE_INT;
param_ma2[4].integer_value=PRICE_OPEN;
//--- Create indicator 2
engine.GetIndicatorsCollection().CreateCustom(NULL,PERIOD_CURRENT,MA2,1,INDICATOR_GROUP_TREND,param_ma2);
//--- Create indicator 3
engine.GetIndicatorsCollection().CreateAMA(NULL,PERIOD_CURRENT,AMA1);
//--- Create indicator 4
engine.GetIndicatorsCollection().CreateAMA(NULL,PERIOD_CURRENT,AMA2,14);
//--- Display descriptions of created indicators
engine.GetIndicatorsCollection().Print();
engine.GetIndicatorsCollection().PrintShort();
OnInit()の最後に、設定された現在の銘柄を「新規ティック」オブジェクトで現在の銘柄として設定します。
//--- Set the current symbol for "New tick" object check_tick.SetSymbol(Symbol()); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+
EAの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 } //--- Create a temporary list for storing “Tick data” objects, //--- a variable for obtaining tick data and //--- a variable for calculating incoming ticks static int tick_count=0; CArrayObj list; MqlTick tick_struct; //--- Check a new tick on the current symbol if(check_tick.IsNewTick()) { //--- If failed to get the price - exit if(!SymbolInfoTick(Symbol(),tick_struct)) return; //--- Create a new tick data object CDataTick *tick_obj=new CDataTick(Symbol(),tick_struct); if(tick_obj==NULL) return; //--- Increase tick counter (simply to display on the screen, no other purpose is provided) tick_count++; //--- Limit the number of ticks in the counting as one hundred thousand (again, no purpose is provided) if(tick_count>100000) tick_count=1; //--- In the comment on the chart display the tick number and its short description Comment("--- №",IntegerToString(tick_count,5,'0'),": ",tick_obj.Header()); //--- If this is the first tick (which follows the first launch of EA) display its full description in the journal if(tick_count==1) tick_obj.Print(); //--- Remove if failed to put the created tick data object in the list if(!list.Add(tick_obj)) delete tick_obj; } //--- If the trailing flag is set if(trailing_on) { TrailingPositions(); // Trailing positions TrailingOrders(); // Trailing of pending orders } } //+------------------------------------------------------------------+
ロジックは、リストのコメントで詳細に指定されています。 明確でシンプルだと思います。
EAをコンパイルし、現在の銘柄と時間枠を使用するように設定が事前に設定されているチャートで起動します。起動して新しいティックが到着すると、ティックデータオブジェクト(到着したティック)の説明が操作ログに表示されます。
Account 8550475: Artyom Trishkin (MetaQuotes Software Corp.) 10426.13 USD, 1:100, Hedge, Demo account MetaTrader 5 --- Initialize "DoEasy" library --- Work with the current symbol only: "EURUSD" Work with the current timeframe only: H1 EURUSD symbol timeseries: - "EURUSD" H1 timeseries: Requested: 1000, Actually: 1000, Created: 1000, On the server: 5153 Library initialize time: 00:00:00.000 ============= Beginning of parameter list (Tick "EURUSD" 2020.12.16 13:22:32.822) ============= Last price update time in milliseconds: 2020.12.16 13:22:32.822 Last price update time: 2020.12.16 13:22:32 Volume for the current Last price: 0 Flags: 6 Changed data on the tick: - Ask price change - Bid price change ------ Bid price: 1.21927 Ask price: 1.21929 Last price: 0.00000 Volume for the current Last price with greater accuracy: 0.00 Spread: 0.00002 ------ Symbol: "EURUSD" ============= End of parameter list (Tick "EURUSD" 2020.12.16 13:22:32.822) =============
and with each new tick a comment with its short description will be displayed on the chart:
次の段階
次の記事では、単一銘柄のティックデータコレクションの作成を開始します。
現在のライブラリバージョンのすべてのファイルは、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部): 指標バッファデータの時系列
MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/8818
- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索