
DoEasyライブラリの時系列(第44部): 指標バッファオブジェクトのコレクションクラス
内容
概念
第39部から、カスタム指標を作成するためのライブラリの使用を検討し始めました。現在までにあるのは、時系列オブジェクトとそのコレクション、および指標バッファオブジェクト(基本抽象バッファとそれに基づく指標バッファ)です。
この記事では、単一のプログラムで任意の量(最大512)のバッファを高速に作成し、データを簡単に取得してアクセスできるようにするための指標バッファのコレクションの開発を開始します。
時系列コレクション — バッファコレクションのリンクを使用すると、任意の複数銘柄および複数期間指標を作成できますが、これは、次回の記事から行うつもりです。本稿では、9つの描画スタイルのいずれかを使用して任意の数のバッファを作成するための指標バッファのコレクションを開発およびテストします。現在、指標に描画されるバッファの最大数は512を超えることはできません。これは、多数のチャートを含む複雑な指標を作成するのに十分すぎるはずです。開発された機能は、このような多数のグラフィカル構造の作成と保守を簡素化することで、プロセス全体を、作成順に描画スタイルと番号、またはコレクション内のバッファインデックスによって作成されたバッファにアクセスするだけに減らします。
データの準備とバッファオブジェクトの改善
前回の記事では、基本抽象バッファの子孫である「指標バッファ」オブジェクトを作成しました。指標バッファとして割り当てられたdouble配列にアクセスしたり、そこからデータを読み取ったりするための補助メソッドを追加してみましょう。
既存の基本的な抽象バッファメソッドで十分ですが、描画スタイルのみに固有の子孫オブジェクトでカスタムメソッドを作成すると、ステータス(描画スタイル)でバッファにアクセスするときに、double配列に簡単にアクセスできるようになり、カスタム指標を作成する際の柔軟性を高めます。
新しいライブラリメッセージを追加しましょう。新しいメッセージインデックスを\MQL5\Include\DoEasy\Datas.mqhに追加します。
MSG_LIB_SYS_FAILED_COLORS_ARRAY_RESIZE, // Failed to change the color array size MSG_LIB_SYS_FAILED_ADD_BUFFER, // Failed to add buffer object to the list MSG_LIB_SYS_FAILED_CREATE_BUFFER_OBJ, // Failed to create \"Indicator buffer\" object MSG_LIB_TEXT_YES, // Yes
...
MSG_LIB_TEXT_BUFFER_TEXT_INVALID_PROPERTY_BUFF, // Invalid number of indicator buffers (#property indicator_buffers) MSG_LIB_TEXT_BUFFER_TEXT_MAX_BUFFERS_REACHED, // Reached maximum possible number of indicator buffers MSG_LIB_TEXT_BUFFER_TEXT_STATUS_NONE, // No drawing
また、新しく追加したインデックスに対応するテキストも追加します。
{"Не удалось изменить размер массива цветов","Failed to resize color array"}, {"Не удалось добавить объект-буфер в список","Failed to add buffer object to list"}, {"Не удалось создать объект \"Индикаторный буфер\"","Failed to create object \"Indicator buffer\""}, {"Да","Yes"},
...
{"Неправильно указано количество буферов индикатора (#property indicator_buffers)","Number of indicator buffers incorrect (#property indicator_buffers)"}, {"Достигнуто максимально возможное количество индикаторных буферов","Maximum number of indicator buffers reached"}, {"Нет отрисовки","No drawing"},
指標は最大512個のバッファを使用できます。
\MQL5\Include\DoEasy\Defines.mqhにそれを指定するマクロ置換を追加します。
//+------------------------------------------------------------------+ //| Macro substitutions | //+------------------------------------------------------------------+ //--- Describe the function with the error line number #define DFUN_ERR_LINE (__FUNCTION__+(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian" ? ", Page " : ", Line ")+(string)__LINE__+": ") #define DFUN (__FUNCTION__+": ") // "Function description" #define COUNTRY_LANG ("Russian") // Country language #define END_TIME (D'31.12.3000 23:59:59') // End date for account history data requests #define TIMER_FREQUENCY (16) // Minimal frequency of the library timer in milliseconds #define TOTAL_TRY (5) // Default number of trading attempts #define IND_COLORS_TOTAL (64) // Maximum possible number of indicator buffer colors #define IND_BUFFERS_MAX (512) // Maximum possible number of indicator buffers //--- Standard sounds
もちろん、「512」の値を使用することもできますが、開発者がいつかこの値を増やした場合、すべてのファイルでこの値を検索してこの値への参照がある場合新しい値に修正する必要がないため、マクロ置換の方が便利です。代わりに、マクロ置換値を変更するだけで済みます。
検索と並べ替えに不要であると以前に識別されたプロパティで、バッファオブジェクトを検索して選択する必要があります。
並べ替えに適用されないすべてのプロパティは、常にプロパティ列挙リストの最後に配置されます。また、並び替え時に未使用のプロパティの数を指定するマクロ置換が有効になります。プロパティを並べ替え可能として設定するには、プロパティ列挙リストの最後から、現在並べ替えが許可されているプロパティの近くにプロパティを移動し、並べ替えで未使用のプロパティの新しい数を指定する必要があります。
もちろん、可能な並び替え基準の列挙を新しいプロパティ(並び替えに使用できるプロパティ)で補足する必要もあります。並び替え基準列挙リストで新しく追加されたプロパティの場所は、プロパティ列挙リストでのこれらのプロパティの場所と一致する必要があります。これらのプロパティを並び替えで使用できるようにしています。
紛らわしいように聞こえますが、実際にはすべてが単純です。\MQL5\Include\DoEasy\Defines.mqhを開いて、必要な変更を加えます。
以前は、整数バッファオブジェクトのプロパティが次の順序で配置されていました。
//+------------------------------------------------------------------+ //| Buffer integer properties | //+------------------------------------------------------------------+ enum ENUM_BUFFER_PROP_INTEGER { BUFFER_PROP_INDEX_PLOT = 0, // Plotted buffer serial number BUFFER_PROP_STATUS, // Buffer status (by drawing style) from the ENUM_BUFFER_STATUS enumeration BUFFER_PROP_TYPE, // Buffer type (from the ENUM_BUFFER_TYPE enumeration) BUFFER_PROP_TIMEFRAME, // Buffer period data (timeframe) BUFFER_PROP_ACTIVE, // Buffer usage flag BUFFER_PROP_DRAW_TYPE, // Graphical construction type (from the ENUM_DRAW_TYPE enumeration) BUFFER_PROP_ARROW_CODE, // Arrow code for DRAW_ARROW style BUFFER_PROP_ARROW_SHIFT, // The vertical shift of the arrows for DRAW_ARROW style BUFFER_PROP_LINE_STYLE, // Line style BUFFER_PROP_LINE_WIDTH, // Line width BUFFER_PROP_DRAW_BEGIN, // The number of initial bars that are not drawn and values in DataWindow BUFFER_PROP_SHOW_DATA, // Flag of displaying construction values in DataWindow BUFFER_PROP_SHIFT, // Indicator graphical construction shift by time axis in bars BUFFER_PROP_COLOR_INDEXES, // Number of colors BUFFER_PROP_COLOR, // Drawing color BUFFER_PROP_NUM_DATAS, // Number of data buffers BUFFER_PROP_INDEX_BASE, // Basic data buffer index BUFFER_PROP_INDEX_COLOR, // Color buffer index BUFFER_PROP_INDEX_NEXT, // Index of the free array to be assigned as the next indicator buffer }; #define BUFFER_PROP_INTEGER_TOTAL (19) // Total number of integer bar properties #define BUFFER_PROP_INTEGER_SKIP (6) // Number of buffer properties not used in sorting //+------------------------------------------------------------------+
ここでは、2つのプロパティを並び替え可能にします。これには、それらをもっと上に動かして並べ替えに使用されないプロパティの数を6 から2に変更します。
//+------------------------------------------------------------------+ //| Buffer integer properties | //+------------------------------------------------------------------+ enum ENUM_BUFFER_PROP_INTEGER { BUFFER_PROP_INDEX_PLOT = 0, // Plotted buffer serial number BUFFER_PROP_STATUS, // Buffer status (by drawing style) from the ENUM_BUFFER_STATUS enumeration BUFFER_PROP_TYPE, // Buffer type (from the ENUM_BUFFER_TYPE enumeration) BUFFER_PROP_TIMEFRAME, // Buffer period data (timeframe) BUFFER_PROP_ACTIVE, // Buffer usage flag BUFFER_PROP_DRAW_TYPE, // Graphical construction type (from the ENUM_DRAW_TYPE enumeration) BUFFER_PROP_ARROW_CODE, // Arrow code for DRAW_ARROW style BUFFER_PROP_ARROW_SHIFT, // The vertical shift of the arrows for DRAW_ARROW style BUFFER_PROP_LINE_STYLE, // Line style BUFFER_PROP_LINE_WIDTH, // Line width BUFFER_PROP_DRAW_BEGIN, // The number of initial bars that are not drawn and values in DataWindow BUFFER_PROP_SHOW_DATA, // Flag of displaying construction values in DataWindow BUFFER_PROP_SHIFT, // Indicator graphical construction shift by time axis in bars BUFFER_PROP_COLOR_INDEXES, // Number of colors BUFFER_PROP_COLOR, // Drawing color BUFFER_PROP_INDEX_BASE, // Basic data buffer index BUFFER_PROP_INDEX_NEXT, // Index of the free array to be assigned as the next indicator buffer BUFFER_PROP_NUM_DATAS, // Number of data buffers BUFFER_PROP_INDEX_COLOR, // Color buffer index }; #define BUFFER_PROP_INTEGER_TOTAL (19) // Total number of integer bar properties #define BUFFER_PROP_INTEGER_SKIP (2) // Number of buffer properties not used in sorting //+------------------------------------------------------------------+
ここでは、リストの最後にある2つのプロパティのみが並べ替えに参加しないことを指定しました。
これらの新しいプロパティを並べ替え基準に追加しましょう。
//+------------------------------------------------------------------+ //| Possible buffer sorting criteria | //+------------------------------------------------------------------+ #define FIRST_BUFFER_DBL_PROP (BUFFER_PROP_INTEGER_TOTAL-BUFFER_PROP_INTEGER_SKIP) #define FIRST_BUFFER_STR_PROP (BUFFER_PROP_INTEGER_TOTAL-BUFFER_PROP_INTEGER_SKIP+BUFFER_PROP_DOUBLE_TOTAL-BUFFER_PROP_DOUBLE_SKIP) enum ENUM_SORT_BUFFER_MODE { //--- Sort by integer properties SORT_BY_BUFFER_INDEX_PLOT = 0, // Sort by the plotted buffer serial number SORT_BY_BUFFER_STATUS, // Sort by buffer drawing style (status) from the ENUM_BUFFER_STATUS enumeration SORT_BY_BUFFER_TYPE, // Sort by buffer type (from the ENUM_BUFFER_TYPE enumeration) SORT_BY_BUFFER_TIMEFRAME, // Sort by the buffer data period (timeframe) SORT_BY_BUFFER_ACTIVE, // Sort by the buffer usage flag SORT_BY_BUFFER_DRAW_TYPE, // Sort by graphical construction type (from the ENUM_DRAW_TYPE enumeration) SORT_BY_BUFFER_ARROW_CODE, // Sort by the arrow code for DRAW_ARROW style SORT_BY_BUFFER_ARROW_SHIFT, // Sort by the vertical shift of the arrows for DRAW_ARROW style SORT_BY_BUFFER_LINE_STYLE, // Sort by the line style SORT_BY_BUFFER_LINE_WIDTH, // Sort by the line width SORT_BY_BUFFER_DRAW_BEGIN, // Sort by the number of initial bars that are not drawn and values in DataWindow SORT_BY_BUFFER_SHOW_DATA, // Sort by the flag of displaying construction values in DataWindow SORT_BY_BUFFER_SHIFT, // Sort by the indicator graphical construction shift by time axis in bars SORT_BY_BUFFER_COLOR_INDEXES, // Sort by a number of attempts SORT_BY_BUFFER_COLOR, // Sort by the drawing color SORT_BY_BUFFER_INDEX_BASE, // Sort by the basic data buffer index SORT_BY_BUFFER_INDEX_NEXT, // Sort by the index of the free array to be assigned as the next indicator buffer //--- Sort by real properties SORT_BY_BUFFER_EMPTY_VALUE = FIRST_BUFFER_DBL_PROP, // Sort by the empty value for plotting where nothing will be drawn //--- Sort by string properties SORT_BY_BUFFER_SYMBOL = FIRST_BUFFER_STR_PROP, // Sort by the buffer symbol SORT_BY_BUFFER_LABEL, // Sort by the name of the graphical indicator series displayed in DataWindow }; //+------------------------------------------------------------------+
ご覧のとおり、並べ替え基準の列挙リストでのそれらの場所は、列挙での整数プロパティの場所と一致しています。プロパティの並べ替えの順序は、オブジェクトプロパティの列挙のプロパティの順序と一致する必要があるため、基準の列挙は必須の条件です。これについては、第3部で説明しました。
ここでは、バッファオブジェクトをプロパティで並べ替えることについて説明しているので、バッファオブジェクトをプロパティで検索するためのツールを準備します。コレクションに格納されているすべてのライブラリオブジェクトにこのような機能をすでに導入しました。それでは、バッファオブジェクトも検索するメソッドを書いてみましょう。
\MQL5\Include\DoEasy\Services\Select.mqhを開いてバッファクラスファイルをインクルードします。
//+------------------------------------------------------------------+ //| Select.mqh | //| Copyright 2020, MetaQuotes Software Corp. | //| https://mql5.com/en/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2020, MetaQuotes Software Corp." #property link "https://mql5.com/en/users/artmedia70" #property version "1.00" //+------------------------------------------------------------------+ //| Include files | //+------------------------------------------------------------------+ #include <Arrays\ArrayObj.mqh> #include "..\Objects\Orders\Order.mqh" #include "..\Objects\Events\Event.mqh" #include "..\Objects\Accounts\Account.mqh" #include "..\Objects\Symbols\Symbol.mqh" #include "..\Objects\PendRequest\PendRequest.mqh" #include "..\Objects\Series\SeriesDE.mqh" #include "..\Objects\Indicators\Buffer.mqh" //+------------------------------------------------------------------+
クラス本体の一番下(時系列バーの操作メソッドを宣言するブロックの後)に、指標バッファの操作メソッドを宣言するブロックを追加します。
//+------------------------------------------------------------------+ //| Methods of working with timeseries bars | //+------------------------------------------------------------------+ //--- Return the list of bars with one out of (1) integer, (2) real and (3) string properties meeting a specified criterion static CArrayObj *ByBarProperty(CArrayObj *list_source,ENUM_BAR_PROP_INTEGER property,long value,ENUM_COMPARER_TYPE mode); static CArrayObj *ByBarProperty(CArrayObj *list_source,ENUM_BAR_PROP_DOUBLE property,double value,ENUM_COMPARER_TYPE mode); static CArrayObj *ByBarProperty(CArrayObj *list_source,ENUM_BAR_PROP_STRING property,string value,ENUM_COMPARER_TYPE mode); //--- Return the bar index in the list with the maximum value of the order's (1) integer, (2) real and (3) string properties static int FindBarMax(CArrayObj *list_source,ENUM_BAR_PROP_INTEGER property); static int FindBarMax(CArrayObj *list_source,ENUM_BAR_PROP_DOUBLE property); static int FindBarMax(CArrayObj *list_source,ENUM_BAR_PROP_STRING property); //--- Return the bar index in the list with the minimum value of the order's (1) integer, (2) real and (3) string properties static int FindBarMin(CArrayObj *list_source,ENUM_BAR_PROP_INTEGER property); static int FindBarMin(CArrayObj *list_source,ENUM_BAR_PROP_DOUBLE property); static int FindBarMin(CArrayObj *list_source,ENUM_BAR_PROP_STRING property); //+------------------------------------------------------------------+ //| Methods of working with indicator buffers | //+------------------------------------------------------------------+ //--- Return the list of buffers with one out of (1) integer, (2) real and (3) string properties meeting a specified criterion static CArrayObj *ByBufferProperty(CArrayObj *list_source,ENUM_BUFFER_PROP_INTEGER property,long value,ENUM_COMPARER_TYPE mode); static CArrayObj *ByBufferProperty(CArrayObj *list_source,ENUM_BUFFER_PROP_DOUBLE property,double value,ENUM_COMPARER_TYPE mode); static CArrayObj *ByBufferProperty(CArrayObj *list_source,ENUM_BUFFER_PROP_STRING property,string value,ENUM_COMPARER_TYPE mode); //--- Return the buffer index in the list with the maximum value of the order's (1) integer, (2) real and (3) string properties static int FindBufferMax(CArrayObj *list_source,ENUM_BUFFER_PROP_INTEGER property); static int FindBufferMax(CArrayObj *list_source,ENUM_BUFFER_PROP_DOUBLE property); static int FindBufferMax(CArrayObj *list_source,ENUM_BUFFER_PROP_STRING property); //--- Return the buffer index in the list with the minimum value of the order's (1) integer, (2) real and (3) string properties static int FindBufferMin(CArrayObj *list_source,ENUM_BUFFER_PROP_INTEGER property); static int FindBufferMin(CArrayObj *list_source,ENUM_BUFFER_PROP_DOUBLE property); static int FindBufferMin(CArrayObj *list_source,ENUM_BUFFER_PROP_STRING property); //--- }; //+------------------------------------------------------------------+
ファイルの最後に、クラス本体で宣言されているすべてのメソッドを追加します。
//+------------------------------------------------------------------+ //| Methods of working with buffer lists | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Return the list of buffers with one integer | //| property meeting the specified criterion | //+------------------------------------------------------------------+ CArrayObj *CSelect::ByBufferProperty(CArrayObj *list_source,ENUM_BUFFER_PROP_INTEGER property,long value,ENUM_COMPARER_TYPE mode) { if(list_source==NULL) return NULL; CArrayObj *list=new CArrayObj(); if(list==NULL) return NULL; list.FreeMode(false); ListStorage.Add(list); int total=list_source.Total(); for(int i=0; i<total; i++) { CBuffer *obj=list_source.At(i); if(!obj.SupportProperty(property)) continue; long obj_prop=obj.GetProperty(property); if(CompareValues(obj_prop,value,mode)) list.Add(obj); } return list; } //+------------------------------------------------------------------+ //| Return the list of buffers with one real | //| property meeting the specified criterion | //+------------------------------------------------------------------+ CArrayObj *CSelect::ByBufferProperty(CArrayObj *list_source,ENUM_BUFFER_PROP_DOUBLE property,double value,ENUM_COMPARER_TYPE mode) { if(list_source==NULL) return NULL; CArrayObj *list=new CArrayObj(); if(list==NULL) return NULL; list.FreeMode(false); ListStorage.Add(list); for(int i=0; i<list_source.Total(); i++) { CBuffer *obj=list_source.At(i); if(!obj.SupportProperty(property)) continue; double obj_prop=obj.GetProperty(property); if(CompareValues(obj_prop,value,mode)) list.Add(obj); } return list; } //+------------------------------------------------------------------+ //| Return the list of buffers with one string | //| property meeting the specified criterion | //+------------------------------------------------------------------+ CArrayObj *CSelect::ByBufferProperty(CArrayObj *list_source,ENUM_BUFFER_PROP_STRING property,string value,ENUM_COMPARER_TYPE mode) { if(list_source==NULL) return NULL; CArrayObj *list=new CArrayObj(); if(list==NULL) return NULL; list.FreeMode(false); ListStorage.Add(list); for(int i=0; i<list_source.Total(); i++) { CBuffer *obj=list_source.At(i); if(!obj.SupportProperty(property)) continue; string obj_prop=obj.GetProperty(property); if(CompareValues(obj_prop,value,mode)) list.Add(obj); } return list; } //+------------------------------------------------------------------+ //| Return the buffer index in the list | //| with the maximum integer property value | //+------------------------------------------------------------------+ int CSelect::FindBufferMax(CArrayObj *list_source,ENUM_BUFFER_PROP_INTEGER property) { if(list_source==NULL) return WRONG_VALUE; int index=0; CBuffer *max_obj=NULL; int total=list_source.Total(); if(total==0) return WRONG_VALUE; for(int i=1; i<total; i++) { CBuffer *obj=list_source.At(i); long obj1_prop=obj.GetProperty(property); max_obj=list_source.At(index); long obj2_prop=max_obj.GetProperty(property); if(CompareValues(obj1_prop,obj2_prop,MORE)) index=i; } return index; } //+------------------------------------------------------------------+ //| Return the buffer index in the list | //| with the maximum real property value | //+------------------------------------------------------------------+ int CSelect::FindBufferMax(CArrayObj *list_source,ENUM_BUFFER_PROP_DOUBLE property) { if(list_source==NULL) return WRONG_VALUE; int index=0; CBuffer *max_obj=NULL; int total=list_source.Total(); if(total==0) return WRONG_VALUE; for(int i=1; i<total; i++) { CBuffer *obj=list_source.At(i); double obj1_prop=obj.GetProperty(property); max_obj=list_source.At(index); double obj2_prop=max_obj.GetProperty(property); if(CompareValues(obj1_prop,obj2_prop,MORE)) index=i; } return index; } //+------------------------------------------------------------------+ //| Return the buffer index in the list | //| with the maximum string property value | //+------------------------------------------------------------------+ int CSelect::FindBufferMax(CArrayObj *list_source,ENUM_BUFFER_PROP_STRING property) { if(list_source==NULL) return WRONG_VALUE; int index=0; CBuffer *max_obj=NULL; int total=list_source.Total(); if(total==0) return WRONG_VALUE; for(int i=1; i<total; i++) { CBuffer *obj=list_source.At(i); string obj1_prop=obj.GetProperty(property); max_obj=list_source.At(index); string obj2_prop=max_obj.GetProperty(property); if(CompareValues(obj1_prop,obj2_prop,MORE)) index=i; } return index; } //+------------------------------------------------------------------+ //| Return the buffer index in the list | //| with the minimum integer property value | //+------------------------------------------------------------------+ int CSelect::FindBufferMin(CArrayObj* list_source,ENUM_BUFFER_PROP_INTEGER property) { int index=0; CBuffer *min_obj=NULL; int total=list_source.Total(); if(total==0) return WRONG_VALUE; for(int i=1; i<total; i++) { CBuffer *obj=list_source.At(i); long obj1_prop=obj.GetProperty(property); min_obj=list_source.At(index); long obj2_prop=min_obj.GetProperty(property); if(CompareValues(obj1_prop,obj2_prop,LESS)) index=i; } return index; } //+------------------------------------------------------------------+ //| Return the buffer index in the list | //| with the minimum real property value | //+------------------------------------------------------------------+ int CSelect::FindBufferMin(CArrayObj* list_source,ENUM_BUFFER_PROP_DOUBLE property) { int index=0; CBuffer *min_obj=NULL; int total=list_source.Total(); if(total== 0) return WRONG_VALUE; for(int i=1; i<total; i++) { CBuffer *obj=list_source.At(i); double obj1_prop=obj.GetProperty(property); min_obj=list_source.At(index); double obj2_prop=min_obj.GetProperty(property); if(CompareValues(obj1_prop,obj2_prop,LESS)) index=i; } return index; } //+------------------------------------------------------------------+ //| Return the buffer index in the list | //| with the minimum string property value | //+------------------------------------------------------------------+ int CSelect::FindBufferMin(CArrayObj* list_source,ENUM_BUFFER_PROP_STRING property) { int index=0; CBuffer *min_obj=NULL; int total=list_source.Total(); if(total==0) return WRONG_VALUE; for(int i=1; i<total; i++) { CBuffer *obj=list_source.At(i); string obj1_prop=obj.GetProperty(property); min_obj=list_source.At(index); string obj2_prop=min_obj.GetProperty(property); if(CompareValues(obj1_prop,obj2_prop,LESS)) index=i; } return index; } //+------------------------------------------------------------------+
CSelectクラスについては第3部で詳しく説明しました。
抽象バッファとその子孫のクラスを少し改善してみましょう。
バッファオブジェクトのプロパティによる検索と並べ替えを実行するため、 CSelectクラスファイルを抽象バッファクラスファイル( \MQL5\Include\DoEasy\Objects\Indicators\Buffer.mqh)にインクルードしましょう。
//+------------------------------------------------------------------+ //| Buffer.mqh | //| Copyright 2020, MetaQuotes Software Corp. | //| https://mql5.com/en/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2020, MetaQuotes Software Corp." #property link "https://mql5.com/en/users/artmedia70" #property version "1.00" #property strict // Necessary for mql4 //+------------------------------------------------------------------+ //| Include files | //+------------------------------------------------------------------+ #include "..\..\Services\Select.mqh" #include "..\..\Objects\BaseObj.mqh" //+------------------------------------------------------------------+
これで、CSelectクラスがCBufferクラスとそのすべての子孫に表示されます。
クラスのpublicセクションに、バッファオブジェクトのカスタム名を設定するメソッドを記述します。
public: //--- Set buffer's (1) integer, (2) real and (3) string properties void SetProperty(ENUM_BUFFER_PROP_INTEGER property,long value) { this.m_long_prop[property]=value; } void SetProperty(ENUM_BUFFER_PROP_DOUBLE property,double value) { this.m_double_prop[this.IndexProp(property)]=value; } void SetProperty(ENUM_BUFFER_PROP_STRING property,string value) { this.m_string_prop[this.IndexProp(property)]=value; } //--- Return (1) integer, (2) real and (3) string buffer properties from the properties array long GetProperty(ENUM_BUFFER_PROP_INTEGER property) const { return this.m_long_prop[property]; } double GetProperty(ENUM_BUFFER_PROP_DOUBLE property) const { return this.m_double_prop[this.IndexProp(property)]; } string GetProperty(ENUM_BUFFER_PROP_STRING property) const { return this.m_string_prop[this.IndexProp(property)]; } //--- Get description of buffer's (1) integer, (2) real and (3) string properties string GetPropertyDescription(ENUM_BUFFER_PROP_INTEGER property); string GetPropertyDescription(ENUM_BUFFER_PROP_DOUBLE property); string GetPropertyDescription(ENUM_BUFFER_PROP_STRING property); //--- Return the flag of the buffer supporting the property virtual bool SupportProperty(ENUM_BUFFER_PROP_INTEGER property) { return true; } virtual bool SupportProperty(ENUM_BUFFER_PROP_DOUBLE property) { return true; } virtual bool SupportProperty(ENUM_BUFFER_PROP_STRING property) { return true; } //--- Compare CBuffer objects by all possible properties (for sorting the lists by a specified buffer object property) virtual int Compare(const CObject *node,const int mode=0) const; //--- Compare CBuffer objects by all properties (to search for equal buffer objects) bool IsEqual(CBuffer* compared_obj) const; //--- Set the buffer name void SetName(const string name) { this.m_name=name; } //--- Default constructor CBuffer(void){;} protected:
バッファにカスタム名を設定すると、コレクションリストでの後続の検索用にバッファに名前を付けることができます。
指定された時系列インデックスからバッファ値を返すメソッドと、指定された時系列インデックスのバッファに割り当てられた色を返すメソッドがあります。ただし、指定された時系列インデックス内のバッファに設定されたカラーのインデックスを返すメソッドはありません。実際、バッファ自体にはカラー値を設定していません。代わりに、カラーインデックス(指定された時系列位置に線を描画するために使用される色のシリアル番号(カラーバッファに割り当てられたもののうち)を指定する値)を設定します。
これを修正しましょう。指定された時系列位置のバッファに設定されたカラーインデックスを返すさらに別のメソッドを宣言し、指定された時系列位置のバッファカラーを返すメソッドの名前をGetColorBufferValue()からGetColorBufferValueColor()に変更します。
//--- Return the size of the data buffer array virtual int GetDataTotal(const uint buffer_index=0) const; //--- Return the value from the specified index of the specified (1) data, (2) color index and (3) color buffer arrays double GetDataBufferValue(const uint buffer_index,const uint series_index) const; int GetColorBufferValueIndex(const uint series_index) const; color GetColorBufferValueColor(const uint series_index) const; //--- Set the value to the specified index of the specified (1) data and (2) color buffer arrays
これで、宣言されたバッファの色を処理する2つのメソッドができました。1つは色を返し、もう1つはカラーインデックスを返します。
クラス本体の外側で、カラーインデックスを返すメソッドを実装し、バッファクラスを返すメソッドの実装を修正します。
//+------------------------------------------------------------------+ //| Return the color index value from the specified timeseries index | //| of the specified color buffer array | //+------------------------------------------------------------------+ int CBuffer::GetColorBufferValueIndex(const uint series_index) const { int data_total=this.GetDataTotal(0); if(data_total==0) return WRONG_VALUE; int data_index=((int)series_index<data_total ? (int)series_index : data_total-1); return(this.ColorsTotal()==1 ? 0 : (int)this.ColorBufferArray[data_index]); } //+------------------------------------------------------------------+ //| Return the color value from the specified timeseries index | //| of the specified color buffer array | //+------------------------------------------------------------------+ color CBuffer::GetColorBufferValueColor(const uint series_index) const { int data_total=this.GetDataTotal(0); if(data_total==0) return clrNONE; int color_index=this.GetColorBufferValueIndex(series_index); return(color_index>WRONG_VALUE ? (color)this.ArrayColors[color_index] : clrNONE); } //+------------------------------------------------------------------+
以前は、メソッドは1つしかなく、カラーインデックスはその内部で取得されていました。
//+------------------------------------------------------------------+ //| Return the value from the specified timeseries index | //| of the specified color buffer array | //+------------------------------------------------------------------+ color CBuffer::GetColorBufferValue(const uint series_index) const { int data_total=this.GetDataTotal(0); if(data_total==0) return clrNONE; int data_index=((int)series_index<data_total ? (int)series_index : data_total-1); int color_index=(this.ColorsTotal()==1 ? 0 : (int)this.ColorBufferArray[data_index]); return (color)this.ArrayColors[color_index]; } //+------------------------------------------------------------------+
これで、この計算は別のGetColorBufferValueIndex()メソッドに移動されましたが、バーの色の戻りメソッドでは、インデックス計算の代わりに新しいメソッドの呼び出しが使用されるようになりました。
抽象バッファの子孫である矢印バッファオブジェクトクラス(残りのバッファクラスと同様)を作成するときに、改善を行いました。矢印コードを設定およびシフトするための仮想メソッドはCBufferクラスで宣言されていますが、子孫クラスに実装するのを忘れています。これを修正しましょう。
矢印バッファオブジェクトクラス\MQL5\Include\DoEasy\Objects\Indicators\BufferArrow.mqhのファイルを開き、これらのメソッドを宣言します。また、指標バッファによって割り当てられた配列との間で設定するおよび返す別の2つのメソッドを追加します。
//+------------------------------------------------------------------+ //| Buffer with the "Drawing with arrows" drawing style | //+------------------------------------------------------------------+ class CBufferArrow : public CBuffer { private: public: //--- Constructor CBufferArrow(const uint index_plot,const uint index_base_array) : CBuffer(BUFFER_STATUS_ARROW,BUFFER_TYPE_DATA,index_plot,index_base_array,1,1,"Arrows") {} //--- Supported integer properties of a buffer virtual bool SupportProperty(ENUM_BUFFER_PROP_INTEGER property); //--- Supported real properties of a buffer virtual bool SupportProperty(ENUM_BUFFER_PROP_DOUBLE property); //--- Supported string properties of a buffer virtual bool SupportProperty(ENUM_BUFFER_PROP_STRING property); //--- Display a short buffer description in the journal virtual void PrintShort(void); //--- Set (1) the arrow code, (2) vertical shift of arrows virtual void SetArrowCode(const uchar code); virtual void SetArrowShift(const int shift); //--- Set the value to the data buffer array void SetData(const uint series_index,const double value) { this.SetBufferValue(0,series_index,value); } //--- Return the value from the data buffer array double GetData(const uint series_index) const { return this.GetDataBufferValue(0,series_index); } }; //+------------------------------------------------------------------+
クラス本体の外で、矢印コードを設定およびシフトするメソッドを実装します。
//+------------------------------------------------------------------+ //| Set the arrow code | //+------------------------------------------------------------------+ void CBufferArrow::SetArrowCode(const uchar code) { this.SetProperty(BUFFER_PROP_ARROW_CODE,code); ::PlotIndexSetInteger((int)this.GetProperty(BUFFER_PROP_INDEX_PLOT),PLOT_ARROW,code); } //+------------------------------------------------------------------+ //| Set the vertical shift of the arrows | //+------------------------------------------------------------------+ void CBufferArrow::SetArrowShift(const int shift) { this.SetProperty(BUFFER_PROP_ARROW_SHIFT,shift); ::PlotIndexSetInteger((int)this.GetProperty(BUFFER_PROP_INDEX_PLOT),PLOT_ARROW_SHIFT,shift); } //+------------------------------------------------------------------+
メソッドは、渡された値を適切なバッファオブジェクトプロパティに書き込み、このプロパティを描画されたバッファオブジェクトバッファに設定します。
単一バッファを備えて、バッファ配列値をバッファオブジェクトに設定するメソッドおよびバッファオブジェクトからバッファ配列に値を返すメソッドの2つをバッファオブジェクトファイルに追加します(線(BufferLine.mqh)、セクション(BufferSection.mqh)、ゼロからのヒストグラム(BufferHistogram.mqh))。
//--- Set the value to the data buffer array void SetData(const uint series_index,const double value) { this.SetBufferValue(0,series_index,value); } //--- Return the value from the data buffer array double GetData(const uint series_index) const { return this.GetDataBufferValue(0,series_index); }
2つのレンダリング用バッファを備えた、バッファオブジェクトデータバッファ配列の値をバッファオブジェクトファイルに設定するメソッドおよびバッファオブジェクトファイルからバッファオブジェクトデータバッファ配列に値を返す4つのメソッドをバッファオブジェクトファイルに追加します(2つのデータ配列のヒストグラム(BufferHistogram2.mqh)、ジグザグ(BufferZigZag.mqh)、2つのデータ配列間の塗りつぶし(BufferFilling.mqh))。
//--- Set the value to the (1) zero and (2) the first data buffer array void SetData0(const uint series_index,const double value) { this.SetBufferValue(0,series_index,value); } void SetData1(const uint series_index,const double value) { this.SetBufferValue(1,series_index,value); } //--- Return the value from the (1) zero and (2) the first data buffer array double GetData0(const uint series_index) const { return this.GetDataBufferValue(0,series_index); } double GetData1(const uint series_index) const { return this.GetDataBufferValue(1,series_index); }
4つのレンダリング用バッファを備えた、OHLC値をバッファオブジェクトデータバッファ配列に設定メソッドおよびバッファオブジェクトデータバッファ配列からOHLCに値を返す8つのメソッドを追加します(バー(BufferBars.mqh)、ローソク足(BufferCandles.mqh))。
//--- Set (1) Open, (2) High, (3) Low and (4) Close values to the appropriate data buffer array void SetDataOpen(const uint series_index,const double value) { this.SetBufferValue(0,series_index,value); } void SetDataHigh(const uint series_index,const double value) { this.SetBufferValue(1,series_index,value); } void SetDataLow(const uint series_index,const double value) { this.SetBufferValue(2,series_index,value); } void SetDataClose(const uint series_index,const double value) { this.SetBufferValue(3,series_index,value); } //--- Return (1) Open, (2) High, (3) Low and (4) Close value from the appropriate data buffer array double GetDataOpen(const uint series_index) const { return this.GetDataBufferValue(0,series_index); } double GetDataHigh(const uint series_index) const { return this.GetDataBufferValue(1,series_index); } double GetDataLow(const uint series_index) const { return this.GetDataBufferValue(2,series_index); } double GetDataClose(const uint series_index) const { return this.GetDataBufferValue(3,series_index); }
もちろん、基本的なSetBufferValue()およびGetBufferValue()抽象バッファオブジェクトの既に記述されたメソッドがなくても問題はありませんが、これらのメソッドでは必要なバッファ番号を指定する必要があります。エンドユーザの作業を簡素化するために最善を尽くします。したがって、適用するメソッドを選択する機能を実装します。
これで、指標バッファオブジェクトのコレクションクラスを開発する準備が整いました。
このクラスには、作成されたすべてのバッファオブジェクトのリストが含まれ、プログラムで使用するためのバッファを作成および取得する機能が提供されます。以前のコレクションクラスとは異なり、ここでは、同じプロパティを持つ同じオブジェクトが存在するかどうかを確認する必要はありません。代わりに、さまざまなイベントを視覚化するために同じバッファを使用できます。
バッファオブジェクトのコレクションクラス
\MQL5\Include\DoEasy\Collections\で、標準ライブラリの基本的なCObjectクラスを持つBuffersCollection.mqhファイルを作成します。ライブラリ基本リストとバッファオブジェクトのクラスファイルをただちにインクルードします。
//+------------------------------------------------------------------+ //| BuffersCollection.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 "ListObj.mqh" #include "..\Objects\Indicators\BufferArrow.mqh" #include "..\Objects\Indicators\BufferLine.mqh" #include "..\Objects\Indicators\BufferSection.mqh" #include "..\Objects\Indicators\BufferHistogram.mqh" #include "..\Objects\Indicators\BufferHistogram2.mqh" #include "..\Objects\Indicators\BufferZigZag.mqh" #include "..\Objects\Indicators\BufferFilling.mqh" #include "..\Objects\Indicators\BufferBars.mqh" #include "..\Objects\Indicators\BufferCandles.mqh" //+------------------------------------------------------------------+ //| Collection of indicator buffers | //+------------------------------------------------------------------+ class CBuffersCollection : public CObject {
クラス本体に必要なコンテンツを入力して(残念ながら、それほど多くはありません)、その目的を検討しましょう。
//+------------------------------------------------------------------+ //| Collection of indicator buffers | //+------------------------------------------------------------------+ class CBuffersCollection : public CObject { private: CListObj m_list; // Buffer object list //--- Return the index of the next (1) drawn and (2) basic buffer int GetIndexNextPlot(void); int GetIndexNextBase(void); //--- Create a new buffer object and place it to the collection list bool CreateBuffer(ENUM_BUFFER_STATUS status); public: //--- Return (1) oneself and (2) the timeseries list CBuffersCollection *GetObject(void) { return &this; } CArrayObj *GetList(void) { return &this.m_list; } //--- Return the number of (1) drawn buffers, (2) all arrays used to build all buffers in the collection int PlotsTotal(void); int BuffersTotal(void); //--- Create the new buffer (1) "Drawing with arrows", (2) "Line", (3) "Sections", (4) "Histogram from the zero line", //--- (5) "Histogram on two indicator buffers", (6) "Zigzag", (7) "Color filling between two levels", //--- (8) "Display as bars", (9) "Display as candles", bool CreateArrow(void) { return this.CreateBuffer(BUFFER_STATUS_ARROW); } bool CreateLine(void) { return this.CreateBuffer(BUFFER_STATUS_LINE); } bool CreateSection(void) { return this.CreateBuffer(BUFFER_STATUS_SECTION); } bool CreateHistogram(void) { return this.CreateBuffer(BUFFER_STATUS_HISTOGRAM); } bool CreateHistogram2(void) { return this.CreateBuffer(BUFFER_STATUS_HISTOGRAM2); } bool CreateZigZag(void) { return this.CreateBuffer(BUFFER_STATUS_ZIGZAG); } bool CreateFilling(void) { return this.CreateBuffer(BUFFER_STATUS_FILLING); } bool CreateBars(void) { return this.CreateBuffer(BUFFER_STATUS_BARS); } bool CreateCandles(void) { return this.CreateBuffer(BUFFER_STATUS_CANDLES); } //--- Return the buffer by the Plot index CBuffer *GetBufferByPlot(const int plot_index); //--- Return buffers by drawing style by a serial number //--- (0 - the very first created buffer with the ХХХ drawing style, 1,2,N - subsequent ones) CBufferArrow *GetBufferArrow(const int number); CBufferLine *GetBufferLine(const int number); CBufferSection *GetBufferSection(const int number); CBufferHistogram *GetBufferHistogram(const int number); CBufferHistogram2 *GetBufferHistogram2(const int number); CBufferZigZag *GetBufferZigZag(const int number); CBufferFilling *GetBufferFilling(const int number); CBufferBars *GetBufferBars(const int number); CBufferCandles *GetBufferCandles(const int number); //--- Constructor CBuffersCollection(); }; //+------------------------------------------------------------------+
したがって、m_listは、作成されたすべてのバッファオブジェクトを追加して保存するリストです。これは、CObjectクラスインスタンスへのポインタの動的配列のクラスの子孫です。
次に作成される指標バッファのインデックスを指定するには、次に描画されるバッファのインデックスを返すGetIndexNextPlot()privateメソッドが必要ですが、GetIndexNextBase()メソッド(private)新しく作成されたバッファオブジェクトの指標バッファとして割り当てることができる実配列のインデックスを指定するには、次の基本バッファのインデックスを返す必要があります。
これを明確にしましょう。指標バッファを作成するときは、データウィンドウでその番号(描画されたバッファ番号)を指定し、それをdouble 配列(基本バッファ配列のインデックス)にバインドします。何故「基本的」なのでしょうか。描画バッファは複数の配列を使用できます。指標として割り当てられた最初の配列のみが基本です。描画に使用される他の配列のインデックスは、「基本配列」+ Nに等しくなります。
したがって、2つの配列に基づく3つの色付きバッファの場合、描画と基本のインデックスは次のようになります。
1番目のバッファ
- 描画バッファ: インデックス0
- 基本配列: インデックス0
- 2番目のバッファ: インデックス1
- カラー配列: インデックス2
2番目のバッファ
- 描画バッファ: インデックス1
- 基本配列: インデックス3
- 2番目の配列: インデックス4
- カラー配列: インデックス5
3番目のバッファ
- 描画バッファ: インデックス2
- 基本配列: インデックス6
- 2番目の配列: インデックス7
- カラー配列: インデックス8
ご覧のとおり、インデックスは、描画されたバッファと各バッファごとの基本配列に対して個別です。指標に複数のバッファが適用されている場合、混乱しやすくなります。コレクションクラスは、描画されたバッファとその配列に正しいインデックスを自動的に割り当てます。これは、プログラムからいつでも参照できることを意味します。
CreateBuffer()メソッドは、新しいバッファを作成し、それをコレクションリストに配置します。
GetObject()メソッドとGetList()メソッドは、コレクションクラスオブジェクトへのポインタと、それに応じてコレクションクラスのバッファオブジェクトのリストを返します。
PlotsTotal()メソッドBuffersTotal() メソッドは、コレクション内に作成された描画バッファの数と、それに応じてすべての描画バッファを構築するために使用された配列の総数を返します。
以下は、特定の描画スタイルでバッファオブジェクトを作成するためのパブリックメソッドです。
//--- Create the new buffer (1) "Drawing with arrows", (2) "Line", (3) "Sections", (4) "Histogram from the zero line", //--- (5) "Histogram on two indicator buffers", (6) "Zigzag", (7) "Color filling between two levels", //--- (8) "Display as bars", (9) "Display as candles", bool CreateArrow(void) { return this.CreateBuffer(BUFFER_STATUS_ARROW); } bool CreateLine(void) { return this.CreateBuffer(BUFFER_STATUS_LINE); } bool CreateSection(void) { return this.CreateBuffer(BUFFER_STATUS_SECTION); } bool CreateHistogram(void) { return this.CreateBuffer(BUFFER_STATUS_HISTOGRAM); } bool CreateHistogram2(void) { return this.CreateBuffer(BUFFER_STATUS_HISTOGRAM2); } bool CreateZigZag(void) { return this.CreateBuffer(BUFFER_STATUS_ZIGZAG); } bool CreateFilling(void) { return this.CreateBuffer(BUFFER_STATUS_FILLING); } bool CreateBars(void) { return this.CreateBuffer(BUFFER_STATUS_BARS); } bool CreateCandles(void) { return this.CreateBuffer(BUFFER_STATUS_CANDLES); }
メソッドは、CreateBuffer()バッファオブジェクトを作成するためのprivateメソッドの結果を返して作成されたバッファの描画スタイルを指定します。
GetBufferByPlot()メソッドは、描画されたバッファインデックスによってバッファへのポインタを返します。
以下は、シリアル番号でバッファオブジェクトへのポインタを返すメソッドです。
//--- Return buffers by drawing style by a serial number //--- (0 - the very first created buffer with the ХХХ drawing style, 1,2,N - subsequent ones) CBufferArrow *GetBufferArrow(const int number); CBufferLine *GetBufferLine(const int number); CBufferSection *GetBufferSection(const int number); CBufferHistogram *GetBufferHistogram(const int number); CBufferHistogram2 *GetBufferHistogram2(const int number); CBufferZigZag *GetBufferZigZag(const int number); CBufferFilling *GetBufferFilling(const int number); CBufferBars *GetBufferBars(const int number); CBufferCandles *GetBufferCandles(const int number);
特定の描画スタイルのオブジェクトを、作成順に番号で返します。
次の例でこれを明確にしましょう。
描画されたバッファインデックス0、1、2、3を使用して4つのBufferArrow()矢印バッファを作成しました。
次に、描画されたバッファインデックスが4、5、6、7、8の5つのBufferLine()ラインバッファを作成しました。
次に、3番目の矢印バッファ(インデックスが2)と4番目の行バッファ(インデックスが7)を操作する必要があります。
3番目の矢印バッファへのポインタを取得するには、(インデックスではなく)シリアル番号でポインタを取得するだけです。数はゼロから数える必要があります。たとえば、3番目の矢印バッファが必要な場合は、次のように取得する必要があります。
CBufferArrow *buffer_arrow=GetBufferArrow(2); // the third arrow buffer (0,1,2)
4番目の線バッファへのポインタは次のように取得されます。
CBufferLine *buffer_line=GetBufferLine(3); // the fourth line buffer (0,1,2,3)
次に、宣言されたすべてのメソッドの実装について考えてみましょう。
クラスコンストラクタ:
//+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CBuffersCollection::CBuffersCollection() { this.m_list.Clear(); this.m_list.Sort(); this.m_list.Type(COLLECTION_BUFFERS_ID); } //+------------------------------------------------------------------+
リストをクリアし、リストの並び替え済みリストフラグを設定し、コレクションタイプの指標バッファコレクションリストIDを設定します。
以下は、次に描画されるバッファのインデックスを返すメソッド次の基本バッファのインデックスを返すメソッドです。
//+------------------------------------------------------------------+ //| Return the index of the next drawn buffer | //+------------------------------------------------------------------+ int CBuffersCollection::GetIndexNextPlot(void) { //--- Return the pointer to the list. If the list is not created for some reason, return -1 CArrayObj *list=this.GetList(); if(list==NULL) return WRONG_VALUE; //--- Get the index of the drawn buffer with the highest value. If the FindBufferMax() method returns -1, //--- the list is empty, return index 0 for the very first buffer in the list int index=CSelect::FindBufferMax(list,BUFFER_PROP_INDEX_PLOT); if(index==WRONG_VALUE) index=0; //--- if the index is not -1, else { //--- get the buffer object from the list by its index CBuffer *buffer=this.m_list.At(index); if(buffer==NULL) return WRONG_VALUE; //--- Return the index following the Plot index of the buffer object index=buffer.IndexPlot()+1; } //--- Return the index value return index; } //+------------------------------------------------------------------+ //| Return the index of the next basic buffer | //+------------------------------------------------------------------+ int CBuffersCollection::GetIndexNextBase(void) { //--- Return the pointer to the list. If the list is not created for some reason, return -1 CArrayObj *list=this.GetList(); if(list==NULL) return WRONG_VALUE; //--- Get the highest index of the next array that can be assigned as an indicator buffer, //--- if the FindBufferMax() method returns -1, //--- the list is empty, return index 0 for the very first buffer in the list int index=CSelect::FindBufferMax(list,BUFFER_PROP_INDEX_NEXT); if(index==WRONG_VALUE) index=0; //--- if the index is not -1, else { //--- get the buffer object from the list by its index CBuffer *buffer=this.m_list.At(index); if(buffer==NULL) return WRONG_VALUE; //--- Return the index of the next array from the buffer object properties index=buffer.IndexNextBuffer(); } //--- Return the index value return index; } //+------------------------------------------------------------------+
これら2つのメソッドのロジックは同じで、コードのコメントで説明しています。
以下は、新しいバッファオブジェクトを作成し、それをコレクションリストに配置するメソッドです。
//+------------------------------------------------------------------+ //| Create a new buffer object and place it to the collection list | //+------------------------------------------------------------------+ bool CBuffersCollection::CreateBuffer(ENUM_BUFFER_STATUS status) { //--- Get the drawn buffer index and the index used to assign the first buffer array as an indicator one int index_plot=this.GetIndexNextPlot(); int index_base=this.GetIndexNextBase(); //--- If any of the indices is not received, return 'false' if(index_plot==WRONG_VALUE || index_base==WRONG_VALUE) return false; //--- If the maximum possible number of indicator buffers has already been reached, inform about it and return 'false' if(this.m_list.Total()==IND_BUFFERS_MAX) { ::Print(CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_MAX_BUFFERS_REACHED)); return false; } //--- Create the buffer drawing style description string descript=::StringSubstr(::EnumToString(status),14); //--- Declare the abstract buffer object CBuffer *buffer=NULL; //--- Create a buffer object depending on the status passed to the method (drawing style) switch(status) { case BUFFER_STATUS_ARROW : buffer=new CBufferArrow(index_plot,index_base); break; case BUFFER_STATUS_LINE : buffer=new CBufferLine(index_plot,index_base); break; case BUFFER_STATUS_SECTION : buffer=new CBufferSection(index_plot,index_base); break; case BUFFER_STATUS_HISTOGRAM : buffer=new CBufferHistogram(index_plot,index_base); break; case BUFFER_STATUS_HISTOGRAM2 : buffer=new CBufferHistogram2(index_plot,index_base); break; case BUFFER_STATUS_ZIGZAG : buffer=new CBufferZigZag(index_plot,index_base); break; case BUFFER_STATUS_FILLING : buffer=new CBufferFilling(index_plot,index_base); break; case BUFFER_STATUS_BARS : buffer=new CBufferBars(index_plot,index_base); break; case BUFFER_STATUS_CANDLES : buffer=new CBufferCandles(index_plot,index_base); break; default: break; } //--- Failed to create a buffer, inform of that and return 'false' if(buffer==NULL) { ::Print(CMessage::Text(MSG_LIB_SYS_FAILED_CREATE_BUFFER_OBJ)," ",descript); return false; } //--- If failed to add a buffer object to the collection list for some reason, //--- inform of that, remove the created buffer object and return 'false' if(!this.m_list.Add(buffer)) { ::Print(CMessage::Text(MSG_LIB_SYS_FAILED_ADD_BUFFER)); delete buffer; return false; } //--- Set a name for the buffer object and return 'true' buffer.SetName("Buffer"+descript+"("+(string)buffer.IndexPlot()+")"); return true; } //+------------------------------------------------------------------+
ロジックは、ここのコメントにも記載されています。CBuffer抽象バッファオブジェクトを宣言していることに注意してください。ただし、実際には、ステータスによってメソッドに渡される描画タイプを使用して新しいオブジェクトを作成します(ステータスは描画スタイルを表します)。すべてのバッファオブジェクトは抽象バッファオブジェクトの子孫であるため、このような宣言とオブジェクトの作成は許容され、便利です。
以下は、プロットインデックス(データウィンドウのインデックス)によってバッファを返すメソッドです。
//+------------------------------------------------------------------+ //| Return the buffer by the Plot index | //+------------------------------------------------------------------+ CBuffer *CBuffersCollection::GetBufferByPlot(const int plot_index) { CArrayObj *list=CSelect::ByBufferProperty(this.GetList(),BUFFER_PROP_INDEX_PLOT,plot_index,EQUAL); return(list!=NULL && list.Total()==1 ? list.At(0) : NULL); } //+------------------------------------------------------------------+
CSelectクラスを使用すると、指定したインデックスを持つバッファオブジェクトのみを含むリストを取得できます(リストにはオブジェクトが1つだけあります)。取得したリストからバッファオブジェクト(見つかった場合)を返します。コレクションリストにそのようなオブジェクトがない場合、NULLを返します。
以下は、特定のタイプのバッファオブジェクトを返すメソッドです。
//+------------------------------------------------------------------+ //| Return the "Drawing by arrows" buffer by a serial number | //| (0 - the very first arrow buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ CBufferArrow *CBuffersCollection::GetBufferArrow(const int number) { CArrayObj *list=CSelect::ByBufferProperty(this.GetList(),BUFFER_PROP_STATUS,BUFFER_STATUS_ARROW,EQUAL); return(list!=NULL && list.Total()>0 ? list.At(number) : NULL); } //+------------------------------------------------------------------+ //| Return the Line buffer by a serial number | //| (0 - the very first line buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ CBufferLine *CBuffersCollection::GetBufferLine(const int number) { CArrayObj *list=CSelect::ByBufferProperty(this.GetList(),BUFFER_PROP_STATUS,BUFFER_STATUS_LINE,EQUAL); return(list!=NULL && list.Total()>0 ? list.At(number) : NULL); } //+------------------------------------------------------------------+ //| Return the Sections buffer by a serial number | //| (0 - the very first sections buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ CBufferSection *CBuffersCollection::GetBufferSection(const int number) { CArrayObj *list=CSelect::ByBufferProperty(this.GetList(),BUFFER_PROP_STATUS,BUFFER_STATUS_SECTION,EQUAL); return(list!=NULL && list.Total()>0 ? list.At(number) : NULL); } //+------------------------------------------------------------------+ //| Return the "Histogram from the zero line" buffer by number | //| (0 - the very first buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ CBufferHistogram *CBuffersCollection::GetBufferHistogram(const int number) { CArrayObj *list=CSelect::ByBufferProperty(this.GetList(),BUFFER_PROP_STATUS,BUFFER_STATUS_HISTOGRAM,EQUAL); return(list!=NULL && list.Total()>0 ? list.At(number) : NULL); } //+------------------------------------------------------------------+ //| Return the "Histogram on two buffers" buffer by number | //| (0 - the very first buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ CBufferHistogram2 *CBuffersCollection::GetBufferHistogram2(const int number) { CArrayObj *list=CSelect::ByBufferProperty(this.GetList(),BUFFER_PROP_STATUS,BUFFER_STATUS_HISTOGRAM2,EQUAL); return(list!=NULL && list.Total()>0 ? list.At(number) : NULL); } //+------------------------------------------------------------------+ //| Return the ZigZag buffer by a serial number | //| (0 - the very first zigzag buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ CBufferZigZag *CBuffersCollection::GetBufferZigZag(const int number) { CArrayObj *list=CSelect::ByBufferProperty(this.GetList(),BUFFER_PROP_STATUS,BUFFER_STATUS_ZIGZAG,EQUAL); return(list!=NULL && list.Total()>0 ? list.At(number) : NULL); } //+------------------------------------------------------------------+ //|Return the "Color filling between two levels" buffer by number | //| (0 - the very first filling buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ CBufferFilling *CBuffersCollection::GetBufferFilling(const int number) { CArrayObj *list=CSelect::ByBufferProperty(this.GetList(),BUFFER_PROP_STATUS,BUFFER_STATUS_FILLING,EQUAL); return(list!=NULL && list.Total()>0 ? list.At(number) : NULL); } //+------------------------------------------------------------------+ //| Return the "Display as bars" buffer by a serial number | //| (0 - the very first bar buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ CBufferBars *CBuffersCollection::GetBufferBars(const int number) { CArrayObj *list=CSelect::ByBufferProperty(this.GetList(),BUFFER_PROP_STATUS,BUFFER_STATUS_BARS,EQUAL); return(list!=NULL && list.Total()>0 ? list.At(number) : NULL); } //+------------------------------------------------------------------+ //|Return the "Display as candles" buffer by a serial number | //| (0 - the very first candle buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ CBufferCandles *CBuffersCollection::GetBufferCandles(const int number) { CArrayObj *list=CSelect::ByBufferProperty(this.GetList(),BUFFER_PROP_STATUS,BUFFER_STATUS_CANDLES,EQUAL); return(list!=NULL && list.Total()>0 ? list.At(number) : NULL); }
すべてのメソッドは同じなので、そのうちの1つだけを考えてみましょう。
必要な描画スタイルのみのバッファオブジェクトを含むリストを取得します。
リストが取得され、空ではない場合は、取得されたリストから指定されたインデックスでオブジェクトを返します。
リストでは、オブジェクトはインデックスの昇順で配置されているため、インデックスの調整は必要ありません。
インデックスがリストの外にある場合、CArrayObjクラスのAt()メソッドはNULLを返します。
リストが取得できなかったか空の場合は、NULLを返します。
以下は、描画されたバッファの数とすべての指標配列の数を返すメソッドです。
//+------------------------------------------------------------------+ //| Return the number of drawn buffers | //+------------------------------------------------------------------+ int CBuffersCollection::PlotsTotal(void) { int index=CSelect::FindBufferMax(this.GetList(),BUFFER_PROP_INDEX_PLOT); CBuffer *buffer=this.m_list.At(index); return(buffer!=NULL ? buffer.IndexPlot()+1 : WRONG_VALUE); } //+------------------------------------------------------------------+ //| Returns the number of all indicator arrays | //+------------------------------------------------------------------+ int CBuffersCollection::BuffersTotal(void) { int index=CSelect::FindBufferMax(this.GetList(),BUFFER_PROP_INDEX_NEXT); CBuffer *buffer=this.m_list.At(index); return(buffer!=NULL ? buffer.IndexNextBuffer() : WRONG_VALUE); } //+------------------------------------------------------------------+
メソッドのロジックは似ています。必要なプロパティの値が最も高いインデックスを取得します。取得したインデックスによってコレクションリストからバッファオブジェクトを取得します。バッファが取得された場合、メソッドに対応するプロパティを返します。それ以外の場合は-1を返します。
これで、指標バッファコレクションクラスの開発は完了です。
次に、ライブラリベースのプログラムのクラスメソッドへのアクセスを提供する必要があります。私の場合、これは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 "TradingControl.mqh" //+------------------------------------------------------------------+ //| 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 CResourceCollection m_resource; // Resource list CTradingControl m_trading; // Trading management object CPause m_pause; // Pause object CArrayObj m_list_counters; // List of timer counters
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 buffer collection, (2) the buffer list from the buffer collection and (3) the buffer by the Plot index CBuffersCollection *GetBuffersCollection(void) { return &this.m_buffers; } CArrayObj *GetListBuffers(void) { return this.m_buffers.GetList(); } CBuffer *GetBufferByPlot(const int plot_index) { return this.m_buffers.GetBufferByPlot(plot_index); } //--- Return buffers by drawing style by a serial number //--- (0 - the very first created buffer with the ХХХ drawing style, 1,2,N - subsequent ones) CBufferArrow *GetBufferArrow(const int number) { return this.m_buffers.GetBufferArrow(number); } CBufferLine *GetBufferLine(const int number) { return this.m_buffers.GetBufferLine(number); } CBufferSection *GetBufferSection(const int number) { return this.m_buffers.GetBufferSection(number); } CBufferHistogram *GetBufferHistogram(const int number) { return this.m_buffers.GetBufferHistogram(number); } CBufferHistogram2 *GetBufferHistogram2(const int number) { return this.m_buffers.GetBufferHistogram2(number); } CBufferZigZag *GetBufferZigZag(const int number) { return this.m_buffers.GetBufferZigZag(number); } CBufferFilling *GetBufferFilling(const int number) { return this.m_buffers.GetBufferFilling(number); } CBufferBars *GetBufferBars(const int number) { return this.m_buffers.GetBufferBars(number); } CBufferCandles *GetBufferCandles(const int number) { return this.m_buffers.GetBufferCandles(number); } //--- Return the number of (1) drawn buffers and (2) all indicator arrays int BufferPlotsTotal(void) { return this.m_buffers.PlotsTotal(); } int BuffersTotal(void) { return this.m_buffers.BuffersTotal(); } //--- Create the new buffer (1) "Drawing with arrows", (2) "Line", (3) "Sections", (4) "Histogram from the zero line", //--- (5) "Histogram on two indicator buffers", (6) "Zigzag", (7) "Color filling between two levels", //--- (8) "Display as bars", (9) "Display as candles", bool BufferCreateArrow(void) { return this.m_buffers.CreateArrow(); } bool BufferCreateLine(void) { return this.m_buffers.CreateLine(); } bool BufferCreateSection(void) { return this.m_buffers.CreateSection(); } bool BufferCreateHistogram(void) { return this.m_buffers.CreateHistogram(); } bool BufferCreateHistogram2(void) { return this.m_buffers.CreateHistogram2(); } bool BufferCreateZigZag(void) { return this.m_buffers.CreateZigZag(); } bool BufferCreateFilling(void) { return this.m_buffers.CreateFilling(); } bool BufferCreateBars(void) { return this.m_buffers.CreateBars(); } bool BufferCreateCandles(void) { return this.m_buffers.CreateCandles(); } //--- Return buffer data by its serial number of (1) arrows, (2) line, (3) sections and (4) histogram from zero //--- (0 - the very first created buffer with the ХХХ drawing style, 1,2,N - subsequent ones) double BufferDataArrow(const int number,const int series_index); double BufferDataLine(const int number,const int series_index); double BufferDataSection(const int number,const int series_index); double BufferDataHistogram(const int number,const int series_index); //--- Return buffer data by its serial number of (1) the zero and (2) the first histogram buffer on two buffers //--- (0 - the very first created buffer with the ХХХ drawing style, 1,2,N - subsequent ones) double BufferDataHistogram20(const int number,const int series_index); double BufferDataHistogram21(const int number,const int series_index); //--- Return buffer data by its serial number of (1) the zero and (2) the first zigzag buffer //--- (0 - the very first created buffer with the ХХХ drawing style, 1,2,N - subsequent ones) double BufferDataZigZag0(const int number,const int series_index); double BufferDataZigZag1(const int number,const int series_index); //--- Return buffer data by its serial number of (1) the zero and (2) the first filling buffer //--- (0 - the very first created buffer with the ХХХ drawing style, 1,2,N - subsequent ones) double BufferDataFilling0(const int number,const int series_index); double BufferDataFilling1(const int number,const int series_index); //--- Return buffer data by its serial number of (1) Open, (2) High, (3) Low and (4) Close bar buffers //--- (0 - the very first created buffer with the ХХХ drawing style, 1,2,N - subsequent ones) double BufferDataBarsOpen(const int number,const int series_index); double BufferDataBarsHigh(const int number,const int series_index); double BufferDataBarsLow(const int number,const int series_index); double BufferDataBarsClose(const int number,const int series_index); //--- Return buffer data by its serial number of (1) Open, (2) High, (3) Low and (4) Close candle buffers //--- (0 - the very first created buffer with the ХХХ drawing style, 1,2,N - subsequent ones) double BufferDataCandlesOpen(const int number,const int series_index); double BufferDataCandlesHigh(const int number,const int series_index); double BufferDataCandlesLow(const int number,const int series_index); double BufferDataCandlesClose(const int number,const int series_index); //--- Set buffer data by its serial number of (1) arrows, (2) line, (3) sections and (4) histogram from zero //--- (0 - the very first created buffer with the ХХХ drawing style, 1,2,N - subsequent ones) void BufferSetDataArrow(const int number,const int series_index,const double value); void BufferSetDataLine(const int number,const int series_index,const double value); void BufferSetDataSection(const int number,const int series_index,const double value); void BufferSetDataHistogram(const int number,const int series_index,const double value); //--- Set data of the (1) zero, (2) first and (3) all histogram buffers on two buffers by a serial number of a created buffer //--- (0 - the very first created buffer with the HISTOGRAM2 drawing style, 1,2,N - subsequent ones) void BufferSetDataHistogram20(const int number,const int series_index,const double value); void BufferSetDataHistogram21(const int number,const int series_index,const double value); void BufferSetDataHistogram2(const int number,const int series_index,const double value0,const double value1); //--- Set data of the (1) zero, (2) first and (3) all zigzag buffers by a serial number of a created buffer //--- (0 - the very first created buffer with the ZIGZAG drawing style, 1,2,N - subsequent ones) void BufferSetDataZigZag0(const int number,const int series_index,const double value); void BufferSetDataZigZag1(const int number,const int series_index,const double value); void BufferSetDataZigZag(const int number,const int series_index,const double value0,const double value1); //--- Set data of the (1) zero, (2) first and (3) all filling buffers by a serial number of a created buffer //--- (0 - the very first created buffer with the FILLING drawing style, 1,2,N - subsequent ones) void BufferSetDataFilling0(const int number,const int series_index,const double value); void BufferSetDataFilling1(const int number,const int series_index,const double value); void BufferSetDataFilling(const int number,const int series_index,const double value0,const double value1); //--- Set data of the (1) Open, (2) High, (3) Low, (4) Close and (5) all bar buffers by a serial number of a created buffer //--- (0 - the very first created buffer with the BARS drawing style, 1,2,N - subsequent ones) void BufferSetDataBarsOpen(const int number,const int series_index,const double value); void BufferSetDataBarsHigh(const int number,const int series_index,const double value); void BufferSetDataBarsLow(const int number,const int series_index,const double value); void BufferSetDataBarsClose(const int number,const int series_index,const double value); void BufferSetDataBars(const int number,const int series_index,const double open,const double high,const double low,const double close); //--- Set data of the (1) Open, (2) High, (3) Low, (4) Close and (5) all candle buffers by a serial number of a created buffer //--- (0 - the very first created buffer with the CANDLES drawing style, 1,2,N - subsequent ones) void BufferSetDataCandlesOpen(const int number,const int series_index,const double value); void BufferSetDataCandlesHigh(const int number,const int series_index,const double value); void BufferSetDataCandlesLow(const int number,const int series_index,const double value); void BufferSetDataCandlesClose(const int number,const int series_index,const double value); void BufferSetDataCandles(const int number,const int series_index,const double open,const double high,const double low,const double close); //--- Return buffer color by its serial number of (1) arrows, (2) line, (3) sections, (4) histogram from zero //--- (5) histogram on two buffers, (6) zigzag, (7) filling, (8) bars and (9) candles //--- (0 - the very first created buffer with the ХХХ drawing style, 1,2,N - subsequent ones) color BufferColorArrow(const int number,const int series_index); color BufferColorLine(const int number,const int series_index); color BufferColorSection(const int number,const int series_index); color BufferColorHistogram(const int number,const int series_index); color BufferColorHistogram2(const int number,const int series_index); color BufferColorZigZag(const int number,const int series_index); color BufferColorFilling(const int number,const int series_index); color BufferColorBars(const int number,const int series_index); color BufferColorCandles(const int number,const int series_index); //--- Return buffer color index by its serial number of (1) arrows, (2) line, (3) sections, (4) histogram from zero //--- (5) histogram on two buffers, (6) zigzag, (7) filling, (8) bars and (9) candles //--- (0 - the very first created buffer with the ХХХ drawing style, 1,2,N - subsequent ones) int BufferColorIndexArrow(const int number,const int series_index); int BufferColorIndexLine(const int number,const int series_index); int BufferColorIndexSection(const int number,const int series_index); int BufferColorIndexHistogram(const int number,const int series_index); int BufferColorIndexHistogram2(const int number,const int series_index); int BufferColorIndexZigZag(const int number,const int series_index); int BufferColorIndexFilling(const int number,const int series_index); int BufferColorIndexBars(const int number,const int series_index); int BufferColorIndexCandles(const int number,const int series_index); //--- Set the color index to the color buffer by its serial number of (1) arrows, (2) line, (3) sections, (4) histogram from zero //--- (5) histogram on two buffers, (6) zigzag, (7) filling, (8) bars and (9) candles //--- (0 - the very first created buffer with the ХХХ drawing style, 1,2,N - subsequent ones) void BufferSetColorIndexArrow(const int number,const int series_index,const int color_index); void BufferSetColorIndexLine(const int number,const int series_index,const int color_index); void BufferSetColorIndexSection(const int number,const int series_index,const int color_index); void BufferSetColorIndexHistogram(const int number,const int series_index,const int color_index); void BufferSetColorIndexHistogram2(const int number,const int series_index,const int color_index); void BufferSetColorIndexZigZag(const int number,const int series_index,const int color_index); void BufferSetColorIndexFilling(const int number,const int series_index,const int color_index); void BufferSetColorIndexBars(const int number,const int series_index,const int color_index); void BufferSetColorIndexCandles(const int number,const int series_index,const int color_index); //--- Set the following for the trading classes:
以下は、描画スタイルと同じ描画スタイルのバッファシリアル番号で特定のバッファデータを返すメソッドです。
//+------------------------------------------------------------------+ //| Return arrow buffer data by its serial number | //| (0 - the very first arrow buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ double CEngine::BufferDataArrow(const int number,const int series_index) { CBufferArrow *buff=this.m_buffers.GetBufferArrow(number); return(buff!=NULL ? buff.GetData(series_index) : EMPTY_VALUE); } //+------------------------------------------------------------------+ //| Return line buffer data by its serial number | //| (0 - the very first line buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ double CEngine::BufferDataLine(const int number,const int series_index) { CBufferLine *buff=this.m_buffers.GetBufferLine(number); return(buff!=NULL ? buff.GetData(series_index) : EMPTY_VALUE); } //+------------------------------------------------------------------+ //| Return section buffer data by its serial number | //| (0 - the very first sections buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ double CEngine::BufferDataSection(const int number,const int series_index) { CBufferSection *buff=this.m_buffers.GetBufferSection(number); return(buff!=NULL ? buff.GetData(series_index) : EMPTY_VALUE); } //+------------------------------------------------------------------+ //| Return histogram buffer data from zero | //| by its serial number | //| (0 - the very first buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ double CEngine::BufferDataHistogram(const int number,const int series_index) { CBufferHistogram *buff=this.m_buffers.GetBufferHistogram(number); return(buff!=NULL ? buff.GetData(series_index) : EMPTY_VALUE); } //+------------------------------------------------------------------+ //| Return histogram zero buffer data on two buffers | //| by its serial number | //| (0 - the very first buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ double CEngine::BufferDataHistogram20(const int number,const int series_index) { CBufferHistogram2 *buff=this.m_buffers.GetBufferHistogram2(number); return(buff!=NULL ? buff.GetData0(series_index) : EMPTY_VALUE); } //+------------------------------------------------------------------+ //| Return histogram first buffer data on two buffers | //| by its serial number | //| (0 - the very first buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ double CEngine::BufferDataHistogram21(const int number,const int series_index) { CBufferHistogram2 *buff=this.m_buffers.GetBufferHistogram2(number); return(buff!=NULL ? buff.GetData1(series_index) : EMPTY_VALUE); } //+------------------------------------------------------------------+ //| Return zigzag zero buffer data | //| by its serial number | //| (0 - the very first zigzag buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ double CEngine::BufferDataZigZag0(const int number,const int series_index) { CBufferZigZag *buff=this.m_buffers.GetBufferZigZag(number); return(buff!=NULL ? buff.GetData0(series_index) : EMPTY_VALUE); } //+------------------------------------------------------------------+ //| Return zigzag first buffer data | //| by its serial number | //| (0 - the very first zigzag buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ double CEngine::BufferDataZigZag1(const int number,const int series_index) { CBufferZigZag *buff=this.m_buffers.GetBufferZigZag(number); return(buff!=NULL ? buff.GetData1(series_index) : EMPTY_VALUE); } //+------------------------------------------------------------------+ //| Return filling zero buffer data | //| by its serial number | //| (0 - the very first filling buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ double CEngine::BufferDataFilling0(const int number,const int series_index) { CBufferFilling *buff=this.m_buffers.GetBufferFilling(number); return(buff!=NULL ? buff.GetData0(series_index) : EMPTY_VALUE); } //+------------------------------------------------------------------+ //| Return filling first buffer data | //| by its serial number | //| (0 - the very first filling buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ double CEngine::BufferDataFilling1(const int number,const int series_index) { CBufferFilling *buff=this.m_buffers.GetBufferFilling(number); return(buff!=NULL ? buff.GetData1(series_index) : EMPTY_VALUE); } //+------------------------------------------------------------------+ //| Return Open data of the bar buffer by its serial number | //| (0 - the very first bar buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ double CEngine::BufferDataBarsOpen(const int number,const int series_index) { CBufferBars *buff=this.m_buffers.GetBufferBars(number); return(buff!=NULL ? buff.GetDataOpen(series_index) : EMPTY_VALUE); } //+------------------------------------------------------------------+ //| Return High data of the bar buffer by its serial number | //| (0 - the very first bar buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ double CEngine::BufferDataBarsHigh(const int number,const int series_index) { CBufferBars *buff=this.m_buffers.GetBufferBars(number); return(buff!=NULL ? buff.GetDataHigh(series_index) : EMPTY_VALUE); } //+------------------------------------------------------------------+ //| Return Low data of the bar buffer by its serial number | //| (0 - the very first bar buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ double CEngine::BufferDataBarsLow(const int number,const int series_index) { CBufferBars *buff=this.m_buffers.GetBufferBars(number); return(buff!=NULL ? buff.GetDataLow(series_index) : EMPTY_VALUE); } //+------------------------------------------------------------------+ //| Return Close data of the bar buffer by its serial number | //| (0 - the very first bar buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ double CEngine::BufferDataBarsClose(const int number,const int series_index) { CBufferBars *buff=this.m_buffers.GetBufferBars(number); return(buff!=NULL ? buff.GetDataClose(series_index) : EMPTY_VALUE); } //+------------------------------------------------------------------+ //| Return Open data of the candle buffer by its serial number | //| (0 - the very first candle buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ double CEngine::BufferDataCandlesOpen(const int number,const int series_index) { CBufferCandles *buff=this.m_buffers.GetBufferCandles(number); return(buff!=NULL ? buff.GetDataOpen(series_index) : EMPTY_VALUE); } //+------------------------------------------------------------------+ //| Return High data of the candle buffer by its serial number | //| (0 - the very first candle buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ double CEngine::BufferDataCandlesHigh(const int number,const int series_index) { CBufferCandles *buff=this.m_buffers.GetBufferCandles(number); return(buff!=NULL ? buff.GetDataHigh(series_index) : EMPTY_VALUE); } //+------------------------------------------------------------------+ //| Return Low data of the candle buffer by its serial number | //| (0 - the very first candle buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ double CEngine::BufferDataCandlesLow(const int number,const int series_index) { CBufferCandles *buff=this.m_buffers.GetBufferCandles(number); return(buff!=NULL ? buff.GetDataLow(series_index) : EMPTY_VALUE); } //+------------------------------------------------------------------+ //| Return Close data of the candle buffer by its serial number | //| (0 - the very first candle buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ double CEngine::BufferDataCandlesClose(const int number,const int series_index) { CBufferCandles *buff=this.m_buffers.GetBufferCandles(number); return(buff!=NULL ? buff.GetDataClose(series_index) : EMPTY_VALUE); } //+------------------------------------------------------------------+
すべてのメソッドは同じです。Candles描画スタイルでバッファオブジェクトのCloseバッファ値を返すメソッドを考えてみましょう。
このメソッドは、Candlesスタイルの作成されたすべてのバッファからCandlesスタイルのバッファシリアル番号を受け取り(特定の描画スタイルのバッファ番号が何を意味するかを上で詳細に検討しました)、CloseCandleバッファデータを取得する必要がある時系列インデックスを受け取ります。
バッファコレクションクラスのGetBufferCandles()メソッドを使用して、必要なバッファへのポインタを受け取ります。バッファを受け取った場合は、指定された時系列インデックスでCloseバッファからデータを返します。その他の場合は「空の値」を返します。
今説明したのとは反対のメソッドです。描画スタイルとシリアル番号によって、適切なバッファオブジェクトの特定のバッファの値を指定された時系列インデックスに設定します。
//+------------------------------------------------------------------+ //| Set arrow buffer data by its serial number | //| (0 - the very first arrow buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ void CEngine::BufferSetDataArrow(const int number,const int series_index,const double value) { CBufferArrow *buff=this.m_buffers.GetBufferArrow(number); if(buff==NULL) return; buff.SetData(series_index,value); } //+------------------------------------------------------------------+ //| Set line buffer data by its serial number | //| (0 - the very first line buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ void CEngine::BufferSetDataLine(const int number,const int series_index,const double value) { CBufferLine *buff=this.m_buffers.GetBufferLine(number); if(buff==NULL) return; buff.SetData(series_index,value); } //+------------------------------------------------------------------+ //| Set section buffer data by its serial number | //| (0 - the very first sections buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ void CEngine::BufferSetDataSection(const int number,const int series_index,const double value) { CBufferSection *buff=this.m_buffers.GetBufferSection(number); if(buff==NULL) return; buff.SetData(series_index,value); } //+------------------------------------------------------------------+ //| Set histogram buffer data from zero | //| by its serial number | //| (0 - the very first buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ void CEngine::BufferSetDataHistogram(const int number,const int series_index,const double value) { CBufferHistogram *buff=this.m_buffers.GetBufferHistogram(number); if(buff==NULL) return; buff.SetData(series_index,value); } //+------------------------------------------------------------------+ //| Set histogram zero buffer data on two buffers | //| by its serial number | //| (0 - the very first buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ void CEngine::BufferSetDataHistogram20(const int number,const int series_index,const double value) { CBufferHistogram2 *buff=this.m_buffers.GetBufferHistogram2(number); if(buff==NULL) return; buff.SetData0(series_index,value); } //+------------------------------------------------------------------+ //| Set histogram first buffer data on two buffers | //| by its serial number | //| (0 - the very first buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ void CEngine::BufferSetDataHistogram21(const int number,const int series_index,const double value) { CBufferHistogram2 *buff=this.m_buffers.GetBufferHistogram2(number); if(buff==NULL) return; buff.SetData1(series_index,value); } //+------------------------------------------------------------------+ //| Set data of all histogram buffers on two buffers | //| by its serial number | //| (0 - the very first buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ void CEngine::BufferSetDataHistogram2(const int number,const int series_index,const double value0,const double value1) { CBufferHistogram2 *buff=this.m_buffers.GetBufferHistogram2(number); if(buff==NULL) return; buff.SetData0(series_index,value0); buff.SetData1(series_index,value1); } //+------------------------------------------------------------------+ //| Set zigzag zero buffer data | //| by its serial number | //| (0 - the very first zigzag buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ void CEngine::BufferSetDataZigZag0(const int number,const int series_index,const double value) { CBufferZigZag *buff=this.m_buffers.GetBufferZigZag(number); if(buff==NULL) return; buff.SetData0(series_index,value); } //+------------------------------------------------------------------+ //| Set zigzag first buffer data | //| by its serial number | //| (0 - the very first zigzag buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ void CEngine::BufferSetDataZigZag1(const int number,const int series_index,const double value) { CBufferZigZag *buff=this.m_buffers.GetBufferZigZag(number); if(buff==NULL) return; buff.SetData1(series_index,value); } //+------------------------------------------------------------------+ //| Set data of all zizag buffers | //| by its serial number | //| (0 - the very first zigzag buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ void CEngine::BufferSetDataZigZag(const int number,const int series_index,const double value0,const double value1) { CBufferZigZag *buff=this.m_buffers.GetBufferZigZag(number); if(buff==NULL) return; buff.SetData0(series_index,value0); buff.SetData1(series_index,value1); } //+------------------------------------------------------------------+ //| Set filling zero buffer data | //| by its serial number | //| (0 - the very first filling buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ void CEngine::BufferSetDataFilling0(const int number,const int series_index,const double value) { CBufferFilling *buff=this.m_buffers.GetBufferFilling(number); if(buff==NULL) return; buff.SetData0(series_index,value); } //+------------------------------------------------------------------+ //| Set filling first buffer data | //| by its serial number | //| (0 - the very first filling buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ void CEngine::BufferSetDataFilling1(const int number,const int series_index,const double value) { CBufferFilling *buff=this.m_buffers.GetBufferFilling(number); if(buff==NULL) return; buff.SetData1(series_index,value); } //+------------------------------------------------------------------+ //| Set data of all filling buffers | //| by its serial number | //| (0 - the very first filling buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ void CEngine::BufferSetDataFilling(const int number,const int series_index,const double value0,const double value1) { CBufferFilling *buff=this.m_buffers.GetBufferFilling(number); if(buff==NULL) return; buff.SetData0(series_index,value0); buff.SetData1(series_index,value1); } //+------------------------------------------------------------------+ //| Set buffer data of Open bars | //| by its serial number | //| (0 - the very first bar buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ void CEngine::BufferSetDataBarsOpen(const int number,const int series_index,const double value) { CBufferBars *buff=this.m_buffers.GetBufferBars(number); if(buff==NULL) return; buff.SetDataOpen(series_index,value); } //+------------------------------------------------------------------+ //| Set buffer data of High bars | //| by its serial number | //| (0 - the very first bar buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ void CEngine::BufferSetDataBarsHigh(const int number,const int series_index,const double value) { CBufferBars *buff=this.m_buffers.GetBufferBars(number); if(buff==NULL) return; buff.SetDataHigh(series_index,value); } //+------------------------------------------------------------------+ //| Set buffer data of Low bars | //| by its serial number | //| (0 - the very first bar buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ void CEngine::BufferSetDataBarsLow(const int number,const int series_index,const double value) { CBufferBars *buff=this.m_buffers.GetBufferBars(number); if(buff==NULL) return; buff.SetDataLow(series_index,value); } //+------------------------------------------------------------------+ //| Set buffer data of Close bars | //| by its serial number | //| (0 - the very first bar buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ void CEngine::BufferSetDataBarsClose(const int number,const int series_index,const double value) { CBufferBars *buff=this.m_buffers.GetBufferBars(number); if(buff==NULL) return; buff.SetDataClose(series_index,value); } //+------------------------------------------------------------------+ //| Set buffer data of Open candles | //| by its serial number | //| (0 - the very first candle buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ void CEngine::BufferSetDataCandlesOpen(const int number,const int series_index,const double value) { CBufferCandles *buff=this.m_buffers.GetBufferCandles(number); if(buff==NULL) return; buff.SetDataOpen(series_index,value); } //+------------------------------------------------------------------+ //| Set buffer data of High candles | //| by its serial number | //| (0 - the very first candle buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ void CEngine::BufferSetDataCandlesHigh(const int number,const int series_index,const double value) { CBufferCandles *buff=this.m_buffers.GetBufferCandles(number); if(buff==NULL) return; buff.SetDataHigh(series_index,value); } //+------------------------------------------------------------------+ //| Set buffer data of Low candles | //| by its serial number | //| (0 - the very first candle buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ void CEngine::BufferSetDataCandlesLow(const int number,const int series_index,const double value) { CBufferCandles *buff=this.m_buffers.GetBufferCandles(number); if(buff==NULL) return; buff.SetDataLow(series_index,value); } //+------------------------------------------------------------------+ //| Set buffer data of Close candles | //| by its serial number | //| (0 - the very first candle buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ void CEngine::BufferSetDataCandlesClose(const int number,const int series_index,const double value) { CBufferCandles *buff=this.m_buffers.GetBufferCandles(number); if(buff==NULL) return; buff.SetDataClose(series_index,value); } //+------------------------------------------------------------------+
すべてのメソッドは同じです。時系列インデックスによる値を、シリアル番号によるCandles描画スタイルのバッファオブジェクトのCloseバッファに設定するメソッドを考えてみましょう。
バッファコレクションクラスのGetBufferCandles()メソッドを使用して、Candles描画スタイルのバッファオブジェクトをシリアル番号で取得します。
オブジェクトの取得に失敗した場合は、メソッドを終了します。メソッドに渡された値を、取得した必要なバッファオブジェクトのCloseバッファに時系列インデックスで設定します。
指定された時系列インデックスによってOHLC値をBarsおよびCandlesバッファオブジェクトのすべてのバッファに同時に設定する、さらに2つの個別のメソッドがあります。
//+------------------------------------------------------------------+ //| Set data of all bar buffers | //| by its serial number | //| (0 - the very first bar buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ void CEngine::BufferSetDataBars(const int number,const int series_index,const double open,const double high,const double low,const double close) { CBufferBars *buff=this.m_buffers.GetBufferBars(number); if(buff==NULL) return; buff.SetDataOpen(series_index,open); buff.SetDataHigh(series_index,high); buff.SetDataLow(series_index,low); buff.SetDataClose(series_index,close); } //+------------------------------------------------------------------+ //| Set data of all candle buffers | //| by its serial number | //| (0 - the very first candle buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ void CEngine::BufferSetDataCandles(const int number,const int series_index,const double open,const double high,const double low,const double close) { CBufferCandles *buff=this.m_buffers.GetBufferCandles(number); if(buff==NULL) return; buff.SetDataOpen(series_index,open); buff.SetDataHigh(series_index,high); buff.SetDataLow(series_index,low); buff.SetDataClose(series_index,close); } //+------------------------------------------------------------------+
ここではすべて上記と同じです。ただし、4つのバッファオブジェクトバッファすべてのすべての値が渡され、メソッドに設定されます。
以下は、描画スタイルとシリアル番号によって、指定された色を特定のバッファオブジェクトのカラーバッファ時系列の指定されたインデックスに返すメソッドです。
//+------------------------------------------------------------------+ //| Return the arrow buffer color by its serial number | //| (0 - the very first arrow buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ color CEngine::BufferColorArrow(const int number,const int series_index) { CBufferArrow *buff=this.m_buffers.GetBufferArrow(number); return(buff!=NULL ? buff.GetColorBufferValueColor(series_index) : clrNONE); } //+------------------------------------------------------------------+ //| Return the line buffer color by its serial number | //| (0 - the very first candle line, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ color CEngine::BufferColorLine(const int number,const int series_index) { CBufferLine *buff=this.m_buffers.GetBufferLine(number); return(buff!=NULL ? buff.GetColorBufferValueColor(series_index) : clrNONE); } //+------------------------------------------------------------------+ //| Return the section buffer color by its serial number | //| (0 - the very first sections buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ color CEngine::BufferColorSection(const int number,const int series_index) { CBufferSection *buff=this.m_buffers.GetBufferSection(number); return(buff!=NULL ? buff.GetColorBufferValueColor(series_index) : clrNONE); } //+------------------------------------------------------------------+ //| Return histogram buffer color from zero | //| by its serial number | //| (0 - the very first buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ color CEngine::BufferColorHistogram(const int number,const int series_index) { CBufferHistogram *buff=this.m_buffers.GetBufferHistogram(number); return(buff!=NULL ? buff.GetColorBufferValueColor(series_index) : clrNONE); } //+------------------------------------------------------------------+ //| Return histogram buffer color on two buffers | //| by its serial number | //| (0 - the very first buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ color CEngine::BufferColorHistogram2(const int number,const int series_index) { CBufferHistogram2 *buff=this.m_buffers.GetBufferHistogram2(number); return(buff!=NULL ? buff.GetColorBufferValueColor(series_index) : clrNONE); } //+------------------------------------------------------------------+ //| Return the zigzag buffer color by its serial number | //| (0 - the very first zigzag buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ color CEngine::BufferColorZigZag(const int number,const int series_index) { CBufferZigZag *buff=this.m_buffers.GetBufferZigZag(number); return(buff!=NULL ? buff.GetColorBufferValueColor(series_index) : clrNONE); } //+------------------------------------------------------------------+ //| Return the filling buffer color by its serial number | //| (0 - the very first filling buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ color CEngine::BufferColorFilling(const int number,const int series_index) { CBufferFilling *buff=this.m_buffers.GetBufferFilling(number); return(buff!=NULL ? buff.GetColorBufferValueColor(series_index) : clrNONE); } //+------------------------------------------------------------------+ //| Return the bar buffer color by its serial number | //| (0 - the very first bar buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ color CEngine::BufferColorBars(const int number,const int series_index) { CBufferBars *buff=this.m_buffers.GetBufferBars(number); return(buff!=NULL ? buff.GetColorBufferValueColor(series_index) : clrNONE); } //+------------------------------------------------------------------+ //| Return the candle buffer color by its serial number | //| (0 - the very first candle buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ color CEngine::BufferColorCandles(const int number,const int series_index) { CBufferCandles *buff=this.m_buffers.GetBufferCandles(number); return(buff!=NULL ? buff.GetColorBufferValueColor(series_index) : clrNONE); } //+------------------------------------------------------------------+
ここではすべてが似ています。必要なバッファオブジェクトをその番号で取得します、オブジェクトを取得できた場合は 指定された時系列インデックスでカラーバッファに設定された色を返します。その他の場合は、「色が未設定」を返します。
(カラー値ではなく)カラーインデックス値は実際にはカラーバッファに設定されているため、特定のバッファオブジェクトのカラーインデックスを指定された時系列インデックスによってカラーバッファから返す適切なメソッドがあります。
//+------------------------------------------------------------------+ //| Return the arrow buffer color index by its serial number | //| (0 - the very first arrow buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ int CEngine::BufferColorIndexArrow(const int number,const int series_index) { CBufferArrow *buff=this.m_buffers.GetBufferArrow(number); return(buff!=NULL ? buff.GetColorBufferValueIndex(series_index) : WRONG_VALUE); } //+------------------------------------------------------------------+ //| Return the line buffer color index by its serial number | //| (0 - the very first candle line, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ int CEngine::BufferColorIndexLine(const int number,const int series_index) { CBufferLine *buff=this.m_buffers.GetBufferLine(number); return(buff!=NULL ? buff.GetColorBufferValueIndex(series_index) : WRONG_VALUE); } //+------------------------------------------------------------------+ //| Return the section buffer color index by its serial number | //| (0 - the very first sections buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ int CEngine::BufferColorIndexSection(const int number,const int series_index) { CBufferSection *buff=this.m_buffers.GetBufferSection(number); return(buff!=NULL ? buff.GetColorBufferValueIndex(series_index) : WRONG_VALUE); } //+------------------------------------------------------------------+ //| Return histogram buffer color index from zero | //| by its serial number | //| (0 - the very first buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ int CEngine::BufferColorIndexHistogram(const int number,const int series_index) { CBufferHistogram *buff=this.m_buffers.GetBufferHistogram(number); return(buff!=NULL ? buff.GetColorBufferValueIndex(series_index) : WRONG_VALUE); } //+------------------------------------------------------------------+ //| Return histogram buffer color index on two buffers | //| by its serial number | //| (0 - the very first buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ int CEngine::BufferColorIndexHistogram2(const int number,const int series_index) { CBufferHistogram2 *buff=this.m_buffers.GetBufferHistogram2(number); return(buff!=NULL ? buff.GetColorBufferValueIndex(series_index) : WRONG_VALUE); } //+------------------------------------------------------------------+ //| Return the zigzag buffer color index by its serial number | //| (0 - the very first zigzag buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ int CEngine::BufferColorIndexZigZag(const int number,const int series_index) { CBufferZigZag *buff=this.m_buffers.GetBufferZigZag(number); return(buff!=NULL ? buff.GetColorBufferValueIndex(series_index) : WRONG_VALUE); } //+------------------------------------------------------------------+ //| Return the filling buffer color index by its serial number | //| (0 - the very first filling buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ int CEngine::BufferColorIndexFilling(const int number,const int series_index) { CBufferFilling *buff=this.m_buffers.GetBufferFilling(number); return(buff!=NULL ? buff.GetColorBufferValueIndex(series_index) : WRONG_VALUE); } //+------------------------------------------------------------------+ //| Return the bar buffer color index by its serial number | //| (0 - the very first bar buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ int CEngine::BufferColorIndexBars(const int number,const int series_index) { CBufferBars *buff=this.m_buffers.GetBufferBars(number); return(buff!=NULL ? buff.GetColorBufferValueIndex(series_index) : WRONG_VALUE); } //+------------------------------------------------------------------+ //| Return the candle buffer color index by its serial number | //| (0 - the very first candle buffer, 1,2,N - subsequent ones) | //+------------------------------------------------------------------+ int CEngine::BufferColorIndexCandles(const int number,const int series_index) { CBufferCandles *buff=this.m_buffers.GetBufferCandles(number); return(buff!=NULL ? buff.GetColorBufferValueIndex(series_index) : WRONG_VALUE); } //+------------------------------------------------------------------+
ここでのすべては、メソッドがカラーインデックスを返すことを除いて、カラーを返すメソッドと同じです。
これらはすべて、指標バッファのコレクションクラスをテストするために必要なCEngineクラスの改善です。
バッファコレクションを使用して指標を作成する機能のテスト
バッファコレクションクラスをテストするために、前の記事の指標を使用して、新しいフォルダ\MQL5\Indicators\TestDoEasy\Part44\にTestDoEasyPart44.mq5として保存します。
ヘッダ全体は次のようになります。
//+------------------------------------------------------------------+ //| TestDoEasyPart44.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> //--- properties #property indicator_chart_window #property indicator_buffers 28 #property indicator_plots 10 //--- classes //--- enums //--- defines //--- structures //--- input variables /*sinput*/ ENUM_SYMBOLS_MODE InpModeUsedSymbols= SYMBOLS_MODE_CURRENT; // Mode of used symbols list /*sinput*/ string InpUsedSymbols = "EURUSD,AUDUSD,EURAUD,EURGBP,EURCAD,EURJPY,EURUSD,GBPUSD,NZDUSD,USDCAD,USDJPY"; // List of used symbols (comma - separator) /*sinput*/ ENUM_TIMEFRAMES_MODE InpModeUsedTFs = TIMEFRAMES_MODE_CURRENT; // Mode of used timeframes list /*sinput*/ string InpUsedTFs = "M1,M5,M15,M30,H1,H4,D1,W1,MN1"; // List of used timeframes (comma - separator) sinput ENUM_INPUT_YES_NO InpDrawArrow = INPUT_YES; // Draw Arrow sinput ENUM_INPUT_YES_NO InpDrawLine = INPUT_NO; // Draw Line sinput ENUM_INPUT_YES_NO InpDrawSection = INPUT_NO; // Draw Section sinput ENUM_INPUT_YES_NO InpDrawHistogram = INPUT_NO; // Draw Histogram sinput ENUM_INPUT_YES_NO InpDrawHistogram2 = INPUT_NO; // Draw Histogram2 sinput ENUM_INPUT_YES_NO InpDrawZigZag = INPUT_NO; // Draw ZigZag sinput ENUM_INPUT_YES_NO InpDrawFilling = INPUT_NO; // Draw Filling sinput ENUM_INPUT_YES_NO InpDrawBars = INPUT_NO; // Draw Bars sinput ENUM_INPUT_YES_NO InpDrawCandles = INPUT_YES; // Draw Candles sinput bool InpUseSounds = true; // Use sounds //--- indicator buffers CArrayObj *list_buffers; // Pointer to the buffer object list //--- global variables CEngine engine; // CEngine library main object string prefix; // Prefix of graphical object names int min_bars; // The minimum number of bars for the indicator calculation int used_symbols_mode; // Mode of working with symbols string array_used_symbols[]; // The array for passing used symbols to the library string array_used_periods[]; // The array for passing used timeframes to the library //+------------------------------------------------------------------+
すべてのバッファオブジェクトファイルのインクルードを「includes」ブロックから削除します。これらはすでにライブラリにインクルードされています。
//--- includes #include <DoEasy\Engine.mqh> #include <DoEasy\Objects\Indicators\BufferArrow.mqh> // 1 construction buffer + 1 color buffer #include <DoEasy\Objects\Indicators\BufferLine.mqh> // 1 construction buffer + 1 color buffer #include <DoEasy\Objects\Indicators\BufferSection.mqh> // 1 construction buffer + 1 color buffer #include <DoEasy\Objects\Indicators\BufferHistogram.mqh> // 1 construction buffer + 1 color buffer #include <DoEasy\Objects\Indicators\BufferHistogram2.mqh> // 2 construction buffers + 1 color buffer #include <DoEasy\Objects\Indicators\BufferZigZag.mqh> // 2 construction buffers + 1 color buffer #include <DoEasy\Objects\Indicators\BufferFilling.mqh> // 2 construction buffers + 1 color buffer #include <DoEasy\Objects\Indicators\BufferBars.mqh> // 4 construction buffer + 1 color buffer #include <DoEasy\Objects\Indicators\BufferCandles.mqh> // 4 construction buffer + 1 color buffer //--- In total: 18 construction buffers + 9 color buffers: 27 indicator buffers, of which 9 are drawn ones //--- properties
コンパイラの描画バッファとインジケータバッファの数を設定します。
#property indicator_buffers 28 #property indicator_plots 10
指標に複数のさまざまなバッファが予想される場合は、「指を数える」のではなく、初期段階で任意の値を設定するだけで済みます。指標を初めて起動すると、誤って指定した場合に備えて、描画されたバッファと指標バッファの有効な数を示すアラートが表示されます。
ライブラリは、作成された指標バッファに、作成順に描画スタイルと番号でアクセスすることを意味します。プログラムから直接バッファプロパティにアクセスすることはまだ実装されていません。これまでのところ、バッファ配列にアクセスすることしかできません。今日は、コレクションからバッファオブジェクトのリストを受け取り、リストから直接バッファにアクセスして(このような機能はすべてのオブジェクトコレクションに存在します)、作成されたオブジェクトを直接操作することで、この制限を回避します。したがって、CObjectオブジェクトへのポインタの動的配列を「指標バッファ」として使用しましょう。
OnInit()ハンドラで、テストに必要なバッファを準備し、2つの異なる方法でアクセスできるかどうかを確認します。
//+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- Initialize DoEasy library OnInitDoEasy(); //--- Set indicator global variables prefix=engine.Name()+"_"; //--- Get the index of the maximum used timeframe in the array, //--- calculate the number of bars of the current period fitting in the maximum used period //--- Use the obtained value if it exceeds 2, otherwise use 2 int index=ArrayMaximum(ArrayUsedTimeframes); int num_bars=NumberBarsInTimeframe(ArrayUsedTimeframes[index]); min_bars=(index>WRONG_VALUE ? (num_bars>2 ? num_bars : 2) : 2); //--- Check and remove remaining indicator graphical objects if(IsPresentObectByPrefix(prefix)) ObjectsDeleteAll(0,prefix); //--- Create the button panel //--- Check playing a standard sound using macro substitutions engine.PlaySoundByDescription(SND_OK); //--- Wait for 600 milliseconds engine.Pause(600); engine.PlaySoundByDescription(SND_NEWS); //--- indicator buffers mapping //--- Create all the necessary buffer objects engine.BufferCreateArrow(); engine.BufferCreateLine(); engine.BufferCreateSection(); engine.BufferCreateHistogram(); engine.BufferCreateHistogram2(); engine.BufferCreateZigZag(); engine.BufferCreateFilling(); engine.BufferCreateBars(); engine.BufferCreateCandles(); engine.BufferCreateArrow(); //--- Check the number of buffers specified in the 'properties' block if(engine.BufferPlotsTotal()!=indicator_plots) Alert(TextByLanguage("Внимание! Значение \"indicator_plots\" должно быть ","Attention! Value of \"indicator_plots\" should be "),engine.BufferPlotsTotal()); if(engine.BuffersTotal()!=indicator_buffers) Alert(TextByLanguage("Внимание! Значение \"indicator_buffers\" должно быть ","Attention! Value of \"indicator_buffers\" should be "),engine.BuffersTotal()); //--- Create color array color array_colors[]={clrDodgerBlue,clrRed,clrGray}; //--- Get the pointer to the collection list of buffer objects and //--- set non-default color values for buffers in a loop according to the list list_buffers=engine.GetListBuffers(); for(int i=0;i<list_buffers.Total();i++) { CBuffer *buff=list_buffers.At(i); buff.SetColors(array_colors); //--- Print data on the next buffer buff.Print(); } //--- Set the line width for ZigZag (the sixth drawn buffer) //--- It has the index of 5 considering that the starting point is zero CBuffer *buff_zz=engine.GetBufferByPlot(5); if(buff_zz!=NULL) { buff_zz.SetWidth(2); } //--- Get the second arrow buffer (created last). //--- The first arrow buffer has the number of 0, while the second one has the number of 1 //--- Set the arrow size of 2 and the code of 161 CBuffer *buff=engine.GetBufferArrow(1); if(buff!=NULL) { buff.SetWidth(2); buff.SetArrowCode(161); } //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+
バッファの作成が簡単になりました。あるタイプまたは別のタイプの指標バッファを作成するように設計されたライブラリメソッドを使用します。ライブラリはすべての配列関数を引き継ぎ、作成されたバッファのプロパティを作成後に変更できます。すぐに指標ヘッダの#propertyで指定された数のバッファを確認します。バッファ数の指定を間違えた場合は、適切な警告が表示されます。このようなチェックは、指標を開発するときに便利です。その後、コードから削除できます。
バッファへのアクセスをテストするために2つのメソッドを使用してみましょう。
まず、GetBufferByPlot()メソッドを使用して、描画されたバッファインデックスによってジグザグバッファにアクセスします。このメソッドでは、描画されたバッファインデックスが指定されます(ここではインデックスです)。ジグザグの場合は5)、
次に、最後に作成された最後の矢印バッファにアクセスします。それは2番目の矢印バッファです。GetBufferArrow()メソッドを使用してアクセスしましょう。このメソッドでは、必要な矢印バッファのシリアル番号を指定します(ここでは、カウントはゼロから始まるため、番号は1です)。
OnCalculate()ハンドラは、データがローソク足バッファオブジェクトメソッドを使用してキャンドルバッファとバーバッファに設定されることを除いて、ほとんど変更されていません(データを1つずつOpen、High、Low、およびCloseに書き込みます)。また、すべてのOHLC値を一度にバーバッファ配列に書き込みます。したがって、バッファオブジェクトを操作するために作成されたすべてのメソッドの動作を確認できます。
//--- Calculate the indicator for(int i=limit; i>WRONG_VALUE && !IsStopped(); i--) { //--- In a loop by the number of buffers in the list for(int j=0;j<total;j++) { //--- get the next buffer and CBuffer *buff=list_buffers.At(j); //--- clear its current data buff.ClearData(0); //--- If drawing is not used, move on to the next one if(!IsUse(buff.Status())) continue; //--- Depending on the number of buffers, fill them with price data //--- one buffer if(buff.BuffersTotal()==1) buff.SetBufferValue(0,i,close[i]); //--- two buffers - the first one is to store the bar open price, while the second one is to store the bar close price else if(buff.BuffersTotal()==2) { buff.SetBufferValue(0,i,open[i]); buff.SetBufferValue(1,i,close[i]); } //--- four buffers - each buffer is to store OHLC bar prices else if(buff.BuffersTotal()==4) { //--- If this is the candle buffer if(buff.Status()==BUFFER_STATUS_CANDLES) { //--- create the pointer to the candle buffer object by assigning the pointer to the abstract buffer object to it //--- and write the appropriate timeseries data to the "candle" object buffers CBufferCandles *candle=buff; candle.SetDataOpen(i,open[i]); candle.SetDataHigh(i,high[i]); candle.SetDataLow(i,low[i]); candle.SetDataClose(i,close[i]); } //--- If this is the bar buffer, use access to the first (and only) created bar buffer object //--- and write the appropriate timeseries data to the "bars" object buffers in one go else { engine.BufferSetDataBars(0,i,open[i],high[i],low[i],close[i]); } } //--- Set the buffer color depending on the candle direction if(open[i]<close[i]) buff.SetBufferColorIndex(i,0); else if(open[i]>close[i]) buff.SetBufferColorIndex(i,1); else buff.SetBufferColorIndex(i,2); } } //--- return value of prev_calculated for next call
完全な指標コードは、以下に添付されているファイルで提供されます。
指標をコンパイルして、銘柄チャートで起動します。設定で単一の矢印バッファを表示するように設定します。このバッファは、チャート上にドットとして表示されます。ただし、最後に作成された2番目の矢印バッファもあります。OnInit()の2番目の矢印バッファにアクセスして、コードとアイコンのサイズを変更しました。したがって、バッファオブジェクトを操作するために作成されたすべてのメソッドの動作を確認できます。
//--- Get the second arrow buffer (created last). //--- The first arrow buffer has the number of 0, while the second one has the number of 1 //--- Set the arrow size of 2 and the code of 161 CBuffer *buff=engine.GetBufferArrow(1); if(buff!=NULL) { buff.SetWidth(2); buff.SetArrowCode(161); }
特定のバッファタイプに番号でアクセスしてオブジェクトを取得できた場合、2つの矢印バッファがグラフに表示されます。最初のバッファはドットで表示され、2番目のバッファはサイズが2の円で表示されます。
Plotインデックスでバッファオブジェクトを返すメソッドを使用してジグザグバッファを受信することにより、ジグザグ線幅を設定しました。ジグザグ表示を接続し、その線幅がOnInit()で設定された線幅に対応していることを確認します。
//--- Set the line width for ZigZag (the sixth drawn buffer) //--- It has the index of 5 considering that the starting point is zero CBuffer *buff_zz=engine.GetBufferByPlot(5); if(buff_zz!=NULL) { buff_zz.SetWidth(2); }
最後に、バーとローソク足がどのように表示されるかを見てみましょう。バッファ配列に価格値を書き込むメソッドが機能する場合は、バーとローソク足がチャートに正しく表示されるはずです。
確認しましょう。
ご覧のとおり、すべてが想定どおりに機能します。
次の段階
次の記事では、複数銘柄モードと複数期間モードでの指標操作の配置に関して、指標バッファコレクションクラスの開発を継続します。
現在のバージョンのライブラリのすべてのファイルは、テスト用EAファイルと一緒に以下に添付されているので、テストするにはダウンロードしてください。
質問、コメント、提案はコメント欄にお願いします。テスト指標はMQL5向けに開発されたのでご注意ください。
添付ファイルはMetaTrader 5のみを対象としています。現在のライブラリバージョンはMetaTrader 4ではテストされていません。
指標バッファコレクションを作成してテストした後で、MetaTrader 4にいくつかのMQL5機能を実装してみます。
シリーズのこれまでの記事:
DoEasyライブラリの時系列(第35部): バーオブジェクトと銘柄の時系列リスト
DoEasyライブラリの時系列(第36部): すべての使用銘柄期間の時系列オブジェクト
DoEasyライブラリの時系列(第37部): すべての使用銘柄期間の時系列オブジェクト
DoEasyライブラリの時系列(第38部): 時系列コレクション-リアルタイムの更新とプログラムからのデータへのアクセス
DoEasyライブラリの時系列(第39部): ライブラリに基づいた指標 - データイベントと時系列イベントの準備
DoEasyライブラリの時系列(第40部): ライブラリに基づいた指標 - 実時間でのデータ更新
DoEasyライブラリの時系列(第41部): 複数銘柄・複数期間指標の例
DoEasyライブラリの時系列(第42部): 抽象指標バッファオブジェクトクラス
DoEasyライブラリの時系列(第43部): 指標バッファオブジェクトクラス
MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/7886




- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索