Vergleich von gleitendem Durchschnitt (und anderen Indikatoren) und Fehler

 

Hallo zusammen!

Ich schreibe einen EA, der auf SMA-Crossing basiert (oder besser gesagt, ich dachte, ich hätte es bereits getan, weil es einfach zu sein scheint). Aber... Ich bin mit einem Problem konfrontiert worden. Der Expert Advisor arbeitet nach folgendem Prinzip: Wenn ein neuer Balken erscheint, analysiert er die SMA-Werte der letzten beiden Balken, wobei der letzte Balken, der gerade erschienen ist, nicht mitgezählt wird (der vorletzte und der vorletzte). Ich vergleiche die Werte scheinbar korrekt wie hier beschrieben. Die einzige Ausnahme ist, dass iMA mit dem letzten Parameter (Offset in Takten) 1 bzw. 2 aufgerufen wird. Ungefähr so (wenn der Code in Analogie zu dem zitierten umgeschrieben wird):

// берем два соседних значения Быстрой МА
double fast0=iMA(Symbol(), Period(), 10, 0, MODE_SMA, PRICE_CLOSE, 1);
double fast1=iMA(Symbol(), Period(), 10, 0, MODE_SMA, PRICE_CLOSE, 2);
 
// берем два значения Медленной МА
double slow0=iMA(Symbol(), Period(), 20, 0, MODE_SMA, PRICE_CLOSE, 1);
double slow1=iMA(Symbol(), Period(), 20, 0, MODE_SMA, PRICE_CLOSE, 2);
 
// сравниваем значения и определяем направление пересечения
if (fast0>slow0 && fast1<slow1) Print("Пересечение ВВЕРХ");
if (fast0<slow0 && fast1>slow1) Print("Пересечение ВНИЗ");

Der Expert Advisor funktioniert in primitiver Form bei Vorhandensein eines Crossing-Signals nach dem Prinzip: Schließen Sie den vorherigen Handel - eröffnen Sie einen neuen. Wenn alle Crossovers erkannt werden, werden die Trades natürlich immer nacheinander ausgeführt (SELL - BUY - SELL - BUY - ...). Das heißt, der Expert Advisor hat zu jeder Zeit nur einen offenen Handel (außer in dem Moment, bevor er den allerersten Handel tätigt). Hier liegt also der Kern des Problems... Für die Minute Zeitrahmen und SMA Perioden 5 und 34 für Close in der Strategie-Tester in der Bar von 17.02.2015 um 01:24 Ich fing eine interessante Situation. Muvings mit diesen Merkmalen kreuzen sich direkt bei Bar-Close. Hier ist das Bild:

17.02.2015 01:24

Zu Fehlersuchzwecken gebe ich die Informationen aus. Die Entsprechung im Protokoll im Vergleich zum angegebenen Code ist wie folgt:

SMAFastCurrent =fast0

SMASlowCurrent =slow0

SMAFastPrevious =fast1

SMASlowPrevious=slow1 und

SMACurDifference = SMAFastCurrent - SMASlowCurrent

SMAPrevDifference = SMAFastPrevious - SMASlowPreviousc (d. h. die Differenz zwischenfast0,slow0 bzw.fast1,slow1).

Wenn also diese Unterschiede das Vorzeichen wechseln, bedeutet dies, dass es sich um ein Signal für eine Mooving Crossing handelt. Aber in diesem speziellen Beispiel funktioniert die Prüfung auf mehr oder weniger nicht. Die Werte dieser Unterschiede sind im Protokoll angegeben. Das rote Rechteck zeigt die Werte der Differenzen auf dem nächsten Balken nach dem Problem (bei 1:25), orange - auf dem nächsten (bei 1:26). Und es ist klar, dass die SMACurDifference-Werte des vorherigen Balkens und SMAPrevDifference des aktuellen Balkens gleich sein müssen (der aktuelle Balken wird zum vorherigen und der neue Balken nimmt seinen Platz ein). Da die Mooving-Kreuzung also beim Abschluss des Problem-Balkens um 1:24 Uhr auftritt, sind die Werte von SMAFastCurrent und SMASlowCurrent beim nächsten Balken (um 1:25 Uhr) (ungefähr) gleich. Der Debugger gibt sie im Allgemeinen mit einer Genauigkeit von 5 Stellen aus (SMAFastCurrent = 1,13371 SMASlowCurrent = 1,13371 siehe Abbildung). Ihre Differenz ist infinitesimal, aber nicht 0 (SMACurDifference = 2.220446049250313e-016). Auf dem nächsten Balken wird ihre Differenz bei denselben exakten Werten genau Null (vgl. SMACurDifference in den roten und SMAPrevDifference in den orangefarbenen Rechtecken). Eigentlich ist es nicht klar, wie man diese Fehler ausschalten kann, wenn selbst scheinbar identische Werte unterschiedliche Differenzen ergeben. Daraus ergeben sich zwei Fragen:

1. Warum wird die Differenz der gleichen Muvings nur zum Zeitpunkt des abwechselnden Auftretens zweier benachbarter Takte gezählt und ergibt ein anderes Ergebnis?

2. Ich dachte daran, ein gewisses Epsilon einzuführen und mit diesem zu vergleichen, anstatt mit Null. Normalerweise wird dies jedoch für den Vergleich eines Infinitesimals mit 0 getan. Was ist mit dem Fall, dass ich einen Vorzeichenwechsel dieses Infinitesimals bestimmen muss?

Natürlich kann ich drei nebeneinander liegende Balken analysieren, aber es ist immer noch theoretisch möglich, dass sich die Muvings zu den Preisen ihrer Schließungen in einem infinitesimalen Abstand berühren. Mir ist klar, dass eine solche Situation nur selten eintritt (vor allem, wenn wir einen größeren Zeitrahmen zugrunde legen), aber sie kann dennoch vorkommen. Und das sollte irgendwie aufgefangen werden, und die Kreuzung von Mouveins sollte auch in diesem Fall aufgedeckt werden.

Vielen Dank im Voraus für jede Hilfe!

Навигатор по форуму и ответы на часто задаваемые вопросы. Настоятельно Рекомендуется к Прочтению! - MQL4 форум
  • www.mql5.com
Навигатор по форуму и ответы на часто задаваемые вопросы. Настоятельно Рекомендуется к Прочтению! - MQL4 форум
 

Versuchen Sie eine Normalisierung und einen Vergleich.

Das MQL4-Referenzhandbuch (und es ist das gleiche für MQL5) sagt, öffnen Sie auf"Real Types (double, float)":

"...Man kann nicht zwei reelle Zahlen auf Gleichheit miteinander vergleichen. In den meisten Fällen können sich zwei scheinbar identische Zahlen als ungleich erweisen, weil sie sich um 15 Dezimalstellen unterscheiden. Um zwei reelle Zahlen korrekt zu vergleichen, muss man die normierte Differenz dieser Zahlen mit einem Nullwert vergleichen...."

"... es wird dringend davon abgeraten, zwei reelle Zahlen miteinander auf Gleichheit zu vergleichen, da ein solcher Vergleich nicht korrekt ist.

..............


Wenn es jedoch notwendig ist, zwei reelle Zahlen auf Gleichheit zu vergleichen, kann dies auf zwei verschiedene Arten geschehen. Die erste Möglichkeit besteht darin, die Differenz zwischen den beiden Zahlen mit einem kleinen Wert zu vergleichen, der die Genauigkeit des Vergleichs definiert.

.............


Bei der zweiten Methode wird die normierte Differenz zweier reeller Zahlen mit einem Nullwert verglichen. Es ist sinnlos, die Differenz normalisierter Zahlen mit Null zu vergleichen, da jede mathematische Operation mit normalisierten Zahlen zu einem nicht-normalisierten Ergebnis führt.

...."

 
rosomah:

Versuchen Sie eine Normalisierung und einen Vergleich.

Das MQL4-Referenzhandbuch (und es ist das gleiche für MQL5) sagt, öffnen Sie auf"Real Types (double, float)":

"...Man kann nicht zwei reelle Zahlen auf Gleichheit miteinander vergleichen. In den meisten Fällen können sich zwei scheinbar identische Zahlen als ungleich erweisen, weil sie sich um 15 Dezimalstellen unterscheiden. Um zwei reelle Zahlen korrekt zu vergleichen, muss man die normierte Differenz dieser Zahlen mit einem Nullwert vergleichen...."

"Es wird kategorisch davon abgeraten, zwei reelle Zahlen miteinander auf Gleichheit zu vergleichen, da dieser Vergleich nicht gültig ist.

..............


Wenn es jedoch notwendig ist, zwei reelle Zahlen auf Gleichheit zu vergleichen, kann dies auf zwei verschiedene Arten geschehen. Die erste Möglichkeit besteht darin, die Differenz zwischen den beiden Zahlen mit einem kleinen Wert zu vergleichen, der die Genauigkeit des Vergleichs angibt.

.............


Die zweite Möglichkeit besteht darin, die normierte Differenz zweier reeller Zahlen mit Null zu vergleichen. Es ist sinnlos, die Differenz normalisierter Zahlen mit Null zu vergleichen, da jede mathematische Operation mit normalisierten Zahlen zu einem nicht-normalisierten Ergebnis führt.

...."

Ich bin mir bewusst, dass es nicht möglich ist, reale Zahlen auf Gleichheit zu vergleichen. In dem von mir zitierten Code gibt es keine Gleichheitsvergleiche. Und es gibt auch keinen Grund dafür. Hier haben wir es mit einer Situation zu tun, in der wir Änderungen eines infinitesimalen Vorzeichens auffangen müssen, die durchaus 0 erreichen könnten. Einfach alles mit mehr oder gleich 0 zu vergleichen, ist auch in diesem Fall gefährlich. Und die Normalisierung kann hier sogar noch gefährlicher sein... Die Anfangswerte von MA werden auf eine unbekannte Zahl normiert (je kleiner der Zeitrahmen, desto kleiner der Wert von MA). Die Normalisierung auf eine konstante Nachkommastelle kann dazu führen, dass alle Werte von MA genau 0 sind. Um ehrlich zu sein, verstehe ich nicht wirklich, was der Unterschied zwischen zwei MA-Werten sein wird...

 

gammaray:

Ich bin mir bewusst, dass es nicht möglich ist, echte Zahlen auf Gleichheit zu vergleichen. In dem von mir zitierten Code gibt es keine Gleichheitsvergleiche. Und es gibt auch keinen Grund dafür. Wir haben es hier mit einer Situation zu tun, in der wir Änderungen eines infinitesimalen Vorzeichens erfassen müssen, das durchaus 0 erreichen kann. Einfach alles mit mehr oder gleich 0 zu vergleichen, ist auch in diesem Fall gefährlich. Und die Normalisierung kann hier sogar noch gefährlicher sein... Die Anfangswerte von MA werden auf eine unbekannte Zahl normiert (je kleiner der Zeitrahmen, desto kleiner der Wert von MA). Die Normalisierung auf eine konstante Nachkommastelle kann dazu führen, dass alle Werte von MA genau 0 sind. Um ehrlich zu sein, verstehe ich nicht wirklich, was der Unterschied zwischen zwei MA-Werten sein wird...

Warum ist die Normalisierung gefährlicher?

Also:

...

Wenn Sie zwei reelle Zahlen auf Gleichheit vergleichen müssen, können Sie dies auf zwei verschiedene Arten tun. Die erste Möglichkeit besteht darin, die Differenz zwischen den beiden Zahlen mit einem kleinen Wert zu vergleichen, der die Genauigkeit des Vergleichs festlegt.

...

Bei der zweiten Methode wird die normierte Differenz zweier reeller Zahlen mit einem Nullwert verglichen. Ein Vergleich der Differenz der normierten Zahlen mit Null ist nutzlos, da jede mathematische Operation mit normierten Zahlen ein nicht normiertes Ergebnis ergibt.

Beispiel:

bool CompareDoubles(double number1,double number2)
  {
   if(NormalizeDouble(number1-number2,8)==0) return(true);
   else return(false);
  }
void OnStart()
  {
   double d_val=0.3;
   float  f_val=0.3;
   if(CompareDoubles(d_val,f_val)) Print(d_val,"equals",f_val);
   else Print("Different: d_val = ",DoubleToString(d_val,16),
              "  f_val = ",DoubleToString(f_val,16));
// Результат: Different: d_val= 0.3000000000000000   f_val= 0.3000000119209290
  }
  • Und meine persönliche praktische Erfahrung (um es bescheiden auszudrücken, sie ist nicht klein in Bezug auf die Anzahl der sorgfältigen Überprüfungen des Programmablaufs, bei denen ich den Vergleich von Zahlen mit Double angewandt habe und immer noch anwende, in Bezug auf die Korrektheit der Bedingungen, die auf der Grundlage solcher Vergleiche ausgelöst werden),
Das erlaubt mir, solche Vergleiche nicht nur als nicht bedrohlich zu betrachten:
if(NormalizeDouble(number1-number2,dig)==0)
if(NormalizeDouble(number1-number2,dig)>0)
if(NormalizeDouble(number1-number2,dig)<0)

// dig=Digits();

sondern umgekehrt eine Abwandlung einer der beiden Möglichkeiten, die, wie es in der Dokumentation heißt, auf Vergleiche von Doppelzahlen angewendet werden kann.

Seitdem:

Man kann zwei reelle Zahlen nicht auf Gleichheit miteinander vergleichen. In den meisten Fällen können sich zwei scheinbar identische Zahlen als ungleich erweisen, weil sie einen Wertunterschied von 15 Dezimalstellen aufweisen. Um zwei reelle Zahlen korrekt zu vergleichen, muss die normierte Differenz dieser Zahlen mit Null verglichen werden.



P./S.: Es hat sich so ergeben, dass die erste Methode aus der Dokumentation für mich weniger geeignet war, auch aufgrund von Aufgaben, die ich in der Regel selbst löse. Daher habe ich mit dem ersten Weg nicht viel Erfahrung.

Bei der zweiten Methode (d. h. dem Vergleich der normalisierten Differenz zweier reeller Zahlen mit dem Nullwert im Ausdruck des bedingten Operators) traten jedoch keine Probleme auf.

Aber wenn ich einen Vergleich von nicht-normalisierten Zahlen gemacht habe (hier meine ich, auch das, was ich ohne die erste Methode gemacht habe), dann ja, dann gab es, dass ich falsche Auslösung von Bedingungen auf der Grundlage von Vergleichen von Zahlen des Typs double gefunden habe.

 
gammaray:

Dies sind die Formulierungen aus der Dokumentation:

Bei der zweiten Methode wird die normierte Differenz von zwei reellen Zahlen mit Null verglichen. Der Vergleich der Differenz normalisierter Zahlen mit Null ist nutzlos, da jede mathematische Operation mit normalisierten Zahlen ein nicht normalisiertes Ergebnis ergibt.

Ich habe den Eindruck, dass man bei mathematischen Operationen (und auch bei verschiedenen Transformationen) so etwas nicht tun sollte:

// dig=Digits();

double delta=NormalizeDouble(number1-number2,dig);

if (delta>0)


D.h., im vorherigen Beitrag habe ich Beispiele für Vergleiche der normierten Differenz zweier reeller Zahlen mit dem Wert Null genannt. Und in diesem Beitrag wird die Differenz der normalisierten Zahlen mit Null verglichen (so wie ich den Text der obigen Sätze in der Dokumentation verstehe).

Das war's, kurz und bündig.

 

gammaray:

...

Was die Normalisierung der Differenz zwischen den beiden MA-Werten bewirken soll, verstehe ich ehrlich gesagt nicht wirklich.

P./S.: Zu diesem Punkt können Sie einfach Print() für eine Weile in Ihren Code einfügen, um zu sehen, was bei großen Datenmengen ausgegeben wird. In Print print drucken Sie nicht-normierte und normierte (bis zu einer gewissen Dezimalstelle, auch größer als in der Tabelle, in der Sie die Experimente durchführen werden) Werte, die Sie durch mathematische Operationen erhalten haben. Einschließlich einfach nicht-normierter und normierter iMA-Werte, da sie auf der Grundlage mathematischer Operationen gebildet werden.

Nur für den Fall, lassen Sie mich auch darauf hinweisen, dass beim Drucken von nicht normalisierten und normalisierten Werten vom Typ Double, sollten sie zusätzlich konvertiert werden, natürlich von numerischen Wert zu Text-Wert mit DoubleToString (und in DoubleToString Experiment mit der Anzahl der Dezimalstellen).

 
gammaray:

P./S.: Ich möchte auch hinzufügen, dass ich denke, dass in den Beispielen aller Schemata, die für MQL4-Programmierer geschrieben wurden, die Normalisierung der mathematischen Berechnungswerte nicht vorgeschrieben oder/und nicht ausdrücklich angegeben ist:

  • zum leichteren Verständnis von Schemata zur Bildung beliebiger Bedingungen;
  • Es kann sein, dass nicht immer und/oder nicht überall eine Normalisierung erforderlich ist (einschließlich der Annahme, dass für verschiedene Aufgaben unterschiedliche Niveaus tolerierbarer Fehler gelten und dementsprechend eine unterschiedliche weitere Normalisierung (oder das Fehlen einer solchen) der Ergebnisse mathematischer Operationen auf die Anzahl der Dezimalstellen für einige individuelle Aufgaben);
  • und/oder es wird davon ausgegangen, dass ein Entwickler mit der Dokumentation vertraut ist und/oder sie gelesen hat, um seine Fragen zu klären.
Etwa so.
 
Das ist viel genauer.
// сравниваем значения и определяем направление пересечения
if (fast0>slow0 && fast1<=slow1) Print("Пересечение ВВЕРХ");
if (fast0<slow0 && fast1>=slow1) Print("Пересечение ВНИЗ");

Ich meine, es wurde nicht berücksichtigt, dass die ma-Werte auch gleich sein können.

сравнивать вещественные числа на равенство нельзя

etwas anders.
 
Aleksey Lebedev:
Ein wenig über etwas anderes.

Es kommt darauf an, was Sie vorhaben und für welche Aufgaben/Ziele.

Beim Schreiben der Beiträge in diesem Thread stütze ich mich also auf:

  • Der Screenshot und die Fragen im ersten Beitrag;
  • den zweiten Beitrag des Verfassers des Threads (über die Gefahren der Normalisierung),

und folglich auch von hier aus und, um es kurz zu machen, von der Bedeutung meiner obigen Beiträge:

Mit Hilfe der Normalisierung ist es möglich, das erforderliche Genauigkeitsniveau der Vergleiche (und/oder der Ausgabewerte) und/oder die für einige Aufgaben und Ziele tolerierbaren Fehler festzulegen/anzupassen, was wiederum die Auslösung von Programmbedingungen genau dort und so ermöglicht, wie es bei der Vorgabe bestimmter Bedingungen im Code beabsichtigt war. Und der Vergleich der normalisierten Differenz mit Null ermöglicht nicht nur bei Vergleichen mit Hilfe von Relationen eine Anpassung/Anpassung: "==".


P./S.: So werde ich auf jeden Fall noch einmal angeben, dass der Vergleich der reellen Zahlen nach dem ersten Weg von zwei hier aufgez�hlten, wegen des Vergleiches des Unterschiedes der Zahlen mit einem beliebigen kleinen Wert, ich nicht schlechter nennen kann, als die Anwendung der Normalisierung, wenn man das Niveau der Vergleiche anpassen muss (einschließlich, da f�r mich der zweite Weg bequemer erschien, den ersten und hielt f�r sich nicht genauer f�r die praktische Anwendung).


 

Das hat im Prinzip nichts mit mql zu tun. Nehmen wir eine abstrakte Programmiersprache. In dem von mir angeführten Beispiel besteht das Hauptproblem darin, dass die Werte für die Differenz der Muwings in ein und demselben Balken nicht gleich sind (2e-16 in der ersten Berechnung und genau 0 in der zweiten). In diesem Fall darf dieser Schnittpunkt in keiner Weise bestimmt werden. Wenn wir zu mql zurückkehren, bedeutet Normalisierung, dass die Zahl gerundet wird (oder besser gesagt, dass einfach alle Zahlen nach einem bestimmten Vorzeichen weggelassen werden, wie in der Sish-Funktion floor, aber auf eine bestimmte Dezimalstelle). Woher weiß ich also, auf welche Ziffer ich normalisieren muss? Wenn die falsche Ziffer gewählt wird, können alle Werte IMMER auf genau 0 gerundet werden. Die Normalisierung ist hier also gefährlich und löst das Problem im Allgemeinen nicht.

Zu dem, was Alexey Lebedev geschrieben hat. Ja, ich habe in diese Richtung gedacht. Wenn wir jedoch beide Differenzen um mehr oder gleich 0 vergleichen, besteht die Wahrscheinlichkeit, dass wir ein falsches Signal erhalten (z. B. die theoretisch mögliche Situation, dass die Bewegungen zwischen benachbarten Balken genau die gleichen Werte haben). Dann ändert ihre Differenz das Vorzeichen nicht (es gibt keine Kreuzung), aber das Signal für die Kreuzung wird programmatisch bestimmt. Sie könnten, wie Sie vorgeschlagen haben, nur einen Vergleich auf mehr oder gleich setzen. Aber dann ist das Problem, dass in der Berechnung in dieser Situation zunächst wird es nicht gleich 0 (2e-16), und auf der nächsten Bar wird es genau 0, aber es wird eine strenge Vergleich sein.

Es ist wichtig zu verstehen, warum die gleiche Differenz, wenn sie auf verschiedenen Balken berechnet wird, NICHT das gleiche Ergebnis ergibt. Wäre das Ergebnis dasselbe, würde das Problem immer durch die Einführung eines nicht strengen Vergleichs gelöst werden

 

gammaray:

Aber das ganze Problem ist, dass bei der Berechnung in dieser Situation zunächst nicht gleich 0 (2e-16), und auf der nächsten Bar wird es bereits genau 0 sein, aber es wird bereits ein strenger Vergleich sein.

Es ist wichtig zu verstehen, warum die gleiche Differenz, wenn sie auf verschiedenen Balken berechnet wird, NICHT das gleiche Ergebnis ergibt. Wäre das Ergebnis dasselbe, würde das Problem immer durch die Einführung eines nicht strengen Vergleichs gelöst werden

Wahrscheinlich wurde die Berechnung der iMA-Funktion optimiert. Erster Wert = Summe(Abschluss)/N, zweiter Wert = vorheriger Wert des MA+(neuer Abschluss-alter Abschluss)/N.

Grund der Beschwerde: