ライブラリ: MT4Orders - ページ 63

 

取引、自動取引システム、取引戦略のテストに関するフォーラム

ライブラリ: MT4Orders

fxsaber, 2021.06.02 10:09

私のリクエストにより、MetaQutoesはライブラリの最新アップデートを完全に英語にローカライズしました。ライブラリの最新ビルドは、ソースコードのコメントが英語に翻訳され、英語のページで利用できるようになりました。


英語ページで公開されていた以前のバージョンとの違い。

// 変更点のリスト:
// 02.11.2018
// 修正: MT4 のポジションをトリガーする前にオープン価格をゼロにすることはできなくなりました。
// 修正: 特定の取引サーバーの稀な実行面を考慮しました。
// 26.11.2018
// 修正: MT4 のクローズポジションのマジックとコメント:オープニングトランザクションの関連フィールドの優先順位が、クローズトランザクションのそれよりも高い。
// 修正: MT4-OrdersTotal および MT4-OrderSelect の計算中に、MT5-OrdersTotal および MT5-PositionsTotal のまれな変更が考慮されます。
// 修正: ライブラリでは、MT5 から削除されていない、ポジションをオープンした注文が考慮されません。
// 17.01.2019
// 修正: 保留注文を選択する際の不運なエラーを修正しました。
// 08.02.2019
// 追加: ポジションのコメントは、OrderCloseを経由して部分決済時に保存される。
// 部分決済時にオープンポジションのコメントを変更する必要がある場合は、OrderClose で指定できます。
// 20.02.2019
// 修正: MT5注文がない場合、ライブラリは既存のMT5トランザクションからの履歴同期を期待します。失敗した場合、そのことを通知します。
// 13.03.2019
// 追加: OrderTicketID() を追加 - MT5 トランザクションまたは MT5 ポジションの PositionID、および保留中の MT4 注文のチケット。
// 追加: SELECT_BY_TICKET は、すべての MT5 チケット (および MT5-PositionID) に対して機能します。
// 02.11.2019
// 修正: CloseByポジションのロット、手数料、クローズ価格を修正しました。
// 12.01.2020
// 修正: 残高取引のOrderTicketID()が正しい値を返すようになりました。
// 修正: SELECT_BY_TICKET - OrderTicketID()による選択(MT5-PositionID)を修正しました。
// 修正:マクロとの互換性を高めるため、内部ライブラリのメソッド名を変更。
// 10.04.2020
// 修正: 部分的に執行されたライブの未決注文がOrdersTotal()に入らなかった。
// 09.06.2020
// 追加:クローズしたポジションのStopLoss/TakeProfit/ClosePriceRequestがより明確に定義されました。
// 10.06.2020
// 追加: ミリ秒を追加し、OrderPrint()の価格と注文の丸めを削除しました。
// 13.08.2020
// 追加: MT4ORDERS_BENCHMARK_MINTIMEマクロを使用してライブラリパーツのパフォーマンスをチェックする機能を追加しました。
// 20.08.2020
// 修正:明らかになった部分的なオーダー実行の特徴を考慮に入れる。
// 29.08.2020
// 修正:取引履歴をより高速に処理できるようにした。
// 24.09.2020
// 追加: SELECT_BY_TICKET(同じチケット)でライブ MT4 注文を選択する際に、MT5 ポジションよりも MT5 注文の優先度を上げる必要がある場合、
// これは、チケットのサイズをマイナスに変更することで可能です: OrderSelect(-Ticket, SELECT_BY_TICKET).
// 追加:MT4のライブ注文(同じチケット)を変更する際に、MT5注文のみの選択を指定する必要がある場合、
// これは、チケットのサイズをマイナスに変更することで可能である: OrderModify(-Ticket, ...)。
// 追加: OrderSelect(INT_MAX, SELECT_BY_POS) - 存在を確認し更新することなく、MT5のポジションに切り替える。
// OrderSelect(INT_MIN, SELECT_BY_POS) - 存在を確認して更新することなく、MT5のライブ注文に切り替える。
// 修正:取引履歴をより高速に処理できるようにした。
// 30.09.2020
// 修正:取引履歴をより高速に処理できるようにした。
// 08.10.2020
// 修正: MT5の新規取引検索の欠陥により、成行注文のOrderSendが長く実行される可能性がありました。
// 21.10.2020
// 追加: MT4との互換性を提供するため、OrderTicketID() を追加 - OrderTicket() を返す。
// 11.11.2020
// 修正:OrderTicketID() および OrderTicketOpen() は、TICKET_TYPE で指定された値タイプを返します。
// 06.12.2020
// 修正: MT5の取引履歴でSL/TPの実行記録が正しくないケースが考慮されるようになりました。
// 追加: MT4ORDERS_TESTER_SELECT_BY_TICKET マーケットでは、OrderTicketID() を介してのみ、SELECT_BY_TICKET がテスターで機能するように強制されています。
// 04.05.2021
// 修正: ポジションをオープンしたMT5注文が消えない場合、MT4注文のリストに追加されなくなりました。
// 修正: MT5のクローズバイ注文がMT4の注文リストに表示されなくなりました。
// 12.05.2021
// 追加: MT4ORDERS_BYPASS_MAXTIMEマクロは、MT5における取引環境の非同期化について、常に出現するケースを変更します。
// 13.05.2021
// 修正: OrderOpenReason()のバグを修正しました。
// 14.05.2021
// 修正: BYPASSメカニズムがOrderSelect(INT_MAX, SELECT_BY_POS)とOrderSelect(INT_MIN, SELECT_BY_POS)に影響しなくなりました。
// 01.06.2021
// 修正:コンパイラ・ビルド2449以降との互換性。
// 修正:同期の改善。ByPass.mqh は最新バージョンでなければならない。
// 追加: OrderLots(true) - 選択されたポジションの同期されたサイズ。


同期メカニズムとともに最新版を使うことをお勧めします。そうすれば、他のトレーディング・ライブラリーでは解決できないような問題はすべて感知できなくなる。

#define  MT4ORDERS_BYPASS_MAXTIME 1000000 // 取引環境の同期を待機する最大時間(マイクロ秒)
#include <MT4Orders.mqh> //https://www.mql5.com/en/code/16006

このメカニズムが機能するためには、このライブラリを ダウンロードする必要があります。取引ロジックを書く際にユーザーの気を散らさずに、取引環境の正しさの複雑で効果的なチェックがすべて自動的に行われます。

 
MT4Orders (+ByPass)はHistorySelect(0, INT_MAX)でのみ機能するため、削除された注文だけを履歴テーブルの最後に追加する現在の問題は 発生しません(+同期)。
 
fxsaber:
MT4Orders (+ByPass)はHistorySelect(0, INT_MAX)でのみ機能するため、削除された注文だけを履歴テーブルの最後に追加する現在の問題は 発生しません(+同期)。

壊れた! MT5のアップデートはお勧めしません。MT5の以前の動作が正しかったことを説明してください。今は違います。

 
fxsaber:

壊れた! MT5のアップデートはお勧めしません。MT5の以前の動作が正しかったことを説明してください。今は違います。

悲しい。

私は、履歴への注文挿入を追跡し、「シフトされた」期間+100を超えない履歴ポジションのみ、すなわちほとんど血でTradesIDクラスでそれを更新する方法をコードにスケッチしました。

このコードはまだテストしていませんし、もちろん最適とは言えません。(黄色 - あなたのオリジナルに変更されたもの)

//注文の挿入と履歴キャッシュの追跡の例
//チケット番号の削除や変更は追跡できません。
// 取引IDに基づく
#include "Classificator.mqh"
class TRADESID
  {
   CLASSIFICATOR<ulong, ulong> OrdersID;
   CLASSIFICATOR<ulong, ulong> DealsID;

   int               LastTotalOrders;
   int               LastTotalDeals;

   //履歴の100番目ごとにオーダーを出す
   ulong             OrderTickets[];


   void              RefreshOrders(void)
     {
      static ulong LastOrderTicket = -1;     //前回のパスで獲得した注文のチケット

      if(::HistorySelect(0, INT_MAX))
        {
         const int Total = ::HistoryOrdersTotal();

         if(this.LastTotalOrders > 0 && LastOrderTicket != ::HistoryOrderGetTicket(this.LastTotalOrders - 1))
           {
            int i;
            // 100枚目のチケットを逆順にチェックする
            for(i = ArraySize(OrderTickets) - 1; i >= 0 && OrderTickets[i] !=::HistoryOrderGetTicket(i * 100) ; i--)
               ;
            if(i < 0)
               LastTotalOrders = 0;
            else
               {LastTotalOrders = i * 100 + 1; LastOrderTicket = OrderTickets[i];}
            ArrayResize(OrderTickets, i + 1);
           }

         while(this.LastTotalOrders < Total)
           {
            const ulong Ticket = LastOrderTicket = ::HistoryOrderGetTicket(this.LastTotalOrders); //(this.LastTotalOrders++)
            
            // 履歴の100番目の位置ごとに、配列にチケットを追加する
            if(LastTotalOrders++ % 100 == 0)
               OrderTickets[::ArrayResize(OrderTickets, ::ArraySize(OrderTickets) + 1) - 1] = Ticket;


            const ulong PositionID = ::HistoryOrderGetInteger(Ticket, ORDER_POSITION_ID);

            if(PositionID)
              {
               this.OrdersID.Add(PositionID, Ticket);

               const ulong PositionBy = ::HistoryOrderGetInteger(Ticket, ORDER_POSITION_BY_ID);

               if(PositionBy)
                  this.OrdersID.Add(PositionBy, Ticket);

              }
           }
        } 

      return;
     }
  };

注文の削除や変更を追跡するのはもっと難しいが、これもあなたのバイブルでは解決できない。

もちろん、ByPASSとMT4HISTORYはそのような修正のためにもっと洗練されたアルゴリズムを必要としますが、複雑なものではなさそうです(私はまだ勉強していません)。

 

また、TRADE_TRANSACTION_HISTORY_UPDATE と TRADE_TRANSACTION_HISTORY_DELETE の トランザクションを追跡することもできます:

https://www.mql5.com/ru/forum/366029/page2#comment_22442705

もしチケット番号が与えられ、履歴の注文がチケット順にソートされていれば、OrderTickets 配列を通して履歴の注文位置を簡単に追跡できます。


P.S. 最後の手段として、HashMap を追加することもできます。

Библиотеки: TradesID
Библиотеки: TradesID
  • 2021.05.13
  • www.mql5.com
Статьи и техническая библиотека по автоматическому трейдингу: Библиотеки: TradesID
 
mktr8591:

悲しいことだ。

もしそのまま返してくれないのなら、私たちは松葉杖を作ることができる。 履歴の注文挿入を追跡し、「シフト」期間+100を超えない履歴ポジションのみで、TradesIDクラスでそれを更新する方法を、私はコードをスケッチした。

私はこのコードをテストしていませんし、もちろん最適ではありません。(黄色 - あなたのオリジナルに変更されたもの)

私の考えが正しければ、あなたはシフトが発生した100を探しています。しかし、新しいチケットそのものが、その後どのようにその100の中にあるのか理解できませんでした。特に、複数のチケットがあり、それらが異なる百にある場合は。

注文の削除や変更を追跡するのはもっと難しいのですが、あなたのバイブルはそれも解決していませんでした。

私には理解できません。具体的に何が追跡されていないのか?とりあえずb2958は やめたほうがいいと思う。

履歴をさかのぼって編集することが目的なら、それは価値がない。解決策はオタクのためではなく、取引のために作られる。

もちろん、ByPASSとMT4HISTORYはそのような修正にもっと洗練されたアルゴリズムを必要としますが、複雑なものではなさそうです(私はまだ勉強していません)。

問題は、各パスで呼び出される正規関数が多ければ多いほど、ラグが発生する確率が高くなることです。EAはハングし始める。複数のExpert Advisor - さらに悪い。複数のターミナルがある場合は、かなり悪い。例えば、OrderSend は ping の数倍の時間がかかるようになります。松葉杖は乱暴なデバッグを意味するという事実に加えて、ラグも生じます。列挙中に履歴が更新されることなどを想像してみてほしい。膨大な数のバグが発生するだろう。


結局のところ、主なことはすべてが完璧に機能したということだ。ただ、均等な場所でそれを壊しているだけで、何のコメントもない。


ZЫ 私にとっては、なぜほとんど誰もそれが何であるかを理解していないのかが謎です。

 
fxsaber:

ZЫ それがどういうことなのか、ほとんど誰も理解していないのが不思議だ。

なぜなら、MT5で注文を使った作業をa)簡単に、b)正しく、c)素早く実装しようとした人がいないからです。私も含めて。

 
fxsaber:

もし私の考えが正しければ、あなたはシフトが発生した100を探しているのでしょう。しかし、この百の中に新しいチケット自体がどのように位置づけられるのか、私には理解できません。特に、複数のチケットがあり、それらが異なる百にある場合は。


もし削除がなく挿入だけがあったなら、ループは

for(i = ArraySize(OrderTickets) - 1; i >= 0 && OrderTickets[i] !=::HistoryOrderGetTicket(i * 100) ; i--)
               ;

ループは、挿入が発生した最も古い百の先頭を検索します。チケットそのものを検索する必要はありません。この百番目と次の(新しい)百番目から始まるすべてのオーダーを調べて、ハッシュマップに追加するだけです。これはいつものようにwhile(this.LastTotalOrders < Total)のループで行われます。 ほとんどの場合、最後の数百件が1-2件になります。

100ではなく、40とか20とか、ステップを減らしたほうがいいかもしれない。

万が一、forの間に履歴が変化し、見つかった100件の前に何かが挿入された場合は、それをループに入れることができる:

 void              RefreshOrders(void)
     {
      static ulong LastOrderTicket = -1;     //前回のパスで獲得した注文のチケット

      if(::HistorySelect(0, INT_MAX))
        {
         // IsStoppedと最大実行時間のチェックを追加する必要がある。
         while(this.LastTotalOrders > 0 && LastOrderTicket != ::HistoryOrderGetTicket(this.LastTotalOrders - 1))
           {
            int i;
            // 100枚目のチケットを逆順にチェックする
            for(i = ArraySize(OrderTickets) - 1; i >= 0 && OrderTickets[i] !=::HistoryOrderGetTicket(i * 100) ; i--)
               ;
            if(i < 0)
               LastTotalOrders = 0;
            else
              {LastTotalOrders = i * 100 + 1; LastOrderTicket = OrderTickets[i];}
            ArrayResize(OrderTickets, i + 1);
            ::HistorySelect(0, INT_MAX);
           }

         const int Total = ::HistoryOrdersTotal();

         while(this.LastTotalOrders < Total)
           {
            const ulong Ticket = LastOrderTicket = ::HistoryOrderGetTicket(this.LastTotalOrders);

            // 履歴の100番目の位置ごとに、配列にチケットを追加する
            if(LastTotalOrders++ % 100 == 0)
               OrderTickets[::ArrayResize(OrderTickets, ::ArraySize(OrderTickets) + 1) - 1] = Ticket;


            const ulong PositionID = ::HistoryOrderGetInteger(Ticket, ORDER_POSITION_ID);

            if(PositionID)
              {
               this.OrdersID.Add(PositionID, Ticket);

               const ulong PositionBy = ::HistoryOrderGetInteger(Ticket, ORDER_POSITION_BY_ID);

               if(PositionBy)
                  this.OrdersID.Add(PositionBy, Ticket);

              }
           }
        } 
      return;
     }

しかし、それは非常にまれなことである。

 
mktr8591:

もし、削除がなく挿入だけがある場合、サイクルは次のようになる。

ループは、挿入が発生した最も古い100件の先頭を検索します。チケットそのものを検索する必要はありません - この100件から始まるすべての注文と次の(新しい)注文を調べてハッシュマップに追加するだけです。これはいつものようにwhile(this.LastTotalOrders < Total)のループの中で行われます。 ほとんど常に、最後の数百件が1-2件になります。

つまり、同じチケットを繰り返しハッシュマップに追加しても、ハッシュマップは変わらないということですか?

注文が800件目に達したことがあります。この場合、数百の注文をハッシュマップする必要があります

 
fxsaber:

つまり、同じチケットを繰り返しハッシュマップに追加しても、ハッシュマップは変わらないという使い方ですか?


はい、今気づいたのですが、チケットOrdersID.Add(PositionID, Ticket)を繰り返し追加すると、OrdersID.ValuesID[]の中でこのチケットは逆になってしまいます。つまり、ハッシュマップが膨らんでしまいます。

どうにかしてチェックする必要があります。あるいは、VALUESIDに配列構造の代わりにHashSetを使う。あるいは似たようなことをする。