Bibliotecas: MT4Orders - página 12

 
Un ejemplo de lo concisa y fiable que puede ser la parte comercial de un Asesor Experto cuando se utiliza la biblioteca en una cuenta neta.

Señales comerciales para MetaTrader 5 con ejecución automática en su cuenta

LCHI2017

MetaTrader 5
Gratis

El Asesor Experto opera con instrumentos bursátiles.

#include <MT4Orders.mqh>     // https://www.mql5.com/es/code/16006
#include <TypeToBytes.mqh>   // https://www.mql5.com/es/code/16280
#include <Price_Compare.mqh> // https://www.mql5.com/es/code/16169

sinput double exLots = 1;

int OrderScan( const int Type0, const int Type1 = -1, const int Type2 = -1, const int Type3 = -1 )
{
  int Res = -1;

  int Types[4];
    
  Types[0] = Type0;
  Types[1] = Type1;
  Types[2] = Type2;
  Types[3] = Type3;
  
  for (int i = 0; (i < 4) && (Types[i] != -1) && (Res == -1); i++)
    for (int j = OrdersTotal() - 1; j >= 0; j--)
      if (OrderSelect(j, SELECT_BY_POS) && (OrderType() == Types[i]) && (OrderSymbol() == _Symbol))
      {
        Res = Types[i];
        
        break;
      }
      
  return(Res);    
}

bool MyOrderModify( const double Price )
{
  return((CP(Price) != OrderOpenPrice()) && OrderModify(OrderTicket(), Price, 0, 0, 0));
}

bool MyOrderSend( const int Type, const double Price )
{
  const double Lots = exLots + OrderLots();      
  
  return((OrderScan(Type) == -1) ? OrderSend(_Symbol, Type, Lots, Price, 0, 0, 0) : MyOrderModify(Price));
}

MqlTick Ticks[];

void OnTick( void )
{  
  static const MqlTick NullTick = {0};
  
  const MqlTick Level = GetLevel(Ticks);
  
  if (_R(Level) != NullTick)
  {
    const int Type = OrderScan(OP_BUY, OP_SELL, OP_BUYLIMIT, OP_SELLLIMIT);
    
    if (Type == OP_BUY)
      MyOrderSend(OP_SELLLIMIT, Level.bid);
    else if (Type == OP_SELL)
      MyOrderSend(OP_BUYLIMIT, Level.ask);
    else if (Type != -1)
      MyOrderModify((OrderScan(OP_BUYLIMIT, OP_SELLLIMIT) == OP_BUYLIMIT) ? Level.ask : Level.bid);
    else
      OrderSend(_Symbol, OP_BUYLIMIT, exLots, Level.ask, 0, 0, 0);
  }
  
  return;
}
 
Muy útil, ¡gracias!
 
La última versión está siempre aquí.
 

Un script que muestra una peculiaridad de la implementación de OrderSelect en el modo SELECT_BY_POS+MODE_TRADES

#include <MT4Orders.mqh>
#include <MQL4_To_MQL5.mqh>

void OnStart()
{
  OrderSend(_Symbol, OP_BUYLIMIT, 1, Ask - 100 * _Point, 0, 0, 0);  // Establecer BuyLimit
  OrderSend(_Symbol, OP_SELLLIMIT, 1, Bid + 100 * _Point, 0, 0, 0); // Fijar límite de venta
  OrderSend(_Symbol, OP_BUY, 1, Ask, 100, 0, 0);                    // Abrió una posición de compra
  
  bool FirstRun = true;
  
  for (int i = OrdersTotal() - 1; i >= 0; i--)
    if (OrderSelect(i, SELECT_BY_POS))
    {
      OrderPrint();
      
      if (FirstRun)
      {
        OrderSend(_Symbol, OP_SELL, 1, Bid, 100, 0, 0); // Abrir posición de venta
        
        FirstRun = false;
      }
    }    
}

MT4

#196155484 2017.05.04 15:38:07 buy 1.00 EURUSD 1.09229 0.00000 0.00000 1.09221 0.00 0.00 -8.00  0
#196155480 2017.05.04 15:38:06 sell limit 1.00 EURUSD 1.09321 0.00000 0.00000 1.09221 0.00 0.00 0.00  0
#196155479 2017.05.04 15:38:06 buy limit 1.00 EURUSD 1.09129 0.00000 0.00000 1.09229 0.00 0.00 0.00  0

MT5

#147352190 2017.05.04 15:38:06 sell limit 1.00 EURUSD 1.09322 0.00000 0.00000 1.09222 0.00 0.00 0.00 0
#147352193 2017.05.04 15:38:06 sell 1.00 EURUSD 1.09222 0.00000 0.00000 1.09231 0.00 0.00 -9.00 0
#147352191 2017.05.04 15:38:06 buy 1.00 EURUSD 1.09231 0.00000 0.00000 1.09222 0.00 0.00 -9.00 0

A pesar de que el resultado de trading del script es idéntico en ambas plataformas, OrderSelect funciona de forma diferente. De ahí los diferentes registros.

El script está especialmente escrito, y no puedo recomendar este estilo de escribir lógica de trading, ya que está plagado de errores lógicos difíciles de ver en cada plataforma. Y tal código deja de ser 100% idéntico en la ejecución.

Por eso no parece conveniente corregir la librería para que esas curvas raras de MT4 se ejecuten en MT5 de forma absolutamente perfecta, como ocurre con el código normal.

Si estoy equivocado en cuanto a la curvatura y rareza de tales construcciones de trading en MT4, por favor, acláremelo.

 
De alguna manera incluso resulta divertido con la ralentización.
 
Vitaly Muzichenko:
Es curioso lo de la ralentización.

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

MT4-Tester VS MT5-Tester

fxsaber, 2017.05.08 01:11 pm.

Si hay dudas de que la ralentización de MT5 se deba al uso de una librería de terceros, quien lo desee puede reescribir la lógica simple de MT4 de este EA en MQL5 a su gusto y probar la hipótesis.
 
fxsaber:

Un script que muestra una peculiaridad de la implementación de OrderSelect en modo SELECT_BY_POS+MODE_TRADES

El script está especialmente chupado, y no puedo recomendar este estilo de escribir lógica de trading

Con otro estilo muy poco recomendable de escribir la lógica de trading, te puedes encontrar con otra característica de OrderSelect, pero ya en modo SELECT_BY_TICKET+MODE_HISTORY.

#include <MT4Orders.mqh>

#define Ask (::SymbolInfoDouble(_Symbol, SYMBOL_ASK))

void OnTick()
{
  static bool FirstRun = true;
  
  if (FirstRun && OrderSelect(OrderSend(_Symbol, OP_BUY, 1, Ask, 0, 0, 0), SELECT_BY_TICKET) &&
      OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 0))  
  {
    Print(OrderTicket()); // 2 - posición ABIERTA fue con este billete
    
    Print(OrderSelect(OrderTicket(), SELECT_BY_TICKET, MODE_HISTORY)); // falso, потому что тикет ЗАКРЫТОЙ позиции равен тикету закрывающей сделки.
    Print(OrderSelect(OrderTicket() + 1, SELECT_BY_TICKET, MODE_HISTORY)); // verdadero, por la razón anterior.
      
    FirstRun = false;
  }
}

Este es un Asesor Experto para un probador. En los comentarios está la razón de este comportamiento. Y es correcto debido a

  • El ticket de una posición abierta (por regla general) es igual al ticket de la orden de apertura (no de una operación). (Términos MT5).
  • Si una posición se cierra parcialmente, los tickets de las posiciones correspondientes cerradas no deben ser iguales al ticket de la posición abierta para evitar ambigüedades. (Términos MT5).

  • Es decir, la propia MT5 está hecha tan "torticeramente" que es difícil pensar en otro comportamiento para MT4Orders. Por supuesto, si haces SELECT_BY_POS por historial primero, registrando todos los tickets, entonces SELECT_BY_TICKET funcionará sin problemas.

    En general, si la lógica de trading de MT4 está escrita "mal", puede haber discrepancias entre MT5+MT4Orders y los resultados de MT4, que son inusuales para la comprensión de MT4. Si se sigue el estilo de escritura "correcto" de MT4, no se habrán detectado problemas en la librería.

     
    fxsaber:

    Si utiliza otro estilo muy poco recomendable de escribir la lógica de operación, puede encontrarse con otra característica de OrderSelect, pero ya en modo SELECT_BY_TICKET+MODE_HISTORY.

    En general, si la lógica de trading de MT4 está escrita "mal", puede haber discrepancias no acostumbradas para MT4 entre MT5+MT4Orders y los resultados de MT4. Si te ciñes al estilo de escritura "correcto" de MT4, no encontrarás ningún problema en la librería.


    La librería es impresionante, muchas gracias :) Después de añadir la sincronización de la historia es indispensable. Funciona rápido incluso para estrategias hft

    Yo lo añadiría a la entrega estándar de mt5

     

    Actualización

    // Lista de cambios:
    // 14.06.2017:
    // Añadir: Se habilita la implementación de la detección SL/TP de posiciones cerradas (cerradas mediante OrderClose).
    // Añadir: MagicNumber es ahora de tipo long - 8 bytes (antes era int - 4 bytes).
    // Añadir: Si en OrderSend, OrderClose o OrderModify el parámetro de entrada de color (el más reciente) se establece igual a INT_MAX, se generará.
    // la solicitud de operación MT5 correspondiente (MT4ORDERS::LastTradeRequest), pero NO se enviará. En su lugar, se comprobará MT5,
    // cuyo resultado estará disponible en MT4ORDERS::LastTradeCheckResult.
    // Si OrderModify y OrderClose tienen éxito, devolverán true, en caso contrario devolverán false.
    // OrderSend devolverá 0 si tiene éxito, en caso contrario -1.
    //
    // Si el parámetro de entrada de color correspondiente se establece como INT_MIN, SÓLO en caso de que MT5 compruebe con éxito el valor generado
    // solicitud comercial (como en el caso de INT_MAX) se enviará.
    // Añadir: Añadidos análogos asíncronos de las funciones de trading de MQL4: OrderSendAsync, OrderModifyAsync, OrderCloseAsync, OrderDeleteAsync.
    // Devuelve el Result.request_id correspondiente si tiene éxito, en caso contrario 0.

    El modo INT_MIN le permite deshacerse por completo de la saturación de los registros del comprobador - es especialmente crítico durante la optimización, porque debido a una lógica comercial errónea, los mensajes abundantes pueden reducir el rendimiento de la optimización muchas veces y, en consecuencia, aumentar no sólo el tiempo sino también los costes monetarios (Nube).

    También es conveniente a la hora de posiciones cerradas.

    Quizás algún día esta funcionalidad se convierta en estándar para MT5.


    Ejemplo de uso de funciones asíncronas MQL4

    #property script_show_inputs
    
    sinput int Amount = 5; // Número de prueba OrderSend(Async)
    
    #include <MT4Orders2.mqh>
    
    #define Ask SymbolInfoDouble(_Symbol, SYMBOL_ASK)
    #define  PRINT(A) Print(#A + " = " + (string)(A));
    
    void OnStart()
    {  
    // OrderSendAsync  
      const ulong StartTime1 = GetMicrosecondCount();
      
      for (int i = 0; i < Amount; i++)
        PRINT(OrderSendAsync(NULL, OP_BUY, 0.1, Ask, 100, 0, 0))
        
      PRINT(GetMicrosecondCount() - StartTime1)
    
    // OrderSend
      const ulong StartTime2 = GetMicrosecondCount();
      
      for (int i = 0; i < Amount; i++)
      {
        PRINT(OrderSend(NULL, OP_BUY, 0.1, Ask, 100, 0, 0))
        Print(MT4ORDERS::LastTradeResult.comment);
      }
        
      PRINT(GetMicrosecondCount() - StartTime2)
      
      PRINT(TerminalInfoInteger(TERMINAL_PING_LAST))
    }


    Resultado

    OrderSendAsync(NULL,OP_BUY,0.1,Ask,100,0,0) = 117
    OrderSendAsync(NULL,OP_BUY,0.1,Ask,100,0,0) = 118
    OrderSendAsync(NULL,OP_BUY,0.1,Ask,100,0,0) = 119
    OrderSendAsync(NULL,OP_BUY,0.1,Ask,100,0,0) = 120
    OrderSendAsync(NULL,OP_BUY,0.1,Ask,100,0,0) = 121
    GetMicrosecondCount()-StartTime1 = 403
    
    OrderSend(NULL,OP_BUY,0.1,Ask,100,0,0) = 153496331
    Request executed 221.820 + 0.013 ms
    OrderSend(NULL,OP_BUY,0.1,Ask,100,0,0) = 153496331
    Request executed 252.067 + 0.008 ms
    OrderSend(NULL,OP_BUY,0.1,Ask,100,0,0) = 153496331
    Request executed 220.909 + 0.005 ms
    OrderSend(NULL,OP_BUY,0.1,Ask,100,0,0) = 153496331
    Request executed 189.578 + 0.005 ms
    OrderSend(NULL,OP_BUY,0.1,Ask,100,0,0) = 153496331
    Request executed 180.182 + 0.010 ms
    GetMicrosecondCount()-StartTime2 = 1064775
    
    TerminalInfoInteger(TERMINAL_PING_LAST) = 97942