Características del lenguaje mql4, sutilezas y técnicas - página 34

 
Me he dado cuenta del siguiente problema: si se ejecuta un script y se bloquea (se cierra la plataforma), el archivo de registro no guarda los registros mientras se ejecuta el script, lo que hace bastante difícil detectar un error en el código. No había notado este problema antes. ¿Siempre ha sido así (no se guardan registros)?
 

Parece que no hay manera de saber en MT4 (sin volver a conectarse) si el apalancamiento de la cuenta ha cambiado.

 
fxsaber #:

Parece que no hay manera en MT4 para saber (sin volver a conectar) si el apalancamiento en la cuenta ha cambiado.

Lo hice hace unos cinco años. El apalancamiento del cliente se redujo a ciertas horas, y no cambió en la variable AccountInfoInteger(ACCOUNT_LEVERAGE). Y tenía que saberlo.

No sé la ciencia, pero he decidido que hay un apalancamiento de la cuenta que cambia pocas veces, y hay un apalancamiento del símbolo que puede cambiar varias veces al día.
Lo he comprobado así:

//+------------------------------------------------------------------------------------------------------------------+
//| Проверяет изменение плеча и сообщает если это было
//+------------------------------------------------------------------------------------------------------------------+
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);
}


A veces el apalancamiento calculado por el símbolo leverageSymb puede dar 199, 198 en lugar de 200 (cuando el apalancamiento es 1:200). Por lo tanto, tuve que restar un determinado % del apalancamiento estándar y compararlo con este valor. La solución anterior fue útil en su momento, puede ser útil.

 
Vasiliy Pushkaryov #:

Lo hice hace unos cinco años. A un cliente se le redujo el apalancamiento a ciertas horas, y no cambió de ninguna manera en la variable AccountInfoInteger(ACCOUNT_LEVERAGE). Y tenía que saberlo.

No sé la ciencia, pero he decidido que hay un apalancamiento de cuenta que cambia raramente, y hay un apalancamiento de símbolo que puede cambiar varias veces al día.
Lo comprobé de esta manera:


A veces el apalancamiento calculado por el símbolo leverageSymb puede dar 199, 198 en lugar de 200 (cuando el apalancamiento es 1:200). Por lo tanto, tuve que restar un determinado % del apalancamiento estándar y compararlo con este valor. La solución anterior ayudó entonces, podría ser útil.

Sí, no hay ningún problema con el seguimiento de los requisitos de margen del símbolo. ACCOUNT_LEVERAGE - sólo reconectar.

 

Es una práctica muy común filtrar el historial de operaciones recordando las órdenes requeridas en una lista de entradas. Y luego SELECT_BY_TICKET en esa lista.

Nunca he visto una variante en la que no se memorice un billete sino una posición. A continuación se muestra una comparación del rendimiento.

#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 la variante del billete pierde casi tres veces en rendimiento.

 
fxsaber #:

Se puede ver que la variante del billete pierde casi tres veces en rendimiento.

si una posición está cerrada/abierta, la lógica con el ticket no se romperá, la lógica con la posición podría.

 
TheXpert #:

si una posición está cerrada/abierta, la lógica con el ticket no se romperá, la lógica con la posición puede.

Sólo se trata del modo MODE_HISTORY.

 

¿Es teóricamente posible que este código pierda algún orden que existía ANTES y DESPUÉS de llamar a la función? O contará dos veces.

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

Es decir, ¿qué ocurre con la indexación cuando se elimina un pedido o aparece durante la enumeración?

 
fxsaber #:

O contará dos veces.

Si asumimos una ordenación por defecto por tiempo o por ticket, los nuevos pedidos aparecen al final de la lista, y lógicamente todos se desplazan cuando se borran los más antiguos.

Resulta que al borrar una orden del principio de la lista se puede tener en cuenta una de las listas dos veces. Parece fácil de solucionar: basta con recordar el billete de la pasada anterior y comparar (pero todavía no hay garantía).

Cómo conseguir un pase en el pase de vuelta - no se ha descubierto

 
Andrei Trukhanovich #:

Si asumimos una ordenación por defecto por tiempo o por ticket, los nuevos pedidos aparecen al final de la lista, y lógicamente todos se desplazan cuando se borran los más antiguos.

Resulta que al borrar una orden del principio de la lista se puede tener en cuenta una de las listas dos veces. Parece fácil de solucionar: basta con recordar el billete de la pasada anterior y comparar (pero todavía no hay garantía).

Cómo conseguir un pase en el pase de vuelta - no lo he resuelto

Gracias por la detallada respuesta. Así que ahora me pregunto cómo pasar por TODOS los pedidos de una sola vez.