Preguntas de OrderSend() - página 5

 

Por lo visto, no he explicado bien el problema anterior. Déjame intentarlo de nuevo.

Durante el último año, la descripción de la lista de valores de la enumeraciónENUM_ORDER_TYPE_FILLING se ha modificado al menos tres veces. La descripción anterior era la siguiente

ENUM_ORDER_TYPE_FILLING

Identificador

Descripción

ORDER_FILLING_FOK

Una operación sólo puede ejecutarse en el volumen especificado y a un precio igual o mejor que el especificado en la orden. Si no hay suficiente oferta en el mercado en ese momento para el símbolo de la orden, ésta no se ejecutará. Este tipo de llenado se utiliza en el modo de ejecución SYMBOL_TRADE_EXECUTION_INSTANT oSYMBOL_TRADE_EXECUTION_REQUEST.

ORDER_FILLING_IOC

Un acuerdo para ejecutar una operación al máximo volumen disponible en el mercado dentro del volumen especificado en la orden y a un precio igual o mejor que el especificado en la orden. En este caso, no se realizarán pedidos adicionales para el volumen que falta. Este tipo de llenado sólo puede estar disponible en los modos de ejecución SYMBOL_TRADE_EXECUTION_MARKET ySYMBOL_TRADE_EXECUTION_EXCHANGE dependiendo de la configuración del servidor de operaciones.

ORDER_FILLING_RETURN

Acuerdo para ejecutar una operación en el volumen máximo disponible en el mercado dentro del volumen especificado en la orden y a un precio igual o mejor que el especificado en la orden. En este caso, se realizará un pedido adicional por el volumen que falte al precio especificado en este pedido. Este tipo de llenado se utiliza sólo para las órdenes pendientes (TRADE_ACTION_PENDING).

Como podemos ver fácilmente, existe una correspondencia uno a uno entre ORDER_FILLING_RETURN y las órdenes pendientes, a saber ORDER_FILLING_RETURN podría aplicarse sólo a las órdenes pendientes y el campo type_filling de todas las órdenes pendientes podría llenarse sólo con el valor de ORDER_FILLING_RETURN.

En el caso de las órdenes de mercado(action==TRADE_ACTION_DEAL) el campo type_filling debería haberse rellenado en función de los modos de ejecución establecidos en el lado del servidor.

Así, teníamos un cierto paradigma: si había una orden pendiente,ORDER_FILLING_RETURN; si había una orden de mercado, ORDER_FILLING_FOK u ORDER_FILLING_IOC (dependiendo del modo).

Ahora todo está un poco al revés, a saber:

ENUM_ORDER_TYPE_FILLING

Identificador

Descripción

ORDER_FILLING_FOK

Esta política de llenado de órdenes significa que la orden sólo puede llenarse hasta el volumen especificado. Si no hay suficiente volumen del instrumento financiero en el mercado en ese momento, la orden no se ejecutará. El volumen requerido puede ser compilado a partir de varias ofertas actualmente disponibles en el mercado.

ORDER_FILLING_IOC

Indica el acuerdo para ejecutar una operación hasta el volumen máximo disponible en el mercado dentro del volumen especificado en la orden. Si la ejecución completa no es posible, la orden se llenará hasta el volumen disponible, y el volumen no cumplido se cancelará.

ORDER_FILLING_RETURN

Este modo sólo se utiliza para las órdenes ORDER_TYPE_BUY_LIMIT y ORDER_TYPE_SELL_LIMIT. En caso de ejecución parcial, la orden limitada con el volumen restante no se elimina, sino que sigue vigente.

Para las órdenes ORDER_TYPE_BUY_STOP_LIMIT y ORDER_TYPE_SELL_STOP_LIMIT se creará en el momento de la activación la correspondiente orden limitada ORDER_TYPE_BUY_LIMIT/ORDER_TYPE_SELL_LIMIT con el tipo de ejecución ORDER_FILLING_RETURN.

La restricción de utilizar ORDER_FILLING_FOK y ORDER_FILLING_IOC sólo con órdenes de mercado ha desaparecido. Tampoco existe ninguna restricción para utilizar ORDER_FILLING_FOK y ORDER_FILLING_IOC con órdenes de mercado en función del modo de ejecución establecido en el servidor. Hay una restricción en el uso de ORDER_FILLING_RETURN sólo con órdenes limitadas y stop_limit .

Así que mi pregunta es: ¿Es aceptable utilizar ORDER_FILLING_FOK y ORDER_FILLING_IOC para todas las órdenes (tanto de mercado como pendientes), incluidas las órdenes limitadas y stop_limit? ¿Alguien ha descubierto los cambios?

 

La Biblioteca Estándar dispone de este método (esquema):

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);
  }

Aquí, en caso de que el volumen de la posición sea mayor queel volumen máximo para realizar una operación, se realizansucesivos intentos de cierre parcial de la posición.

Después de una llamada exitosa de la función OrderSend(), se establece un retraso de segundos y luego se llama a la funciónPositionSelect() en el cuerpo del bucle do-while. Es decir, se supone que en caso de que el servidor acepte con éxito una orden de mercado, un segundo es suficiente para actualizar los datos sobre la posición abierta en el terminal base y obtener los datos de posición actualizados (en este ejemplo - el volumen de la posición) en la siguiente iteración. Pero hace dos años, el retraso en el mismo método antes de llamar a la función PositionSelect() era de tres segundos. Por lo tanto, la pregunta es:

¿Es suficiente un segundo en todos los casos para asegurar que después de una llamada exitosa a OrderSend(), la base de datos del terminal está garantizada para recibir datos de posición actualizados (y por lo tanto permitir que el volumen de posición restante sea procesado correctamente en el lado del terminal)? ¿Cuál es el tiempo máximo en el que se debe garantizar que la base de datos del terminal reciba datos de posición actualizados en este caso?

 

El campeonato tiene esa regla:

Lascondiciones de negociación serán lo más parecidas a las reales:

En real con un corredor (después de la retirada) el procesamiento se convirtió en unos 3 segundos (apertura-cierre-modificación).Inmediatamente cambió a NDD.Satisfecho hasta ahora.
 
Karlson:

El campeonato tiene esta regla:

Lascondiciones de negociación serán lo más parecidas a las reales:

  • tiempo de procesamiento de 2 a 7 segundos

Bien, ¡gracias por el consejo! Resulta que un segundo no es suficiente para que la base de datos del terminal reciba los datos de posición actualizados tras una llamada exitosa de la función OrderSend()?

De esta conclusión se deduce que el método de la Biblioteca Estándar que he citado no garantiza en absoluto que la posición se invierta en lugar de cerrarse. Es decir, si el método PositionClose() retrasa un segundo la siguiente iteración, y las solicitudes de negociación pueden tardar entre 2 y 7 veces más en procesarse, no podemos descartar que durante las nuevas iteraciones, la funciónPositionSelect() reciba la información previa sobre el estado de la posición desde el terminal base y bombardee el servidor con órdenes idénticas, cuyo volumen total en este caso será mayor que elimporte inicial de la posición que se cierra.

¿Por qué entonces hay un retraso de un segundo en el método PositionClose(), si permite voltear la posición en lugar de cerrarla? ¿Y no es coherente con las"condiciones comerciales, lo más parecidas a las reales"?

En general, necesito más información sobre cuánto tiempo se garantiza que la base de datos del terminal, después de una llamada exitosa de la función OrderSend(), reciba los datos de posición actualizados, y cuál es la razón del retraso de un segundo en el método estándar PositionClose().

 
Empecemos por el hecho de que
if(PositionSelect(symbol))

no garantiza nada. No se puede aplicar.

En segundo lugar, no se ofrece ninguna garantía para la actualización de los datos del terminal. Usted mismo tiene que establecer un TradeContextBusy artificial y esperar a que se procesen todas sus órdenes.
No se puede hacer inmediatamente y de frente en MQL5. No hay garantías de tiempo.

 

sergeev:

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

if(PositionSelect(symbol))

no garantiza nada. No se puede aplicar.

En segundo lugar, no se garantiza la actualización de los datos de la terminal: usted mismo tiene que organizar un TradeContextBusy artificial y esperar a que se procesen todas sus órdenes.
No se puede utilizar MQL5 directa y directamente. No hay garantías de tiempo.

Sí, tendré que seguir reflexionando. Resulta que debería haber tomado el método estándar de la biblioteca como ejemplo para el reciclaje.

¿Puede decirme si en el historial aparece un acuerdo con el

DEAL_ENTRY_OUT

Salida del mercado

¿significa que toda la información de la base de datos del terminal ha cambiado automáticamente (se ha actualizado al estado actual)? ¿O es posible que la operación ya aparezca en el historial y la información sobre la posición siga sin actualizarse? En otras palabras, la pregunta es interesante: ¿cambian simultáneamente la información sobre los acuerdos en el historial y la información sobre las posiciones correspondientes? ¿O, en este caso, las operaciones y las posiciones también se actualizan en el terminal de forma asíncrona? No logré captarlo en el artículo de Rosh - por lo que entendí, allí se describe la asincronía entre la actualización de la base del terminal y la devolución del resultado de la solicitud de comercio.

 

El modelo de intercambio de datos en el terminal es asíncrono, como has notado.

por lo que al operar (recuperar las propiedades de las órdenes/operaciones/posiciones) debemos analizar el éxito de la recuperación de datos. Y en el caso de cualquier error (falso/0), terminar el análisis de la lógica comercial.

Todas las órdenes ejecutadas y no confirmadas de OrderSend serán recordadas y esperarán la aparición de la orden, bloqueando el nuevo envío de la orden misma si no hay respuesta del envío anterior todavía.

Y, por ejemplo, sería mejor sustituir PositionSelect por una construcción

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

En general, la lógica comercial debe ser asíncrona. Dado que el terminal es asíncrono, el servidor MT y el servidor del proveedor de liquidez son asíncronos.

La tarea de comprobar la sincronización depende enteramente del programador de MQL.

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

No tuve ningún problema en utilizar esta respuesta en el último campeonato

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

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

Y, por ejemplo, sería mejor sustituir PositionSelect por la construcción

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

Por favor, explique, si no es difícil, ¿cuál es la ventaja de utilizarPositionsTotal() + PositionGetSymbol() sobre el uso de PositionSelect()? Las tres funciones acceden a la misma base de terminales, y PositionGetSymbol() y PositionSelect() pueden fallar. Es decir, si la posición existe en la base terminal, tanto la función PositionSelect() como la construcción propuesta pueden fallar. Todavía tienes que comprobar el código de error.

¿Cuáles son las peculiaridades/fiabilidad de su construcción? Todavía no he podido entenderlo.

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

Me estoy devanando los sesos... el tope no cuaja... y un montón de errores. esto es lo que queda del experimento, y ya no funciona

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);}

Si hago esto, no hay errores, pero el stop-loss sigue sin estar fijado

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