OrderSend() questions - page 5

 

Apparently, I didn't explain the previous problem very clearly. Let me try again.

During the last year, the description of theENUM_ORDER_TYPE_FILLING enumeration value list has been changed at least three times. The previous description looked as follows

ENUM_ORDER_TYPE_FILLING

Identifier

Description

ORDER_FILLING_FOK

A trade can only be executed in the volume specified and at a price equal to or better than that specified in the order. If there is not enough supply on the market at the moment for the order symbol then the order will not be filled. This filling type is used in the SYMBOL_TRADE_EXECUTION_INSTANT execution mode or SYMBOL_TRADE_EXECUTION_REQUEST.

ORDER_FILLING_IOC

An agreement to execute a trade at the maximum volume available in the market within the volume specified in the order and at a price equal to or better than that specified in the order. In this case no additional orders will be placed for the lacking volume. This filling type can be available only in the execution modes SYMBOL_TRADE_EXECUTION_MARKET andSYMBOL_TRADE_EXECUTION_EXCHANGE depending on the settings on the trade server.

ORDER_FILLING_RETURN

Agreement to make a trade at the maximum volume available on the market within the volume specified in the order and at a price equal to or better than that specified in the order. In this case an additional order will be placed for the missing volume at the price specified in this order. This filling type is used only for pending orders (TRADE_ACTION_PENDING).

As we can easily see, there is a one-to-one correspondence between ORDER_FILLING_RETURN and pending orders, namely: ORDER_FILLING_RETURN could be applied only to pending orders and the type_filling fieldof all pending orders could be filled only with the value of ORDER_FILLING_RETURN.

For market orders(action==TRADE_ACTION_DEAL) the field type_filling should have been filled out depending on the execution modes set on the server side.

Thus we had a certain paradigm: if there was a pending order,ORDER_FILLING_RETURN; if there was a market order, ORDER_FILLING_FOK or ORDER_FILLING_IOC (depending on the mode).

Now we have turned things upside down a bit, namely:

ENUM_ORDER_TYPE_FILLING

Identifier

Description

ORDER_FILLING_FOK

This order filling policy means that the order can only be filled to the specified volume. If there is not enough volume of the financial instrument in the market at the moment, the order will not be executed. The required volume can be compiled from several offers currently available in the market.

ORDER_FILLING_IOC

Indicates agreement to execute a trade to the maximum volume available in the market within the volume specified in the order. If full execution is not possible, the order will be filled to the available volume, and the unfulfilled volume will be canceled.

ORDER_FILLING_RETURN

This mode is only used for ORDER_TYPE_BUY_LIMIT and ORDER_TYPE_SELL_LIMIT orders. In case of partial execution the limit order with the remaining volume is not deleted but remains in effect.

For ORDER_TYPE_BUY_STOP_LIMIT and ORDER_TYPE_SELL_STOP_LIMIT orders the corresponding ORDER_TYPE_BUY_LIMIT/ORDER_TYPE_SELL_LIMIT limit order with the ORDER_FILLING_RETURN execution type will be created on activation.

The restriction of using ORDER_FILLING_FOK and ORDER_FILLING_IOC only with market orders is gone. Also there is no restriction on using ORDER_FILLING_FOK and ORDER_FILLING_IOC with market orders depending on the execution mode set on the server. There is a restriction on using ORDER_FILLING_RETURN only with limit and stop_limit orders .

So my question is: Is it acceptable to use ORDER_FILLING_FOK and ORDER_FILLING_IOC at all for all orders (both market and pending) including limit and stop_limit orders? Has anyone figured out the changes?

 

The Standard Library has this method (schematic):

bool CTrade::PositionClose(const string symbol,ulong deviation)
  {
   do
     {
      //--- checking
      if(PositionSelect(symbol))
        {
         if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
           {
            //--- prepare request for close BUY position
            m_request.type =ORDER_TYPE_SELL;
            m_request.price=SymbolInfoDouble(symbol,SYMBOL_BID);
           }
         else
           {
            //--- prepare request for close SELL position
            m_request.type =ORDER_TYPE_BUY;
            m_request.price=SymbolInfoDouble(symbol,SYMBOL_ASK);
           }
        }
      else
        {
         //--- position not found
         m_result.retcode=retcode;
         return(false);
        }
      m_request.action      =TRADE_ACTION_DEAL;
      m_request.volume      =PositionGetDouble(POSITION_VOLUME);
      //--- check volume
      double max_volume=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX);
      if(m_request.volume>max_volume)
        {
         m_request.volume=max_volume;
         partial_close=true;
        }
      else
         partial_close=false;
      //--- order send
      if(!OrderSend(m_request,m_result))
        {
         if(--retry_count!=0) continue;
         if(retcode==TRADE_RETCODE_DONE_PARTIAL)
            m_result.retcode=retcode;
         return(false);
        }
      retcode=TRADE_RETCODE_DONE_PARTIAL;
      if(partial_close) Sleep(1000);
     }
   while(partial_close);
   return(true);
  }

Here, in case the position volume is greater thanthe maximum volume for making a trade, successive attempts to partially close the position are made.

After a successful call of the OrderSend() function, a seconds delay is set and then thePositionSelect() function is called in the body of the do-while loop. I.e. it is supposed that in case the server successfully accepts a market order, one second is enough to update the data about the open position in the base terminal and get the updated position data (in our example - the position volume) at the next iteration. But two years ago, the delay in the same method before calling the PositionSelect() function was three seconds. The question is therefore:

Is one second sufficient in all cases to ensure that after a successful call to OrderSend(), the terminal database is guaranteed to receive updated position data (and thereby allow the remaining position volume to be processed correctly on the terminal side)? What is the maximum time in which the terminal database should be guaranteed to receive updated position data in this case?

 

The championship has this rule:

Trading conditions will be as close to real as possible:

  • Processing time of trade requests from 2 to 7 seconds
On real with one broker (after withdrawal) processing became about 3 seconds (opening-closing-modification).Immediately switched to NDD.Satisfied so far.
 
Karlson:

The championship has this rule:

Trading conditions will be as close to real as possible:

  • processing time of 2 to 7 seconds

OK, thanks for the tip! It turns out that one second is not enough for the terminal database to receive the updated position data after a successful call of the OrderSend() function ?

From this conclusion, it follows that the Standard Library method I cited does not guarantee at all that the position will be reversed instead of being closed. I.e., if the PositionClose() method delays the next iteration by one second, and trade requests can take 2-7 times longer to process, we cannot rule out that during the new iterations, thePositionSelect() function will receive the previous information about position's state from the base terminal and bombard the server with identical orders, whose total volume in this case will be larger than theinitial amount of the position being closed.

Why then is there a one-second delay in the PositionClose() method, if it allows to flip the position instead of closing it? And it is not consistent with the "trading conditions, as close as possible to the real ones"?

In general, I need more information about how long the terminal database, after a successful call of the OrderSend() function, is guaranteed to receive the updated position data, and what is the reason for the one-second delay in the standard PositionClose() method.

 
Let us start with the fact that
if(PositionSelect(symbol))

does not guarantee anything. It cannot be used.

Secondly, no guarantees are provided for the terminal data update. You have to set up an artificial TradeContextBusy yourself and wait for all of your orders to be processed.
You cannot do it immediately and head-on into MQL5. There are no time guarantees.

 

sergeev:

начнем с того, что

if(PositionSelect(symbol))

does not guarantee anything. It cannot be applied.

Secondly, there is no guarantee for terminal data update - you have to organize an artificial TradeContextBusy yourself and wait for all of your orders to be processed.
You cannot use MQL5 directly and directly. There are no time guarantees.

Yep, I'll have to keep pondering. It turns out that I should have taken the standard method from the library as an example for recycling.

Can you tell me if a deal appears in the history with the

DEAL_ENTRY_OUT

Market Exit

does it mean that all information in the database of the terminal has automatically changed (updated to the current state)? Or the trade may already appear in the history and information about the position will still not be updated? In other words, the question is interesting: do information about deals in the history and information about the corresponding positions change simultaneously? Or, in this case, the deals and positions are also updated in the terminal asynchronously? I did not manage to catch it in Rosh's article - as far as I understood it, the asynchrony between the terminal base update and the return of the trade request result is described there.

 

The data exchange model in the terminal is asynchronous, as you noticed.

so when trading (retrieving properties of orders/trades/positions) we need to analyse the success of data retrieval. And in the case of any error (false/0), terminate the analysis of the trading logic.

All the executed and unconfirmed OrderSend orders will be remembered and wait for the appearance of the order, blocking the new order sending itself if there is no answer from the previous sending yet.

And, for example, it would be better to replace PositionSelect with a construct

for(int i=PositionsTotal()-1;i>=0;i--) 
{
  if(PositionGetSymbol(i)==Symbol())
  {
    ....
  }

In general, the trading logic must be asynchronous. Since the terminal is asynchronous, the MT-server and the server of the liquidity provider are asynchronous.

The task of checking the synchronization is entirely up to the MQL programmer.

Документация по MQL5: Стандартные константы, перечисления и структуры / Торговые константы / Типы торговых операций
Документация по MQL5: Стандартные константы, перечисления и структуры / Торговые константы / Типы торговых операций
  • www.mql5.com
Стандартные константы, перечисления и структуры / Торговые константы / Типы торговых операций - Документация по MQL5
 

I had no problem using this answer in the last championship

https://www.mql5.com/ru/forum/4342#comment_88688

Дублирование запросов на открытие позиций.
Дублирование запросов на открытие позиций.
  • www.mql5.com
Дублирование запросов на открытие позиций.
 
sergeev:

And, for example, it would be better to replace PositionSelect with the construct

for(int i=PositionsTotal()-1;i>=0;i--) 
{
  if(PositionGetSymbol(i)==Symbol())
  {
    ....
  }

Please explain, if it's not difficult, what is the advantage of usingPositionsTotal() + PositionGetSymbol() over using PositionSelect()? All three functions are accessing the same terminal base, and the PositionGetSymbol() and PositionSelect() functions may fail. I.e., if the position exists in the terminal base, both the PositionSelect() function and the proposed construction may fail. You still have to check the error code.

What are peculiarities/reliability of your construct? I still couldn't figure it out.

Документация по MQL5: Торговые функции / PositionSelect
Документация по MQL5: Торговые функции / PositionSelect
  • www.mql5.com
Торговые функции / PositionSelect - Документация по MQL5
 

I'm racking my brains... the stop just won't set... and a lot of errors. this is what's left of the experiment, and it doesn't work any more

void OnTick(){ if(PositionsTotal()<1){OPEN();}}

bool OPEN(){
             MqlTradeRequest request;
             MqlTradeResult result;
             

             request.symbol       = _Symbol;
             request.action       = TRADE_ACTION_DEAL;
             request.type_filling = ORDER_FILLING_FOK;
             request.deviation    = 100;
             request.volume       = NormalizeDouble(2,2);
             request.type         = ORDER_TYPE_BUY;
             request.price        = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
             request.tp           = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK) + 500*_Point,_Digits);
             request.sl           = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK) - 500*_Point,_Digits);

             OrderSend(request,result);     
                        
             if(result.retcode==10009 || result.retcode==10008)  Print("Succsesful open");
             else                                               Print("Error open: ",DoubleToString(GetLastError(),0),"  response code: ",result.retcode);
    
   return(true);}

If you do this, there are no errors, but the stop-loss is still not set

MqlTradeRequest request={0};MqlTradeResult result={0};
Reason: