Erreurs, bugs, questions - page 442

 
voix_kas:

Est-ce que quelqu'un a un code prêt à l'emploi pour calculer le nombre de chiffres significatifs pour un volume?
Quelque chose comme SymbolInfoInteger(_Symbol, SYMBOL_DIGITS), mais seulement pour le volume.
Par exemple, pour le cas SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_STEP) = "1.0" - la réponse serait "0", pour "0.1" - "1", pour "0.01". - "2", etc.

Permettez-moi de clarifier une nuance. Pour une étape de volume comme "0.1", "0.01", "0.001" j'ai.

Le code devrait fonctionner pour les cas suivants comme "0.2", "0.11", 0.023" etc.

Il n'existe pas de code spécifiquepour le volume. Il y en a pour tout.

int CountSignedDigits(double x)
{  
  for(int i=0; i<1000; i++,x*=10) if(x-MathFloor(x)<DBL_MIN*2) return i;
  return -1;
}
Le script est à vérifier dans la remorque.
Dossiers :
_UniTest.mq5  2 kb
 
MetaDriver:
Un script à vérifier dans la remorque.
Vous voulez dire que..., je pensais que je devais vérifier le lot acceptable avant de passer une commande.
 
sergeev:
Vous voulez dire que..., et je pensais que je devais vérifier le lot autorisé avant de passer une commande.

;)

Je ne sais pas vraiment ce qu'il veut. On verra ce qu'il dira. J'exerce juste ma télépathie. ;)

 
voix_kas:

Quelqu'un a-t-il un code prêt à l'emploi pour calculer le nombre de chiffres significatifs d'un volume ?
Quelque chose comme SymbolInfoInteger(_Symbol, SYMBOL_DIGITS), mais seulement pour le volume.
Par exemple, pour le cas SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_STEP) = "1.0" - la réponse serait "0", pour "0.1" - "1", pour "0.01". - "2", etc.

Permettez-moi de clarifier une nuance. Pour une étape de volume comme "0.1", "0.01", "0.001" j'ai.
Le code devrait fonctionner pour les cas suivants comme "0.2", "0.11", 0.023" etc.

Spécifiquement pour les volumes, cela peut être simple :

      int N=0;
      double step=SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP);
      if(step-1.0<0)  N++;
      if(step-0.1<0)  N++;
      if(step-0.01<0) N++;
[Supprimé]  

sergeev
MetaDriver
Valmars

Une question bien formulée est la moitié de la réponse. :) Désolé, je suis déjà allé me coucher, je n'ai pas réussi à décrire la tâche avec précision. Je vais réessayer.

Je parle de transmettre un volume normalisé à un ordre de transaction.
C'est ce que nous faisons avec le prix :

MqlTradeRequest TradeRequest;
...
TradeRequest.volume = NormalizeDouble(Volume, GetVolumeDigits(_Symbol));
TradeRequest.price  = NormalizeDouble(Price, SymbolInfoInteger(_Symbol, SYMBOL_DIGITS));
...

La normalisation des prix - je pense que c'est clair pour tout le monde.

A mon époque (depuis MT4), j'ai lu quelque part dans des articles de MT qu'il serait souhaitable de normaliser également le volume.
En fait, j'ai écrit la fonctionGetVolumeDigits(string Symbol) pour trouver la plus petite valeur possible du volume selon les conditions du courtier. Il existe au moins deux implémentations (le résultat est le même) :
Mise en œuvre n° 1.

int GetVolumeDigits(string Symbol) {
  int VolumeDigits = 0;
  double VolumeStep = SymbolInfoDouble(Symbol, SYMBOL_VOLUME_STEP);
  while (VolumeStep < 1) {
    VolumeStep *= 10;
    VolumeDigits++;
  }
  return VolumeDigits;
}
Mise en œuvre №2.

int GetVolumeDigits(string Symbol) {
  return (int)MathLog10(1.0 / SymbolInfoDouble(Symbol, SYMBOL_VOLUME_STEP));
}

Les deux fonctionnent parfaitement pour les variantes dont le pas minimum est de 1,0, 0,1, 0,01, 0,001, etc. C'est-à-dire que si le pas minimum est de 1,0, la fonction renverra 0 ; si le pas est de 0,1, la fonction renverra 1, etc.
Que se passe-t-il si le pas minimum est de 1,1, ou de 0,11, ou de 0,011, par exemple ? Cet algorithme affichera de manière incorrecte le chiffre le moins significatif.
Bien sûr, vous pouvez affirmer que de tels cas n'existent pas dans la pratique. Je veux juste envisager une telle possibilité hypothétique dans mon conseiller expert. J'ai pensé que peut-être quelqu'un pourrait partager son expérience en la matière...

 
voix_kas:
Oui, j'ai compris, j'ai besoin que le résultat soit un multiple de VolumeStep. Cela n'a rien à voir avec Digits, il faut d'abord calculer le volume avec Digits et ensuite le réduire au multiple le plus proche de VolumeStep.
 
voix_kas:

Il s'agit d'envoyer le volume normalisé à l'ordre de transaction.
Je veux juste envisager cette possibilité hypothétique dans notre Expert Advisor.

de quel outil "hypothétique" parlons-nous ?

1. La variante de MetaDriver vous convient. CountSignedDigits indique le nombre de caractères dans un lot quelconque.

2. En connaissant le nombre de chiffres, vous pouvez effectuer la normalisation :

double MinLot; // минимальный лот по символу
double MaxLot; // максимальный лот по символу
double LotStep; // шаг лота по символу
int dig; // знаковость лота узнали из функции CountSignedDigits

double NL(double lot)
{
  if (lot<=MinLot) return(MinLot); // проверка на минимальный
  double d=MathFloor((lot-MinLot)/StepLot); // сколько ЦЕЛЫХ шагов умещается в проверяемом лоте
  lot=MinLot+StepLot*d; // рассчитали по этому целому числу
  lot=MathMin(lot, MaxLot);  lot=NormalizeDouble(lot, dig);// не забыли проверить на максимальный // нормализовали
  return(lot); // вернули
}
[Supprimé]  

sergeev
Merci pour la fonction de validation du lot. J'utilise une construction/branchements de chèques similaire.
Ma question vise à trouver la place la plus jeune dans le lot, pour le normaliser.
En particulier, MetaDriver a donné sa construction pour "tout". :) Cependant, il n'est pas sans défaut (ou mon compilateur est défaillant). Voici le code et le résultat de l'exécution :

void OnStart() {
  Print(CountSignedDigits(110.0));
  Print(CountSignedDigits(11.0));
  Print(CountSignedDigits(1.1));
  Print(CountSignedDigits(0.11));
  Print(CountSignedDigits(0.011));
  Print(CountSignedDigits(0.0011));
  Print(CountSignedDigits(0.00011));
}

int CountSignedDigits(double x) {  
  for (int i = 0; i < 1000; i++, x *= 10)
    if (x - MathFloor(x) < DBL_MIN * 2)
      return i;
  return -1;
}

Résultat :

2011.07.03 13:15:21     test (EURUSD,M5)        5
2011.07.03 13:15:21     test (EURUSD,M5)        4
2011.07.03 13:15:21     test (EURUSD,M5)        18      -    Здесь только у меня бяка вылазиет?
2011.07.03 13:15:21     test (EURUSD,M5)        2
2011.07.03 13:15:21     test (EURUSD,M5)        1
2011.07.03 13:15:21     test (EURUSD,M5)        0
2011.07.03 13:15:21     test (EURUSD,M5)        0

Option suivante (la fonction CountSignedDigits est la même) :

void OnStart() {
  double value = 110.0;
  int count = 9;
  while (count) {
    Print(DoubleToString(value), " - ", CountSignedDigits(value));
    value /= 10;
    count--;
  }
}

Résultat :

2011.07.03 13:23:32     test (EURUSD,M5)        0.00000110 - 22       -   Почему-то здесь бяка...
2011.07.03 13:23:32     test (EURUSD,M5)        0.00001100 - 21       -
2011.07.03 13:23:32     test (EURUSD,M5)        0.00011000 - 5
2011.07.03 13:23:32     test (EURUSD,M5)        0.00110000 - 4
2011.07.03 13:23:32     test (EURUSD,M5)        0.01100000 - 3        - Здесь уже все нормально. Почему результаты разные?!
2011.07.03 13:23:32     test (EURUSD,M5)        0.11000000 - 2
2011.07.03 13:23:32     test (EURUSD,M5)        1.10000000 - 1
2011.07.03 13:23:32     test (EURUSD,M5)        11.00000000 - 0
2011.07.03 13:23:32     test (EURUSD,M5)        110.00000000 - 0
[Supprimé]  

Modification de la ligne suivante dans OnStart :

double value = 210.0;

Résultat :

2011.07.03 13:28:01     test (EURUSD,M5)        0.00000021 - 23
2011.07.03 13:28:01     test (EURUSD,M5)        0.00000210 - 22
2011.07.03 13:28:01     test (EURUSD,M5)        0.00002100 - 21
2011.07.03 13:28:01     test (EURUSD,M5)        0.00021000 - 20
2011.07.03 13:28:01     test (EURUSD,M5)        0.00210000 - 19
2011.07.03 13:28:01     test (EURUSD,M5)        0.02100000 - 3
2011.07.03 13:28:01     test (EURUSD,M5)        0.21000000 - 2
2011.07.03 13:28:01     test (EURUSD,M5)        2.10000000 - 1
2011.07.03 13:28:01     test (EURUSD,M5)        21.00000000 - 0
2011.07.03 13:28:01     test (EURUSD,M5)        210.00000000 - 0

Soit je fais quelque chose de mal (merci de corriger), soit MetaDriver a fait une erreur théorique (lors de la conception de l'algorithme).

 
voix_kas:

Ma question vise à déterminer l'endroit le plus bas du lot pour le normaliser.

Vous n'avez pas besoin de définir la fouille pour le lot, il suffit de le normaliser à la bonne étape :
   lot = NormalizeDouble( lot / lot_step, 0 ) * lot_step;
   if ( lot < lot_min ) lot = lot_min;
   if ( lot > lot_max ) lot = lot_max;


Même si, lors de l'envoi d'une demande de transaction, le lot variable est mal renseigné (à la deuxième décimale), il sera rejeté par le terminal lui-même.

En tout cas, je n'ai eu aucun problème pendant plusieurs années d'utilisation de ce modèle.


Et si vous voulez réassurer, vous pouvez le normaliser jusqu'à la huitième décimale (avec réserve) - si, après une normalisation "correcte", des déchets apparaissent, ils seront beaucoup plus loin.

Документация по MQL5: Стандартные константы, перечисления и структуры / Структуры данных / Структура торгового запроса
Документация по MQL5: Стандартные константы, перечисления и структуры / Структуры данных / Структура торгового запроса
  • www.mql5.com
Стандартные константы, перечисления и структуры / Структуры данных / Структура торгового запроса - Документация по MQL5