取引環境に対応する際の典型的な間違いとその対処法 - ページ 3

 
fxsaber:

簡単な例で見る正しい選択

まだポジションが決まっていないのであれば、注文が入るのを待った方が良いと思います。
 
Комбинатор:
注文がまだポジションに計上されていない場合は、計上されるのを待つだけの方が良いと思います。

その発想はない。

 
通常のOrderSend(タイムアウトなし)の条件付き実装スキーム
static MqlTradeResult LastResult = {0};

void OnTradeTransaction( const MqlTradeTransaction&, const MqlTradeRequest&, const MqlTradeResult &Result )
{ 
  LastResult = Result;
}

// Условный алгоритм реализации штатной OrderSend
bool OrderSend( const MqlTradeRequest &Request, MqlTradeResult &Result )
{  
  bool Res = OrderSendAsync(Request, Result);
  
  if (Res)
  {
    while (LastResult.request_id != Result.request_id)
      OnTradeTransaction(); // условно-схематичный вызов
          
    Result = LastResult;    
    Res = (Result.retcode == TRADE_RETCODE_PLACED) ||
          (Result.retcode == TRADE_RETCODE_DONE) ||
          (Result.retcode == TRADE_RETCODE_DONE_PARTIAL);

    LastResult.request_id = 0;
  }
    
  return(Res);
}


この図は、MetaQuotes-DemoでOrderSendAsyncを使って 成行注文を出すと、注文が約定するか拒否されるまで、対応する注文を確実にキャッチすることができないことを示しています。つまり、MT5には、そのOrderSendAsyncの中間結果を評価する簡単なメカニズムがない。

 

がテーマになっているようです。

ここで、このコード:

if ( !OrderSend(request,result) ) PrintFormat("OrderSend error %d",GetLastError());
else Print(result.price);

は、DEMO(result=request)で完璧に動作します。

しかし、REALでは、結果を得ることができません(result=0.0).数秒待たない限りは。

 
Ivan Ivanov:

主題にあるようだ。

このようなコードがあることを指摘したい。

DEMOでは、完璧に動作します(result=request)。

しかし、REALでは結果(result=0.0)を得ることができません。数秒待たない限りは。

ログ、OrderSend 後の構造体フィールドの値、取引サーバー名などのデータが不足しています。

 
fxsaber:

一言で言えば、「成行注文があれば、それも『ポジション』だと思え」ということです。ラップポジションなので倒置カンマで。ハイライトされたコードは通常、どこにも表示されません。しかし、ポジションの再オープンを 回避することができます。ここで最も興味深いのは、赤で示した部分です。このチップの必要性はすぐにわかるものではありません。

for (int i = OrdersTotal() - 1; i >= 0; i--)
    if (OrderGetTicket(i) && (OrderGetInteger(ORDER_TYPE) <= ORDER_TYPE_SELL) &&
        !OrderGetInteger(ORDER_POSITION_ID) && (OrderGetString(ORDER_SYMBOL) == Symb))
      Res++;  // если мы сюда попадаем при проверке состояния, не запускать стратегию вообще, т.к. это промежуточное состояние.
 
Комбинатор:

次のティックではトレードシグナルが出ないかもしれません。私自身はMT4スタイルを使っているので、どうしてもそういう「ポジション」を面倒くさがらずに見てしまうんです。

 
fxsaber:

ログ、OrderSend後の構造体フィールドの値、取引サーバー名などのデータが不足しています。

//+------------------------------------------------------------------+
//|                                                      TestBUY.mq5 |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
{//--- объявление и инициализация запроса и результата
  MqlTradeRequest request={0};
  MqlTradeResult result={0};
//--- параметры запроса
  request.action =TRADE_ACTION_DEAL;
  request.symbol=_Symbol; 
  request.volume=0.01;
  request.type=ORDER_TYPE_BUY;
  request.price=SymbolInfoDouble(_Symbol,SYMBOL_ASK);
  request.deviation=5;
  request.magic=1234;
  request.tp=0.0;
  request.comment=DoubleToString(request.price,_Digits);
//--- отправка запроса
  if ( !OrderSend(request,result) )
    PrintFormat("OrderSend error %d",GetLastError()); // если отправить запрос не удалось, вывести
//--- информация об операции
  PrintFormat("retcode=%u deal=%I64u order=%I64u",result.retcode,result.deal,result.order," NewOrder");
}


2018.02.20 15:20:35.845 取引注文 #66745055 買い 0.01 / 0.01 EURUSDeur at market done in 610.625 ms

2018.02.20 15:20:35.935 トレード案件 #5461453 買い 0.01 EURUSDeur at 1.23403 完了(注文#66745055に基づく)

2018.02.20 15:20:35.845 TestBUY (EURUSDeur,M15)retcode=10009 deal=0 order=66745055

要求が満たされた場合(10009)、なぜdeal=0なのか?

 
Ivan Ivanov:

リクエストが完了した場合(10009)、なぜdeal=0なのか?

ほぼそこから議論が 始まりましたね。リンク先に詳細があります。

OrderSendが完全に動作するソリューションもありますが、それは宣伝になります。

 
fxsaber:

簡単な例で見る正しい選択

一言で言えば、「成行注文があれば、それも『ポジション』と考えよ」ということです。包み込むようなポジションなので、引用符で囲んでいます。ハイライトされたコードは通常、どこにも表示されません。しかし、ポジションの再オープンを 回避することができます。ここで最も興味深いのは、赤で示した部分です。このチップの必要性はすぐにわかるものではありません。

いわゆる寄り付き成行注文があることです。同じSL/TPです。もちろん、このような成行注文を「ポジション」と見なすのは好ましくありません。そして、せっかく出した注文も閉まってしまうのは避けたい。つまり、ハイライトされた状態が適切なフィルターということになる。

for (int i = OrdersTotal() - 1; i >= 0; i--)
    if (OrderGetTicket(i) && (OrderGetInteger(ORDER_TYPE) <= ORDER_TYPE_SELL) &&
        !OrderGetInteger(ORDER_POSITION_ID) && (OrderGetString(ORDER_SYMBOL) == Symb))
      Res++;  

SZYここに このコードを挿入して、デモサーバーで 結果を確認してください。

興味のある方はぜひ、この問題について議論してください。この件に関する私の考えは以下の通りです。


  1. サーバーに注文を出す。
  2. 成行注文が表示され、最終的にはキャンセルされるかもしれないが、すでにポジションとしてカウントされているのか?
for (int i = OrdersTotal() - 1; i >= 0; i--)
    if (OrderGetTicket(i) && (OrderGetInteger(ORDER_TYPE) <= ORDER_TYPE_SELL) &&
        !OrderGetInteger(ORDER_POSITION_ID) && (OrderGetString(ORDER_SYMBOL) == Symb))
      Res++;  

このループは、ポジションIDを持たない(IDが0である)オーダーが見つかった場合、1つのポジションを追加します。

ポジションを1つ増やしました。

サーバーで注文がキャンセルされた場合はどうなりますか?

...

成行注文を計算するときに、例えば、1つ見つけた場合、WRONG_VALUEを返すべきだと思います - ポジションは0より小さくできません。これは、未記録の成行注文があることを示すシグナルとなる。しかし、ポジションの数を増やすことはしない。