Bibliotecas: MT4Orders - página 61

 
Andrey Khatimlianskii:

O que acontece depois de transcorrido esse segundo? A operação continuará na ausência de sincronização?

Sim, ela continuará emitindo um alerta. Mas não consigo imaginar que um segundo não seja suficiente. A sincronização dura milissegundos.

Se isso acontecer, é aconselhável relatar o fato aqui.

Isso é algo que precisa ser escrito nos robôs de combate?

Não. Se você executar o script acima sem essa linha, as estatísticas provavelmente mostrarão que não houve uma única dessincronização. Eu precisava dessa linha como um fator adicional que provocasse a detecção do problema. Quase inicialmente, a biblioteca tenta trazer cada solicitação de negociação para o estado de sincronização. Desativei essa linha de propósito para complicar a tarefa e testar um mecanismo independente para identificar a dessincronização.

 
Andrey Khatimlianskii:

Ou é suficiente verificar MT4ORDERS::ByPass.Is() antes das operações de negociação (para garantir que não haja dessincronização)?

Toda vez que OrdersTotal, OrdersHistoryTotal e OrderSelect são chamados, ByPass.Is()==true fica pendente. É por isso que o resultado dessas funções é relevante logo após serem chamadas. Eles podem mudar com o passar do tempo, portanto, é correto chamá-los novamente se houver alguma pausa. Essa é a resposta para a pergunta acima. É correto fazer isso não apenas no MT5, mas também no MT4.


Portanto, se você acabou de ler o ambiente de negociação, pode fazer uma operação de negociação imediatamente, porque o ambiente ainda é relevante. É por isso que foi possível ocultar o mecanismo do usuário comum da biblioteca.

 
// Lista de modificações:
// 13.05.2021
// Correção: corrigido um erro em OrderOpenReason().
 
amrali:

Bug encontrado:

A função OrderOpenReason() retorna (ENUM_DEAL_REASON)DEAL_REASON_TP para ordens fechadas no takeprofit.

Obrigado! Corrigido.

 

fxsaber:

Sim, ele o fará, emitindo um alerta. Mas não consigo imaginar que um segundo não seja suficiente. A ressincronização dura milissegundos.
Se isso acontecer, seria aconselhável relatar o fato aqui.

Se você ainda não confia no fato de o ambiente ser sincronizado em um segundo, como interromper corretamente o EA (não permitir novas ordens) se não houver sincronização?

if ( MT4ORDERS::ByPass.Is() == false ) // o ambiente não está sincronizado, não negocie
        return;

OrderSend(...);

?

 
Andrey Khatimlianskii:

Se não confiarmos no fato de que o ambiente foi sincronizado em um segundo, como poderemos interromper corretamente o EA (proibir novas ordens) se não houver sincronização?

Aqui fica a seu critério. Você pode fazer o que escreveu. Ou fazer outra espera. Ou aumentar a pausa. Eu tentaria esperar pelo menos uma dessincronização tão longa.

 
fxsaber:

Fica a seu critério. Você pode fazer o que escreveu. Ou fazer outra espera. Ou aumentar a pausa. Eu tentaria esperar pelo menos uma dessincronização tão longa.

Obrigado!

Tentarei esperar por um alerta ou um backoff, removerei as outras verificações.

 
// Lista de modificações:
// 14.05.2021
// Correção: o mecanismo BYPASS não afeta mais OrderSelect(INT_MAX, SELECT_BY_POS) e OrderSelect(INT_MIN, SELECT_BY_POS).

Importante para quem usa snapshots e outras técnicas de negociação muito específicas.

 

Cansado de surpresas com as margens. Recomendo a execução desses scripts de teste antes de usar os Expert Advisors de combate.

// Verifique se o cálculo da margem no MT5 está correto.

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

bool EqualDouble( const double Value1, const double Value2, const double Epsilon = 0.01 )
{
  return(Value1 && Value2 && (MathMax(Value1, Value2) / MathMin(Value1, Value2) < 1 + Epsilon));
}

#define  TOSTRING(A) #A + " = " + (string)(A) + " "

bool CheckMargin( const string Symb )
{
  const double RealMargin = AccountInfoDouble(ACCOUNT_MARGIN);
// const double CalcMargin = GetMarginRequired(Symb); // https://www.mql5.com/ru/forum/170952/page9#comment_4134898
  
  double CalcMargin = 0;
  OrderCalcMargin(ORDER_TYPE_BUY, Symb, 1, SymbolInfoDouble(Symb, SYMBOL_ASK), CalcMargin);
  
  const bool Res = EqualDouble(RealMargin, CalcMargin);
  
  const string Str = TOSTRING(Symb) + TOSTRING(RealMargin) + TOSTRING(CalcMargin) + "- " + (string)Res;
  
  if (Res)
    Print(Str);
  else
    Alert(Str);
      
  return(Res);
}

bool CheckCalcMargin( const string Symb )
{
  bool Res = !OrdersTotal();
  
  if (Res)
  {
    const TICKET_TYPE Ticket = OrderSend(Symb, OP_BUY, 1, SymbolInfoDouble(Symb, SYMBOL_ASK), 0, 0, 0);
    
    if (Res = (Ticket != -1))
    {
      Res = CheckMargin(Symb);
      
      if (OrderSelect(Ticket, SELECT_BY_TICKET))
        OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 0);
    }
  }
  else
  {
    Alert("ERROR: OrdersTotal() != 0");
    
    ExpertRemove();
  }
  
  return(Res);
}

void OnStart()
{
  if (AccountInfoInteger(ACCOUNT_TRADE_MODE) != ACCOUNT_TRADE_MODE_DEMO)
    Alert("Demo account is required!");
  else  
    for (int i = SymbolsTotal(true) - 1; !IsStopped() && (i >= 0); i--)
    {
      const string Symb = SymbolName(i, true);
      
      if (!SymbolInfoInteger(Symb, SYMBOL_CUSTOM))
        CheckCalcMargin(Symb);
    }
}

Vemos uma discrepância total entre os valores calculados da margem do MT5 e os reais. Em tais circunstâncias, talvez a única maneira seja evitar os símbolos correspondentes.


ZЫ E também é cansativo o fato de que você pega coisas elementares e imediatamente encontra bugs lá, e não há uma palavra sobre isso no fórum!

 
fxsaber:
Respeito à única pessoa no fórum que nunca se cansa de relatar bugs. A maioria das pessoas desiste depois de algumas mensagens ignoradas.
E quase ninguém aqui usa esses símbolos, por isso eles não notaram.