
MetaTraderプログラムを簡単かつ迅速に開発するためのライブラリ(第16部): 銘柄コレクションイベント
内容
- すべてのライブラリオブジェクトの基本オブジェクトクラス
- 銘柄コレクションイベント
- 口座イベントクラスの改善
- 銘柄イベントクラスと改善された口座クラスの使用
- 銘柄イベントと口座イベントのテスト
- 次の段階
第12部で口座オブジェクトと口座コレクションを作成したとき、また第13部で現在の口座イベントを追跡したとき、イベントをEngineオブジェクトに送信する新しい型のオブジェクトを作成する必要性に気づきました 。
口座イベント追跡の原則は、第4部で検討を開始した、取引イベントの追跡時に適用されるものとは異なります取引イベントが、以前に発生したイベントへの本格的なアクセスのために定義され、取引イベントのコレクションに送信される一方、口座イベントは単にリアルタイムで動作します。イベントはライブラリ基本オブジェクトに送信される前に定義されてEventChartCustom()を使用してプログラムを持つチャートに送信されます。その後、同時に発生したイベントのリストにライブラリの基本オブジェクトからアクセスできるようになり、プログラムで処理できます。これが、口座オブジェクトでイベントが配置される方法です。
ここで、ほとんどすべてのオブジェクトには他のオブジェクトと共通するプロパティがあり、開発中には新しいオブジェクトがあるごとにこれらのプロパティを何度も設定していることがわかります。
これは、すべてのライブラリオブジェクトの継承元となる基本オブジェクトを作成する必要があるという明確な決定につながります。現在、それらは標準ライブラリのCObject基本オブジェクトから継承されています。CObjectから派生した別のオブジェクトを作成し、ライブラリのすべてのオブジェクトをそこから継承することにします。したがって、各オブジェクトに共通するすべてのプロパティは、基本オブジェクトで一度設定されて、すべての子孫オブジェクトには、これらのプロパティが自動的に付与されます。
最も興味深いことに、イベントオブジェクトを作成して基本オブジェクトに書き込むことができるようになった一方、すべてのライブラリオブジェクトはイベントをプログラムに送信できるということです。これはまさにライブラリの概念に必要なものです。オブジェクトはプログラムに自己のステータスを通知できる必要があり、ライブラリとプログラムはオブジェクトからの適切なメッセージを処理し、オブジェクトイベントを特定(プログラム)または処理(ライブラリ)する必要があります。これにより、ライブラリはオブジェクトイベントの処理を目的としたすべてのアクションを引き継ぐため、ライブラリの対話性が向上し、エンドユーザーによるプログラムの開発が大幅に簡素化されます。
オブジェクトイベント構造体は、EventChartCustom()関数によってイベントID、long、double、stringパラメータを送信するために必要なデータを繰り返すことになります。プログラムに送信されるすべてのイベントデータが、イベント登録中にイベントが発生したオブジェクトのクラスにすぐに書き込まれるため、プログラムへのイベント送信が簡単になります。それを取得し、さらに処理するためにプログラムにリダイレクトするだけです。
開発を始めましょう。まず、イベントオブジェクトを作成し、次に基本オブジェクトを作成します。その後、銘柄コレクションイベントの追跡を実装し、口座イベントクラスの概念を念頭に置いて調整を行います。取引イベントは、その構造が完全に異なり、概念と矛盾するため、そのまま残ります。その上、取引イベントはすでに完成しており、データをプログラムに送信します。
すべてのライブラリオブジェクトの基本オブジェクトクラス
\MQL5\Include\DoEasy\Objects\ライブラリフォルダで、新しいCBaseObj クラスをBaseObj.mqhファイルで作成します。CObject標準ライブラリオブジェクトクラスがクラスの基本クラスとなります。 クラスは比較的小さいので、ここでそのコード全体を提供します。その後、メンバとメソッドごとに分析します。
オブジェクトイベントクラスの新しいファイルを作成しないようにするには、同じファイルの基本クラスの前にそのクラスを記述します。//+------------------------------------------------------------------+ //| BaseObj.mqh | //| Copyright 2018, MetaQuotes Software Corp. | //| https://mql5.com/ja/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2018, MetaQuotes Software Corp." #property link "https://mql5.com/ja/users/artmedia70" #property version "1.00" #property strict // mql4で必要 //+------------------------------------------------------------------+ //| ファイルをインクルードする | //+------------------------------------------------------------------+ #include <Arrays\ArrayObj.mqh> #include "..\Services\DELib.mqh" //+------------------------------------------------------------------+ //| Base object event class for all library objects | //+------------------------------------------------------------------+ class CEventBaseObj : public CObject { private: long m_time; long m_chart_id; ushort m_event_id; long m_lparam; double m_dparam; string m_sparam; public: void Time(const long time) { this.m_time=time; } long Time(void) const { return this.m_time; } void ChartID(const long chart_id) { this.m_chart_id=chart_id; } long ChartID(void) const { return this.m_chart_id; } void ID(const ushort id) { this.m_event_id=id; } ushort ID(void) const { return this.m_event_id; } void LParam(const long lparam) { this.m_lparam=lparam; } long LParam(void) const { return this.m_lparam; } void DParam(const double dparam) { this.m_dparam=dparam; } double DParam(void) const { return this.m_dparam; } void SParam(const string sparam) { this.m_sparam=sparam; } string SParam(void) const { return this.m_sparam; } public: //--- コンストラクタ CEventBaseObj(const ushort event_id,const long lparam,const double dparam,const string sparam) : m_chart_id(::ChartID()) { this.m_event_id=event_id; this.m_lparam=lparam; this.m_dparam=dparam; this.m_sparam=sparam; } //--- Comparison method to search for identical event objects virtual int Compare(const CObject *node,const int mode=0) const { const CEventBaseObj *compared=node; return ( this.ID()>compared.ID() ? 1 : this.ID()<compared.ID() ? -1 : this.LParam()>compared.LParam() ? 1 : this.LParam()<compared.LParam() ? -1 : this.DParam()>compared.DParam() ? 1 : this.DParam()<compared.DParam() ? -1 : this.SParam()>compared.SParam() ? 1 : this.SParam()<compared.SParam() ? -1 : 0 ); } }; //+------------------------------------------------------------------+ //| Base object class for all library objects | //+------------------------------------------------------------------+ class CBaseObj : public CObject { private: protected: CArrayObj m_list_events; // Object event list MqlTick m_tick; // Tick structure for receiving quote data double m_hash_sum; // Object data hash sum double m_hash_sum_prev; // Object data hash sum during the previous check int m_digits_currency; // Number of decimal places in an account currency int m_global_error; // Global error code long m_chart_id; // Control program chart ID bool m_is_event; // Object event flag int m_event_code; // Object event code string m_name; // Object name string m_folder_name; // Name of the folder storing CBaseObj descendant objects //--- Return time in milliseconds from MqlTick long TickTime(void) const { return #ifdef __MQL5__ this.m_tick.time_msc #else this.m_tick.time*1000 #endif ;} //--- return the flag of the event code presence in the event object bool IsPresentEventFlag(const int change_code) const { return (this.m_event_code & change_code)==change_code; } //--- Return the number of decimal places of the account currency int DigitsCurrency(void) const { return this.m_digits_currency; } //--- Returns the number of decimal places in the 'double' value int GetDigits(const double value) const; //--- Initialize the variables of (1) tracked, (2) controlled object data (implementation in the descendants) virtual void InitChangesParams(void); virtual void InitControlsParams(void); //--- (1) Check the object change, return the change code, (2) set the event type and fill in the list of events (implementation in the descendants) virtual int SetEventCode(void); virtual void SetTypeEvent(void); public: //--- Add the event object to the list bool EventAdd(const ushort event_id,const long lparam,const double dparam,const string sparam); //--- Return the occurred event flag to the object data bool IsEvent(void) const { return this.m_is_event; } //--- Return (1) the list of events, (2) the object event code and (3) the global error code CArrayObj *GetListEvents(void) { return &this.m_list_events; } int GetEventCode(void) const { return this.m_event_code; } int GetError(void) const { return this.m_global_error; } //--- Return the event object by its number in the list CEventBaseObj *GetEvent(const int shift=WRONG_VALUE,const bool check_out=true); //--- Return the number of object events int GetEventsTotal(void) const { return this.m_list_events.Total(); } //--- (1) Set and (2) return the chart ID of the control program void SetChartID(const long id) { this.m_chart_id=id; } long GetChartID(void) const { return this.m_chart_id; } //--- (1) Set the sub-folder name, (2) return the folder name for storing descendant object files void SetSubFolderName(const string name) { this.m_folder_name=DIRECTORY+name; } string GetFolderName(void) const { return this.m_folder_name; } //--- Return the object name string GetName(void) const { return this.m_name; } //--- Update the object data (implementation in the descendants) virtual void Refresh(void); //--- コンストラクタ CBaseObj(); }; //+------------------------------------------------------------------+ //| コンストラクタ | //+------------------------------------------------------------------+ CBaseObj::CBaseObj() : m_global_error(ERR_SUCCESS), m_hash_sum(0),m_hash_sum_prev(0), m_is_event(false),m_event_code(0), m_chart_id(::ChartID()), m_folder_name(DIRECTORY), m_name("") { ::ZeroMemory(this.m_tick); this.m_digits_currency=(#ifdef __MQL5__ (int)::AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS) #else 2 #endif); this.m_list_events.Clear(); this.m_list_events.Sort(); } //+------------------------------------------------------------------+ //| Add the event object to the list | //+------------------------------------------------------------------+ bool CBaseObj::EventAdd(const ushort event_id,const long lparam,const double dparam,const string sparam) { CEventBaseObj *event=new CEventBaseObj(event_id,lparam,dparam,sparam); if(event==NULL) return false; this.m_list_events.Sort(); if(this.m_list_events.Search(event)>WRONG_VALUE) { delete event; return false; } return this.m_list_events.Add(event); } //+------------------------------------------------------------------+ //| Return the object event by its index in the list | //+------------------------------------------------------------------+ CEventBaseObj *CBaseObj::GetEvent(const int shift=WRONG_VALUE,const bool check_out=true) { int total=this.m_list_events.Total(); if(total==0 || (!check_out && shift>total-1)) return NULL; int index=(shift<=0 ? total-1 : shift>total-1 ? 0 : total-shift-1); CEventBaseObj *event=this.m_list_events.At(index); return(event!=NULL ? event : NULL); } //+------------------------------------------------------------------+ //| Return the number of decimal places in the 'double' value | //+------------------------------------------------------------------+ int CBaseObj::GetDigits(const double value) const { string val_str=(string)value; int len=::StringLen(val_str); int n=len-::StringFind(val_str,".",0)-1; if(::StringSubstr(val_str,len-1,1)=="0") n--; return n; } //+------------------------------------------------------------------+
基本オブジェクトのイベントクラスを見てみましょう。
基本オブジェクトイベントクラスのprivateセクションでは、すべてのイベントプロパティを格納するためにクラスメンバ変数が宣言されています。
private: long m_time; long m_chart_id; ushort m_event_id; long m_lparam; double m_dparam; string m_sparam;
イベント時間、イベントの送信先チャートのID、イベントID、イベントのlong、double、string値はコントロールプログラムのチャートに渡されます。
これらの変数のほとんどの値は、クラスコンストラクタに渡されます。
//--- コンストラクタ CEventBaseObj(const ushort event_id,const long lparam,const double dparam,const string sparam) : m_chart_id(::ChartID()) { this.m_event_id=event_id; this.m_lparam=lparam; this.m_dparam=dparam; this.m_sparam=sparam; }
割り当てられた値はそれらに割り当てられます。
また、クラス初期化リストでは、チャートID変数が現在のチャートIDを受け取ります。
以下は、2つのオブジェクトイベントクラスを比較するメソッドです。
//--- Comparison method to search for identical event objects virtual int Compare(const CObject *node,const int mode=0) const { const CEventBaseObj *compared=node; return ( this.ID()>compared.ID() ? 1 : this.ID()<compared.ID() ? -1 : this.LParam()>compared.LParam() ? 1 : this.LParam()<compared.LParam() ? -1 : this.DParam()>compared.DParam() ? 1 : this.DParam()<compared.DParam() ? -1 : this.SParam()>compared.SParam() ? 1 : this.SParam()<compared.SParam() ? -1 : 0 ); }
2つのクラス(現在のクラスとポインタによってメソッドに渡されるクラス)のすべてのフィールドを要素ごとに比較します。 すべてのフィールドが等しい場合、メソッドは0を返します。これらのオブジェクトはCArrayObjリストに格納されているため、標準ライブラリポインタの動的リストで同じオブジェクトを検索するために必要です。 一方、Search()メソッドはリスト内の類似オブジェクトの検索に使われます。
//+------------------------------------------------------------------+ //| Search of position of element in a sorted array | //+------------------------------------------------------------------+ int CArrayObj::Search(const CObject *element) const { int pos; //--- check if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1) return(-1); //--- search pos=QuickSearch(element); if(m_data[pos].Compare(element,m_sort_mode)==0) return(pos); //--- not found return(-1); } //+------------------------------------------------------------------+
これはオブジェクトにCompare()仮想メソッドを必要とします。2つのオブジェクトのすべてのプロパティが一致する場合、メソッドは0を返します。
クラスのpublicセクションで、すべてのオブジェクトプロパティを設定および返すためのメソッドを宣言します。
public: void Time(const long time) { this.m_time=time; } long Time(void) const { return this.m_time; } void ChartID(const long chart_id) { this.m_chart_id=chart_id; } long ChartID(void) const { return this.m_chart_id; } void ID(const ushort id) { this.m_event_id=id; } ushort ID(void) const { return this.m_event_id; } void LParam(const long lparam) { this.m_lparam=lparam; } long LParam(void) const { return this.m_lparam; } void DParam(const double dparam) { this.m_dparam=dparam; } double DParam(void) const { return this.m_dparam; } void SParam(const string sparam) { this.m_sparam=sparam; } string SParam(void) const { return this.m_sparam; }
ここではすべてが明確であり、コメントが必要でありません。これは、オブジェクトイベントクラス全体です。
すべてのライブラリオブジェクトの基本オブジェクトクラスを考えてみましょう。
前のオブジェクトの処理中に既に遭遇したクラスメンバ変数は、クラスのprotectedセクションで宣言されています。
protected: CArrayObj m_list_events; // Object event list MqlTick m_tick; // Tick structure for receiving quote data double m_hash_sum; // Object data hash sum double m_hash_sum_prev; // Object data hash sum during the previous check int m_digits_currency; // Number of decimal places in an account currency int m_global_error; // Global error code long m_chart_id; // Control program chart ID bool m_is_event; // Object event flag int m_event_code; // Object event code string m_name; // Object name string m_folder_name; // Name of the folder storing CBaseObj descendant objects
- オブジェクトイベントのリストであるm_list_events は、上記で検討したイベントクラスのオブジェクトを格納するためのものです。オブジェクトには一度に複数のイベントがある場合があるため、それらをすべて定義してリストに配置する必要があります。これにより、CEngineライブラリのメインオブジェクトからすべてのイベントのリストを抽出して処理できます。
- m_tickティック構造体は、価格とイベント時間の取得に役立ちます。
- m_hash_sum ハッシュの合計は、オブジェクトプロパティで発生した変更を定義するために必要です。
オブジェクトプロパティの変更は、現在のハッシュ値と以前のハッシュ値(m_hash_sum_prev)を比較することで定義されます。 - m_digits_currency口座通貨の小数点以下の桁数は、金銭的価値の変更に関連するいくつかのイベントのデータを正しく表示するために必要です。
- 関数が異常を返したときに取得されたエラーの数は、m_global_errorグローバルエラーコードに書き込まれます。このコードは、呼び出し側プログラムに渡されてさらに処理されます。
- コントロールプログラムのチャートIDであるm_chart_idは、オブジェクトイベントの送信先のチャートを指定するために使用されます。
- m_is_eventオブジェクトイベントフラグは、イベントに対するタイムリーな反応のために調査対象オブジェクトで発生したイベントをプログラムに通知するために必要です。
- m_event_codeオブジェクトイベントコードには、同時に発生したすべてのイベントのフラグが格納されます。これらのフラグの存在により、同時に発生したオブジェクトイベントのリストを定義できます。
- m_nameオブジェクト名は、イベントを受け取るオブジェクトのテキストプロパティをプログラムに通知するために必要です。たとえば、これは口座の場合は口座番号+名義+サーバ名で、銘柄の場合は銘柄名です。
- オブジェクトファイルを保存するためのフォルダの名前m_folder_nameは、オブジェクトをファイルに保存するために必要です。同じタイプのオブジェクトファイルを保持するサブフォルダの名前はここに保存されます。
サブフォルダの基本ディレクトリは、すべてのクライアント端末の共通ファイルのディレクトリ+ライブラリフォルダ名「DoEasy\\」です。ファイルの保存については第12部で口座コレクションを作成する際に既に説明しました。
ライブラリオブジェクトでこれらのプロパティをすべて作成し、説明されているオブジェクトに対応するさまざまなライブラリの部分の記述で説明しました。次に、これらを単一のクラスに配置しました。すべてのライブラリオブジェクトの基本オブジェクトCBaseObjでは、これらのクラスメンバの定義を子孫オブジェクトクラスから削除します(添付ファイルを参照)。
クラスのprivateセクションにあるメソッドを見てみましょう。
//--- Return time in milliseconds from MqlTick long TickTime(void) const { return #ifdef __MQL5__ this.m_tick.time_msc #else this.m_tick.time*1000 #endif ;} //--- return the flag of the event code presence in the event object bool IsPresentEventFlag(const int change_code) const { return (this.m_event_code & change_code)==change_code; } //--- Return the number of decimal places of the account currency int DigitsCurrency(void) const { return this.m_digits_currency; } //--- Returns the number of decimal places in the 'double' value int GetDigits(const double value) const; //--- Initialize the variables of (1) tracked, (2) controlled object data (implementation in the descendants) virtual void InitChangesParams(void); virtual void InitControlsParams(void); //--- (1) Check the object change, return the change code, (2) set the event type and fill in the list of events (implementation in the descendants) virtual int SetEventCode(void); virtual void SetTypeEvent(void);
- TickTime()メソッドはミリ秒単位でイベント時間を返します。MQL4の場合、構造体にミリ秒がないため、秒単位の時間*1000が返されます
- IsPresentEventFlag()メソッドはm_event_code変数に特定のイベントコードの存在を返します。
- DigitsCurrency()メソッドは、m_digits_currency変数から口座通貨値の小数点以下の桁数を返します。
- GetDigits()メソッドは、渡されたdouble値の小数点以下の桁数を計算して返します。
- InitChangesParams()仮想メソッドは、編集可能なすべてのオブジェクトプロパティのパラメータを初期化します。
- InitControlsParams()仮想メソッドは、追跡対象のオブジェクトプロパティのパラメータを初期化します。
- SetEventCode()仮想メソッドは、オブジェクトプロパティの変更を確認し、発生した変更のコードを返します。
- SetTypeEvent()仮想メソッドは、発生したイベントのタイプをイベントコードに基づいて設定し、すべてのイベントをオブジェクトイベントリストに配置します。
これらのメソッドはすべて、以前の記事で既に開発されているので、ここでは説明しません。すべての仮想メソッドはここでは何もしないので、基本オブジェクトの子孫クラスに実装する必要があることを明確にしたいだけです。
次のメソッドは、クラスのpublicセクションで宣言されています。
public: //--- Add the event object to the list bool EventAdd(const ushort event_id,const long lparam,const double dparam,const string sparam); //--- Return the occurred event flag to the object data bool IsEvent(void) const { return this.m_is_event; } //--- Return (1) the list of events, (2) the object event code and (3) the global error code CArrayObj *GetListEvents(void) { return &this.m_list_events; } int GetEventCode(void) const { return this.m_event_code; } int GetError(void) const { return this.m_global_error; } //--- Return the event object by its number in the list CEventBaseObj *GetEvent(const int shift=WRONG_VALUE,const bool check_out=true); //--- Return the number of object events int GetEventsTotal(void) const { return this.m_list_events.Total(); } //--- (1) Set and (2) return the chart ID of the control program void SetChartID(const long id) { this.m_chart_id=id; } long GetChartID(void) const { return this.m_chart_id; } //--- (1) Set the sub-folder name, (2) return the folder name for storing descendant object files void SetSubFolderName(const string name) { this.m_folder_name=DIRECTORY+name; } string GetFolderName(void) const { return this.m_folder_name; } //--- Return the object name string GetName(void) const { return this.m_name; } //--- Update the object data (implementation in the descendants) virtual void Refresh(void);
クラスコンストラクタの初期化リストで、初期値がクラスメンバ変数に割り当てられます。
//+------------------------------------------------------------------+ //| コンストラクタ | //+------------------------------------------------------------------+ CBaseObj::CBaseObj() : m_global_error(ERR_SUCCESS), m_hash_sum(0),m_hash_sum_prev(0), m_is_event(false),m_event_code(0), m_chart_id(::ChartID()), m_folder_name(DIRECTORY), m_name("") { ::ZeroMemory(this.m_tick); this.m_digits_currency=(#ifdef __MQL5__ (int)::AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS) #else 2 #endif); this.m_list_events.Clear(); this.m_list_events.Sort(); } //+------------------------------------------------------------------+
ティック構造体がゼロに設定され、口座通貨の小数点以下の桁数が割り当てられます。イベントのリストがクリアされてオブジェクトイベントリストのリスト並び替え済みフラグが設定されます。
以下はリストにイベントを追加するメソッドです。
//+------------------------------------------------------------------+ //| Add the event object to the list | //+------------------------------------------------------------------+ bool CBaseObj::EventAdd(const ushort event_id,const long lparam,const double dparam,const string sparam) { CEventBaseObj *event=new CEventBaseObj(event_id,lparam,dparam,sparam); if(event==NULL) return false; this.m_list_events.Sort(); if(this.m_list_events.Search(event)>WRONG_VALUE) { delete event; return false; } return this.m_list_events.Add(event); } //+------------------------------------------------------------------+
イベントID、およびイベントプロパティのlong、double、string値がメソッドに渡されます。その後、これらのパラメータを持つ新しいイベントが作成されます。同じイベントがリストに既に存在する場合、イベントオブジェクトとメソッドはfalseを返します。そうでない場合、メソッドはリストにイベントオブジェクトを追加した結果を返します。
以下は、リスト内のイベントオブジェクトをインデックスで返すメソッドです。
//+------------------------------------------------------------------+ //| Return the object event by its index in the list | //+------------------------------------------------------------------+ CEventBaseObj *CBaseObj::GetEvent(const int shift=WRONG_VALUE,const bool check_out=true) { int total=this.m_list_events.Total(); if(total==0 || (!check_out && shift>total-1)) return NULL; int index=(shift<=0 ? total-1 : shift>total-1 ? 0 : total-shift-1); CEventBaseObj *event=this.m_list_events.At(index); return(event!=NULL ? event : NULL); } //+------------------------------------------------------------------+
このメソッドは以前に検討しました。ここでは、インデックスの値がリストを超えたときにインデックスを確認および修正する必要性を定義するフラグのみを追加しました。デフォルトでは、インデックス-1がメソッドに渡され、リストの範囲外でないことが確認されます。この場合、メソッドはリストから最新のイベントオブジェクトを返します。インデックスでオブジェクトを取得するには、必要なインデックスをメソッドに渡し、リスト範囲確認フラグをfalseに設定します。この場合は、オブジェクト(またはリスト内のインデックス)が返されます。インデックスがリスト外にある場合、NULLが返されます。
以下は、以前に考慮したdouble値の小数点以下の桁数を返すメソッドです。
//+------------------------------------------------------------------+ //| Return the number of decimal places in the 'double' value | //+------------------------------------------------------------------+ int CBaseObj::GetDigits(const double value) const { string val_str=(string)value; int len=::StringLen(val_str); int n=len-::StringFind(val_str,".",0)-1; if(::StringSubstr(val_str,len-1,1)=="0") n--; return n; } //+------------------------------------------------------------------+
新しい基本オブジェクトの準備ができました。
次に、ライブラリの各基本オブジェクトで、CObject基本クラスをCBaseObjで置き換えます。以下がそのオブジェクトです。
CAccountクラスオブジェクト:
//+------------------------------------------------------------------+ //| Account class | //+------------------------------------------------------------------+ class CAccount : public CBaseObj {
CSymbolクラスオブジェクト:
//+------------------------------------------------------------------+ //| Abstract symbol class | //+------------------------------------------------------------------+ class CSymbol : public CBaseObj {
コレクションクラスには、一般的なオブジェクトプロパティもあります。
取引イベントコレクション:
//+------------------------------------------------------------------+ //| Collection of account trading events | //+------------------------------------------------------------------+ class CEventsCollection : public CBaseObj {
口座コレクション:
//+------------------------------------------------------------------+ //| Account collection | //+------------------------------------------------------------------+ class CAccountsCollection : public CBaseObj {
銘柄コレクション:
//+------------------------------------------------------------------+ //| Symbol collection | //+------------------------------------------------------------------+ class CSymbolsCollection : public CBaseObj {
これで、すべてのCBaseObjを基本とするオブジェクトにはいくつかのプロパティの同様のセットが存在するので、新しく作成されたオブジェクトごとにそれらを新たにリセットする必要はありません。さらに、すべてのオブジェクトに類似したプロパティを追加し、この基本オブジェクトに基づいて作成できるようになりました。さらに、すべてのオブジェクトに類似したプロパティを追加し、この基本オブジェクトに基づいて作成できるようになりました。各オブジェクトイベントにはEventChartCustom()プログラムチャートにイベントを送信するための関数と同じパラメータセットがあります。したがって、新しいオブジェクトの開発と既製のオブジェクトの改善を大幅に簡素化しました。
これで、銘柄コレクションイベントを作成する準備ができました
銘柄コレクションイベント
いつものように、すべては定数と列挙の定義から始まります。Defines.mqhファイルを開き、銘柄イベントの追跡に必要なデータを追加します。
銘柄は使用するためには[気配値表示]ウィンドウに存在する必要がありますが、存在できる銘柄の数は制限されているので、
[気配値表示]ウィンドウに同時に配置される銘柄の最大可能数を示すマクロ置換を含む文字列を銘柄パラメータに追加します。
//--- Symbol parameters #define CLR_DEFAULT (0xFF000000) // Default color #define SYMBOLS_COMMON_TOTAL (1000) // Total number of working symbols
銘柄を使用するためのデータのセクションから銘柄を使用するモードの列挙を
//+------------------------------------------------------------------+ //| Data for working with symbols | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Modes of working with symbols | //+------------------------------------------------------------------+ enum ENUM_SYMBOLS_MODE { SYMBOLS_MODE_CURRENT, // Work with the current symbol only SYMBOLS_MODE_DEFINES, // Work with the specified symbol list SYMBOLS_MODE_MARKET_WATCH, // Work with the Market Watch window symbols SYMBOLS_MODE_ALL // Work with the full symbol list }; //+------------------------------------------------------------------+
Datas.mqhファイルに移動します。
//+------------------------------------------------------------------+ //| Datas.mqh | //| Copyright 2018, MetaQuotes Software Corp. | //| https://mql5.com/ja/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2018, MetaQuotes Software Corp." #property link "https://mql5.com/ja/users/artmedia70" //+------------------------------------------------------------------+ //| Enumerations | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Modes of working with symbols | //+------------------------------------------------------------------+ enum ENUM_SYMBOLS_MODE { SYMBOLS_MODE_CURRENT, // Work with the current symbol only SYMBOLS_MODE_DEFINES, // Work with the specified symbol list SYMBOLS_MODE_MARKET_WATCH, // Work with the Market Watch window symbols SYMBOLS_MODE_ALL // Work with the full symbol list }; //+------------------------------------------------------------------+ //| Data sets | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Major Forex symbols | //+------------------------------------------------------------------+ string DataSymbolsFXMajors[]= {
この決定は、データがライブラリだけでなく、ライブラリに基づいたプログラムにも必要であるという事実によって促されました。この列挙は、ライブラリよりも一般的なプログラムデータを指します。たとえば、データは他の多くの列挙と一緒にプログラム入力として使用されるため、必要なコンパイル言語に変換されます(後で実装)。したがって、Datas.mqhに配置します。
Defines.mqhから移動された列挙の代わりに、銘柄イベントフラグのリストを持つ列挙および可能な銘柄イベントのリストを持つ列挙を追加します。
//+------------------------------------------------------------------+ //| Data for working with symbols | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| List of symbol event flags | //+------------------------------------------------------------------+ enum ENUM_SYMBOL_EVENT_FLAGS { SYMBOL_EVENT_FLAG_NO_EVENT = 0, // No event SYMBOL_EVENT_FLAG_TRADE_MODE = 1, // Change order execution permissions SYMBOL_EVENT_FLAG_SESSION_DEALS = 2, // Change the number of deals in the current session SYMBOL_EVENT_FLAG_SESSION_BUY_ORDERS = 4, // Change the total number of the current buy orders SYMBOL_EVENT_FLAG_SESSION_SELL_ORDERS = 8, // Change the total number of the current sell orders SYMBOL_EVENT_FLAG_VOLUME = 16, // Change in the last deal volume exceeds the specified value in +/- SYMBOL_EVENT_FLAG_VOLUME_HIGH_DAY = 32, // Change of the maximum volume per day exceeds the specified value in +/- SYMBOL_EVENT_FLAG_VOLUME_LOW_DAY = 64, // Change of the minimum volume per day exceeds the specified value in +/- SYMBOL_EVENT_FLAG_SPREAD = 128, // Change of a spread exceeds the specified change value in +/- SYMBOL_EVENT_FLAG_STOPLEVEL = 256, // Change of a Stop order level exceeds the specified value in +/- SYMBOL_EVENT_FLAG_FREEZELEVEL = 512, // Change of the freeze level exceeds the specified value in +/- SYMBOL_EVENT_FLAG_BID_LAST = 1024, // Change of the Bid or Last price exceeds the specified value in +/- SYMBOL_EVENT_FLAG_BID_LAST_HIGH = 2048, // Change of the maximum Bid or Last price per day exceeds the specified value in +/- SYMBOL_EVENT_FLAG_BID_LAST_LOW = 4096, // Change of the minimum Bid or Last price per day exceeds the specified value in +/- SYMBOL_EVENT_FLAG_ASK = 8192, // Change of the Ask price exceeds the specified value in +/- SYMBOL_EVENT_FLAG_ASK_HIGH = 16384, // Change of the maximum Ask price per day exceeds the specified value in +/- SYMBOL_EVENT_FLAG_ASK_LOW = 32768, // Change of the minimum Ask price per day exceeds the specified value in +/- SYMBOL_EVENT_FLAG_VOLUME_REAL_DAY = 65536, // Change of the real volume per day exceeds the specified value in +/- SYMBOL_EVENT_FLAG_VOLUME_HIGH_REAL_DAY = 131072, // Change of the maximum real volume per day exceeds the specified value in +/- SYMBOL_EVENT_FLAG_VOLUME_LOW_REAL_DAY = 262144, // Change of the minimum real volume per day exceeds the specified value in +/- SYMBOL_EVENT_FLAG_OPTION_STRIKE = 524288, // Change of the strike price exceeds the specified value in +/- SYMBOL_EVENT_FLAG_VOLUME_LIMIT = 1048576, // Change of the maximum available total position volume and pending orders in one direction SYMBOL_EVENT_FLAG_SWAP_LONG = 2097152, // Change swap long SYMBOL_EVENT_FLAG_SWAP_SHORT = 4194304, // Change swap short SYMBOL_EVENT_FLAG_SESSION_VOLUME = 8388608, // Change of the total volume of deals in the current session exceeds the specified value in +/- SYMBOL_EVENT_FLAG_SESSION_TURNOVER = 16777216, // Change of the total turnover in the current session exceeds the specified value in +/- SYMBOL_EVENT_FLAG_SESSION_INTEREST = 33554432, // Change of the total volume of open positions in the current session exceeds the specified value in +/- SYMBOL_EVENT_FLAG_SESSION_BUY_ORD_VOLUME = 67108864, // Change of the total volume of buy orders exceeds the specified value in +/- SYMBOL_EVENT_FLAG_SESSION_SELL_ORD_VOLUME = 134217728, // Change of the total volume of sell orders exceeds the specified value in +/- SYMBOL_EVENT_FLAG_SESSION_OPEN = 268435456, // Change of the session open price exceeds the specified value in +/- SYMBOL_EVENT_FLAG_SESSION_CLOSE = 536870912, // Change of the session close price exceeds the specified value in +/- SYMBOL_EVENT_FLAG_SESSION_AW = 1073741824 // Change of the average weighted session price exceeds the specified value in +/- }; //+------------------------------------------------------------------+ //| List of possible symbol events | //+------------------------------------------------------------------+ enum ENUM_SYMBOL_EVENT { SYMBOL_EVENT_NO_EVENT = ACCOUNT_EVENTS_NEXT_CODE, // No event SYMBOL_EVENT_MW_ADD, // Adding a symbol to the Market Watch window SYMBOL_EVENT_MW_DEL, // Removing a symbol from the Market Watch window SYMBOL_EVENT_MW_SORT, // Sorting symbols in the Market Watch window SYMBOL_EVENT_TRADE_DISABLE, // Disable order execution SYMBOL_EVENT_TRADE_LONGONLY, // Allow buy only SYMBOL_EVENT_TRADE_SHORTONLY, // Allow sell only SYMBOL_EVENT_TRADE_CLOSEONLY, // Enable close only SYMBOL_EVENT_TRADE_FULL, // No trading limitations SYMBOL_EVENT_SESSION_DEALS_INC, // The increase in the number of deals in the current session exceeds the specified value SYMBOL_EVENT_SESSION_DEALS_DEC, // The decrease in the number of deals in the current session exceeds the specified value SYMBOL_EVENT_SESSION_BUY_ORDERS_INC, // The increase in the total number of buy orders currently exceeds the specified value SYMBOL_EVENT_SESSION_BUY_ORDERS_DEC, // The decrease in the total number of buy orders currently exceeds the specified value SYMBOL_EVENT_SESSION_SELL_ORDERS_INC, // The increase in the total number of sell orders currently exceeds the specified value SYMBOL_EVENT_SESSION_SELL_ORDERS_DEC, // The decrease in the total number of sell orders currently exceeds the specified value SYMBOL_EVENT_VOLUME_INC, // Volume increase in the last deal exceeds the specified value SYMBOL_EVENT_VOLUME_DEC, // Volume decrease in the last deal exceeds the specified value SYMBOL_EVENT_VOLUME_HIGH_DAY_INC, // The increase in the maximum volume per day exceeds the specified value SYMBOL_EVENT_VOLUME_HIGH_DAY_DEC, // The decrease in the maximum volume per day exceeds the specified value SYMBOL_EVENT_VOLUME_LOW_DAY_INC, // The increase in the minimum volume per day exceeds the specified value SYMBOL_EVENT_VOLUME_LOW_DAY_DEC, // The decrease in the minimum volume per day exceeds the specified value SYMBOL_EVENT_SPREAD_INC, // The increase in a spread exceeds the specified change SYMBOL_EVENT_SPREAD_DEC, // The decrease in a spread exceeds the specified change SYMBOL_EVENT_STOPLEVEL_INC, // The increase of a Stop order level exceeds the specified value SYMBOL_EVENT_STOPLEVEL_DEC, // The decrease of a Stop order level exceeds the specified value SYMBOL_EVENT_FREEZELEVEL_INC, // The increase in the freeze level exceeds the specified value SYMBOL_EVENT_FREEZELEVEL_DEC, // The decrease in the freeze level exceeds the specified value SYMBOL_EVENT_BID_LAST_INC, // The increase in the Bid or Last price exceeds the specified value SYMBOL_EVENT_BID_LAST_DEC, // The decrease in the Bid or Last price exceeds the specified value SYMBOL_EVENT_BID_LAST_HIGH_INC, // The increase in the maximum Bid or Last price per day exceeds the specified value SYMBOL_EVENT_BID_LAST_HIGH_DEC, // The decrease in the maximum Bid or Last price per day exceeds the specified value relative to the specified price SYMBOL_EVENT_BID_LAST_LOW_INC, // The increase in the minimum Bid or Last price per day exceeds the specified value relative to the specified price SYMBOL_EVENT_BID_LAST_LOW_DEC, // The decrease in the minimum Bid or Last price per day exceeds the specified value SYMBOL_EVENT_ASK_INC, // The increase in the Ask price exceeds the specified value SYMBOL_EVENT_ASK_DEC, // The decrease in the Ask price exceeds the specified value SYMBOL_EVENT_ASK_HIGH_INC, // The increase in the maximum Ask price per day exceeds the specified value SYMBOL_EVENT_ASK_HIGH_DEC, // The decrease in the maximum Ask price per day exceeds the specified value SYMBOL_EVENT_ASK_LOW_INC, // The increase in the minimum Ask price per day exceeds the specified value SYMBOL_EVENT_ASK_LOW_DEC, // The decrease in the minimum Ask price per day exceeds the specified value SYMBOL_EVENT_VOLUME_REAL_DAY_INC, // The increase in the real volume per day exceeds the specified value SYMBOL_EVENT_VOLUME_REAL_DAY_DEC, // The decrease in the real volume per day exceeds the specified value SYMBOL_EVENT_VOLUME_HIGH_REAL_DAY_INC, // The increase in the maximum real volume per day exceeds the specified value SYMBOL_EVENT_VOLUME_HIGH_REAL_DAY_DEC, // The decrease in the maximum real volume per day exceeds the specified value SYMBOL_EVENT_VOLUME_LOW_REAL_DAY_INC, // The increase in the minimum real volume per day exceeds the specified value SYMBOL_EVENT_VOLUME_LOW_REAL_DAY_DEC, // The decrease in the minimum real volume per day exceeds the specified value SYMBOL_EVENT_OPTION_STRIKE_INC, // The increase in the strike price exceeds the specified value SYMBOL_EVENT_OPTION_STRIKE_DEC, // The decrease in the strike price exceeds the specified value SYMBOL_EVENT_VOLUME_LIMIT_INC, // The increase in the maximum available total position volume and pending orders in one direction SYMBOL_EVENT_VOLUME_LIMIT_DEC, // The decrease in the maximum available total position volume and pending orders in one direction SYMBOL_EVENT_SWAP_LONG_INC, // The increase in the swap long SYMBOL_EVENT_SWAP_LONG_DEC, // The decrease in the swap long SYMBOL_EVENT_SWAP_SHORT_INC, // The increase in the swap short SYMBOL_EVENT_SWAP_SHORT_DEC, // The decrease in the swap short SYMBOL_EVENT_SESSION_VOLUME_INC, // The increase in the total volume of deals in the current session exceeds the specified value SYMBOL_EVENT_SESSION_VOLUME_DEC, // The decrease in the total volume of deals in the current session exceeds the specified value SYMBOL_EVENT_SESSION_TURNOVER_INC, // The increase in the total turnover in the current session exceeds the specified value SYMBOL_EVENT_SESSION_TURNOVER_DEC, // The decrease in the total turnover in the current session exceeds the specified value SYMBOL_EVENT_SESSION_INTEREST_INC, // The increase in the total volume of open positions in the current session exceeds the specified value SYMBOL_EVENT_SESSION_INTEREST_DEC, // The decrease in the total volume of open positions in the current session exceeds the specified value SYMBOL_EVENT_SESSION_BUY_ORD_VOLUME_INC, // The increase in the total volume of buy orders exceeds the specified value SYMBOL_EVENT_SESSION_BUY_ORD_VOLUME_DEC, // The decrease in the total volume of buy orders exceeds the specified value SYMBOL_EVENT_SESSION_SELL_ORD_VOLUME_INC, // The increase in the total volume of sell orders exceeds the specified value SYMBOL_EVENT_SESSION_SELL_ORD_VOLUME_DEC, // The decrease in the total volume of sell orders exceeds the specified value SYMBOL_EVENT_SESSION_OPEN_INC, // The increase in the session open price exceeds the specified value relative to the specified price SYMBOL_EVENT_SESSION_OPEN_DEC, // The decrease in the session open price exceeds the specified value relative to the specified price SYMBOL_EVENT_SESSION_CLOSE_INC, // The increase in the session close price exceeds the specified value relative to the specified price SYMBOL_EVENT_SESSION_CLOSE_DEC, // The decrease in the session close price exceeds the specified value relative to the specified price SYMBOL_EVENT_SESSION_AW_INC, // The increase in the average weighted session price exceeds the specified value SYMBOL_EVENT_SESSION_AW_DEC, // The decrease in the average weighted session price exceeds the specified value }; #define SYMBOL_EVENTS_NEXT_CODE (SYMBOL_EVENT_SESSION_AW_DEC+1) // The code of the next event after the last symbol event code //+------------------------------------------------------------------+
ここでは、すべてがフラグの列挙と、可能な口座および取引イベントに似ています。第4部ではイベントフラグとイベントIDを考慮しました。
[気配値表示]ウィンドウの場所で銘柄を並べ替えるには、さらに別の整数銘柄プロパティを追加します。
//+------------------------------------------------------------------+ //| Symbol integer properties | //+------------------------------------------------------------------+ enum ENUM_SYMBOL_PROP_INTEGER { SYMBOL_PROP_STATUS = 0, // Symbol status SYMBOL_PROP_INDEX_MW, // Symbol index in the Market Watch window SYMBOL_PROP_CUSTOM, // Custom symbol flag SYMBOL_PROP_CHART_MODE, // The price type used for generating bars – Bid or Last (from the ENUM_SYMBOL_CHART_MODE enumeration) SYMBOL_PROP_EXIST, // Flag indicating that the symbol under this name exists SYMBOL_PROP_SELECT, // The indication that the symbol is selected in Market Watch SYMBOL_PROP_VISIBLE, // The indication that the symbol is displayed in Market Watch SYMBOL_PROP_SESSION_DEALS, // The number of deals in the current session SYMBOL_PROP_SESSION_BUY_ORDERS, // The total number of Buy orders at the moment SYMBOL_PROP_SESSION_SELL_ORDERS, // The total number of Sell orders at the moment SYMBOL_PROP_VOLUME, // Last deal volume SYMBOL_PROP_VOLUMEHIGH, // Maximum volume within a day SYMBOL_PROP_VOLUMELOW, // Minimum volume within a day SYMBOL_PROP_TIME, // Latest quote time SYMBOL_PROP_DIGITS, // Number of decimal places SYMBOL_PROP_DIGITS_LOTS, // Number of decimal places for a lot SYMBOL_PROP_SPREAD, // Spread in points SYMBOL_PROP_SPREAD_FLOAT, // Floating spread flag SYMBOL_PROP_TICKS_BOOKDEPTH, // Maximum number of orders displayed in the Depth of Market SYMBOL_PROP_TRADE_CALC_MODE, // Contract price calculation method (from the ENUM_SYMBOL_CALC_MODE enumeration) SYMBOL_PROP_TRADE_MODE, // Order execution type (from the ENUM_SYMBOL_TRADE_MODE enumeration) SYMBOL_PROP_START_TIME, // Symbol trading start date (usually used for futures) SYMBOL_PROP_EXPIRATION_TIME, // Symbol trading end date (usually used for futures) SYMBOL_PROP_TRADE_STOPS_LEVEL, // Minimum distance in points from the current close price for setting Stop orders SYMBOL_PROP_TRADE_FREEZE_LEVEL, // Freeze distance for trading operations (in points) SYMBOL_PROP_TRADE_EXEMODE, // Deal execution mode (from the ENUM_SYMBOL_TRADE_EXECUTION enumeration) SYMBOL_PROP_SWAP_MODE, // Swap calculation model (from the ENUM_SYMBOL_SWAP_MODE enumeration) SYMBOL_PROP_SWAP_ROLLOVER3DAYS, // Triple-day swap (from the ENUM_DAY_OF_WEEK enumeration) SYMBOL_PROP_MARGIN_HEDGED_USE_LEG, // Calculating hedging margin using the larger leg (Buy or Sell) SYMBOL_PROP_EXPIRATION_MODE, // Flags of allowed order expiration modes SYMBOL_PROP_FILLING_MODE, // Flags of allowed order filling modes SYMBOL_PROP_ORDER_MODE, // Flags of allowed order types SYMBOL_PROP_ORDER_GTC_MODE, // Expiration of Stop Loss and Take Profit orders if SYMBOL_EXPIRATION_MODE=SYMBOL_EXPIRATION_GTC (from the ENUM_SYMBOL_ORDER_GTC_MODE enumeration) SYMBOL_PROP_OPTION_MODE, // Option type (from the ENUM_SYMBOL_OPTION_MODE enumeration) SYMBOL_PROP_OPTION_RIGHT, // Option right (Call/Put) (from the ENUM_SYMBOL_OPTION_RIGHT enumeration) //--- skipped property SYMBOL_PROP_BACKGROUND_COLOR // The color of the background used for the symbol in Market Watch }; #define SYMBOL_PROP_INTEGER_TOTAL (36) // Total number of integer properties #define SYMBOL_PROP_INTEGER_SKIP (1) // Number of symbol integer properties not used in sorting //+------------------------------------------------------------------+
新しいプロパティを追加したため、整数プロパティの合計数を35ではなく36に増やす必要があります。
最後に、新しいプロパティを可能な銘柄並び替え基準のリストに追加します。
//+------------------------------------------------------------------+ //| Possible symbol sorting criteria | //+------------------------------------------------------------------+ #define FIRST_SYM_DBL_PROP (SYMBOL_PROP_INTEGER_TOTAL-SYMBOL_PROP_INTEGER_SKIP) #define FIRST_SYM_STR_PROP (SYMBOL_PROP_INTEGER_TOTAL-SYMBOL_PROP_INTEGER_SKIP+SYMBOL_PROP_DOUBLE_TOTAL-SYMBOL_PROP_DOUBLE_SKIP) enum ENUM_SORT_SYMBOLS_MODE { //--- 整数型プロパティによって並び替える SORT_BY_SYMBOL_STATUS = 0, // Sort by symbol status SORT_BY_SYMBOL_INDEX_MW, // Sort by index in the Market Watch window SORT_BY_SYMBOL_CUSTOM, // Sort by custom symbol property SORT_BY_SYMBOL_CHART_MODE, // Sort by price type for constructing bars – Bid or Last (from the ENUM_SYMBOL_CHART_MODE enumeration) SORT_BY_SYMBOL_EXIST, // Sort by the flag that a symbol with such a name exists SORT_BY_SYMBOL_SELECT, // Sort by the flag indicating that a symbol is selected in Market Watch SORT_BY_SYMBOL_VISIBLE, // Sort by the flag indicating that a selected symbol is displayed in Market Watch SORT_BY_SYMBOL_SESSION_DEALS, // Sort by the number of deals in the current session SORT_BY_SYMBOL_SESSION_BUY_ORDERS, // Sort by the total number of current buy orders SORT_BY_SYMBOL_SESSION_SELL_ORDERS, // Sort by the total number of current sell orders SORT_BY_SYMBOL_VOLUME, // Sort by last deal volume SORT_BY_SYMBOL_VOLUMEHIGH, // Sort by maximum volume for a day SORT_BY_SYMBOL_VOLUMELOW, // Sort by minimum volume for a day SORT_BY_SYMBOL_TIME, // Sort by the last quote time SORT_BY_SYMBOL_DIGITS, // Sort by a number of decimal places SORT_BY_SYMBOL_DIGITS_LOT, // Sort by a number of decimal places in a lot SORT_BY_SYMBOL_SPREAD, // Sort by spread in points SORT_BY_SYMBOL_SPREAD_FLOAT, // Sort by floating spread SORT_BY_SYMBOL_TICKS_BOOKDEPTH, // Sort by a maximum number of requests displayed in the market depth SORT_BY_SYMBOL_TRADE_CALC_MODE, // Sort by contract price calculation method (from the ENUM_SYMBOL_CALC_MODE enumeration) SORT_BY_SYMBOL_TRADE_MODE, // Sort by order execution type (from the ENUM_SYMBOL_TRADE_MODE enumeration) SORT_BY_SYMBOL_START_TIME, // Sort by an instrument trading start date (usually used for futures) SORT_BY_SYMBOL_EXPIRATION_TIME, // Sort by an instrument trading end date (usually used for futures) SORT_BY_SYMBOL_TRADE_STOPS_LEVEL, // Sort by the minimum indent from the current close price (in points) for setting Stop orders SORT_BY_SYMBOL_TRADE_FREEZE_LEVEL, // Sort by trade operation freeze distance (in points) SORT_BY_SYMBOL_TRADE_EXEMODE, // Sort by trade execution mode (from the ENUM_SYMBOL_TRADE_EXECUTION enumeration) SORT_BY_SYMBOL_SWAP_MODE, // Sort by swap calculation model (from the ENUM_SYMBOL_SWAP_MODE enumeration) SORT_BY_SYMBOL_SWAP_ROLLOVER3DAYS, // Sort by week day for accruing a triple swap (from the ENUM_DAY_OF_WEEK enumeration) SORT_BY_SYMBOL_MARGIN_HEDGED_USE_LEG, // Sort by the calculation mode of a hedged margin using the larger leg (Buy or Sell) SORT_BY_SYMBOL_EXPIRATION_MODE, // Sort by flags of allowed order expiration modes SORT_BY_SYMBOL_FILLING_MODE, // Sort by flags of allowed order filling modes SORT_BY_SYMBOL_ORDER_MODE, // Sort by flags of allowed order types SORT_BY_SYMBOL_ORDER_GTC_MODE, // Sort by StopLoss and TakeProfit orders lifetime SORT_BY_SYMBOL_OPTION_MODE, // Sort by option type (from the ENUM_SYMBOL_OPTION_MODE enumeration) SORT_BY_SYMBOL_OPTION_RIGHT, // Sort by option right (Call/Put) (from the ENUM_SYMBOL_OPTION_RIGHT enumeration) //--- 実数型プロパティによって並び替える SORT_BY_SYMBOL_BID = FIRST_SYM_DBL_PROP, // Sort by Bid SORT_BY_SYMBOL_BIDHIGH, // Sort by maximum Bid for a day SORT_BY_SYMBOL_BIDLOW, // Sort by minimum Bid for a day SORT_BY_SYMBOL_ASK, // Sort by Ask SORT_BY_SYMBOL_ASKHIGH, // Sort by maximum Ask for a day SORT_BY_SYMBOL_ASKLOW, // Sort by minimum Ask for a day SORT_BY_SYMBOL_LAST, // Sort by the last deal price SORT_BY_SYMBOL_LASTHIGH, // Sort by maximum Last for a day SORT_BY_SYMBOL_LASTLOW, // Sort by minimum Last for a day SORT_BY_SYMBOL_VOLUME_REAL, // Sort by Volume for a day SORT_BY_SYMBOL_VOLUMEHIGH_REAL, // Sort by maximum Volume for a day SORT_BY_SYMBOL_VOLUMELOW_REAL, // Sort by minimum Volume for a day SORT_BY_SYMBOL_OPTION_STRIKE, // Sort by an option execution price SORT_BY_SYMBOL_POINT, // Sort by a single point value SORT_BY_SYMBOL_TRADE_TICK_VALUE, // Sort by SYMBOL_TRADE_TICK_VALUE_PROFIT value SORT_BY_SYMBOL_TRADE_TICK_VALUE_PROFIT, // Sort by a calculated tick price for a profitable position SORT_BY_SYMBOL_TRADE_TICK_VALUE_LOSS, // Sort by a calculated tick price for a loss-making position SORT_BY_SYMBOL_TRADE_TICK_SIZE, // Sort by a minimum price change SORT_BY_SYMBOL_TRADE_CONTRACT_SIZE, // Sort by a trading contract size SORT_BY_SYMBOL_TRADE_ACCRUED_INTEREST, // Sort by accrued interest SORT_BY_SYMBOL_TRADE_FACE_VALUE, // Sort by face value SORT_BY_SYMBOL_TRADE_LIQUIDITY_RATE, // Sort by liquidity rate SORT_BY_SYMBOL_VOLUME_MIN, // Sort by a minimum volume for performing a deal SORT_BY_SYMBOL_VOLUME_MAX, // Sort by a maximum volume for performing a deal SORT_BY_SYMBOL_VOLUME_STEP, // Sort by a minimum volume change step for deal execution SORT_BY_SYMBOL_VOLUME_LIMIT, // Sort by a maximum allowed aggregate volume of an open position and pending orders in one direction SORT_BY_SYMBOL_SWAP_LONG, // Sort by a long swap value SORT_BY_SYMBOL_SWAP_SHORT, // Sort by a short swap value SORT_BY_SYMBOL_MARGIN_INITIAL, // Sort by an initial margin SORT_BY_SYMBOL_MARGIN_MAINTENANCE, // Sort by a maintenance margin for an instrument SORT_BY_SYMBOL_MARGIN_LONG_INITIAL, // Sort by initial margin requirement applicable to Long orders SORT_BY_SYMBOL_MARGIN_BUY_STOP_INITIAL, // Sort by initial margin requirement applicable to BuyStop orders SORT_BY_SYMBOL_MARGIN_BUY_LIMIT_INITIAL, // Sort by initial margin requirement applicable to BuyLimit orders SORT_BY_SYMBOL_MARGIN_BUY_STOPLIMIT_INITIAL, // Sort by initial margin requirement applicable to BuyStopLimit orders SORT_BY_SYMBOL_MARGIN_LONG_MAINTENANCE, // Sort by maintenance margin requirement applicable to Long orders SORT_BY_SYMBOL_MARGIN_BUY_STOP_MAINTENANCE, // Sort by maintenance margin requirement applicable to BuyStop orders SORT_BY_SYMBOL_MARGIN_BUY_LIMIT_MAINTENANCE, // Sort by maintenance margin requirement applicable to BuyLimit orders SORT_BY_SYMBOL_MARGIN_BUY_STOPLIMIT_MAINTENANCE, // Sort by maintenance margin requirement applicable to BuyStopLimit orders SORT_BY_SYMBOL_MARGIN_SHORT_INITIAL, // Sort by initial margin requirement applicable to Short orders SORT_BY_SYMBOL_MARGIN_SELL_STOP_INITIAL, // Sort by initial margin requirement applicable to SellStop orders SORT_BY_SYMBOL_MARGIN_SELL_LIMIT_INITIAL, // Sort by initial margin requirement applicable to SellLimit orders SORT_BY_SYMBOL_MARGIN_SELL_STOPLIMIT_INITIAL, // Sort by initial margin requirement applicable to SellStopLimit orders SORT_BY_SYMBOL_MARGIN_SHORT_MAINTENANCE, // Sort by maintenance margin requirement applicable to Short orders SORT_BY_SYMBOL_MARGIN_SELL_STOP_MAINTENANCE, // Sort by maintenance margin requirement applicable to SellStop orders SORT_BY_SYMBOL_MARGIN_SELL_LIMIT_MAINTENANCE, // Sort by maintenance margin requirement applicable to SellLimit orders SORT_BY_SYMBOL_MARGIN_SELL_STOPLIMIT_MAINTENANCE, // Sort by maintenance margin requirement applicable to SellStopLimit orders SORT_BY_SYMBOL_SESSION_VOLUME, // Sort by summary volume of the current session deals SORT_BY_SYMBOL_SESSION_TURNOVER, // Sort by the summary turnover of the current session SORT_BY_SYMBOL_SESSION_INTEREST, // Sort by the summary open interest SORT_BY_SYMBOL_SESSION_BUY_ORDERS_VOLUME, // Sort by the current volume of Buy orders SORT_BY_SYMBOL_SESSION_SELL_ORDERS_VOLUME, // Sort by the current volume of Sell orders SORT_BY_SYMBOL_SESSION_OPEN, // Sort by a session Open price SORT_BY_SYMBOL_SESSION_CLOSE, // Sort by a session Close price SORT_BY_SYMBOL_SESSION_AW, // Sort by an average weighted price of the current session SORT_BY_SYMBOL_SESSION_PRICE_SETTLEMENT, // Sort by a settlement price of the current session SORT_BY_SYMBOL_SESSION_PRICE_LIMIT_MIN, // Sort by a minimum price of the current session SORT_BY_SYMBOL_SESSION_PRICE_LIMIT_MAX, // Sort by a maximum price of the current session SORT_BY_SYMBOL_MARGIN_HEDGED, // Sort by a contract size or a margin value per one lot of hedged positions //--- 文字列型プロパティによって並び替える SORT_BY_SYMBOL_NAME = FIRST_SYM_STR_PROP, // Sort by a symbol name SORT_BY_SYMBOL_BASIS, // Sort by an underlying asset of a derivative SORT_BY_SYMBOL_CURRENCY_BASE, // Sort by a base currency of a symbol SORT_BY_SYMBOL_CURRENCY_PROFIT, // Sort by a profit currency SORT_BY_SYMBOL_CURRENCY_MARGIN, // Sort by a margin currency SORT_BY_SYMBOL_BANK, // Sort by a feeder of the current quote SORT_BY_SYMBOL_DESCRIPTION, // Sort by a symbol string description SORT_BY_SYMBOL_FORMULA, // Sort by the formula used for custom symbol pricing SORT_BY_SYMBOL_ISIN, // Sort by the name of a symbol in the ISIN system SORT_BY_SYMBOL_PAGE, // Sort by an address of the web page containing symbol information SORT_BY_SYMBOL_PATH // Sort by a path in the symbol tree }; //+------------------------------------------------------------------+
Defines.mqhファイルでの作業は完了です。
ここで、銘柄オブジェクトクラスを改善する必要があります。一部の銘柄プロパティの変更を追跡するため、絶対値で、または特定の所定の閾値の増加を検出するために、現在の値を前の値と比較する必要があります。これを実現するには、銘柄プロパティの構造体を作成し、構造体の現在の値のフィールドを以前の値の構造のフィールドと比較する必要があります。オブジェクトイベントを定義するロジックについては口座イベントの追跡を実装する際に既に説明しました。ここでも同じことを行いますが、基本オブジェクトにはイベントを保存してプログラムに送信するメソッドが既に備わっているという点が異なります。
基本オブジェクトファイルをCSymbolクラスに接続します。クラスのprivateセクションで、追跡対象の銘柄プロパティの構造体を作成し、銘柄プロパティの現在および以前ののステータスを保存するための構造体の2つの変数を宣言します 。
//+------------------------------------------------------------------+ //| Symbol.mqh | //| Copyright 2018, MetaQuotes Software Corp. | //| https://mql5.com/ja/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2018, MetaQuotes Software Corp." #property link "https://mql5.com/ja/users/artmedia70" #property version "1.00" #property strict // mql4で必要 //+------------------------------------------------------------------+ //| ファイルをインクルードする | //+------------------------------------------------------------------+ #include "..\BaseObj.mqh" //+------------------------------------------------------------------+ //| Abstract symbol class | //+------------------------------------------------------------------+ class CSymbol : public CBaseObj { private: struct MqlDataSymbol { //--- Symbol integer properties ENUM_SYMBOL_TRADE_MODE trade_mode; // SYMBOL_TRADE_MODE Order filling modes long session_deals; // SYMBOL_SESSION_DEALS The number of deals in the current session long session_buy_orders; // SYMBOL_SESSION_BUY_ORDERS The total number of current buy orders long session_sell_orders; // SYMBOL_SESSION_SELL_ORDERS The total number of current sell orders long volume; // SYMBOL_VOLUME Last deal volume long volume_high_day; // SYMBOL_VOLUMEHIGH Maximum volume within a day long volume_low_day; // SYMBOL_VOLUMELOW Minimum volume within a day int spread; // SYMBOL_SPREAD Spread in points int stops_level; // SYMBOL_TRADE_STOPS_LEVEL Minimum distance in points from the current close price for setting Stop orders int freeze_level; // SYMBOL_TRADE_FREEZE_LEVEL Freeze distance for trading operations (in points) //--- Symbol real properties double bid_last; // SYMBOL_BID/SYMBOL_LAST Bid - the best sell offer/Last deal price double bid_last_high; // SYMBOL_BIDHIGH/SYMBOL_LASTHIGH Maximum Bid within the day/Maximum Last per day double bid_last_low; // SYMBOL_BIDLOW/SYMBOL_LASTLOW Minimum Bid within the day/Minimum Last per day double ask; // SYMBOL_ASK Ask - nest buy offer double ask_high; // SYMBOL_ASKHIGH Maximum Ask of the day double ask_low; // SYMBOL_ASKLOW Minimum Ask of the day double volume_real_day; // SYMBOL_VOLUME_REAL Real Volume of the day double volume_high_real_day; // SYMBOL_VOLUMEHIGH_REAL Maximum real Volume of the day double volume_low_real_day; // SYMBOL_VOLUMELOW_REAL Minimum real Volume of the day double option_strike; // SYMBOL_OPTION_STRIKE Strike price double volume_limit; // SYMBOL_VOLUME_LIMIT Maximum permissible total volume for a position and pending orders in one direction double swap_long; // SYMBOL_SWAP_LONG Long swap value double swap_short; // SYMBOL_SWAP_SHORT Short swap value double session_volume; // SYMBOL_SESSION_VOLUME The total volume of deals in the current session double session_turnover; // SYMBOL_SESSION_TURNOVER The total turnover in the current session double session_interest; // SYMBOL_SESSION_INTEREST The total volume of open positions double session_buy_ord_volume; // SYMBOL_SESSION_BUY_ORDERS_VOLUME The total volume of Buy orders at the moment double session_sell_ord_volume; // SYMBOL_SESSION_SELL_ORDERS_VOLUME The total volume of Sell orders at the moment double session_open; // SYMBOL_SESSION_OPEN Session open price double session_close; // SYMBOL_SESSION_CLOSE Session close price double session_aw; // SYMBOL_SESSION_AW The average weighted price of the session }; MqlDataSymbol m_struct_curr_symbol; // Current symbol data MqlDataSymbol m_struct_prev_symbol; // Previous symbol data //---
次に、指定された制御対象のプロパティの変更値、発生した変更値、および追跡対象のイベントの存在を示すフラグを保存するためのクラスメンバ変数を宣言します。
//--- Execution bool m_is_change_trade_mode; // Flag of changing trading mode for a symbol //--- Current session deals long m_control_session_deals_inc; // Controlled value of the growth of the number of deals long m_control_session_deals_dec; // Controlled value of the decrease in the number of deals long m_changed_session_deals_value; // Value of change in the number of deals bool m_is_change_session_deals_inc; // Flag of a change in the number of deals exceeding the growth value bool m_is_change_session_deals_dec; // Flag of a change in the number of deals exceeding the decrease value //--- Buy orders of the current session long m_control_session_buy_ord_inc; // Controlled value of the growth of the number of Buy orders long m_control_session_buy_ord_dec; // Controlled value of the decrease in the number of Buy orders long m_changed_session_buy_ord_value; // Buy orders change value bool m_is_change_session_buy_ord_inc; // Flag of a change in the number of Buy orders exceeding the growth value bool m_is_change_session_buy_ord_dec; // Flag of a change in the number of Buy orders being less than the growth value //--- Sell orders of the current session long m_control_session_sell_ord_inc; // Controlled value of the growth of the number of Sell orders long m_control_session_sell_ord_dec; // Controlled value of the decrease in the number of Sell orders long m_changed_session_sell_ord_value; // Sell orders change value bool m_is_change_session_sell_ord_inc; // Flag of a change in the number of Sell orders exceeding the growth value bool m_is_change_session_sell_ord_dec; // Flag of a change in the number of Sell orders exceeding the decrease value //--- Volume of the last deal long m_control_volume_inc; // Controlled value of the volume growth in the last deal long m_control_volume_dec; // Controlled value of the volume decrease in the last deal long m_changed_volume_value; // Value of the volume change in the last deal bool m_is_change_volume_inc; // Flag of the volume change in the last deal exceeding the growth value bool m_is_change_volume_dec; // Flag of the volume change in the last deal being less than the growth value //--- Maximum volume within a day long m_control_volume_high_day_inc; // Controlled value of the maximum volume growth for a day long m_control_volume_high_day_dec; // Controlled value of the maximum volume decrease for a day long m_changed_volume_high_day_value; // Maximum volume change value within a day bool m_is_change_volume_high_day_inc; // Flag of the maximum day volume exceeding the growth value bool m_is_change_volume_high_day_dec; // Flag of the maximum day volume exceeding the decrease value //--- Minimum volume within a day long m_control_volume_low_day_inc; // Controlled value of the minimum volume growth for a day long m_control_volume_low_day_dec; // Controlled value of the minimum volume decrease for a day long m_changed_volume_low_day_value; // Minimum volume change value within a day bool m_is_change_volume_low_day_inc; // Flag of the minimum day volume exceeding the growth value bool m_is_change_volume_low_day_dec; // Flag of the minimum day volume exceeding the decrease value //--- Spread int m_control_spread_inc; // Controlled spread growth value in points int m_control_spread_dec; // Controlled spread decrease value in points int m_changed_spread_value; // Spread change value in points bool m_is_change_spread_inc; // Flag of spread change in points exceeding the growth value bool m_is_change_spread_dec; // Flag of spread change in points exceeding the decrease value //--- StopLevel int m_control_stops_level_inc; // Controlled StopLevel growth value in points int m_control_stops_level_dec; // Controlled StopLevel decrease value in points int m_changed_stops_level_value; // StopLevel change value in points bool m_is_change_stops_level_inc; // Flag of StopLevel change in points exceeding the growth value bool m_is_change_stops_level_dec; // Flag of StopLevel change in points exceeding the decrease value //--- Freeze distance int m_control_freeze_level_inc; // Controlled FreezeLevel growth value in points int m_control_freeze_level_dec; // Controlled FreezeLevel decrease value in points int m_changed_freeze_level_value; // FreezeLevel change value in points bool m_is_change_freeze_level_inc; // Flag of FreezeLevel change in points exceeding the growth value bool m_is_change_freeze_level_dec; // Flag of FreezeLevel change in points exceeding the decrease value //--- Bid/Last double m_control_bid_last_inc; // Controlled value of Bid or Last price growth double m_control_bid_last_dec; // Controlled value of Bid or Last price decrease double m_changed_bid_last_value; // Bid or Last price change value bool m_is_change_bid_last_inc; // Flag of Bid or Last price change exceeding the growth value bool m_is_change_bid_last_dec; // Flag of Bid or Last price change exceeding the decrease value //--- Maximum Bid/Last of the day double m_control_bid_last_high_inc; // Controlled growth value of the maximum Bid or Last price of the day double m_control_bid_last_high_dec; // Controlled decrease value of the maximum Bid or Last price of the day double m_changed_bid_last_high_value; // Maximum Bid or Last change value for the day bool m_is_change_bid_last_high_inc; // Flag of the maximum Bid or Last price change for the day exceeding the growth value bool m_is_change_bid_last_high_dec; // Flag of the maximum Bid or Last price change for the day exceeding the decrease value //--- Minimum Bid/Last of the day double m_control_bid_last_low_inc; // Controlled growth value of the minimum Bid or Last price of the day double m_control_bid_last_low_dec; // Controlled decrease value of the minimum Bid or Last price of the day double m_changed_bid_last_low_value; // Minimum Bid or Last change value for the day bool m_is_change_bid_last_low_inc; // Flag of the minimum Bid or Last price change for the day exceeding the growth value bool m_is_change_bid_last_low_dec; // Flag of the minimum Bid or Last price change for the day exceeding the decrease value //--- Ask double m_control_ask_inc; // Controlled value of the Ask price growth double m_control_ask_dec; // Controlled value of the Ask price decrease double m_changed_ask_value; // Ask price change value bool m_is_change_ask_inc; // Flag of the Ask price change exceeding the growth value bool m_is_change_ask_dec; // Flag of the Ask price change exceeding the decrease value //--- Maximum Ask price for the day double m_control_ask_high_inc; // Controlled growth value of the maximum Ask price of the day double m_control_ask_high_dec; // Controlled decrease value of the maximum Ask price of the day double m_changed_ask_high_value; // Maximum Ask price change value for the day bool m_is_change_ask_high_inc; // Flag of the maximum Ask price change for the day exceeding the growth value bool m_is_change_ask_high_dec; // Flag of the maximum Ask price change for the day exceeding the decrease value //--- Minimum Ask price for the day double m_control_ask_low_inc; // Controlled growth value of the minimum Ask price of the day double m_control_ask_low_dec; // Controlled decrease value of the minimum Ask price of the day double m_changed_ask_low_value; // Minimum Ask price change value for the day bool m_is_change_ask_low_inc; // Flag of the minimum Ask price change for the day exceeding the growth value bool m_is_change_ask_low_dec; // Flag of the minimum Ask price change for the day exceeding the decrease value //--- Real Volume for the day double m_control_volume_real_inc; // Controlled value of the real volume growth of the day double m_control_volume_real_dec; // Controlled value of the real volume decrease of the day double m_changed_volume_real_value; // Real volume change value of the day bool m_is_change_volume_real_inc; // Flag of the real volume change for the day exceeding the growth value bool m_is_change_volume_real_dec; // Flag of the real volume change for the day exceeding the decrease value //--- Maximum real volume for the day double m_control_volume_high_real_day_inc; // Controlled value of the maximum real volume growth of the day double m_control_volume_high_real_day_dec; // Controlled value of the maximum real volume decrease of the day double m_changed_volume_high_real_day_value; // Maximum real volume change value of the day bool m_is_change_volume_high_real_day_inc; // Flag of the maximum real volume change for the day exceeding the growth value bool m_is_change_volume_high_real_day_dec; // Flag of the maximum real volume change for the day exceeding the decrease value //--- Minimum real volume for the day double m_control_volume_low_real_day_inc; // Controlled value of the minimum real volume growth of the day double m_control_volume_low_real_day_dec; // Controlled value of the minimum real volume decrease of the day double m_changed_volume_low_real_day_value; // Minimum real volume change value of the day bool m_is_change_volume_low_real_day_inc; // Flag of the minimum real volume change for the day exceeding the growth value bool m_is_change_volume_low_real_day_dec; // Flag of the minimum real volume change for the day exceeding the decrease value //--- Strike price double m_control_option_strike_inc; // Controlled value of the strike price growth double m_control_option_strike_dec; // Controlled value of the strike price decrease double m_changed_option_strike_value; // Strike price change value bool m_is_change_option_strike_inc; // Flag of the strike price change exceeding the growth value bool m_is_change_option_strike_dec; // Flag of the strike price change exceeding the decrease value //--- Total volume of positions and orders double m_changed_volume_limit_value; // Minimum total volume change value bool m_is_change_volume_limit_inc; // Flag of the minimum total volume increase bool m_is_change_volume_limit_dec; // Flag of the minimum total volume decrease //--- Swap long double m_changed_swap_long_value; // Swap long change value bool m_is_change_swap_long_inc; // Flag of the swap long increase bool m_is_change_swap_long_dec; // Flag of the swap long decrease //--- Swap short double m_changed_swap_short_value; // Swap short change value bool m_is_change_swap_short_inc; // Flag of the swap short increase bool m_is_change_swap_short_dec; // Flag of the swap short decrease //--- The total volume of deals in the current session double m_control_session_volume_inc; // Controlled value of the total trade volume growth in the current session double m_control_session_volume_dec; // Controlled value of the total trade volume decrease in the current session double m_changed_session_volume_value; // The total deal volume change value in the current session bool m_is_change_session_volume_inc; // Flag of total trade volume change in the current session exceeding the growth value bool m_is_change_session_volume_dec; // Flag of total trade volume change in the current session exceeding the decrease value //--- The total turnover in the current session double m_control_session_turnover_inc; // Controlled value of the total turnover growth in the current session double m_control_session_turnover_dec; // Controlled value of the total turnover decrease in the current session double m_changed_session_turnover_value; // Total turnover change value in the current session bool m_is_change_session_turnover_inc; // Flag of total turnover change in the current session exceeding the growth value bool m_is_change_session_turnover_dec; // Flag of total turnover change in the current session exceeding the decrease value //--- The total volume of open positions double m_control_session_interest_inc; // Controlled value of the total open position volume growth in the current session double m_control_session_interest_dec; // Controlled value of the total open position volume decrease in the current session double m_changed_session_interest_value; // Change value of the open positions total volume in the current session bool m_is_change_session_interest_inc; // Flag of total open positions' volume change in the current session exceeding the growth value bool m_is_change_session_interest_dec; // Flag of total open positions' volume change in the current session exceeding the decrease value //--- The total volume of Buy orders at the moment double m_control_session_buy_ord_volume_inc; // Controlled value of the current total buy order volume growth double m_control_session_buy_ord_volume_dec; // Controlled value of the current total buy order volume decrease double m_changed_session_buy_ord_volume_value; // Change value of the current total buy order volume bool m_is_change_session_buy_ord_volume_inc; // Flag of changing the current total buy orders volume exceeding the growth value bool m_is_change_session_buy_ord_volume_dec; // Flag of changing the current total buy orders volume exceeding the decrease value //--- The total volume of Sell orders at the moment double m_control_session_sell_ord_volume_inc; // Controlled value of the current total sell order volume growth double m_control_session_sell_ord_volume_dec; // Controlled value of the current total sell order volume decrease double m_changed_session_sell_ord_volume_value; // Change value of the current total sell order volume bool m_is_change_session_sell_ord_volume_inc; // Flag of changing the current total sell orders volume exceeding the growth value bool m_is_change_session_sell_ord_volume_dec; // Flag of changing the current total sell orders volume exceeding the decrease value //--- Session open price double m_control_session_open_inc; // Controlled value of the session open price growth double m_control_session_open_dec; // Controlled value of the session open price decrease double m_changed_session_open_value; // Session open price change value bool m_is_change_session_open_inc; // Flag of the session open price change exceeding the growth value bool m_is_change_session_open_dec; // Flag of the session open price change exceeding the decrease value //--- Session close price double m_control_session_close_inc; // Controlled value of the session close price growth double m_control_session_close_dec; // Controlled value of the session close price decrease double m_changed_session_close_value; // Session close price change value bool m_is_change_session_close_inc; // Flag of the session close price change exceeding the growth value bool m_is_change_session_close_dec; // Flag of the session close price change exceeding the decrease value //--- The average weighted session price double m_control_session_aw_inc; // Controlled value of the average weighted session price growth double m_control_session_aw_dec; // Controlled value of the average weighted session price decrease double m_changed_session_aw_value; // The average weighted session price change value bool m_is_change_session_aw_inc; // Flag of the average weighted session price change value exceeding the growth value bool m_is_change_session_aw_dec; // Flag of the average weighted session price change value exceeding the decrease value
privateセクションで、追跡対象の変数の初期化および銘柄プロパティの仮想メソッド(CBaseObj基本クラスで既に宣言済み)と、プロパティの変更を確認してイベントコードを返すメソッドとコードでイベントタイプを設定し、イベントリストに書き込むメソッドを宣言します。
//--- Initialize the variables of (1) tracked, (2) controlled symbol data virtual void InitChangesParams(void); virtual void InitControlsParams(void); //--- Check symbol changes, return a change code virtual int SetEventCode(void); //--- Set an event type and fill in the event list virtual void SetTypeEvent(void);
クラス本体の外側で実装しましょう。
以下は、追跡対象の銘柄オブジェクトプロパティを初期化するメソッドです。
//+------------------------------------------------------------------+ //| Initialize the variables of tracked symbol data | //+------------------------------------------------------------------+ void CSymbol::InitChangesParams(void) { //--- List and code of changes this.m_list_events.Clear(); // Clear the change list this.m_list_events.Sort(); // Sort the change list //--- Execution this.m_is_change_trade_mode=false; // Flag of changing trading mode for a symbol //--- Current session deals this.m_changed_session_deals_value=0; // Value of change in the number of deals this.m_is_change_session_deals_inc=false; // Flag of a change in the number of deals exceeding the growth value this.m_is_change_session_deals_dec=false; // Flag of a change in the number of deals exceeding the decrease value //--- Buy orders of the current session this.m_changed_session_buy_ord_value=0; // Buy orders change value this.m_is_change_session_buy_ord_inc=false; // Flag of a change in the number of Buy orders exceeding the growth value this.m_is_change_session_buy_ord_dec=false; // Flag of a change in the number of Buy orders exceeding the decrease value //--- Sell orders of the current session this.m_changed_session_sell_ord_value=0; // Sell orders change value this.m_is_change_session_sell_ord_inc=false; // Flag of a change in the number of Sell orders exceeding the growth value this.m_is_change_session_sell_ord_dec=false; // Flag of a change in the number of Sell orders exceeding the decrease value //--- Volume of the last deal this.m_changed_volume_value=0; // Value of the volume change in the last deal this.m_is_change_volume_inc=false; // Flag of the volume change in the last deal exceeding the growth value this.m_is_change_volume_dec=false; // Flag of the volume change in the last deal exceeding the decrease value //--- Maximum volume within a day this.m_changed_volume_high_day_value=0; // Maximum volume change value within a day this.m_is_change_volume_high_day_inc=false; // Flag of the maximum day volume exceeding the growth value this.m_is_change_volume_high_day_dec=false; // Flag of the maximum day volume exceeding the decrease value //--- Minimum volume within a day this.m_changed_volume_low_day_value=0; // Minimum volume change value within a day this.m_is_change_volume_low_day_inc=false; // Flag of the minimum day volume exceeding the growth value this.m_is_change_volume_low_day_dec=false; // Flag of the minimum day volume exceeding the decrease value //--- Spread this.m_changed_spread_value=0; // Spread change value in points this.m_is_change_spread_inc=false; // Flag of spread change in points exceeding the growth value this.m_is_change_spread_dec=false; // Flag of spread change in points exceeding the decrease value //--- StopLevel this.m_changed_stops_level_value=0; // StopLevel change value in points this.m_is_change_stops_level_inc=false; // Flag of StopLevel change in points exceeding the growth value this.m_is_change_stops_level_dec=false; // Flag of StopLevel change in points exceeding the decrease value //--- Freeze distance this.m_changed_freeze_level_value=0; // FreezeLevel change value in points this.m_is_change_freeze_level_inc=false; // Flag of FreezeLevel change in points exceeding the growth value this.m_is_change_freeze_level_dec=false; // Flag of FreezeLevel change in points exceeding the decrease value //--- Bid/Last this.m_changed_bid_last_value=0; // Bid or Last price change value this.m_is_change_bid_last_inc=false; // Flag of Bid or Last price change exceeding the growth value this.m_is_change_bid_last_dec=false; // Flag of Bid or Last price change exceeding the decrease value //--- Maximum Bid/Last of the day this.m_changed_bid_last_high_value=0; // Maximum Bid or Last change value for the day this.m_is_change_bid_last_high_inc=false; // Flag of the maximum Bid or Last price change for the day exceeding the growth value this.m_is_change_bid_last_high_dec=false; // Flag of the maximum Bid or Last price change for the day exceeding the decrease value //--- Minimum Bid/Last of the day this.m_changed_bid_last_low_value=0; // Minimum Bid or Last change value for the day this.m_is_change_bid_last_low_inc=false; // Flag of the minimum Bid or Last price change for the day exceeding the growth value this.m_is_change_bid_last_low_dec=false; // Flag of the minimum Bid or Last price change for the day exceeding the decrease value //--- Ask this.m_changed_ask_value=0; // Ask price change value this.m_is_change_ask_inc=false; // Flag of the Ask price change exceeding the growth value this.m_is_change_ask_dec=false; // Flag of the Ask price change exceeding the decrease value //--- Maximum Ask price for the day this.m_changed_ask_high_value=0; // Maximum Ask price change value for the day this.m_is_change_ask_high_inc=false; // Flag of the maximum day Ask exceeding the growth value this.m_is_change_ask_high_dec=false; // Flag of the maximum day Ask exceeding the decrease value //--- Minimum Ask price for the day this.m_changed_ask_low_value=0; // Minimum Ask price change value for the day this.m_is_change_ask_low_inc=false; // Flag of the minimum Ask volume exceeding the growth value this.m_is_change_ask_low_dec=false; // Flag of the minimum Ask volume exceeding the decrease value //--- Real Volume for the day this.m_changed_volume_real_value=0; // Real volume change value of the day this.m_is_change_volume_real_inc=false; // Flag of the real volume change for the day exceeding the growth value this.m_is_change_volume_real_dec=false; // Flag of the real volume change for the day exceeding the decrease value //--- Maximum real volume for the day this.m_changed_volume_high_real_day_value=0; // Maximum real volume change value of the day this.m_is_change_volume_high_real_day_inc=false; // Flag of the maximum real volume change for the day exceeding the growth value this.m_is_change_volume_high_real_day_dec=false; // Flag of the maximum real volume change for the day exceeding the decrease value //--- Minimum real volume for the day this.m_changed_volume_low_real_day_value=0; // Minimum real volume change value of the day this.m_is_change_volume_low_real_day_inc=false; // Flag of the minimum real volume change for the day exceeding the growth value this.m_is_change_volume_low_real_day_dec=false; // Flag of the minimum real volume change for the day exceeding the decrease value //--- Strike price this.m_changed_option_strike_value=0; // Strike price change value this.m_is_change_option_strike_inc=false; // Flag of the strike price change exceeding the growth value this.m_is_change_option_strike_dec=false; // Flag of the strike price change exceeding the decrease value //--- Total volume of positions and orders this.m_changed_volume_limit_value=0; // Minimum total volume change value this.m_is_change_volume_limit_inc=false; // Flag of the minimum total volume increase this.m_is_change_volume_limit_dec=false; // Flag of the minimum total volume decrease //--- Swap long this.m_changed_swap_long_value=0; // Swap long change value this.m_is_change_swap_long_inc=false; // Flag of the swap long increase this.m_is_change_swap_long_dec=false; // Flag of the swap long decrease //--- Swap short this.m_changed_swap_short_value=0; // Swap short change value this.m_is_change_swap_short_inc=false; // Flag of the swap short increase this.m_is_change_swap_short_dec=false; // Flag of the swap short decrease //--- The total volume of deals in the current session this.m_changed_session_volume_value=0; // The total deal volume change value in the current session this.m_is_change_session_volume_inc=false; // Flag of total trade volume change in the current session exceeding the growth value this.m_is_change_session_volume_dec=false; // Flag of total trade volume change in the current session exceeding the decrease value //--- The total turnover in the current session this.m_changed_session_turnover_value=0; // Total turnover change value in the current session this.m_is_change_session_turnover_inc=false; // Flag of total turnover change in the current session exceeding the growth value this.m_is_change_session_turnover_dec=false; // Flag of total turnover change in the current session exceeding the decrease value //--- The total volume of open positions this.m_changed_session_interest_value=0; // Change value of the open positions total volume in the current session this.m_is_change_session_interest_inc=false; // Flag of total open positions' volume change in the current session exceeding the growth value this.m_is_change_session_interest_dec=false; // Flag of total open positions' volume change in the current session exceeding the decrease value //--- The total volume of Buy orders at the moment this.m_changed_session_buy_ord_volume_value=0; // Change value of the current total buy order volume this.m_is_change_session_buy_ord_volume_inc=false; // Flag of changing the current total buy orders volume exceeding the growth value this.m_is_change_session_buy_ord_volume_dec=false; // Flag of changing the current total buy orders volume exceeding the decrease value //--- The total volume of Sell orders at the moment this.m_changed_session_sell_ord_volume_value=0; // Change value of the current total sell order volume this.m_is_change_session_sell_ord_volume_inc=false; // Flag of changing the current total sell orders volume exceeding the growth value this.m_is_change_session_sell_ord_volume_dec=false; // Flag of changing the current total sell orders volume exceeding the decrease value //--- Session open price this.m_changed_session_open_value=0; // Session open price change value this.m_is_change_session_open_inc=false; // Flag of the session open price change exceeding the growth value this.m_is_change_session_open_dec=false; // Flag of the session open price change exceeding the decrease value //--- Session close price this.m_changed_session_close_value=0; // Session close price change value this.m_is_change_session_close_inc=false; // Flag of the session close price change exceeding the growth value this.m_is_change_session_close_dec=false; // Flag of the session close price change exceeding the decrease value //--- The average weighted session price this.m_changed_session_aw_value=0; // The average weighted session price change value this.m_is_change_session_aw_inc=false; // Flag of the average weighted session price change value exceeding the growth value this.m_is_change_session_aw_dec=false; // Flag of the average weighted session price change value exceeding the decrease value } //+------------------------------------------------------------------+
メソッドでは単に、追跡対象の銘柄プロパティの変数に初期値が割り当てられます。これらは、クラスのprivateセクションで以前に宣言された初期変数です。
以下は、銘柄プロパティの制御値を初期化するメソッドです。
//+------------------------------------------------------------------+ //| Initialize the variables of controlled symbol data | //+------------------------------------------------------------------+ void CSymbol::InitControlsParams(void) { //--- Current session deals this.m_control_session_deals_inc=10; // Controlled value of the growth of the number of deals this.m_control_session_deals_dec=10; // Controlled value of the decrease in the number of deals //--- Buy orders of the current session this.m_control_session_buy_ord_inc=10; // Controlled value of the growth of the number of Buy orders this.m_control_session_buy_ord_dec=10; // Controlled value of the decrease in the number of Buy orders //--- Sell orders of the current session this.m_control_session_sell_ord_inc=10; // Controlled value of the growth of the number of Sell orders this.m_control_session_sell_ord_dec=10; // Controlled value of the decrease in the number of Sell orders //--- Volume of the last deal this.m_control_volume_inc=10; // Controlled value of the volume growth in the last deal this.m_control_volume_dec=10; // Controlled value of the volume decrease in the last deal //--- Maximum volume within a day this.m_control_volume_high_day_inc=50; // Controlled value of the maximum volume growth for a day this.m_control_volume_high_day_dec=50; // Controlled value of the maximum volume decrease for a day //--- Minimum volume within a day this.m_control_volume_low_day_inc=50; // Controlled value of the minimum volume growth for a day this.m_control_volume_low_day_dec=50; // Controlled value of the minimum volume decrease for a day //--- Spread this.m_control_spread_inc=2; // Controlled spread growth value in points this.m_control_spread_dec=2; // Controlled spread decrease value in points //--- StopLevel this.m_control_stops_level_inc=2; // Controlled StopLevel growth value in points this.m_control_stops_level_dec=2; // Controlled StopLevel decrease value in points //--- Freeze distance this.m_control_freeze_level_inc=2; // Controlled FreezeLevel growth value in points this.m_control_freeze_level_dec=2; // Controlled FreezeLevel decrease value in points //--- Bid/Last this.m_control_bid_last_inc=DBL_MAX; // Controlled value of Bid or Last price growth this.m_control_bid_last_dec=DBL_MAX; // Controlled value of Bid or Last price decrease //--- Maximum Bid/Last of the day this.m_control_bid_last_high_inc=DBL_MAX; // Controlled growth value of the maximum Bid or Last price of the day this.m_control_bid_last_high_dec=DBL_MAX; // Controlled decrease value of the maximum Bid or Last price of the day //--- Minimum Bid/Last of the day this.m_control_bid_last_low_inc=DBL_MAX; // Controlled growth value of the minimum Bid or Last price of the day this.m_control_bid_last_low_dec=DBL_MAX; // Controlled decrease value of the minimum Bid or Last price of the day //--- Ask this.m_control_ask_inc=DBL_MAX; // Controlled value of the Ask price growth this.m_control_ask_dec=DBL_MAX; // Controlled value of the Ask price decrease //--- Maximum Ask price for the day this.m_control_ask_high_inc=DBL_MAX; // Controlled growth value of the maximum Ask price of the day this.m_control_ask_high_dec=DBL_MAX; // Controlled decrease value of the maximum Ask price of the day //--- Minimum Ask price for the day this.m_control_ask_low_inc=DBL_MAX; // Controlled growth value of the minimum Ask price of the day this.m_control_ask_low_dec=DBL_MAX; // Controlled decrease value of the minimum Ask price of the day //--- Real Volume for the day this.m_control_volume_real_inc=50; // Controlled value of the real volume growth of the day this.m_control_volume_real_dec=50; // Controlled value of the real volume decrease of the day //--- Maximum real volume for the day this.m_control_volume_high_real_day_inc=20; // Controlled value of the maximum real volume growth of the day this.m_control_volume_high_real_day_dec=20; // Controlled value of the maximum real volume decrease of the day //--- Minimum real volume for the day this.m_control_volume_low_real_day_inc=10; // Controlled value of the minimum real volume growth of the day this.m_control_volume_low_real_day_dec=10; // Controlled value of the minimum real volume decrease of the day //--- Strike price this.m_control_option_strike_inc=0; // Controlled value of the strike price growth this.m_control_option_strike_dec=0; // Controlled value of the strike price decrease //--- The total volume of deals in the current session this.m_control_session_volume_inc=10; // Controlled value of the total trade volume growth in the current session this.m_control_session_volume_dec=10; // Controlled value of the total trade volume decrease in the current session //--- The total turnover in the current session this.m_control_session_turnover_inc=1000; // Controlled value of the total turnover growth in the current session this.m_control_session_turnover_dec=500; // Controlled value of the total turnover decrease in the current session //--- The total volume of open positions this.m_control_session_interest_inc=50; // Controlled value of the total open position volume growth in the current session this.m_control_session_interest_dec=20; // Controlled value of the total open position volume decrease in the current session //--- The total volume of Buy orders at the moment this.m_control_session_buy_ord_volume_inc=50; // Controlled value of the current total buy order volume growth this.m_control_session_buy_ord_volume_dec=20; // Controlled value of the current total buy order volume decrease //--- The total volume of Sell orders at the moment this.m_control_session_sell_ord_volume_inc=50; // Controlled value of the current total sell order volume growth this.m_control_session_sell_ord_volume_dec=20; // Controlled value of the current total sell order volume decrease //--- Session open price this.m_control_session_open_inc=0; // Controlled value of the session open price growth this.m_control_session_open_dec=0; // Controlled value of the session open price decrease //--- Session close price this.m_control_session_close_inc=0; // Controlled value of the session close price growth this.m_control_session_close_dec=0; // Controlled value of the session close price decrease //--- The average weighted session price this.m_control_session_aw_inc=0; // Controlled value of the average weighted session price growth this.m_control_session_aw_dec=0; // Controlled value of the average weighted session price decrease } //+------------------------------------------------------------------+
メソッドでは単に、制御対象の銘柄プロパティの変数に初期値が割り当てられます。これらは、クラスのprivateセクションで以前に宣言された初期変数です。プロパティが変数に設定された値を超えると、適切な口座イベントが生成されます。プロパティコントロールを無効にするには、DBL_MAXの値をその変数に割り当てる必要があります。変更を追跡するには、変数に0を割り当てます。
以下は、発生した銘柄プロパティの変更を確認して、発生した変更コードを返すメソッドです。
//+------------------------------------------------------------------+ //| Check symbol changes, return a change code | //+------------------------------------------------------------------+ int CSymbol::SetEventCode(void) { this.m_event_code=SYMBOL_EVENT_FLAG_NO_EVENT; if(this.m_struct_curr_symbol.trade_mode!=this.m_struct_prev_symbol.trade_mode) this.m_event_code+=SYMBOL_EVENT_FLAG_TRADE_MODE; if(this.m_struct_curr_symbol.session_deals!=this.m_struct_prev_symbol.session_deals) this.m_event_code+=SYMBOL_EVENT_FLAG_SESSION_DEALS; if(this.m_struct_curr_symbol.session_buy_orders!=this.m_struct_prev_symbol.session_buy_orders) this.m_event_code+=SYMBOL_EVENT_FLAG_SESSION_BUY_ORDERS; if(this.m_struct_curr_symbol.session_sell_orders!=this.m_struct_prev_symbol.session_sell_orders) this.m_event_code+=SYMBOL_EVENT_FLAG_SESSION_SELL_ORDERS; if(this.m_struct_curr_symbol.volume!=this.m_struct_prev_symbol.volume) this.m_event_code+=SYMBOL_EVENT_FLAG_VOLUME; if(this.m_struct_curr_symbol.volume_high_day!=this.m_struct_prev_symbol.volume_high_day) this.m_event_code+=SYMBOL_EVENT_FLAG_VOLUME_HIGH_DAY; if(this.m_struct_curr_symbol.volume_low_day!=this.m_struct_prev_symbol.volume_low_day) this.m_event_code+=SYMBOL_EVENT_FLAG_VOLUME_LOW_DAY; if(this.m_struct_curr_symbol.spread!=this.m_struct_prev_symbol.spread) this.m_event_code+=SYMBOL_EVENT_FLAG_SPREAD; if(this.m_struct_curr_symbol.stops_level!=this.m_struct_prev_symbol.stops_level) this.m_event_code+=SYMBOL_EVENT_FLAG_STOPLEVEL; if(this.m_struct_curr_symbol.freeze_level!=this.m_struct_prev_symbol.freeze_level) this.m_event_code+=SYMBOL_EVENT_FLAG_FREEZELEVEL; if(this.m_struct_curr_symbol.bid_last!=this.m_struct_prev_symbol.bid_last) this.m_event_code+=SYMBOL_EVENT_FLAG_BID_LAST; if(this.m_struct_curr_symbol.bid_last_high!=this.m_struct_prev_symbol.bid_last_high) this.m_event_code+=SYMBOL_EVENT_FLAG_BID_LAST_HIGH; if(this.m_struct_curr_symbol.bid_last_low!=this.m_struct_prev_symbol.bid_last_low) this.m_event_code+=SYMBOL_EVENT_FLAG_BID_LAST_LOW; if(this.m_struct_curr_symbol.ask!=this.m_struct_prev_symbol.ask) this.m_event_code+=SYMBOL_EVENT_FLAG_ASK; if(this.m_struct_curr_symbol.ask_high!=this.m_struct_prev_symbol.ask_high) this.m_event_code+=SYMBOL_EVENT_FLAG_ASK_HIGH; if(this.m_struct_curr_symbol.ask_low!=this.m_struct_prev_symbol.ask_low) this.m_event_code+=SYMBOL_EVENT_FLAG_ASK_LOW; if(this.m_struct_curr_symbol.volume_real_day!=this.m_struct_prev_symbol.volume_real_day) this.m_event_code+=SYMBOL_EVENT_FLAG_VOLUME_REAL_DAY; if(this.m_struct_curr_symbol.volume_high_real_day!=this.m_struct_prev_symbol.volume_high_real_day) this.m_event_code+=SYMBOL_EVENT_FLAG_VOLUME_HIGH_REAL_DAY; if(this.m_struct_curr_symbol.volume_low_real_day!=this.m_struct_prev_symbol.volume_low_real_day) this.m_event_code+=SYMBOL_EVENT_FLAG_VOLUME_LOW_REAL_DAY; if(this.m_struct_curr_symbol.option_strike!=this.m_struct_prev_symbol.option_strike) this.m_event_code+=SYMBOL_EVENT_FLAG_OPTION_STRIKE; if(this.m_struct_curr_symbol.volume_limit!=this.m_struct_prev_symbol.volume_limit) this.m_event_code+=SYMBOL_EVENT_FLAG_VOLUME_LIMIT; if(this.m_struct_curr_symbol.swap_long!=this.m_struct_prev_symbol.swap_long) this.m_event_code+=SYMBOL_EVENT_FLAG_SWAP_LONG; if(this.m_struct_curr_symbol.swap_short!=this.m_struct_prev_symbol.swap_short) this.m_event_code+=SYMBOL_EVENT_FLAG_SWAP_SHORT; if(this.m_struct_curr_symbol.session_volume!=this.m_struct_prev_symbol.session_volume) this.m_event_code+=SYMBOL_EVENT_FLAG_SESSION_VOLUME; if(this.m_struct_curr_symbol.session_turnover!=this.m_struct_prev_symbol.session_turnover) this.m_event_code+=SYMBOL_EVENT_FLAG_SESSION_TURNOVER; if(this.m_struct_curr_symbol.session_interest!=this.m_struct_prev_symbol.session_interest) this.m_event_code+=SYMBOL_EVENT_FLAG_SESSION_INTEREST; if(this.m_struct_curr_symbol.session_buy_ord_volume!=this.m_struct_prev_symbol.session_buy_ord_volume) this.m_event_code+=SYMBOL_EVENT_FLAG_SESSION_BUY_ORD_VOLUME; if(this.m_struct_curr_symbol.session_sell_ord_volume!=this.m_struct_prev_symbol.session_sell_ord_volume) this.m_event_code+=SYMBOL_EVENT_FLAG_SESSION_SELL_ORD_VOLUME; if(this.m_struct_curr_symbol.session_open!=this.m_struct_prev_symbol.session_open) this.m_event_code+=SYMBOL_EVENT_FLAG_SESSION_OPEN; if(this.m_struct_curr_symbol.session_close!=this.m_struct_prev_symbol.session_close) this.m_event_code+=SYMBOL_EVENT_FLAG_SESSION_CLOSE; if(this.m_struct_curr_symbol.session_aw!=this.m_struct_prev_symbol.session_aw) this.m_event_code+=SYMBOL_EVENT_FLAG_SESSION_AW; //--- return this.m_event_code; } //+------------------------------------------------------------------+
まず、メソッドでイベントコードがリセットされます。次に、現在のデータの構造体と以前のデータの構造体で、制御対象の銘柄パラメータ値が比較されます。データが同じでなければ、イベントコードに適切なフラグが追加されます。
以下は、イベントタイプを設定し、発生したイベントをイベントリストに書き込むメソッドです。
//+------------------------------------------------------------------+ //| Set a symbol object event type | //+------------------------------------------------------------------+ void CSymbol::SetTypeEvent(void) { this.InitChangesParams(); ENUM_SYMBOL_EVENT event_id=SYMBOL_EVENT_NO_EVENT; //--- Change of trading modes on a symbol if(this.IsPresentEventFlag(SYMBOL_EVENT_FLAG_TRADE_MODE)) { event_id= ( this.TradeMode()==SYMBOL_TRADE_MODE_DISABLED ? SYMBOL_EVENT_TRADE_DISABLE : this.TradeMode()==SYMBOL_TRADE_MODE_LONGONLY ? SYMBOL_EVENT_TRADE_LONGONLY : this.TradeMode()==SYMBOL_TRADE_MODE_SHORTONLY ? SYMBOL_EVENT_TRADE_SHORTONLY : this.TradeMode()==SYMBOL_TRADE_MODE_CLOSEONLY ? SYMBOL_EVENT_TRADE_CLOSEONLY : SYMBOL_EVENT_TRADE_FULL ); this.m_is_change_trade_mode=true; if(this.EventAdd(event_id,this.TickTime(),this.TradeMode(),this.Name())) this.m_struct_prev_symbol.trade_mode=this.m_struct_curr_symbol.trade_mode; } //--- Change of the number of deals in the current session if(this.IsPresentEventFlag(SYMBOL_EVENT_FLAG_SESSION_DEALS)) { this.m_changed_session_deals_value=this.m_struct_curr_symbol.session_deals-this.m_struct_prev_symbol.session_deals; if(this.m_changed_session_deals_value>this.m_control_session_deals_inc) { this.m_is_change_session_deals_inc=true; event_id=SYMBOL_EVENT_SESSION_DEALS_INC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_session_deals_value,this.Name())) this.m_struct_prev_symbol.session_deals=this.m_struct_curr_symbol.session_deals; } else if(this.m_changed_session_deals_value<-this.m_control_session_deals_dec) { this.m_is_change_session_deals_dec=true; event_id=SYMBOL_EVENT_SESSION_DEALS_DEC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_session_deals_value,this.Name())) this.m_struct_prev_symbol.session_deals=this.m_struct_curr_symbol.session_deals; } } //--- Change of the total number of the current buy orders if(this.IsPresentEventFlag(SYMBOL_EVENT_FLAG_SESSION_BUY_ORDERS)) { this.m_changed_session_buy_ord_value=this.m_struct_curr_symbol.session_buy_orders-this.m_struct_prev_symbol.session_buy_orders; if(this.m_changed_session_buy_ord_value>this.m_control_session_buy_ord_inc) { this.m_is_change_session_buy_ord_inc=true; event_id=SYMBOL_EVENT_SESSION_BUY_ORDERS_INC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_session_buy_ord_value,this.Name())) this.m_struct_prev_symbol.session_buy_orders=this.m_struct_curr_symbol.session_buy_orders; } else if(this.m_changed_session_buy_ord_value<-this.m_control_session_buy_ord_dec) { this.m_is_change_session_buy_ord_dec=true; event_id=SYMBOL_EVENT_SESSION_BUY_ORDERS_DEC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_session_buy_ord_value,this.Name())) this.m_struct_prev_symbol.session_buy_orders=this.m_struct_curr_symbol.session_buy_orders; } } //--- Change of the total number of the current sell orders if(this.IsPresentEventFlag(SYMBOL_EVENT_FLAG_SESSION_SELL_ORDERS)) { this.m_changed_session_sell_ord_value=this.m_struct_curr_symbol.session_sell_orders-this.m_struct_prev_symbol.session_sell_orders; if(this.m_changed_session_sell_ord_value>this.m_control_session_sell_ord_inc) { this.m_is_change_session_sell_ord_inc=true; event_id=SYMBOL_EVENT_SESSION_SELL_ORDERS_INC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_session_sell_ord_value,this.Name())) this.m_struct_prev_symbol.session_sell_orders=this.m_struct_curr_symbol.session_sell_orders; } else if(this.m_changed_session_sell_ord_value<-this.m_control_session_sell_ord_dec) { this.m_is_change_session_sell_ord_dec=true; event_id=SYMBOL_EVENT_SESSION_SELL_ORDERS_DEC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_session_sell_ord_value,this.Name())) this.m_struct_prev_symbol.session_sell_orders=this.m_struct_curr_symbol.session_sell_orders; } } //--- Volume change in the last deal if(this.IsPresentEventFlag(SYMBOL_EVENT_FLAG_VOLUME)) { this.m_changed_volume_value=this.m_struct_curr_symbol.volume-this.m_struct_prev_symbol.volume; if(this.m_changed_volume_value>this.m_control_volume_inc) { this.m_is_change_volume_inc=true; event_id=SYMBOL_EVENT_VOLUME_INC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_volume_value,this.Name())) this.m_struct_prev_symbol.volume=this.m_struct_curr_symbol.volume; } else if(this.m_changed_volume_value<-this.m_control_volume_dec) { this.m_is_change_volume_dec=true; event_id=SYMBOL_EVENT_VOLUME_DEC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_volume_value,this.Name())) this.m_struct_prev_symbol.volume=this.m_struct_curr_symbol.volume; } } //--- Maximum volume change for a day if(this.IsPresentEventFlag(SYMBOL_EVENT_FLAG_VOLUME_HIGH_DAY)) { this.m_changed_volume_high_day_value=this.m_struct_curr_symbol.volume_high_day-this.m_struct_prev_symbol.volume_high_day; if(this.m_changed_volume_high_day_value>this.m_control_volume_high_day_inc) { this.m_is_change_volume_high_day_inc=true; event_id=SYMBOL_EVENT_VOLUME_HIGH_DAY_INC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_volume_high_day_value,this.Name())) this.m_struct_prev_symbol.volume_high_day=this.m_struct_curr_symbol.volume_high_day; } else if(this.m_changed_volume_high_day_value<-this.m_control_volume_high_day_dec) { this.m_is_change_volume_high_day_dec=true; event_id=SYMBOL_EVENT_VOLUME_HIGH_DAY_DEC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_volume_high_day_value,this.Name())) this.m_struct_prev_symbol.volume_high_day=this.m_struct_curr_symbol.volume_high_day; } } //--- Minimum volume change for a day if(this.IsPresentEventFlag(SYMBOL_EVENT_FLAG_VOLUME_LOW_DAY)) { this.m_changed_volume_low_day_value=this.m_struct_curr_symbol.volume_low_day-this.m_struct_prev_symbol.volume_low_day; if(this.m_changed_volume_low_day_value>this.m_control_volume_low_day_inc) { this.m_is_change_volume_low_day_inc=true; event_id=SYMBOL_EVENT_VOLUME_LOW_DAY_INC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_volume_low_day_value,this.Name())) this.m_struct_prev_symbol.volume_low_day=this.m_struct_curr_symbol.volume_low_day; } else if(this.m_changed_volume_low_day_value<-this.m_control_volume_low_day_dec) { this.m_is_change_volume_low_day_dec=true; event_id=SYMBOL_EVENT_VOLUME_LOW_DAY_DEC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_volume_low_day_value,this.Name())) this.m_struct_prev_symbol.volume_low_day=this.m_struct_curr_symbol.volume_low_day; } } //--- Spread value change in points if(this.IsPresentEventFlag(SYMBOL_EVENT_FLAG_SPREAD)) { this.m_changed_spread_value=this.m_struct_curr_symbol.spread-this.m_struct_prev_symbol.spread; if(this.m_changed_spread_value>this.m_control_spread_inc) { this.m_is_change_spread_inc=true; event_id=SYMBOL_EVENT_SPREAD_INC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_spread_value,this.Name())) this.m_struct_prev_symbol.spread=this.m_struct_curr_symbol.spread; } else if(this.m_changed_spread_value<-this.m_control_spread_dec) { this.m_is_change_spread_dec=true; event_id=SYMBOL_EVENT_SPREAD_DEC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_spread_value,this.Name())) this.m_struct_prev_symbol.spread=this.m_struct_curr_symbol.spread; } } //--- StopLevel change in points if(this.IsPresentEventFlag(SYMBOL_EVENT_FLAG_STOPLEVEL)) { this.m_changed_stops_level_value=this.m_struct_curr_symbol.stops_level-this.m_struct_prev_symbol.stops_level; if(this.m_changed_stops_level_value>this.m_control_stops_level_inc) { this.m_is_change_stops_level_inc=true; event_id=SYMBOL_EVENT_STOPLEVEL_INC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_stops_level_value,this.Name())) this.m_struct_prev_symbol.stops_level=this.m_struct_curr_symbol.stops_level; } else if(this.m_changed_stops_level_value<-this.m_control_stops_level_dec) { this.m_is_change_stops_level_dec=true; event_id=SYMBOL_EVENT_STOPLEVEL_DEC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_stops_level_value,this.Name())) this.m_struct_prev_symbol.stops_level=this.m_struct_curr_symbol.stops_level; } } //--- FreezeLevel change in points if(this.IsPresentEventFlag(SYMBOL_EVENT_FLAG_FREEZELEVEL)) { this.m_changed_freeze_level_value=this.m_struct_curr_symbol.freeze_level-this.m_struct_prev_symbol.freeze_level; if(this.m_changed_freeze_level_value>this.m_control_freeze_level_inc) { this.m_is_change_freeze_level_inc=true; event_id=SYMBOL_EVENT_FREEZELEVEL_INC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_freeze_level_value,this.Name())) this.m_struct_prev_symbol.freeze_level=this.m_struct_curr_symbol.freeze_level; } else if(this.m_changed_freeze_level_value<-this.m_control_freeze_level_dec) { this.m_is_change_freeze_level_dec=true; event_id=SYMBOL_EVENT_FREEZELEVEL_DEC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_freeze_level_value,this.Name())) this.m_struct_prev_symbol.freeze_level=this.m_struct_curr_symbol.freeze_level; } } //--- Bid/Last price change if(this.IsPresentEventFlag(SYMBOL_EVENT_FLAG_BID_LAST)) { this.m_changed_bid_last_value=this.m_struct_curr_symbol.bid_last-this.m_struct_prev_symbol.bid_last; if(this.m_changed_bid_last_value>this.m_control_bid_last_inc) { this.m_is_change_bid_last_inc=true; event_id=SYMBOL_EVENT_BID_LAST_INC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_bid_last_value,this.Name())) this.m_struct_prev_symbol.bid_last=this.m_struct_curr_symbol.bid_last; } else if(this.m_changed_bid_last_value<-this.m_control_bid_last_dec) { this.m_is_change_bid_last_dec=true; event_id=SYMBOL_EVENT_BID_LAST_DEC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_bid_last_value,this.Name())) this.m_struct_prev_symbol.bid_last=this.m_struct_curr_symbol.bid_last; } } //--- Maximum Bid/Last change for a day if(this.IsPresentEventFlag(SYMBOL_EVENT_FLAG_BID_LAST_HIGH)) { this.m_changed_bid_last_high_value=this.m_struct_curr_symbol.bid_last_high-this.m_struct_prev_symbol.bid_last_high; if(this.m_changed_bid_last_high_value>this.m_control_bid_last_high_inc) { this.m_is_change_bid_last_high_inc=true; event_id=SYMBOL_EVENT_BID_LAST_HIGH_INC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_bid_last_high_value,this.Name())) this.m_struct_prev_symbol.bid_last_high=this.m_struct_curr_symbol.bid_last_high; } else if(this.m_changed_bid_last_high_value<-this.m_control_bid_last_high_dec) { this.m_is_change_bid_last_high_dec=true; event_id=SYMBOL_EVENT_BID_LAST_HIGH_DEC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_bid_last_high_value,this.Name())) this.m_struct_prev_symbol.bid_last_high=this.m_struct_curr_symbol.bid_last_high; } } //--- Minimum Bid/Last change for a day if(this.IsPresentEventFlag(SYMBOL_EVENT_FLAG_BID_LAST_LOW)) { this.m_changed_bid_last_low_value=this.m_struct_curr_symbol.bid_last_low-this.m_struct_prev_symbol.bid_last_low; if(this.m_changed_bid_last_low_value>this.m_control_bid_last_low_inc) { this.m_is_change_bid_last_low_inc=true; event_id=SYMBOL_EVENT_BID_LAST_LOW_INC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_bid_last_low_value,this.Name())) this.m_struct_prev_symbol.bid_last_low=this.m_struct_curr_symbol.bid_last_low; } else if(this.m_changed_bid_last_low_value<-this.m_control_bid_last_low_dec) { this.m_is_change_bid_last_low_dec=true; event_id=SYMBOL_EVENT_BID_LAST_LOW_DEC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_bid_last_low_value,this.Name())) this.m_struct_prev_symbol.bid_last_low=this.m_struct_curr_symbol.bid_last_low; } } //--- Ask price change if(this.IsPresentEventFlag(SYMBOL_EVENT_FLAG_ASK)) { this.m_changed_ask_value=this.m_struct_curr_symbol.ask-this.m_struct_prev_symbol.ask; if(this.m_changed_ask_value>this.m_control_ask_inc) { this.m_is_change_ask_inc=true; event_id=SYMBOL_EVENT_ASK_INC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_ask_value,this.Name())) this.m_struct_prev_symbol.ask=this.m_struct_curr_symbol.ask; } else if(this.m_changed_ask_value<-this.m_control_ask_dec) { this.m_is_change_ask_dec=true; event_id=SYMBOL_EVENT_ASK_DEC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_ask_value,this.Name())) this.m_struct_prev_symbol.ask=this.m_struct_curr_symbol.ask; } } //--- Maximum As change for a day if(this.IsPresentEventFlag(SYMBOL_EVENT_FLAG_ASK_HIGH)) { this.m_changed_ask_high_value=this.m_struct_curr_symbol.ask_high-this.m_struct_prev_symbol.ask_high; if(this.m_changed_ask_high_value>this.m_control_ask_high_inc) { this.m_is_change_ask_high_inc=true; event_id=SYMBOL_EVENT_ASK_HIGH_INC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_ask_high_value,this.Name())) this.m_struct_prev_symbol.ask_high=this.m_struct_curr_symbol.ask_high; } else if(this.m_changed_ask_high_value<-this.m_control_ask_high_dec) { this.m_is_change_ask_high_dec=true; event_id=SYMBOL_EVENT_ASK_HIGH_DEC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_ask_high_value,this.Name())) this.m_struct_prev_symbol.ask_high=this.m_struct_curr_symbol.ask_high; } } //--- Minimum Ask change for a day if(this.IsPresentEventFlag(SYMBOL_EVENT_FLAG_ASK_LOW)) { this.m_changed_ask_low_value=this.m_struct_curr_symbol.ask_low-this.m_struct_prev_symbol.ask_low; if(this.m_changed_ask_low_value>this.m_control_ask_low_inc) { this.m_is_change_ask_low_inc=true; event_id=SYMBOL_EVENT_ASK_LOW_INC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_ask_low_value,this.Name())) this.m_struct_prev_symbol.ask_low=this.m_struct_curr_symbol.ask_low; } else if(this.m_changed_ask_low_value<-this.m_control_ask_low_dec) { this.m_is_change_ask_low_dec=true; event_id=SYMBOL_EVENT_ASK_LOW_DEC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_ask_low_value,this.Name())) this.m_struct_prev_symbol.ask_low=this.m_struct_curr_symbol.ask_low; } } //--- Real volume change for a day if(this.IsPresentEventFlag(SYMBOL_EVENT_FLAG_VOLUME_REAL_DAY)) { this.m_changed_volume_real_value=this.m_struct_curr_symbol.volume_real_day-this.m_struct_prev_symbol.volume_real_day; if(this.m_changed_volume_real_value>this.m_control_volume_real_inc) { this.m_is_change_volume_real_inc=true; event_id=SYMBOL_EVENT_VOLUME_REAL_DAY_INC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_volume_real_value,this.Name())) this.m_struct_prev_symbol.volume_real_day=this.m_struct_curr_symbol.volume_real_day; } else if(this.m_changed_volume_real_value<-this.m_control_volume_real_dec) { this.m_is_change_volume_real_dec=true; event_id=SYMBOL_EVENT_VOLUME_REAL_DAY_DEC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_volume_real_value,this.Name())) this.m_struct_prev_symbol.volume_real_day=this.m_struct_curr_symbol.volume_real_day; } } //--- Maximum real volume change for a day if(this.IsPresentEventFlag(SYMBOL_EVENT_FLAG_VOLUME_HIGH_REAL_DAY)) { this.m_changed_volume_high_real_day_value=this.m_struct_curr_symbol.volume_high_real_day-this.m_struct_prev_symbol.volume_high_real_day; if(this.m_changed_volume_high_real_day_value>this.m_control_volume_high_real_day_inc) { this.m_is_change_volume_high_real_day_inc=true; event_id=SYMBOL_EVENT_VOLUME_HIGH_REAL_DAY_INC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_volume_high_real_day_value,this.Name())) this.m_struct_prev_symbol.volume_high_real_day=this.m_struct_curr_symbol.volume_high_real_day; } else if(this.m_changed_volume_high_real_day_value<-this.m_control_volume_high_real_day_dec) { this.m_is_change_volume_high_real_day_dec=true; event_id=SYMBOL_EVENT_VOLUME_HIGH_REAL_DAY_DEC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_volume_high_real_day_value,this.Name())) this.m_struct_prev_symbol.volume_high_real_day=this.m_struct_curr_symbol.volume_high_real_day; } } //--- Minimum real volume change for a day if(this.IsPresentEventFlag(SYMBOL_EVENT_FLAG_VOLUME_LOW_REAL_DAY)) { this.m_changed_volume_low_real_day_value=this.m_struct_curr_symbol.volume_low_real_day-this.m_struct_prev_symbol.volume_low_real_day; if(this.m_changed_volume_low_real_day_value>this.m_control_volume_low_real_day_inc) { this.m_is_change_volume_low_real_day_inc=true; event_id=SYMBOL_EVENT_VOLUME_LOW_REAL_DAY_INC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_volume_low_real_day_value,this.Name())) this.m_struct_prev_symbol.volume_low_real_day=this.m_struct_curr_symbol.volume_low_real_day; } else if(this.m_changed_volume_low_real_day_value<-this.m_control_volume_low_real_day_dec) { this.m_is_change_volume_low_real_day_dec=true; event_id=SYMBOL_EVENT_VOLUME_LOW_REAL_DAY_DEC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_volume_low_real_day_value,this.Name())) this.m_struct_prev_symbol.volume_low_real_day=this.m_struct_curr_symbol.volume_low_real_day; } } //--- Strike price change if(this.IsPresentEventFlag(SYMBOL_EVENT_FLAG_OPTION_STRIKE)) { this.m_changed_option_strike_value=this.m_struct_curr_symbol.option_strike-this.m_struct_prev_symbol.option_strike; if(this.m_changed_option_strike_value>this.m_control_option_strike_inc) { this.m_is_change_option_strike_inc=true; event_id=SYMBOL_EVENT_OPTION_STRIKE_INC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_option_strike_value,this.Name())) this.m_struct_prev_symbol.option_strike=this.m_struct_curr_symbol.option_strike; } else if(this.m_changed_option_strike_value<-this.m_control_option_strike_dec) { this.m_is_change_option_strike_dec=true; event_id=SYMBOL_EVENT_OPTION_STRIKE_DEC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_option_strike_value,this.Name())) this.m_struct_prev_symbol.option_strike=this.m_struct_curr_symbol.option_strike; } } //--- Change of the maximum available total position volume and pending orders in one direction if(this.IsPresentEventFlag(SYMBOL_EVENT_FLAG_VOLUME_LIMIT)) { this.m_changed_volume_limit_value=this.m_struct_curr_symbol.volume_limit-this.m_struct_prev_symbol.volume_limit; if(this.m_changed_volume_limit_value>0) { this.m_is_change_volume_limit_inc=true; event_id=SYMBOL_EVENT_VOLUME_LIMIT_INC; } else { this.m_is_change_volume_limit_dec=true; event_id=SYMBOL_EVENT_VOLUME_LIMIT_DEC; } if(this.EventAdd(event_id,this.TickTime(),this.m_changed_volume_limit_value,this.Name())) this.m_struct_prev_symbol.volume_limit=this.m_struct_curr_symbol.volume_limit; } //--- Swap long change if(this.IsPresentEventFlag(SYMBOL_EVENT_FLAG_SWAP_LONG)) { this.m_changed_swap_long_value=this.m_struct_curr_symbol.swap_long-this.m_struct_prev_symbol.swap_long; if(this.m_changed_swap_long_value>0) { this.m_is_change_swap_long_inc=true; event_id=SYMBOL_EVENT_SWAP_LONG_INC; } else { this.m_is_change_swap_long_dec=true; event_id=SYMBOL_EVENT_SWAP_LONG_DEC; } if(this.EventAdd(event_id,this.TickTime(),this.m_changed_swap_long_value,this.Name())) this.m_struct_prev_symbol.swap_long=this.m_struct_curr_symbol.swap_long; } //--- Swap short change if(this.IsPresentEventFlag(SYMBOL_EVENT_FLAG_SWAP_SHORT)) { this.m_changed_swap_short_value=this.m_struct_curr_symbol.swap_short-this.m_struct_prev_symbol.swap_short; if(this.m_changed_swap_short_value>0) { this.m_is_change_swap_short_inc=true; event_id=SYMBOL_EVENT_SWAP_SHORT_INC; } else { this.m_is_change_swap_short_dec=true; event_id=SYMBOL_EVENT_SWAP_SHORT_DEC; } if(this.EventAdd(event_id,this.TickTime(),this.m_changed_swap_short_value,this.Name())) this.m_struct_prev_symbol.swap_short=this.m_struct_curr_symbol.swap_short; } //--- Change of the total volume of deals during the current session if(this.IsPresentEventFlag(SYMBOL_EVENT_FLAG_SESSION_VOLUME)) { this.m_changed_session_volume_value=this.m_struct_curr_symbol.session_volume-this.m_struct_prev_symbol.session_volume; if(this.m_changed_session_volume_value>this.m_control_session_volume_inc) { this.m_is_change_session_volume_inc=true; event_id=SYMBOL_EVENT_SESSION_VOLUME_INC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_session_volume_value,this.Name())) this.m_struct_prev_symbol.session_volume=this.m_struct_curr_symbol.session_volume; } else if(this.m_changed_session_volume_value<-this.m_control_session_volume_dec) { this.m_is_change_session_volume_dec=true; event_id=SYMBOL_EVENT_SESSION_VOLUME_DEC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_session_volume_value,this.Name())) this.m_struct_prev_symbol.session_volume=this.m_struct_curr_symbol.session_volume; } } //--- Change of the total turnover during the current session if(this.IsPresentEventFlag(SYMBOL_EVENT_FLAG_SESSION_TURNOVER)) { this.m_changed_session_turnover_value=this.m_struct_curr_symbol.session_turnover-this.m_struct_prev_symbol.session_turnover; if(this.m_changed_session_turnover_value>this.m_control_session_turnover_inc) { this.m_is_change_session_turnover_inc=true; event_id=SYMBOL_EVENT_SESSION_TURNOVER_INC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_session_turnover_value,this.Name())) this.m_struct_prev_symbol.session_turnover=this.m_struct_curr_symbol.session_turnover; } else if(this.m_changed_session_turnover_value<-this.m_control_session_turnover_dec) { this.m_is_change_session_turnover_dec=true; event_id=SYMBOL_EVENT_SESSION_TURNOVER_DEC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_session_turnover_value,this.Name())) this.m_struct_prev_symbol.session_turnover=this.m_struct_curr_symbol.session_turnover; } } //--- Change of the total volume of open positions during the current session if(this.IsPresentEventFlag(SYMBOL_EVENT_FLAG_SESSION_INTEREST)) { this.m_changed_session_interest_value=this.m_struct_curr_symbol.session_interest-this.m_struct_prev_symbol.session_interest; if(this.m_changed_session_interest_value>this.m_control_session_interest_inc) { this.m_is_change_session_interest_inc=true; event_id=SYMBOL_EVENT_SESSION_INTEREST_INC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_session_interest_value,this.Name())) this.m_struct_prev_symbol.session_interest=this.m_struct_curr_symbol.session_interest; } else if(this.m_changed_session_interest_value<-this.m_control_session_interest_dec) { this.m_is_change_session_interest_dec=true; event_id=SYMBOL_EVENT_SESSION_INTEREST_DEC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_session_interest_value,this.Name())) this.m_struct_prev_symbol.session_interest=this.m_struct_curr_symbol.session_interest; } } //--- Change of the current total volume of buy orders if(this.IsPresentEventFlag(SYMBOL_EVENT_FLAG_SESSION_BUY_ORD_VOLUME)) { this.m_changed_session_buy_ord_volume_value=this.m_struct_curr_symbol.session_buy_ord_volume-this.m_struct_prev_symbol.session_buy_ord_volume; if(this.m_changed_session_buy_ord_volume_value>this.m_control_session_buy_ord_volume_inc) { this.m_is_change_session_buy_ord_volume_inc=true; event_id=SYMBOL_EVENT_SESSION_BUY_ORD_VOLUME_INC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_session_buy_ord_volume_value,this.Name())) this.m_struct_prev_symbol.session_buy_ord_volume=this.m_struct_curr_symbol.session_buy_ord_volume; } else if(this.m_changed_session_buy_ord_volume_value<-this.m_control_session_buy_ord_volume_dec) { this.m_is_change_session_buy_ord_volume_dec=true; event_id=SYMBOL_EVENT_SESSION_BUY_ORD_VOLUME_DEC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_session_buy_ord_volume_value,this.Name())) this.m_struct_prev_symbol.session_buy_ord_volume=this.m_struct_curr_symbol.session_buy_ord_volume; } } //--- Change of the current total volume of sell orders if(this.IsPresentEventFlag(SYMBOL_EVENT_FLAG_SESSION_SELL_ORD_VOLUME)) { this.m_changed_session_sell_ord_volume_value=this.m_struct_curr_symbol.session_sell_ord_volume-this.m_struct_prev_symbol.session_sell_ord_volume; if(this.m_changed_session_sell_ord_volume_value>this.m_control_session_sell_ord_volume_inc) { this.m_is_change_session_sell_ord_volume_inc=true; event_id=SYMBOL_EVENT_SESSION_SELL_ORD_VOLUME_INC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_session_sell_ord_volume_value,this.Name())) this.m_struct_prev_symbol.session_sell_ord_volume=this.m_struct_curr_symbol.session_sell_ord_volume; } else if(this.m_changed_session_sell_ord_volume_value<-this.m_control_session_sell_ord_volume_dec) { this.m_is_change_session_sell_ord_volume_dec=true; event_id=SYMBOL_EVENT_SESSION_SELL_ORD_VOLUME_DEC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_session_sell_ord_volume_value,this.Name())) this.m_struct_prev_symbol.session_sell_ord_volume=this.m_struct_curr_symbol.session_sell_ord_volume; } } //--- Session open price change if(this.IsPresentEventFlag(SYMBOL_EVENT_FLAG_SESSION_OPEN)) { this.m_changed_session_open_value=this.m_struct_curr_symbol.session_open-this.m_struct_prev_symbol.session_open; if(this.m_changed_session_open_value>this.m_control_session_open_inc) { this.m_is_change_session_open_inc=true; event_id=SYMBOL_EVENT_SESSION_OPEN_INC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_session_open_value,this.Name())) this.m_struct_prev_symbol.session_open=this.m_struct_curr_symbol.session_open; } else if(this.m_changed_session_open_value<-this.m_control_session_open_dec) { this.m_is_change_session_open_dec=true; event_id=SYMBOL_EVENT_SESSION_OPEN_DEC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_session_open_value,this.Name())) this.m_struct_prev_symbol.session_open=this.m_struct_curr_symbol.session_open; } } //--- Session close price change if(this.IsPresentEventFlag(SYMBOL_EVENT_FLAG_SESSION_CLOSE)) { this.m_changed_session_close_value=this.m_struct_curr_symbol.session_close-this.m_struct_prev_symbol.session_close; if(this.m_changed_session_close_value>this.m_control_session_close_inc) { this.m_is_change_session_close_inc=true; event_id=SYMBOL_EVENT_SESSION_CLOSE_INC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_session_close_value,this.Name())) this.m_struct_prev_symbol.session_close=this.m_struct_curr_symbol.session_close; } else if(this.m_changed_session_close_value<-this.m_control_session_close_dec) { this.m_is_change_session_close_dec=true; event_id=SYMBOL_EVENT_SESSION_CLOSE_DEC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_session_close_value,this.Name())) this.m_struct_prev_symbol.session_close=this.m_struct_curr_symbol.session_close; } } //--- Average weighted session price change if(this.IsPresentEventFlag(SYMBOL_EVENT_FLAG_SESSION_AW)) { this.m_changed_session_aw_value=this.m_struct_curr_symbol.session_aw-this.m_struct_prev_symbol.session_aw; if(this.m_changed_session_aw_value>this.m_control_session_aw_inc) { this.m_is_change_session_aw_inc=true; event_id=SYMBOL_EVENT_SESSION_AW_INC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_session_aw_value,this.Name())) this.m_struct_prev_symbol.session_aw=this.m_struct_curr_symbol.session_aw; } else if(this.m_changed_session_aw_value<-this.m_control_session_aw_dec) { this.m_is_change_session_aw_dec=true; event_id=SYMBOL_EVENT_SESSION_AW_DEC; if(this.EventAdd(event_id,this.TickTime(),this.m_changed_session_aw_value,this.Name())) this.m_struct_prev_symbol.session_aw=this.m_struct_curr_symbol.session_aw; } } } //+------------------------------------------------------------------+
追跡対象の銘柄プロパティの変更を確認する同一ブロックのため、このメソッドは非常に「かさばり」ます。第13部では、口座の変更を追跡する際に同様のメソッドを既に検討しました。ここでは、イベントを保存する機能全体がCBaseObj基本オブジェクトにあることを除いて、ロジックは似ています。
平均加重セッション価格の変更を例に考えて考えてみましょう。
メソッドの一番最初で、InitChangesParams()メソッドを使用して追跡対象のプロパティの値をリセットし、イベントステータスを「イベントなし」に設定します。
- 同じく基本オブジェクトにあるIsPresentEventFlag()メソッドを使用して、SYMBOL_SESSION_AW銘柄値変更のフラグがm_event_code変数に設定されたイベントコードに存在するかどうかを確認します。
確認された値の変更のフラグがイベントコードに存在する場合、
- プロパティ値を計算し、値が制御値を超えているかどうかを確認します。
- 計算された値が制御値を超える場合、
- 加重平均価格イベントのフラグを設定し、
- 「平均加重値上げ」イベントIDに書き入れて
- CBaseObj基本クラスのEventAdd()リストにイベントを追加するメソッドを呼び出します。
イベントがリストに正常に追加された場合、
- さらに確認するために、現在のプロパティ値を以前の値として保存します。
EventAdd()リストにイベントを追加するメソッドにデータを送信します。
- event ID (event_idはイベントを確認する際に書き入れられます)
- ミリ秒単位の現在時刻(CBaseObj基本クラスのTickTime()メソッド)
- 銘柄プロパティが変更された計算値(m_changed_session_aw_value)
- オブジェクト名(ここでは銘柄値)
また、保護されたクラスコンストラクタを少し変更します。オブジェクト銘柄の新しいプロパティ「[気配値表示]ウィンドウでの銘柄インデックス」を埋めるために、[気配値表示]の銘柄をスキャンするときにはこのインデックスを渡す必要があります。インデックスは直接クラスコンストラクタに渡されます。
protected: //--- 保護されたパラメトリックコンストラクタ CSymbol(ENUM_SYMBOL_STATUS symbol_status,const string name,const int index);
クラスの同じprotectedセクションに、スワップチャージメソッドによって小数点以下の桁数を返すメソッドをもう1つ追加します。
//--- Get and return integer properties of a selected symbol from its parameters bool SymbolExists(const string name) const; long SymbolExists(void) const; long SymbolCustom(void) const; long SymbolChartMode(void) const; long SymbolMarginHedgedUseLEG(void) const; long SymbolOrderFillingMode(void) const; long SymbolOrderMode(void) const; long SymbolExpirationMode(void) const; long SymbolOrderGTCMode(void) const; long SymbolOptionMode(void) const; long SymbolOptionRight(void) const; long SymbolBackgroundColor(void) const; long SymbolCalcMode(void) const; long SymbolSwapMode(void) const; long SymbolDigitsLot(void); int SymbolDigitsBySwap(void); //--- Get and return real properties of a selected symbol from its parameters
スワップは、金銭、ポイント、割合で請求されるので、これらのスワップ料金タイプごとに、適切な小数点以下の桁数を返す必要があります。これはまさにこのメソッドが行うことです。クラス本体の外側で実装しましょう。
//+------------------------------------------------------------------+ //| Return the number of decimal places | //| depending on the swap calculation method | //+------------------------------------------------------------------+ int CSymbol::SymbolDigitsBySwap(void) { return ( this.SwapMode()==SYMBOL_SWAP_MODE_POINTS || this.SwapMode()==SYMBOL_SWAP_MODE_REOPEN_CURRENT || this.SwapMode()==SYMBOL_SWAP_MODE_REOPEN_BID ? this.Digits() : this.SwapMode()==SYMBOL_SWAP_MODE_CURRENCY_SYMBOL || this.SwapMode()==SYMBOL_SWAP_MODE_CURRENCY_MARGIN || this.SwapMode()==SYMBOL_SWAP_MODE_CURRENCY_DEPOSIT ? this.DigitsCurrency(): this.SwapMode()==SYMBOL_SWAP_MODE_INTEREST_CURRENT || this.SwapMode()==SYMBOL_SWAP_MODE_INTEREST_OPEN ? 1 : 0 ); } //+------------------------------------------------------------------+
Refresh()メソッドはすべてのCBaseObjobjectの基本クラスでも定義されているので、仮想にしましょう。また、相場データをリフレッシュするメソッドであるRefreshRates()の型をvoid から boolに変更します。RefreshRates()メソッドはRefresh()の冒頭で呼び出されます。データが取得されなかった場合、このメソッドはfalseを返すので、Refresh()メソッドの終了はすぐに実行されます。銘柄イベントの説明を返すメソッドの定義を追加します。
//--- Update all symbol data virtual void Refresh(void); //--- Update quote data by a symbol bool RefreshRates(void); //--- Return description of symbol events string EventDescription(const ENUM_SYMBOL_EVENT event);
クラスのpublicセクションの簡易アクセスメソッドのセクションの、銘柄整数プロパティを返すメソッドで、[気配値表示]ウィンドウで銘柄インデックスを返すメソッドを追加します。
//+------------------------------------------------------------------+ //| Methods of a simplified access to the order object properties | //+------------------------------------------------------------------+ //--- Integer properties long Status(void) const { return this.GetProperty(SYMBOL_PROP_STATUS); } int IndexInMarketWatch(void) const { return (int)this.GetProperty(SYMBOL_PROP_INDEX_MW); } bool IsCustom(void) const { return (bool)this.GetProperty(SYMBOL_PROP_CUSTOM); } color ColorBackground(void) const { return (color)this.GetProperty(SYMBOL_PROP_BACKGROUND_COLOR); } ENUM_SYMBOL_CHART_MODE ChartMode(void) const { return (ENUM_SYMBOL_CHART_MODE)this.GetProperty(SYMBOL_PROP_CHART_MODE); } bool IsExist(void) const { return (bool)this.GetProperty(SYMBOL_PROP_EXIST); } bool IsExist(const string name) const { return this.SymbolExists(name); } bool IsSelect(void) const { return (bool)this.GetProperty(SYMBOL_PROP_SELECT); } bool IsVisible(void) const { return (bool)this.GetProperty(SYMBOL_PROP_VISIBLE); } long SessionDeals(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_DEALS); } long SessionBuyOrders(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_BUY_ORDERS); } long SessionSellOrders(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_SELL_ORDERS); } long Volume(void) const { return this.GetProperty(SYMBOL_PROP_VOLUME); } long VolumeHigh(void) const { return this.GetProperty(SYMBOL_PROP_VOLUMEHIGH); } long VolumeLow(void) const { return this.GetProperty(SYMBOL_PROP_VOLUMELOW); } datetime Time(void) const { return (datetime)this.GetProperty(SYMBOL_PROP_TIME); } int Digits(void) const { return (int)this.GetProperty(SYMBOL_PROP_DIGITS); } int DigitsLot(void) const { return (int)this.GetProperty(SYMBOL_PROP_DIGITS_LOTS); } int Spread(void) const { return (int)this.GetProperty(SYMBOL_PROP_SPREAD); } bool IsSpreadFloat(void) const { return (bool)this.GetProperty(SYMBOL_PROP_SPREAD_FLOAT); } int TicksBookdepth(void) const { return (int)this.GetProperty(SYMBOL_PROP_TICKS_BOOKDEPTH); } ENUM_SYMBOL_CALC_MODE TradeCalcMode(void) const { return (ENUM_SYMBOL_CALC_MODE)this.GetProperty(SYMBOL_PROP_TRADE_CALC_MODE); } ENUM_SYMBOL_TRADE_MODE TradeMode(void) const { return (ENUM_SYMBOL_TRADE_MODE)this.GetProperty(SYMBOL_PROP_TRADE_MODE); } datetime StartTime(void) const { return (datetime)this.GetProperty(SYMBOL_PROP_START_TIME); } datetime ExpirationTime(void) const { return (datetime)this.GetProperty(SYMBOL_PROP_EXPIRATION_TIME); } int TradeStopLevel(void) const { return (int)this.GetProperty(SYMBOL_PROP_TRADE_STOPS_LEVEL); } int TradeFreezeLevel(void) const { return (int)this.GetProperty(SYMBOL_PROP_TRADE_FREEZE_LEVEL); } ENUM_SYMBOL_TRADE_EXECUTION TradeExecutionMode(void) const { return (ENUM_SYMBOL_TRADE_EXECUTION)this.GetProperty(SYMBOL_PROP_TRADE_EXEMODE); } ENUM_SYMBOL_SWAP_MODE SwapMode(void) const { return (ENUM_SYMBOL_SWAP_MODE)this.GetProperty(SYMBOL_PROP_SWAP_MODE); } ENUM_DAY_OF_WEEK SwapRollover3Days(void) const { return (ENUM_DAY_OF_WEEK)this.GetProperty(SYMBOL_PROP_SWAP_ROLLOVER3DAYS); } bool IsMarginHedgedUseLeg(void) const { return (bool)this.GetProperty(SYMBOL_PROP_MARGIN_HEDGED_USE_LEG); } int ExpirationModeFlags(void) const { return (int)this.GetProperty(SYMBOL_PROP_EXPIRATION_MODE); } int FillingModeFlags(void) const { return (int)this.GetProperty(SYMBOL_PROP_FILLING_MODE); } int OrderModeFlags(void) const { return (int)this.GetProperty(SYMBOL_PROP_ORDER_MODE); } ENUM_SYMBOL_ORDER_GTC_MODE OrderModeGTC(void) const { return (ENUM_SYMBOL_ORDER_GTC_MODE)this.GetProperty(SYMBOL_PROP_ORDER_GTC_MODE); } ENUM_SYMBOL_OPTION_MODE OptionMode(void) const { return (ENUM_SYMBOL_OPTION_MODE)this.GetProperty(SYMBOL_PROP_OPTION_MODE); } ENUM_SYMBOL_OPTION_RIGHT OptionRight(void) const { return (ENUM_SYMBOL_OPTION_RIGHT)this.GetProperty(SYMBOL_PROP_OPTION_RIGHT); } //--- Real properties
実数プロパティを返すメソッドでは、
Bid価格またはLast価格を返すメソッド、一日の最高のBid価格またはLast価格を返すメソッド、最低のBid価格またはLast価格を返すメソッドを追加します。
//--- Real properties double Bid(void) const { return this.GetProperty(SYMBOL_PROP_BID); } double BidHigh(void) const { return this.GetProperty(SYMBOL_PROP_BIDHIGH); } double BidLow(void) const { return this.GetProperty(SYMBOL_PROP_BIDLOW); } double Ask(void) const { return this.GetProperty(SYMBOL_PROP_ASK); } double AskHigh(void) const { return this.GetProperty(SYMBOL_PROP_ASKHIGH); } double AskLow(void) const { return this.GetProperty(SYMBOL_PROP_ASKLOW); } double Last(void) const { return this.GetProperty(SYMBOL_PROP_LAST); } double LastHigh(void) const { return this.GetProperty(SYMBOL_PROP_LASTHIGH); } double LastLow(void) const { return this.GetProperty(SYMBOL_PROP_LASTLOW); } double VolumeReal(void) const { return this.GetProperty(SYMBOL_PROP_VOLUME_REAL); } double VolumeHighReal(void) const { return this.GetProperty(SYMBOL_PROP_VOLUMEHIGH_REAL); } double VolumeLowReal(void) const { return this.GetProperty(SYMBOL_PROP_VOLUMELOW_REAL); } double OptionStrike(void) const { return this.GetProperty(SYMBOL_PROP_OPTION_STRIKE); } double Point(void) const { return this.GetProperty(SYMBOL_PROP_POINT); } double TradeTickValue(void) const { return this.GetProperty(SYMBOL_PROP_TRADE_TICK_VALUE); } double TradeTickValueProfit(void) const { return this.GetProperty(SYMBOL_PROP_TRADE_TICK_VALUE_PROFIT); } double TradeTickValueLoss(void) const { return this.GetProperty(SYMBOL_PROP_TRADE_TICK_VALUE_LOSS); } double TradeTickSize(void) const { return this.GetProperty(SYMBOL_PROP_TRADE_TICK_SIZE); } double TradeContractSize(void) const { return this.GetProperty(SYMBOL_PROP_TRADE_CONTRACT_SIZE); } double TradeAccuredInterest(void) const { return this.GetProperty(SYMBOL_PROP_TRADE_ACCRUED_INTEREST); } double TradeFaceValue(void) const { return this.GetProperty(SYMBOL_PROP_TRADE_FACE_VALUE); } double TradeLiquidityRate(void) const { return this.GetProperty(SYMBOL_PROP_TRADE_LIQUIDITY_RATE); } double LotsMin(void) const { return this.GetProperty(SYMBOL_PROP_VOLUME_MIN); } double LotsMax(void) const { return this.GetProperty(SYMBOL_PROP_VOLUME_MAX); } double LotsStep(void) const { return this.GetProperty(SYMBOL_PROP_VOLUME_STEP); } double VolumeLimit(void) const { return this.GetProperty(SYMBOL_PROP_VOLUME_LIMIT); } double SwapLong(void) const { return this.GetProperty(SYMBOL_PROP_SWAP_LONG); } double SwapShort(void) const { return this.GetProperty(SYMBOL_PROP_SWAP_SHORT); } double MarginInitial(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_INITIAL); } double MarginMaintenance(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_MAINTENANCE); } double MarginLongInitial(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_LONG_INITIAL); } double MarginBuyStopInitial(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_BUY_STOP_INITIAL); } double MarginBuyLimitInitial(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_BUY_LIMIT_INITIAL); } double MarginBuyStopLimitInitial(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_INITIAL); } double MarginLongMaintenance(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_LONG_MAINTENANCE); } double MarginBuyStopMaintenance(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_BUY_STOP_MAINTENANCE); } double MarginBuyLimitMaintenance(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_BUY_LIMIT_MAINTENANCE); } double MarginBuyStopLimitMaintenance(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_MAINTENANCE); } double MarginShortInitial(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_SHORT_INITIAL); } double MarginSellStopInitial(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_SELL_STOP_INITIAL); } double MarginSellLimitInitial(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_SELL_LIMIT_INITIAL); } double MarginSellStopLimitInitial(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_INITIAL); } double MarginShortMaintenance(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_SHORT_MAINTENANCE); } double MarginSellStopMaintenance(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_SELL_STOP_MAINTENANCE); } double MarginSellLimitMaintenance(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_SELL_LIMIT_MAINTENANCE); } double MarginSellStopLimitMaintenance(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_MAINTENANCE); } double SessionVolume(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_VOLUME); } double SessionTurnover(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_TURNOVER); } double SessionInterest(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_INTEREST); } double SessionBuyOrdersVolume(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_BUY_ORDERS_VOLUME); } double SessionSellOrdersVolume(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_SELL_ORDERS_VOLUME); } double SessionOpen(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_OPEN); } double SessionClose(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_CLOSE); } double SessionAW(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_AW); } double SessionPriceSettlement(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_PRICE_SETTLEMENT); } double SessionPriceLimitMin(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_PRICE_LIMIT_MIN); } double SessionPriceLimitMax(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_PRICE_LIMIT_MAX); } double MarginHedged(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_HEDGED); } double NormalizedPrice(const double price) const; double BidLast(void) const; double BidLastHigh(void) const; double BidLastLow(void) const; //--- String properties
クラス本体の外側で実装しましょう。
//+------------------------------------------------------------------+ //| Return Bid or Last price | //| depending on the chart construction method | //+------------------------------------------------------------------+ double CSymbol::BidLast(void) const { return(this.ChartMode()==SYMBOL_CHART_MODE_BID ? this.GetProperty(SYMBOL_PROP_BID) : this.GetProperty(SYMBOL_PROP_LAST)); } //+------------------------------------------------------------------+ //| Return maximum Bid or Last price for a day | //| depending on the chart construction method | //+------------------------------------------------------------------+ double CSymbol::BidLastHigh(void) const { return(this.ChartMode()==SYMBOL_CHART_MODE_BID ? this.GetProperty(SYMBOL_PROP_BIDHIGH) : this.GetProperty(SYMBOL_PROP_LASTHIGH)); } //+------------------------------------------------------------------+ //| Return minimum Bid or Last price for a day | //| depending on the chart construction method | //+------------------------------------------------------------------+ double CSymbol::BidLastLow(void) const { return(this.ChartMode()==SYMBOL_CHART_MODE_BID ? this.GetProperty(SYMBOL_PROP_BIDLOW) : this.GetProperty(SYMBOL_PROP_LASTLOW)); } //+------------------------------------------------------------------+
ここではすべてが簡単です。価格チャートの作成に使用された価格に応じて、適切な銘柄プロパティ(Bid価格またはLast価格付き)が返されます。
また、制御対象のプロパティを設定するメソッドとプロパティ変更値と銘柄のイベントフラグを返すメソッドをpublicセクションに書き込みます。
//+------------------------------------------------------------------+ //| Get and set the parameters of tracked changes | //+------------------------------------------------------------------+ //--- Execution //--- Flag of changing the trading mode for a symbol bool IsChangedTradeMode(void) const { return this.m_is_change_trade_mode; } //--- Current session deals //--- setting the controlled value of (1) growth, (2) decrease in the number of deals during the current session //--- getting (3) the number of deals change value during the current session, //--- getting the flag of the number of deals change during the current session exceeding the (4) growth, (5) decrease value void SetControlSessionDealsInc(const long value) { this.m_control_session_deals_inc=::fabs(value); } void SetControlSessionDealsDec(const long value) { this.m_control_session_deals_dec=::fabs(value); } long GetValueChangedSessionDeals(void) const { return this.m_changed_session_deals_value; } bool IsIncreaseSessionDeals(void) const { return this.m_is_change_session_deals_inc; } bool IsDecreaseSessionDeals(void) const { return this.m_is_change_session_deals_dec; } //--- Buy orders of the current session //--- setting the controlled value of (1) growth, (2) decrease in the current number of Buy orders //--- getting (3) the current number of Buy orders change value, //--- getting the flag of the current Buy orders' number change exceeding the (4) growth, (5) decrease value void SetControlSessionBuyOrdInc(const long value) { this.m_control_session_buy_ord_inc=::fabs(value); } void SetControlSessionBuyOrdDec(const long value) { this.m_control_session_buy_ord_dec=::fabs(value); } long GetValueChangedSessionBuyOrders(void) const { return this.m_changed_session_buy_ord_value; } bool IsIncreaseSessionBuyOrders(void) const { return this.m_is_change_session_buy_ord_inc; } bool IsDecreaseSessionBuyOrders(void) const { return this.m_is_change_session_buy_ord_dec; } //--- Sell orders of the current session //--- setting the controlled value of (1) growth, (2) decrease in the current number of Sell orders //--- getting (3) the current number of Sell orders change value, //--- getting the flag of the current Sell orders' number change exceeding the (4) growth, (5) decrease value void SetControlSessionSellOrdInc(const long value) { this.m_control_session_sell_ord_inc=::fabs(value); } void SetControlSessionSellOrdDec(const long value) { this.m_control_session_sell_ord_dec=::fabs(value); } long GetValueChangedSessionSellOrders(void) const { return this.m_changed_session_sell_ord_value; } bool IsIncreaseSessionSellOrders(void) const { return this.m_is_change_session_sell_ord_inc; } bool IsDecreaseSessionSellOrders(void) const { return this.m_is_change_session_sell_ord_dec; } //--- Volume of the last deal //--- setting the last deal volume controlled (1) growth, (2) decrease value //--- getting (3) volume change values in the last deal, //--- getting the flag of the volume change in the last deal exceeding the (4) growth, (5) decrease value void SetControlVolumeInc(const long value) { this.m_control_volume_inc=::fabs(value); } void SetControlVolumeDec(const long value) { this.m_control_volume_dec=::fabs(value); } long GetValueChangedVolume(void) const { return this.m_changed_volume_value; } bool IsIncreaseVolume(void) const { return this.m_is_change_volume_inc; } bool IsDecreaseVolume(void) const { return this.m_is_change_volume_dec; } //--- Maximum volume within a day //--- setting the maximum day volume controlled (1) growth, (2) decrease value //--- getting (3) the maximum volume change value within a day, //--- getting the flag of the maximum day volume change exceeding the (4) growth, (5) decrease value void SetControlVolumeHighInc(const long value) { this.m_control_volume_high_day_inc=::fabs(value); } void SetControlVolumeHighDec(const long value) { this.m_control_volume_high_day_dec=::fabs(value); } long GetValueChangedVolumeHigh(void) const { return this.m_changed_volume_high_day_value; } bool IsIncreaseVolumeHigh(void) const { return this.m_is_change_volume_high_day_inc; } bool IsDecreaseVolumeHigh(void) const { return this.m_is_change_volume_high_day_dec; } //--- Minimum volume within a day //--- setting the minimum day volume controlled (1) growth, (2) decrease value //--- getting (3) the minimum volume change value within a day, //--- getting the flag of the minimum day volume change exceeding the (4) growth, (5) decrease value void SetControlVolumeLowInc(const long value) { this.m_control_volume_low_day_inc=::fabs(value); } void SetControlVolumeLowDec(const long value) { this.m_control_volume_low_day_dec=::fabs(value); } long GetValueChangedVolumeLow(void) const { return this.m_changed_volume_low_day_value; } bool IsIncreaseVolumeLow(void) const { return this.m_is_change_volume_low_day_inc; } bool IsDecreaseVolumeLow(void) const { return this.m_is_change_volume_low_day_dec; } //--- Spread //--- setting the controlled spread decrease (1) growth, (2) decrease value in points //--- getting (3) spread change value in points, //--- getting the flag of the spread change in points exceeding the (4) growth, (5) decrease value void SetControlSpreadInc(const int value) { this.m_control_spread_inc=::fabs(value); } void SetControlSpreadDec(const int value) { this.m_control_spread_dec=::fabs(value); } int GetValueChangedSpread(void) const { return this.m_changed_spread_value; } bool IsIncreaseSpread(void) const { return this.m_is_change_spread_inc; } bool IsDecreaseSpread(void) const { return this.m_is_change_spread_dec; } //--- StopLevel //--- setting the controlled StopLevel decrease (1) growth, (2) decrease value in points //--- getting (3) StopLevel change value in points, //--- getting the flag of StopLevel change in points exceeding the (4) growth, (5) decrease value void SetControlStopLevelInc(const int value) { this.m_control_stops_level_inc=::fabs(value); } void SetControlStopLevelDec(const int value) { this.m_control_stops_level_dec=::fabs(value); } int GetValueChangedStopLevel(void) const { return this.m_changed_stops_level_value; } bool IsIncreaseStopLevel(void) const { return this.m_is_change_stops_level_inc; } bool IsDecreaseStopLevel(void) const { return this.m_is_change_stops_level_dec; } //--- Freeze distance //--- setting the controlled FreezeLevel decrease (1) growth, (2) decrease value in points //--- getting (3) FreezeLevel change value in points, //--- getting the flag of FreezeLevel change in points exceeding the (4) growth, (5) decrease value void SetControlFreezeLevelInc(const int value) { this.m_control_freeze_level_inc=::fabs(value); } void SetControlFreezeLevelDec(const int value) { this.m_control_freeze_level_dec=::fabs(value); } int GetValueChangedFreezeLevel(void) const { return this.m_changed_freeze_level_value; } bool IsIncreaseFreezeLevel(void) const { return this.m_is_change_freeze_level_inc; } bool IsDecreaseFreezeLevel(void) const { return this.m_is_change_freeze_level_dec; } //--- Bid/Last //--- setting the Bid or Last price controlled (1) growth, (2) decrease value //--- getting (3) Bid or Last price change value, //--- getting the flag of the Bid or Last price change exceeding the (4) growth, (5) decrease value void SetControlBidLastInc(const double value) { this.m_control_bid_last_inc=::fabs(value); } void SetControlBidLastDec(const double value) { this.m_control_bid_last_dec=::fabs(value); } double GetValueChangedBidLast(void) const { return this.m_changed_bid_last_value; } bool IsIncreaseBidLast(void) const { return this.m_is_change_bid_last_inc; } bool IsDecreaseBidLast(void) const { return this.m_is_change_bid_last_dec; } //--- Maximum Bid/Last of the day //--- setting the maximum Bid or Last price controlled (1) growth, (2) decrease value //--- getting the (3) maximum Bid or Last price change value, //--- getting the flag of the maximum Bid or Last price change exceeding the (4) growth, (5) decrease value void SetControlBidLastHighInc(const double value) { this.m_control_bid_last_high_inc=::fabs(value); } void SetControlBidLastHighDec(const double value) { this.m_control_bid_last_high_dec=::fabs(value); } double GetValueChangedBidLastHigh(void) const { return this.m_changed_bid_last_high_value; } bool IsIncreaseBidLastHigh(void) const { return this.m_is_change_bid_last_high_inc; } bool IsDecreaseBidLastHigh(void) const { return this.m_is_change_bid_last_high_dec; } //--- Minimum Bid/Last of the day //--- setting the minimum Bid or Last price controlled (1) growth, (2) decrease value //--- getting the (3) minimum Bid or Last price change value, //--- getting the flag of the minimum Bid or Last price change exceeding the (4) growth, (5) decrease value void SetControlBidLastLowInc(const double value) { this.m_control_bid_last_low_inc=::fabs(value); } void SetControlBidLastLowDec(const double value) { this.m_control_bid_last_low_dec=::fabs(value); } double GetValueChangedBidLastLow(void) const { return this.m_changed_bid_last_low_value; } bool IsIncreaseBidLastLow(void) const { return this.m_is_change_bid_last_low_inc; } bool IsDecreaseBidLastLow(void) const { return this.m_is_change_bid_last_low_dec; } //--- Ask //--- setting the Ask price controlled (1) growth, (2) decrease value //--- getting (3) Ask price change value, //--- getting the flag of the Ask price change exceeding the (4) growth, (5) decrease value void SetControlAskInc(const double value) { this.m_control_ask_inc=::fabs(value); } void SetControlAskDec(const double value) { this.m_control_ask_dec=::fabs(value); } double GetValueChangedAsk(void) const { return this.m_changed_ask_value; } bool IsIncreaseAsk(void) const { return this.m_is_change_ask_inc; } bool IsDecreaseAsk(void) const { return this.m_is_change_ask_dec; } //--- Maximum Ask price for the day //--- setting the maximum day Ask controlled (1) growth, (2) decrease value //--- getting (3) the maximum Ask change value within a day, //--- getting the flag of the maximum day Ask change exceeding the (4) growth, (5) decrease value void SetControlAskHighInc(const double value) { this.m_control_ask_high_inc=::fabs(value); } void SetControlAskHighDec(const double value) { this.m_control_ask_high_dec=::fabs(value); } double GetValueChangedAskHigh(void) const { return this.m_changed_ask_high_value; } bool IsIncreaseAskHigh(void) const { return this.m_is_change_ask_high_inc; } bool IsDecreaseAskHigh(void) const { return this.m_is_change_ask_high_dec; } //--- Minimum Ask price for the day //--- setting the minimum day Ask controlled (1) growth, (2) decrease value //--- getting (3) the minimum Ask change value within a day, //--- getting the flag of the minimum day Ask change exceeding the (4) growth, (5) decrease value void SetControlAskLowInc(const double value) { this.m_control_ask_low_inc=::fabs(value); } void SetControlAskLowDec(const double value) { this.m_control_ask_low_dec=::fabs(value); } double GetValueChangedAskLow(void) const { return this.m_changed_ask_low_value; } bool IsIncreaseAskLow(void) const { return this.m_is_change_ask_low_inc; } bool IsDecreaseAskLow(void) const { return this.m_is_change_ask_low_dec; } //--- Real Volume for the day //--- setting the real day volume controlled (1) growth, (2) decrease value //--- getting (3) the change value of the real day volume, //--- getting the flag of the real day volume change exceeding the (4) growth, (5) decrease value void SetControlVolumeRealInc(const double value) { this.m_control_volume_real_inc=::fabs(value); } void SetControlVolumeRealDec(const double value) { this.m_control_volume_real_dec=::fabs(value); } double GetValueChangedVolumeReal(void) const { return this.m_changed_volume_real_value; } bool IsIncreaseVolumeReal(void) const { return this.m_is_change_volume_real_inc; } bool IsDecreaseVolumeReal(void) const { return this.m_is_change_volume_real_dec; } //--- Maximum real volume for the day //--- setting the maximum real day volume controlled (1) growth, (2) decrease value //--- getting (3) the change value of the maximum real day volume, //--- getting the flag of the maximum real day volume change exceeding the (4) growth, (5) decrease value void SetControlVolumeHighRealInc(const double value) { this.m_control_volume_high_real_day_inc=::fabs(value); } void SetControlVolumeHighRealDec(const double value) { this.m_control_volume_high_real_day_dec=::fabs(value); } double GetValueChangedVolumeHighReal(void) const { return this.m_changed_volume_high_real_day_value; } bool IsIncreaseVolumeHighReal(void) const { return this.m_is_change_volume_high_real_day_inc; } bool IsDecreaseVolumeHighReal(void) const { return this.m_is_change_volume_high_real_day_dec; } //--- Minimum real volume for the day //--- setting the minimum real day volume controlled (1) growth, (2) decrease value //--- getting (3) the change value of the minimum real day volume, //--- getting the flag of the minimum real day volume change exceeding the (4) growth, (5) decrease value void SetControlVolumeLowRealInc(const double value) { this.m_control_volume_low_real_day_inc=::fabs(value); } void SetControlVolumeLowRealDec(const double value) { this.m_control_volume_low_real_day_dec=::fabs(value); } double GetValueChangedVolumeLowReal(void) const { return this.m_changed_volume_low_real_day_value; } bool IsIncreaseVolumeLowReal(void) const { return this.m_is_change_volume_low_real_day_inc; } bool IsDecreaseVolumeLowReal(void) const { return this.m_is_change_volume_low_real_day_dec; } //--- Strike price //--- setting the strike price controlled (1) growth, (2) decrease value //--- getting (3) the change value of the strike price, //--- getting the flag of the strike price change exceeding the (4) growth, (5) decrease value void SetControlOptionStrikeInc(const double value) { this.m_control_option_strike_inc=::fabs(value); } void SetControlOptionStrikeDec(const double value) { this.m_control_option_strike_dec=::fabs(value); } double GetValueChangedOptionStrike(void) const { return this.m_changed_option_strike_value; } bool IsIncreaseOptionStrike(void) const { return this.m_is_change_option_strike_inc; } bool IsDecreaseOptionStrike(void) const { return this.m_is_change_option_strike_dec; } //--- Maximum allowed total volume of unidirectional positions and orders //--- (1) getting the change value of the maximum allowed total volume of unidirectional positions and orders, //--- getting the flag of (2) increasing, (3) decreasing the maximum allowed total volume of unidirectional positions and orders double GetValueChangedVolumeLimit(void) const { return this.m_changed_volume_limit_value; } bool IsIncreaseVolumeLimit(void) const { return this.m_is_change_volume_limit_inc; } bool IsDecreaseVolumeLimit(void) const { return this.m_is_change_volume_limit_dec; } //--- Swap long //--- (1) getting the swap long change value, //--- getting the flag of (2) increasing, (3) decreasing the swap long double GetValueChangedSwapLong(void) const { return this.m_changed_swap_long_value; } bool IsIncreaseSwapLong(void) const { return this.m_is_change_swap_long_inc; } bool IsDecreaseSwapLong(void) const { return this.m_is_change_swap_long_dec; } //--- Swap short //--- (1) getting the swap short change value, //--- getting the flag of (2) increasing, (3) decreasing the swap short double GetValueChangedSwapShort(void) const { return this.m_changed_swap_short_value; } bool IsIncreaseSwapShort(void) const { return this.m_is_change_swap_short_inc; } bool IsDecreaseSwapShort(void) const { return this.m_is_change_swap_short_dec; } //--- The total volume of deals in the current session //--- setting the controlled value of (1) growth, (2) decrease in the total volume of deals during the current session //--- getting (3) the total deal volume change value in the current session, //--- getting the flag of the total deal volume change during the current session exceeding the (4) growth, (5) decrease value void SetControlSessionVolumeInc(const double value) { this.m_control_session_volume_inc=::fabs(value); } void SetControlSessionVolumeDec(const double value) { this.m_control_session_volume_dec=::fabs(value); } double GetValueChangedSessionVolume(void) const { return this.m_changed_session_volume_value; } bool IsIncreaseSessionVolume(void) const { return this.m_is_change_session_volume_inc; } bool IsDecreaseSessionVolume(void) const { return this.m_is_change_session_volume_dec; } //--- The total turnover in the current session //--- setting the controlled value of the turnover (1) growth, (2) decrease during the current session //--- getting (3) the total turnover change value in the current session, //--- getting the flag of the total turnover change during the current session exceeding the (4) growth, (5) decrease value void SetControlSessionTurnoverInc(const double value) { this.m_control_session_turnover_inc=::fabs(value); } void SetControlSessionTurnoverDec(const double value) { this.m_control_session_turnover_dec=::fabs(value); } double GetValueChangedSessionTurnover(void) const { return this.m_changed_session_turnover_value; } bool IsIncreaseSessionTurnover(void) const { return this.m_is_change_session_turnover_inc; } bool IsDecreaseSessionTurnover(void) const { return this.m_is_change_session_turnover_dec; } //--- The total volume of open positions //--- setting the controlled value of (1) growth, (2) decrease in the total volume of open positions during the current session //--- getting (3) the change value of the open positions total volume in the current session, //--- getting the flag of the open positions total volume change during the current session exceeding the (4) growth, (5) decrease value void SetControlSessionInterestInc(const double value) { this.m_control_session_interest_inc=::fabs(value); } void SetControlSessionInterestDec(const double value) { this.m_control_session_interest_dec=::fabs(value); } double GetValueChangedSessionInterest(void) const { return this.m_changed_session_interest_value; } bool IsIncreaseSessionInterest(void) const { return this.m_is_change_session_interest_inc; } bool IsDecreaseSessionInterest(void) const { return this.m_is_change_session_interest_dec; } //--- The total volume of Buy orders at the moment //--- setting the controlled value of (1) growth, (2) decrease in the current total buy order volume //--- getting (3) the change value of the current total buy order volume, //--- getting the flag of the current total buy orders' volume change exceeding the (4) growth, (5) decrease value void SetControlSessionBuyOrdVolumeInc(const double value) { this.m_control_session_buy_ord_volume_inc=::fabs(value); } void SetControlSessionBuyOrdVolumeDec(const double value) { this.m_control_session_buy_ord_volume_dec=::fabs(value); } double GetValueChangedSessionBuyOrdVolume(void) const { return this.m_changed_session_buy_ord_volume_value; } bool IsIncreaseSessionBuyOrdVolume(void) const { return this.m_is_change_session_buy_ord_volume_inc; } bool IsDecreaseSessionBuyOrdVolume(void) const { return this.m_is_change_session_buy_ord_volume_dec; } //--- The total volume of Sell orders at the moment //--- setting the controlled value of (1) growth, (2) decrease in the current total sell order volume //--- getting (3) the change value of the current total sell order volume, //--- getting the flag of the current total sell orders' volume change exceeding the (4) growth, (5) decrease value void SetControlSessionSellOrdVolumeInc(const double value) { this.m_control_session_sell_ord_volume_inc=::fabs(value); } void SetControlSessionSellOrdVolumeDec(const double value) { this.m_control_session_sell_ord_volume_dec=::fabs(value); } double GetValueChangedSessionSellOrdVolume(void) const { return this.m_changed_session_sell_ord_volume_value; } bool IsIncreaseSessionSellOrdVolume(void) const { return this.m_is_change_session_sell_ord_volume_inc; } bool IsDecreaseSessionSellOrdVolume(void) const { return this.m_is_change_session_sell_ord_volume_dec; } //--- Session open price //--- setting the session open price controlled (1) growth, (2) decrease value //--- getting (3) the change value of the session open price, //--- getting the flag of the session open price change exceeding the (4) growth, (5) decrease value void SetControlSessionPriceOpenInc(const double value) { this.m_control_session_open_inc=::fabs(value); } void SetControlSessionPriceOpenDec(const double value) { this.m_control_session_open_dec=::fabs(value); } double GetValueChangedSessionPriceOpen(void) const { return this.m_changed_session_open_value; } bool IsIncreaseSessionPriceOpen(void) const { return this.m_is_change_session_open_inc; } bool IsDecreaseSessionPriceOpen(void) const { return this.m_is_change_session_open_dec; } //--- Session close price //--- setting the session close price controlled (1) growth, (2) decrease value //--- getting (3) the change value of the session close price, //--- getting the flag of the session close price change exceeding the (4) growth, (5) decrease value void SetControlSessionPriceCloseInc(const double value) { this.m_control_session_close_inc=::fabs(value); } void SetControlSessionPriceCloseDec(const double value) { this.m_control_session_close_dec=::fabs(value); } double GetValueChangedSessionPriceClose(void) const { return this.m_changed_session_close_value; } bool IsIncreaseSessionPriceClose(void) const { return this.m_is_change_session_close_inc; } bool IsDecreaseSessionPriceClose(void) const { return this.m_is_change_session_close_dec; } //--- The average weighted session price //--- setting the average weighted session price controlled (1) growth, (2) decrease value //--- getting (3) the change value of the average weighted session price, //--- getting the flag of the average weighted session price change exceeding the (4) growth, (5) decrease value void SetControlSessionPriceAWInc(const double value) { this.m_control_session_aw_inc=::fabs(value); } void SetControlSessionPriceAWDec(const double value) { this.m_control_session_aw_dec=::fabs(value); } double GetValueChangedSessionPriceAW(void) const { return this.m_changed_session_aw_value; } bool IsIncreaseSessionPriceAW(void) const { return this.m_is_change_session_aw_inc; } bool IsDecreaseSessionPriceAW(void) const { return this.m_is_change_session_aw_dec; } //---
ここでは、制御対象のプロパティの変更値を設定するためのメソッドが、制御プロパティごとに提供されています。値を超えると、イベントが形成されます。イベントフラグは、イベントフラグを返すメソッドを使用して受信できますが、変更値は適切なメソッドを使用して取得することもできます。第13部で口座イベントの追跡を実装するときに、同様のメソッドについて説明しました。
クラスコンストラクタにいくつかの変更が加えられました。
//+------------------------------------------------------------------+ //| Closedパラメトリックコンストラクタ | //+------------------------------------------------------------------+ CSymbol::CSymbol(ENUM_SYMBOL_STATUS symbol_status,const string name,const int index) { this.m_name=name; if(!this.Exist()) { ::Print(DFUN_ERR_LINE,"\"",this.m_name,"\"",": ",TextByLanguage("Ошибка. Такого символа нет на сервере","Error. There is no such symbol on the server")); this.m_global_error=ERR_MARKET_UNKNOWN_SYMBOL; } bool select=::SymbolInfoInteger(this.m_name,SYMBOL_SELECT); ::ResetLastError(); if(!select) { if(!this.SetToMarketWatch()) { this.m_global_error=::GetLastError(); ::Print(DFUN_ERR_LINE,"\"",this.m_name,"\": ",TextByLanguage("Не удалось поместить в обзор рынка. Ошибка: ","Failed to put in the market watch. Error: "),this.m_global_error); } } ::ResetLastError(); if(!::SymbolInfoTick(this.m_name,this.m_tick)) { this.m_global_error=::GetLastError(); ::Print(DFUN_ERR_LINE,"\"",this.m_name,"\": ",TextByLanguage("Не удалось получить текущие цены. Ошибка: ","Could not get current prices. Error: "),this.m_global_error); } //--- Initialize data this.Reset(); this.InitMarginRates(); ::ZeroMemory(this.m_struct_prev_symbol); this.m_struct_prev_symbol.trade_mode=WRONG_VALUE; this.InitChangesParams(); this.InitControlsParams(); #ifdef __MQL5__ ::ResetLastError(); if(!this.MarginRates()) { this.m_global_error=::GetLastError(); ::Print(DFUN_ERR_LINE,this.Name(),": ",TextByLanguage("Не удалось получить коэффициенты взимания маржи. Ошибка: ","Failed to get margin rates. Error: "),this.m_global_error); return; } #endif //--- 整数型プロパティを保存する this.m_long_prop[SYMBOL_PROP_STATUS] = symbol_status; this.m_long_prop[SYMBOL_PROP_INDEX_MW] = index; this.m_long_prop[SYMBOL_PROP_VOLUME] = (long)this.m_tick.volume; this.m_long_prop[SYMBOL_PROP_SELECT] = ::SymbolInfoInteger(this.m_name,SYMBOL_SELECT); this.m_long_prop[SYMBOL_PROP_VISIBLE] = ::SymbolInfoInteger(this.m_name,SYMBOL_VISIBLE); this.m_long_prop[SYMBOL_PROP_SESSION_DEALS] = ::SymbolInfoInteger(this.m_name,SYMBOL_SESSION_DEALS); this.m_long_prop[SYMBOL_PROP_SESSION_BUY_ORDERS] = ::SymbolInfoInteger(this.m_name,SYMBOL_SESSION_BUY_ORDERS); this.m_long_prop[SYMBOL_PROP_SESSION_SELL_ORDERS] = ::SymbolInfoInteger(this.m_name,SYMBOL_SESSION_SELL_ORDERS); this.m_long_prop[SYMBOL_PROP_VOLUMEHIGH] = ::SymbolInfoInteger(this.m_name,SYMBOL_VOLUMEHIGH); this.m_long_prop[SYMBOL_PROP_VOLUMELOW] = ::SymbolInfoInteger(this.m_name,SYMBOL_VOLUMELOW); this.m_long_prop[SYMBOL_PROP_DIGITS] = ::SymbolInfoInteger(this.m_name,SYMBOL_DIGITS); this.m_long_prop[SYMBOL_PROP_SPREAD] = ::SymbolInfoInteger(this.m_name,SYMBOL_SPREAD); this.m_long_prop[SYMBOL_PROP_SPREAD_FLOAT] = ::SymbolInfoInteger(this.m_name,SYMBOL_SPREAD_FLOAT); this.m_long_prop[SYMBOL_PROP_TICKS_BOOKDEPTH] = ::SymbolInfoInteger(this.m_name,SYMBOL_TICKS_BOOKDEPTH); this.m_long_prop[SYMBOL_PROP_TRADE_MODE] = ::SymbolInfoInteger(this.m_name,SYMBOL_TRADE_MODE); this.m_long_prop[SYMBOL_PROP_START_TIME] = ::SymbolInfoInteger(this.m_name,SYMBOL_START_TIME); this.m_long_prop[SYMBOL_PROP_EXPIRATION_TIME] = ::SymbolInfoInteger(this.m_name,SYMBOL_EXPIRATION_TIME); this.m_long_prop[SYMBOL_PROP_TRADE_STOPS_LEVEL] = ::SymbolInfoInteger(this.m_name,SYMBOL_TRADE_STOPS_LEVEL); this.m_long_prop[SYMBOL_PROP_TRADE_FREEZE_LEVEL] = ::SymbolInfoInteger(this.m_name,SYMBOL_TRADE_FREEZE_LEVEL); this.m_long_prop[SYMBOL_PROP_TRADE_EXEMODE] = ::SymbolInfoInteger(this.m_name,SYMBOL_TRADE_EXEMODE); this.m_long_prop[SYMBOL_PROP_SWAP_ROLLOVER3DAYS] = ::SymbolInfoInteger(this.m_name,SYMBOL_SWAP_ROLLOVER3DAYS); this.m_long_prop[SYMBOL_PROP_TIME] = this.TickTime(); this.m_long_prop[SYMBOL_PROP_EXIST] = this.SymbolExists(); this.m_long_prop[SYMBOL_PROP_CUSTOM] = this.SymbolCustom(); this.m_long_prop[SYMBOL_PROP_MARGIN_HEDGED_USE_LEG] = this.SymbolMarginHedgedUseLEG(); this.m_long_prop[SYMBOL_PROP_ORDER_MODE] = this.SymbolOrderMode(); this.m_long_prop[SYMBOL_PROP_FILLING_MODE] = this.SymbolOrderFillingMode(); this.m_long_prop[SYMBOL_PROP_EXPIRATION_MODE] = this.SymbolExpirationMode(); this.m_long_prop[SYMBOL_PROP_ORDER_GTC_MODE] = this.SymbolOrderGTCMode(); this.m_long_prop[SYMBOL_PROP_OPTION_MODE] = this.SymbolOptionMode(); this.m_long_prop[SYMBOL_PROP_OPTION_RIGHT] = this.SymbolOptionRight(); this.m_long_prop[SYMBOL_PROP_BACKGROUND_COLOR] = this.SymbolBackgroundColor(); this.m_long_prop[SYMBOL_PROP_CHART_MODE] = this.SymbolChartMode(); this.m_long_prop[SYMBOL_PROP_TRADE_CALC_MODE] = this.SymbolCalcMode(); this.m_long_prop[SYMBOL_PROP_SWAP_MODE] = this.SymbolSwapMode(); //--- 実数型プロパティを保存する this.m_double_prop[this.IndexProp(SYMBOL_PROP_ASKHIGH)] = ::SymbolInfoDouble(this.m_name,SYMBOL_ASKHIGH); this.m_double_prop[this.IndexProp(SYMBOL_PROP_ASKLOW)] = ::SymbolInfoDouble(this.m_name,SYMBOL_ASKLOW); this.m_double_prop[this.IndexProp(SYMBOL_PROP_LASTHIGH)] = ::SymbolInfoDouble(this.m_name,SYMBOL_LASTHIGH); this.m_double_prop[this.IndexProp(SYMBOL_PROP_LASTLOW)] = ::SymbolInfoDouble(this.m_name,SYMBOL_LASTLOW); this.m_double_prop[this.IndexProp(SYMBOL_PROP_POINT)] = ::SymbolInfoDouble(this.m_name,SYMBOL_POINT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE)] = ::SymbolInfoDouble(this.m_name,SYMBOL_TRADE_TICK_VALUE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE_PROFIT)] = ::SymbolInfoDouble(this.m_name,SYMBOL_TRADE_TICK_VALUE_PROFIT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE_LOSS)] = ::SymbolInfoDouble(this.m_name,SYMBOL_TRADE_TICK_VALUE_LOSS); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_SIZE)] = ::SymbolInfoDouble(this.m_name,SYMBOL_TRADE_TICK_SIZE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_CONTRACT_SIZE)] = ::SymbolInfoDouble(this.m_name,SYMBOL_TRADE_CONTRACT_SIZE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_MIN)] = ::SymbolInfoDouble(this.m_name,SYMBOL_VOLUME_MIN); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_MAX)] = ::SymbolInfoDouble(this.m_name,SYMBOL_VOLUME_MAX); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_STEP)] = ::SymbolInfoDouble(this.m_name,SYMBOL_VOLUME_STEP); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_LIMIT)] = ::SymbolInfoDouble(this.m_name,SYMBOL_VOLUME_LIMIT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SWAP_LONG)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SWAP_LONG); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SWAP_SHORT)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SWAP_SHORT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_INITIAL)] = ::SymbolInfoDouble(this.m_name,SYMBOL_MARGIN_INITIAL); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_MAINTENANCE)] = ::SymbolInfoDouble(this.m_name,SYMBOL_MARGIN_MAINTENANCE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_VOLUME)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_VOLUME); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_TURNOVER)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_TURNOVER); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_INTEREST)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_INTEREST); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_BUY_ORDERS_VOLUME)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_BUY_ORDERS_VOLUME); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_SELL_ORDERS_VOLUME)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_SELL_ORDERS_VOLUME); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_OPEN)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_OPEN); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_CLOSE)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_CLOSE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_AW)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_AW); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_PRICE_SETTLEMENT)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_PRICE_SETTLEMENT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_PRICE_LIMIT_MIN)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_PRICE_LIMIT_MIN); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_PRICE_LIMIT_MAX)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_PRICE_LIMIT_MAX); this.m_double_prop[this.IndexProp(SYMBOL_PROP_BID)] = this.m_tick.bid; this.m_double_prop[this.IndexProp(SYMBOL_PROP_ASK)] = this.m_tick.ask; this.m_double_prop[this.IndexProp(SYMBOL_PROP_LAST)] = this.m_tick.last; this.m_double_prop[this.IndexProp(SYMBOL_PROP_BIDHIGH)] = this.SymbolBidHigh(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_BIDLOW)] = this.SymbolBidLow(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_REAL)] = this.SymbolVolumeReal(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUMEHIGH_REAL)] = this.SymbolVolumeHighReal(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUMELOW_REAL)] = this.SymbolVolumeLowReal(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_OPTION_STRIKE)] = this.SymbolOptionStrike(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_ACCRUED_INTEREST)] = this.SymbolTradeAccruedInterest(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_FACE_VALUE)] = this.SymbolTradeFaceValue(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_LIQUIDITY_RATE)] = this.SymbolTradeLiquidityRate(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_HEDGED)] = this.SymbolMarginHedged(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_LONG_INITIAL)] = this.m_margin_rate.Long.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOP_INITIAL)] = this.m_margin_rate.BuyStop.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_LIMIT_INITIAL)] = this.m_margin_rate.BuyLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_INITIAL)] = this.m_margin_rate.BuyStopLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_LONG_MAINTENANCE)] = this.m_margin_rate.Long.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOP_MAINTENANCE)] = this.m_margin_rate.BuyStop.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_LIMIT_MAINTENANCE)] = this.m_margin_rate.BuyLimit.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_MAINTENANCE)] = this.m_margin_rate.BuyStopLimit.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SHORT_INITIAL)] = this.m_margin_rate.Short.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOP_INITIAL)] = this.m_margin_rate.SellStop.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_LIMIT_INITIAL)] = this.m_margin_rate.SellLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_INITIAL)] = this.m_margin_rate.SellStopLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SHORT_MAINTENANCE)] = this.m_margin_rate.Short.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOP_MAINTENANCE)] = this.m_margin_rate.SellStop.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_LIMIT_MAINTENANCE)] = this.m_margin_rate.SellLimit.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_MAINTENANCE)]= this.m_margin_rate.SellStopLimit.Maintenance; //--- 文字列プロパティを保存する this.m_string_prop[this.IndexProp(SYMBOL_PROP_NAME)] = this.m_name; this.m_string_prop[this.IndexProp(SYMBOL_PROP_CURRENCY_BASE)] = ::SymbolInfoString(this.m_name,SYMBOL_CURRENCY_BASE); this.m_string_prop[this.IndexProp(SYMBOL_PROP_CURRENCY_PROFIT)] = ::SymbolInfoString(this.m_name,SYMBOL_CURRENCY_PROFIT); this.m_string_prop[this.IndexProp(SYMBOL_PROP_CURRENCY_MARGIN)] = ::SymbolInfoString(this.m_name,SYMBOL_CURRENCY_MARGIN); this.m_string_prop[this.IndexProp(SYMBOL_PROP_DESCRIPTION)] = ::SymbolInfoString(this.m_name,SYMBOL_DESCRIPTION); this.m_string_prop[this.IndexProp(SYMBOL_PROP_PATH)] = ::SymbolInfoString(this.m_name,SYMBOL_PATH); this.m_string_prop[this.IndexProp(SYMBOL_PROP_BASIS)] = this.SymbolBasis(); this.m_string_prop[this.IndexProp(SYMBOL_PROP_BANK)] = this.SymbolBank(); this.m_string_prop[this.IndexProp(SYMBOL_PROP_ISIN)] = this.SymbolISIN(); this.m_string_prop[this.IndexProp(SYMBOL_PROP_FORMULA)] = this.SymbolFormula(); this.m_string_prop[this.IndexProp(SYMBOL_PROP_PAGE)] = this.SymbolPage(); //--- 追加の整数型プロパティを保存する this.m_long_prop[SYMBOL_PROP_DIGITS_LOTS] = this.SymbolDigitsLot(); //--- if(!select) this.RemoveFromMarketWatch(); } //+------------------------------------------------------------------+
これで、コンストラクタは[気配値表示]銘柄インデックスを受け取り、銘柄名がオブジェクト名に割り当てられ、以前の銘柄データの構造体がリセットされます。前のデータ構造体フィールドtrade_modeにはWRONG_VALUE があります(銘柄取引モードフィールドにこの値があると、 最初の起動を定義します)。変更されたおよび制御対象の銘柄プロパティの変数が初期化されますす。コンストラクタに渡されたインデックスが「[気配値表示]ウィンドウインデックス」銘柄プロパティに書き入れられます。
CBaseObj基本クラスにm_name変数があり、オブジェクト名(この場合は銘柄名)を格納するため、CSymbolクラスにはm_symbol_name変数が含まれなくなりました。その出現はすべてm_name(クラスコンストラクタで銘柄名が割り当てられている)に置き換える必要があります。
this.m_symbol_nameテキストのいずれかの出現をCSymbolクラスで強調表示してCtrl+Hを押します。強調表示が検索フィールドに挿入された状態で、検索と置換ウィンドウが表示されます。置換フィールドに this.m_nameを入力し、検出されたすべてのthis.m_symbol_nameの出現をリスト内のthis.m_nameに置き換えます。また、CBaseObj基本オブジェクトに配置された残りのクラスメンバ変数も削除する必要があります。CSymbolに存在すると、コンパイル中に変数の重複の警告がトリガされます。以下に添付されているファイルでは、このような変数はすべて削除されています。ファイルをダウンロードして、その内容を見てください。
整数プロパティの説明を返すメソッドに、新しい「[気配値表示]ウィンドウインデックスの説明銘柄プロパティの説明を追加します。
//+------------------------------------------------------------------+ //| Return the description of the symbol integer property | //+------------------------------------------------------------------+ string CSymbol::GetPropertyDescription(ENUM_SYMBOL_PROP_INTEGER property) { return ( property==SYMBOL_PROP_STATUS ? TextByLanguage("Статус","Status")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+(string)this.GetProperty(property) ) : property==SYMBOL_PROP_INDEX_MW ? TextByLanguage("Индекс в окне \"Обзор рынка\"","Index in the \"Market Watch window\"")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+this.GetStatusDescription() ) : property==SYMBOL_PROP_CUSTOM ? TextByLanguage("Пользовательский символ","Custom symbol")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+(this.GetProperty(property) ? TextByLanguage("Да","Yes") : TextByLanguage("Нет","No")) ) : property==SYMBOL_PROP_CHART_MODE ? TextByLanguage("Тип цены для построения баров","Price type used for generating symbols bars")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+this.GetChartModeDescription() ) : property==SYMBOL_PROP_EXIST ? TextByLanguage("Символ с таким именем существует","Symbol with this name exists")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+(this.GetProperty(property) ? TextByLanguage("Да","Yes") : TextByLanguage("Нет","No")) ) : property==SYMBOL_PROP_SELECT ? TextByLanguage("Символ выбран в Market Watch","Symbol selected in Market Watch")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+(this.GetProperty(property) ? TextByLanguage("Да","Yes") : TextByLanguage("Нет","No")) ) : property==SYMBOL_PROP_VISIBLE ? TextByLanguage("Символ отображается в Market Watch","Symbol visible in Market Watch")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+(this.GetProperty(property) ? TextByLanguage("Да","Yes") : TextByLanguage("Нет","No")) ) : property==SYMBOL_PROP_SESSION_DEALS ? TextByLanguage("Количество сделок в текущей сессии","Number of deals in the current session")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__(string)this.GetProperty(property) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_SESSION_BUY_ORDERS ? TextByLanguage("Общее число ордеров на покупку в текущий момент","Number of Buy orders at the moment")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__(string)this.GetProperty(property) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_SESSION_SELL_ORDERS ? TextByLanguage("Общее число ордеров на продажу в текущий момент","Number of Sell orders at the moment")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__(string)this.GetProperty(property) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_VOLUME ? TextByLanguage("Объем в последней сделке","Volume of the last deal")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__(string)this.GetProperty(property) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_VOLUMEHIGH ? TextByLanguage("Максимальный объём за день","Maximal day volume")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__(string)this.GetProperty(property) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_VOLUMELOW ? TextByLanguage("Минимальный объём за день","Minimal day volume")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__(string)this.GetProperty(property) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_TIME ? TextByLanguage("Время последней котировки","Time of the last quote")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+(this.GetProperty(property)==0 ? TextByLanguage("(Ещё не было тиков)","(No ticks yet)") : TimeMSCtoString(this.GetProperty(property))) ) : property==SYMBOL_PROP_DIGITS ? TextByLanguage("Количество знаков после запятой","Digits after decimal point")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+(string)this.GetProperty(property) ) : property==SYMBOL_PROP_DIGITS_LOTS ? TextByLanguage("Количество знаков после запятой в значении лота","Digits after decimal point in the value of the lot")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+(string)this.GetProperty(property) ) : property==SYMBOL_PROP_SPREAD ? TextByLanguage("Размер спреда в пунктах","Spread value in points")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+(string)this.GetProperty(property) ) : property==SYMBOL_PROP_SPREAD_FLOAT ? TextByLanguage("Плавающий спред","Spread is floating")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+(this.GetProperty(property) ? TextByLanguage("Да","Yes") : TextByLanguage("Нет","No")) ) : property==SYMBOL_PROP_TICKS_BOOKDEPTH ? TextByLanguage("Максимальное количество показываемых заявок в стакане","Maximal number of requests shown in Depth of Market")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__(string)this.GetProperty(property) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_TRADE_CALC_MODE ? TextByLanguage("Способ вычисления стоимости контракта","Contract price calculation mode")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+this.GetCalcModeDescription() ) : property==SYMBOL_PROP_TRADE_MODE ? TextByLanguage("Тип исполнения ордеров","Order execution type")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+this.GetTradeModeDescription() ) : property==SYMBOL_PROP_START_TIME ? TextByLanguage("Дата начала торгов по инструменту","Date of symbol trade beginning")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : (this.GetProperty(property)==0 ? TextByLanguage(": (Отсутствует)",": (Not set)") : ": "+TimeMSCtoString(this.GetProperty(property)*1000)) ) : property==SYMBOL_PROP_EXPIRATION_TIME ? TextByLanguage("Дата окончания торгов по инструменту","Date of symbol trade end")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : (this.GetProperty(property)==0 ? TextByLanguage(": (Отсутствует)",": (Not set)") : ": "+TimeMSCtoString(this.GetProperty(property)*1000)) ) : property==SYMBOL_PROP_TRADE_STOPS_LEVEL ? TextByLanguage("Минимальный отступ от цены закрытия для установки Stop ордеров","Minimal indention from close price to place Stop orders")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+(string)this.GetProperty(property) ) : property==SYMBOL_PROP_TRADE_FREEZE_LEVEL ? TextByLanguage("Дистанция заморозки торговых операций","Distance to freeze trade operations in points")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+(string)this.GetProperty(property) ) : property==SYMBOL_PROP_TRADE_EXEMODE ? TextByLanguage("Режим заключения сделок","Deal execution mode")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+this.GetTradeExecDescription() ) : property==SYMBOL_PROP_SWAP_MODE ? TextByLanguage("Модель расчета свопа","Swap calculation model")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+this.GetSwapModeDescription() ) : property==SYMBOL_PROP_SWAP_ROLLOVER3DAYS ? TextByLanguage("День недели для начисления тройного свопа","Day of week to charge 3 days swap rollover")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+DayOfWeekDescription(this.SwapRollover3Days()) ) : property==SYMBOL_PROP_MARGIN_HEDGED_USE_LEG ? TextByLanguage("Расчет хеджированной маржи по наибольшей стороне","Calculating hedging margin using the larger leg")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+(this.GetProperty(property) ? TextByLanguage("Да","Yes") : TextByLanguage("Нет","No")) ) : property==SYMBOL_PROP_EXPIRATION_MODE ? TextByLanguage("Флаги разрешенных режимов истечения ордера","Flags of allowed order expiration modes")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+this.GetExpirationModeFlagsDescription() ) : property==SYMBOL_PROP_FILLING_MODE ? TextByLanguage("Флаги разрешенных режимов заливки ордера","Flags of allowed order filling modes")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+this.GetFillingModeFlagsDescription() ) : property==SYMBOL_PROP_ORDER_MODE ? TextByLanguage("Флаги разрешённых типов ордеров","Flags of allowed order types")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+this.GetOrderModeFlagsDescription() ) : property==SYMBOL_PROP_ORDER_GTC_MODE ? TextByLanguage("Срок действия StopLoss и TakeProfit ордеров","Expiration of Stop Loss and Take Profit orders")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+this.GetOrderGTCModeDescription() ) : property==SYMBOL_PROP_OPTION_MODE ? TextByLanguage("Тип опциона","Option type")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+this.GetOptionTypeDescription() ) : property==SYMBOL_PROP_OPTION_RIGHT ? TextByLanguage("Право опциона","Option right")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+this.GetOptionRightDescription() ) : property==SYMBOL_PROP_BACKGROUND_COLOR ? TextByLanguage("Цвет фона символа в Market Watch","Background color of symbol in Market Watch")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : #ifdef __MQL5__ (this.GetProperty(property)==CLR_DEFAULT || this.GetProperty(property)==CLR_NONE ? TextByLanguage(": (Отсутствует)",": (Not set)") : ": "+::ColorToString((color)this.GetProperty(property),true)) #else TextByLanguage(": Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : "" ); } //+------------------------------------------------------------------+
Exist()メソッドの2番目の形式と、CSymbolクラスメソッドの実装リストから数値の小数点以下の桁数を返すメソッドを削除します。
//+------------------------------------------------------------------+
bool CSymbol::Exist(const string name) const
{
int total=::SymbolsTotal(false);
for(int i=0;i<total;i++)
if(::SymbolName(i,false)==name)
return true;
return false;
}
//+------------------------------------------------------------------+
//| Return the number of decimal places in the 'double' value |
//+------------------------------------------------------------------+
int CSymbol::GetDigits(const double value) const
{
string val_str=(string)value;
int len=::StringLen(val_str);
int n=len-::StringFind(val_str,".",0)-1;
if(::StringSubstr(val_str,len-1,1)=="0")
n--;
return n;
}
//+------------------------------------------------------------------+
これらのメソッドはここでは単純に冗長です。このクラスでは、入力のあるExist()は必要ありません。よって、これを適切であるサービス関数のDELib.mqhファイルに移動しました。一方GetDigits()はCBaseObj基本クラスに移動されました。
CSymbolクラスのRefresh()メソッドはタイマーから起動され、すべての銘柄データを更新します。同じメソッドで銘柄プロパティの変更を検索します。もう1つのメソッドであるRefreshRates()もタイマーから起動されますが、リフレッシュレートが高くなります。このメソッドでは、銘柄相場データのみが更新されます。両方のメソッドで銘柄プロパティの変更の検索を実装すると、イベントメッセージの重複が発生します。
考えられる解決策は次のとおりです。RefreshRates()メソッドは相場データを更新し、正常に受信したことを示すフラグを返します。メソッドは以前と同様にタイマーから呼び出されますが、 Refresh() メソッドから呼び出す機能も追加されます。したがって、両方のメソッドは以前と同様に呼び出されます。それぞれのタイマーで、銘柄プロパティの変更の検索はRefresh()メソッドでのみ実行されます。
必要な変更をRefreshRates()およびRefresh()メソッドに追加しましょう。
//+------------------------------------------------------------------+ //| Update quote data by a symbol | //+------------------------------------------------------------------+ bool CSymbol::RefreshRates(void) { //--- Get quote data ::ResetLastError(); if(!::SymbolInfoTick(this.m_name,this.m_tick)) { this.m_global_error=::GetLastError(); return false; } //--- Update integer properties this.m_long_prop[SYMBOL_PROP_VOLUME] = (long)this.m_tick.volume; this.m_long_prop[SYMBOL_PROP_TIME] = this.TickTime(); //--- Update real properties this.m_double_prop[this.IndexProp(SYMBOL_PROP_ASK)] = this.m_tick.ask; this.m_double_prop[this.IndexProp(SYMBOL_PROP_ASKHIGH)] = ::SymbolInfoDouble(this.m_name,SYMBOL_ASKHIGH); this.m_double_prop[this.IndexProp(SYMBOL_PROP_ASKLOW)] = ::SymbolInfoDouble(this.m_name,SYMBOL_ASKLOW); this.m_double_prop[this.IndexProp(SYMBOL_PROP_BID)] = this.m_tick.bid; this.m_double_prop[this.IndexProp(SYMBOL_PROP_BIDHIGH)] = this.SymbolBidHigh(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_BIDLOW)] = this.SymbolBidLow(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_LAST)] = this.m_tick.last; this.m_double_prop[this.IndexProp(SYMBOL_PROP_LASTHIGH)] = ::SymbolInfoDouble(this.m_name,SYMBOL_LASTHIGH); this.m_double_prop[this.IndexProp(SYMBOL_PROP_LASTLOW)] = ::SymbolInfoDouble(this.m_name,SYMBOL_LASTLOW); return true; } //+------------------------------------------------------------------+
まず、銘柄の相場データを取得します。取得に失敗した場合は、エラーコードを記述し、falseを返すメソッドを終了します。データが取得されている場合、f必要な銘柄プロパティに書き入れ、 trueを返します。
//+------------------------------------------------------------------+ //| Update all symbol data | //+------------------------------------------------------------------+ void CSymbol::Refresh(void) { //--- Update quote data if(!this.RefreshRates()) return; #ifdef __MQL5__ ::ResetLastError(); if(!this.MarginRates()) { this.m_global_error=::GetLastError(); return; } #endif //--- Prepare event data this.m_is_event=false; ::ZeroMemory(this.m_struct_curr_symbol); this.m_hash_sum=0; //--- Update integer properties this.m_long_prop[SYMBOL_PROP_SELECT] = ::SymbolInfoInteger(this.m_name,SYMBOL_SELECT); this.m_long_prop[SYMBOL_PROP_VISIBLE] = ::SymbolInfoInteger(this.m_name,SYMBOL_VISIBLE); this.m_long_prop[SYMBOL_PROP_SESSION_DEALS] = ::SymbolInfoInteger(this.m_name,SYMBOL_SESSION_DEALS); this.m_long_prop[SYMBOL_PROP_SESSION_BUY_ORDERS] = ::SymbolInfoInteger(this.m_name,SYMBOL_SESSION_BUY_ORDERS); this.m_long_prop[SYMBOL_PROP_SESSION_SELL_ORDERS] = ::SymbolInfoInteger(this.m_name,SYMBOL_SESSION_SELL_ORDERS); this.m_long_prop[SYMBOL_PROP_VOLUMEHIGH] = ::SymbolInfoInteger(this.m_name,SYMBOL_VOLUMEHIGH); this.m_long_prop[SYMBOL_PROP_VOLUMELOW] = ::SymbolInfoInteger(this.m_name,SYMBOL_VOLUMELOW); this.m_long_prop[SYMBOL_PROP_SPREAD] = ::SymbolInfoInteger(this.m_name,SYMBOL_SPREAD); this.m_long_prop[SYMBOL_PROP_TICKS_BOOKDEPTH] = ::SymbolInfoInteger(this.m_name,SYMBOL_TICKS_BOOKDEPTH); this.m_long_prop[SYMBOL_PROP_START_TIME] = ::SymbolInfoInteger(this.m_name,SYMBOL_START_TIME); this.m_long_prop[SYMBOL_PROP_EXPIRATION_TIME] = ::SymbolInfoInteger(this.m_name,SYMBOL_EXPIRATION_TIME); this.m_long_prop[SYMBOL_PROP_TRADE_STOPS_LEVEL] = ::SymbolInfoInteger(this.m_name,SYMBOL_TRADE_STOPS_LEVEL); this.m_long_prop[SYMBOL_PROP_TRADE_FREEZE_LEVEL] = ::SymbolInfoInteger(this.m_name,SYMBOL_TRADE_FREEZE_LEVEL); this.m_long_prop[SYMBOL_PROP_BACKGROUND_COLOR] = this.SymbolBackgroundColor(); //--- Update real properties this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE)] = ::SymbolInfoDouble(this.m_name,SYMBOL_TRADE_TICK_VALUE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE_PROFIT)] = ::SymbolInfoDouble(this.m_name,SYMBOL_TRADE_TICK_VALUE_PROFIT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE_LOSS)] = ::SymbolInfoDouble(this.m_name,SYMBOL_TRADE_TICK_VALUE_LOSS); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_SIZE)] = ::SymbolInfoDouble(this.m_name,SYMBOL_TRADE_TICK_SIZE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_CONTRACT_SIZE)] = ::SymbolInfoDouble(this.m_name,SYMBOL_TRADE_CONTRACT_SIZE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_MIN)] = ::SymbolInfoDouble(this.m_name,SYMBOL_VOLUME_MIN); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_MAX)] = ::SymbolInfoDouble(this.m_name,SYMBOL_VOLUME_MAX); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_STEP)] = ::SymbolInfoDouble(this.m_name,SYMBOL_VOLUME_STEP); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_LIMIT)] = ::SymbolInfoDouble(this.m_name,SYMBOL_VOLUME_LIMIT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SWAP_LONG)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SWAP_LONG); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SWAP_SHORT)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SWAP_SHORT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_INITIAL)] = ::SymbolInfoDouble(this.m_name,SYMBOL_MARGIN_INITIAL); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_MAINTENANCE)] = ::SymbolInfoDouble(this.m_name,SYMBOL_MARGIN_MAINTENANCE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_VOLUME)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_VOLUME); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_TURNOVER)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_TURNOVER); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_INTEREST)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_INTEREST); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_BUY_ORDERS_VOLUME)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_BUY_ORDERS_VOLUME); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_SELL_ORDERS_VOLUME)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_SELL_ORDERS_VOLUME); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_OPEN)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_OPEN); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_CLOSE)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_CLOSE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_AW)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_AW); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_PRICE_SETTLEMENT)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_PRICE_SETTLEMENT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_PRICE_LIMIT_MIN)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_PRICE_LIMIT_MIN); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_PRICE_LIMIT_MAX)] = ::SymbolInfoDouble(this.m_name,SYMBOL_SESSION_PRICE_LIMIT_MAX); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_REAL)] = this.SymbolVolumeReal(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUMEHIGH_REAL)] = this.SymbolVolumeHighReal(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUMELOW_REAL)] = this.SymbolVolumeLowReal(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_OPTION_STRIKE)] = this.SymbolOptionStrike(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_ACCRUED_INTEREST)] = this.SymbolTradeAccruedInterest(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_FACE_VALUE)] = this.SymbolTradeFaceValue(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_LIQUIDITY_RATE)] = this.SymbolTradeLiquidityRate(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_HEDGED)] = this.SymbolMarginHedged(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_LONG_INITIAL)] = this.m_margin_rate.Long.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOP_INITIAL)] = this.m_margin_rate.BuyStop.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_LIMIT_INITIAL)] = this.m_margin_rate.BuyLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_INITIAL)] = this.m_margin_rate.BuyStopLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_LONG_MAINTENANCE)] = this.m_margin_rate.Long.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOP_MAINTENANCE)] = this.m_margin_rate.BuyStop.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_LIMIT_MAINTENANCE)] = this.m_margin_rate.BuyLimit.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_MAINTENANCE)] = this.m_margin_rate.BuyStopLimit.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SHORT_INITIAL)] = this.m_margin_rate.Short.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOP_INITIAL)] = this.m_margin_rate.SellStop.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_LIMIT_INITIAL)] = this.m_margin_rate.SellLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_INITIAL)] = this.m_margin_rate.SellStopLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SHORT_MAINTENANCE)] = this.m_margin_rate.Short.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOP_MAINTENANCE)] = this.m_margin_rate.SellStop.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_LIMIT_MAINTENANCE)] = this.m_margin_rate.SellLimit.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_MAINTENANCE)]= this.m_margin_rate.SellStopLimit.Maintenance; //--- Fill in the current symbol data structure this.m_struct_curr_symbol.ask = this.Ask(); this.m_struct_curr_symbol.ask_high = this.AskHigh(); this.m_struct_curr_symbol.ask_low = this.AskLow(); this.m_struct_curr_symbol.bid_last = (this.ChartMode()==SYMBOL_CHART_MODE_BID ? this.Bid() : this.Last()); this.m_struct_curr_symbol.bid_last_high = (this.ChartMode()==SYMBOL_CHART_MODE_BID ? this.BidHigh() : this.LastHigh()); this.m_struct_curr_symbol.bid_last_low = (this.ChartMode()==SYMBOL_CHART_MODE_BID ? this.BidLow() : this.LastLow()); this.m_struct_curr_symbol.volume = this.Volume(); this.m_struct_curr_symbol.session_deals = this.SessionDeals(); this.m_struct_curr_symbol.session_buy_orders = this.SessionBuyOrders(); this.m_struct_curr_symbol.session_sell_orders = this.SessionSellOrders(); this.m_struct_curr_symbol.volume_high_day = this.VolumeHigh(); this.m_struct_curr_symbol.volume_low_day = this.VolumeLow(); this.m_struct_curr_symbol.spread = this.Spread(); this.m_struct_curr_symbol.stops_level = this.TradeStopLevel(); this.m_struct_curr_symbol.freeze_level = this.TradeFreezeLevel(); this.m_struct_curr_symbol.volume_limit = this.VolumeLimit(); this.m_struct_curr_symbol.swap_long = this.SwapLong(); this.m_struct_curr_symbol.swap_short = this.SwapShort(); this.m_struct_curr_symbol.session_volume = this.SessionVolume(); this.m_struct_curr_symbol.session_turnover = this.SessionTurnover(); this.m_struct_curr_symbol.session_interest = this.SessionInterest(); this.m_struct_curr_symbol.session_buy_ord_volume = this.SessionBuyOrdersVolume(); this.m_struct_curr_symbol.session_sell_ord_volume = this.SessionSellOrdersVolume(); this.m_struct_curr_symbol.session_open = this.SessionOpen(); this.m_struct_curr_symbol.session_close = this.SessionClose(); this.m_struct_curr_symbol.session_aw = this.SessionAW(); this.m_struct_curr_symbol.volume_real_day = this.VolumeReal(); this.m_struct_curr_symbol.volume_high_real_day = this.VolumeHighReal(); this.m_struct_curr_symbol.volume_low_real_day = this.VolumeLowReal(); this.m_struct_curr_symbol.option_strike = this.OptionStrike(); this.m_struct_curr_symbol.trade_mode = this.TradeMode(); //--- Hash sum calculation this.m_hash_sum+=(double)this.m_struct_curr_symbol.volume; this.m_hash_sum+=(double)this.m_struct_curr_symbol.session_deals; this.m_hash_sum+=(double)this.m_struct_curr_symbol.session_buy_orders; this.m_hash_sum+=(double)this.m_struct_curr_symbol.session_sell_orders; this.m_hash_sum+=(double)this.m_struct_curr_symbol.volume_high_day; this.m_hash_sum+=(double)this.m_struct_curr_symbol.volume_low_day; this.m_hash_sum+=(double)this.m_struct_curr_symbol.spread; this.m_hash_sum+=(double)this.m_struct_curr_symbol.stops_level; this.m_hash_sum+=(double)this.m_struct_curr_symbol.freeze_level; this.m_hash_sum+=this.m_struct_curr_symbol.ask; this.m_hash_sum+=this.m_struct_curr_symbol.ask_high; this.m_hash_sum+=this.m_struct_curr_symbol.ask_low; this.m_hash_sum+=this.m_struct_curr_symbol.bid_last; this.m_hash_sum+=this.m_struct_curr_symbol.bid_last_high; this.m_hash_sum+=this.m_struct_curr_symbol.bid_last_low; this.m_hash_sum+=this.m_struct_curr_symbol.volume_limit; this.m_hash_sum+=this.m_struct_curr_symbol.swap_long; this.m_hash_sum+=this.m_struct_curr_symbol.swap_short; this.m_hash_sum+=this.m_struct_curr_symbol.session_volume; this.m_hash_sum+=this.m_struct_curr_symbol.session_turnover; this.m_hash_sum+=this.m_struct_curr_symbol.session_interest; this.m_hash_sum+=this.m_struct_curr_symbol.session_buy_ord_volume; this.m_hash_sum+=this.m_struct_curr_symbol.session_sell_ord_volume; this.m_hash_sum+=this.m_struct_curr_symbol.session_open; this.m_hash_sum+=this.m_struct_curr_symbol.session_close; this.m_hash_sum+=this.m_struct_curr_symbol.session_aw; this.m_hash_sum+=this.m_struct_curr_symbol.volume_real_day; this.m_hash_sum+=this.m_struct_curr_symbol.volume_high_real_day; this.m_hash_sum+=this.m_struct_curr_symbol.volume_low_real_day; this.m_hash_sum+=this.m_struct_curr_symbol.option_strike; this.m_hash_sum+=this.m_struct_curr_symbol.trade_mode; //--- 初回実行 if(this.m_struct_prev_symbol.trade_mode==WRONG_VALUE) { this.m_struct_prev_symbol=this.m_struct_curr_symbol; this.m_hash_sum_prev=this.m_hash_sum; return; } //--- If symbol's hash sum changed if(this.m_hash_sum!=this.m_hash_sum_prev) { this.m_event_code=this.SetEventCode(); this.SetTypeEvent(); CEventBaseObj *event=this.GetEvent(WRONG_VALUE,false); if(event!=NULL) { ENUM_SYMBOL_EVENT event_id=(ENUM_SYMBOL_EVENT)event.ID(); if(event_id!=SYMBOL_EVENT_NO_EVENT) { this.m_is_event=true; } } this.m_hash_sum_prev=this.m_hash_sum; } } //+------------------------------------------------------------------+
ここではまずRefreshRates()メソッドを呼び出します。相場データの取得に失敗した場合、残りのデータを取得しても意味がありません。メソッドを終了します。
次に、イベントフラグ、現在の銘柄プロパティステータスの構造体、現在のハッシュ合計をリセットします。次に、すべての銘柄プロパティに現在のデータを書き入れて、これらのデータを現在の銘柄プロパティステータスの構造体に書き込みます。構造体に書き入れた後で、ハッシュ合計を計算します。
これが最初の起動である場合(SYMBOL_TRADE_MODE銘柄プロパティがWRONG_VALUEに設定されている場合)、現在のステータス構造体の値を前のステータス構造体に保存し、現在のハッシュ合計を現在のステータス構造体に書き込んでメソッドを終了します。これが最初の起動ではない場合、以前と現在のハッシュ合計の不等式を確認する必要があります。
ハッシュ合計が変更している場合、銘柄プロパティが変更しています。イベントコードを配置するメソッド、発生したイベントのリストのイベントコードとイベントエントリからイベントと新しく追加されたイベントから最後のイベントを呼び出すメソッドを受信するためのメソッドを呼び出します。イベントの種類を確認します。「No event」でない場合は、イベントフラグをアクティブにします。最後に、現在のハッシュの合計を以前のハッシュの合計として保存して、さらに確認します。
これにより、イベントを検索し、新しい基本オブジェクトを操作するためのCSymbolクラスの改善が完了しました。
銘柄オブジェクトクラスの準備ができました。これで、各銘柄はイベントを追跡し、イベントリストに配置できるようになりました。銘柄コレクションを使用するため、すべてのコレクション銘柄を循環させて、各銘柄からイベントリストを取得する必要があります。これらのすべてのイベントは、コレクションイベントリストに配置する必要があります(CBaseObj基本オブジェクトにあるため、コレクションは同じリストを備えています)。そのため、取得されたイベントリストを調査して、各コレクション銘柄で1つまたは複数のイベントが発生したという事実を定義するだけです。
銘柄コレクションクラスのSymbolsCollection.mqhファイルを開いて必要な変更を加えます。
//+------------------------------------------------------------------+ //| SymbolsCollection.mqh | //| Copyright 2018, MetaQuotes Software Corp. | //| https://mql5.com/ja/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2018, MetaQuotes Software Corp." #property link "https://mql5.com/ja/users/artmedia70" #property version "1.00" //+------------------------------------------------------------------+ //| ファイルをインクルードする | //+------------------------------------------------------------------+ #include <Arrays\ArrayString.mqh> #include "ListObj.mqh" #include "..\Services\Select.mqh" #include "..\Objects\Symbols\Symbol.mqh" #include "..\Objects\Symbols\SymbolFX.mqh" #include "..\Objects\Symbols\SymbolFXMajor.mqh" #include "..\Objects\Symbols\SymbolFXMinor.mqh" #include "..\Objects\Symbols\SymbolFXExotic.mqh" #include "..\Objects\Symbols\SymbolFXRub.mqh" #include "..\Objects\Symbols\SymbolMetall.mqh" #include "..\Objects\Symbols\SymbolIndex.mqh" #include "..\Objects\Symbols\SymbolIndicative.mqh" #include "..\Objects\Symbols\SymbolCrypto.mqh" #include "..\Objects\Symbols\SymbolCommodity.mqh" #include "..\Objects\Symbols\SymbolExchange.mqh" #include "..\Objects\Symbols\SymbolFutures.mqh" #include "..\Objects\Symbols\SymbolCFD.mqh" #include "..\Objects\Symbols\SymbolStocks.mqh" #include "..\Objects\Symbols\SymbolBonds.mqh" #include "..\Objects\Symbols\SymbolOption.mqh" #include "..\Objects\Symbols\SymbolCollateral.mqh" #include "..\Objects\Symbols\SymbolCustom.mqh" #include "..\Objects\Symbols\SymbolCommon.mqh" //+------------------------------------------------------------------+ //| Symbol collection | //+------------------------------------------------------------------+ class CSymbolsCollection : public CBaseObj { private: CListObj m_list_all_symbols; // The list of all symbol objects CArrayString m_list_names; // Symbol name control list ENUM_SYMBOLS_MODE m_mode_list; // Mode of working with symbol lists ENUM_SYMBOL_EVENT m_last_event; // The last event string m_array_symbols[]; // The array of used symbols passed from the program int m_delta_symbol; // Difference in the number of symbols compared to the previous check int m_total_symbols; // Number of symbols in the Market Watch window int m_total_symbol_prev; // Number of symbols in the Market Watch window during the previous check //--- Return the flag of a symbol object presence by its name in the (1) list of all symbols, (2) Market Watch window, (3) control list bool IsPresentSymbolInList(const string symbol_name); bool IsPresentSymbolInMW(const string symbol_name); bool IsPresentSymbolInControlList(const string symbol_name); //--- Create the symbol object and place it to the list bool CreateNewSymbol(const ENUM_SYMBOL_STATUS symbol_status,const string name,const int index); //--- Return the (1) type of a used symbol list (Market watch/Server), //--- (2) the number of visible symbols, (3) symbol index in the Market Watch window ENUM_SYMBOLS_MODE TypeSymbolsList(const string &symbol_used_array[]); int SymbolsTotalVisible(void) const; int SymbolIndexInMW(const string name) const; //--- Define a symbol affiliation with a group by name and return it ENUM_SYMBOL_STATUS SymbolStatus(const string symbol_name) const; //--- Return a symbol affiliation with a category by custom criteria ENUM_SYMBOL_STATUS StatusByCustomPredefined(const string symbol_name) const; //--- Return a symbol affiliation with categories by margin calculation ENUM_SYMBOL_STATUS StatusByCalcMode(const string symbol_name) const; //--- Return a symbol affiliation with pre-defined (1) majors, (2) minors, (3) exotics, (4) RUB, //--- (5) indicatives, (6) metals, (7) commodities, (8) indices, (9) cryptocurrency, (10) options bool IsPredefinedFXMajor(const string name) const; bool IsPredefinedFXMinor(const string name) const; bool IsPredefinedFXExotic(const string name) const; bool IsPredefinedFXRUB(const string name) const; bool IsPredefinedIndicative(const string name) const; bool IsPredefinedMetall(const string name) const; bool IsPredefinedCommodity(const string name) const; bool IsPredefinedIndex(const string name) const; bool IsPredefinedCrypto(const string name) const; bool IsPredefinedOption(const string name) const; public: //--- 完全なコレクションリストを「そのまま」で返す CArrayObj *GetList(void) { return &this.m_list_all_symbols; } //--- 比較された基準を満たす選択された(1)整数、(2)実数、(3)文字列プロパティののリストを返す CArrayObj *GetList(ENUM_SYMBOL_PROP_INTEGER property,long value,ENUM_COMPARER_TYPE mode=EQUAL) { return CSelect::BySymbolProperty(this.GetList(),property,value,mode); } CArrayObj *GetList(ENUM_SYMBOL_PROP_DOUBLE property,double value,ENUM_COMPARER_TYPE mode=EQUAL) { return CSelect::BySymbolProperty(this.GetList(),property,value,mode); } CArrayObj *GetList(ENUM_SYMBOL_PROP_STRING property,string value,ENUM_COMPARER_TYPE mode=EQUAL) { return CSelect::BySymbolProperty(this.GetList(),property,value,mode); } //--- Return the (1) symbol object, (2) the symbol object index from the list by a name CSymbol *GetSymbolByName(const string name); int GetSymbolIndexByName(const string name); //--- Return the number of new symbols in the Market Watch window int NewSymbols(void) const { return this.m_delta_symbol; } //--- Return (1) the mode of working with symbol lists, (2) the event flag and (3) the event of one of the collection symbols ENUM_SYMBOLS_MODE ModeSymbolsList(void) const { return this.m_mode_list; } bool IsEvent(void) const { return this.m_is_event; } int GetLastEventsCode(void) const { return this.m_event_code; } ENUM_SYMBOL_EVENT GetLastEvent(void) const { return this.m_last_event; } //--- Return the number of symbols in the collection int GetSymbolsCollectionTotal(void) const { return this.m_list_all_symbols.Total(); } //--- コンストラクタ CSymbolsCollection(); //--- (1) Set the list of used symbols, (2) creating the symbol list (Market Watch or the complete list) bool SetUsedSymbols(const string &symbol_used_array[]); bool CreateSymbolsList(const bool flag); //--- Save names of used Market Watch symbols void CopySymbolsNames(void); //--- Update (1) all, (2) quote data of the collection symbols virtual void Refresh(void); void RefreshRates(void); //--- Working with the events of the (1) collection symbol list, (2) market watch window void SymbolsEventsControl(void); void MarketWatchEventsControl(const bool send_events=true); //--- Return the description of the (1) Market Watch window event, (2) mode of working with symbols string EventDescription(const ENUM_SYMBOL_EVENT event); string ModeSymbolsListDescription(void); }; //+------------------------------------------------------------------+
標準ライブラリから含まれているCArrayStringクラスファイルは、[気配値表示]ウィンドウのスナップショットの作成に使用されます。このリストは、[気配値表示]からの銘柄セットのコピーを保存し、ウィンドウ内の銘柄リストの現在のステータスをスナップショット内の銘柄リストと比較します。変更があった場合は、[気配値表示]ウィンドウイベントを作成するためにそれらに対応する必要があります。
コレクション銘柄のいずれかに発生した最後のイベントは、m_last_event変数に追加されます。したがって、変数には、使用されている銘柄の1つで発生した最新のイベントが格納されます。
m_array_symbols配列は、使用されている銘柄の配列をコントロールプログラムから銘柄コレクションクラスに渡します。
[気配値表示]ウィンドウの現在および以前の銘柄数はそれぞれm_total_symbolsと m_total_symbols_prevクラスメンバ変数に保存されます。変数の値を比較することにより、[気配値表示]で銘柄を追加および削除するイベントを定義できます。
IsPresentSymbolInMW()およびIsPresentSymbolInControlList()プライベートクラスメソッドは、[気配値表示]でのその名前の銘柄プレゼンスフラグを返しますと[気配値表示]ウィンドウのスナップショットリストを返します。SymbolsTotalVisible()およびSymbolIndexInMW()メソッドは、[気配値表示]ウィンドウおよびそれに応じて、ウィンドウリストの銘柄インデックスを返します。
以下のメソッドをクラスのpublicセクションに追加します。
IsEvent() — 銘柄コレクションまたは[気配値表示]ウィンドウでイベントの存在のフラグを返します。GetLastEventsCode() — 銘柄コレクションまたは[気配値表示]ウィンドウで最後のイベントのコードを返します。
GetLastEvent() — 銘柄コレクションまたは[気配値表示]ウィンドウで最後のイベントを返します。GetSymbolsCollectionTotal() — コレクション内の銘柄の総数を返します。
CreateSymbolsList() — [気配値表示]ウィンドウまたはサーバ上の銘柄の完全なリスト(1000以下)を使用するときにコレクションリストを作成します。
CopySymbolsNames() — すべてのコレクション銘柄のリストから[気配値表示]ウィンドウ銘柄のスナップショットを作成します
Refresh() — このメソッドは基本オブジェクトクラスで仮想クラスとして宣言されているため、メソッドは仮想メソッドとして宣言されます(銘柄コレクションはCBaseObjに基づいて作成されるようになりました)。
SymbolsEventsControl() — 銘柄コレクションイベントを定義するために銘柄コレクションリストを使用するメソッド。MarketWatchEventsControl() — [気配値表示]ウィンドウでイベントを定義するための[気配値表示]ウィンドウリストを使用するメソッド
EventDescription() — 銘柄コレクションイベントの説明を返します。
ModeSymbolsListDescription() — 銘柄の使用モードの説明を返します。
メソッドの実装を見てみましょう。
クラスコンストラクタの初期化リストで、[気配値表示]を使用する変数を初期化します。クラス本体で、コレクション銘柄のリストの並び替えを名前による並び替えから[気配値表示]ウィンドウのインデックスによる並び替えに変更し、[気配値表示]ウィンドウスナップショットのリストをクリアします。
//+------------------------------------------------------------------+ //| コンストラクタ | //+------------------------------------------------------------------+ CSymbolsCollection::CSymbolsCollection(void) : m_total_symbol_prev(0), m_delta_symbol(0), m_mode_list(SYMBOLS_MODE_CURRENT) { this.m_list_all_symbols.Sort(SORT_BY_SYMBOL_INDEX_MW); this.m_list_all_symbols.Clear(); this.m_list_all_symbols.Type(COLLECTION_SYMBOLS_ID); this.m_list_names.Clear(); } //+------------------------------------------------------------------+
一部の銘柄は[気配値表示]ウィンドウに表示されないがまだ存在している場合があるため(SYMBOL_VISIBLE銘柄プロパティ)、一部の銘柄(通常、これらは預金通貨の証拠金要件と利益の計算に必要なクロスです) は自動的に選択され、[気配値表示]には表示されません。したがって、表示される銘柄の数のみを調べるには、ウィンドウ銘柄によるループではこのプロパティが設定されている銘柄のみを計算する必要があります。
SymbolsTotalVisible()は[気配値表示]ウィンドウで表示されている銘柄の数を返します。
//+------------------------------------------------------------------+ //| Return the number of visible symbols in the Market Watch window | //+------------------------------------------------------------------+ int CSymbolsCollection::SymbolsTotalVisible(void) const { int total=::SymbolsTotal(true),n=0; for(int i=0;i<total;i++) { if(!::SymbolInfoInteger(::SymbolName(i,true),SYMBOL_VISIBLE)) continue; n++; } return n; } //+------------------------------------------------------------------+
以下は、[気配値表示]ウィンドウリストで銘柄インデックスを返すメソッドです。
//+------------------------------------------------------------------+ //| Return symbol index in the Market Watch window | //+------------------------------------------------------------------+ int CSymbolsCollection::SymbolIndexInMW(const string name) const { int total=::SymbolsTotal(true); for(int i=0;i<total;i++) { if(!::SymbolInfoInteger(::SymbolName(i,true),SYMBOL_VISIBLE)) continue; if(SymbolName(i,true)==name) return i; } return WRONG_VALUE; } //+------------------------------------------------------------------+
気配値表示からの銘柄リストを使用する場合、コレクション銘柄リスト内の銘柄の位置を[気配値表示]内の銘柄の位置と同期できるように、 ウィンドウリスト内の各銘柄のインデックスを見つける必要があります。たとえば、これは、ターミナルウィンドウと完全に同期したカスタム銘柄リストウィンドウを作成する場合に役立ちます。インデックスは銘柄プロパティの1つであり、それによってリストを並び替えできます。インデックスは、抽象銘柄クラスコンストラクタに渡されます。
以下は、[気配値表示]ウィンドウに表示されている銘柄のフラグを返すメソッドです。
//+------------------------------------------------------------------+ //| Return the visible symbol object presence flag | //| by its name in the Market Watch window | //+------------------------------------------------------------------+ bool CSymbolsCollection::IsPresentSymbolInMW(const string symbol_name) { int total=SymbolsTotal(true); for(int i=0;i<total;i++) { string name=::SymbolName(i,true); if(!::SymbolInfoInteger(name,SYMBOL_VISIBLE)) continue; if(name==symbol_name) return true; } return false; } //+------------------------------------------------------------------+
メソッドは銘柄名を受け取り、[気配値表示]ウィンドウで選択された銘柄の完全なリストのループで、非表示の銘柄をスキップして、次の銘柄の名前をメソッドに渡された銘柄と比較します。名前が一致した場合はtrueを返します。名前がリストに見つからない場合は、falseを返します。
以下は、[気配値表示]ウィンドウのスナップショットリストに銘柄が存在するかどうかのフラグを返すメソッドです。
//+------------------------------------------------------------------+ //| Return the flag of a symbol object presence in the control list | //+------------------------------------------------------------------+ bool CSymbolsCollection::IsPresentSymbolInControlList(const string symbol_name) { int total=this.m_list_names.Total(); for(int i=0;i<total;i++) { string name=this.m_list_names.At(i); if(name==NULL) continue; if(name==symbol_name) return true; } return false; } //+------------------------------------------------------------------+
必要な銘柄名がメソッドに渡されます。[気配値表示]ウィンドウのループ内のスナップショットリストにより、必要な銘柄を受け取り、その名前がメソッドに渡されたものと一致する場合、 trueを返し、その他の場合は、falseを介します。
以下は、[気配値表示]ウィンドウまたはサーバ上の銘柄の完全なリストを操作するときにリストを作成するメソッドです。
//+------------------------------------------------------------------+ //| Creating the symbol list (Market Watch or the complete list) | //+------------------------------------------------------------------+ bool CSymbolsCollection::CreateSymbolsList(const bool flag) { bool res=true; int total=::SymbolsTotal(flag); for(int i=0;i<total && i<SYMBOLS_COMMON_TOTAL;i++) { string name=::SymbolName(i,flag); if(flag && !::SymbolInfoInteger(name,SYMBOL_VISIBLE)) continue; ENUM_SYMBOL_STATUS status=this.SymbolStatus(name); bool add=this.CreateNewSymbol(status,name,i); res &=add; if(!add) continue; } return res; } //+------------------------------------------------------------------+
このメソッドはフラグを受け取り、検索モードを設定します: trueでは[気配値表示]ウィンドウで選択された銘柄を使用、falseではサーバ上に存在する銘柄の完全なリストを使用します。flagに応じて、[気配値表示]ウィンドウまたはサーバのいずれかで銘柄の総数を取得します。リストによるループで、ただしDefines.mqhファイルのSYMBOLS_COMMON_TOTAL定数によって設定された値(1000)を越えない範囲で、リストから次の銘柄の名前を取得して、[気配値表示]ウィンドウを使用している場合はその可視性プロパティを確認して、非表示の場合はスキップします。
その名前で銘柄オブジェクトステータスを取得し、前の記事で検討したすべてのコレクション銘柄のリストにCreateNewSymbol()メソッドを使用して銘柄を追加します 。(新しい銘柄プロパティ([気配値表示]ウィンドウの銘柄リストのインデックス)を追加したため、メソッドが少し変更されていることに注意してください。インデックスも銘柄オブジェクトに渡されるようになっています)。
すべてのコレクション銘柄のリストに各銘柄を追加した結果は、メソッドの使用結果を返す変数に追加されます。この変数の合計値は、銘柄処理ループ全体が完了するとメソッドから返されます。
銘柄オブジェクトの作成方法とリストへの配置を改善するメソッドを考えてみましょう。
//+------------------------------------------------------------------+ //| Create a symbol object and place it to the list | //+------------------------------------------------------------------+ bool CSymbolsCollection::CreateNewSymbol(const ENUM_SYMBOL_STATUS symbol_status,const string name,const int index) { if(this.IsPresentSymbolInList(name)) { return true; } if(#ifdef __MQL5__ !::SymbolInfoInteger(name,SYMBOL_EXIST) #else !Exist(name) #endif ) { string t1=TextByLanguage("Ошибка входных данных: нет символа ","Input error: no "); string t2=TextByLanguage(" на сервере"," symbol on the server"); ::Print(DFUN,t1,name,t2); this.m_global_error=ERR_MARKET_UNKNOWN_SYMBOL; return false; } CSymbol *symbol=NULL; switch(symbol_status) { case SYMBOL_STATUS_FX : symbol=new CSymbolFX(name,index); break; // Forex symbol case SYMBOL_STATUS_FX_MAJOR : symbol=new CSymbolFXMajor(name,index); break; // Major Forex symbol case SYMBOL_STATUS_FX_MINOR : symbol=new CSymbolFXMinor(name,index); break; // Minor Forex symbol case SYMBOL_STATUS_FX_EXOTIC : symbol=new CSymbolFXExotic(name,index); break; // Exotic Forex symbol case SYMBOL_STATUS_FX_RUB : symbol=new CSymbolFXRub(name,index); break; // Forex symbol/RUR case SYMBOL_STATUS_METAL : symbol=new CSymbolMetall(name,index); break; // Metal case SYMBOL_STATUS_INDEX : symbol=new CSymbolIndex(name,index); break; // Index case SYMBOL_STATUS_INDICATIVE : symbol=new CSymbolIndicative(name,index); break; // Indicative case SYMBOL_STATUS_CRYPTO : symbol=new CSymbolCrypto(name,index); break; // Cryptocurrency symbol case SYMBOL_STATUS_COMMODITY : symbol=new CSymbolCommodity(name,index); break; // Commodity case SYMBOL_STATUS_EXCHANGE : symbol=new CSymbolExchange(name,index); break; // Exchange symbol case SYMBOL_STATUS_FUTURES : symbol=new CSymbolFutures(name,index); break; // Futures case SYMBOL_STATUS_CFD : symbol=new CSymbolCFD(name,index); break; // CFD case SYMBOL_STATUS_STOCKS : symbol=new CSymbolStocks(name,index); break; // Stock case SYMBOL_STATUS_BONDS : symbol=new CSymbolBonds(name,index); break; // Bond case SYMBOL_STATUS_OPTION : symbol=new CSymbolOption(name,index); break; // Option case SYMBOL_STATUS_COLLATERAL : symbol=new CSymbolCollateral(name,index); break; // Non-tradable asset case SYMBOL_STATUS_CUSTOM : symbol=new CSymbolCustom(name,index); break; // Custom symbol default : symbol=new CSymbolCommon(name,index); break; // The rest } if(symbol==NULL) { ::Print(DFUN,TextByLanguage("Не удалось создать объект-символ ","Failed to create symbol object "),name); return false; } if(!this.m_list_all_symbols.Add(symbol)) { string t1=TextByLanguage("Не удалось добавить символ ","Failed to add "); string t2=TextByLanguage(" в список"," symbol to the list"); ::Print(DFUN,t1,name,t2); delete symbol; return false; } return true; } //+------------------------------------------------------------------+
リストからわかるように、ここではさらに、銘柄名とともにそれと銘柄オブジェクトクラスコンストラクタのそれぞれに送信するインデックスを渡します。これは、CSymbol抽象銘柄クラスから派生した各クラスを改良する必要があることを意味します。
例としてCSymbolFXクラスを使用して、この改良を検討してみましょう。
//+------------------------------------------------------------------+ //| SymbolFX.mqh | //| Copyright 2018, MetaQuotes Software Corp. | //| https://mql5.com/ja/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2018, MetaQuotes Software Corp." #property link "https://mql5.com/ja/users/artmedia70" #property version "1.00" //+------------------------------------------------------------------+ //| ファイルをインクルードする | //+------------------------------------------------------------------+ #include "Symbol.mqh" //+------------------------------------------------------------------+ //| Forex symbol | //+------------------------------------------------------------------+ class CSymbolFX : public CSymbol { public: //--- コンストラクタ CSymbolFX(const string name,const int index) : CSymbol(SYMBOL_STATUS_FX,name,index) {} //--- Supported integer properties of a symbol virtual bool SupportProperty(ENUM_SYMBOL_PROP_INTEGER property); //--- Supported real properties of a symbol virtual bool SupportProperty(ENUM_SYMBOL_PROP_DOUBLE property); //--- Supported string properties of a symbol virtual bool SupportProperty(ENUM_SYMBOL_PROP_STRING property); //--- Display a short symbol description in the journal virtual void PrintShort(void); }; //+------------------------------------------------------------------+
ここでは、銘柄名に加えて、クラスコンストラクタもそのインデックスを受け取り、インデックスは初期化リストでCSymbol親クラスコンストラクターに渡されます。
抽象銘柄から派生したすべてのクラスで変更する必要があるのはこれですべてです。銘柄オブジェクトクラスに対するすべての変更は、以下に添付されているファイルで既に行われています。
以下は、コレクション内で使用される銘柄のリストを設定する改良されたメソッドです。
//+------------------------------------------------------------------+ //| Set the list of used symbols | //+------------------------------------------------------------------+ bool CSymbolsCollection::SetUsedSymbols(const string &symbol_used_array[]) { ::ArrayCopy(this.m_array_symbols,symbol_used_array); this.m_mode_list=this.TypeSymbolsList(this.m_array_symbols); this.m_list_all_symbols.Clear(); this.m_list_all_symbols.Sort(SORT_BY_SYMBOL_INDEX_MW); //--- Use only the current symbol if(this.m_mode_list==SYMBOLS_MODE_CURRENT) { string name=::Symbol(); ENUM_SYMBOL_STATUS status=this.SymbolStatus(name); return this.CreateNewSymbol(status,name,this.SymbolIndexInMW(name)); } else { bool res=true; //--- Use the pre-defined symbol list if(this.m_mode_list==SYMBOLS_MODE_DEFINES) { int total=::ArraySize(this.m_array_symbols); for(int i=0;i<total;i++) { string name=this.m_array_symbols[i]; ENUM_SYMBOL_STATUS status=this.SymbolStatus(name); bool add=this.CreateNewSymbol(status,name,this.SymbolIndexInMW(name)); res &=add; if(!add) continue; } return res; } //--- Use the full list of the server symbols else if(this.m_mode_list==SYMBOLS_MODE_ALL) { return this.CreateSymbolsList(false); } //--- Use the symbol list from the Market Watch window else if(this.m_mode_list==SYMBOLS_MODE_MARKET_WATCH) { this.MarketWatchEventsControl(false); return true; } } return false; } //+------------------------------------------------------------------+
ここで、コントロールプログラムからカスタム配列に渡された使用済み銘柄の配列をコピーします。銘柄の使用モードを保存してすべての銘柄のリストの並び替えをインデックスによる並び替えに設定します。これで、新しい銘柄オブジェクトの作成方法は、銘柄名に加えてそのインデックスを受け取るようになります。
サーバ上のすべての銘柄の完全なリストを使用する場合、フラグ=falseでコレクション銘柄リストを作成するメソッドを呼び出して、サーバでの銘柄の完全なリストの作成を示します。
ウィンドウからリストを使用する場合、フラグ=falseを使用して[気配値表示]ウィンドウを使用するメソッドを呼び出し、イベントの使用を完全に禁止するのではなく、リストの作成とそのデータの書き込みの要件を示します。
以下はすべてのコレクション銘柄のイベントを使用するメソッドです。
//+------------------------------------------------------------------+ //| Working with the events of the collection symbol list | //+------------------------------------------------------------------+ void CSymbolsCollection::SymbolsEventsControl(void) { this.m_is_event=false; this.m_list_events.Clear(); this.m_list_events.Sort(); //--- The full update of all collection symbols int total=this.m_list_all_symbols.Total(); for(int i=0;i<total;i++) { CSymbol *symbol=this.m_list_all_symbols.At(i); if(symbol==NULL) continue; symbol.Refresh(); if(!symbol.IsEvent()) continue; this.m_is_event=true; CArrayObj *list=symbol.GetListEvents(); if(list==NULL) continue; this.m_event_code=symbol.GetEventCode(); int n=list.Total(); for(int j=0; j<n; j++) { CEventBaseObj *event=list.At(j); if(event==NULL) continue; ENUM_SYMBOL_EVENT event_id=(ENUM_SYMBOL_EVENT)event.ID(); if(event_id==SYMBOL_EVENT_NO_EVENT) continue; this.m_last_event=event_id; if(this.EventAdd((ushort)event.ID(),event.LParam(),event.DParam(),event.SParam())) { ::EventChartCustom(this.m_chart_id,(ushort)event_id,event.LParam(),event.DParam(),event.SParam()); } } } } //+------------------------------------------------------------------+
このメソッドはタイマーで動作します。まず、データが初期化されます。
銘柄コレクションイベントフラグがリセットされ
銘柄コレクション内のイベントのリストがクリアされ
並び替え済みリストフラグがリストに設定されます。
次に、コレクション銘柄リスト内のすべての銘柄によるループで、次の銘柄を受信し、すべてのデータを更新し、銘柄に設定されたイベントフラグの存在を確認します。イベントがない場合は、コレクションの次の銘柄を確認します。
銘柄がイベントフラグを備えている場合、コレクション全体にイベントフラグを設定します(少なくとも1つの銘柄にイベントが存在することは、イベントがコレクション全体に存在することを意味します)。現在のすべての銘柄イベントのリストを取得し、リストから現在の銘柄のイベントコードに等しい最後のコレクションイベントのコードを設定します。イベントが存在する場合、最後のコレクションイベントのコードを格納する変数に設定された値は次の銘柄に対して更新されますが、現在のすべての銘柄イベントのリストによるループで、新しいイベントを取得して、イベントIDを最後のコレクションイベントとして保存します。同様に、次の銘柄のイベントは最後の銘柄コレクションイベントを更新します。
次に、銘柄イベントパラメータが設定されたコレクションイベントを作成(イベントID 、long、double、string)し、銘柄イベントを銘柄コレクションイベントのリストに保存します。
銘柄イベントがコレクションイベントリストに正常に保存された場合、イベントは、呼び出し元プログラムでさらに処理するために、同じイベントパラメータでEventChartCustom()関数を使用してイベントでプログラムチャートに送信されます 。
したがって、コレクションリストの各銘柄からイベントリストを受信したら、各銘柄のイベントのリストを調べて、すべてのイベントをコレクションイベントリストに送信します。ループが完了すると、コレクションイベントのリストには、すべてのコレクション銘柄のすべてのイベントが表示されます。各イベントに対してカスタムイベントが作成され、コントロールプログラムチャートに送信されます。
[気配値表示]ウィンドウのイベントを区別するには、すべての[気配値表示]銘柄のハッシュ合計を計算する必要があります。ハッシュ合計の変化は、イベントが発生したことを示します最初に思い浮かぶのは、ウィンドウ内の銘柄の数の単純なカウントです。ただし、銘柄を追加または削除してもリストのサイズが増減しますが、マウスで銘柄を並べ替えても銘柄の数は変わりません。これは、[気配値表示]ウィンドウの銘柄の数がハッシュ合計の計算に適していないことを意味します。
次のようにしましょう。リストに保存された各銘柄の名前は、銘柄(文字)コードのuchar値の合計に [気配値表示]ウィンドウでの銘柄のインデックスを追加して構成される数字(銘柄コード)にとして表すことができます。これらすべての銘柄コードの合計がハッシュの合計になります。
- リストに銘柄を追加すると、ハッシュの合計が変更されます(追加された銘柄の新しいコードが追加されます)。
- リストから銘柄を削除すると、ハッシュ合計も変更されます(削除された銘柄のコードはハッシュ合計から差し引かれます)。
- 銘柄リストを並べ替えると、ハッシュの合計が変更されます(インデックスが変更されるため、並べ替えられた銘柄のコードが変更されます)
以下は、[気配値表示]ウィンドウイベントを使用するメソッドの実装です。
//+------------------------------------------------------------------+ //| Working with market watch window events | //+------------------------------------------------------------------+ void CSymbolsCollection::MarketWatchEventsControl(const bool send_events=true) { ::ResetLastError(); //--- If no current prices are received, exit if(!::SymbolInfoTick(::Symbol(),this.m_tick)) { this.m_global_error=::GetLastError(); return; } uchar array[]; int sum=0; this.m_hash_sum=0; //--- Calculate the hash sum of all visible symbols in the Market Watch window this.m_total_symbols=this.SymbolsTotalVisible(); //--- In the loop by all Market Watch window symbols int total_symbols=::SymbolsTotal(true); for(int i=0;i<total_symbols;i++) { //--- get a symbol name by index string name=::SymbolName(i,true); //--- skip if invisible if(!::SymbolInfoInteger(name,SYMBOL_VISIBLE)) continue; //--- write symbol name (characters) codes to the uchar array ::StringToCharArray(name,array); //--- in a loop by the resulting array, sum up the values of all array cells creating the symbol code for(int j=::ArraySize(array)-1;j>WRONG_VALUE;j--) sum+=array[j]; //--- add the symbol code and the loop index specifying the symbol index in the market watch list to the hash sum m_hash_sum+=i+sum; } //--- If sending events is disabled, create the collection list and exit saving the current hash some as the previous one if(!send_events) { //--- Clear the list this.m_list_all_symbols.Clear(); //--- Clear the collection list this.CreateSymbolsList(true); //--- Clear the market watch window snapshot this.CopySymbolsNames(); //--- save the current hash some as the previous one this.m_hash_sum_prev=this.m_hash_sum; //--- save the current number of visible symbols as the previous one this.m_total_symbol_prev=this.m_total_symbols; return; } //--- If the hash sum of symbols in the Market Watch window has changed if(this.m_hash_sum!=this.m_hash_sum_prev) { //--- Define the Market Watch window event this.m_delta_symbol=this.m_total_symbols-this.m_total_symbol_prev; ENUM_SYMBOL_EVENT event_id= ( this.m_total_symbols>this.m_total_symbol_prev ? SYMBOL_EVENT_MW_ADD : this.m_total_symbols<this.m_total_symbol_prev ? SYMBOL_EVENT_MW_DEL : SYMBOL_EVENT_MW_SORT ); //--- Adding a symbol to the Market Watch window if(event_id==SYMBOL_EVENT_MW_ADD) { string name=""; //--- In the loop by all Market Watch window symbols int total=::SymbolsTotal(true), index=WRONG_VALUE; for(int i=0;i<total;i++) { //--- get the symbol name and check its "visibility". Skip it if invisible name=::SymbolName(i,true); if(!::SymbolInfoInteger(name,SYMBOL_VISIBLE)) continue; //--- If there is no symbol in the collection symbol list yet if(!this.IsPresentSymbolInList(name)) { //--- clear the collection list this.m_list_all_symbols.Clear(); //--- recreate the collection list this.CreateSymbolsList(true); //--- create the symbol collection snapshot this.CopySymbolsNames(); //--- get a new symbol index in the Market Watch window index=this.GetSymbolIndexByName(name); //--- If the "Adding a new symbol" event is successfully added to the event list if(this.EventAdd(event_id,this.TickTime(),index,name)) { //--- send the event to the chart: //--- long value = event time in milliseconds, double value = symbol index, string value = added symbol name ::EventChartCustom(this.m_chart_id,(ushort)event_id,this.TickTime(),index,name); } } } //--- Save the new number of visible symbols in the market watch window this.m_total_symbols=this.SymbolsTotalVisible(); } //--- Remove a symbol from the Market Watch window else if(event_id==SYMBOL_EVENT_MW_DEL) { //--- clear the collection list this.m_list_all_symbols.Clear(); //--- recreate the collection list this.CreateSymbolsList(true); //--- In a loop by the market watch window snapshot int total=this.m_list_names.Total(); for(int i=0; i<total;i++) { //--- get a symbol name string name=this.m_list_names.At(i); if(name==NULL) continue; //--- if no symbol with such a name exists in the collection symbol list if(!this.IsPresentSymbolInList(name)) { //--- If the "Removing a symbol" event is successfully added to the event list if(this.EventAdd(event_id,this.TickTime(),WRONG_VALUE,name)) { //--- send the event to the chart: //--- long value = event tine in milliseconds, double value = -1 for an absent symbol, string value = a removed symbol name ::EventChartCustom(this.m_chart_id,(ushort)event_id,this.TickTime(),WRONG_VALUE,name); } } } //--- Recreate the market watch snapshot this.CopySymbolsNames(); //--- Save the new number of visible symbols in the market watch window this.m_total_symbols=this.SymbolsTotalVisible(); } //--- Sorting symbols in the Market Watch window else if(event_id==SYMBOL_EVENT_MW_SORT) { //--- clear the collection list this.m_list_all_symbols.Clear(); //--- set sorting of the collection list as sorting by index this.m_list_all_symbols.Sort(SORT_BY_SYMBOL_INDEX_MW); //--- recreate the collection list this.CreateSymbolsList(true); //--- get the current symbol index in the Market Watch window int index=this.GetSymbolIndexByName(Symbol()); //--- send the event to the chart: //--- long value = event time in milliseconds, double value = current symbol index, string value = current symbol name ::EventChartCustom(this.m_chart_id,(ushort)event_id,this.TickTime(),index,::Symbol()); } //--- save the current number of visible symbols as the previous one this.m_total_symbol_prev=this.m_total_symbols; //--- save the current hash some as the previous one this.m_hash_sum_prev=this.m_hash_sum; } } //+------------------------------------------------------------------+
メソッドコードですべてのブランチを記述するのを避けるために、コードをブロックごとに配置しました。各ブロックには詳細なコメントが付いています。コメントですべてが明確であることを願っています。質問がある場合は、記事へのコメントで質問してください。
[気配値表示]ウィンドウを使用して、そこで発生するイベントを追跡する場合、ハッシュの合計のみでの作業は不十分です。イベントの前に何が起こったのかを知りたい場合は、[気配値表示]銘柄リスト([気配値表示]スナップショット)のコピーが必要です。たとえば、このコピーにより、削除された銘柄を見つけることができます。[気配値表示]のスナップショットがなければ、削除された銘柄の名前を知ることはできません。
以下は、[気配値表示]ウィンドウのスナップショットを作成するメソッドです。
//+------------------------------------------------------------------+ //| Save names of used Market Watch symbols | //+------------------------------------------------------------------+ void CSymbolsCollection::CopySymbolsNames(void) { this.m_list_names.Clear(); int total=this.m_list_all_symbols.Total(); for(int i=0;i<total;i++) { CSymbol *symbol=this.m_list_all_symbols.At(i); if(symbol==NULL) continue; this.m_list_names.Add(symbol.Name()); } } //+------------------------------------------------------------------+
ここでは、銘柄名のリストをクリアします。コレクション銘柄リストによるループで、新しい銘柄を受け取り、銘柄名のリストに追加します。
ループが完了すると、コレクションイベントのリストには、すべてのコレクション銘柄のすべてのイベントが表示されます。
以下は、名前で銘柄オブジェクトを返すメソッドです。
//+------------------------------------------------------------------+ //| Return an object symbol from the list by a name | //+------------------------------------------------------------------+ CSymbol *CSymbolsCollection::GetSymbolByName(const string name) { CArrayObj *list=this.GetList(SYMBOL_PROP_NAME,name,EQUAL); if(list==NULL || list.Total()==0) return NULL; CSymbol *symbol=list.At(0); return(symbol!=NULL ? symbol : NULL); } //+------------------------------------------------------------------+
メソッドに銘柄名が渡されます。次に、「銘柄名」プロパティでGetList()オブジェクトのリストを受信する方法を使用して、 その名前がメソッドに渡されたものと一致する場合に。単一のオブジェクト銘柄を配置する新しいリストを作成します。
リストから銘柄オブジェクトを取得し、検索が成功した場合はそれを返します 。銘柄コレクションリストにそのような名前の銘柄がない場合はNULLを返します。
以下は、銘柄コレクションリストで銘柄インデックスを返すメソッドです。
//+------------------------------------------------------------------+ //| Return the symbol object index from the list by a name | //+------------------------------------------------------------------+ int CSymbolsCollection::GetSymbolIndexByName(const string name) { int total=this.m_list_all_symbols.Total(); for(int i=0;i<total;i++) { CSymbol *symbol=this.m_list_all_symbols.At(i); if(symbol==NULL) continue; if(symbol.Name()==name) return i; } return WRONG_VALUE; } //+------------------------------------------------------------------+
ここで、必要な銘柄名がメソッドに渡されます。次に、コレクション銘柄リスト内のすべての銘柄によるループで、リストから別の銘柄オブジェクトを取得します。その名前が必要なものと一致する場合、ループインデックスを返します。その他の場合は-1を返します。
以下は、[気配値表示]ウィンドウからイベントの説明を返すメソッドです。
//+------------------------------------------------------------------+ //| Return the Market Watch window event description | //+------------------------------------------------------------------+ string CSymbolsCollection::EventDescription(const ENUM_SYMBOL_EVENT event) { return ( event==SYMBOL_EVENT_MW_ADD ? TextByLanguage("В окно \"Обзор рынка\" добавлен символ","Added symbol to \"Market Watch\" window") : event==SYMBOL_EVENT_MW_DEL ? TextByLanguage("Из окна \"Обзор рынка\" удалён символ","Removed from \"Market Watch\" window") : event==SYMBOL_EVENT_MW_SORT ? TextByLanguage("Изменено расположение символов в окне \"Обзор рынка\"","Changed arrangement of symbols in \"Market Watch\" window") : EnumToString(event) ); } //+------------------------------------------------------------------+
このメソッドはイベントを受信し、受信したイベントに応じてテキストの説明を返します。
以下は、銘柄の操作モードを返すメソッドです。
//+------------------------------------------------------------------+ //| Return a description of the mode of working with symbols | //+------------------------------------------------------------------+ string CSymbolsCollection::ModeSymbolsListDescription(void) { return ( this.m_mode_list==SYMBOLS_MODE_CURRENT ? TextByLanguage("Работа только с текущим символом","Work only with current symbol") : this.m_mode_list==SYMBOLS_MODE_DEFINES ? TextByLanguage("Работа с предопределённым списком символов","Work with predefined list of symbols") : this.m_mode_list==SYMBOLS_MODE_MARKET_WATCH ? TextByLanguage("Работа с символами из окна \"Обзор рынка\"","Working with symbols from \"Market Watch\" window") : TextByLanguage("Работа с полным списком всех доступных символов","Work with full list of all available symbols") ); } //+------------------------------------------------------------------+
ここでは、m_mode_list 変数の存在が確認され、変数値に応じた動作モードのテキスト記述が返されます。
これで、銘柄イベントクラスの作成が完了しました。
銘柄イベントクラスを機能させる前に、イベントトラッキングも配置できることに注意してください。クラスはCBaseObj基本オブジェクトを特徴とし、口座クラスはCBaseObjに基づいています。これは、両方のクラスが既に準備されたイベント検索機能を使用できることを意味します。BaseObjから派生するすべての後続オブジェクトにも、オブジェクトイベントを追跡できるプロパティが付与されます。
口座イベントクラスの改善
Account.mqh口座クラスファイルを開いて、必要な変更を加えます。
Object.mqhファイルのインクルードをBaseObj.mqhのインクルードに置き換えます。
//+------------------------------------------------------------------+ //| Account.mqh | //| Copyright 2018, MetaQuotes Software Corp. | //| https://mql5.com/ja/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2018, MetaQuotes Software Corp." #property link "https://mql5.com/ja/users/artmedia70" #property version "1.00" //+------------------------------------------------------------------+ //| ファイルをインクルードする | //+------------------------------------------------------------------+ #include "..\BaseObj.mqh" #include "..\..\Services\DELib.mqh"で置き換えます。 //+------------------------------------------------------------------+ //| Account class | //+------------------------------------------------------------------+ class CAccount : public CBaseObj { private:
CObjectではなく、CBaseObjを基本クラスとして設定します。
CBaseObjから継承したオブジェクトに名前を割り当てることができるようになったため、その機能を使用して口座オブジェクトの名前を設定します。
CAccountクラスコンストラクタの最後に、口座オブジェクト名を設定する行を追加します。
//+------------------------------------------------------------------+ //| コンストラクタ | //+------------------------------------------------------------------+ CAccount::CAccount(void) { //--- 整数型プロパティを保存する this.m_long_prop[ACCOUNT_PROP_LOGIN] = ::AccountInfoInteger(ACCOUNT_LOGIN); this.m_long_prop[ACCOUNT_PROP_TRADE_MODE] = ::AccountInfoInteger(ACCOUNT_TRADE_MODE); this.m_long_prop[ACCOUNT_PROP_LEVERAGE] = ::AccountInfoInteger(ACCOUNT_LEVERAGE); this.m_long_prop[ACCOUNT_PROP_LIMIT_ORDERS] = ::AccountInfoInteger(ACCOUNT_LIMIT_ORDERS); this.m_long_prop[ACCOUNT_PROP_MARGIN_SO_MODE] = ::AccountInfoInteger(ACCOUNT_MARGIN_SO_MODE); this.m_long_prop[ACCOUNT_PROP_TRADE_ALLOWED] = ::AccountInfoInteger(ACCOUNT_TRADE_ALLOWED); this.m_long_prop[ACCOUNT_PROP_TRADE_EXPERT] = ::AccountInfoInteger(ACCOUNT_TRADE_EXPERT); this.m_long_prop[ACCOUNT_PROP_MARGIN_MODE] = #ifdef __MQL5__::AccountInfoInteger(ACCOUNT_MARGIN_MODE) #else ACCOUNT_MARGIN_MODE_RETAIL_HEDGING #endif ; this.m_long_prop[ACCOUNT_PROP_CURRENCY_DIGITS] = #ifdef __MQL5__::AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS) #else 2 #endif ; this.m_long_prop[ACCOUNT_PROP_SERVER_TYPE] = (::TerminalInfoString(TERMINAL_NAME)=="MetaTrader 5" ? 5 : 4); //--- 実数型プロパティを保存する this.m_double_prop[this.IndexProp(ACCOUNT_PROP_BALANCE)] = ::AccountInfoDouble(ACCOUNT_BALANCE); this.m_double_prop[this.IndexProp(ACCOUNT_PROP_CREDIT)] = ::AccountInfoDouble(ACCOUNT_CREDIT); this.m_double_prop[this.IndexProp(ACCOUNT_PROP_PROFIT)] = ::AccountInfoDouble(ACCOUNT_PROFIT); this.m_double_prop[this.IndexProp(ACCOUNT_PROP_EQUITY)] = ::AccountInfoDouble(ACCOUNT_EQUITY); this.m_double_prop[this.IndexProp(ACCOUNT_PROP_MARGIN)] = ::AccountInfoDouble(ACCOUNT_MARGIN); this.m_double_prop[this.IndexProp(ACCOUNT_PROP_MARGIN_FREE)] = ::AccountInfoDouble(ACCOUNT_MARGIN_FREE); this.m_double_prop[this.IndexProp(ACCOUNT_PROP_MARGIN_LEVEL)] = ::AccountInfoDouble(ACCOUNT_MARGIN_LEVEL); this.m_double_prop[this.IndexProp(ACCOUNT_PROP_MARGIN_SO_CALL)] = ::AccountInfoDouble(ACCOUNT_MARGIN_SO_CALL); this.m_double_prop[this.IndexProp(ACCOUNT_PROP_MARGIN_SO_SO)] = ::AccountInfoDouble(ACCOUNT_MARGIN_SO_SO); this.m_double_prop[this.IndexProp(ACCOUNT_PROP_MARGIN_INITIAL)] = ::AccountInfoDouble(ACCOUNT_MARGIN_INITIAL); this.m_double_prop[this.IndexProp(ACCOUNT_PROP_MARGIN_MAINTENANCE)]=::AccountInfoDouble(ACCOUNT_MARGIN_MAINTENANCE); this.m_double_prop[this.IndexProp(ACCOUNT_PROP_ASSETS)] = ::AccountInfoDouble(ACCOUNT_ASSETS); this.m_double_prop[this.IndexProp(ACCOUNT_PROP_LIABILITIES)] = ::AccountInfoDouble(ACCOUNT_LIABILITIES); this.m_double_prop[this.IndexProp(ACCOUNT_PROP_COMMISSION_BLOCKED)]=::AccountInfoDouble(ACCOUNT_COMMISSION_BLOCKED); //--- 文字列プロパティを保存する this.m_string_prop[this.IndexProp(ACCOUNT_PROP_NAME)] = ::AccountInfoString(ACCOUNT_NAME); this.m_string_prop[this.IndexProp(ACCOUNT_PROP_SERVER)] = ::AccountInfoString(ACCOUNT_SERVER); this.m_string_prop[this.IndexProp(ACCOUNT_PROP_CURRENCY)] = ::AccountInfoString(ACCOUNT_CURRENCY); this.m_string_prop[this.IndexProp(ACCOUNT_PROP_COMPANY)] = ::AccountInfoString(ACCOUNT_COMPANY); //--- Account object name this.m_name=TextByLanguage("Счёт ","Account ")+(string)this.Login()+": "+this.Name()+" ("+this.Company()+")"; } //+-------------------------------------------------------------------+
ご覧のとおり、オブジェクト名は、口座テキスト、口座番号、クライアント名、および口座を提供している会社の名前で構成されています。
たとえば、私の名前でMetaQuotes-Demo口座の1つに接続すると、口座オブジェクト名は「Account 8550475: Artyom Trishkin (MetaQuotes Software Corp.)
」になります。
「names」変数値を簡単な口座名を表示するメソッドに入力します(以前は、変数は口座オブジェクトを設定したのと同じ方法で設定されていました)。
//+------------------------------------------------------------------+ //| Display a short account description in the journal | //+------------------------------------------------------------------+ void CAccount::PrintShort(void) { string mode=(this.MarginMode()==ACCOUNT_MARGIN_MODE_RETAIL_HEDGING ? ", Hedge" : this.MarginMode()==ACCOUNT_MARGIN_MODE_EXCHANGE ? ", Exhange" : ""); string names=this.m_name+" "; string values=::DoubleToString(this.Balance(),(int)this.CurrencyDigits())+" "+this.Currency()+", 1:"+(string)+this.Leverage()+mode+", "+this.TradeModeDescription()+" "+this.ServerTypeDescription(); ::Print(names,values); } //+------------------------------------------------------------------+
これでCAccountクラスの改善は終わりです。
それでは、口座コレクションクラスを改善しましょう。AccountsCollection.mqhファイルを開き、必要な変更を追加します。
口座コレクションクラス基本オブジェクトの役割を CBaseObj クラスに割り当てましょう。
//+------------------------------------------------------------------+ //| Account collection | //+------------------------------------------------------------------+ class CAccountsCollection : public CBaseObj { private:
クラスはオブジェクトイベントを追跡する機能を備えた基本オブジェクトから継承されるため、口座コレクションクラスから重複する変数とメソッドを削除します。
口座データ構造体で、ハッシュ合計フィールドを削除します。
struct MqlDataAccount { double hash_sum; // Account data hash sum //--- Account integer properties long login; // ACCOUNT_LOGIN (Account number) long leverage; // ACCOUNT_LEVERAGE (Leverage) int limit_orders; // ACCOUNT_LIMIT_ORDERS (Maximum allowed number of active pending orders) bool trade_allowed; // ACCOUNT_TRADE_ALLOWED (Permission to trade for the current account from the server side) bool trade_expert; // ACCOUNT_TRADE_EXPERT (Permission to trade for an EA from the server side) //--- Account real properties double balance; // ACCOUNT_BALANCE (Account balance in a deposit currency) double credit; // ACCOUNT_CREDIT (Credit in a deposit currency) double profit; // ACCOUNT_PROFIT (Current profit on an account in the account currency) double equity; // ACCOUNT_EQUITY (Equity on an account in the deposit currency) double margin; // ACCOUNT_MARGIN (Reserved margin on an account in a deposit currency) double margin_free; // ACCOUNT_MARGIN_FREE (Free funds available for opening a position in a deposit currency) double margin_level; // ACCOUNT_MARGIN_LEVEL (Margin level on an account in %) double margin_so_call; // ACCOUNT_MARGIN_SO_CALL (MarginCall) double margin_so_so; // ACCOUNT_MARGIN_SO_SO (StopOut) double margin_initial; // ACCOUNT_MARGIN_INITIAL (Funds reserved on an account to ensure a guarantee amount for all pending orders) double margin_maintenance; // ACCOUNT_MARGIN_MAINTENANCE (Funds reserved on an account to ensure a minimum amount for all open positions) double assets; // ACCOUNT_ASSETS (Current assets on an account) double liabilities; // ACCOUNT_LIABILITIES (Current liabilities on an account) double comission_blocked; // ACCOUNT_COMMISSION_BLOCKED (Current sum of blocked commissions on an account) };
privateクラスメンバ変数を削除します。
MqlTick m_tick; // Tick structure string m_symbol; // Current symbol long m_chart_id; // Control program chart ID CListObj m_list_accounts; // Account object list CArrayInt m_list_changes; // Account change list string m_folder_name; // Name of a folder account objects are stored int m_index_current; // Index of an account object featuring the current account data //--- Tracking account changes bool m_is_account_event; // Account data event flag int m_change_code; // Account change code
SetChangeCode()メソッドの名前をSetEventCode()に変更し、同じ型のメソッドの名前が異なるクラスで同じになるようにします。
SetTypeEvent()メソッドは、CBaseObjクラスで既に宣言されており、子孫で実装される必要があるため、仮想化する必要があります。
CBaseObjで既に実装されているため、クラスからIsPresentEventFlag()メソッドを削除します。
クラスpublicセクションの重複したメソッドを削除します。
GetEventCode()、GetListChanges()、SetChartID()各メソッドを削除します。 ENUM_ACCOUNT_EVENT GetEvent(const int shift=WRONG_VALUE)メソッドは以下のようになるはずです。
ENUM_ACCOUNT_EVENT GetEventID(const int shift=WRONG_VALUE,const bool check_out=true);
クラス本体の外部での実装をすぐに考えてみましょう。
//+------------------------------------------------------------------+ //| Return the account event by its number in the list | //+------------------------------------------------------------------+ ENUM_ACCOUNT_EVENT CAccountsCollection::GetEventID(const int shift=WRONG_VALUE,const bool check_out=true) { CEventBaseObj *event=this.GetEvent(shift,check_out); if(event==NULL) return ACCOUNT_EVENT_NO_EVENT; return (ENUM_ACCOUNT_EVENT)event.ID(); } //+------------------------------------------------------------------+
メソッドは、必要なイベントインデックス(最後のイベントインデックスの場合は-1)とイベントリストの境界を超えるインデックスを検出するフラグを受け取ります。
本稿の冒頭で検討したGetEvent()CBaseObj基本オブジェクトメソッドを使用してイベントオブジェクトを取得します。イベントがない場合は「イベントなし」を返します。あった場合はイベントIDを返します。
クラスコンストラクタの初期化リストで、銘柄設定を除くすべてのパラメータの初期化を削除し、口座オブジェクトファイルを保存するサブフォルダの名前を設定します。
//+------------------------------------------------------------------+ //| コンストラクタ | //+------------------------------------------------------------------+ CAccountsCollection::CAccountsCollection(void) : m_symbol(::Symbol()) { this.m_list_accounts.Clear(); this.m_list_accounts.Sort(SORT_BY_ACCOUNT_LOGIN); this.m_list_accounts.Type(COLLECTION_ACCOUNT_ID); ::ZeroMemory(this.m_struct_prev_account); ::ZeroMemory(this.m_tick); this.InitChangesParams(); this.InitControlsParams(); //--- Create the folder for storing account files this.SetSubFolderName("Accounts"); ::ResetLastError(); if(!::FolderCreate(this.m_folder_name,FILE_COMMON)) ::Print(DFUN,TextByLanguage("Не удалось создать папку хранения файлов. Ошибка ","Could not create file storage folder. Error "),::GetLastError()); //--- Create the current account object and add it to the list CAccount* account=new CAccount(); if(account!=NULL) { if(!this.AddToList(account)) { ::Print(DFUN_ERR_LINE,TextByLanguage("Ошибка. Не удалось добавить текущий объект-аккаунт в список-коллекцию.","Error. Failed to add current account object to collection list.")); delete account; } else account.PrintShort(); } else ::Print(DFUN,TextByLanguage("Ошибка. Не удалось создать объект-аккаунт с данными текущего счёта.","Error. Failed to create an account object with current account data.")); //--- Download account objects from the files to the collection this.LoadObjects(); //--- Save the current account index this.m_index_current=this.Index(); } //+------------------------------------------------------------------+
口座データを更新するためのRefresh()メソッドは、CBaseObjクラスで宣言され、その子孫で実装されるため、仮想化する必要があります。
メソッドの実装にいくつかの変更が加えられました。
//+------------------------------------------------------------------+ //| Update the current account data | //+------------------------------------------------------------------+ void CAccountsCollection::Refresh(void) { ::ResetLastError(); if(!::SymbolInfoTick(::Symbol(),this.m_tick)) { this.m_global_error=::GetLastError(); return; } if(this.m_index_current==WRONG_VALUE) return; CAccount* account=this.m_list_accounts.At(this.m_index_current); if(account==NULL) return; //--- Prepare event data this.m_is_event=false; ::ZeroMemory(this.m_struct_curr_account); this.m_hash_sum=0; this.SetAccountsParams(account); //--- 初回実行 if(!this.m_struct_prev_account.login) { this.m_struct_prev_account=this.m_struct_curr_account; this.m_hash_sum_prev=this.m_hash_sum; return; } //--- If the account hash sum changed if(this.m_hash_sum!=this.m_hash_sum_prev) { this.m_list_events.Clear(); this.m_event_code=this.SetEventCode(); this.SetTypeEvent(); int total=this.m_list_events.Total(); if(total>0) { this.m_is_event=true; for(int i=0;i<total;i++) { CEventBaseObj *event=this.GetEvent(i,false); if(event==NULL) continue; ENUM_ACCOUNT_EVENT event_id=(ENUM_ACCOUNT_EVENT)event.ID(); if(event_id==ACCOUNT_EVENT_NO_EVENT) continue; long lparam=event.LParam(); double dparam=event.DParam(); string sparam=event.SParam(); ::EventChartCustom(this.m_chart_id,(ushort)event_id,lparam,dparam,sparam); } } this.m_hash_sum_prev=this.m_hash_sum; } } //+------------------------------------------------------------------+
行った変更について考えてみましょう。
まず、銘柄で相場データを受信します(ミリ秒の時間を定義するため)。受信に失敗した場合、メソッドを終了します。
口座イベントフラグと現在のハッシュ合計値をリセットします。最初の起動時に、現在のハッシュ合計を以前のハッシュ合計として保存します。
ハッシュ合計を変更する場合、口座イベントリストをクリアして、銘柄イベントリストを受信するときに実行されるものと同様に、口座イベントリストからイベントを受信するためのアクションを実行します (上記)。
これで、CBaseObjから継承されたオブジェクトについて、イベントを受信するために実行されるアクションは同様になります。したがって、それらを取得するメソッドをもう一度よく理解しておくと、以降の記事ですべてが明確になり、オブジェクトイベントリストを取得するために実行したアクションの説明に戻る必要がなくなります。
口座オブジェクトおよび口座データ構造体に口座プロパティを保存するメソッドで、ハッシュ合計構造体フィールドへのアクセスをCBaseObjクラスのハッシュ合計変数で置き換えて、オブジェクト名を保存します。
//+------------------------------------------------------------------+ //| Write the current account data to the account object properties | //+------------------------------------------------------------------+ void CAccountsCollection::SetAccountsParams(CAccount *account) { if(account==NULL) return; //--- Name this.m_name=account.GetName(); //--- Account number this.m_struct_curr_account.login=account.Login(); //--- Leverage account.SetProperty(ACCOUNT_PROP_LEVERAGE,::AccountInfoInteger(ACCOUNT_LEVERAGE)); this.m_struct_curr_account.leverage=account.Leverage(); this.m_hash_sum+=(double)this.m_struct_curr_account.leverage; //--- Maximum allowed number of active pending orders account.SetProperty(ACCOUNT_PROP_LIMIT_ORDERS,::AccountInfoInteger(ACCOUNT_LIMIT_ORDERS)); this.m_struct_curr_account.limit_orders=(int)account.LimitOrders(); this.m_hash_sum+=(double)this.m_struct_curr_account.limit_orders; //--- Permission to trade for the current account from the server side account.SetProperty(ACCOUNT_PROP_TRADE_ALLOWED,::AccountInfoInteger(ACCOUNT_TRADE_ALLOWED)); this.m_struct_curr_account.trade_allowed=account.TradeAllowed(); this.m_hash_sum+=(double)this.m_struct_curr_account.trade_allowed; //--- Permission to trade for an EA from the server side account.SetProperty(ACCOUNT_PROP_TRADE_EXPERT,::AccountInfoInteger(ACCOUNT_TRADE_EXPERT)); this.m_struct_curr_account.trade_expert=account.TradeExpert(); this.m_hash_sum+=(double)this.m_struct_curr_account.trade_expert; //--- Account balance in a deposit currency account.SetProperty(ACCOUNT_PROP_BALANCE,::AccountInfoDouble(ACCOUNT_BALANCE)); this.m_struct_curr_account.balance=account.Balance(); this.m_hash_sum+=(double)this.m_struct_curr_account.balance; //--- Credit in a deposit currency account.SetProperty(ACCOUNT_PROP_CREDIT,::AccountInfoDouble(ACCOUNT_CREDIT)); this.m_struct_curr_account.credit=account.Credit(); this.m_hash_sum+=(double)this.m_struct_curr_account.credit; //--- Current profit on an account in the account currency account.SetProperty(ACCOUNT_PROP_PROFIT,::AccountInfoDouble(ACCOUNT_PROFIT)); this.m_struct_curr_account.profit=account.Profit(); this.m_hash_sum+=(double)this.m_struct_curr_account.profit; //--- Equity on an account in the deposit currency account.SetProperty(ACCOUNT_PROP_EQUITY,::AccountInfoDouble(ACCOUNT_EQUITY)); this.m_struct_curr_account.equity=account.Equity(); this.m_hash_sum+=(double)this.m_struct_curr_account.equity; //--- Reserved margin on an account in the deposit currency account.SetProperty(ACCOUNT_PROP_MARGIN,::AccountInfoDouble(ACCOUNT_MARGIN)); this.m_struct_curr_account.margin=account.Margin(); this.m_hash_sum+=(double)this.m_struct_curr_account.margin; //--- Free funds available for opening a position on an account in the deposit currency account.SetProperty(ACCOUNT_PROP_MARGIN_FREE,::AccountInfoDouble(ACCOUNT_MARGIN_FREE)); this.m_struct_curr_account.margin_free=account.MarginFree(); this.m_hash_sum+=(double)this.m_struct_curr_account.margin_free; //--- Margin level on an account in % account.SetProperty(ACCOUNT_PROP_MARGIN_LEVEL,::AccountInfoDouble(ACCOUNT_MARGIN_LEVEL)); this.m_struct_curr_account.margin_level=account.MarginLevel(); this.m_hash_sum+=(double)this.m_struct_curr_account.margin_level; //--- Margin Call level account.SetProperty(ACCOUNT_PROP_MARGIN_SO_CALL,::AccountInfoDouble(ACCOUNT_MARGIN_SO_CALL)); this.m_struct_curr_account.margin_so_call=account.MarginSOCall(); this.m_hash_sum+=(double)this.m_struct_curr_account.margin_so_call; //--- Stop Out level account.SetProperty(ACCOUNT_PROP_MARGIN_SO_SO,::AccountInfoDouble(ACCOUNT_MARGIN_SO_SO)); this.m_struct_curr_account.margin_so_so=account.MarginSOSO(); this.m_hash_sum+=(double)this.m_struct_curr_account.margin_so_so; //--- Funds reserved on an account to ensure a guarantee amount for all pending orders account.SetProperty(ACCOUNT_PROP_MARGIN_INITIAL,::AccountInfoDouble(ACCOUNT_MARGIN_INITIAL)); this.m_struct_curr_account.margin_initial=account.MarginInitial(); this.m_hash_sum+=(double)this.m_struct_curr_account.margin_initial; //--- Funds reserved on an account to ensure a minimum amount for all open positions account.SetProperty(ACCOUNT_PROP_MARGIN_MAINTENANCE,::AccountInfoDouble(ACCOUNT_MARGIN_MAINTENANCE)); this.m_struct_curr_account.margin_maintenance=account.MarginMaintenance(); this.m_hash_sum+=(double)this.m_struct_curr_account.margin_maintenance; //--- Current assets on an account account.SetProperty(ACCOUNT_PROP_ASSETS,::AccountInfoDouble(ACCOUNT_ASSETS)); this.m_struct_curr_account.assets=account.Assets(); this.m_hash_sum+=(double)this.m_struct_curr_account.assets; //--- Current liabilities on an account account.SetProperty(ACCOUNT_PROP_LIABILITIES,::AccountInfoDouble(ACCOUNT_LIABILITIES)); this.m_struct_curr_account.liabilities=account.Liabilities(); this.m_hash_sum+=(double)this.m_struct_curr_account.liabilities; //--- Current sum of blocked commissions on an account account.SetProperty(ACCOUNT_PROP_COMMISSION_BLOCKED,::AccountInfoDouble(ACCOUNT_COMMISSION_BLOCKED)); this.m_struct_curr_account.comission_blocked=account.ComissionBlocked(); this.m_hash_sum+=(double)this.m_struct_curr_account.comission_blocked; } //+------------------------------------------------------------------+
口座コレクションクラスの SetTypeEvent()メソッドが、オブジェクトのイベントを定義する機能により改善および変更されました。メソッドは大規模ですが、口座イベントタイプを定義するためのすべてのアクションは同じタイプです。これらは、銘柄イベントタイプの定義を分析したときに、すでに考慮されているため、口座での取引を有効にするイベントの例のみを提供します。メソッドの完全なコードは、本稿に添付されているファイルにあります。
//+------------------------------------------------------------------+ //| Set the account object event type | //+------------------------------------------------------------------+ void CAccountsCollection::SetTypeEvent(void) { this.InitChangesParams(); ENUM_ACCOUNT_EVENT event_id=ACCOUNT_EVENT_NO_EVENT; //--- Changing permission to trade for the account if(this.IsPresentEventFlag(ACCOUNT_EVENT_FLAG_TRADE_ALLOWED)) { if(!this.m_struct_curr_account.trade_allowed) { this.m_is_change_trade_allowed_off=true; event_id=ACCOUNT_EVENT_TRADE_ALLOWED_OFF; if(this.EventAdd(event_id,this.TickTime(),this.m_is_change_trade_allowed_off,this.m_name)) this.m_struct_prev_account.trade_allowed=this.m_struct_curr_account.trade_allowed; } else { this.m_is_change_trade_allowed_on=true; event_id=ACCOUNT_EVENT_TRADE_ALLOWED_ON; if(this.EventAdd(event_id,this.TickTime(),this.m_is_change_trade_allowed_on,this.m_name)) this.m_struct_prev_account.trade_allowed=this.m_struct_curr_account.trade_allowed; } } //--- Changing permission for auto trading for the account
これで、口座コレクションクラスの変更と改善が完了しました。次に、更新された銘柄および口座イベントクラスを機能させるときです。
覚えていっらしゃるかもしれませんが、すべての制御はCEngineクラスから始まり、すべてのデータもCEngineクラスに送信されます。銘柄および口座イベントクラスも例外ではありません。
銘柄イベントクラスと改善された口座クラスの使用
Engine.mqhファイルを開き、必要な変更を追加します。
クラスのprivateセクションで、銘柄イベントフラグと銘柄の最後のイベントの値を宣言します。
//+------------------------------------------------------------------+ //| ライブラリ基本クラス | //+------------------------------------------------------------------+ class CEngine : public CObject { private: CHistoryCollection m_history; // 過去の注文と取引のコレクション CMarketCollection m_market; // 注文と取引のコレクション CEventsCollection m_events; // Event collection CAccountsCollection m_accounts; // Account collection CSymbolsCollection m_symbols; // Symbol collection CArrayObj m_list_counters; // タイマーカウンタのリスト int m_global_error; // Global error code bool m_first_start; // 初期実行フラグ bool m_is_hedge; // ヘッジ勘定フラグ bool m_is_tester; // Flag of working in the tester bool m_is_market_trade_event; // 口座取引イベントフラグ bool m_is_history_trade_event; // 口座過去の取引イベントフラグ bool m_is_account_event; // Account change event flag bool m_is_symbol_event; // Symbol change event flag ENUM_TRADE_EVENT m_last_trade_event; // Last account trading event ENUM_ACCOUNT_EVENT m_last_account_event; // Last event in the account properties ENUM_SYMBOL_EVENT m_last_symbol_event; // Last event in the symbol properties //--- IDによるカウンタインデックスを返す
クラスのpublicセクションで、最後の取引イベントの説明を返すメソッドを宣言します。
//--- Return the list of historical (1) orders, (2) removed pending orders, (3) deals, //--- (4) all market orders of a position by its ID, (5) description of the last trading event CArrayObj *GetListHistoryOrders(void); CArrayObj *GetListHistoryPendings(void); CArrayObj *GetListDeals(void); CArrayObj *GetListAllOrdersByPosID(const ulong position_id); string GetLastTradeEventDescription(void);
また銘柄イベントを使用する新しいメソッドも宣言し、口座イベントフラグを返すメソッドを変更します。
//--- Return the list of (1) used symbols, (2) symbol events, (3) the last symbol change event //--- (4) the current symbol, (5) symbol event description, (6) Market Watch event description CArrayObj *GetListAllUsedSymbols(void) { return this.m_symbols.GetList(); } CArrayObj *GetListSymbolsEvents(void) { return this.m_symbols.GetListEvents(); } ENUM_SYMBOL_EVENT GetLastSymbolsEvent() { return this.m_symbols.GetLastEvent(); } CSymbol *GetSymbolCurrent(void); string GetSymbolEventDescription(ENUM_SYMBOL_EVENT event); string GetMWEventDescription(ENUM_SYMBOL_EVENT event) { return this.m_symbols.EventDescription(event); } string ModeSymbolsListDescription(void) { return this.m_symbols.ModeSymbolsListDescription(); } //--- Return the list of order, deal and position events CArrayObj *GetListAllOrdersEvents(void) { return this.m_events.GetList(); } //--- 直近の取引イベントをリセットする void ResetLastTradeEvent(void) { this.m_events.ResetLastTradeEvent(); } //--- Return the (1) last trading event, (2) the last event in the account properties, (3) hedging account flag, (4) flag of working in the tester ENUM_TRADE_EVENT LastTradeEvent(void) const { return this.m_last_trade_event; } ENUM_ACCOUNT_EVENT LastAccountEvent(void) const { return this.m_last_account_event; } ENUM_SYMBOL_EVENT LastSymbolsEvent(void) const { return this.m_last_symbol_event; } //--- Return the (1) hedge account, (2) working in the tester, (3) account event and (4) symbol event flag bool IsHedge(void) const { return this.m_is_hedge; } bool IsTester(void) const { return this.m_is_tester; } bool IsAccountsEvent(void) const { return this.m_accounts.IsEvent(); } bool IsSymbolsEvent(void) const { return this.m_symbols.IsEvent(); } //--- Return the (1) symbol object by name, as well as the code of the last event of (2) an account and (3) a symbol CSymbol *GetSymbolObjByName(const string name) { return this.m_symbols.GetSymbolByName(name); } int GetAccountEventsCode(void) const { return this.m_accounts.GetEventCode(); } int GetSymbolsEventsCode(void) const { return this.m_symbols.GetLastEventsCode(); } //--- Return the number of (1) symbols, (2) events in the symbol collection int GetSymbolsCollectionTotal(void) const { return this.m_symbols.GetSymbolsCollectionTotal(); } int GetSymbolsCollectionEventsTotal(void) const { return this.m_symbols.GetEventsTotal(); }
クラスコンストラクタの初期化リストで、銘柄コレクションの最後のイベントの初期化を追加します。
//+------------------------------------------------------------------+ //| CEngineコンストラクタ | //+------------------------------------------------------------------+ CEngine::CEngine() : m_first_start(true), m_last_trade_event(TRADE_EVENT_NO_EVENT), m_last_account_event(ACCOUNT_EVENT_NO_EVENT), m_last_symbol_event(SYMBOL_EVENT_NO_EVENT), m_global_error(ERR_SUCCESS) { this.m_is_hedge=#ifdef __MQL4__ true #else bool(::AccountInfoInteger(ACCOUNT_MARGIN_MODE)==ACCOUNT_MARGIN_MODE_RETAIL_HEDGING) #endif; this.m_is_tester=::MQLInfoInteger(MQL_TESTER); this.m_list_counters.Sort(); this.m_list_counters.Clear(); this.CreateCounter(COLLECTION_ORD_COUNTER_ID,COLLECTION_ORD_COUNTER_STEP,COLLECTION_ORD_PAUSE); this.CreateCounter(COLLECTION_ACC_COUNTER_ID,COLLECTION_ACC_COUNTER_STEP,COLLECTION_ACC_PAUSE); this.CreateCounter(COLLECTION_SYM_COUNTER_ID1,COLLECTION_SYM_COUNTER_STEP1,COLLECTION_SYM_PAUSE1); this.CreateCounter(COLLECTION_SYM_COUNTER_ID2,COLLECTION_SYM_COUNTER_STEP2,COLLECTION_SYM_PAUSE2); ::ResetLastError(); #ifdef __MQL5__ if(!::EventSetMillisecondTimer(TIMER_FREQUENCY)) { ::Print(DFUN_ERR_LINE,"Не удалось создать таймер. Ошибка: ","Could not create timer. Error: ",(string)::GetLastError()); this.m_global_error=::GetLastError(); } //---__MQL4__ #else if(!this.IsTester() && !::EventSetMillisecondTimer(TIMER_FREQUENCY)) { ::Print(DFUN_ERR_LINE,"Не удалось создать таймер. Ошибка: ","Could not create timer. Error: ",(string)::GetLastError()); this.m_global_error=::GetLastError(); } #endif } //+------------------------------------------------------------------+
クラスタイマーハンドラで、銘柄コレクションのブロックを処理するtimer 1およびtimer 2に変更を追加します。
//+------------------------------------------------------------------+ //| CEngineタイマー | //+------------------------------------------------------------------+ void CEngine::OnTimer(void) { //--- 過去の注文と取引、および成行注文とポジションの収集のタイマー int index=this.CounterIndex(COLLECTION_ORD_COUNTER_ID); if(index>WRONG_VALUE) { CTimerCounter* counter=this.m_list_counters.At(index); if(counter!=NULL) { //--- If this is not a tester if(!this.IsTester()) { //--- If unpaused, work with the order, deal and position collections events if(counter.IsTimeDone()) this.TradeEventsControl(); } //--- If this is a tester, work with collection events by tick else this.TradeEventsControl(); } } //--- Account collection timer index=this.CounterIndex(COLLECTION_ACC_COUNTER_ID); if(index>WRONG_VALUE) { CTimerCounter* counter=this.m_list_counters.At(index); if(counter!=NULL) { //--- If this is not a tester if(!this.IsTester()) { //--- If unpaused, work with the account collection events if(counter.IsTimeDone()) this.AccountEventsControl(); } //--- If this is a tester, work with collection events by tick else this.AccountEventsControl(); } } //--- Timer 1 of the symbol collection (updating symbol quote data in the collection) index=this.CounterIndex(COLLECTION_SYM_COUNTER_ID1); if(index>WRONG_VALUE) { CTimerCounter* counter=this.m_list_counters.At(index); if(counter!=NULL) { //--- If this is not a tester if(!this.IsTester()) { //--- If the pause is over, update quote data of all symbols in the collection if(counter.IsTimeDone()) this.m_symbols.RefreshRates(); } //--- In case of a tester, update quote data of all collection symbols by tick else this.m_symbols.RefreshRates(); } } //--- Timer 2 of the symbol collection (updating all data of all symbols in the collection and tracking symbl and symbol search events in the market watch window) index=this.CounterIndex(COLLECTION_SYM_COUNTER_ID2); if(index>WRONG_VALUE) { CTimerCounter* counter=this.m_list_counters.At(index); if(counter!=NULL) { //--- If this is not a tester if(!this.IsTester()) { //--- If the pause is over if(counter.IsTimeDone()) { //--- update data and work with events of all symbols in the collection this.SymbolEventsControl(); //--- When working with the market watch list, check the market watch window events if(this.m_symbols.ModeSymbolsList()==SYMBOLS_MODE_MARKET_WATCH) this.MarketWatchEventsControl(); } } //--- If this is a tester, work with events of all symbols in the collection by tick else this.SymbolEventsControl(); } } } //+------------------------------------------------------------------+
ここでは、timer 1カウンタが処理を完了した後、すべてのコレクション銘柄の相場データを更新する必要があるため、銘柄コレクションのRefreshRates()メソッドを呼び出します。timer 2カウンタ操作が完了したら、すべてのコレクション銘柄を完全に更新し、銘柄コレクションと[気配値表示]銘柄リストの両方で発生したイベントを追跡する必要があるため、CEngineクラスメソッドの SymbolEventsControl()を呼び出します。テスターで作業していない場合は MarketWatchEventsControl()も呼び出します。
以下は、銘柄コレクションイベントを使用するメソッドの実装です。
//+------------------------------------------------------------------+ //| Working with symbol collection events | //+------------------------------------------------------------------+ void CEngine::SymbolEventsControl(void) { this.m_symbols.SymbolsEventsControl(); this.m_is_symbol_event=this.m_symbols.IsEvent(); //--- If there are changes in symbol properties if(this.m_is_symbol_event) { //--- Get the last event of the symbol property change this.m_last_symbol_event=this.m_symbols.GetLastEvent(); } } //+------------------------------------------------------------------+
ここでは、銘柄コレクションメソッドのSymbolsEventsControl()を呼び出します。これは、銘柄コレクションイベントクラスについて説明する際に上記で検討したものです。メソッドの処理が完了すると、コレクション銘柄でイベントが検出された場合、銘柄コレクションクラスでイベントフラグが有効になります。フラグステータスは、CBaseObj 基本オブジェクトクラスのIsEvent() メソッドを使用して、m_is_symbol_event銘柄コレクションイベントフラグ変数に設定されます。 その値は呼び出し元プログラムで追跡されます。銘柄コレクションのイベントが登録されている場合、最後のイベントをm_last_symbol_event変数に書き込みます。その値は、呼び出し元プログラムで追跡することもできます。
以下は、[気配値表示]ウィンドウイベントを使用するメソッドの実装です。
//+------------------------------------------------------------------+ //| Working with symbol list events in the market watch window | //+------------------------------------------------------------------+ void CEngine::MarketWatchEventsControl(void) { if(this.IsTester()) return; this.m_symbols.MarketWatchEventsControl(); } //+------------------------------------------------------------------+
ここで、これがテスターの場合は終了し、そうでない場合は、[気配値表示]ウィンドウイベントを処理するための銘柄コレクションクラスのMarketWatchEventsControl()メソッドを呼び出します 。銘柄コレクションクラスイベントの追跡について説明する際に、上記のメソッドは既に検討しました。
以下は、最後の取引イベントの説明を返すメソッドの実装です。
//+------------------------------------------------------------------+ //| Return the description of the last trading event | //+------------------------------------------------------------------+ string CEngine::GetLastTradeEventDescription(void) { CArrayObj *list=this.m_events.GetList(); if(list!=NULL) { if(list.Total()==0) return TextByLanguage("С момента последнего запуска ЕА торговых событий не было","There have been no trade events since the last launch of EA"); CEvent *event=list.At(list.Total()-1); if(event!=NULL) return event.TypeEventDescription(); } return DFUN_ERR_LINE+TextByLanguage("Не удалось получить описание последнего торгового события","Failed to get the description of the last trading event"); } //+------------------------------------------------------------------+
ここでは、口座の取引イベントの完全なリストを取得します。リストを取得したがサイズがゼロの場合、「no trading events yet(取引イベントはまだありません)」メッセージを返します。そうでない場合はリストから最後のイベントを受診してその説明を返します。逆の場合、取引イベントの取得に失敗したことに関するメッセージを返します。
以下は、銘柄コレクションの最後のイベントの説明を返すメソッドです。
//+------------------------------------------------------------------+ //| Return the symbol event description | //+------------------------------------------------------------------+ string CEngine::GetSymbolEventDescription(ENUM_SYMBOL_EVENT event) { CArrayObj *list=this.m_symbols.GetList(); if(list!=NULL) { if(list.Total()==0) return TextByLanguage("С момента последнего запуска ЕА не было никаких событий символов","There have been no events of symbols since the last launch of EA"); CSymbol *symbol=list.At(list.Total()-1); if(symbol!=NULL) return symbol.EventDescription(event); } return DFUN_ERR_LINE+TextByLanguage("Не удалось получить описание события символа","Failed to get symbol's event description"); } //+------------------------------------------------------------------+
このメソッドは、先ほど検討した最後の取引イベントを返すメソッドと同様に機能します。
CEngineクラスの改善が完了しました。銘柄イベント、および更新された口座クラスと口座イベントをテストする準備がすべて整いました。
クラスにいくつかの追加の変更が加えられました。それらは主にいくつかのメソッドの名前に関連しているため、ここでは考慮されていません。これらは、異なるクラスの同じ型のメソッドが適切な場合は常に同じ名前を持つようにするために導入されました。ライブラリコードは常に進化しているため、これらのマイナーな改善点をすべて記事で説明する意味はないと思います。それらは本稿に添付されたファイルでいつでも見つけることができます。
銘柄イベントと口座イベントのテスト
テストには、前の記事のテストEAを\MQL5\Experts\TestDoEasy\にPart16\TestDoEasyPart16.mq5という名前で保存し、すべての必要な変更を加えます。
グローバル変数のリストで、銘柄リストの使用モードを保存するための変数を追加します。
//--- グローバル変数 CEngine engine; #ifdef __MQL5__ CTrade trade; #endif SDataButt butt_data[TOTAL_BUTT]; string prefix; double lot; double withdrawal=(InpWithdrawal<0.1 ?0.1 : InpWithdrawal); ulong magic_number; uint stoploss; uint takeprofit; uint distance_pending; uint distance_stoplimit; uint slippage; bool trailing_on; double trailing_stop; double trailing_step; uint trailing_start; uint stoploss_to_modify; uint takeprofit_to_modify; int used_symbols_mode; string used_symbols; string array_used_symbols[];
銘柄使用の「サーバ上の銘柄の完全なリストを使用する」モードを選択すると、最初の起動では、銘柄コレクションが既存のすべての銘柄のすべてのデータを収集する必要があるため、かなり時間がかかる場合があります。したがって、それについてユーザに警告する必要があります。ユーザがそれを行うように要求することだけを行うので、ライブラリ自体でそれを行うことは意味がありません。したがって、警告はプログラムのOnInit()ハンドラで行う必要があります。
次の方法でやってみましょう。EA設定でサーバで利用可能な銘柄の完全なリストを選択すると、プログラムは警告を含むMessageBox()関数による標準ウィンドウを表示します。
銘柄の完全なリストをダウンロードする場合は[Yes]を、現在の銘柄のみを使用する場合は[No]を選択するよう求められます。ユーザーは、[Yes]をクリックして、使用可能なすべての銘柄からコレクションが作成されるのを待つか、[No]をクリックして現在の銘柄を使用するかを選択するだけです。
EAのOnInit()ハンドラで質問を送信する機能を備えたチェックを準備しましょう。
//--- Check if working with the full list is selected used_symbols_mode=InpModeUsedSymbols; if((ENUM_SYMBOLS_MODE)used_symbols_mode==SYMBOLS_MODE_ALL) { int total=SymbolsTotal(false); string ru_n="\nКоличество символов на сервере "+(string)total+".\nМаксимальное количество: "+(string)SYMBOLS_COMMON_TOTAL+" символов."; string en_n="\nThe number of symbols on server "+(string)total+".\nMaximal number: "+(string)SYMBOLS_COMMON_TOTAL+" symbols."; string caption=TextByLanguage("Внимание!","Attention!"); string ru="Выбран режим работы с полным списком.\nВ этом режиме первичная подготовка списка коллекции символов может занять длительное время."+ru_n+"\nПродолжить?\n\"Нет\" - работа с текущим символом \""+Symbol()+"\""; string en="Full list mode selected.\nIn this mode, the initial preparation of the collection symbols list may take a long time."+en_n+"\nContinue?\n\"No\" - working with the current symbol \""+Symbol()+"\""; string message=TextByLanguage(ru,en); int flags=(MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2); int mb_res=MessageBox(message,caption,flags); switch(mb_res) { case IDNO : used_symbols_mode=SYMBOLS_MODE_CURRENT; break; default: break; } }
ここで、EA設定でユーザが選択した銘柄使用モードは、used_symbols_modeグローバル変数に割り当てられます。
完全なリストを使用して作業する場合、警告ウィンドウのテキストを作成し、画面にそのウィンドウを表示します。次に、ユーザがクリックしたボタンを確認します。いいえの場合、現在の銘柄使用モードがused_symbols_mode変数に割り当てられます。
残りの場合([Yes]ボタンまたはEsc)、使用可能な銘柄の完全なリストを使用するモードを終了します。
次に、使用されている銘柄の配列を作成します(配列作成関数にused_symbols_mode変数を送信)。
//--- Fill in the array of used symbols used_symbols=InpUsedSymbols; CreateUsedSymbolsArray((ENUM_SYMBOLS_MODE)used_symbols_mode,used_symbols,array_used_symbols);
ライブラリ内の使用されているリストのタイプを設定(銘柄使用モード)し、適用された銘柄使用モードに関するメッセージを操作ログに送信します。
//--- Set the type of the used symbol list in the symbol collection engine.SetUsedSymbols(array_used_symbols); //--- Displaying the selected mode of working with the symbol object collection Print(engine.ModeSymbolsListDescription(),TextByLanguage(". Количество используемых символов: ",". Number of symbols used: "),engine.GetSymbolsCollectionTotal());
銘柄コレクションの高速チェック用のコードブロックは、このテストEAでは必要ないため、OnInit()ハンドラから削除されます。
//--- Fast check of the symbol object collection
CArrayObj *list=engine.GetListAllUsedSymbols();
CSymbol *symbol=NULL;
if(list!=NULL)
{
int total=list.Total();
for(int i=0;i<total;i++)
{
symbol=list.At(i);
if(symbol==NULL)
continue;
symbol.Refresh();
symbol.RefreshRates();
symbol.PrintShort();
if(InpModeUsedSymbols<SYMBOLS_MODE_MARKET_WATCH)
symbol.Print();
}
}
OnTick()ハンドラに最後のイベントを銘柄コレクションに格納するための変数を追加し、口座および銘柄コレクションイベントを処理するブロックを記述します。
//+------------------------------------------------------------------+ //| エキスパートティック関数 | //+------------------------------------------------------------------+ void OnTick() { //--- Initializing the last events static ENUM_TRADE_EVENT last_trade_event=WRONG_VALUE; static ENUM_ACCOUNT_EVENT last_account_event=WRONG_VALUE; static ENUM_SYMBOL_EVENT last_symbol_event=WRONG_VALUE; //--- If working in the tester if(MQLInfoInteger(MQL_TESTER)) { engine.OnTimer(); PressButtonsControl(); } //--- If the last trading event changed if(engine.LastTradeEvent()!=last_trade_event) { last_trade_event=engine.LastTradeEvent(); Comment("\nLast trade event: ",engine.GetLastTradeEventDescription()); engine.ResetLastTradeEvent(); } //--- If there is an account event if(engine.IsAccountsEvent()) { //--- the last account event last_account_event=engine.LastAccountEvent(); //--- If this is a tester if(MQLInfoInteger(MQL_TESTER)) { //--- Get the list of all account events occurred simultaneously CArrayObj* list=engine.GetListAccountEvents(); if(list!=NULL) { //--- Get the next event in a loop int total=list.Total(); for(int i=0;i<total;i++) { //--- take an event from the list CEventBaseObj *event=list.At(i); if(event==NULL) continue; //--- Send an event to the event handler long lparam=event.LParam(); double dparam=event.DParam(); string sparam=event.SParam(); OnDoEasyEvent(CHARTEVENT_CUSTOM+event.ID(),lparam,dparam,sparam); } } } } //--- If there is a symbol collection event if(engine.IsSymbolsEvent()) { //--- the last event in the symbol collection last_symbol_event=engine.LastSymbolsEvent(); //--- If this is a tester if(MQLInfoInteger(MQL_TESTER)) { //--- Get the list of all symbol events occurred simultaneously CArrayObj* list=engine.GetListSymbolsEvents(); if(list!=NULL) { //--- Get the next event in a loop int total=list.Total(); for(int i=0;i<total;i++) { //--- take an event from the list CEventBaseObj *event=list.At(i); if(event==NULL) continue; //--- Send an event to the event handler long lparam=event.LParam(); double dparam=event.DParam(); string sparam=event.SParam(); OnDoEasyEvent(CHARTEVENT_CUSTOM+event.ID(),lparam,dparam,sparam); } } } } //--- If the trailing flag is set if(trailing_on) { TrailingPositions(); TrailingOrders(); } } //+------------------------------------------------------------------+
ここではすべてが簡単です。口座および銘柄コレクションイベントを処理するために必要なすべてのアクションは、コードでコメントされています。
ご覧のとおり、イベント処理は、口座および銘柄コレクションの両方で、すべてのオブジェクトで同様になりました。結局、イベントのリストを受信し、リストからイベントライブラリを処理するEAのOnDoEasyEvent()ハンドラに新しいイベントを送信することになります。これは、CBaseObj基本オブジェクトからライブラリオブジェクトを継承する変更により、子孫オブジェクトのイベントの処理が実装されたことにより可能になりました。
OnDoEasyEvent() EAハンドラで、銘柄コレクションイベントを処理するコードを追加します。
//+------------------------------------------------------------------+ //| Handling DoEasy library events | //+------------------------------------------------------------------+ void OnDoEasyEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { int idx=id-CHARTEVENT_CUSTOM; string event="::"+string(idx); int digits=Digits(); //--- Handling trading events if(idx>TRADE_EVENT_NO_EVENT && idx<TRADE_EVENTS_NEXT_CODE) { event=EnumToString((ENUM_TRADE_EVENT)ushort(idx)); digits=(int)SymbolInfoInteger(sparam,SYMBOL_DIGITS); } //--- Handling account events else if(idx>ACCOUNT_EVENT_NO_EVENT && idx<ACCOUNT_EVENTS_NEXT_CODE) { Print(TimeMSCtoString(lparam)," ",sparam,": ",engine.GetAccountEventDescription((ENUM_ACCOUNT_EVENT)idx)); //--- if this is an equity increase if((ENUM_ACCOUNT_EVENT)idx==ACCOUNT_EVENT_EQUITY_INC) { //--- Close a position with the highest profit exceeding zero when the equity exceeds the value, //--- specified in the CAccountsCollection::InitControlsParams() method for //--- the m_control_equity_inc variable tracking the equity growth by 15 units (by default) //--- AccountCollection file, InitControlsParams() method, string 1199 //--- すべてのポジションのリストを取得する CArrayObj* list_positions=engine.GetListMarketPosition(); //--- Select positions with the profit exceeding zero list_positions=CSelect::ByOrderProperty(list_positions,ORDER_PROP_PROFIT_FULL,0,MORE); if(list_positions!=NULL) { //--- 手数料とスワップを考慮して、リストを利益順に並べ替える list_positions.Sort(SORT_BY_ORDER_PROFIT_FULL); //--- Get the position index with the highest profit int index=CSelect::FindOrderMax(list_positions,ORDER_PROP_PROFIT_FULL); if(index>WRONG_VALUE) { COrder* position=list_positions.At(index); if(position!=NULL) { //--- Get a ticket of a position with the highest profit and close the position by a ticket #ifdef __MQL5__ trade.PositionClose(position.Ticket()); #else PositionClose(position.Ticket(),position.Volume()); #endif } } } } } //--- Handling symbol events else if(idx>SYMBOL_EVENT_NO_EVENT && idx<SYMBOL_EVENTS_NEXT_CODE) { string name=""; //--- Market Watch window event if(idx<SYMBOL_EVENT_TRADE_DISABLE) { string descr=engine.GetMWEventDescription((ENUM_SYMBOL_EVENT)idx); name=(idx==SYMBOL_EVENT_MW_SORT ? "" : ": "+sparam); Print(TimeMSCtoString(lparam)," ",descr,name); } //--- Symbol event else { CSymbol *symbol=engine.GetSymbolObjByName(sparam); if(symbol!=NULL) { string descr=": "+symbol.EventDescription((ENUM_SYMBOL_EVENT)ushort(idx)); Print(TimeMSCtoString(lparam)," ",sparam,descr); } } } } //+------------------------------------------------------------------+
ここにあるのは、[気配値表示]ウィンドウイベントの処理およびコレクション銘柄イベントの処理の2つのオプションのみです。
[気配値表示]ウィンドウイベントに対しては、
必要なメッセージを作成して操作ログに送信します。
銘柄イベントに対しては、
「sparam」文字列イベントパラメータから取得した名前でリストから銘柄を受け取り、銘柄オブジェクトからイベントの文字列説明を取得し、作成したテキストに追加し、操作ログにテキストを送信します。
テストのためには他の追加アクションは実装しません。
これでテストEAの変更が完了しました。
EAの全コードは添付ファイルにあります。
デモ口座でEAを起動すると、しばらくすると銘柄プロパティの変更に関連するエントリが表示されます。たとえば、月曜日に取引セッションを開く前夜にEAを起動すると、さまざまな銘柄のスプレッドの変更に関する複数のエントリが操作ログに表示され始めます。
以下の例では、銘柄スプレッドの変更に関する次のメッセージが1時間以内に4つの[気配値表示]銘柄についてのみ操作ログに表示されます。
2019.07.15 04:02:24.167 TestDoEasyPart16 (EURUSD,H4) Working with symbols from the "Market Watch" window. The number of symbols used: 4 2019.07.15 04:02:25.762 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:02:27.316 GBPUSD: Spread value in points decreased by -7 (351) 2019.07.15 04:02:31.259 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:02:32.676 USDCHF: Spread value in points increased by 4 (287) 2019.07.15 04:02:33.761 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:02:35.218 USDCHF: Spread value in points decreased by -4 (283) 2019.07.15 04:02:46.261 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:02:47.680 USDCHF: Spread value in points increased by 4 (287) 2019.07.15 04:02:48.761 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:02:50.222 USDCHF: Spread value in points decreased by -4 (283) 2019.07.15 04:02:53.760 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:02:55.305 USDCHF: Spread value in points increased by 4 (287) 2019.07.15 04:02:56.760 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:02:58.221 USDCHF: Spread value in points decreased by -4 (283) 2019.07.15 04:03:01.261 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:03:02.683 USDCHF: Spread value in points increased by 4 (287) 2019.07.15 04:03:03.760 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:03:05.226 USDCHF: Spread value in points decreased by -4 (283) 2019.07.15 04:03:16.260 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:03:17.673 USDCHF: Spread value in points increased by 4 (287) 2019.07.15 04:03:18.789 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:03:20.219 USDCHF: Spread value in points decreased by -4 (283) 2019.07.15 04:03:30.832 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:03:32.686 USDCHF: Spread value in points increased by 4 (287) 2019.07.15 04:03:33.819 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:03:35.219 USDCHF: Spread value in points decreased by -4 (283) 2019.07.15 04:03:38.820 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:03:39.926 USDCHF: Spread value in points increased by 4 (287) 2019.07.15 04:03:41.821 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:03:43.221 USDCHF: Spread value in points decreased by -4 (283) 2019.07.15 04:03:45.820 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:03:47.673 USDCHF: Spread value in points increased by 4 (287) 2019.07.15 04:03:48.836 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:03:50.234 USDCHF: Spread value in points decreased by -4 (283) 2019.07.15 04:03:50.865 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:03:52.598 USDCHF: Spread value in points increased by 51 (334) 2019.07.15 04:03:58.867 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:04:00.450 EURUSD: Spread value in points decreased by -42 (50) 2019.07.15 04:03:58.868 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:04:00.430 USDCHF: Spread value in points decreased by -96 (238) 2019.07.15 04:03:59.417 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:04:00.934 USDCHF: Spread value in points increased by 22 (260) 2019.07.15 04:03:59.912 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:04:01.431 USDCHF: Spread value in points decreased by -5 (255) 2019.07.15 04:04:35.445 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:04:36.984 GBPUSD: Spread value in points decreased by -112 (239) 2019.07.15 04:04:35.445 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:04:36.985 EURUSD: Spread value in points decreased by -7 (43) 2019.07.15 04:04:35.445 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:04:36.984 USDCHF: Spread value in points decreased by -127 (128) 2019.07.15 04:04:58.460 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:05:00.102 GBPUSD: Spread value in points decreased by -207 (32) 2019.07.15 04:04:58.959 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:05:00.696 EURUSD: Spread value in points decreased by -4 (39) 2019.07.15 04:05:01.006 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:05:02.697 EURUSD: Spread value in points increased by 3 (42) 2019.07.15 04:05:02.037 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:05:03.686 EURUSD: Spread value in points decreased by -32 (10)
... 途中省略 ...
2019.07.15 04:55:09.780 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:55:11.578 GBPUSD: Spread value in points decreased by -3 (29) 2019.07.15 04:55:09.780 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:55:11.478 USDCHF: Spread value in points increased by 4 (32) 2019.07.15 04:55:10.482 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:55:11.681 USDCHF: Spread value in points decreased by -3 (29) 2019.07.15 04:55:11.623 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:55:13.477 USDCHF: Spread value in points increased by 3 (32) 2019.07.15 04:55:12.111 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:55:13.884 USDCHF: Spread value in points decreased by -5 (27) 2019.07.15 04:55:13.626 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:55:15.275 USDCHF: Spread value in points increased by 4 (31) 2019.07.15 04:55:19.628 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:55:21.381 USDCHF: Spread value in points decreased by -3 (28) 2019.07.15 04:55:20.126 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:55:21.882 USDCHF: Spread value in points increased by 3 (31) 2019.07.15 04:55:28.659 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:55:30.292 EURUSD: Spread value in points increased by 3 (20) 2019.07.15 04:55:33.690 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:55:35.298 EURUSD: Spread value in points decreased by -3 (17) 2019.07.15 04:55:53.298 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:55:55.137 EURUSD: Spread value in points increased by 3 (20) 2019.07.15 04:55:53.826 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:55:55.643 EURUSD: Spread value in points decreased by -3 (17) 2019.07.15 04:55:54.906 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:55:56.632 USDCHF: Spread value in points decreased by -3 (28) 2019.07.15 04:55:55.912 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:55:57.536 USDCHF: Spread value in points increased by 4 (32) 2019.07.15 04:55:56.907 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:55:58.636 USDCHF: Spread value in points decreased by -4 (28) 2019.07.15 04:55:57.434 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:55:58.832 USDCHF: Spread value in points increased by 4 (32) 2019.07.15 04:55:59.949 TestDoEasyPart16 (EURUSD,H4) 2019.07.15 00:56:01.538 USDCHF: Spread value in points decreased by -3 (29)
次に、2つの銘柄を使用してテスターでEAを起動し、表示されるエントリを確認します。
テスターの設定で、使用する銘柄のモードのリストEA入力パラメータで、Working with the specified symbol listをドロップダウンリストから選択し、使用される銘柄のリスト(コンマ-区切り記号)パラメータで、コンマで区切られた2つの銘柄EURUSD,GBPUSDを入力し、視覚EAテストを起動します。
両方の銘柄のイベントに関するエントリ(特に、使用されている銘柄のスプレッドの変更に関連するもの)が操作ログに送信されます。口座のプロパティを変更すると(この場合、現在の利益の増加です)、適切なエントリが操作ログに送信され、収益性の高いポジションが決済されます。
次の段階
次の記事では、CBaseObj基本オブジェクトクラスに基づいて、プログラムから制御および追跡対象のオブジェクトプロパティの値を変更するための便利なアクセスを実装します。
現在のバージョンのライブラリのすべてのファイルは、テスト用EAファイルと一緒に以下に添付されているので、テストするにはダウンロードしてください。
質問、コメント、提案はコメント欄にお願いします。
シリーズのこれまでの記事:
第1部: 概念、データ管理第2部: 過去の注文と取引のコレクション
第3部:注文と取引のコレクション、検索と並び替え
第4部: 取引イベント概念
第5部: 取引イベントのクラスとコレクション取引イベントのプログラムへの送信
第6部: ネッティング勘定イベント
第7部: StopLimit注文発動イベント、注文およびポジション変更イベントの機能の準備
第8部: 注文とポジションの変更イベント
第9部:MQL4との互換性 - データの準備
第10部:MQL4との互換性 - ポジションオープンイベントと指値注文発動イベント
第11部:MQL4との互換性 - ポジション決済イベント
第12部:口座オブジェクトクラスと口座オブジェクトコレクション
第13部:口座オブジェクトイベント>第14部銘柄オブジェクト
第15部銘柄オブジェクトコレクション
MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/7071





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