記事"MetaTraderプログラムを簡単かつ迅速に開発するためのライブラリ(第10部): MQL4との互換性 - ポジションオープンイベントと指値注文発動イベント"についてのディスカッション - ページ 3

 
Alexey Viktorov:

アルテム、強調されているコードの部分がどのような役割を果たしているのか教えてほしい。

タイマーが有効になっていない場合、このコードはどのように実行されるのでしょうか?

しかし、このコードセクションを削除すると、イベントメッセージが表示されなくなります。しかし、このコードですべてが機能します。

そして、イベント・メッセージと一緒に、チケット、価格、そしてポジションとオーダーの 他のプロパティを 取得できるようにしたいのです。

コメントを変更したようですね。OnTimer() では、EAは テスターではなく テストされます:

/************************Expert tick function************************/
void OnTick()
{
//--- 最後の取引イベントの初期化
   static ENUM_TRADE_EVENT last_event=WRONG_VALUE;
//--- テスターで作業する場合
   if(MQLInfoInteger(MQL_TESTER))
     {
      engine.OnTimer();
     }
//--- 最後の取引イベントが変更された場合
   if(engine.LastTradeEvent()!=last_event)
     {
      last_event=engine.LastTradeEvent();
      Comment("last_event: ",EnumToString(last_event));
      Print(__FUNCTION__, " last_event: ",EnumToString(last_event));
      //engine.ResetLastTradeEvent();
      //Print("last_event: ",EnumToString(last_event));
     }

}
/***************************Timer function***************************/
void OnTimer()
{
//--- 最後の取引イベントの初期化
   static ENUM_TRADE_EVENT last_event=WRONG_VALUE;
//--- もし ジョブが  в тестере
   if(!MQLInfoInteger(MQL_TESTER))
     {
      engine.OnTimer();
     }
}
/*******************************************************************/

OnTick() ではライブラリタイマーはテスターでのみ 開始され、OnTimer() ではライブラリタイマーはテスターでは 開始さ れません

これから例を作ってみます。

 
Artyom Trishkin:

コメント変えたんじゃない?

コメントが勝手に変わっただけで、私は触っていません))))))

一箇所コピーして、違う場所に貼り付けただけで、気にしていませんでした。しかし、その後!の形で否定を入れて、重要ではありませんでした触れませんでした。

OnInit()でタイマーが開始されないのなら、OnTimer()ハンドラの意味は何なのか、なぜその中のコードが少なくとも1回は実行されるのか。

基本的に、ログへのメッセージは取得できました。あとはアイテムのプロパティを 取得するだけです。種類、チケット、価格、開店、閉店、変更の時間。

 
Alexey Viktorov:

そして、イベント・メッセージと共に、チケット、価格、そしてポジションや注文の 他のプロパティを 取得できるようにしたいです。

テスターでは、OnChartEvent() - パラメータ lparam.dparam には価格が格納されます。sparamにはシンボルが格納されます。

テスターでデータを取得するには、現在のところ、engine.LastTradeEvent() で取得したイベントコードを使用する必要があります - すべてがイベントに依存しているためです - 変更であれば、変更のリストを取得する必要があり、注文数の変更であれば、これらの新しい注文のリストを取得する必要があります。

必要な値をプログラムに返すために、CEngineを追加する必要がある。まだ、プログラムに情報を送るところまでは行っていません。必要なデータの準備について説明しているところです。今後の記事で、必要なデータすべてに簡単にアクセスできるクラスに到達する予定です。そして、もし緊急に必要であれば、CEngineにイベントのクラスコレクションからリストを返す機能を追加する必要があります:

public:
//--- begin_timeからend_timeの範囲の時間を持つイベントをコレクションから選択する。
   CArrayObj        *GetListByTime(const datetime begin_time=0,const datetime end_time=0);
//--- イベントの完全なリスト・コレクションを "そのまま "返す。
   CArrayObj        *GetList(void)                                                                       { return &this.m_list_events;                                           }
//--- 比較される基準を満たす、選択された (1) 整数、(2) 実数、および (3) 文字列プロパティによるリストを返す。
   CArrayObj        *GetList(ENUM_EVENT_PROP_INTEGER property,long value,ENUM_COMPARER_TYPE mode=EQUAL)  { return CSelect::ByEventProperty(this.GetList(),property,value,mode);  }
   CArrayObj        *GetList(ENUM_EVENT_PROP_DOUBLE property,double value,ENUM_COMPARER_TYPE mode=EQUAL) { return CSelect::ByEventProperty(this.GetList(),property,value,mode);  }
   CArrayObj        *GetList(ENUM_EVENT_PROP_STRING property,string value,ENUM_COMPARER_TYPE mode=EQUAL) { return CSelect::ByEventProperty(this.GetList(),property,value,mode);  }

すべてのイベントはm_list_eventsリストに格納され、これらのメソッドは、完全なリストか、与えられた基準によってフィルタリングされたリストを返します。

最後のイベントを取得するには、CEngine でこのリストをプログラムに返し、プログラムでリストから必要なイベントを取り出せば十分です。

この作業はもうすぐ自動化されます。

もしまだ松葉杖を作る必要があるのなら、プライベートで話し合ってください。ここでは意味がありません - ライブラリーには適用されません。開発中であり、さらに通常の適切な作業が行われ、プログラムにすべての、そして必要なイベントが含まれるようになります。

 
Alexey Viktorov:

コメントは勝手に変わりました、触ってません。)

一箇所コピーして、違う場所に貼り付けただけで、気にしていませんでした。でも、「!」の形で否定を入れただけで、肝心なところには手をつけていません。

OnInit()でタイマーをスタートさせないの なら、OnTimer()ハンドラーに何の意味があるのか、なぜその中のコードが少なくとも一度は実行されるのか。

基本的に、ログへのメッセージは取得できました。あとはアイテムのプロパティを 取得するだけです。タイプ、チケット、価格、オープン、クローズ、変更の時間。

どういう意味か説明してください。タイマーを作るということですか?CEngineのコンストラクタで作成 します:

//+------------------------------------------------------------------+
//| CEngineコンストラクタ|
//+------------------------------------------------------------------+
CEngine::CEngine() : m_first_start(true),m_last_trade_event(TRADE_EVENT_NO_EVENT)
  {
   this.m_list_counters.Sort();
   this.m_list_counters.Clear();
   this.CreateCounter(COLLECTION_COUNTER_ID,COLLECTION_COUNTER_STEP,COLLECTION_PAUSE);
   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);
   ::ResetLastError();
   #ifdef __MQL5__
      if(!::EventSetMillisecondTimer(TIMER_FREQUENCY))
         ::Print(DFUN,「タイマーの作成に失敗しました。エラー: ","Could not create timer. Error: ",(string)::GetLastError());
   //---__MQL4__
   #else 
      if(!this.IsTester() && !::EventSetMillisecondTimer(TIMER_FREQUENCY))
         ::Print(DFUN,「タイマーの作成に失敗しました。エラー: ","Could not create timer. Error: ",(string)::GetLastError());
   #endif 
  }
//+------------------------------------------------------------------+
 
Artyom Trishkin:

テスターでは、OnChartEvent()- パラメータ lparam で、最後のイベントのオーダーチケットを取得することはできません。dparamには価格が格納されます。sparamにはシンボルが格納されます。

すでに見つけました。そして、チケットを取得することによって、必要なすべてを得ることができます。どのような価格から修正があった場合を除きます。または修正前の価格を知るために本当の松葉杖を作る。原則として、それはまだ非常に必要ではありません。

 
Alexey Viktorov:

基本的にログメッセージは受け取った。私はポジションのプロパティを 取得する必要があります。種類、チケット、価格、オープン、クローズ、変更の時間。

手っ取り早く解決するには、CEngine の publicセクションにイベント・リスト・リターンを 追加します:

public:
   //--- マーケットの (1) ポジション、(2) 保留注文、(3) 成行注文のリストを返す。
   CArrayObj*           GetListMarketPosition(void);
   CArrayObj*           GetListMarketPendings(void);
   CArrayObj*           GetListMarketOrders(void);
   //--- 過去の (1) 注文、(2) 削除された未決注文、(3) 取引、(4) ポジションの全成行注文のリストを識別子で返す。
   CArrayObj*           GetListHistoryOrders(void);
   CArrayObj*           GetListHistoryPendings(void);
   CArrayObj*           GetListDeals(void);
   CArrayObj*           GetListAllOrdersByPosID(const ulong position_id);
//--- イベントのリストを返す
   CArrayObj*           GetListAllEvents(void)                          { return this.m_events.GetList();      }
//--- 最後の取引イベントをリセットする
   void                 ResetLastTradeEvent(void)                       { this.m_events.ResetLastTradeEvent(); }
//--- (1) 最終売買イベント、(2) ヘッジ口座フラグ、(3) テスター動作フラグを返す。
   ENUM_TRADE_EVENT     LastTradeEvent(void)                      const { return this.m_last_trade_event;      }
   bool                 IsHedge(void)                             const { return this.m_is_hedge;              }
   bool                 IsTester(void)                            const { return this.m_is_tester;             }
//--- タイマー・カウンターを作成する
   void                 CreateCounter(const int id,const ulong frequency,const ulong pause);
//--- タイマー
   void                 OnTimer(void);
//--- コンストラクタ/デストラクタ
                        CEngine();
                       ~CEngine();
  };
//+------------------------------------------------------------------+

EAに次のコードを追加 します:

//+------------------------------------------------------------------+
//| エキスパートティック機能|
//+------------------------------------------------------------------+
void OnTick()
  {
//--- 最後の取引イベントの初期化
   static ENUM_TRADE_EVENT last_event=WRONG_VALUE;
//--- テスターで作業する場合
   if(MQLInfoInteger(MQL_TESTER))
     {
      engine.OnTimer();
      PressButtonsControl();
     }
//--- 最後の取引イベントが変更された場合
   if(engine.LastTradeEvent()!=last_event)
     {
      last_event=engine.LastTradeEvent();
      Comment("\nlast_event: ",EnumToString(last_event));
      CArrayObj* list=engine.GetListAllEvents();
      if(list!=NULL)
        {
         if(list.Total()>0)
           {
            CEvent* event=list.At(list.Total()-1);
            if(event!=NULL)
              {
               event.Print();
              }
           }
        }
     }
//--- 後続フラグがセットされている場合
   if(trailing_on)
     {
      TrailingPositions();
      TrailingOrders();
     }
  }
//+------------------------------------------------------------------+

そして、最後のイベントがログに出力されます。

 
Artyom Trishkin:

どういう意味ですか?タイマーを作るということですか?CEngineのコンストラクタで作ります

まあ、そのためにライブラリ全体を調べなければならないんだけどね。)))

 
Alexey Viktorov:

もう見つけたよ、ありがとう。チケットが手に入れば、必要なものはすべて手に入るしね。改造の値段以外はね。それか、改造前の価格を知るための本物の松葉杖を作るか。まだ必要ないんだ。

改造前の価格も。

 
Alexey Viktorov:

まあ、そのために図書館中を調べなければならなかったんだけどね。)))

いいえ、記事を読むだけです

 

そしてこうなった:

デモでこのコードを実行している間に、指値注文が設定され、削除された。

443342388 2019.05.27 14:54:10 buy limit 0.01 eurusd 1.11835 0.00000 0.00000 2019.05.27 15:01:14 1.11972 cancelled 

そして突然、次のモッキングの間に、1つのポジションが変更され、1つのポジションがオープンされ、1つのポジションがクローズされました。しかし、長い間削除されていた注文を削除した記録はどこから来たのでしょうか?

2019.05.27 18:34:11.903 00 EURUSD,H1: OnChartEvent: id=1002, event=TRADE_EVENT_PENDING_ORDER_REMOVED, lparam=443342388, dparam=1.11835, sparam=EURUSD
2019.05.27 18:34:11.903 00 EURUSD,H1: OnChartEvent: id=1024, event=TRADE_EVENT_POSITION_CLOSED, lparam=443417294, dparam=1.11933, sparam=EURUSD
2019.05.27 18:34:11.903 00 EURUSD,H1: - Отложенный ордер удалён: 2019.05.27 14:54:10.000 -
EURUSD Удалён 0.01 Buy Limit #443342388  по цене 1.11835
2019.05.27 18:34:11.903 00 EURUSD,H1: - Позиция закрыта: 2019.05.27 18:33:02.000 -
EURUSD Закрыт Sell #443417294  по цене 1.11912, профит -0.21 USD
2019.05.27 18:33:02.755 00 EURUSD,H1: OnChartEvent: id=1022, event=TRADE_EVENT_POSITION_OPENED, lparam=443417294, dparam=1.11912, sparam=EURUSD
2019.05.27 18:33:02.755 00 EURUSD,H1: - Позиция открыта: 2019.05.27 18:33:02.000 -
EURUSD Открыт 0.01 Sell #443417294 [0.01 Market order Sell #443417294]  по цене 1.11912
2019.05.27 18:29:21.913 00 EURUSD,H1: OnChartEvent: id=1050, event=TRADE_EVENT_MODIFY_POSITION_TAKE_PROFIT, lparam=443218277, dparam=1.12218, sparam=EURUSD
2019.05.27 18:29:21.913 00 EURUSD,H1: - Модифицирован TakeProfit позиции: 2019.05.27 18:27:45.000 -
EURUSD Buy #443218277:  модифицирован TakeProfit: [1.12240 --> 1.12218]