Caractéristiques du langage mql4, subtilités et techniques - page 34

 
J'ai remarqué le problème suivant : si vous exécutez un script et qu'il se plante (ferme la plate-forme), le fichier journal n'enregistre pas les enregistrements pendant l'exécution du script, ce qui rend assez difficile la détection d'une erreur dans le code. Je n'ai jamais remarqué ce problème auparavant. Est-ce que ça a toujours été comme ça (pas d'enregistrement) ?
 

Il semble qu'il n'y ait aucun moyen de savoir dans MT4 (sans se reconnecter) si l'effet de levier sur le compte a changé.

 
fxsaber #:

Il semble qu'il n'y ait aucun moyen dans MT4 de savoir (sans se reconnecter) si l'effet de levier du compte a changé.

Je l'ai fait il y a environ cinq ans. L'effet de levier du client a été réduit à certaines heures, et il n'a pas changé dans la variable AccountInfoInteger(ACCOUNT_LEVERAGE). Et il avait besoin de le savoir.

Je ne connais pas la science, mais j'ai décidé qu'il y a un levier de compte qui change rarement, et un levier de symbole qui peut changer plusieurs fois par jour.
Je l'ai vérifié de cette façon :

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


Parfois, l'effet de levier actuel calculé par le symbole leverageSymb peut donner 199, 198 au lieu de 200 (lorsque l'effet de levier est de 1:200). J'ai donc dû soustraire un certain % du levier standard et le comparer à cette valeur. La solution ci-dessus, qui a aidé à l'époque, pourrait s'avérer utile.

 
Vasiliy Pushkaryov #:

J'ai fait ça il y a environ cinq ans. Un client a vu son effet de levier réduit à certaines heures, et il n'y a eu aucun changement dans la variable AccountInfoInteger(ACCOUNT_LEVERAGE). Et il devait le savoir.

Je ne connais pas la science, mais j'ai décidé qu'il y a un levier de compte qui change rarement, et un levier de symbole qui peut changer plusieurs fois par jour.
Je l'ai vérifié de cette façon :


Parfois, l'effet de levier actuel calculé par le symbole leverageSymb peut donner 199, 198 au lieu de 200 (lorsque l'effet de levier est de 1:200). J'ai donc dû soustraire un certain % du levier standard et le comparer à cette valeur. La solution proposée ci-dessus pourrait alors s'avérer utile.

Oui, il n'y a aucun problème à suivre les exigences de marge du symbole. ACCOUNT_LEVERAGE - reconnexion uniquement.

 

Il est très courant de filtrer l'historique des transactions en mémorisant les ordres requis dans une liste de tickets. Et ensuite SELECT_BY_TICKET sur cette liste.

Je n'ai jamais vu une variante où l'on ne mémorise pas un ticket mais une position. Vous trouverez ci-dessous une comparaison des performances.

#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

On constate que la variante ticket perd presque trois fois en performance.

 
fxsaber #:

On constate que la variante ticket perd presque trois fois en performance.

si une position est fermée/ouverte, la logique avec le ticket ne sera pas cassée, la logique avec la position pourrait l'être.

 
TheXpert #:

si une position est fermée/ouverte, la logique avec le ticket ne sera pas cassée, la logique avec la position peut l'être.

Il s'agit uniquement du mode MODE_HISTORY.

 

Est-il théoriquement possible que ce code manque un ordre qui existait AVANT et APRÈS l 'appel de la fonction? Ou bien cela comptera-t-il deux fois.

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

Par exemple, qu'arrive-t-il à l'indexation lorsqu'une commande est supprimée ou apparaît pendant l'énumération ?

 
fxsaber #:

Ou bien il comptera deux fois.

Si nous supposons un tri par défaut par heure ou par ticket, les nouvelles commandes apparaissent à la fin de la liste, et logiquement toutes sont décalées lorsque les plus anciennes sont supprimées.

Il s'avère que lors de la suppression d'une commande du début de la liste, l'une d'entre elles peut être prise en compte deux fois. Cela semble facile à contourner - il suffit de se souvenir du ticket de la passe précédente et de comparer (mais toujours pas de garantie).

Comment obtenir un laissez-passer pour le retour - pas encore trouvé

 
Andrei Trukhanovich #:

Si nous supposons un tri par défaut par heure ou par ticket, les nouvelles commandes apparaissent à la fin de la liste, et logiquement toutes sont décalées lorsque les plus anciennes sont supprimées.

Il s'avère que lors de la suppression d'une commande du début de la liste, l'une d'entre elles peut être prise en compte deux fois. Cela semble facile à contourner - il suffit de se souvenir du ticket de la passe précédente et de comparer (mais toujours pas de garantie).

Comment obtenir un laissez-passer pour le retour - je n'ai pas encore trouvé la solution.

Merci pour cette réponse détaillée ! Alors maintenant, je me demande comment passer en revue TOUTES les commandes en UNE seule fois.

Raison: