Fehler, Irrtümer, Fragen - Seite 442

 
voix_kas:

Hat jemand einen fertigen Code zur Berechnung der Anzahl der signifikanten Stellen für ein Volumen?
So etwas wie SymbolInfoInteger(_Symbol, SYMBOL_DIGITS), aber nur für Volumen.
Zum Beispiel für den Fall SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_STEP) = "1.0" - die Antwort wäre "0", für "0.1" - "1", für "0.01" - 2" usw.

Lassen Sie mich eine Nuance klarstellen. Für einen Volumenschritt wie "0,1", "0,01", "0,001" habe ich.

Der Code sollte für die folgenden Fälle funktionieren: "0,2", "0,11", 0,023" usw.

Es gibt keinen speziellen Codefür die Lautstärke. Es gibt für alles eine Lösung.

int CountSignedDigits(double x)
{  
  for(int i=0; i<1000; i++,x*=10) if(x-MathFloor(x)<DBL_MIN*2) return i;
  return -1;
}
Das Skript ist zur Kontrolle im Trailer.
Dateien:
_UniTest.mq5  2 kb
 
MetaDriver:
Ein Skript zum Überprüfen im Trailer.
Sie meinen, dass..., ich dachte, ich sollte die zulässige Menge überprüfen, bevor ich eine Bestellung aufgebe.
 
sergeev:
Sie meinen, dass..., und ich dachte, ich sollte die zulässige Menge überprüfen, bevor ich eine Bestellung aufgebe.

;)

Ich weiß nicht wirklich, was er will. Wir werden sehen, was er sagt. Ich übe nur meine Telepathie. ;)

 
voix_kas:

Hat jemand einen fertigen Code für die Berechnung der Anzahl der signifikanten Stellen für ein Volumen?
So etwas wie SymbolInfoInteger(_Symbol, SYMBOL_DIGITS), aber nur für Volumen.
Zum Beispiel für den Fall SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_STEP) = "1.0" - die Antwort wäre "0", für "0.1" - "1", für "0.01" - 2" usw.

Lassen Sie mich eine Nuance klarstellen. Für einen Volumenschritt wie "0,1", "0,01", "0,001" habe ich.
Der Code sollte für die folgenden Fälle funktionieren: "0,2", "0,11", 0,023" usw.

Speziell für Volumen kann einfach sein:

      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++;
 

sergeev
MetaDriver
Valmars

Eine gut formulierte Frage ist schon die halbe Antwort. :) Entschuldigung, ich bin schon ins Bett gegangen, ich habe die Aufgabe nicht genau beschrieben. Ich werde es noch einmal versuchen.

Ich spreche davon, ein normalisiertes Volumen an einen Handelsauftrag zu übergeben.
Es geht darum, was wir mit dem Preis machen:

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

Preisnormalisierung - ich denke, das ist jedem klar.

Zu meiner Zeit (seit MT4) habe ich irgendwo in MT-Artikeln gelesen, dass es wünschenswert wäre, auch das Volumen zu normalisieren.
Eigentlich habe ich die FunktionGetVolumeDigits(string Symbol) geschrieben, um den kleinstmöglichen Wert des Volumens gemäß den Bedingungen des Brokers zu finden. Es gibt mindestens zwei Implementierungen (das Ergebnis ist das gleiche):
Umsetzung #1.

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

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

Beide funktionieren perfekt mit Varianten, bei denen die Mindestschrittweite = 1,0, 0,1, 0,01, 0,001 usw. ist. Das heißt, wenn der Mindestschritt 1,0 ist, gibt die Funktion 0 zurück; wenn der Schritt 0,1 ist, gibt die Funktion 1 zurück usw.
Was ist, wenn der Mindestschritt z. B. 1,1, 0,11 oder 0,011 beträgt? Bei diesem Algorithmus wird fälschlicherweise die niedrigstwertige Ziffer angezeigt.
Sie können natürlich behaupten, dass es solche Fälle in der Praxis nicht gibt. Ich möchte nur eine solche hypothetische Möglichkeit in meinem Expert Advisor berücksichtigen. Ich dachte, dass vielleicht jemand seine Erfahrungen in dieser Angelegenheit mitteilen könnte...

 
voix_kas:
Ja, ich verstehe, Sie wollen, dass das Ergebnis ein Vielfaches von VolumeStep ist. Nun, das hat nichts mit den Ziffern zu tun. Berechnen Sie das Volumen zunächst mit Ziffern und reduzieren Sie es dann auf das nächste Vielfache von VolumeStep.
 
voix_kas:

Es geht darum, das normalisierte Volumen an den Handelsauftrag zu senden.
Ich möchte nur diese hypothetische Möglichkeit in unserem Expert Advisor berücksichtigen.

Von welchem "hypothetischen" Instrument ist die Rede?

1. Die Variante von MetaDriver ist für Sie geeignet. CountSignedDigits zeigt die Anzahl der Zeichen in jedem Los an.

2. Wenn Sie die Anzahl der Ziffern kennen, können Sie die Normalisierung vornehmen:

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); // вернули
}
 

sergeev
Vielen Dank für die Losvalidierungsfunktion. Ich verwende eine ähnliche Konstruktion/Verzweigung von Schecks.
Meine Frage zielt darauf ab, den jüngsten Platz auf dem Parkplatz zu finden, um ihn zu normalisieren.
Insbesondere gab MetaDriver seine Konstruktion für "alles" an. :) Allerdings ist es nicht ohne Fehler (oder mein Compiler ist fehlerhaft). Nachstehend finden Sie den Code und das Ausführungsergebnis:

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;
}

Ergebnis:

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

Nächste Option (die Funktion CountSignedDigits ist dieselbe):

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

Ergebnis:

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
 

Die folgende Zeile in OnStart wurde geändert:

double value = 210.0;

Ergebnis:

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

Entweder mache ich etwas falsch (bitte korrigieren), oder MetaDriver hat einen Fehler in der Theorie gemacht (bei der Entwicklung des Algorithmus).

 
voix_kas:

Meine Frage zielt darauf ab, die niedrigste Stelle in der Partie zu bestimmen, um sie zu normalisieren.

Sie brauchen nicht zu definieren, wie viel zu graben ist, sondern nur, wie hoch die richtige Stufe ist:
   lot = NormalizeDouble( lot / lot_step, 0 ) * lot_step;
   if ( lot < lot_min ) lot = lot_min;
   if ( lot > lot_max ) lot = lot_max;


Selbst wenn beim Senden einer Handelsanforderung die Variable Lot unsauber wird (mit der zweiten Dezimalstelle), wird sie vom Terminal selbst abgelehnt.

Zumindest hatte ich in den vielen Jahren, in denen ich dieses Design verwende, keine Probleme.


Und wenn Sie sich rückversichern wollen, können Sie es auf die 8. Dezimalstelle normalisieren (mit Reserve) - wenn nach der "richtigen" Normalisierung Müll auftaucht, wird es viel weiter sein.

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