Características da linguagem mql4, sutilezas e técnicas - página 34

 
Notei o seguinte problema: se você executa um script e ele trava (fecha a plataforma), então o arquivo de registro não salva registros enquanto o script está rodando, o que torna bastante difícil detectar um erro no código. Nunca tinha notado este problema antes. Sempre foi assim (não há registros salvos) ?
 

Parece não haver maneira de saber em MT4 (sem reconectar) se a alavancagem da conta mudou.

 
fxsaber #:

Parece não haver como saber no MT4 (sem reconectar) se a alavancagem na conta mudou.

Eu o fiz há cerca de cinco anos. A alavancagem do cliente foi reduzida em certas horas, e não mudou na variável AccountInfoInteger(ACCOUNT_LEVERAGE). E ele precisava saber sobre isso.

Não sei sobre a ciência, mas decidi que há uma alavancagem de conta que raramente muda, e há uma alavancagem de símbolo que pode mudar várias vezes ao dia.
Eu verifiquei desta forma:

//+------------------------------------------------------------------------------------------------------------------+
//| Проверяет изменение плеча и сообщает если это было
//+------------------------------------------------------------------------------------------------------------------+
void leverageCheck()
{
  if(MarketInfo(Symbol(), MODE_MARGINREQUIRED) == 0) return;

   // --- получаем текущее плечо из маржинальных требований, стоимости пункта, тек.котировки
  double leverageSymb = MarketInfo(Symbol(),MODE_TICKVALUE) * Bid / MarketInfo(Symbol(),MODE_MARGINREQUIRED) / Point;
  leverageSymb = int(MathRound(leverageSymb));
  
   // --- если плечо по символу стало меньше на 10% плеча по счету отметим это
  if(leverageSymb < percVar(AccountInfoInteger(ACCOUNT_LEVERAGE), -10))
  {
    string txt = TimeToString(TimeCurrent()) + " Leverage is reduced 1:" + (string)leverageSymb;
    Print(txt, " but account leverage = " + (string)AccountInfoInteger(ACCOUNT_LEVERAGE));

    // --- вывод информации на график
  }
}

//+-------------------------------------------------------------------------------------------------------------------+
//| Получает переменную, увеличивает или уменьшает его на переданный процент и возвращает новое значение
//| Чтобы уменьшить, нужно передать percent с минусом
//+-------------------------------------------------------------------------------------------------------------------+
double percVar(double var, double percent)
{
  return var*(1 + percent/100);
}


s vezes a alavancagem calculada atualmente pelo símbolo de alavancagemSymb pode dar 199, 198 ao invés de 200 (quando a alavancagem é 1:200). Portanto, eu tive que subtrair uma certa % da alavancagem padrão e compará-la com este valor. A solução acima ajudou no momento, pode vir a ser útil.

 
Vasiliy Pushkaryov #:

Eu fiz isso há cerca de cinco anos. Um cliente teve sua alavancagem reduzida em certas horas, e isso não mudou em nada na variável AccountInfoInteger(ACCOUNT_LEVERAGE). E ele precisava saber sobre isso.

Não sei sobre a ciência, mas decidi que há uma alavancagem de conta que raramente muda, e há uma alavancagem de símbolo que pode mudar várias vezes ao dia.
Eu verifiquei desta forma:


s vezes a alavancagem calculada atualmente pelo símbolo de alavancagemSymb pode dar 199, 198 ao invés de 200 (quando a alavancagem é 1:200). Portanto, eu tive que subtrair uma certa % da alavancagem padrão e compará-la com este valor. A solução acima ajudou então, pode vir a ser útil.

Sim, não há problema em rastrear os requisitos de margem do símbolo. ACCOUNT_LEVERAGE - somente reconectar.

 

É muito comum filtrar o histórico comercial, lembrando as ordens necessárias em uma lista de bilhetes. E depois SELECT_BY_TICKET nessa lista.

Nunca vi uma variante em que não fosse um bilhete, mas uma posição fosse memorizada. Abaixo está uma comparação de desempenho.

#include <MT4Orders.mqh> // https://www.mql5.com/ru/code/16006
#include <fxsaber\Benchmark\Benchmark.mqh> // https://www.mql5.com/ru/code/31279

int Filter( TICKET_TYPE &Tickets[], int &Pos[] )
{
  const int Total = OrdersHistoryTotal();            

  ArrayResize(Tickets, Total);
  ArrayResize(Pos, Total);
  
  int Amount = 0;

  for (int i = 0; i < Total; i++)
    if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY) && (OrderProfit() > 0))
    {
      Tickets[Amount] = OrderTicket();
      Pos[Amount] = i;
      
      Amount++;
    }
    
  ArrayResize(Tickets, Amount);
  ArrayResize(Pos, Amount);
  
  return(Amount);
}

template <typename T>
double Func1( int TypeSelect, const T &Array[] )
{
  double Res = 0;
  const int Total = ArraySize(Array);
  
  for (int i = 0; i < Total; i++)
    if (OrderSelect(Array[i], TypeSelect, MODE_HISTORY))
      Res += OrderProfit();
      
  return(Res);
}

void OnStart()
{   
  TICKET_TYPE Tickets[];
  int Pos[];

  Print(Filter(Tickets, Pos));
  
  const double Res1 = _B(Func1(SELECT_BY_TICKET, Tickets), 1); // Так делают почти все.
  const double Res2 = _B(Func1(SELECT_BY_POS, Pos), 1);        // Не встречал.
  
  Print(Res1);
  Print(Res2);
}


2021.10.11 01:37:08.254 Test19 EURUSD.rann,M1: 561002.61
2021.10.11 01:37:08.254 Test19 EURUSD.rann,M1: 561002.61
2021.10.11 01:37:08.254 Test19 EURUSD.rann,M1: Alert: Bench_Stack = 0, 1 <= Time[Test19.mq4 49 in OnStart: Func1(SELECT_BY_POS,Pos)] = 2827 mcs.
2021.10.11 01:37:08.251 Test19 EURUSD.rann,M1: Alert: Bench_Stack = 0, 1 <= Time[Test19.mq4 48 in OnStart: Func1(SELECT_BY_TICKET,Tickets)] = 7460 mcs.
2021.10.11 01:37:08.244 Test19 EURUSD.rann,M1: 35936

Vemos que a variante de ingressos perde quase três vezes em desempenho.

 
fxsaber #:

Pode-se ver que a variante de ingressos perde quase três vezes em desempenho.

se uma posição for fechada/aberta, a lógica com o bilhete não se quebrará, a lógica com a posição poderá.

 
TheXpert #:

se uma posição for fechada/aberta, a lógica com o bilhete não se quebrará, a lógica com a posição poderá.

Trata-se apenas do modo MODE_HISTÓRIA.

 

É teoricamente possível que este código falhe alguma ordem que existia ANTES e DEPOIS de a função ter sido chamada? Ou será contado duas vezes.

double GetLots()
{
  double Lots = 0;
  
  for (int i = OrdersTotal() - 1; i >= 0; i--)
    if (OrderSelect(i, SELECT_BY_POS))
      Lots += OrderLots();
      
  return(Lots);
}

Ou seja, o que acontece com a indexação quando um pedido é excluído ou aparece durante a enumeração?

 
fxsaber #:

Ou então, contará duas vezes.

Se assumirmos a classificação padrão por tempo ou bilhete, novos pedidos aparecem no final da lista e, logicamente, todos são deslocados quando os mais antigos são excluídos.

Acontece que ao apagar uma ordem do início da lista, uma das ordens pode ser levada em conta duas vezes. Parece fácil de se trabalhar - basta lembrar o bilhete do passe anterior e comparar (mas ainda sem garantia).

Como obter um passe para o passe de retorno - não descoberto

 
Andrei Trukhanovich #:

Se assumirmos a classificação padrão por tempo ou bilhete, novos pedidos aparecem no final da lista e, logicamente, todos são deslocados quando os mais antigos são excluídos.

Acontece que ao apagar uma ordem do início da lista, uma das ordens pode ser levada em conta duas vezes. Parece fácil de se trabalhar - basta lembrar o bilhete do passe anterior e comparar (mas ainda sem garantia).

Como obter um passe para o passe de retorno - ainda não resolvido

Obrigado pela resposta detalhada! Por isso, agora estou me perguntando como fazer TODAS as encomendas em UM momento.