特定のブローカーのライブ口座における複数注文入力の問題 - ページ 2

 
Malacarne:

BlindMist さん、あなたのアカウントがブローカーサーバーと同期しているかどうかを確認するために、ローカルのデータベースをチェックすることは 理にかなっていると思います。

この問題に対処するために、提案された投稿 をご覧ください。

提案されたポストを見たところ、注文が複数回実行されるのを防ぐ方法について言及されていません...

Sleep()関数を使っても、どれくらいの時間待てば取引が失敗したと確信できるのでしょうか...。

私のEAでは、注文の送信要求が10秒後にタイムアウトして再試行されるようにしています。

 
BlindMist:

提案された投稿を見たところ、注文が何度も実行されるのを防ぐ方法が書かれていないのですが...。

Sleep()関数を使ったとしても、どれくらいの時間待てば取引が失敗したと確信できるのでしょうか?

私のEAでは、注文の送信要求を10秒後にタイムアウトさせてから再試行するようにしています。

BlindMistさん、その件についての私の考えは、(PositionSelectのテストやSleepのテストの代わりに)それをチェックする唯一の方法だと思います。

この問題で唯一良いのは、PositionSelectは遅かれ早かれ、サーバーから更新された位置を取得することです。したがって、致命的なエラーを示すために最大時間(タイムアウト)待ち、それが問題ないかどうかをチェックするために小さなサンプルを作る必要があります(私の例では100ms)。

bool fatalError=false; // atention: declare this as global

....

if (fatalError==false) {
  if (m_Trade.PositionOpen(Symbol(), ORDER_TYPE_BUY, LotSize, Price, 0, 0)) {
    Print("Position opened in ", Symbol());
    int maxTimeout=0;
    while (!PositionSelect(Symbol())) {
       Sleep(100);
       maxTimeout++;
       if (maxTimeout>100) {
          Print("### PositionSelect fatal error!");
          fatalError=true;
          break;
       }
    }
    Print("--> PositionSelect delay=",maxTimeout*100);
    break;
  }
}

これをよりモジュール的に行うもう一つの方法は、例えばタイムアウトを制御する関数を 作成することです。

bool PositionSelectTimeout(string symbol,int timeout) 
  { // timeout in seconds
   int maxTimeout=0;
   while(!PositionSelect(symbol)) 
     {
      Sleep(100);
      maxTimeout++;
      if(maxTimeout>(timeout*10)) return(false); // fatal error (timeout)
     }
   return(true); // position selected
  }

ここでの主なアイデアは、私のPositionSelectTimeout()は、元のPositionSelect()を置き換えることです、もちろん回避策として、ちょうどMQは本当に良い、決定的な解決策に対処することができるので。

例えば、以下のような感じです。

if (PositionSelectTimeout(Symbol(),60)) { // 60 seconds timeout
 ...
}

// instead of ...

if (PositionSelect(Symbol())) {
 ...
}

ですから、私の意見では、FinanceEngineerは 問題を解決するために同じことをしなければならず、ループの中にこのテストを挿入して、ポジションが休憩してもよいかどうかダブルチェックする必要があります。

 
figurelli:

BlindMistさん、こんにちは。このトピックに関する私のアイデアは、(PositionSelectの1つのテストや1つのSleepの代わりに)それをチェックする唯一の方法だと思います、長い時間待ってから致命的なエラーのようなものを作成したり、シンボルの位置を取得したらすぐにジャンプしたりします(以下のコード)。

この問題で唯一良いことは、おそらくPositionSelectは遅かれ早かれサーバーから更新された位置を取得するので、致命的なエラーを示すために最大時間(我々のタイムアウト)を待ち、それが問題ないかどうかをチェックするために小さなサンプル(私の例では100ミリ秒)を作成しなければならない、ということです。

もう一つの方法は、例えばタイムアウトを制御する関数を作成することです。

ここでの主なアイデアは、私のPositionSelectTimeout()がオリジナルのPositionSelect()を置き換えることです。

例えば、以下のような感じです。

ですから、私の意見では、FinanceEngineerは 問題を解決するために同じことをしなければならず、ループの中にこのテストを挿入して、位置を休憩してもよいかどうかダブルチェックしなければなりません。

figurelliさん、とても詳しいご回答ありがとうございます。私のシステムが改善されるかどうか、試してみることにします。
 
BlindMist:
figurelliさん、とても詳しいお返事ありがとうございます。私のシステムをより良くするかどうか、試してみます。
ありがとうございます、どういたしまして。
 
BlindMist:

提案された投稿を見たところ、注文が何度も実行されるのを防ぐ方法が書かれていないのですが...。

Sleep()関数を使ったとしても、どれくらいの時間待てば取引が失敗したと確信できるのでしょうか?

私のEAでは、注文の送信要求が10秒後にタイムアウトして再試行されるようにしています。

一回の注文執行に 15秒。これは本当にひどい。この問題は、ブローカーのサーバーから何も得ることができないことです(例えば、簡単なステータスチェックのコードなど)。
 
FinanceEngineer:
1回の注文実行 に15秒。これは本当にひどい。この問題は、ブローカーのサーバーから何も得られないということです(例えば、簡単なステータスチェックのコードなど)。

こんにちは、FinanceEngineer、あなたは正しい、しかし、管理するための最初のものは、市場が速く、それが通常のような問題になるので、低遅延ブローカーを選択することである。

また、低遅延ブローカーを持つことができるので、それは常に最悪の場合について考えるのが良いです、しかし、一日のいくつかの瞬間に大きな遅延、例えば、あなたが関連するニュースを持っているとき。

とにかく、MT5のOrderSend()は、MT4の戻り値がTicketであるため、MT4ほど管理しやすいものではありません。MT5では、MQL5アーキテクチャで導入された株式市場の非同期通信により、ブローカーOMSプロトコル(例えばFIXなど)との通信が可能になったため、この変更が必要でした。

しかし、これは、今日の注文管理のためのOMSの大きな変化だと思います。なぜなら、リアルタイムのTicketを得るのは非常に難しく、MT5はこの新しいシナリオに更新されています。

この意味で、MT5でOrderSend()の後に行うより適切なことは、PositionSelect()をチェックすることであり、上記のすべての理由から、私が提案するPositionSelectTimeout()の回避策を使うことを強くお勧めします。

最悪のケースを考えると、マーケットにオーダーを送った後に、すべてのif { } else { }条件を管理することで、あらゆる状況に対応できるようにするしかないようです。

catch { }も欲しいところですが、これに近いことはGetLastError()を使って行うことができます。

これは、ポジションを確定するためにチケットも必要で、MT5のOrderSend()はMT4のように同期してチケットを返さないからです。

 
BlindMist:

提案された投稿を見たところ、注文が何度も実行されるのを防ぐ方法が書かれていないのですが...。

Sleep()関数を使ったとしても、どれくらいの時間待てば取引が失敗したと確信できるのでしょうか?

私のEAでは、注文送信要求が10秒後にタイムアウトして再試行するようにしています。しかし、最初の要求から15~20秒後に注文が実行されることがあります。

これは私が現在使用しているコードです。今のところ、何の問題もありません。このコードを試してみて、そのブローカーで動作するかどうかを確認することができます。

      bool checkOrderSend = OrderSend(request, result);
     
      if(result.retcode==10009 || result.retcode==10008)
      {
          Print("OrderSend was successful. Code: ",result.retcode);

          
          break;
      }
      else
      {
          Print(ResultRetcodeDescription(result.retcode));
      }
     

 
FinanceEngineer:

これは私が現在使用しているコードです。今のところ、私は何の問題も持っていません。あなたはこのコードを試して、それがそのブローカーのために動作するかどうかを確認することができます。

      bool checkOrderSend = OrderSend(request, result);
     
      if(result.retcode==10009 || result.retcode==10008)
      {
          Print("OrderSend was successful. Code: ",result.retcode);

          
          break;
      }
      else
      {
          Print(ResultRetcodeDescription(result.retcode));
      }
     

checkOrderSend 変数で何をするのですか?

サーバーの取引完了を確認せずに複数の注文が実行されるのをどのように防ぐのですか?

 
figurelli:

checkOrderSend 変数で何をするのですか?

サーバーの取引完了を確認せずに、複数の注文が実行されるのを防ぐにはどうすればよいですか?

こんにちは、figurelliさん。

私が言いたかったのは、OrderSend関数の 最後で、10009と10008の両方のコードをチェックすることです。 というのも、多くの人が10009と10008のどちらか一方しか確認せず、注文が出ない状況を避けるためにforループを組んでいるため、多くの注文が出るということがわかったからです。

私の場合、そのブローカーで注文が出ないと、forループは10回試行することになります。 だから、もし誰かが複数の注文を受けているのなら、10009と10008の両方をチェックしてOrdersendingループを停止しているかどうかを確認する必要があることを明確にする価値があるだろう。

しかし、皮肉なことに、デモ口座では、1つのリターンコードのみをチェックすることは問題ありません。しかし、皮肉なことに、デモ口座では、1つのリターンコードだけをチェックすればよいのです。これでは、複数注文の問題は発生しません。このように、ライブ口座とデモ口座では、微妙に挙動が異なることがわかりました。

よろしくお願いします。

 
FinanceEngineer:

こんにちは、figurelliです。

私が言いたかったのは、OrderSend関 数の最後で、10009と10008の両方のコードをチェックすることです。 というのも、多くの人が片方のコード(つまり10009か10008)しかチェックせず、注文がない状況を避けるために通常forループを配置するように、多くの複数の注文を取得していることがわかったからです。

私の場合、そのブローカーで注文が出ないと、forループは10回試行することになります。 だから、もし誰かが複数の注文を受けているのなら、10009と10008の両方をチェックしてOrdersendingループを停止しているかどうかを確認する必要があることを明確にする価値があるだろう。

しかし、皮肉なことに、デモ口座では、1つのリターンコードのみをチェックすることは問題ありません。しかし、皮肉なことに、デモ口座では、1つのリターンコードだけをチェックすればよいのです。これでは、複数注文の問題は発生しません。このように、ライブ口座とデモ口座では、微妙に挙動が異なることがわかりました。

よろしくお願いします。

こんにちは、FinanceEngineer、多分私たちがこれを行う場合、おそらく我々はここで他の重要なポイントに対処し、フォーカスを失うことはありませんので、元のコードの複数の注文の問題をチェックし始める方が良いだろう、あなたは何を考えているのでしょうか?