Typical mistakes and how to deal with them when dealing with the trading environment - page 3

 
fxsaber:

The right option using a simple example

I think it is better to wait for the order to be taken into account if it is not yet in the position.
 
Комбинатор:
I think it is better if the order has not yet been accounted for in the position, just wait for it to be accounted for.

I don't get the idea.

 
Conditional Implementation Scheme for Normal OrderSend (No Timeout)
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);
}


This diagram shows that when a market order is placed using OrderSendAsync in MetaQuotes-Demo, it is impossible to reliably catch the corresponding order being placed until the order is either executed or rejected. I.e. there are no simple mechanisms in MT5 for evaluating intermediate results of their OrderSendAsync.

 

seems to be in theme,

I would like to point out that this code :

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

works flawlessly on the DEMO (result=request),

but on REAL - it's impossible to get a result (result=0.0). ... Unless you wait a few seconds.

 
Ivan Ivanov:

Seems to be in the subject,

I would like to point out that such code :

On DEMO it works flawlessly (result=request),

but on REAL - it's impossible to get result (result=0.0). ... Unless you wait a few seconds.

Data is missing - logs, structure field values after OrderSend, trade server name.

 
fxsaber:

The point in a nutshell is this: if there is a market order, consider it a 'position' as well. In inverted commas because it is a wrapped position. The highlighted code usually does not appear anywhere. But it avoids re-opening positions. The most interesting thing here is highlighted in red. The need for this chip is not immediately apparent.

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++;  // если мы сюда попадаем при проверке состояния, не запускать стратегию вообще, т.к. это промежуточное состояние.
 
Комбинатор:

There may not be a trade signal on the next tick. I use MT4-style myself, so I can't help but see such "positions" without getting in trouble.

 
fxsaber:

Data is missing - logs, structure field values after OrderSend, trade server name.

//+------------------------------------------------------------------+
//|                                                      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 Trades order #66745055 buy 0.01 / 0.01 EURUSDeur at market done in 610.625 ms

2018.02.20 15:20:35.935 Trades deal #5461453 buy 0.01 EURUSDeur at 1.23403 done (based on order #66745055)

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

If the request is met (10009) , why deal=0

 
Ivan Ivanov:

If the request is done (10009) , why deal=0

That's almost where the discussion started. The links have all the details.

There is a solution for OrderSend to work perfectly, but that would be advertising.

 
fxsaber:

The right option using a simple example

The point in a nutshell is this: if there is a market order, consider it a "position" as well. In quotes, because it's a wrapped position. The highlighted code usually doesn't appear anywhere. But it avoids re-opening positions. The most interesting thing here is highlighted in red. The need for this chip is not immediately apparent.

The matter is that there are so-called closing market orders. The same SL/TP. Obviously, we would not like to see such market orders as "positions". And we would not like to see those orders that we have placed to close as well. So the highlighted condition is the appropriate filter.

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 Insert this code here and check the result on the demo server.

I invite all interested to discuss this question. My opinion on this matter is as follows:


  1. Send order to server
  2. A market order appears and may eventually be cancelled, but have we already counted it as a position?
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++;  

This loop adds one position if an order is found that does not have a position identifier (the ID is zero).

We have returned one more position.

What if the order is cancelled by the server?

...

I think that when calculating market orders, we should return WRONG_VALUE, for example, if we have found one - positions cannot be less than zero. This will be a signal that there is an unrecorded market order. But not to add the number of positions.