Discusión sobre el artículo "Biblioteca para el desarrollo rápido y sencillo de programas para MetaTrader (Parte XXVI): Trabajando con las solicitudes comerciales pendientes - primera implementación"

 

Artículo publicado Biblioteca para el desarrollo rápido y sencillo de programas para MetaTrader (Parte XXVI): Trabajando con las solicitudes comerciales pendientes - primera implementación (apertura de posiciones):

En el presente artículo, vamos a organizar el guardado de ciertos datos en el valor del número mágico de las órdenes y posiciones, y también implementaremos las solicitudes comerciales. Para comprobar el concepto, crearemos una primera solicitud pendiente de prueba para abrir posiciones de mercado al recibir del servidor un error que requiera la espera y el envío de una solicitud repetida.

Compilamos e iniciamos el asesor. Desconectamos internet y esperamos a que aparezca este icono en la esquina inferior derecha:



Después de desconectar internet y pulsar el botón Sell, el servidor comercial retornará error, y en el diario se mostrarán las entradas:

2019.11.26 15:34:48.661 CTrading::OpenPosition<uint,uint>: Invalid request:
2019.11.26 15:34:48.661 No connection with the trade server
2019.11.26 15:34:48.661 Correction of trade request parameters ...
2019.11.26 15:34:48.661 Trading attempt #1. Error: No connection with the trade server

Al obtener este error, la biblioteca crea una solicitud pendiente con los parámetros existentes en el intento fallido de apertura de una posición corta.
En la solicitud pendiente también está registrado el número de intentos y un tiempo de espera de 20 segundos.

A continuación, conectamos internet, reestableciendo con ello la conexión con el servidor comercial:


En cuanto se reestablezca, la biblioteca comenzará a procesar la solicitud pendiente, enviando esta al servidor. Como resultado, tendremos una posición abierta con las siguientes entradas en el diario:

2019.11.26 15:35:00.853 CTrading::OpenPosition<double,double>: Invalid request:
2019.11.26 15:35:00.853 Trading is prohibited for the current account
2019.11.26 15:35:00.853 Correction of trade request parameters ...
2019.11.26 15:35:00.853 Trading operation aborted
2019.11.26 15:35:01.192 CTrading::OpenPosition<double,double>: Invalid request:
2019.11.26 15:35:01.192 Trading is prohibited for the current account
2019.11.26 15:35:01.192 Correction of trade request parameters ...
2019.11.26 15:35:01.192 Trading operation aborted
2019.11.26 15:35:01.942 - Position is open: 2019.11.26 10:35:01.660 -
2019.11.26 15:35:01.942 EURUSD Opened 0.10 Sell #486405595 [0.10 Market-order Sell #486405595] at price 1.10126, sl 1.10285, tp 1.09985, Magic number 17629307 (123), G1: 13
2019.11.26 15:35:01.942 OnDoEasyEvent: Position is open

Como podemos ver por el diario, después de reestablecer la conexión con el servidor comercial, el permiso de comercio para la cuenta actual no se ha activado de inmediato.
Pero, aun así, la solicitud comercial ha cumplido su parte
...

En el propio diario, podemos ver el número mágico real 17629307, tras este, entre paréntesis, vemos el número mágico establecido en los ajustes del asesor (123), además de la entrada G1: 13, que nos indica que el identificador del nuevo grupo es igual a 13; en cuanto al identificador del segundo grupo, no lo hay, ya que su valor es igual a cero, por eso no se ha mostrado una segunda entrada con el identificador del segunndo grupo G2: XX

Autor: Artyom Trishkin

 
Hola, he descargado la última versión de la biblioteca y Expert Part_26, poner el modo visual en el probador y las órdenes de mercado se abren, pero todas las órdenes pendientes no lo son.

órdenes se abren, pero todas las órdenes pendientes no lo son.

Símbolos de cambio, broker Otkritie, versión 5.00 build 2190.

 
Alexander:
Hola! He descargado la última versión de la biblioteca y Experto Part_26, poner el modo visual y el modo de mercado en el probador.

Las órdenes se abren, pero todas las órdenes pendientes no.

Símbolos de cambio, broker Otkritie, versión 5.00 build 2190.

Foro sobre trading, sistemas automatizados de trading y testeo de estrategias de trading

Discusión del artículo "Biblioteca para la creación fácil y rápida de programas para MetaTrader (Parte XXV): Manejo de errores devueltos por el servidor de trading"

Artyom Trishkin, 2019.11.28 09:39

En esta versión de la biblioteca, así como en la siguiente, se me pasó comprobar los tipos de llenado de órdenes y los tipos de caducidad de órdenes. Habrá correcciones en el próximo (27) artículo.

Por ahora, puedo sugerir que se especifique explícitamente el tipo de vencimiento al enviar una solicitud de operación. Por ejemplo, para colocar una orden pendiente Sell Limit, es necesario añadirlo en el Asesor Experto de prueba:

//--- Si se pulsa el botón BUTT_SELL_LIMIT: Fijar SellLimit
else if(button==EnumToString(BUTT_SELL_LIMIT))
  {
   //--- Establecer orden SellLimit
   engine.PlaceSellLimit(lot,Symbol(),distance_pending,stoploss,takeprofit,magic,TextByLanguage("PendienteVenderLímite","Pending order SellLimit"),0,ORDER_TIME_DAY);
  }

Y hacer lo mismo en todas las líneas que contienen la llamada de métodos para establecer órdenes pendientes.


 
Sí, gracias, así funciona.
 
//--- Ubicación de los datos en el número mágico valor int
      //-----------------------------------------------------------
      // bit 32|31 24|2316|15 8|7 0|
      //-----------------------------------------------------------
      // byte | 3 | 2| 1 | 0 |
      //-----------------------------------------------------------
      // data | uchar | uchar | ushort |
      //-----------------------------------------------------------
      // descr |pend req id| id2 | id1 | magic |
      //----------------------------------------------------------- 
//--- Devuelve (1) el numberber mágico especificado, el ID del (2) primer grupo, (3) segundo grupo, (4) petición pendiente del valor del numberber mágico
   ushort            GetMagicID(void)                                const { return ushort(this.Magic() & 0xFFFF);                                 }
   uchar             GetGroupID1(void)                               const { return uchar(this.Magic()>>16) & 0x0F;                                }
   uchar             GetGroupID2(void)                               const { return uchar((this.Magic()>>16) & 0xF0)>>4;                           }
   uchar             GetPendReqID(void)                              const { return uchar(this.Magic()>>24) & 0xFF;                                }

Existe una función muy práctica para extraer bits de un número.

//--- extraer cnt bits en la posición kth bit
   uint              _getBits(const uint number,uint pos,uint cnt=1) const { return (number >> pos) & ((1 << cnt) - 1);                            }
      
   ushort            GetMagicID(void)                                const { return ushort(_getBits(this.Magic(),0,16));                           }
   uchar             GetGroupID1(void)                               const { return uchar(_getBits(this.Magic(),16,4));                            }
   uchar             GetGroupID2(void)                               const { return uchar(_getBits(this.Magic(),20,4));                            }
   uchar             GetPendReqID(void)                              const { return uchar(_getBits(this.Magic(),24,8));                            }
 
amrali:

Existe una función muy práctica para extraer bits de un número.

Gracias
 
¿Existe alguna implementación en la biblioteca para abrir una ejecución de mercado inmediata?
 
iabbott:
¿Existe una implementación en la biblioteca para abrir una ejecución de mercado inmediata?
 

¿Podrías decirme, por favor, dónde exactamente, en qué método, se decodifica la magia codificada en la solicitud pendiente?

Después de un error al abrir una posición(fondos insuficientes) y luego de activar una solicitud pendiente, tengo una posición creada con una magia completamente diferente (aparentemente, la codificada).

¿Dónde se decodifica? Quiero un majik nativo, no uno nuevo.

 
void CTradingControl::OnPReqByErrCodeHandler()

Aquí es donde se supone que debes llamar al método que devuelve la magia original. ¿Y qué método es ese? ¿GetMagicID()?

 
//+------------------------------------------------------------------+
//| Devuelve el beneficio de la orden en pips|
//+------------------------------------------------------------------+
int COrder::ProfitInPoints(void) const
  {
   MqlTick tick={0};
   string symbol=this.Symbol();
   if(!::SymbolInfoTick(symbol,tick))
      return 0;
   ENUM_ORDER_TYPE type=(ENUM_ORDER_TYPE)this.TypeOrder();
   double point=::SymbolInfoDouble(symbol,SYMBOL_POINT);
   if(type==ORDER_TYPE_CLOSE_BY || point==0) return 0;
   if(this.Status()==ORDER_STATUS_HISTORY_ORDER)
      return int(type==ORDER_TYPE_BUY ? (this.PriceClose()-this.PriceOpen())/point : type==ORDER_TYPE_SELL ? (this.PriceOpen()-this.PriceClose())/point : 0);
   else if(this.Status()==ORDER_STATUS_MARKET_POSITION)
     {
      if(type==ORDER_TYPE_BUY)
         return int((tick.bid-this.PriceOpen())/point);
      else if(type==ORDER_TYPE_SELL)
         return int((this.PriceOpen()-tick.ask)/point);
     }
   else if(this.Status()==ORDER_STATUS_MARKET_PENDING)
     {
      if(type==ORDER_TYPE_BUY_LIMIT || type==ORDER_TYPE_BUY_STOP || type==ORDER_TYPE_BUY_STOP_LIMIT)
         return (int)fabs((tick.bid-this.PriceOpen())/point);
      else if(type==ORDER_TYPE_SELL_LIMIT || type==ORDER_TYPE_SELL_STOP || type==ORDER_TYPE_SELL_STOP_LIMIT)
         return (int)fabs((this.PriceOpen()-tick.ask)/point);
     }
   return 0;
  }

¿Por qué no hay cálculo aquí para el tipo ORDER_STATUS_DEAL?

En general, no está claro cómo obtener el beneficio en puntos de una operación o posición cerrada...
Y siempre es 0:

deal_profit_pts=(int)deal.GetProperty(ORDER_PROP_PROFIT_PT)