記事"MetaTraderプログラムを簡単かつ迅速に開発するためのライブラリ(第4部)MQL4との互換性 - ポジション決済イベント"についてのディスカッション

 

新しい記事 MetaTraderプログラムを簡単かつ迅速に開発するためのライブラリ(第4部)MQL4との互換性 - ポジション決済イベント はパブリッシュされました:

MetaTrader 5およびMetaTrader 4プラットフォーム用のプログラムの開発を簡素化する大規模なクロスプラットフォームライブラリの開発を継続します。第10部では、MQL4とのライブラリの互換性に関する作業を再開し、ポジションを開くイベントと未決注文の発動イベントを定義しました。本稿では、ポジション決済イベントを定義し、未使用の注文プロパティを取り除きます。

部分決済イベントと未決注文削除イベントは、個別のイベントとして定義されています。

EAをもう一度起動し、イベントの定義を確認するボタンをクリックします。



ご覧のとおり、イベントは正しく定義されています。「close by」イベントが定義され、ストップレベルの変更と未決注文価格も追跡されています。

作者: Artyom Trishkin

 

ミリ秒単位の時間変数の影響、特にMQL5バージョンに関するCHistoryCollection::GetListByTime(...) 関数について、いくつか指摘があります。

それらは(関連性の高いものから順に)です:

1) datetime 変数も長い ミリ秒時間変数も、1970年01月01日からの経過時間を表します。しかし、実際に格納される値の間には1000のファクターがあります。したがって、両方の型を直接代入することはできません。結果として、GetListByTime(...)はCOrder m_order_instanceの time millisecondプロパティに直接datetime パラメータを格納するため、変更後に動作しなくなりました。可能な解決策は、(おそらくdelib.mqhに)2つの新しい変換関数を追加して、この1000ファクターを処理することです:

//+------------------------------------------------------------------+
//| ミリ秒単位の時間をdatetimeに変換する。
//+------------------------------------------------------------------+
datetime TimeMSCtoDate(const long time_msc)
  {
   return datetime(time_msc/1000);
  }
//+------------------------------------------------------------------+
//| 日時をミリ秒単位で時間に変換する。
//+------------------------------------------------------------------+
long DatetoTimeMSC(const datetime time_sec)
  {
   return long(time_sec * 1000);
  }
もしMetaQuotesが最初からdatetime 変数をミリ秒単位、あるいはマイクロ秒単位で経過時間を定義していれば、この種の問題は起きなかっただろう(10年後にロボットがミリ秒未満で取引しないとは誰が言ったのだろうか?)
いずれにせよ、この問題は少なくともCEventsCollectionと CMarketCollection クラスのGetListByTime(...) 関数にも存在し、おそらく他の場所にも存在します...
2) Historyコレクションは、それがソートされているかどうか、ソートされている場合、ソートプロパティはどれか(.SortMode() 関数)を知っているオブジェクトですが、GetListByTime(...) 関数は、コレクションがすでに ORDER_PROP_TIME_OPEN またはORDER_PROP_TIME_CLOSE プロパティ(CEventsCollectionと CMarketCollectionの バージョンではORDER_PROP_TIME_OPENだけ)によってソートされていると仮定します。OOPの哲学に従って、GetListByTime(...)は、先に進む前にコレクションが適切にソートされているかどうかをチェックすべきである。
実際のところ、プログラム例TestDoEasyPart03_1.mq5 は、ORDER_PROP_TIME_OPEN(MT5 のデフォルト)で並べ替えられた履歴コレクションを作成し、GetListByTime(...,SELECT_BY_TIME_CLOSE)を 呼び出します。このチェックで、これが表示されたはずだ!
3) 大したことではないが、MT5が新しい標準になるはずなので、SELECT_BY_TIME_OPENを CHistoryCollection::GetListByTime(...) 関数のselect_time_mode パラメータのデフォルト値にするのはどうだろうか?

前者の提案に従えば、これはCHistoryCollection::GetListByTime(...) 関数のコードになる:

public:
        .......

   //--- begin_timeからend_timeまでの時間を持つコレクションから注文を選択する。
   CArrayObj        *GetListByTime(const datetime begin_time=0,const datetime end_time=0,
                                   const ENUM_SELECT_BY_TIME select_time_mode=SELECT_BY_TIME_OPEN);
        .......

//+------------------------------------------------------------------+
//| 時間|を含むコレクションから注文を選択する。
| 開始時刻から終了時刻まで|
//+------------------------------------------------------------------+
CArrayObj *CHistoryCollection::GetListByTime(const datetime begin_time=0,const datetime end_time=0,
                                             const ENUM_SELECT_BY_TIME select_time_mode=SELECT_BY_TIME_OPEN)
  {
   ENUM_ORDER_PROP_INTEGER property=(select_time_mode==SELECT_BY_TIME_CLOSE ? ORDER_PROP_TIME_CLOSE : ORDER_PROP_TIME_OPEN);
   
   if(property != (ENUM_ORDER_PROP_INTEGER)m_list_all_orders.SortMode())
      {
      ::Print(DFUN+"History list not prpperly sorted");           //ENUM_MESSAGES_LIBに追加するメッセージもある。
      return NULL;
      }

   CArrayObj *list=new CArrayObj();
   if(list==NULL)
     {
      ::Print(DFUN+CMessage::Text(MSG_LIB_SYS_FAILED_CREATE_TEMP_LIST));
      return NULL;
     }
   datetime begin=begin_time,end=(end_time==0 ? END_TIME : end_time);
   if(begin_time>end_time) begin=0;
   list.FreeMode(false);
   ListStorage.Add(list);
   //---
   this.m_order_instance.SetProperty(property,DatetoTimeMSC(begin));
   int index_begin=this.m_list_all_orders.SearchGreatOrEqual(&m_order_instance);
   if(index_begin==WRONG_VALUE)
      return list;
   this.m_order_instance.SetProperty(property,DatetoTimeMSC(end));
   int index_end=this.m_list_all_orders.SearchLessOrEqual(&m_order_instance);
   if(index_end==WRONG_VALUE)
      return list;
   for(int i=index_begin; i<=index_end; i++)
      list.Add(this.m_list_all_orders.At(i));
   return list;
  }



 
Alvaro Arioni :

ミリ秒単位の時間変数の影響、特にMQL5バージョンに関するCHistoryCollection::GetListByTime(...) 関数について、いくつか指摘があります。

それらは(関連性の高いものから順に)です:

1) datetime 変数も長い ミリ秒時間変数も、1970年01月01日からの経過時間を表します。しかし、実際に格納される値の間には1000のファクターがあります。したがって、両方の型を直接代入することはできません。その結果、GetListByTime(...)はCOrder m_order_instance の time millisecond プロパティにdatetime パラメータを直接格納するため、変更後に動作しなくなりました。可能な解決策は、(おそらくdelib.mqhに)2つの新しい変換関数をインクルードして、その1000ファクターを処理することです:

もしMetaQuotesが最初からdatetime 変数をミリ秒単位、あるいはマイクロ秒単位で経過時間を定義していれば、このような問題は起きなかったでしょう(10年後にロボットがミリ秒未満で取引しないとは誰が言ったのでしょうか)。
いずれにせよ、この問題は少なくともCEventsCollectionと CMarketCollection クラスのGetListByTime(...) 関数にも存在し、おそらく他の場所にも存在する
...

2) Historyコレクションは、ソートされているかどうか、ソートされている場合はどのソート・プロパティかを知っているオブジェクトである(.一方、GetListByTime(...) 関数は、コレクションがすでに ORDER_PROP_TIME_OPEN またはORDER_PROP_TIME_CLOSE プロパティ(CEventsCollectionと CMarketCollectionの バージョンではORDER_PROP_TIME_OPENだけ)によってソートされていると仮定します。OOPの哲学に従って、GetListByTime(...)は、先に進む前にコレクションが適切にソートされているかどうかをチェックする必要があります。
実際のところ、プログラム例TestDoEasyPart03_1.mq5 は、ORDER_PROP_TIME_OPEN(MT5 のデフォルト) で並べ替えられた履歴コレクションを作成し、GetListByTime(...,SELECT_BY_TIME_CLOSE) を呼び出します。このチェックで、これは表示されたはずです!
3) 大したことではないが、MT5が新しい標準になるはずなので、CHistoryCollection::GetListByTime(...) 関数のselect_time_mode パラメータのデフォルト値をSELECT_BY_TIME_OPENに したらどうだろうか?

前者の提案に従えば、これはCHistoryCollection::GetListByTime(...) 関数のコードになる:



ありがとうございます。ライブラリのその後のバージョン(XI上の記事)では、時間変換がすでに使用されているようです(私は一般的にdatetimeのままにしていました - すべてがlongになっています)。

私はコレクションについて少し理解していませんでした - 間違ったソートの例を示してください。利用可能な最新の記事で望ましい(記事は、ライブラリを作成するシーケンスを記述し、すべてが変更されるので)