Bibliotecas: MT4Orders - página 19

 
Jeka77769:

Olá! A descrição diz: "Consequentemente, o OrderSelect no modo SELECT_BY_TICKET no MT5, em casos raros (no testador), pode não selecionar o que foi planejado no MT4. "Você pode explicar em quais casos exatamente?

Quando os tíquetes de posição/negociação/ordem coincidem.

 
Outro exemplo(descrição) de código entre plataformas

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

Expert Advisors: eaBreakeven

fxsaber, 2018.01.11 08:13 pm.

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

input int    Breakeven           = 15;           //Breakeven em pontos
input int    Distance            = 5;            /Distância de equilíbrio em pontos do preço de abertura da posição
input int    MagicNumber         = 16112017;     /Número mágico
input bool   EnableSound         = true;         //Ativar/desativar a reprodução de som quando o ponto de equilíbrio for definido
input string SoundFile           = "alert1.wav"; /Nome do arquivo de som

void OnTick()
{
  DoBreakeven();
}

double GetNewStopLoss()
{
  const double point = SymbolInfoDouble(OrderSymbol(), SYMBOL_POINT);  
  const double stop_level = SymbolInfoInteger(OrderSymbol(), SYMBOL_TRADE_STOPS_LEVEL) * point;
  
  const double price_open = OrderOpenPrice();
  const double latest_price = OrderClosePrice();  
  const double stoploss = OrderStopLoss();

  double new_stoploss = 0;
  
  //--- Mova o stop-loss para o preço de equilíbrio + distância, se o lucro da posição for maior que os pontos de equilíbrio 
  return(((OrderType() == OP_BUY)  && (CP(latest_price - price_open, point) >= Breakeven * point) &&
                                      (CP(new_stoploss = price_open + Distance * point, point) > stoploss) &&
                                      (CP(latest_price - new_stoploss, point) > stop_level)) ||
         ((OrderType() == OP_SELL) && (CP(price_open - latest_price, point) >= Breakeven * point) &&
                                      ((CP(new_stoploss = price_open - Distance * point, point) < stoploss) || !stoploss) &&
                                      (CP(new_stoploss - latest_price, point) > stop_level))
         ? NormalizeDouble(new_stoploss, (int)SymbolInfoInteger(OrderSymbol(), SYMBOL_DIGITS)) : 0);
}

void DoBreakeven()
{
//Se o ponto de equilíbrio for negativo, desative a função de ponto de equilíbrio
  if (Breakeven >= 0)      
  //Loop para posições
    for (int i = OrdersTotal() - 1; i >= 0; i--)
      if (OrderSelect(i, SELECT_BY_POS) && (OrderType() <= OP_SELL) && (!MagicNumber || (OrderMagicNumber() == MagicNumber)))
      {
        const double new_stoploss = GetNewStopLoss();
        
        if (new_stoploss)      
        {
          if (!OrderModify(OrderTicket(), OrderOpenPrice(), new_stoploss, OrderTakeProfit(), OrderExpiration()))
            Print(GetLastError());
          else if(EnableSound)
            PlaySound(SoundFile);
        }
      }
}
 

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

Como alterar o volume de uma ordem pendente?

fxsaber, 2018.01.19 16:34

#include <MT4Orders.mqh> // https://www.mql5.com/pt/code/16006

// Altera o volume da ordem pendente. Async = true - modo assíncrono de envio de ordens
bool OrderChangeLots( const long Ticket, const double Lots, const bool Async = false )
{
  return(OrderSelect(Ticket, SELECT_BY_TICKET) && (Lots != OrderLots()) && (Async
         ? (OrderDeleteAsync(Ticket) &&
            OrderSendAsync(OrderSymbol(), OrderType(), Lots, OrderOpenPrice(), 0, OrderStopLoss(), OrderTakeProfit(), OrderComment(), OrderMagicNumber(), OrderExpiration()))
         : (OrderDelete(Ticket) &&
            (OrderSend(OrderSymbol(), OrderType(), Lots, OrderOpenPrice(), 0, OrderStopLoss(), OrderTakeProfit(), OrderComment(), OrderMagicNumber(), OrderExpiration()) != -1))));
}

void OnStart()
{
  for (int i = OrdersTotal() - 1; i >= 0; i--)
    if (OrderSelect(i, SELECT_BY_POS) && (OrderType() >= OP_BUYLIMIT))
      OrderChangeLots(OrderTicket(), OrderLots() + 1, true);
}
 
Quanto melhor for a redação de um Expert Advisor MT4, mais fácil será convertê-lo para o MT5. E o tamanho/complexidade do EA original não importa na conversão.

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

Expert Advisors: Arbitragem de três pontos

fxsaber, 2018.01.20 09:58

#define  MT4_TICKET_TYPE  // Obrigar o OrderSend e o OrderTicket a retornar um valor do mesmo tipo que no MT4 - int.
#include <MT4Orders.mqh> // https://www.mql5.com/pt/code/16006

#define MODE_MARGINREQUIRED 0

// https://www.mql5.com/ru/forum/170952/page9#comment_4134898
// O montante de fundos livres necessários para abrir 1 lote para compra
double MarketInfo( const string Symb, const int )
{
  MqlTick Tick;
  double MarginInit, MarginMain;

  return((SymbolInfoTick(Symb, Tick) && SymbolInfoMarginRate(Symb, ORDER_TYPE_BUY, MarginInit, MarginMain)) ? MarginInit * Tick.ask *
          SymbolInfoDouble(Symb, SYMBOL_TRADE_TICK_VALUE) / (SymbolInfoDouble(Symb, SYMBOL_TRADE_TICK_SIZE) * AccountInfoInteger(ACCOUNT_LEVERAGE)) : 0);
}

int DayOfWeek( void )
{
  MqlDateTime sTime = {0};

  TimeToStruct(TimeCurrent(), sTime);

  return(sTime.day_of_week);
}

int Hour( void )
{
  return((int)((TimeCurrent() % (24 * 3600)) / 3600));
}

#include "ThreePoint.mq4"
 
Se o OnTradeTransaction permite que você escreva um consultor não comercial (Serviço) que rastreia a presença de um consultor "clone" comercial em execução na conta.
 

fechamento de uma posição, é deduzida imediatamente do saldo.

  • Por esse motivo, o patrimônio líquido antes de fechar todas as posições não mostra qual será o saldo após o fechamento.
  • Isso significa que simplesmente não é possível calcular o ponto de equilíbrio no MT5.
  • O MT4Orders ainda tem uma comissão para posições. Por esse motivo, ocorre a seguinte situação

    #include <MT4Orders.mqh>
    
    #define  PRINT(A) Print(#A + " = " + (string)(A))
    
    void OnStart()
    {
      double ProfitWithoutCommission = 0;
      double ProfitWithCommission = 0;  
      
      for (int i = OrdersTotal(); i >= 0; i--)
        if (OrderSelect(i, SELECT_BY_POS))
        {
          OrderPrint();
          
          ProfitWithoutCommission += OrderProfit() + OrderSwap(); // Calcular o lucro atual sem levar em conta a comissão
          
          ProfitWithCommission += OrderProfit() + OrderSwap() + OrderCommission(); // Calcular o lucro atual com a comissão levada em conta
        }
            
      PRINT(AccountInfoDouble(ACCOUNT_EQUITY) - AccountInfoDouble(ACCOUNT_BALANCE));
      
      PRINT(ProfitWithoutCommission);
      PRINT(ProfitWithCommission);  
    }


    Resultado

    #895889 2018.02.08 09:08:26 sell 1.00 EURUSD 1.22807 0.00000 0.00000 1.22877 -6.14 0.00 -70.00 0
    AccountInfoDouble(ACCOUNT_EQUITY)-AccountInfoDouble(ACCOUNT_BALANCE) = -70.0
    ProfitWithoutCommission = -70.0
    ProfitWithCommission = -76.14


    Como você pode ver, a diferença entre o patrimônio líquido e o saldo difere de acordo com o valor da comissão. E pode parecer que a expressão clássica do MT4

    ProfitWithCommission += OrderProfit() + OrderSwap() + OrderCommission(); // Calcular o lucro atual com a comissão levada em conta

    perde seu significado no MT5. Mas isso não acontece. De fato, ao fechar uma posição, o saldo será alterado por esse valor, e não pelo que o patrimônio líquido mostrava antes. Grosso modo, o valor do Patrimônio Líquido no MT5 é falso, do ponto de vista desse conceito no MT4.

    Leve em conta essa peculiaridade do MT5. A biblioteca é mais precisa nesse caso. E será fácil calcular o mesmo ponto de equilíbrio.

     

    posição aberta. Para fazer isso, basta fazer qualquer negociação sem um comentário sobre o símbolo da posição.

    A biblioteca não perderá o comentário no caso descrito - OrderComment() produzirá o comentário que estava lá quando a posição foi aberta.

     
    // Lista de modificações:
    // 13.02.2018
    // Adicionar: adicionado o registro de erros do MT5-OrderSend.
    // Correção: agora somente as ordens de fechamento do MT5 (SL/TP/SO, fechamento parcial/completo) estão "invisíveis".
    // Correção: O mecanismo para determinar SL/TP de posições fechadas após OrderClose foi corrigido - funciona se StopLevel permitir.
     

    Algumas peculiaridades da operação do MT5são descritas aqui em detalhes. A biblioteca funcionou corretamente nessa situação por um longo tempo. Mas ela estava jurando (Alert) que a situação não era padrão.

    Agora ela não vai mais jurar

    // Lista de modificações:
    // 15.02.2018
    // Correção: a verificação de sincronização MT5-OrderSend agora leva em conta possíveis peculiaridades da implementação ECN/STP.


    Como teste, você pode executar esse script em uma conta demo complicada FXOpen-MT5.

    #include <Debug.mqh> // https://c.mql5.com/3/173/Debug.mqh
    #include <MT4Orders.mqh>
    
    #define Bid (SymbolInfoDouble(_Symbol, SYMBOL_BID))
    #define Ask (SymbolInfoDouble(_Symbol, SYMBOL_ASK))
    
    void OnStart()
    {
      _P(OrderCloseBy(_P(OrderSend(_Symbol, OP_BUY, 1, Ask, 0, 0, 0)), _P(OrderSend(_Symbol, OP_SELL, 1, Bid, 0, 0, 0))));
    }


    Resultado

    void OnStart(), Line = 9: OrderSend(_Symbol,OP_SELL,1,Bid,0,0,0) = 897247
    void OnStart(), Line = 9: OrderSend(_Symbol,OP_BUY,1,Ask,0,0,0) = 897248
    void OnStart(), Line = 9: OrderCloseBy(_P(OrderSend(_Symbol,OP_BUY,1,Ask,0,0,0)),_P(OrderSend(_Symbol,OP_SELL,1,Bid,0,0,0))) = true
    Arquivos anexados:
    Debug.mqh  1 kb
     

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

    Organização do ciclo de força bruta da ordem

    fxsaber, 2018.02.16 09:40

    O MT5 não está funcionando bem. Um exemplo mostrando o problema

    // Exemplo de leitura incorreta do ambiente de negociação em cada tick
    // O script emula dois ticks do TS, que deve abrir uma posição se não houver nenhuma.
    
    #include <Trade/Trade.mqh>
    
    // Retorna o número de posições por caractere
    int GetAmountPositions( const string Symb )
    {
      int Res = 0;
      
      // Este código MQL5 tem um erro
      for (int i = PositionsTotal() - 1; i >= 0; i--)
        if (PositionGetSymbol(i) == Symb)
          Res++;
    
    /*
    // No MT4, esse código é executado sem erros
      for (int i = OrdersTotal() - 1; i >= 0; i--)
        if (OrderSelect(i, SELECT_BY_POS) && (OrderType() <= OP_SELL) && (OrderSymbol() == Symb))
          Res++;
    */      
      return(Res);
    }
    
    // Exemplo de OnTick
    void ExampleOnTick()
    {
      static CTrade Trade;
      
      // Se não houver posição, abrir
      if (!GetAmountPositions(_Symbol))
        Trade.Buy(1);    
    }
    
    // Emulação da chegada de dois eventos Tick
    void OnStart()
    {
      ExampleOnTick(); 
      
      Sleep(10); // Entre dois ticks ~10 ms.
      
      ExampleOnTick();
    }

    O que você acha, se executar esse script em um símbolo sem posições, o que acontecerá no final?

    A resposta correta é que uma ou duas posições serão abertas.

    Esse problema é contornado se você escrever no estilo MQL4, pelo menos parcialmente. Para ter certeza disso, basta fazer GetAmountPositions no estilo MQL4 (comentado no código-fonte), removendo o estilo MQL5.

    Seja especialmente vigilante com o estilo MQL5.