OnTradeTransaction - ページ 8

 
Igor Zakharov:

しかし、あるケースでは、セキュリティシステムを作るように言われました。その条件は、ポジションが常にロックされていること(リアルポジションまたは保留中の注文)、つまり、買いロットの数が売りロットの数と同じであることでした。フィバーでのオーダー/ポジション/トレードカウントのニュアンスを知るきっかけになった案件です。

その違いは、4はブローカーから答えを受け取ると、まず未決済注文と履歴の「テーブル」を同期させ、ブローカーの答えをユーザーに知らせます。 5はこの答えをすぐに私たちに伝え、同時に「テーブル」を修正します(そしてすべてのmqlプログラムはこれらの「テーブル」からデータを読み込みます)。ミリ秒タイマーでキャッチする瞬間です。でも、それならテスターでキャッチすればいいのでは?

一般的に、私は心の平和を...

いや、もっとひどい状況だ。

保留(または成行)から履歴注文(約定または取消)に変わる瞬間、注文はしばらくの間、端末から完全に消えます。保留中の市場(または「開始」された市場)にも、歴史的な市場にも表示されない。

つまり、実行ではなく、この2つのテーブルを同期させることが重要なのです。サーバーからの回答(「注文が実行され、トランザクションが生成されました」)は、一方のテーブルからは削除されますが、他方のテーブルには入力されません。

 
Andrey Khatimlianskii:

いや、もっとひどい状況だ。

注文が保留(または成行)から履歴(約定または取消)に変わると、しばらくの間、端末から完全に消えます。保留中の市場(または「開始」された市場)にも、歴史的な市場にも表示されない。

つまり、実行ではなく、この2つのテーブルを同期させることが重要なのです。サーバーから回答が来て(「注文が実行され、so-and-soの取引が誘発されました」)、一方のテーブルから削除されますが、他方には入力されません。

確認すると面白いです。イゴール・マカヌは、タスクで興味をそそられましたhttps://www.mql5.com/ru/forum/6343/page1097#comment_12518742

膝の上で最初の近似値を出した。そして、OnOrderとOnOrderTransactionの操作と取引環境の状態について いくつかの統計を取り、 もし私があまり怠惰でなければ、異なる口座/ブローカーで何が起こっているかを見るためにデモ・テストにかけるかもしれません。

であれば、分析が可能になる。これまでの想定:1.部分約定は確認せず、口座の特殊性も確認しない、成行注文を出し、開いたポジションは記憶し、ジャーナルで取引が開かれるのを待ち、反対方向に再度開く。2.理想的には、OnOrderTransactionで特定のトランザクションをキャッチする必要がありますが、今のところ私はこの方法でやっています - 両方のイベントで同じようにすべてをチェックします。

もちろん、このコードは最適なものではありません。上の投稿のようにすべてが悪いと、オーダーポジションが失われるのはもう目に見えています。

//+------------------------------------------------------------------+
//|                                                 Test_Makalu2.mq5 |
//|                                           Copyright 2019, Allex@ |
//|                                                 alex-all@mail.ru |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, Allex@"
#property link      "alex-all@mail.ru"
#property version   "1.00"
#include <Expert\Expert.mqh>
//--- input parameters
input int      TP=200;
input int      SL=200;
input double   Lot=0.01;
input string   File;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CExpertTest : public CExpert
  {
public:
   int               type;
   ulong             order;
   ulong             deal;
   ulong             position;
   bool              send;
   bool              placed;
   bool              opened;
   bool              history;
   datetime          last_history;

                     CExpertTest() {order=0;};
                    ~CExpertTest() {};
   bool              Buy(double volume,double price,double sl,double tp,const string comment="") {return m_trade.Buy(volume, price, sl, tp,  comment);};
   bool              Sell(double volume,double price,double sl,double tp,const string comment="") {return m_trade.Sell(volume, price, sl, tp,  comment);};
   bool              CheckOrder(ulong order)
     {
      ulong state;
      if(OrderSelect(order))
        {
         if(OrderGetInteger(ORDER_STATE)==ORDER_STATE_FILLED)
            position=OrderGetInteger(ORDER_POSITION_ID);
        }
      else
         if(HistoryOrderSelect(order))
           {
            if(HistoryOrderGetInteger(order,ORDER_STATE,state)&& state==ORDER_STATE_FILLED)
               position=HistoryOrderGetInteger(order,ORDER_POSITION_ID);
           }
         else
           {
            return false;
           }
      return true;

     }
   virtual bool      Processing(void)
     {
      double price;
      if(order==0)
        {
         last_history=TimeCurrent();
         price=m_symbol.Ask();
         if(Buy(Lot,price,m_symbol.NormalizePrice(price-SL*m_symbol.Point()),m_symbol.NormalizePrice(price+TP*m_symbol.Point())))
            if(m_trade.ResultRetcode()==TRADE_RETCODE_DONE)
              {
               //ulong deal2;
               deal=m_trade.ResultDeal();
               order=m_trade.ResultOrder();
               if(order!=0 && CheckOrder(order))
                  return true;
              }
        }
      return false;
     }
   void              OnTrade()
     {
      if(order==0 || !CheckOrder(order))
         return;
      HistorySelect(last_history,TimeCurrent());
      for(int i=HistoryDealsTotal()-1; i>=0; i--)
        {
         ulong ticket=HistoryDealGetTicket(i);
         ulong ordticket=HistoryDealGetInteger(ticket,DEAL_ORDER);
         ulong pos=HistoryDealGetInteger(ticket,DEAL_POSITION_ID);
         if(pos==position || ordticket==order || ticket==deal)
           {
            int entry=HistoryDealGetInteger(ticket,DEAL_ENTRY);
            ulong type=HistoryDealGetInteger(ticket,DEAL_TYPE);
            if(pos==position && entry==DEAL_ENTRY_OUT)
              {
               Refresh();
               double price;
               double sl;
               double tp;
               bool result=false;
               datetime dt=TimeCurrent();
               if(type==DEAL_TYPE_SELL)
                 {
                  price=m_symbol.Bid();
                  sl=m_symbol.NormalizePrice(price+SL*m_symbol.Point());
                  tp=m_symbol.NormalizePrice(price-TP*m_symbol.Point());
                  result=Sell(Lot,price,sl,tp);
                 }
               if(type==DEAL_TYPE_BUY)
                 {
                  price=m_symbol.Ask();
                  sl=m_symbol.NormalizePrice(price-SL*m_symbol.Point());
                  tp=m_symbol.NormalizePrice(price+TP*m_symbol.Point());
                  result=Buy(Lot,price,sl,tp);
                 }
               if(result && m_trade.ResultRetcode()==TRADE_RETCODE_DONE)
                 {
                  deal=m_trade.ResultDeal();
                  order=m_trade.ResultOrder();
                  if(order!=0 && CheckOrder(order))
                     last_history=dt;
                 }
              }
           }
        }
     }
  };
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
CExpertTest Expert;
//---
int OnInit()
  {
   if(!Expert.Init(Symbol(),Period(),Point()))
      return INIT_FAILED;
   Expert.OnTradeProcess(true);
   return(INIT_SUCCEEDED);
  }
//---
void OnTick()
  {
   Expert.OnTick();
  }
//+------------------------------------------------------------------+
void OnTrade()
  {
   Expert.OnTrade();
  }
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction& trans,
                        const MqlTradeRequest& request,
                        const MqlTradeResult& result)
  {
   Expert.OnTrade();
  }
Вопросы от начинающих MQL5 MT5 MetaTrader 5
Вопросы от начинающих MQL5 MT5 MetaTrader 5
  • 2019.07.21
  • www.mql5.com
Подскажите пожалуйста, такой показатель тестера в жизни реален? И хороший это или плохой результат за год с депо 3000...
 
Aleksey Mavrin:

これは調べてみると面白いですね。イゴール・マカヌが 挑戦状で興味をそそるhttps://www.mql5.com/ru/forum/6343/page1097#comment_12518742

ディスカッションの中で解決策があったのですがhttps://www.mql5.com/ru/forum/6343/page1098#comment_12519819 、ディスカッションの一部が削除されてしまいました((
 
MT4Ordersのスレッドに解決策があります。しかし、すべてのレーキを自分で感じなければならない ;)
 
Aleksey Mavrin:

膝の第一近似値を作成。

このデモは見た方がいいです。ForexTimeFXTM-Demo01

 
Igor Zakharov:

通常の」取引ロボットでは、私が説明したようなケースは全く気づきませんでした。

どのようなトレーディング・ライブラリであっても、様々なデモ口座でのストレス・テストにより、そのお粗末さをチェックすることができますし、またそうすべきです。何事もなく通過できるはずです。

まあ、それを実現するためには、筆者が個人的にMT5-jokesに精通する必要があるのだが。しかし、実際にやってみると、それだけでは十分でないことがわかりました。

トレードサーバーへのひどいスパム注文では検出されなかった、非常に特殊なものがあります。フィードバックにより、開発者自身も気づいていないような不思議な挙動を発見することができました。

 
Igor Makanu:
議論に解決策があったhttps://www.mql5.com/ru/forum/6343/page1098#comment_12519819 、議論の一部が削除されました((
アンドレイ・ハチムリアンスキー
MT4Ordersのブランチに解決策があります。しかし、すべてのレーキを自分で感じなければならない ;)

そうなんです、レーキはいつも面白いんです、そしてプロがどうやったかを見てください。fxsaberの 解決策は簡潔で素晴らしいのですが、その解決策には1つの点で引っ掛かりがあります。マニュアルには、ポジションチケットは開いた注文のチケットと全く同じであると書かれていますが、全てではありません。

私の解答では、そこから進めていました。

fxsaber
fxsaber
  • www.mql5.com
Опубликовал пост "Out-Of-Sample" - где расположить, справа или слева? Когда-то в паблике столкнулся с мнением, что OOS должен располагаться только справа. Т.е. расположение его слева от интервала Оптимизации - ошибка. Я с этим был категорически не согласен, т.к. не видел разницы. Теперь вижу. Ошибался, был не прав... Опубликовал пост...
 
fxsaber:

どのようなトレーディング・ライブラリでも、様々なデモ口座でのストレス・テストを通じて、お粗末さをチェックすることができますし、そうすべきです。何事もなく通過できるはずです。

テストでは200msを使い、返すときに男性が5msに設定した。 5では、どのアカウントでもほぼ毎回動作した。

重要かどうかわかりませんが、彼らはwinapi timeBeginPeriod(1)を使いました、つまり、標準の20ms以下ですべてが起こりました

 
Aleksey Mavrin:

ポジション・チケットは基本的にオープニング・オーダー・チケットであるが、常にそうであるとは限らない。

あまりよく覚えていないのですが、いつもそうだったような気がします。

 
fxsaber:

あまりよく覚えていないのですが、ずっとあったのだと思います。

そうですね、この場合、位置の識別子が生涯不変であることです。ロールオーバーやネッティングの際に変化するポジションティッカーと混同していました。

しかし、私は理解していない - ポジションが部分的に閉じているとき、チケットはポジションに影響を与える最後の注文のチケットに変更されないのですか?

自分のコードを見直してみます、ありがとうございました。このフォーラムを訪れたのは無駄ではありません。)

現在の注文や履歴のリストにない「失われた注文」について:これはバグではないようです。

これはバグではなく、ターミナルサーバーであるMT-marketの特殊性(即時執行の場合、マーケットが機能しない)を注意深く見る必要があると思います。端末が成行注文を出すと、同期機能の場合、サーバーから返事が来るのを待ちますから、そう思います。

エラーがなければ、TRADE_RETCODE_DONE(即時約定の場合はリクオートですが、今のところマーケット型です)のみ返信されることがあり、これは基本的にサーバーがマーケットに注文を送ったことを意味し、それは

実際には、サーバーが注文を送信し、その返信を待っていることを意味します。現時点での注文の状態は、私の記憶違いでなければORDER_STATE_STARTED であり、そのチケットは既知である。注文が成立した場合、サーバは端末に OnTradeTransaction を送信し、注文の状態は ORDER_STATE_FILLED に変化し、取引は既知となる

と位置がわかるようになります。このとき初めて、端末は注文を履歴に記録する。何が起こったかわからないし、サーバーからの最初の応答もすでに出ているので、あらかじめこのようなことはしない。

これは、注文がECNネットワークまたはどこか他の場所で実行されるまでの時間であり、それらは2つのリストのいずれにも含まれていません。つまり、成行注文の場合、履歴にのみ表示されます(即時約定中の再注文の場合はよくわかりません)。

は、開いているもののリストに表示されることはありません。そして、保留中の注文がトリガーされると、それはすでに成行注文になっているので、オープンなもののリストから削除され、マーケットサーバーからの応答を待って、履歴に送られます。

そうだろうか?