Caratteristiche del linguaggio mql4, sottigliezze e tecniche - pagina 34

 
Ho notato il seguente problema: se si esegue uno script e questo si blocca (chiude la piattaforma), allora il file di log non salva i record mentre lo script è in esecuzione, il che rende abbastanza difficile individuare un errore nel codice. Non ho notato questo problema prima. È sempre stato così (nessun record salvato)?
 

Sembra che non ci sia modo di sapere in MT4 (senza riconnettersi) se la leva del conto è cambiata.

 
fxsaber #:

Sembra che non ci sia modo in MT4 di sapere (senza riconnettersi) se la leva del conto è cambiata.

L'ho fatto circa cinque anni fa. La leva del cliente è stata ridotta in certe ore, e non è cambiata nella variabile AccountInfoInteger(ACCOUNT_LEVERAGE). E aveva bisogno di saperlo.

Non conosco la scienza, ma ho deciso che c'è una leva del conto che cambia raramente, e c'è una leva del simbolo che può cambiare più volte al giorno.
Ho controllato in questo modo:

//+------------------------------------------------------------------------------------------------------------------+
//| Проверяет изменение плеча и сообщает если это было
//+------------------------------------------------------------------------------------------------------------------+
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 volte l'attuale leva calcolata dal simbolo leverageSymb potrebbe dare 199, 198 invece di 200 (quando la leva è 1:200). Quindi, ho dovuto sottrarre una certa % dalla leva standard e confrontarla con questo valore. La soluzione di cui sopra ha aiutato in quel momento, potrebbe tornare utile.

 
Vasiliy Pushkaryov #:

L'ho fatto circa cinque anni fa. Un cliente ha avuto il suo leverage ridotto in certe ore, e non è cambiato in alcun modo nella variabile AccountInfoInteger(ACCOUNT_LEVERAGE). E aveva bisogno di saperlo.

Non conosco la scienza, ma ho deciso che c'è una leva del conto che cambia raramente, e c'è una leva del simbolo che può cambiare più volte al giorno.
Ho controllato in questo modo:


A volte l'attuale leva calcolata dal simbolo leverageSymb potrebbe dare 199, 198 invece di 200 (quando la leva è 1:200). Quindi, ho dovuto sottrarre una certa % dalla leva standard e confrontarla con questo valore. La soluzione di cui sopra ha aiutato allora, potrebbe essere utile.

Sì, non c'è nessun problema nel seguire i requisiti di margine del simbolo. ACCOUNT_LEVERAGE - solo riconnessione.

 

È una pratica molto comune filtrare la storia del trading ricordando gli ordini richiesti in una lista di ticket. E poi SELECT_BY_TICKET su quella lista.

Non ho mai visto una variante in cui non si memorizza un biglietto ma una posizione. Qui sotto c'è un confronto delle prestazioni.

#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

Vediamo che la variante del biglietto perde quasi tre volte in prestazioni.

 
fxsaber #:

Si può vedere che la variante del biglietto perde quasi tre volte in prestazioni.

se una posizione è chiusa/aperta, la logica con il biglietto non si rompe, la logica con la posizione potrebbe.

 
TheXpert #:

se una posizione è chiusa/aperta, la logica con il biglietto non si rompe, la logica con la posizione sì.

Si tratta solo della modalità MODE_HISTORY.

 

È teoricamente possibile che questo codice si perda qualche ordine che esisteva PRIMA e DOPO che la funzione sia stata chiamata? O conterà due volte.

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

Cioè cosa succede all'indicizzazione quando un ordine viene cancellato o appare durante l'enumerazione?

 
fxsaber #:

Oppure conterà due volte.

Se assumiamo l'ordinamento predefinito per tempo o ticket, i nuovi ordini appaiono alla fine della lista, e logicamente tutti vengono spostati quando i più vecchi vengono cancellati.

Si scopre che quando si cancella un ordine dall'inizio della lista uno della lista può essere preso in considerazione due volte. Sembra facile da aggirare - basta ricordare il biglietto del passaggio precedente e confrontare (ma ancora nessuna garanzia).

Come ottenere un passaggio sul passaggio di ritorno - non capito

 
Andrei Trukhanovich #:

Se assumiamo l'ordinamento predefinito per tempo o ticket, i nuovi ordini appaiono alla fine della lista, e logicamente tutti vengono spostati quando i più vecchi vengono cancellati.

Si scopre che quando si cancella un ordine dall'inizio della lista uno della lista può essere preso in considerazione due volte. Sembra facile da aggirare - basta ricordare il biglietto del passaggio precedente e confrontare (ma ancora nessuna garanzia).

Come ottenere un passaggio per il ritorno - non l'ho capito

Grazie per la risposta dettagliata! Così ora mi sto chiedendo come passare attraverso TUTTI gli ordini in una sola volta.