Bibliotecas: MT4Orders - página 43

 
traveller00:
Em uma conta real na bolsa de valores e em uma negociação real, a corretora Otkritie, mesmo esperando por 10 segundos, não ajudou, ainda aparecem alertas de que há uma dessincronização com o histórico. E eles aparecem com bastante frequência. O que, na minha opinião, é bastante estranho, pois em outros atrasos especiais não são vistos, o ping é de 4 ms e a execução da ordem geralmente é inferior a 15 ms. Começo até a duvidar que tudo esteja correto lá, talvez isso esteja relacionado à rede? Embora eu não use INOUT, todos IN e OUT separadamente. Há algum plano para contornar esse caso? Para memorizar os tíquetes eu mesmo, por exemplo. E qual é a prioridade dada à solução desse problema?

Por favor, publique os dois registros.

 

Oi fxsaber,

Felicidades para 2020!

É uma escolha de design não incluir um número mágico na solicitação de negociação para a função MT4OrderClose?

Atualmente, o DEAL_ENTRY_OUT do MT4OrderClose terá magic == 0.

Isso não faz muita diferença porque, com o ID da posição, você pode rastrear o número mágico de DEAL_ENTRY_IN, no entanto, para fins de análise de histórico, ter uma correspondência DEAL_ENTRY_IN / DEAL_ENTRY_OUT provavelmente daria mais flexibilidade.


Hi fxsaber,

Parabéns para 2020!

É uma escolha de design não incluir o número mágico na solicitação de negociação para a função MT4OrderClose?

Atualmente, DEAL_ENTRY_OUT por MT4OrderClose terá magic == 0.

Não é um grande problema porque, com o ID da posição, é possível rastrear o número mágico de DEAL_ENTRY_IN, no entanto, para fins de análise de histórico, ter DEAL_ENTRY_IN/DEAL_ENTRY_OUT correspondentes talvez proporcione mais flexibilidade.

 
Enrique Dangeroux:

É uma escolha de design não incluir o número mágico na solicitação de negociação para a função MT4OrderClose?

Atualmente, DEAL_ENTRY_OUT do MT4OrderClose terá magic == 0.

Isso não faz muita diferença porque, com o ID da posição, você pode rastrear o número mágico de DEAL_ENTRY_IN; no entanto, para fins de análise de histórico, ter uma correspondência DEAL_ENTRY_IN / DEAL_ENTRY_OUT provavelmente proporcionaria mais flexibilidade.

No OrderClose, você pode definir o MagicNumber, se desejar.

No MT5, ao fechar parcialmente uma posição, é possível alterar o MagicNumber da posição aberta, de modo que você tem uma opção.

Por exemplo, se você tiver uma posição aberta com MagicNumber = 5 e fechar a posição manualmente, então DEAL_ENTRY_OUT_MAGIC = 0. A biblioteca ainda retornará OrderMagicNumber() = 5.

 
// Lista de modificações:
// 12.01.2020
// Correção: OrderTicketID() para transações de saldo agora retorna o valor correto.
// Correção: corrigida a seleção SELECT_BY_TICKET por OrderTicketID() (MT5-PositionID).
// Correção: Alterado o nome do método interno da biblioteca para melhor compatibilidade com macros.
 
Não sei se é um bug ou um recurso, mas para futuros, o lucro e o preço de abertura não são calculados exatamente como esperado. Digamos que uma posição seja aberta às 12h00, às 18h40 a posição é liberada e reaberta automaticamente e, às 20h00, a posição é fechada. GetHistoryPositionData para o ticket da quarta negociação (saída da posição) seleciona o lucro como MT4ORDERS::Order.Profit = ::HistoryDealGetDouble(Ticket, DEAL_PROFIT); que retornará a diferença entre as negociações 3-4 (compensação e saída). Mas ele retornará o preço de abertura como MT4ORDERS::Order.OpenPrice = ::HistoryDealGetDouble(OpenTicket, DEAL_PRICE);. Ou seja, ele retornará o preço de abertura da primeira negociação. Em minha opinião, faz sentido uniformizá-lo, extraindo tudo da primeira negociação (tanto o preço de abertura quanto o lucro) ou extraindo tudo da última abertura (da terceira negociação até a compensação). Ou isso é um recurso e deveria ser assim, e eu estou perdendo alguma coisa?
 
traveller00:
Não sei se é um bug ou um recurso, mas para futuros, o lucro e o preço de abertura não são calculados exatamente como esperado. Digamos que uma posição seja aberta às 12h00, às 18h40 a posição é liberada e reaberta automaticamente e, às 20h00, a posição é fechada. GetHistoryPositionData para o ticket da quarta negociação (saída da posição) seleciona o lucro como MT4ORDERS::Order.Profit = ::HistoryDealGetDouble(Ticket, DEAL_PROFIT); que retornará essencialmente a diferença entre as negociações 3-4 (compensação e saída). Mas ele retornará o preço de abertura como MT4ORDERS::Order.OpenPrice = ::HistoryDealGetDouble(OpenTicket, DEAL_PRICE);. Ou seja, ele retornará o preço de abertura da primeira negociação. Em minha opinião, faz sentido uniformizá-lo, extraindo tudo da primeira negociação (tanto o preço de abertura quanto o lucro) ou extraindo tudo da última abertura (da terceira negociação até a compensação). Ou isso é um recurso e deveria ser assim, e eu estou perdendo alguma coisa?

Portanto, você está analisando o histórico da Netting por meio da biblioteca. Esse é exatamente o caso mencionado inicialmente, para o qual a biblioteca ainda não foi concluída. E se ela será concluída é uma grande questão. Porque há muita confusão, e na prática não há essa necessidade.

Eu ainda uso a mesma biblioteca no Netting, mas deixo de trabalhar com o histórico.

 

https://www.mql5.com/ru/blogs/post/733393


Medição da velocidade em uma situação a partir de uma postagem de blog.

#include <MT4Orders.mqh>

#define  BENCH(A)                                                               \
{                                                                              \
  const ulong _StartTime = GetMicrosecondCount();                              \
  A;                                                                           \
  Print("Time[" + #A + "] = " + (string)(GetMicrosecondCount() - _StartTime)); \
}

void OnStart()
{
  BENCH(HistorySelectByPosition(270107))
  BENCH(HistorySelectByPosition(270107))

  BENCH(HistorySelect(0, INT_MAX))
  BENCH(HistorySelect(0, INT_MAX))

  BENCH(OrdersHistoryTotal())
  BENCH(OrdersHistoryTotal())

  BENCH(OrderSelect(270107, SELECT_BY_TICKET, MODE_HISTORY))
  BENCH(OrderPrint());

  BENCH(OrderSelect(1000, SELECT_BY_POS, MODE_HISTORY))
  BENCH(OrderPrint());
}


Resultado.

Time[HistorySelectByPosition(270107)] = 9232 // Partida a frio.
Time[HistorySelectByPosition(270107)] = 8571 // Hot Launch.

Time[HistorySelect(0,INT_MAX)] = 152856 // Partida a frio.
Time[HistorySelect(0,INT_MAX)] = 94924  // Hot Launch.

Time[OrdersHistoryTotal()] = 155735 // Partida a frio.
Time[OrdersHistoryTotal()] = 6774   // Hot Launch.

Time[OrderSelect(270107,1,1)] = 23 // Livre.
#85469 2020.02.05 22:32:12 buy 0.01 USDCNH 6.97767 0.00000 6.98533 2020.02.05 22:32:13 6.97533 0.00 0.00 -0.34 OrderSendTest_Position 0
Time[OrderPrint()] = 20 // Livre.

Time[OrderSelect(1000,0,1)] = 11 // Livre.
#10613 2020.02.06 02:34:32 buy 0.01 EURUSD 1.10049 0.00000 1.11046 2020.02.06 02:34:32 1.10046 0.00 0.00 -0.03 OrderSendTest_Position 0
Time[OrderPrint()] = 13 // Livre.


Você pode ver claramente o quanto as funções HistorySelect custam.

O OrdersHistoryTotal é quente, embora seja menor, mas ainda é perceptível, por isso sempre houve uma recomendação para tentar não chamá-lo mais de uma vez por evento.

OrderSelect by history acabou sendo gratuito.

Особенности исполнения торговых приказов MT5
Особенности исполнения торговых приказов MT5
  • www.mql5.com
Анализировал с владельцем MT5-сервера тормоза торговых приказов. Запускался OrderSend-Test2.mq5 в том же месте, где MT5-сервер стоит. Т.е. нулевой пинг. Демо, все внутри. Изучались логи MT5-сервера (2170) и MT5-клиента (2280). Логи сервера не буду приводить, просто словами опишу. Думаю, результаты буду интерсны всем, т.к. это поможет раскрыть...
 

Você pode coletar estatísticas sobre o tempo gasto na execução de ordens de mercado (incluindo TP/SL).

/Estatísticas do tempo gasto na execução de ordens de mercado (incluindo TP/SL).
#property script_show_inputs

input datetime inFrom = 0;
input datetime inTo = INT_MAX;

struct ORDER
{
  ulong Ticket;
  
  ulong FillingTime;
  
  string ToString( void ) const
  {
    return((string)Ticket + ": " + ::TimeToString(this.FillingTime / 1000, TIME_SECONDS) +
                            "." + ::IntegerToString(this.FillingTime % 1000, 3, '0'));
  }
};

// Coleta dados sobre o tempo gasto na execução de ordens de mercado
int GetOrders( ORDER &Orders[], const datetime From = 0, const datetime To = INT_MAX )
{
  int Amount = 0;
  
  if (HistorySelect(From, To)) // Se houver registros no histórico
    for (int i = ArrayResize(Orders, HistoryOrdersTotal()) - 1; i >= 0; i--) // Executar a seleção de pedidos
    {
      const ulong TicketOrder = HistoryOrderGetTicket(i); // Selecionamos um mandado
      
      if ((HistoryOrderGetInteger(TicketOrder, ORDER_TYPE) <= ORDER_TYPE_SELL) &&   // Se a ordem de mercado
          (HistoryOrderGetInteger(TicketOrder, ORDER_STATE) == ORDER_STATE_FILLED)) // Se a ordem tiver sido executada
      {
        Orders[Amount].Ticket = TicketOrder;
        
        // Lembrou-se do tempo necessário para a execução.
        Orders[Amount++].FillingTime = HistoryOrderGetInteger(TicketOrder, ORDER_TIME_DONE_MSC) -
                                       HistoryOrderGetInteger(TicketOrder, ORDER_TIME_SETUP_MSC);
      }
      }
  
  return(ArrayResize(Orders, Amount));
}

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

#define  PRINT(A) Print(#A + " = " + (string)(A))

void OnStart()
{
  ORDER Orders[];
  
  if (GetOrders(Orders, inFrom, inTo))
  {
    ArraySortStruct(Orders, FillingTime); // https://www.mql5.com/ru/forum/170952/page166#comment_15151387
    
    // Imprimiu as ordens de mercado executadas há mais tempo.
    for (int i = ArraySize(Orders) - 1, k = 0; (i >= 0) && (k < 10); i--, k++)
    {
      Print((string)k + " - " + Orders[i].ToString());

    #ifdef __MT4ORDERS__
      if (OrderSelect(Orders[i].Ticket, SELECT_BY_TICKET))
      {
        OrderPrint();
        
        PRINT(OrderTicketID());
        PRINT(OrderTicketOpen());
  
        Print("-------------------");      
      }
    #endif // __MT4ORDERS__ 
    }
  }
}


Resultado.

0 - 348806: 00:01:57.311
1 - 348530: 00:01:39.027
2 - 348494: 00:01:15.259
3 - 348406: 00:01:07.671
4 - 348950: 00:01:04.869
5 - 348960: 00:01:02.888
6 - 348814: 00:01:00.654
7 - 348392: 00:01:00.642
8 - 348508: 00:00:54.515
9 - 348550: 00:00:54.467


Até dois minutos de execução em uma conta em execução. Compartilhe suas estatísticas aqui. O script não usa nenhuma biblioteca e é adequado para Netting/Hedge.

 

No MT4/5, é bastante desagradável depurar ao trabalhar com o histórico de negociação. Você precisa usar várias soluções de apoio.


No MT5, você pode ver imediatamente todos os campos da ordem selecionada por meio do MT4Orders. Para fazer isso, você precisa adicionar MT4ORDERS::Order à observação MT4ORDERS::Order.


Dessa forma, você pode ver todas as propriedades da ordem selecionada.

 
fxsaber:

Compartilhe suas estatísticas aqui. O script não usa nenhuma biblioteca, sendo adequado para Netting/Hedge.

É assim que a realidade é:

2020.02.27 14:53:30.275 ExecutionSpeed (EURUSD,H1)      0 - 34487054: 00:00:06.768
2020.02.27 14:53:30.275 ExecutionSpeed (EURUSD,H1)      1 - 34487223: 00:00:06.166
2020.02.27 14:53:30.275 ExecutionSpeed (EURUSD,H1)      2 - 49869622: 00:00:03.656
2020.02.27 14:53:30.275 ExecutionSpeed (EURUSD,H1)      3 - 34486559: 00:00:02.833
2020.02.27 14:53:30.275 ExecutionSpeed (EURUSD,H1)      4 - 34486482: 00:00:02.051
2020.02.27 14:53:30.275 ExecutionSpeed (EURUSD,H1)      5 - 34486480: 00:00:02.023
2020.02.27 14:53:30.275 ExecutionSpeed (EURUSD,H1)      6 - 34486467: 00:00:01.983
2020.02.27 14:53:30.275 ExecutionSpeed (EURUSD,H1)      7 - 42624984: 00:00:01.589
2020.02.27 14:53:30.275 ExecutionSpeed (EURUSD,H1)      8 - 33738445: 00:00:01.088
2020.02.27 14:53:30.275 ExecutionSpeed (EURUSD,H1)      9 - 42625044: 00:00:00.932