私のEAではダブルエントリーを行います - ページ 7

 

スリープを使用 するとダニがいなくなりますか?

どのような結果になるのでしょうか?

Documentation on MQL5: Common Functions / Sleep
Documentation on MQL5: Common Functions / Sleep
  • www.mql5.com
Common Functions / Sleep - Documentation on MQL5
 
doshur:

スリープを使用 するとダニがいなくなりますか?

どのような結果になるのでしょうか?

それはあなたのストラテジーによります。この「二重取引」の問題は、取引コードが各ティックで実行される場合にのみ発生するため、おそらくティックに依存するストラテジーをお持ちのことでしょう。ですから、遅延(スリープ)中に到着したティックを失った場合、どのような結果になるかを評価するのはあなた次第です。

 
angevoyageur:

それはあなたのストラテジーによります。この「二重売買」の問題は、取引コードが各ティックで実行される場合にのみ発生するため、おそらくティックに依存するストラテジーをお持ちの方でしょう。そのため、遅延(スリープ)中に到着したティックを失うと、どのような結果になるかを評価するのはあなた次第です。

つまり、もし私が800秒間スリープしたら

ということは、次の800msの間、ティックを失うということですか?私がトレードを開始した後、私のEAは何もしません、ただTPかSLまでそこに座っているか、終了する時間を待っているだけです。

では、私の戦略はスリープを使っても 大丈夫なのでしょうか?

refreshrates() を呼び出すとティックが戻ってくるのでしょうか?

Documentation on MQL5: Common Functions / Sleep
Documentation on MQL5: Common Functions / Sleep
  • www.mql5.com
Common Functions / Sleep - Documentation on MQL5
 
doshur:

ということは、800msスリープしたら

次の800msの間、ティックを失うということですか?取引開始後、私のEAは何もせず、TPかSLまでそこに座っているか、終了する時間を待っているだけです。

では、私の戦略はスリープを使っても 大丈夫なのでしょうか?

refreshrates() を呼び出すとティックが戻ってくるのでしょうか?

doshur, ticks you loose, you loose, there is no wayback machine.

ドキュメントについてhttps://www.mql5.com/en/docs/common/sleep この関数は、現在のExpert Advisorやスクリプトの実行を指定された時間内に一時停止 します。

そのため、OnTimerイベントも中断されます。おそらく、EAが1つのスレッドしか使用していないためです。

だから、固定スリープを使用すると、決定的な解決策ではありませんが、ちょうど "数値"、すなわち、遅延があなたの値よりも低い場合には回避策です。

そして、私が提案する理由は、PositionOpenの実行をダブルチェックし、ちょうどSleep()よりも良い回避策として返すために、取引を開いた後にPositionSelectをテストするループと、問題の原因(angevoyageur テストによる)を証明するものです。

Documentation on MQL5: Common Functions / Sleep
Documentation on MQL5: Common Functions / Sleep
  • www.mql5.com
Common Functions / Sleep - Documentation on MQL5
 

これは、私が今使っているものです。figurelliが提供する回避策をよりエレガントな方法でコーディングするにはどうしたらよいでしょうか?

//
         {
            Price = SymbolInfoDouble(Symbol(), SYMBOL_ASK);

            if(m_Trade.PositionOpen(Symbol(), ORDER_TYPE_BUY, LotSize, Price, 0, 0))
            {
               Sleep(800);

               if(m_Trade.ResultRetcode() == 10009)
               {
                  Print("Position opened in ", Symbol());

                  return;
               }
               else
               {
                  Print("Error opening position in ", Symbol(), " - ", m_Trade.ResultComment(), "\n", "Return Code Desc - ", m_Trade.ResultRetcodeDescription());
               }
            }
            else
            {
               Print("Error with PositionOpen in ", Symbol(), " - ", m_Trade.ResultComment(), "\n", "Return Code Desc - ", m_Trade.ResultRetcodeDescription());
            }
         }
 
doshur:

これは、私が今使っているものです。figurelliが提供する回避策をよりエレガントな方法でコーディングするにはどうしたらよいでしょうか?

こんにちは、doshur。私もあるEAで 二重エントリーの問題に悩まされていました。実は、この問題は流動性の高い資産を取引しているときだけ発生していました。非同期モードで注文を送信するように設定しても、EAはPositionsTotal()を更新するためにサーバーからの応答を待つ時間が長すぎました...その間、他の受信ティックが2番目の注文を送信する条件をトリガーしていました...ポルトガル語のフォーラムで私は回避策を投稿しましたが、ここで共有したいです。

アイデアは簡単です。

//--- global variables
CTrade trade;
bool position_opened=false;

//--- inside OnTick()
if( conditions to open && position_opened==false )
  {
   //--- set the global variable to true to avoid duplicate orders
   position_opened=true;
   trade.PositionOpen(_Symbol,order_type,lot,price,sl,tp,"comment");
  }

このコードの唯一の問題は、注文がサーバーに受け入れられなかった場合、グローバル変数を「リセット」する必要があることです...これを使えばいいんです。

MqlTradeResult mresult;

//--- 
if(mresult.retcode==10009 || mresult.retcode==10008)
  {Print("Success!");}
else 
  {
   Print("Error = ",GetLastError());
   ResetLastError();
   //--- Sets the global variable to false
   position_opened=false;
   return;
  }

つまり、最初に送った注文がエラーを返した場合、グローバル変数をfalseに設定し、EAが別の注文を送れるようにするのです。しかし、私はこのコードを株式と先物でテストしただけで、FX市場ではテストしていません... :-(

 
Malacarne:

こんにちは、doshur。私もあるEAで二重入力の問題を抱えていました。実は、この問題は流動性の高い資産を取引しているときだけ発生していました。非同期モードで注文を送信するように設定しても、EAはPositionsTotal()を更新するためにサーバーからの応答を待つ時間が長すぎるようでした...その間、他の受信ティックが2番目の注文を送信する条件をトリガーしていました...ポルトガル語のフォーラムで私は回避策を投稿しましたが、ここで共有したいと思います。

アイデアは簡単です。

このコードの唯一の問題は、注文がサーバーに受け入れられなかった場合、グローバル変数を「リセット」する必要があることです...これを使えばいいんです。

つまり、最初に送った注文がエラーを返した場合、グローバル変数をfalseに設定し、EAが別の注文を送れるようにするのです。しかし、私はこのコードを株式と先物でテストしただけで、FX市場ではテストしていません... :-(

これは実行できそうです。この回避策について、figlliとangevoyageurから コメントがあるかどうか見てみましょう...
 
doshur:
これは実行可能なようです。この回避策について、figlliとangevoyageurから コメントがあるかどうか見てみましょう...。

Malacarneが提案したこの解決策(いくつかの調整を加えて)は、私にとって(Malacarneが控えめに言うように)回避策ではなく、この問題に対処する一つの優雅で正しい方法なので、素晴らしいものです。

私見ですが、ダブルエントリーの問題はMT5のバグではなく、コーディングのバグだと思います。

PositionOpen(...)メソッドの正常終了は 必ずしも取引操作の正常実行を意味 するものではありません。ResultRetcode()ResultDeal() 取引要求の結果(取引サーバーのリターンコード)を確認 する必要があります。

ということで、どんな相場状況にも強いように、ちょっとした変更を提案します。

1) PostionOpen()の戻り値も、例えば、元のコードと同じようにテストしてください。

if (trade.PositionOpen(_Symbol,order_type,lot,price,sl,tp,"comment")) position_opened=true;

2) 10010 -TRADE_RETCODE_DONE_PARTIAL - リクエストの一部のみが完了した、のように、他の関連するポストを開くことができるので、ResultRetcode()をより完全に処理 すること。また、10008 - TRADE_RETCODE_PLACED - Order placedは、私にとってはSuccessではなく、10009 -TRADE_RETCODE_DONE -Request completed で、これは非同期のメッセージなので、マラカーンコードの第2部は取引実行後に、これや取引チケットを考慮することが できました

とにかく、私にとっては、今が正しい道であり、最終的なカットであるように見えます。

 
Malacarne:

こんにちは、doshur。私もあるEAで二重入力の問題を抱えていました。実は、この問題は流動性の高い資産を取引しているときだけ発生していました。非同期モードで注文を送信するように設定しても、EAはPositionsTotal()を更新するためにサーバーからの応答を待つ時間が長すぎるようです...一方、他の受信ティックが2番目の注文を送信する条件をトリガーしていました...ポルトガル語のフォーラムで私は回避策を投稿しましたが、ここで共有したいと思います。

アイデアは簡単です。

このコードの唯一の問題は、注文がサーバーに受け入れられなかった場合、グローバル変数を「リセット」する必要があることです...これを使えばいいんです。

つまり、最初に送った注文がエラーを返した場合、グローバル変数をfalseに設定し、EAが別の注文を送れるようにするのです。しかし、私はこのコードを株式と先物でテストしただけで、FX市場ではテストしていません... :-(

それは有効なアプローチですが、ポジションがクローズされたときに、グローバル変数position_openedをfalseにリセットしなければなりません。どこでそんなことしてるんだ?

あなたの実装について、いくつかの詳細。

  1. position_opened を true に設定し、エラーが発生したら false に設定する必要はありません。
  2. CTradeクラスのオブジェクトを使用しているので、新しいMqlTradeResult 構造体を使用する必要はありません。
  3. figurelli さんの投稿にあるように、PositionOpen の戻り値をチェックする必要があります。
  4. クラス名はCtradeではなくCTradeです。mql5は大文字と小文字を区別します。
  5. position_openedはboolなので、falseと比較する必要はない。もし比較するのであれば、'='ではなく、'=='を使用しなければなりません。

ということで、以下が修正したコードです(コンパイル済みですがテストはして いません).

//+------------------------------------------------------------------+
//|                                                      ProjectName |
//|                                      Copyright 2012, CompanyName |
//|                                       http://www.companyname.net |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>

//--- global variables
CTrade trade;
bool position_opened=false;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnTick()
  {
   bool conditions_to_open;
   ENUM_ORDER_TYPE order_type;
   double lot;
   double price,sl,tp;

//---...set variables

//--- inside OnTick()
   if(conditions_to_open && !position_opened) //-- Or position_opened==false
     {
      if(trade.PositionOpen(_Symbol,order_type,lot,price,sl,tp,"comment")
         && 
         (trade.ResultRetcode()==10009 || trade.ResultRetcode()==10008)) //-- Or others condition according to your needs
        {
         //--- set the global variable to true to avoid duplicate orders
         position_opened=true;
         Print("Success!");
        }
      else
        {
         Print("Error = ",GetLastError(), "trade error = ", trade.ResultRetcode());
         //--- Sets the global variable to false
         // position_opened=false;                                         //-- Not needed as position_opened is already false
         return;
        }

     }
//--- 
  }
//+------------------------------------------------------------------+
 
figurelli:

...

私見ですが、本来の二重入力の問題は、MT5のバグではなく、ヘルプにあるように、コーディングのバグだと思います。

"PositionOpen(...)メソッドの正常終了は 必ずしも取引操作の正常実行を意味 するものではありません。ResultRetcode()ResultDeal()返す値で 取引要求の結果(取引サーバーのリターンコード)を確認する必要が あります。" と記載されています。

このトピックの問題とは関係ないと思います。この問題は、リクエストが正常に満たされ、ポジションがオープンされた場合です。しかし、このポジションは、貿易サーバー上で開かれ、私たちが遭遇した問題は、通常のようにもっと重要な遅延があり、MT5端末は、新しいティックがすでに処理されている後に、この新しいポジションを通知された場合です。

このように設計されているので、バグではありません。しかし、私の意見では、これは同期と非同期の取引要求を明示的に許可するプラットフォームのために設計されていないです。というのも、サーバーからリクエストに対する応答(上記のコードではtrade.ResultRetCode)を受け取ったとき、MT5プラットフォームが取引結果について通知され更新されるのを待たなければならないのです。(私はこのスレッドでそのすべてを理解しました)。

そこで、どのような相場状況にも対応できるように、いくつかの小さな変更を提案します。

1) PostionOpen()の戻り値も、元のコードと同じようにテストしてください。

2) ResultRetcode()をより完全に処理する。 10010 -TRADE_RETCODE_DONE_PARTIAL - リクエストの一部のみが完了した、のように、他の関連ポストを開くことができるから。また、10008 - TRADE_RETCODE_PLACED - Order placedは、私にとってはSuccessではなく、10009 -TRADE_RETCODE_DONE -Request completed で、 これは 非同期のメッセージ なので、マラカーンコードの第2部は取引実行後に、これや取引チケットを考慮するかもしれないですね

ともあれ、これで最終的な結論が出たようです。

もちろん、PositionOpenの戻り値とトレード結果の戻りコードをチェックしなければならないのは、全くその通りです。しかし、ResultRetCodeは同期で、ポジション(取引と注文)についてのMT5データベースの更新は非同期です。あなたの提案で行ったテストでは、取引要求の返された値をチェックするコードをもちろん使用しているので、これを実証しています。