English Русский 中文 Español 日本語 Português
Wir betrachten die adaptive Trendfolgemethode in der Praxis

Wir betrachten die adaptive Trendfolgemethode in der Praxis

MetaTrader 5Beispiele | 7 November 2017, 06:35
1 516 0
Dmitriy Gizlyk
Dmitriy Gizlyk

Einleitung

Die in diesem Artikel vorgestellte Handelsstrategie wurde ursprünglich 2001-2002 von Vladimir Kravchuk in der Zeitschrift "Devisenspekulant" beschrieben. Das System basiert auf der Verwendung digitaler Filter und der Spektralschätzung diskreter Zeitreihen.

Ein Live-Chart von Kursveränderungen kann eine beliebige Form haben. In der Mathematik werden solche Funktionen als nicht analytisch bezeichnet. Aber aus dem bekannten Theorem von Fourier geht hervor, dass jede Funktion in einem finiten Zeitintervall als eine unendliche Summe von Sinusfunktionen dargestellt werden kann. D.h. alle Zeitsignale können durch Frequenzfunktionen dargestellt werden, die als deren Frequenzspektren bezeichnet werden.

Für nichtzufällige Signale wird zwischen den Darstellungen im Zeitraum und im Frequenzraum (d.h. die Berechnung des Frequenzspektrums) per Fourier-Transformation gewechselt. Zufallsprozesse werden durch spektrale Leistungsdichte dargestellt, die eine Fourier-Transformation nicht eines Zufallsprozesses, sondern seiner Autokorrelationsfunktion ist.

1. Theoretische Aspekte der Strategie

Es sei daran erinnert, dass das Filtern eine Änderung des Frequenzspektrums in der gewünschten Richtung ist. Eine solche Transformation kann Frequenzkomponenten in einem bestimmten Bereich stärken oder schwächen, eine konkrete Komponente unterdrücken oder ausschließen. Als digitaler Filter wird ein digitales System zur Umwandlung von Signalen bezeichnet, die nur in diskreten Zeitpunkten definiert werden.

Bei der Arbeit mit digitalen Filtern und diskreten Zeitreihen gibt es bestimmte wichtige Aspekte. 

Erstens, basieren die meisten populären technischen Tools (MA, RSI, Momentum, Stochastic usw.) auf der Änderung des Frequenzspektrums des Signals, d.h. sie sind digitale Filter. Der Verstärkungskoeffizient ihrer Übertragungsfunktion hängt von der Frequenz ab. Aber viele lassen diese Übertragungsfunktion unberücksichtigt. Deswegen wissen die meisten Nutzer nicht, in welcher Richtung sich das Frequenzspektrum des Signals ändert, das heißt, sie verstehen nicht die eigentliche Natur der Wirkung des Indikators auf das Signal. Dies erschwert die Einstellung des Indikators und die Interpretation seiner Signale.

Zweitens, sieht die Bewegung von Devisenkursen immer als ein diskretes Signal aus, dessen allgemeine Eigenschaften man bei der Entwicklung technischer Indikatoren berücksichtigen muss. So ist zum Beispiel das Spektrum eines diskreten Signals immer eine periodische Funktion. Wenn man diese Eigenschaft ignoriert, kann das eine unbehebbare Verzerrung der Input-Zeitreihe hervorrufen.

Drittens, sind spektrale Dichten von Preisbewegungen auf verschiedenen Märkten total unterschiedlich. Dabei hat der Nutzer keinen exakten Algorithmus, wie die Parameter der Indikatoren einzustellen sind. Stattdessen muss er zufällige Parameter auswählen und diese in der Praxis testen.

Häufig entsteht die Situation, dass ein bereits optimierter Indikator oder Expert Advisor, der sich gestern von bester Seite gezeigt hat, heute durchaus schlechte Ergebnisse liefert. Das ist mit der "Nicht-Stationarität" der Zeitreihen verbunden. In der Tat, wenn man zwei Schätzungen der spektralen Leistungsdichte vergleicht, die auf verschiedenen Zeitrahmen für einen Markt berechnet wurden, verschiebt sich die Amplitude von Spektralspitzen und ändert ihre Form. Dies kann man als das Auftreten des Doppler-Effekts interpretieren, wenn die Bewegung der Quelle einer harmonischen Welle hinsichtlich des Empfängers die Wellenlänge ändert. Dies beweist noch einmal das Vorhandensein einer Trendbewegung auf dem Markt.

Das Ziel der adaptiven Trendfolgemethode besteht darin, ein angemessenes Minimum an technischen Werkzeugen zu finden, mit welchem man einen Algorithmus für den Handel mit maximaler Profitabilität bei minimalem Risiko entwickeln kann. Dafür werden mehrere Schritte unternommen.

  • Es wird die spektrale Zusammensetzung von Preisschwankungen eines konkreten Marktes untersucht.
  • Nichtrekursive digitale Filter werden adaptiv eingestellt. Als Ergebnis dieses Verfahrens erhalten wir einen Satz bereits optimierter Impulsantworten.
  • Die Input-Zeitreihe wird gefiltert, und als Ergebnis wird ein Set von Indikatoren festgelegt, die im Artikel weiter beschrieben werden.
  • Es wird der Handelsalgorithmus entwickelt.
Die adaptive Methode kann auf jeden Markt angewandt werden. Man muss berücksichtigen, dass die Kapitalisierung und die Liquidität des ausgewählten Marktes die maximale Größe einer offenen Position bestimmen werden. 

1.1 Auswahl der Methode der Spektralanalyse

Die Entwicklung eines Handelssystems auf Basis der adaptiven Trendfolgemethode beginnt mit der Untersuchung des Spektrums der Preisbewegung eines konkreten Symbols. Es ist offensichtlich, dass von den Ergebnissen dieser Phase die endgültige Effektivität des ganzen Systems abhängt.

Es scheint, die Lösung ist zum Greifen nah: man muss eine spektrale oder harmonische Analyse durchführen. Aber welche Methode passt am besten? Heute sind zwei grundlegende Klassen der Methoden der Spektralanalyse bekannt: parametrische und nichtparametrische.

Parametrische Methoden der Spektralanalyse sind Methoden, in welchen ein bestimmtes Modell der spektralen Dichte definiert wird und seine Parameter basierend auf den Beobachtungsergebnissen des entsprechenden Prozesses innerhalb eines begrenzten Zeitraums geschätzt werden. Dabei kann das ursprüngliche Modell ganz unterschiedlich aussehen.

Unter anderem kann die spektrale Dichte einer Zeitreihe, realisiert als eine rationalen Funktion, als Ausgangsmodell dienen. Man kann zwischen einem autoregressiven Modell, einem Modell des gleitenden Durchschnitts und einem Modell des autoregressiven gleitenden Durchschnitts unterscheiden. Bei der Schätzung der Parameter dieser Modelle werden verschiedene methodologische Ansätze verwendet.

Für die Lösung dieser Aufgabe können wir das Variationsprinzip und das entsprechende Funktional für die Einschätzung der Qualität verwenden. Die Rolle der zu schätzenden Parameter spielen hier die Lagrange-Multiplikatoren. Dieser Ansatz wird bei der Schätzung der spektralen Dichte anhand der Maximum-Entropie-Methode verwendet, die die Maximierung die Entropie des Prozesses nach einzelnen bekannten Werten der Korrelationsfunktion erfordert.

Nichtparametrische Methoden der Spektralanalyse haben im Vergleich zu den parametrischen keine vorgegebenen Modelle. Besonders populär ist die Methode, in welcher am Anfang die Periodizität des Prozesses (d.h. das Quadrat des Betrags der Fourier-Transformation der vorhandenen Implementierung) ermittelt wird. Danach beschränkt sich die Aufgabe auf die Auswahl eines passenden Fensters, das bestimmte Bedingungen erfüllt.

Darüber hinaus wird die Blackman-Tukey-Methode breit verwendet, in welcher die Fourier-Transformation der gewichteten Schätzung der Korrelationsfolge für die zu untersuchenden Zeitreihe ermittelt wird.

Ein weiterer Ansatz besteht darin, das Problem der Schätzung der spektralen Dichte einer Zeitreihe auf die Lösung einer fundamentalen integralen Gleichung zu beschränken, die die Fourier-Transformation der zu untersuchenden Zeitreihe durch einen Zufallsprozess mit einem orthogonalen Inkrement beschreibt.

Nach der Meinung des Autors des Handelssystems ist es unmöglich, die spektrale Leistungsdichte der Schwankungen von Devisenkursen qualitativ einzuschätzen, indem man klassische nichtparametrische Methoden der spektralen Schätzung basierend auf der Berechnung der diskreten Fourier-Transformation von Zeitreihen verwendet. Die einzige Lösung ist, parametrische Methoden der Spektralanalyse zu verwenden, die fähig sind, eine stichhaltige Schätzung der spektralen Leistungsdichte für eine kurze diskrete Zeitstichprobe zu erhalten, wo der Prozess entweder stationär ist, oder stationär gemacht werden kann, indem man den linearen Trend entfernt. Unter allen parametrischen Methoden der Spektralschätzung ist die Maximum-Entropie-Methode besonders interessant.

1.2. Die verwendeten Werkzeuge der technischen Analyse

Die adaptive Trendlinie stellt das wesentliche Merkmal der Strategie dar. Ihre Richtung zeigt die Richtung des aktuellen Trends.

Eine adaptive Trendlinie ist eine tieffrequente Komponente der Input-Zeitreihe. Sie wird durch einen Tiefpassfilter erhalten. Je tiefer die Grenzfrequenz fc des Tiefpassfilters ist, desto stärker wird die Trendlinie geglättet.

Zwischen den Punkten der adaptiven Trendlinie gibt es eine innere Verbindung, deren Stärke indirekt proportional dem Abstand zwischen ihnen gleich ist. Keine Verbindung ist nur zwischen den Werten der Punkte vorhanden, der Abstand zwischen denen gleich oder größer als das Nyquist-Intervall TN=1/(2 fc) ist. Daraus folgt: Je tiefer die Grenzfrequenz des Filters ist, desto stärker wird diese Verbindung, und der Zeitpunkt der Umkehr wird verschoben.

Für die Ermittlung eines Trends verwendet das Handelssystem zwei adaptive Trendlinien mit verschiedenen Perioden.

FATL — Fast Adaptive Trend Line. Für das Zeichnen wird der Tiefpassfilter 1 benötigt. Er unterdrückt hochfrequentes Rauschen und Marktzyklen mit einer sehr kurzen Schwingungsperiode.

SATL — Slow Adaptive Trend Line. Für das Zeichnen wird der Tiefpassfilter 2 benötigt. Im Vergleich zum Tiefpassfilter 1, durchlässt er Marktzyklen mit einer längeren Schwingungsperiode.

Die Parameter der oben beschriebenen Filter (die Grenzfrequenz fc und die Dämpfung σ im Sperrbereich) werden basierend auf den Schätzungen des Spektrums des für uns relevanten Symbols berechnet. Der Tiefpassfilter 1 und der Tiefpassfilter 2 weisen eine Dämpfung von mindestens 40 Db im Sperrbereich auf. Die Verwendung der Filter beeinflusst auf keine Weise die Amplitude und die Phase des eingehenden Signals im Durchlassbereich. Diese Eigenschaft der digitalen Filter sichert ein effektives Unterdrücken des Rauschens, und im Vergleich zu einfachen MA erzeugen sie weniger falsche Signale.

Aus der mathematischen Sicht ist FATL(k) der erwartete Kurs Close(k), wobei k die Nummer des Handelstages ist.

RFTL Reference Fast Trend Line und RSTL (Reference Slow Trend Line) sind die schnelle und die langsame Referenzlinie des Trends. Sie stellen die Werte dar, die die digitalen Filter TPF-1 und TPF-2 als Reaktion auf ein eingehendes Signal ausgegeben haben, und die mit einer Verzögerung, die gleich dem entsprechenden Nyquist-Intervall ist, erfasst wurden.

FTLM (Fast Trend Line Momentum) und STLM (Slow Trend Line Momentum) demonstrieren die Verschiebungen von FATL und SATL. Sie werden analog zum Indikator Momentum berechnet, statt Schlusskurse werden die durch das Filtern geglätteten Trendlinien verwendet. Im Endeffekt werden die Linien glatter und regelmäßiger, als bei dem uns vertrauten Momentum.

Die Linien FTLM und STLM werden nach den Regeln der diskreten Mathematik berechnet. Das ist die Differenz zwischen zwei benachbarten unabhängigen Punkten, die vom Band des Prozesses begrenzt sind. Bei einer gewöhnlichen Berechnung von Momentum wird diese Bedingung häufig vernachlässigt, was zu unbehebbaren Verzerrungen im Spektrum des eingehenden Signals führt.

RBCI — Range Bound Channel Index. Er wird mithilfe des Bandfilters berechnet, zu dessen Aufgaben gehören:

  • Entfernen eines tieffrequenten Trends, der aus tieffrequenten spektralen Komponenten mit den Perioden, die größer als T2 = 1/fc2 sind, gebildet wurde;
  • Entfernen eines hochfrequenten Rauschens, das aus hochfrequenten spektralen Komponenten mit den Perioden, die kleiner als T1 = 1/fc1 sind, gebildet wurde.

Die Perioden T1 und T2 werden so ausgewählt, dass die Bedingung T2 > T1 erfüllt ist. Dabei muss die Grenzfrequenz fc1 und fc2 so sein, dass alle herrschenden Marktzyklen berücksichtigt werden.

Einfach ausgedrückt, RBCI(k) = FATL(k) - SATL(k). Tatsächlich, wenn sich RBCI an seine lokale Extrema nähert, nähern sich die Preise an die obere oder (je nach dem, ob es sich um ein Hoch oder Tief handelt) untere Grenze des Handelsbereichs.

PCCI — Perfect Commodity Channel Index. Die Berechnungsformel: PCCI(k) = close(k) – FATL(k).

Die Berechnungsmethode ist gleich der Berechnung des Index des Warenkanals CCI. CCI ist eine normierte Differenz zwischen dem aktuellen Preis und seinem gleitenden Durchschnitt, und PCCI — die Differenz zwischen dem Tagesschlusskurs Tages und dem erwarteten Ergebnis (das, wie wir bereits oben festgestellt haben, basierend auf dem FATL-Wert berechnet wird).

Das heißt, PCCI ist eine hochfrequente Komponente von Kursschwankungen, normiert durch ihre Standardabweichung.

Beispiel für IndikatorenBeispiel für Indikatoren


1.3. Interpretationregeln für Signale des Indikators.

Definieren wir die Hauptprinzipien des Handelssystems.

  • Es handelt sich um ein Trend-System, Handel nach Trend. Der Trend wird mithilfe von SATL ermittelt.
  • Die Einstiegspunkte werden entsprechend den dynamischen Eigenschaften des "schnellen" und des "langsamen" Trends von FTLM und STLM ermittelt.
  • Es wird der aktuelle Zustand des Marktes berücksichtigt (ob der Markt neutral, überkauft oder überverkaut ist, lokale Extrema), der nach dem RBCI-Index bestimmt wird.
  • Die Richtung des Einstiegs wird nach den Trendindikatoren ermittelt. Oszillatoren können nur im Fall einer Stagnation verwendet werden.
  • Es ist obligatorisch, Stop-Orders (nach den Indexen RBCI, PCCI und nach der Volatilität des Marktes) zu setzen.

Die oben angeführten Werkzeuge sind nach folgenden Regeln zu interpretieren.

  • Wenn die SATL-Linie nach oben gerichtet ist, herrscht auf dem Markt ein aufsteigender Trend, wenn nach unten - dann ein absteigender Trend. Das Auftreten lokaler Extrema weist auf eine Umkehr des Trends hin. Der Schnittpunkt mit RSTL ist ein Merkmal dafür, dass sich der Trend komplett umgekehrt hat. In diesem Fall ändert STML das Vorzeichen.
  • Wenn die SATL Linie horizontal oder fast horizontal ist, ist das das Merkmal einer Stagnation auf dem Makrt.
  • STLM ist positiv bei einem bullischen Trend und negativ bei einem bärischen Trend. Er wird als Frühindikator betrachtet. Seine lokalen Extrema kündigen das Auftreten der entsprechenden SATL-Extrema an. Der absolute Wert von STLM ist direkt proportional der Trendstärke. Wenn sich STLM und SATL in einer Richtung bewegen, heißt das, dass sich der Trend verstärkt. Die Bidirektionalität weist auf eine Abschwächung des Trends hin. Die horizontale STLM-Linie weist auf einen sich komplett herausgebildeten Trend.
  • Wenn die "schnelle" und die "langsame" Trendlinien (FATL und SATL) eine Richtung haben, geht es um einen starken Trend. Andernfalls ist der Markt entweder konsolidiert, oder er befindet sich in der Korrekturphase. 
  • Wenn die FATL- und SATL- Linien begonnen haben, sich in eine Richtung zu bewegen, heißt das, dass sich der Trend umgekehrt hat. Wenn die Richtung nach der Phase der Bidirektionalität wieder gleich ist, heißt das, dass die Korrektur auf dem Markt abgeschlossen ist, und die Kurse sich wieder in der Richtung von SATL bewegen.

Formulieren wir die grundlegenden Handelssignale anhand der angeführten Regeln.

  1. Am Anfang eines langfristigen Trends erscheint ein zuverlässiges Umkehrsignal: STLM sinkt und weist auf die Konvergenz der adaptiven und der langsamen Trendlinien (SATL und RSTL) hin. Während sich ein Signal bildet, steigt die Volatilität der Preise. Das ist ein charakteristisches Merkmal einer Trendwende. Deswegen ist es wichtig, bei der Auswahl des Einstiegpunktes für einen Abschluss PCCI zu berücksichtigen. Beim bärischen Signal verkaufen wir, wenn der PCCI Oszillator zum Zeitpunkt des Schließens der letzten Kerze oberhalb des Levels -100 liegt. Wenn der PCCI-Wert unterhalb des Levels -100 liegt, öffnen wir nicht einen Abschluss und warten, bis der Oszillator diesen Level überschreitet.

  2. Das nächste Signal weist auf die Fortsetzung des sich herausgebildeten und verstärkten Trends nach einer kurzen Korrektur hin. In solchen Fällen ist die Volatilität in der Regel schwächer, als bei einer Umkehr des Trends. Deswegen sind hier die Bedingungen für die Formation des Signals strikter, und das Signal selbst ist zuverlässiger.
    Handeln, wenn sich die Indikatoren FATL, FTLM und RBCI synchron bewegen. Falsche Signale werden durch den STLM Indikator gefiltert (sein absoluter Wert entweder steigt, oder bleibt unverändert). Wenn STLM sinkt, weist das auf eine Konvergenz von SATL und RSTL hin. Gleichzeitig wird beim Eingehen eines bärischen Signals vom RBCI überprüft, ob der Markt überverkauft ist. Der Einstiegspreis wird so ausgewählt, dass er gleich oder besser als der Open-Kurs des nächsten Balkens nach dem Eingehen des Signals ist.

  3. Dieses Signal basiert auf der Summe aktiver Zyklen im angegebenen Frequenzband, das durch den RBCI-Index festgelegt wird. Die Richtung der STLM-Linie und die Konvergenz/Divergenz von SATL und RSTL werden nicht berücksichtigt. Wichtig ist nur, ob der STLM-Wert positiv oder negativ ist, denn er weist auf die Richtung des Haupttrends auf dem Markt hin. Ein zusätzlicher Filter ist die Richtung und das Verhalten der FATL-Linie.
    Das Signal wird gebildet, wenn der zusammengesetzte Wellenzyklus bei einem neutralen oder absteigenden langfristigen Trend das lokale Maximum im stark überkauften Bereich erreicht. Bei einer Stagnation wird das Potential der Bewegung, verursacht durch Marktzyklen, höher als das Potential der Bewegung, verursacht durch die Volatilität, sein. Wenn der Trend sich gebildet hat, wird das Potential der Bewegung auf Basis von Marktzyklen zum Potential eines langfristigen Trends addiert.
    Der Eröffnungskurs des Abschlusses wird auch so ausgewählt, dass er gleich ober besser als Open des nächsten Balkens nach dem Eingehen des Signals ist.

  4. Die Grundlage des Signals bilden zwei Divergenzen: die zwischen der Richtung der Bewegung von RBCI und der FATL-Linie und die zwischen den Indexen RBCI und FTLM. Wenn sich während einer bestimmten FATL-Periode die Indexen RBCI und FTLM gegenläufig bewegen, wird Stand-by aktiviert. Das bärische Signal stellt ein lokales Minimum von FTLM dar, vorausgesetzt dass FATL und RBCI ihre Richtung nicht ändern. Auf den Charts sieht das wie ein "Nicken" von FTLM in die Richtung der Bewegung von FATL aus.
    Meistens sehen wir dieses Signal neben dem Endpunkt des "schnellen" Abwärtstrends (FTLM-Wert gegen "0"). Das System bildet ein relativ genaues Signal für eine kurze Trendbewegung.
    Das ist ein Signal, das der Umkehr des Trends vorausgeht.
    Der Einstiegspreis wird so ausgewählt, dass er gleich oder besser als der Eröffnungskurs der nächsten Kerze nach dem Eingehen des Signals ist.

  5. Das Signal wird während eines langen Trends gebildet. Die Indexe RBCI und PCCI erreichen die Werte des überkauften Marktes (für einen absteigenden Trend) gleichzeitig. Meistens bilden sich solche Signale in der letzten Trendphase, wenn Kurse plötzlich in die Gegenrichtung springen und dann wieder in die Richtung des immer noch starken Haupttrends "knicken".
    Der Einstiegspreis wird so ausgewählt, dass er gleich oder besser als der Eröffnugnskurs der nächsten Kerze nach dem Eingehen des Signals ist.

  6. Beim Bilden eines langfristigen bärischen Trends (SATL sinkt, aber der STLM-Wert ist noch positiv) erreicht der PCCI-Index die Werte über 100 (überkaufter Bereich). Das Umkehrsignal basiert auf der Verwendung einer hohen Marktvolatilität beim Bilden des Trends.
    Der Einstiegspreis wird so ausgewählt, dass er gleich oder besser als der Eröffnungskurs der nächsten Kerze nach dem Eingehen des Signals ist.

  7. Ein starkes Umkehrsignal gibt es, nachdem die erste technische Korrektur nach oben abgeschlossen wurde, nachdem die SATL-Linie die FATL-Linie von oben nach unten durchbricht. Danach wird verkauft. Auf den Abschluss der technischen Korrektur weist das lokale Maximum von FATL hin.
    Der Verkaufspreis ist höher oder gleich dem Eröffnungskurs der Kerze, die dem Eingehen des Signals folgt.

  8. Und schließlich wird noch ein Signal erzeugt, wenn sich die "schnelle" und die "langsame" adaptive Linien FATL und SATL sowie FATL und RFTL gleichzeitig kreuzen (Ausbruch nach unten — verkaufen, Ausbruch nach oben - kaufen). Dieses Signal markiert den Moment eines abrupten Bruchs des alten und bereits schwachen Trends. Der Verkaufspreis ist höher oder gleich der Kerze, die dem Eingehen des Signals folgt.

2. Erstellen von Tiefpassfiltern

Nachdem wir die grundlegenden Aspekte der Strategie dargestellt haben, kommen wir zum praktischen Teil der Arbeit. Natürlich beginnen wir die Arbeit mit dem Erstellen eines Tiefpassfilters, denn gerade solche Filter bilden die Grundlage für die Strategie.

Um einen Tiefpassfilter zu erstellen, müssen wir zuerst seine Hauptparameter, die Grenzfrequenz und die Dämpfung, definieren. Da der Autor der Strategie angibt, dass der Filter eine Dämpfung von mindestens 40 Db im Sperrbereich besitzen muss, müssen wir eine Spektralanalyse von Preisdaten des Symbols für das Ermitteln der Frequenzgrenze durchführen.

Wie bereits oben erwähnt, verwendete der Autor bei der Schätzung der spektralen Leistungsdicthe die Maximum-Entropie-Methode. Diese Methode gehört zu den parametrischen und wird nach einem mathematischen Modell ausgeführt. Das mathematische Modell erstellen wir mithilfe der Methode der Autoregression.

2.1. Analyse der spektralen Leistungsdichte.

Für die Schätzung der spektralen Dichte erstellen wir die Klasse CSpertrum (der komplette Code ist im Anhang zu finden). Während der Initialisierung der Klasse werden der Symbolnamen, die Timeframe und die Anzahl der Balken für die Analyse übergeben.

class CSpectrum
  {
private:
   int               ci_HistoryBars;               //Bars for analysis
   string            cs_Symbol;                    //Symbol
   ENUM_TIMEFRAMES   ce_Timeframe;                 //Timeframe
   double            cda_AR[];                     //Autoregression coefficients
   int               ci_NumberCoeffs;              //Number of coefficients
  
public:
                     CSpectrum(int bars=2880, string symbol=NULL, ENUM_TIMEFRAMES period=PERIOD_CURRENT);
                    ~CSpectrum();
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
CSpectrum::CSpectrum(int bars=2880, string symbol=NULL, ENUM_TIMEFRAMES period=PERIOD_CURRENT)
  {
   ci_HistoryBars =  bars;
   cs_Symbol      =  (symbol==NULL ? _Symbol : symbol);
   ce_Timeframe   =  period;
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
CSpectrum::~CSpectrum()
  {
  }

Die Funktion der Autoregression und der spektralen Leistungsdichte wird nach der von Victor vorgeschlagenen Methode berechnet. Denjenigen, die sich den Algorithmus detailliert anschauen wollen, empfehle ich, diesen Artikel zu lesen. Das Ergebnis der Funktion der Spektralanalyse der Fläche ist ein Array von Daten, der als eine Grafik dargestellt werden kann.

Die spektrale Leistungsdichte von EURUSD

Die Ausbrüche im Chart zeigen die Erhöhung der Signalstärke bei einer bestimmten Frequenz. Gerade diese Ausbrüche müssen wird finden, um die Frequenzgänge unserer Filter zu ermitteln. Dafür fügen wir der Klasse CSpecrum die öffentliche Funktion GetPeriods hinzu, die die Perioden für FATL und SATL nach Aufruf zurückgibt.

Innerhalb der Funktion werden die Ausbrüche als Fraktale definiert. Für die Periode des SATL Filters definieren wir den allerersten Ausbruch, der Impulse mit der niedrigsten Frequenz anzeigt. Für FATL finden wir das Impuls mit der höchsten Frequenz und einer Leistung von mehr als -40 dB, indem wir Rauschimpulse mit einer kleinen Amplitude und einer hohen Frequenz eliminieren. Wenn die Funktion die Perioden für die Filter nicht findet, gibt sie false zurück.

bool CSpectrum::GetPeriods(int &FAT,int &SAT)
  {
   if(!Spectrum())
      return false;
   FAT=SAT=0;
   int total=ArraySize(cad_Spectr)-1;
   for(int i=1;(i<total);i++)
     {
      int temp=2*(total+1)/i;
      if(cad_Spectr[i]==0 || temp>(int)ci_HistoryBars/4)
         continue;
      if((cad_Spectr[i]-cad_Spectr[i+1])>=0 && (cad_Spectr[i]-cad_Spectr[i-1])>0)
        {
         if(SAT==0)
            SAT=temp;
         else
           {
            if(cad_Spectr[i]<-40)
              {
               if(FAT==0)
                  FAT=temp;
               break;
              }
            if(temp>=20)
               FAT=temp;
           }
        }
     }
   if(SAT==0 || FAT==0)
      return false;
   return true;
  }

2.2. Berechnen der Koeffizienten des Tiefpassfilters.

Nachdem wir die Frequenzen der Filter festgelegt haben, ist es an der Zeit, unsere Tiefpassfilter zu erstellen. Die allgemeine Formel eines digitalen Filters sieht wie folgt aus:


Wobei y — Ausgabedaten des Filters; x — Array der Quelldaten; hk — Impulsantworten; N — Anzahl der Impulsantworten.

Als Ausgangswerte nehmen wir die Kursdaten des Symbols, die Anzahl der Impulsantworten setzen wir gleich dem Nyquist-Intervall. Die Impulsantworten müssen wir noch berechnen. Die idealen Impulsantworten für einen Tiefpassfilter kann man nach der folgenden Formel berechnen:


Wobei fc und wc — Grenzfrequenz.

Leider ist aber unsere Welt weit vom Ideal entfernt. Deswegen brauchen wir eine "reale" Impulsantwort. Um diese Impulsantwort zu berechnen, brauchen wir die Gewichtsfunktion w(n). Es gibt mehrere Typen von Gewichtsfunktionen. Ich verwende die Blackman-Funktion, die wie folgt aussieht:


Wobei N die Anzahl der Elemente des Filters ist.

Um eine echte Impulsantworte zu erhalten, muss man die ideale Impulsantwort mit der entsprechenden Gewichtsfunktion multiplizieren.


Wir haben die Berechnungsformeln definiert, erstellen wir nun die CFLF Klasse, in welcher wir Impulsantworten berechnen und Eingabedaten filtern werden. Für die Berechnung der Koeffizienten der Impulsantwort erstellen wir eine öffentliche Funktion CalcImpulses, welcher wir die Periode des Filters übergeben. Weiter wiederholt der Algorithmus der Funktion die oben angeführten Formeln. Danach normalisieren wir die Impulsantworten, indem wir deren Summe auf "1" bringen.

bool CFLF::CalcImpulses(int period)
  {
   if(period<20)
      return false;
   int N=(int)(period/2);
   if(ArraySize(cda_H)!=N)
      if(ArrayResize(cda_H,N)<N)
         return false;
   double H_id[],W[];
   if(ArrayResize(H_id,N)<N || ArrayResize(W,N)<N)
      return false;
  
   cd_Fs=1/(double)period;
   for (int i=0;i<N;i++)
     {
      if (i==0)
         H_id[i] = 2*M_PI*cd_Fs;
      else
         H_id[i] = MathSin(2*M_PI*cd_Fs*i )/(M_PI*i);
      
      W[i] = 0.42 - 0.5 * MathCos((2*M_PI*i) /( N-1)) + 0.08 * MathCos((4*M_PI*i) /( N-1));
      cda_H[i] = H_id[i] * W[i];
     }
      
   //Normalization
   double SUM=MathSum(cda_H);
   if(SUM==QNaN || SUM==0)
      return false;
   for (int i=0; i<N; i++)
      cda_H[i]/=SUM; //summ of coefficients equal 1 
   //---
   return true;
  }

2.3. Berechnen der Indikatoren FATL, SATL, RTFL und STL.

Nachdem wir die Impulsantworten erhalten haben, können wir mit der Berechnung der Werte der verwendeten Indikatoren beginnen. Es ist praktisch, die Werte der Indikatoren FATL, SATL, RFTL und RSTL direkt aus der Klasse des Filters zu erhalten.

Da wir verschiedene Instanzen der Klasse für den schnellen und langsamen Filter verwenden werden, reicht es uns, die Funktionen AdaptiveTrendLine und ReferenceTrendLine in der Klasse zu erstellen. Den Funktionen werden das verwendete Symbol, die Timeframe und die Verschiebung hinsichtlich der aktuellen Kerze übergeben. Die Funktionen werden einen gefilterten Wert zurückgeben.

Es ist zu beachten, dass die Funktion ReferenceTrendLine im Grunde genommen gleich der Funktion AdaptiveTrendLine ist. Der Unterschied besteht nur darin, dass ReferenceTrendLine mit einer Verschiebung um die Nyquist-Periode berechnet wird. Daher berechnen wir die Nyquist-Periode in ReferenceTrendLine und rufen die Funktion AdaptiveTrendLine auf, dabei geben wir die gewünschte Verschiebung hinsichtlich des aktuellen Balkens an.

double CFLF::AdaptiveTrendLine(string symbol=NULL,ENUM_TIMEFRAMES timeframe=0,int shift=1)
  {
   string symb=(symbol==NULL ? _Symbol : symbol);
   int bars=ArraySize(cda_H);
   double values[];
   if(CopyClose(symb,timeframe,shift,bars,values)<=0)
      return QNaN;
   double mean=MathMean(values);
   double result=0;
   for(int i=0;i<bars;i++)
      result+=cda_H[i]*(values[bars-i-1]-mean);
   result+=mean;
   return result;
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double CFLF::ReferenceTrendLine(string symbol=NULL,ENUM_TIMEFRAMES timeframe=0,int shift=1)
  {
   shift+=(int)(1/(2*cd_Fs));
   return AdaptiveTrendLine(symbol,timeframe,shift);
  }

Die anderen Indikatoren sind von den erhaltenen Werten abgeleitet und werden unten berechnet.

3. Erstellen eines Moduls von Handelssignalen für den MQL5 Wizard

Ich habe mich entschieden, auf die übliche Programmierweise eines Experten zu verzichten, und Sie an den MQL5 Wizard in MetaTrader 5 zu erinnern. Diese hilfreiche Funktion ist eine Art von Konstruktor, in welchem der Expert Advisor aus vorher vorbereiteten Modulen zusammengesetzt wird. Dies erlaubt es, ohne viel Mühe einen neuen Expert Advisor zu erstellen, indem man neue Funktionen hinzufügt und ungenutzte löscht. Deswegen schlage ich vor, den Entscheidungsalgorithmus unseres Expert Advisors in so ein Modul einzubetten. Diese Methode wurde bereits mehrmals in Artikeln beschrieben [4], [5]. Deswegen gehe ich in diesem Artikel nur auf die Punkte ein, die unsere Strategie betreffen.

Beginnen wir mit dem Erstellen der Signalklasse CSignalATCF auf Basis der Klasse CExpertSignal und fügen wir ihr die vorher erstellten Klassen hinzu.

class CSignalATCF : public CExpertSignal
  {
private:
   CSpectrum         *Spectrum;     //Class for spectr calculation
   CFLF              *FFLF;         //Class of fast low frequency filter
   CFLF              *SFLF;         //Class of slow low frequency filter

public:                      CSignalATCF();                     ~CSignalATCF();   };

Bei der Initialisierung müssen wir den Namen des Symbols, die Timeframe, Anzahl der Balken in der Historie (für die Analyse der spektralen Leistungsdichte) und die Anzahl der Balken der Mittelung (wird bei der Berechnung der Indikatoren RBCI und PCCI verwendet) dem Modul übergeben. Darüber hinaus muss man angeben, welche Muster für die Eröffnung von Positionen zu verwenden sind. Die Beschreibung des Moduls wird wie folgt aussehen:

// wizard description start
//+---------------------------------------------------------------------------+
//| Description of the class                                                  |
//| Title=Signals degign by DNG for Adaptive Trend & Cycles Following Method  |
//| Type=SignalAdvanced                                                       |
//| Name=Signals Adaptive Trend & Cycles Following Method                     |
//| ShortName=ATCF                                                            |
//| Class=CSignalATCF                                                         |
//| Page=https://www.mql5.com/ru/articles/3456                                |
//| Parameter=TimeFrame,ENUM_TIMEFRAMES,PERIOD_H4,Timeframe                   |
//| Parameter=HistoryBars,uint,1560,Bars in history to analysis               |
//| Parameter=AveragePeriod,uint,500,Period for RBCI and PCCI                 |
//| Parameter=Pattern1,bool,true,Use pattern 1                                |
//| Parameter=Pattern2,bool,true,Use pattern 2                                |
//| Parameter=Pattern3,bool,true,Use pattern 3                                |
//| Parameter=Pattern4,bool,true,Use pattern 4                                |
//| Parameter=Pattern5,bool,true,Use pattern 5                                |
//| Parameter=Pattern6,bool,true,Use pattern 6                                |
//| Parameter=Pattern7,bool,true,Use pattern 7                                |
//| Parameter=Pattern8,bool,true,Use pattern 8                                |
//+---------------------------------------------------------------------------+
// wizard description end

Deklarieren wir alle benötigten Variablen und Funktionen:

class CSignalATCF : public CExpertSignal
  {
private:
   ENUM_TIMEFRAMES   ce_Timeframe;     //Timeframe
   uint              ci_HistoryBars;   //Bars in history to analysis
   uint              ci_AveragePeriod; //Period for RBCI and PCCI
   CSpectrum         *Spectrum;        //Class for spectr calculation
   CFLF              *FFLF;            //Class of fast low frequency filter
   CFLF              *SFLF;            //Class of slow low frequency filter
   //--- Indicators data
   double             FATL, FATL1, FATL2;
   double             SATL, SATL1;
   double             RFTL, RFTL1, RFTL2;
   double             RSTL, RSTL1;
   double             FTLM, FTLM1, FTLM2;
   double             STLM, STLM1;
   double             RBCI, RBCI1, RBCI2;
   double             PCCI, PCCI1, PCCI2;
   //--- Patterns flags
   bool               cb_UsePattern1;
   bool               cb_UsePattern2;
   bool               cb_UsePattern3;
   bool               cb_UsePattern4;
   bool               cb_UsePattern5;
   bool               cb_UsePattern6;
   bool               cb_UsePattern7;
   bool               cb_UsePattern8;
   //---
   datetime           cdt_LastSpectrCalc;
   datetime           cdt_LastCalcIndicators;
   bool               cb_fast_calced;
   bool               cb_slow_calced;
   
   bool              CalculateIndicators(void);
       
public:
                     CSignalATCF();
                    ~CSignalATCF();
   //---
   void              TimeFrame(ENUM_TIMEFRAMES value);
   void              HistoryBars(uint value);
   void              AveragePeriod(uint value);
   void              Pattern1(bool value)                {  cb_UsePattern1=value;   }
   void              Pattern2(bool value)                {  cb_UsePattern2=value;   }
   void              Pattern3(bool value)                {  cb_UsePattern3=value;   }
   void              Pattern4(bool value)                {  cb_UsePattern4=value;   }
   void              Pattern5(bool value)                {  cb_UsePattern5=value;   }
   void              Pattern6(bool value)                {  cb_UsePattern6=value;   }
   void              Pattern7(bool value)                {  cb_UsePattern7=value;   }
   void              Pattern8(bool value)                {  cb_UsePattern8=value;   }
   //--- method of verification of settings
   virtual bool      ValidationSettings(void);
   //--- method of creating the indicator and timeseries
   virtual bool      InitIndicators(CIndicators *indicators);
   //--- methods of checking if the market models are formed
   virtual int       LongCondition(void);
   virtual int       ShortCondition(void);
  };

Erstellen wir eine Funktion für die Berechnung der Indikatorenwerte:

bool CSignalATCF::CalculateIndicators(void)
  {
   //--- Check time of last calculation
   datetime current=(datetime)SeriesInfoInteger(m_symbol.Name(),ce_Timeframe,SERIES_LASTBAR_DATE);
   if(current==cdt_LastCalcIndicators)
      return true;                  // Exit if data alredy calculated on this bar
   //--- Check fo recalc spectrum
   MqlDateTime Current;
   TimeToStruct(current,Current);
   Current.hour=0;
   Current.min=0;
   Current.sec=0;
   datetime start_day=StructToTime(Current);
   
   if(!cb_fast_calced || !cb_slow_calced || (!PositionSelect(m_symbol.Name()) && start_day>cdt_LastSpectrCalc))
     {
      if(CheckPointer(Spectrum)==POINTER_INVALID)
        {
         Spectrum=new CSpectrum(ci_HistoryBars,m_symbol.Name(),ce_Timeframe);
         if(CheckPointer(Spectrum)==POINTER_INVALID)
           {
            cb_fast_calced=false;
            cb_slow_calced=false;
            return false;
           }
        }
      
      int fast,slow;
      if(Spectrum.GetPeriods(fast,slow))
        {
         cdt_LastSpectrCalc=(datetime)SeriesInfoInteger(m_symbol.Name(),ce_Timeframe,SERIES_LASTBAR_DATE);
         if(CheckPointer(FFLF)==POINTER_INVALID)
           {
            FFLF=new CFLF();
            if(CheckPointer(FFLF)==POINTER_INVALID)
               return false;
           }
         cb_fast_calced=FFLF.CalcImpulses(fast);
         if(CheckPointer(SFLF)==POINTER_INVALID)
           {
            SFLF=new CFLF();
            if(CheckPointer(SFLF)==POINTER_INVALID)
               return false;
           }
         cb_slow_calced=SFLF.CalcImpulses(slow);
        }
     }
   if(!cb_fast_calced || !cb_slow_calced)
      return false;                       // Exit on some error
   
   //--- Calculate indicators data
   int shift=StartIndex();
   double rbci[],pcci[],close[];
   if(ArrayResize(rbci,ci_AveragePeriod)<(int)ci_AveragePeriod || ArrayResize(pcci,ci_AveragePeriod)<(int)ci_AveragePeriod ||
      m_close.GetData(shift,ci_AveragePeriod,close)<(int)ci_AveragePeriod)
     {
      return false;
     }
   for(uint i=0;i<ci_AveragePeriod;i++)
     {
      double fatl=FFLF.AdaptiveTrendLine(m_symbol.Name(),ce_Timeframe,shift+i);
      double satl=SFLF.AdaptiveTrendLine(m_symbol.Name(),ce_Timeframe,shift+i);
      switch(i)
        {
         case 0:
            FATL=fatl;
            SATL=satl;
            break;
         case 1:
            FATL1=fatl;
            SATL1=satl;
            break;
         case 2:
            FATL2=fatl;
            break;
        }
      rbci[i]=fatl-satl;
      pcci[i]=close[i]-fatl;
     }
   RFTL=FFLF.ReferenceTrendLine(m_symbol.Name(),ce_Timeframe,shift);
   RSTL=SFLF.ReferenceTrendLine(m_symbol.Name(),ce_Timeframe,shift);
   RFTL1=FFLF.ReferenceTrendLine(m_symbol.Name(),ce_Timeframe,shift+1);
   RSTL1=SFLF.ReferenceTrendLine(m_symbol.Name(),ce_Timeframe,shift+1);
   RFTL2=FFLF.ReferenceTrendLine(m_symbol.Name(),ce_Timeframe,shift+2);
   FTLM=FATL-RFTL;
   STLM=SATL-RSTL;
   FTLM1=FATL1-RFTL1;
   STLM1=SATL1-RSTL1;
   FTLM2=FATL2-RFTL2;
   double dev=MathStandardDeviation(rbci);
   if(dev==0 || dev==QNaN)
      return false;
   RBCI=rbci[0]/dev;
   RBCI1=rbci[1]/dev;
   RBCI2=rbci[2]/dev;
   dev=MathAverageDeviation(pcci);
   if(dev==0 || dev==QNaN)
      return false;
   PCCI=pcci[0]/(dev*0.015);
   PCCI1=pcci[1]/(dev*0.015);
   PCCI2=pcci[2]/(dev*0.015);
   cdt_LastCalcIndicators=current;
  //---
   return true;
  }

Verschlüsseln wir die Muster für das Öffnen und Schließen von Positionen, und geben wir die entsprechenden Gewichte an (40 — für das Schließen und 80 — für das Öffnen). Unten ist die Funktion für das Öffnen von Long-Positionen angeführt. Die Funktion für Short-Positionen sieht ähnlich aus.

int CSignalATCF::LongCondition(void)
  {
   if(!CalculateIndicators() || m_open.GetData(1)>m_close.GetData(1))
      return 0;
   int result=0;
   //--- Close
   if(m_high.GetData(2)<m_close.GetData(1) || (STLM1<=0 && STLM>0) || (PCCI1<PCCI && PCCI1<=PCCI2) || (RBCI>RBCI1 && RBCI1>=RBCI2 && RBCI1<-1) || (RBCI1<=0 && RBCI>0))
      result=40;
   //--- Pattern 1
   if(cb_UsePattern1 && FTLM>0 && STLM>STLM1 && PCCI<100)
      result=80;
   else
   //--- Pattern 2
   if(cb_UsePattern2 && STLM>0 && FATL>FATL1 && FTLM>FTLM1 && RBCI>RBCI1 && (STLM>=STLM1 || (STLM<STLM1 && RBCI<1)))
      result=80;
   else
   //--- Pattern 3
   if(cb_UsePattern3 && STLM>0 && FATL>FATL1 && RBCI>RBCI1 && RBCI1<-1 && RBCI1<=RBCI2 && FTLM>FTLM1)
      result=80;
   else
   //--- Pattern 4
   if(cb_UsePattern4 && SATL>SATL1 && FATL>FATL1 && RBCI>RBCI1 && FTLM<FTLM1 && FTLM2<=FTLM1)
      result=80;
   else
   //--- Pattern 5
   if(cb_UsePattern5 && SATL>SATL1 && STLM>=0 && PCCI1<=-100 && PCCI1<PCCI && PCCI>-100 && RBCI>RBCI1 && RBCI1<=RBCI2 && RBCI1<-1)
      result=80;
   else
   //--- Pattern 6
   if(cb_UsePattern6 && SATL>SATL1 && STLM<0 && PCCI1<=-100 && PCCI>-100)
      result=80;
   else
   //--- Pattern 7
   if(cb_UsePattern7 && FATL>FATL1 && FATL1<=SATL1 && FATL>SATL && FATL1<=FATL2)
      result=80;
   //--- Pattern 8
   if(cb_UsePattern8 && FATL>FATL1 && FATL1<=SATL1 && FATL>SATL && FATL1<=RFTL1 && FATL>RFTL)
      result=80;
   
   return result;
  }


4. Erstellen des Expert Advisors der adaptiven Trendfolgemethode

Nachdem das Signalmodul erstellt wurde, kann man mit dem Erstellen des Expert Advisors beginnen. Der Prozess der Erstellung eines Expert Advisors mithilfe des MQL5 Wizard wurde in diesem Artikel ausführlich beschrieben. Bei der Erstellung des Expert Advisors habe ich nur ein Modul von Handelssignalen verwendet, das oben erstellt wurde. Es wurde ein Trailing Stop mit einer festen Punktzahl hinzugefügt. Beim Testen der Strategie werden wir eine feste Lotgröße verwenden. Dies erlaubt es uns, die Qualität der generierten Signale einzuschätzen.

Hinzufügen eines Signalmoduls

Liste der Signalmodule

Auswahl des Trailing-Moduls

Auswahl des Moduls des Money Managements

5. Testen des Expert Advisors.

Nachdem der Expert Advisor erstellt wurde, können wir die adaptive Trendfolgemethode im Strategietester testen. Beim Testen muss man unbedingt das Gewicht für das Öffnen einer Position als 60 und das Gewicht für das Schließen einer Position als 10 angeben.

5.1. Test ohne Stop Loss, Take Profit und Trailing Stop.

Um die Qualität der vom Expert Advisor generierten Signalen zu prüfen, wurde der erste Test ohne Verwendung von Stop Loss, Take Profit und Trailing Stop durchgeführt. Es wurde auf H4 für 7 Monate des Jahres 2017 getestet.

Test 1

Test 1

Leider hat der erste Test gezeigt, dass die Strategie ohne Verwendung von Stop-Loss Verluste bringt.

Test 1. Das Ergebnis

Test 1. Das Ergebnis

Test 1. Das Ergebnis

Test 1. Das Ergebnis

Test 1. Das Ergebnis 

Eine detaillierte Analyse der Abschlüsse auf dem Preischart hat zwei Schwachstellen der Strategie aufgedeckt:

  1. Dem Expert Advisor gelingt es nicht, die Abschlüsse bei Rückschlägen zu schließen, was zum Verlust des Gewinns und zum Schließen potentiell profitabler Abschlüsse mit Verlusten führt.
  2. Der Expert Advisor geht gut mit großen Bewegungen um, aber öffnet eine Reihe verlustbringender Trades während der Stagnation.

Test 1. Trades auf dem Chart

5.2. Test unter Verwendung von Stop Loss und Trailing Stop.

Um Verluste zu minimieren, werden Stop Loss und Trailing Stop verwendet.

Test 2

Test 2

Die Ergebnisse des zweiten Tests zeigten eine Reduzierung der Haltezeit einer Position, eine kleine Erhöhung des Anteils profitabler Trades, und eine allgemeine Tendenz zum Gewinn. 

Test 2. Das Ergebnis

Test 2. Das Ergebnis

Test 2. Das Ergebnis

Test 2. Das Ergebnis

Test 2. Das Ergebnis

Nichtsdestotrotz betrug der Anteil der profitablen Trades 39.26%. Und das zweite Problem war auch immer noch da (verlustbringende Trades bei einer Stagnation).

5.3. Testen mit Stop-Orders.

Um Verluste zu reduzieren, die mit Serien verlustbringender Trades bei Stagnation verbunden sind, wurde ein Test mit Stop-Orders durchgeführt.

Test 3

Test 3

Im Laufe des dritten Tests hat sich die Anzahl der Trades fast halbiert, während sich der Gesamtgewinn dabei erhöht hat und der Anteil profitabler Trades auf 44.57% gestiegen ist.

Test 3. Das Ergebnis

Test 3. Das Ergebnis

Test 3. Das Ergebnis

Test 3. Das Ergebnis

Test 3. Das Ergebnis


Fazit

Der Artikel beschäftigt sich mit der adaptiven Trendfolgemethode. Das Testen hat das Potential dieser Strategie gezeigt, aber um die Strategie auf dem realen Markt verwenden zu können, müssen einige Schwachstellen beseitigt werden. Nichtsdestotrotz ist diese Methode brauchbar. Die Quelldateien und Testergebnisse sind unten im Anhang zum Artikel zu finden.

Quellenangaben

  1. "Devisenspekulant", Dezember 2000 - Juni 2001.
  2. Analyse der wesentlichen Merkmale von Zeitreihen.
  3. Ein autoregressives (AR) Model für die Extrapolation der Kurde - ein Indikator für den MetaTrader 5
  4. MQL5 Wizard: Wie man ein eigenes Modul von Handelssignalen schreibt
  5. In 6 Schritten zum eigenen automatischen Handelssystem!
  6. MQL5 Wizard: Neue Version

Die im Artikel verwendeten Programme:

#
 Name
Typ 
Beschreibung 
 1 Spectrum.mqh Klassenbibliothek Klasse für die Schätzung der spektralen Leistungsdichte des zu untersuchenden Symbols
 2 FLF.mqh Klassenbibliothek Klasse für die Erstellung eines Tiefpassfilters und das Filtern von Quelldaten
 3 SignalATCF.mqh Klassenbibliothek Modul von Handelssignalen basierend auf der adaptiven Trendfolgemethode
 4 ATCF.mq5 Expert Advisor Expert Advisor auf Basis der adaptiven Trendfolgemethode
 5 ACTF_Test.zip Zip-Datei Die Zip-Datei beinhaltet die Ergebnisse des Testens des Expert Advisors im Strategietester.

Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/3456

Beigefügte Dateien |
ACTF_Test.zip (226.43 KB)
MQL5.zip (289.94 KB)
Optimieren einer Strategie unter Verwendung einer Kurve der Salden und dem Vergleich der Ergebnisse mit dem Kriterium "Balance + max Sharpe Ratio" Optimieren einer Strategie unter Verwendung einer Kurve der Salden und dem Vergleich der Ergebnisse mit dem Kriterium "Balance + max Sharpe Ratio"
In diesem Artikel betrachten wir ein weiteres Kriterium für die Optimierung einer Strategie auf Basis einer grafischen Analyse der Salden. Die linearen Regression wird mit der Funktion aus der Bibliothek ALGLIB berechnet.
Cross-Plattform Expert Advisor: Die Klassen CExpertAdvisor und CExpertAdvisors Classes Cross-Plattform Expert Advisor: Die Klassen CExpertAdvisor und CExpertAdvisors Classes
In diesem Artikel geht es in erster Linie um die Klassen CExpertAdvisor und CExpertAdvisors, die als Container für alle anderen in dieser Artikelserie beschriebenen Komponenten im Hinblick auf einen plattformübergreifende Expert Advisor dienen.
Ein neuer Ansatz der Interpretation der klassischen und der versteckten Divergenz Ein neuer Ansatz der Interpretation der klassischen und der versteckten Divergenz
Der Artikel untersucht die klassische Methode eine Divergenz zu erkennen und bietet eine zusätzliche Interpretation. Auf Basis dieser neuen Interpretation wurde eine Handelsstrategie entwickelt. Auch diese Strategie ist in diesem Artikel beschrieben.
Automatische Suche nach Divergenzen und Konvergenzen Automatische Suche nach Divergenzen und Konvergenzen
Der Artikel behandelt alle Arten von Divergenzen: einfach, versteckt, erweitert, dreifache, vierfache, Konvergenzen, sowie Divergenzen der Klassen A, B und C. Es wurde ein universeller Indikator für deren Ermittlung und Darstellung auf dem Chart entwickelt.