Bibliotecas: MT4Orders - página 12

 
Um exemplo de como a parte de negociação de um Expert Advisor pode ser concisa e confiável ao usar a biblioteca em uma conta líquida.

Sinais de negociação para o MetaTrader 5 com execução automática em sua conta

LCHI2017

MetaTrader 5
Free

O Expert Advisor opera com instrumentos de ações.

#include <MT4Orders.mqh>     // https://www.mql5.com/pt/code/16006
#include <TypeToBytes.mqh>   // https://www.mql5.com/pt/code/16280
#include <Price_Compare.mqh> // https://www.mql5.com/pt/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;
}
 
Muito útil, obrigado!
 
A versão mais recente está sempre aqui.
 

Um script que mostra uma peculiaridade da implementação do OrderSelect no 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);  // Definir BuyLimit
  OrderSend(_Symbol, OP_SELLLIMIT, 1, Bid + 100 * _Point, 0, 0, 0); // Definir SellLimit
  OrderSend(_Symbol, OP_BUY, 1, Ask, 100, 0, 0);                    // Abriu uma posição 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 posição de venda
        
        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

Apesar do fato de que o resultado da negociação do script é idêntico em ambas as plataformas, o OrderSelect funciona de forma diferente. Daí os diferentes registros.

O script é especialmente sugado, e não posso recomendar esse estilo de escrever a lógica de negociação, pois está repleto de erros lógicos difíceis de ver em cada plataforma. E esse código deixa de ser 100% idêntico na execução.

É por isso que parece inconveniente corrigir a biblioteca para que essas raras curvas do MT4 sejam executadas no MT5 de forma absolutamente perfeita, como acontece com o código normal.

Se eu estiver errado sobre a curvatura e a raridade de tais construções de negociação no MT4, por favor, esclareça.

 
De alguma forma, ela até se mostra engraçada com a lentidão.
 
Vitaly Muzichenko:
É engraçado o fato de estarmos desacelerando.

Fórum sobre negociação, sistemas de negociação automatizados e teste de estratégias de negociação

Testador MT4 VS Testador MT5

fxsaber, 2017.05.08 01:11 pm.

Se houver dúvidas de que a lentidão do MT5 é causada pelo uso de uma biblioteca de terceiros, aqueles que desejarem podem reescrever a lógica simples do MT4 deste EA em MQL5 à sua maneira e testar a hipótese.
 
fxsaber:

Um script que mostra uma peculiaridade da implementação do OrderSelect no modo SELECT_BY_POS+MODE_TRADES

O script é especialmente ruim, e não posso recomendar esse estilo de escrever a lógica de negociação

Com outro estilo altamente não recomendado de escrever a lógica de negociação, você pode se deparar com outro recurso do OrderSelect, mas já no 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 - A posição OPEN estava com esse tíquete
    
    Print(OrderSelect(OrderTicket(), SELECT_BY_TICKET, MODE_HISTORY)); // falso, потому что тикет ЗАКРЫТОЙ позиции равен тикету закрывающей сделки.
    Print(OrderSelect(OrderTicket() + 1, SELECT_BY_TICKET, MODE_HISTORY)); // verdadeiro, pelo motivo acima.
      
    FirstRun = false;
  }
}

Este é um Expert Advisor para um testador. Nos comentários está o motivo desse comportamento. E ele está correto devido a

  • O ticket de uma posição aberta (como regra) é igual ao ticket da ordem de abertura (não uma negociação). (termos do MT5).
  • Se uma posição for parcialmente fechada, os tíquetes das posições correspondentes fechadas não devem ser iguais ao tíquete da posição aberta para evitar ambiguidade (termos do MT5).

  • Ou seja, o próprio MT5 é feito de forma tão "torta" que é difícil pensar em outro comportamento para o MT4Orders. É claro que, se você fizer o SELECT_BY_POS pelo histórico primeiro, registrando todos os tíquetes, o SELECT_BY_TICKET funcionará sem problemas.

    Em geral, se a lógica de negociação do MT4 estiver "mal escrita", poderá haver discrepâncias entre os resultados do MT5+MT4Orders e os resultados do MT4 que são incomuns para a compreensão do MT4. Se você seguir o estilo "correto" de escrita do MT4, não serão detectados problemas na biblioteca.

    [Excluído]  
    fxsaber:

    Se você usar outro estilo altamente não recomendado de escrever a lógica de negociação, poderá se deparar com outro recurso do OrderSelect, mas já no modo SELECT_BY_TICKET+MODE_HISTORY.

    Em geral, se a lógica de negociação do MT4 for escrita de forma "incorreta", poderá haver discrepâncias incomuns para a compreensão do MT4 entre os resultados do MT5+MT4Orders e do MT4. Se você se ater ao estilo "correto" de escrita do MT4, não encontrará nenhum problema na biblioteca.


    A biblioteca é incrível, muito obrigado :) Depois de adicionar a sincronização de histórico, ela se tornou indispensável. Funciona rapidamente, mesmo com estratégias de alta velocidade

    Eu a adicionaria à entrega padrão do MT5

     

    Atualização

    // Lista de modificações:
    // 14.06.2017:
    // Adicionar: a implementação da detecção de SL/TP de posições fechadas (fechadas via OrderClose) está ativada.
    // Adição: MagicNumber agora é do tipo long - 8 bytes (anteriormente era int - 4 bytes).
    // Adicionar: se em OrderSend, OrderClose ou OrderModify o parâmetro de entrada de cor (o mais recente) for definido como INT_MAX, ele será gerado.
    // a solicitação de negociação MT5 correspondente (MT4ORDERS::LastTradeRequest), mas ela NÃO será enviada. Em vez disso, ela será verificada pelo MT5,
    // O resultado estará disponível em MT4ORDERS::LastTradeCheckResult.
    // Se o OrderModify e o OrderClose forem bem-sucedidos, eles retornarão true, caso contrário, retornarão false.
    // O OrderSend retornará 0 se for bem-sucedido, caso contrário, retornará -1.
    //
    // Se o parâmetro de entrada de cor correspondente for definido como INT_MIN, SOMENTE em caso de verificação bem-sucedida do MT5 do
    // solicitação de negociação (como no caso de INT_MAX), ela será enviada.
    // Adição: adicionados análogos assíncronos das funções de negociação MQL4: OrderSendAsync, OrderModifyAsync, OrderCloseAsync, OrderDeleteAsync.
    // Retornar o Result.request_id correspondente se for bem-sucedido; caso contrário, 0.

    O modo INT_MIN permite que você se livre completamente do entupimento dos registros do testador - isso é especialmente importante durante a otimização, pois, devido à lógica de negociação errônea, a abundância de mensagens pode reduzir o desempenho da otimização muitas vezes e, consequentemente, aumentar não apenas o tempo, mas também os custos financeiros (nuvem).

    Também é conveniente ao posições fechadas.

    Talvez um dia essa funcionalidade se torne padrão para o MT5.


    Exemplo de uso de funções MQL4 assíncronas

    #property script_show_inputs
    
    sinput int Amount = 5; // Número de testes 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