Diskussion zum Artikel "Die Rezepte MQL5 - Die Erstellung des Ringpuffers für eine schnelle Berechnung der Indikatoren im gleitenden Fenster"
Forum über Handel, automatisierte Handelssysteme und das Testen von Handelsstrategien
fxsaber, 2016.09.16 14:32
void OnStart() { double Index = -345.23; double Size = -432.98; double Array[]; // Jede beliebige Größe (und nicht Integer) wird funktionieren. ArrayResize(Array, (int)Size < 0 ? (int)MathAbs(Size) : (int)Size); // Bei jedem Index (und nicht Integer) wird IMMER (außer bei Null - wenn die Array-Größe Null ist) ohne Fehler ausgeführt. // So wird das Array zu einer unendlichen Kopie seiner selbst in beide Richtungen Array[(int)Index < 0 ? ArraySize(Array) + ((int)Index % ArraySize(Array)) : (int)Index % ArraySize(Array)] = 1; }
int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) { //--- bool calc = false; for(int i = prev_calculated; i < rates_total; i++) { Sma.AddValue(price[i]); buff[i] = Sma.SMA(); calc = true; } if(!calc) { Sma.ChangeValue(MaPeriod-1, price[rates_total-1]); buff[rates_total-1] = Sma.SMA(); } return(rates_total-1); }
int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) { //--- if (prev_calculated < rates_total) for(int i = prev_calculated; i < rates_total; i++) { Sma.AddValue(price[i]); buff[i] = Sma.SMA(); } else { Sma.ChangeValue(MaPeriod-1, price[rates_total-1]); buff[rates_total-1] = Sma.SMA(); } return(rates_total-1); }
ZY Wenn prev_calculated auf Null gesetzt wird, kommt es zu Fehlern.
Sehr guter Artikel zu einem sehr wichtigen Thema.
DerRingpuffer ist ein entscheidender Mechanismus.
Ergänzend zu dem Artikel möchte ich meine Idee hinzufügen, wie die Verwendung von Ringpuffern weiter entwickelt werden kann:
Wenn parallel zur Aufzeichnung der Werte eines Parameters in einem Ringpuffer ein zweiter Ringpuffer für diesen Parameter angelegt wird, der die Zeit zwischen den Wertänderungen im ersten Puffer aufzeichnet, kann aus den Daten beider Ringpuffer eine Kurve der Wertänderungen im aktuellen Zeitraum konstruiert werden. Ferner ist es möglich, mit Hilfe mathematischer Operationen den Charakter der Parameterwertänderung, d.h. ihre aktuelle Signatur, zu extrahieren und nicht mit spezifischen Werten, sondern mit dem Kontext der Parameteränderung für die gesamte aktuelle Periode zu arbeiten.
P.S. Es wäre toll, wenn jemand dies als unabhängigen Mechanismus implementieren könnte. Versuchen Sie es?
Vielen Dank für den Artikel! Ich habe ein paar Fragen und bissige Bemerkungen )
По возможности избегайте запросов по получению данных множества таймфреймов. Вместо этого для расчетов воспользуйтесь одним (наименьшим) таймфреймом. Например, если вам требуется рассчитать два индикатора на M1 и H1, получите данные M1, сконвертируйте их в H1 и затем подайте эти данные для расчета индикатора на H1. Такой подход сложнее, но позволит существенно сэкономит память.
Worauf ist die Einsparung zurückzuführen?
Die vom Terminal generierte H1-Zeitreihe benötigt mehr Speicher als die gleiche Zeitreihe, die im Expert Advisor generiert wird?
Wir benötigten jedoch immer noch fast 3 GB RAM. Gibt es eine andere Möglichkeit, diese Zahl zu reduzieren? Das können wir, wenn wir die Anzahl der Zeitrahmen optimieren. Versuchen wir, den Testcode ein wenig zu ändern und nur einen Zeitrahmen anstelle von 21 zu verwenden - PERIOD_M1. Die Anzahl der Indikatoren bleibt gleich, nur einige von ihnen werden dupliziert:
Jetzt belegen die gleichen 504 Indikatoren im internen Berechnungsmodus 548 MB RAM.
Ich verstehe diesen Schritt überhaupt nicht. Wie kann man die Berechnung von Indikatoren für 21 Zeitrahmen mit der Berechnung für 1 TF vergleichen? Die Ergebnisse der Berechnungen sind sehr unterschiedlich, welchen Unterschied macht es, wie viel Speicher verwendet wird?
Es gibt wohl kaum eine wichtigere Anwendung für Ringpuffer als den Handel. Umso überraschender ist es, dass dieser Datenkonstruktionsalgorithmus in der MQL-Gemeinschaft bis jetzt nicht behandelt wurde.
Konstantin Gruzdev hat seine Klasse und einige Beispiele bereits 2012 veröffentlicht. Eine Suche wird sie finden.
Im Allgemeinen ist die Technik natürlich gut. Ein Nachteil ist, dass alle Indikatoren neu geschrieben werden müssen.
Vielen Dank für den Artikel! Ich habe ein paar Fragen und bissige Kommentare )
Vermeiden Sie nach Möglichkeit Abfragen zum Abruf von Daten aus mehreren Zeiträumen. Verwenden Sie stattdessen einen (kleinsten) Zeitrahmen für die Berechnungen. Wenn Sie z. B. zwei Indikatoren für M1 und H1 berechnen müssen, holen Sie die M1-Daten ab, konvertieren Sie sie in H1 und füttern Sie dann diese Daten, um den Indikator für H1 zu berechnen. Dieser Ansatz ist zwar komplizierter, spart aber Speicherplatz.
Was spart Speicherplatz?
Die vom Terminal generierte H1-Zeitreihe belegt mehr Speicherplatz als die gleiche Zeitreihe, die im Expert Advisor generiert wird?
Leider ja. Und viel mehr. Dabei spielt es keine Rolle, ob Sie einen einzelnen Balken oder die gesamte verfügbare Historie angefordert haben. Alle Daten für den angegebenen Zeitrahmen werden in den internen Speicher kopiert. Ich weiß nicht genau, wie viele Daten kopiert werden, aber nach meinen Speichermessungen wurde festgestellt, dass fast alles kopiert wird.
Wir brauchen aber immer noch fast 3 GB RAM. Gibt es eine Möglichkeit, diese Zahl zu reduzieren? Das kann man, wenn man die Anzahl der Zeitrahmen optimiert. Versuchen wir, den Testcode ein wenig zu ändern und nur einen Zeitrahmen anstelle von 21 zu verwenden - PERIOD_M1. Die Anzahl der Indikatoren bleibt gleich, nur einige von ihnen werden dupliziert:
Jetzt belegen die gleichen 504 Indikatoren im internen Berechnungsmodus 548 MB RAM.
Ich verstehe diesen Schritt überhaupt nicht. Wie kann man die Berechnung von Indikatoren für 21 Zeitrahmen mit der Berechnung für 1 TF vergleichen? Die Ergebnisse der Berechnungen sind sehr unterschiedlich, was macht es für einen Unterschied, wie viel Speicher verwendet wird?
Wenn Sie nur einen kleinsten Zeitrahmen verwenden, um mehrere Indikatoren für verschiedene Zeitrahmen zu berechnen, sparen Sie Speicherplatz. Nehmen wir an, es gibt zwei Indikatoren, von denen einer die Werte auf M1 und der andere auf H1 zählt. Wir können Kurse für M1 und für H1 laden. Wir können Kurse für jeden Indikator laden und Werte von ihnen erhalten. Da jedoch auch H1 geladen wird, steigt der Speicherbedarf erheblich. Wenn wir also M1 abfragen, dann M1 in H1 konvertieren und diese Daten in den Indikator auf H1 einspeisen, wird der Speicherbedarf erheblich gesenkt. Diese Einsparung wird dadurch erreicht, dass MetaTrader-interne Puffer viel mehr Speicher für die Speicherung von H1-Kursen bereitstellen, als wenn diese Kurse innerhalb des Expert Advisors gespeichert würden.
Ein weiteres interessantes Merkmal, das in dem Artikel nicht erwähnt wurde. Das Modell der Speicherzuweisung im Strategietester ist anders und viel sparsamer. Es wird viel weniger Speicher zugewiesen, wenn mehrere Zeitrahmen verwendet werden, aber alles wird normal berechnet.
...
Mit dem Verfassen des Artikels wurden im Allgemeinen drei Ziele verfolgt:
- Schnelle Algorithmen für Berechnungen von Indikatoren innerhalb des Expert Advisors zu erstellen (abgeschlossen).
- Schaffung einer komfortablen Schnittstelle für Berechnungen im Ringpuffer (abgeschlossen).
- Erstellen einer speicherschonenden Berechnung (nicht implementiert).
Sehr guter Artikel zu einem sehr wichtigen Thema.
Der Ringpuffer ist ein entscheidender Mechanismus.
Ergänzend zu dem Artikel möchte ich meine Idee hinzufügen, wie die Verwendung von Ringpuffern weiter entwickelt werden kann:
Wenn parallel zur Aufzeichnung der Werte eines Parameters in einem Ringpuffer ein zweiter Ringpuffer für diesen Parameter angelegt wird, der die Zeit zwischen den Wertänderungen im ersten Puffer aufzeichnet, kann aus den Daten beider Ringpuffer eine Kurve der Wertänderungen im aktuellen Zeitraum konstruiert werden. Ferner ist es möglich, mit Hilfe mathematischer Operationen den Charakter der Parameterwertänderung, d.h. ihre aktuelle Signatur, zu extrahieren und nicht mit spezifischen Werten, sondern mit dem Kontext der Parameteränderung für die gesamte aktuelle Periode zu arbeiten.
P.S. Es wäre toll, wenn jemand dies als unabhängigen Mechanismus implementieren könnte. Versuchen Sie es?
Was Sie beschreiben, ist nur ein Indikator. Erstellen Sie eine Klasse, sagen wir CTradeChange. Darin platzieren Sie zwei synchrone Ringpuffer: einer speichert N letzte Preise, der andere N letzte Zeitwerte:
CTradeChange change;
...
change.Add(value, TimeCurrent());
Berechnen Sie dann in der Add-Methode die Differenz zwischen dem aktuellen und dem vorherigen Zeitwert.
Mit dem Verfassen des Artikels wurden im Allgemeinen drei Ziele verfolgt:
- Schaffung schneller Algorithmen für die Berechnung von Indikatoren innerhalb des Expert Advisors (abgeschlossen).
- Schaffung einer praktischen Schnittstelle für Berechnungen im Ringpuffer (abgeschlossen).
- Erstellen einer speicherschonenden Berechnung (nicht implementiert).
Ich danke Ihnen für Ihre Antworten.
Bei der Entwicklung des im Artikel erwähnten Panels kam ich auf die Notwendigkeit, die Anzahl der auf den Charts angezeigten Balken zu begrenzen (5000). Eben wegen des Speichers...
In MT4 war es viel einfacher: Erstens wurde jeder TF unabhängig geladen, so dass es nicht erforderlich war, M1 zu laden, und zweitens nahmen die Indikatorpuffer so viel Platz ein, wie man sie füllte (sogar 100 Balken, wenn man nicht mehr brauchte).
In 5 ist es universeller und integraler geworden, da die TFs aus M1 generiert werden, aber der Speicherplatz kann schwierig sein.
Was Sie beschreiben, ist nur ein Indikator. Erstellen Sie eine Klasse, sagen wir CTradeChange. Darin platzieren Sie zwei synchrone Ringpuffer: einer speichert N letzte Preise, der andere N letzte Zeitwerte:
Berechnen Sie dann in der Add-Methode die Differenz zwischen dem aktuellen und dem vorherigen Zeitwert.
Sie haben eine seltsame Antwort gegeben. Es scheint, dass Sie die Idee überhaupt nicht verstanden haben. Ich zitiere sie noch einmal:
"Wenn Sie parallel zur Aufzeichnung der Parameterwerte im Ringpuffer für diesen Parameter einen zweiten Ringpuffer anlegen, der die Zeit zwischen den Änderungen der Werte im ersten Puffer aufzeichnet, dann können Sie auf der Grundlage der Daten aus beiden Ringpuffern eine Kurve der Wertänderungen im aktuellen Zeitraum erstellen. Mit Hilfe mathematischer Operationen können Sie die Art der Änderung des Parameterwerts- d. h. seine aktuelle Signatur -extrahieren und nicht mit spezifischen Werten, sondern mit dem Kontext der Parameteränderung über den gesamten aktuellen Zeitraum arbeiten."
Wohlgemerkt, ich habe nicht gefragt, wie man zwei synchrone Ringpuffer baut, da ihr Mechanismus recht einfach ist, sondern vorgeschlagen, zu versuchen, den Anwendungsbereich von Ringpuffern weiter zu entwickeln als in dem Artikel beschrieben.
Der von Ihnen in dem Artikel vorgeschlagene Anwendungsbereich ist das Abrufen bestimmter Werte durch Indizes innerhalb der aktuellen Periode.
Ich schlage vor, den Bereich zu erweitern, um Signaturen von Wertänderungen innerhalb der aktuellen Periode zu erhalten. Dies kann durch das Aufzeichnen einer Kurve (nicht in einem Diagramm) auf der Grundlage von Daten aus zwei Ringpuffern geschehen:
1. Puffer mit Werten der aktuellen Periode.
2. Puffer mit Zeitintervallen zwischen den Werten des ersten Puffers.
Durch die Kombination der Daten ist es möglich, die Kurve mathematisch darzustellen (nicht notwendigerweise in einem Diagramm) und sie innerhalb des Programms algorithmisch darzustellen und zu untersuchen. Dazu ist es notwendig, beide Puffer zu scannen und die Signatur der Parameteränderung zu berücksichtigen.
Diese Lösung eröffnet die Möglichkeit, nicht nur mit bestimmten Werten des Parameters innerhalb einer Periode zu arbeiten, sondern mit der Signatur seiner Veränderung über die gesamte Periode.
Zum Beispiel wird es möglich sein, das Programm zu spezifizieren:
if(Характер_изменения_значения_параметра_за_период == BIG_WAVE)Лот += 10;
Die Konstante BIG_WAVE ist die Signatur, die den Charakter der Wertänderung für die aktuelle Periode ausdrückt.
Wir können zum Beispiel 5 Muster von Signaturen bilden:
FLAT, RISING, BIG_WAVE, FALLING, SMALL_WAVES.
Jede dieser Konstanten ist ein Muster für einen bestimmten Charakter der Parameteränderung innerhalb der aktuellen Periode.
Wir müssen das Format der Signaturaufzeichnung entwickeln und diese Vorlagen erstellen. Dann liest der Algorithmus die aktuelle Signatur und vergleicht sie mit den Vorlagen, wobei er die engsten Übereinstimmungen (es kann keine absolute Übereinstimmung geben) zwischen der Art der aktuellen Änderung und einer der Vorlagen findet.
Die Vorteile dieses Ansatzes gegenüber der üblichen Verwendung spezifischer Werte liegen auf der Hand.
Die Verwendung von Signaturen ermöglicht es, Entscheidungen auf den aus dem Datensatz extrahierten Kontext zu stützen und nicht zu versuchen, diesen Kontext aus einzelnen Werten zu extrahieren.
P.S. Ich hoffe, Sie haben meinen Standpunkt diesmal verstanden.
Das ist eine seltsame Antwort, die Sie gegeben haben. Sie scheinen den Punkt überhaupt nicht verstanden zu haben. Ich zitiere sie noch einmal:
...
Die von mir vorgeschlagene Erweiterung des Bereichs besteht darin, Signaturen von Wertveränderungen innerhalb des aktuellen Zeitraums zu erhalten. Dies kann durch Aufzeichnen einer Kurve (nicht in einem Diagramm) auf der Grundlage der Daten aus den beiden Ringpuffern geschehen:
P.S. Ich hoffe, Sie haben mich dieses Mal verstanden.
Ich habe Sie auch beim ersten Mal sehr gut verstanden.
Was ist eine "Wertänderungssignatur"? Es ist ein Wert, der sich in der Dynamik ändert. Daher ist es ein Indikator. Es ist nicht notwendig, einen Ringpuffer zu diesem Zweck zu entwickeln, sondern es reicht aus, auf der Grundlage mehrerer dieser Ringindikatoren einen Algorithmus zu erstellen, um genau den "Charakter der Veränderung" zu berechnen, von dem Sie sprechen.

- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.
Neuer Artikel Die Rezepte MQL5 - Die Erstellung des Ringpuffers für eine schnelle Berechnung der Indikatoren im gleitenden Fenster :
Der Ringpuffer ist die einfachste und gleichzeitig die effekviste Weise, Daten für Berechnungen im gleitenden Fenster zu organisieren. Der Artikel beschreibt diesen Algorithmus und zeigt, wie er Berechnungen im gleitenden Fenster zu einem einfachen und effektiven Prozess macht.
Die graphische Abbildung des Indikators ist äquivalent zu dem gleichnamigen Standardindikator MovingAverage:
Abb. 1. Die Abbildung des einfachen, gleitenden Durchschnitts, der mit dem Ringpuffer berechnet wurde.
Autor: Vasiliy Sokolov