
Aufbau eines nutzerdefinierten Systems zur Erkennung von Marktregimen in MQL5 (Teil 1): Der Indikator
- Einführung
- Das Verständnis von Marktregimen
- Schaffung der statistischen Grundlage
- Implementierung des Marktregime-Detektors
- Erstellen eines nutzerdefinierten Indikators für die Regime-Visualisierung
- Schlussfolgerung
Einführung
Die Finanzmärkte befinden sich in einem ständigen Wandel und wechseln zwischen Phasen starker Trends, seitwärts gerichteter Konsolidierung und chaotischer Volatilität. Für algorithmische Händler stellt dies eine große Herausforderung dar: Eine Strategie, die in Trendmärkten außergewöhnlich gut abschneidet, versagt oft kläglich bei schwankenden Märkten, während Ansätze, die für eine geringe Volatilität konzipiert sind, bei einem Anstieg der Volatilität das Konto sprengen können. Trotz dieser Tatsache werden die meisten Handelssysteme unter der impliziten Annahme entwickelt, dass das Marktverhalten im Laufe der Zeit gleich bleibt.
Diese grundlegende Diskrepanz zwischen der Marktrealität und dem Design des Handelssystems führt zu dem nur allzu bekannten Muster der Verschlechterung der Strategieperformance. Ein System funktioniert während der Backtests und der anfänglichen Einführung hervorragend, gerät aber ins Wanken, wenn sich die Marktbedingungen unweigerlich ändern. Der Händler steht dann vor einer schwierigen Entscheidung: die Strategie aufgeben und neu beginnen oder Drawdowns hinnehmen und darauf hoffen, dass die Marktbedingungen seinen Ansatz wieder begünstigen.
Was wäre, wenn es einen besseren Weg gäbe? Was wäre, wenn Ihr Handelssystem objektiv das aktuelle Marktregime erkennen und seine Strategie entsprechend anpassen könnte? Genau das werden wir in diesem Artikel aufbauen: ein umfassendes System zur Erkennung von Marktregimen in MQL5, das die Marktbedingungen in verschiedene Regime einteilen kann und einen Rahmen für adaptive Handelsstrategien bietet.
Am Ende dieser Artikelserie werden Sie ein komplettes System zur Erkennung von Marktregimen implementiert haben, das Folgendes umfasst:- Eine solide statistische Grundlage für eine objektive Marktklassifizierung
- Eine nutzerdefinierte Marktregime-Detektorklasse, die Trends, Schwankungen und volatile Marktbedingungen identifiziert
- Ein nutzerdefinierter Indikator, der Regimewechsel direkt auf Ihren Charts visualisiert
- Ein anpassungsfähiger Expert Advisor, der automatisch geeignete Strategien auf der Grundlage des aktuellen Systems auswählt (Teil 2)
- Praktische Beispiele für die Implementierung und Optimierung des Systems für Ihre spezifischen Handelsanforderungen (Teil 2)
Ganz gleich, ob Sie ein erfahrener algorithmischer Händler sind, der seine bestehenden Systeme verbessern möchte, oder ein Neuling, der von Anfang an robustere Strategien entwickeln möchte, dieses System zur Erkennung von Marktregimen wird Ihnen leistungsstarke Werkzeuge an die Hand geben, um sich in der sich ständig verändernden Landschaft der Finanzmärkte zurechtzufinden.
Das Verständnis von Marktregimen
Bevor wir uns mit den Einzelheiten der Umsetzung befassen, ist es wichtig zu verstehen, was Marktregelungen sind und warum sie für Händler wichtig sind. Die Märkte verhalten sich im Laufe der Zeit nicht einheitlich, sondern sie wechseln zwischen verschiedenen Verhaltenszuständen oder „Regimen“. Diese Systeme haben einen erheblichen Einfluss auf die Preisentwicklung und folglich auch auf die Performance der Handelsstrategien.
Was sind Marktregime?
Marktregime sind bestimmte Muster des Marktverhaltens, die durch spezifische statistische Eigenschaften der Preisbewegungen gekennzeichnet sind. Es gibt zwar verschiedene Möglichkeiten, Marktregime zu klassifizieren, aber wir werden uns auf drei Haupttypen konzentrieren, die für die Entwicklung von Handelsstrategien am wichtigsten sind:- Trend-Regime: Die Märkte weisen starke Richtungsbewegungen mit minimaler Mittelwertumkehr auf. Der Preis neigt dazu, sich beständig in eine Richtung zu bewegen, wobei es zu flachen Rücksetzern kommt. Statistisch gesehen weisen tendenzielle Märkte eine positive Autokorrelation der Renditen auf, was bedeutet, dass Kursbewegungen in eine Richtung wahrscheinlich von Bewegungen in dieselbe Richtung gefolgt werden.
- Reichweitenregime: Die Märkte oszillieren zwischen Unterstützungs- und Widerstandsniveaus mit starken Tendenzen zur Rückkehr zum Mittelwert. Der Preis neigt dazu, zwischen definierten Grenzen zu pendeln, anstatt in eine der beiden Richtungen auszubrechen. Statistisch gesehen weisen die Renditen von Wertpapiermärkten eine negative Autokorrelation auf, was bedeutet, dass auf Aufwärtsbewegungen wahrscheinlich Abwärtsbewegungen folgen und umgekehrt.
- Volatile Regime: An den Märkten kommt es zu großen, sprunghaften Kursbewegungen mit unklarer Richtung. Diese Regime treten häufig in Zeiten der Unsicherheit, der Nachrichtenlage oder des Marktstresses auf. Statistisch gesehen weisen die volatilen Regimes eine hohe Standardabweichung der Renditen mit unvorhersehbaren Autokorrelationsmustern auf.
Zu verstehen, in welchem Regime sich der Markt derzeit befindet, ist für Handelsentscheidungen von entscheidender Bedeutung. Eine Strategie, die für Märkte mit einem Trend optimiert ist, wird wahrscheinlich unter schwankenden Bedingungen schlecht abschneiden, während Strategien der Rückkehr zum Mittelwert, die für schwankende Märkte entwickelt wurden, während starker Trends katastrophale Folgen haben können.
Warum greifen traditionelle Indikatoren zu kurz?
Die meisten technischen Indikatoren wurden entwickelt, um bestimmte Preismuster oder Bedingungen zu erkennen und nicht, um Marktregime zu klassifizieren. Zum Beispiel:- Gleitende Durchschnitte und MACD können bei der Erkennung von Trends helfen, unterscheiden aber nicht zwischen Trend- und Volatilitätstendenzen.
- RSI- und Stochastik-Oszillatoren funktionieren gut in schwankenden Märkten, erzeugen aber falsche Signale in Trendbedingungen.
- Bollinger Bänder passen sich der Volatilität an, identifizieren aber nicht explizit Regimeübergänge.
Statistische Grundlagen der Regime-Erkennung
Um ein effektives System zur Erkennung von Regimen zu entwickeln, müssen wir statistische Maße nutzen, die das Marktverhalten objektiv klassifizieren können. Zu den wichtigsten statistischen Konzepten, die wir verwenden werden, gehören:- Autokorrelation: Misst die Korrelation zwischen einer Zeitreihe und einer verzögerten Version ihrer selbst. Eine positive Autokorrelation könnte einen Trend bedeuten, während eine negative Autokorrelation auf ein (schwankendes) Verhalten mit einer Rückkehr zum Mittelwert hindeutet.
- Volatilität: Misst die Streuung der Renditen, in der Regel anhand der Standardabweichung. Plötzliche Anstiege der Volatilität signalisieren oft Regimewechsel.
- Trendstärke: Kann mit verschiedenen Methoden quantifiziert werden, darunter der absolute Wert der Autokorrelation, die Steigung der linearen Regression oder spezielle Indikatoren wie der ADX.
Durch die Kombination dieser statistischen Maße können wir einen robusten Rahmen für die objektive Klassifizierung von Marktregimen schaffen. Im nächsten Abschnitt werden wir diese Konzepte in MQL5-Code implementieren, um unser System zur Erkennung von Marktregimen aufzubauen.
Schaffung der statistischen Grundlage
In diesem Abschnitt werden wir die wichtigsten statistischen Komponenten implementieren, die für unser System zur Erkennung von Marktregimen benötigt werden. Wir werden eine robuste Klasse CStatistics erstellen, die alle für die Regimeklassifizierung erforderlichen mathematischen Berechnungen durchführen wird.
Die Klasse CStatistics
Die Grundlage unseres Systems zur Erkennung von Regimen ist eine leistungsstarke Statistikklasse, die verschiedene Berechnungen mit Preisdaten durchführen kann. Schauen wir uns die wichtigsten Komponenten dieser Klasse an:
//+------------------------------------------------------------------+ //| Class for statistical calculations | //+------------------------------------------------------------------+ class CStatistics { private: double m_data[]; // Data array for calculations int m_dataSize; // Size of the data array bool m_isSorted; // Flag indicating if data is sorted double m_sortedData[]; // Sorted copy of data for percentile calculations public: // Constructor and destructor CStatistics(); ~CStatistics(); // Data management methods bool SetData(const double &data[], int size); bool AddData(double value); void Clear(); // Basic statistical methods double Mean() const; double StandardDeviation() const; double Variance() const; // Range and extremes double Min() const; double Max() const; double Range() const; // Time series specific methods double Autocorrelation(int lag) const; double TrendStrength() const; double MeanReversionStrength() const; // Percentile calculations double Percentile(double percentile); double Median(); };
Diese Klasse bietet eine umfassende Reihe von statistischen Funktionen, die es uns ermöglichen, Preisdaten zu analysieren und das aktuelle Marktregime zu bestimmen. Schauen wir uns einige der wichtigsten Methoden im Detail an.
Konstruktor und Destruktor
//+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CStatistics::CStatistics() { m_dataSize = 0; m_isSorted = false; ArrayResize(m_data, 0); ArrayResize(m_sortedData, 0); } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CStatistics::~CStatistics() { Clear(); }
Konstruktor und Destruktor helfen bei der Initialisierung der Klasse und der Deinitialisierung der Klasse. Der Konstruktor initialisiert unsere Mitgliedsvariablen und Arrays, während der Destruktor durch den Aufruf der Methode Clear() für eine ordnungsgemäße Bereinigung sorgt. Dieses Muster der ordnungsgemäßen Initialisierung und Bereinigung ist in MQL5 wichtig, um Speicherlecks zu vermeiden und einen zuverlässigen Betrieb zu gewährleisten.
Methoden der Datenverwaltung
Als Nächstes implementieren wir die Datenverwaltungsmethoden, mit denen wir Daten setzen, hinzufügen und löschen können:
bool CStatistics::SetData(const double &data[], int size) { if(size <= 0) return false; m_dataSize = size; ArrayResize(m_data, size); for(int i = 0; i < size; i++) m_data[i] = data[i]; m_isSorted = false; return true; } bool CStatistics::AddData(double value) { m_dataSize++; ArrayResize(m_data, m_dataSize); m_data[m_dataSize - 1] = value; m_isSorted = false; return true; } void CStatistics::Clear() { m_dataSize = 0; ArrayResize(m_data, 0); ArrayResize(m_sortedData, 0); m_isSorted = false; }
Mit der Methode SetData() kann der gesamte Datensatz durch ein neues Array ersetzt werden, was bei der Verarbeitung historischer Kursdaten nützlich ist. Die Methode AddData() fügt einen einzelnen Wert an die vorhandenen Daten an, was für inkrementelle Aktualisierungen praktisch ist, wenn neue Preisdaten verfügbar werden. Die Methode Clear() setzt das Objekt in seinen Ausgangszustand zurück und gibt den zugewiesenen Speicher frei.
Beachten Sie, dass wir m_isSorted = false setzen, wenn sich die Daten ändern. Dieses Flag hilft uns, die Leistung zu optimieren, indem wir die Daten nur dann sortieren, wenn dies für die Berechnung der Prozentsätze erforderlich ist.
Grundlegende statistische Methoden
Lassen Sie uns nun die grundlegenden statistischen Methoden zur Berechnung von Mittelwert, Standardabweichung und Varianz anwenden:
double CStatistics::Mean() const { if(m_dataSize <= 0) return 0.0; double sum = 0.0; for(int i = 0; i < m_dataSize; i++) sum += m_data[i]; return sum / m_dataSize; } double CStatistics::StandardDeviation() const { if(m_dataSize <= 1) return 0.0; double mean = Mean(); double sum = 0.0; for(int i = 0; i < m_dataSize; i++) sum += MathPow(m_data[i] - mean, 2); return MathSqrt(sum / (m_dataSize - 1)); } double CStatistics::Variance() const { if(m_dataSize <= 1) return 0.0; double stdDev = StandardDeviation(); return stdDev * stdDev; }
Bei diesen Methoden werden statistische Standardformeln verwendet. Mit der Methode Mean() wird der Durchschnitt aller Datenpunkte berechnet. Die Methode StandardDeviation() misst die Streuung der Datenpunkte um den Mittelwert, was für die Identifizierung volatiler Marktregimes entscheidend ist. Die Methode Variance() gibt das Quadrat der Standardabweichung zurück und liefert damit ein weiteres Maß für die Streuung der Daten.
Beachten Sie, wie wir Randfälle, wie leere Datensätze oder einzelne Datenpunkte, behandeln, indem wir Null zurückgeben. Dieser defensive Programmieransatz verhindert Fehler bei der Arbeit mit unzureichenden Daten.Bereichs- und Extremwertmethoden
//+------------------------------------------------------------------+ //| Calculate minimum value in the data | //+------------------------------------------------------------------+ double CStatistics::Min() const { if(m_dataSize <= 0) return 0.0; double min = m_data[0]; for(int i = 1; i < m_dataSize; i++) if(m_data[i] < min) min = m_data[i]; return min; } //+------------------------------------------------------------------+ //| Calculate maximum value in the data | //+------------------------------------------------------------------+ double CStatistics::Max() const { if(m_dataSize <= 0) return 0.0; double max = m_data[0]; for(int i = 1; i < m_dataSize; i++) if(m_data[i] > max) max = m_data[i]; return max; } //+------------------------------------------------------------------+ //| Calculate range (max - min) of the data | //+------------------------------------------------------------------+ double CStatistics::Range() const { return Max() - Min(); }
Diese Methoden liefern zusätzliche Erkenntnisse über die Datenverteilung. Die Methoden Min() und Max() ermitteln den kleinsten und den größten Wert im Datensatz, während die Methode Range() die Differenz zwischen ihnen berechnet. Diese Maßstäbe können nützlich sein, um Preisgrenzen auf schwankenden Märkten zu ermitteln.
Zeitreihenspezifische Methoden
Nun wollen wir die zeitreihenspezifischen Methoden implementieren, die für die Erkennung von Regimen entscheidend sind:
double CStatistics::Autocorrelation(int lag) const { if(m_dataSize <= lag || lag <= 0) return 0.0; double mean = Mean(); double numerator = 0.0; double denominator = 0.0; for(int i = 0; i < m_dataSize - lag; i++) { numerator += (m_data[i] - mean) * (m_data[i + lag] - mean); } for(int i = 0; i < m_dataSize; i++) { denominator += MathPow(m_data[i] - mean, 2); } if(denominator == 0.0) return 0.0; return numerator / denominator; } double CStatistics::TrendStrength() const { // Use lag-1 autocorrelation as a measure of trend strength double ac1 = Autocorrelation(1); // Positive autocorrelation indicates trending behavior return ac1; } double CStatistics::MeanReversionStrength() const { // Negative autocorrelation indicates mean-reverting behavior double ac1 = Autocorrelation(1); // Return the negative of autocorrelation, so positive values // indicate stronger mean reversion return -ac1; }
Die Methode Autokorrelation() berechnet die Korrelation zwischen der Datenreihe und einer verzögerten Version ihrer selbst. Dies ist ein aussagekräftiges Maß für die Unterscheidung zwischen tendenziellen und schwankenden Märkten. Eine positive Autokorrelation (Werte größer als Null) deutet auf einen Trend hin, während eine negative Autokorrelation (Werte kleiner als Null) auf ein Rückkehr zum Mittelwert oder Seitwärtsbewegung schließen lässt.
Die Methode TrendStrength() verwendet die Lag-1-Autokorrelation als direktes Maß für die Trendstärke. Höhere positive Werte bedeuten stärkere Trends. Die Methode MeanReversionStrength() gibt das Negativ der Autokorrelation zurück, sodass positive Werte stärkere Tendenzen zu einer Rückkehr zum Mittelwert anzeigen.
Diese Methoden bilden das statistische Rückgrat unseres Systems zur Erkennung von Regimen und liefern objektive Maßstäbe für das Marktverhalten, die wir zur Klassifizierung von Regimen verwenden werden.
Perzentil-Berechnungen
Abschließend wollen wir Methoden zur Berechnung von Perzentilen und des Medians implementieren:
double CStatistics::Percentile(double percentile) { if(m_dataSize <= 0 || percentile < 0.0 || percentile > 100.0) return 0.0; // Sort data if needed if(!m_isSorted) { ArrayResize(m_sortedData, m_dataSize); for(int i = 0; i < m_dataSize; i++) m_sortedData[i] = m_data[i]; ArraySort(m_sortedData); m_isSorted = true; } // Calculate position double position = (percentile / 100.0) * (m_dataSize - 1); int lowerIndex = (int)MathFloor(position); int upperIndex = (int)MathCeil(position); // Handle edge cases if(lowerIndex == upperIndex) return m_sortedData[lowerIndex]; // Interpolate double fraction = position - lowerIndex; return m_sortedData[lowerIndex] + fraction * (m_sortedData[upperIndex] - m_sortedData[lowerIndex]); } double CStatistics::Median() { return Percentile(50.0); }
Die Methode Percentile() berechnet den Wert, unter den ein bestimmter Prozentsatz der Beobachtungen fällt. Zunächst werden die Daten sortiert (sofern nicht bereits sortiert) und dann durch lineare Interpolation der genaue Perzentilwert ermittelt. Die Methode Median() ist eine Komfortfunktion, die das 50. Perzentil zurückgibt, das den mittleren Wert des Datensatzes darstellt.
Beachten Sie die Optimierung mit dem Flag m_isSorted, das sicherstellt, dass die Daten nur einmal sortiert werden, auch wenn mehrere Perzentile berechnet werden. Dies ist ein Beispiel dafür, wie eine sorgfältige Implementierung die Leistung von MQL5-Code verbessern kann.
Mit der Vervollständigung unserer Klasse CStatistics verfügen wir nun über ein leistungsstarkes Instrumentarium zur Analyse von Preisdaten und zur Erkennung von Marktregimen. Im nächsten Abschnitt bauen wir auf dieser Grundlage auf und erstellen die Klasse Market Regime Detector.
Implementierung des Marktregime-Detektors
Nachdem wir nun unsere statistische Grundlage geschaffen haben, können wir die Kernkomponente unseres Systems aufbauen: den Marktregime-Detektor. In diesem Kurs werden wir die von uns eingeführten statistischen Maßnahmen nutzen, um die Marktbedingungen in bestimmte Regime einzuordnen.
Enumeration für die Marktregime
Definieren wir zunächst die Typen der Marktregime, die unser System identifizieren wird. Wir erstellen eine separate Datei mit dem Namen MarketRegimeEnum.mqh, um sicherzustellen, dass die Enum-Definition für alle Komponenten unseres Systems verfügbar ist:
// Define market regime types enum ENUM_MARKET_REGIME { REGIME_TRENDING_UP = 0, // Trending up regime REGIME_TRENDING_DOWN = 1, // Trending down regime REGIME_RANGING = 2, // Ranging/sideways regime REGIME_VOLATILE = 3, // Volatile/chaotic regime REGIME_UNDEFINED = 4 // Undefined regime (default) };
Diese Erkennen definiert die fünf möglichen Marktregime, die unser System erkennen kann. Wir werden diese Werte in unserer gesamten Implementierung verwenden, um den aktuellen Marktzustand darzustellen.
Die Klasse CMarketRegimeDetector
Die Detektorklasse des Marktregimes kombiniert unsere statistischen Werkzeuge mit einer Logik zur Klassifizierung von Marktregimen. Schauen wir uns seine Struktur an:
class CMarketRegimeDetector { private: // Configuration int m_lookbackPeriod; // Period for calculations int m_smoothingPeriod; // Period for smoothing regime transitions double m_trendThreshold; // Threshold for trend detection double m_volatilityThreshold; // Threshold for volatility detection // Data buffers double m_priceData[]; // Price data buffer double m_returns[]; // Returns data buffer double m_volatility[]; // Volatility buffer double m_trendStrength[]; // Trend strength buffer double m_regimeBuffer[]; // Regime classification buffer // Statistics objects CStatistics m_priceStats; // Statistics for price data CStatistics m_returnsStats; // Statistics for returns data CStatistics m_volatilityStats; // Statistics for volatility data // Current state ENUM_MARKET_REGIME m_currentRegime; // Current detected regime // Helper methods void CalculateReturns(); void CalculateVolatility(); void CalculateTrendStrength(); ENUM_MARKET_REGIME DetermineRegime(); public: // Constructor and destructor CMarketRegimeDetector(int lookbackPeriod = 100, int smoothingPeriod = 10); ~CMarketRegimeDetector(); // Configuration methods void SetLookbackPeriod(int period); void SetSmoothingPeriod(int period); void SetTrendThreshold(double threshold); void SetVolatilityThreshold(double threshold); // Processing methods bool Initialize(); bool ProcessData(const double &price[], int size); // Access methods ENUM_MARKET_REGIME GetCurrentRegime() const { return m_currentRegime; } string GetRegimeDescription() const; double GetTrendStrength() const; double GetVolatility() const; // Buffer access for indicators bool GetRegimeBuffer(double &buffer[]) const; bool GetTrendStrengthBuffer(double &buffer[]) const; bool GetVolatilityBuffer(double &buffer[]) const; };
Diese Klasse kapselt alle Funktionen, die zur Erkennung von Marktregimen erforderlich sind. Lassen Sie uns jede Methode im Detail implementieren.
Konstruktor und Destruktor
Implementieren wir zunächst den Konstruktor und den Destruktor:
CMarketRegimeDetector::CMarketRegimeDetector(int lookbackPeriod, int smoothingPeriod) { // Set default parameters m_lookbackPeriod = (lookbackPeriod > 20) ? lookbackPeriod : 100; m_smoothingPeriod = (smoothingPeriod > 0) ? smoothingPeriod : 10; m_trendThreshold = 0.2; m_volatilityThreshold = 1.5; // Initialize current regime m_currentRegime = REGIME_UNDEFINED; // Initialize buffers ArrayResize(m_priceData, m_lookbackPeriod); ArrayResize(m_returns, m_lookbackPeriod - 1); ArrayResize(m_volatility, m_lookbackPeriod - 1); ArrayResize(m_trendStrength, m_lookbackPeriod - 1); ArrayResize(m_regimeBuffer, m_lookbackPeriod); // Initialize buffers with zeros ArrayInitialize(m_priceData, 0.0); ArrayInitialize(m_returns, 0.0); ArrayInitialize(m_volatility, 0.0); ArrayInitialize(m_trendStrength, 0.0); ArrayInitialize(m_regimeBuffer, (double)REGIME_UNDEFINED); } CMarketRegimeDetector::~CMarketRegimeDetector() { // Free memory (not strictly necessary in MQL5, but good practice) ArrayFree(m_priceData); ArrayFree(m_returns); ArrayFree(m_volatility); ArrayFree(m_trendStrength); ArrayFree(m_regimeBuffer); }
Der Konstruktor initialisiert alle Mitgliedsvariablen und Arrays mit Standardwerten. Es beinhaltet eine Parametervalidierung, um sicherzustellen, dass der Rückblickzeitraum mindestens 20 Balken beträgt (für statistische Signifikanz) und der Glättungszeitraum positiv ist. Der Destruktor gibt den für die Arrays zugewiesenen Speicher frei, was eine gute Praxis ist, auch wenn MQL5 eine automatische Garbage Collection hat.
Konfigurationsmethoden
Als Nächstes implementieren wir die Konfigurationsmethoden, mit denen die Nutzer das Verhalten des Detektors anpassen können:
void CMarketRegimeDetector::SetLookbackPeriod(int period) { if(period <= 20) return; m_lookbackPeriod = period; // Resize buffers ArrayResize(m_priceData, m_lookbackPeriod); ArrayResize(m_returns, m_lookbackPeriod - 1); ArrayResize(m_volatility, m_lookbackPeriod - 1); ArrayResize(m_trendStrength, m_lookbackPeriod - 1); ArrayResize(m_regimeBuffer, m_lookbackPeriod); // Re-initialize Initialize(); } void CMarketRegimeDetector::SetSmoothingPeriod(int period) { if(period <= 0) return; m_smoothingPeriod = period; } void CMarketRegimeDetector::SetTrendThreshold(double threshold) { if(threshold <= 0.0) return; m_trendThreshold = threshold; } void CMarketRegimeDetector::SetVolatilityThreshold(double threshold) { if(threshold <= 0.0) return; m_volatilityThreshold = threshold; }
Mit diesen Methoden können die Nutzer die Parameter des Detektors an ihre spezifischen Handelsinstrumente und Zeitrahmen anpassen. Die Methode SetLookbackPeriod() ist besonders wichtig, da sie die Größe aller internen Puffer an den neuen Zeitraum anpasst. Bei den anderen Methoden werden die entsprechenden Parameter nach der Validierung der Eingabewerte einfach aktualisiert.
Initialisierungs- und Verarbeitungsmethoden
Lassen Sie uns nun die Initialisierungs- und Datenverarbeitungsmethoden implementieren:
bool CMarketRegimeDetector::Initialize() { // Initialize buffers with zeros ArrayInitialize(m_priceData, 0.0); ArrayInitialize(m_returns, 0.0); ArrayInitialize(m_volatility, 0.0); ArrayInitialize(m_trendStrength, 0.0); ArrayInitialize(m_regimeBuffer, (double)REGIME_UNDEFINED); // Reset current regime m_currentRegime = REGIME_UNDEFINED; return true; } bool CMarketRegimeDetector::ProcessData(const double &price[], int size) { if(size < m_lookbackPeriod) return false; // Copy the most recent price data for(int i = 0; i < m_lookbackPeriod; i++) m_priceData[i] = price[size - m_lookbackPeriod + i]; // Calculate returns, volatility, and trend strength CalculateReturns(); CalculateVolatility(); CalculateTrendStrength(); // Determine the current market regime m_currentRegime = DetermineRegime(); // Update regime buffer for indicator display for(int i = 0; i < m_lookbackPeriod - 1; i++) m_regimeBuffer[i] = m_regimeBuffer[i + 1]; m_regimeBuffer[m_lookbackPeriod - 1] = (double)m_currentRegime; return true; }
Die Methode Initialize() setzt alle Puffer und das aktuelle Regime auf ihre Standardwerte zurück. Die Methode ProcessData() ist das Herzstück des Detektors, das neue Preisdaten verarbeitet und die Regimeklassifizierung aktualisiert. Es kopiert zunächst die jüngsten Kursdaten, berechnet dann die Renditen, die Volatilität und die Trendstärke und bestimmt schließlich das aktuelle Marktregime. Außerdem wird der Regimepuffer für die Indikatoranzeige aktualisiert, wobei die Werte verschoben werden, um Platz für das neue Regime zu schaffen.
Berechnungsmethoden
Implementieren wir die Berechnungsmethoden, mit denen die statistischen Maße für die Regimeerkennung berechnet werden:
void CMarketRegimeDetector::CalculateReturns() { for(int i = 0; i < m_lookbackPeriod - 1; i++) { // Calculate percentage returns if(m_priceData[i] != 0.0) m_returns[i] = (m_priceData[i + 1] - m_priceData[i]) / m_priceData[i] * 100.0; else m_returns[i] = 0.0; } // Update returns statistics m_returnsStats.SetData(m_returns, m_lookbackPeriod - 1); } void CMarketRegimeDetector::CalculateVolatility() { // Use a rolling window for volatility calculation int windowSize = MathMin(20, m_lookbackPeriod - 1); for(int i = 0; i < m_lookbackPeriod - 1; i++) { if(i < windowSize - 1) { m_volatility[i] = 0.0; continue; } double sum = 0.0; double mean = 0.0; // Calculate mean for(int j = 0; j < windowSize; j++) mean += m_returns[i - j]; mean /= windowSize; // Calculate standard deviation for(int j = 0; j < windowSize; j++) sum += MathPow(m_returns[i - j] - mean, 2); m_volatility[i] = MathSqrt(sum / (windowSize - 1)); } // Update volatility statistics m_volatilityStats.SetData(m_volatility, m_lookbackPeriod - 1); } void CMarketRegimeDetector::CalculateTrendStrength() { // Use a rolling window for trend strength calculation int windowSize = MathMin(50, m_lookbackPeriod - 1); for(int i = 0; i < m_lookbackPeriod - 1; i++) { if(i < windowSize - 1) { m_trendStrength[i] = 0.0; continue; } double window[]; ArrayResize(window, windowSize); // Copy data to window for(int j = 0; j < windowSize; j++) window[j] = m_returns[i - j]; // Create temporary statistics object CStatistics tempStats; tempStats.SetData(window, windowSize); // Calculate trend strength using autocorrelation m_trendStrength[i] = tempStats.TrendStrength(); } // Update price statistics m_priceStats.SetData(m_priceData, m_lookbackPeriod); }Diese Methoden berechnen die wichtigsten statistischen Maße, die zur Erkennung von Regimen verwendet werden:
- CalculateReturns() berechnet aus den Kursdaten prozentuale Renditen, die für statistische Analysen besser geeignet sind als Rohkurse.
- CalculateVolatility() verwendet den Ansatz eines Rolling-Windows, um die Standardabweichung der Renditen zu jedem Zeitpunkt zu berechnen und so ein Maß für die Marktvolatilität zu erhalten.
- CalculateTrendStrength() verwendet ebenfalls den Ansatz eines Rolling-Windows, erstellt jedoch für jedes Fenster ein temporäres CStatistics-Objekt und verwendet dessen Methode TrendStrength() zur Berechnung der auf einer Autokorrelation basierenden Trendstärke.
Diese rollierenden Berechnungen ermöglichen eine reaktionsschnellere und genauere Bewertung der Marktbedingungen als die Verwendung des gesamten Rückblicks für jede Berechnung.
Regime-Klassifizierung
Das Herzstück unseres Systems ist die Methode DetermineRegime(), die den aktuellen Marktzustand auf der Grundlage statistischer Maße klassifiziert:
ENUM_MARKET_REGIME CMarketRegimeDetector::DetermineRegime() { // Get the latest values double latestTrendStrength = m_trendStrength[m_lookbackPeriod - 2]; double latestVolatility = m_volatility[m_lookbackPeriod - 2]; // Get the average volatility for comparison double avgVolatility = 0.0; int count = 0; for(int i = m_lookbackPeriod - 22; i < m_lookbackPeriod - 2; i++) { if(i >= 0) { avgVolatility += m_volatility[i]; count++; } } if(count > 0) avgVolatility /= count; else avgVolatility = latestVolatility; // Determine price direction double priceChange = m_priceData[m_lookbackPeriod - 1] - m_priceData[m_lookbackPeriod - m_smoothingPeriod - 1]; // Classify the regime if(latestVolatility > avgVolatility * m_volatilityThreshold) { // Highly volatile market return REGIME_VOLATILE; } else if(MathAbs(latestTrendStrength) > m_trendThreshold) { // Trending market if(priceChange > 0) return REGIME_TRENDING_UP; else return REGIME_TRENDING_DOWN; } else { // Ranging market return REGIME_RANGING; } }Mit dieser Methode wird ein hierarchischer Klassifizierungsansatz umgesetzt:
- Zunächst wird geprüft, ob der Markt eine hohe Volatilität aufweist, indem die aktuelle Volatilität mit der durchschnittlichen Volatilität der letzten 20 Balken verglichen wird. Wenn die Volatilität den Schwellenwert überschreitet, wird der Markt als volatil eingestuft.
- Wenn der Markt nicht volatil ist, wird geprüft, ob ein signifikanter Trend vorliegt, indem die absolute Trendstärke mit der Trendschwelle verglichen wird. Wird ein Trend erkannt, wird die Richtung (aufwärts oder abwärts) auf der Grundlage der Kursveränderung während des Glättungszeitraums bestimmt.
- Wird weder eine Volatilität noch ein Trend festgestellt, wird der Markt als schwankend eingestuft.
Dieser hierarchische Ansatz gewährleistet, dass die Volatilität Vorrang vor der Trenderkennung hat, da Trendfolgestrategien in volatilen Märkten besonders anfällig sind.
Zugriffsmethoden
Zum Schluss wollen wir die Zugriffsmethoden implementieren, die Informationen über das aktuelle Marktregime liefern:
string CMarketRegimeDetector::GetRegimeDescription() const { switch(m_currentRegime) { case REGIME_TRENDING_UP: return "Trending Up"; case REGIME_TRENDING_DOWN: return "Trending Down"; case REGIME_RANGING: return "Ranging"; case REGIME_VOLATILE: return "Volatile"; default: return "Undefined"; } } double CMarketRegimeDetector::GetTrendStrength() const { if(m_lookbackPeriod <= 2) return 0.0; return m_trendStrength[m_lookbackPeriod - 2]; } double CMarketRegimeDetector::GetVolatility() const { if(m_lookbackPeriod <= 2) return 0.0; return m_volatility[m_lookbackPeriod - 2]; } bool CMarketRegimeDetector::GetRegimeBuffer(double &buffer[]) const { if(ArraySize(buffer) < m_lookbackPeriod) ArrayResize(buffer, m_lookbackPeriod); for(int i = 0; i < m_lookbackPeriod; i++) buffer[i] = m_regimeBuffer[i]; return true; } bool CMarketRegimeDetector::GetTrendStrengthBuffer(double &buffer[]) const { int size = m_lookbackPeriod - 1; if(ArraySize(buffer) < size) ArrayResize(buffer, size); for(int i = 0; i < size; i++) buffer[i] = m_trendStrength[i]; return true; } bool CMarketRegimeDetector::GetVolatilityBuffer(double &buffer[]) const { int size = m_lookbackPeriod - 1; if(ArraySize(buffer) < size) ArrayResize(buffer, size); for(int i = 0; i < size; i++) buffer[i] = m_volatility[i]; return true; }Diese Methoden ermöglichen den Zugriff auf das aktuelle Regime und seine Merkmale:
- GetRegimeDescription() gibt eine für den Menschen lesbare Beschreibung des aktuellen Regimes zurück.
- GetTrendStrength() und GetVolatility() geben die aktuellen Werte für Trendstärke und Volatilität zurück.
- GetRegimeBuffer(), GetTrendStrengthBuffer() und GetVolatilityBuffer() kopieren die internen Puffer in externe Arrays, was für die Anzeige von Indikatoren nützlich ist.
Mit der Fertigstellung unserer Klasse CMarketRegimeDetector verfügen wir nun über ein leistungsfähiges Instrument zur Erkennung von Marktregimen. Im nächsten Abschnitt werden wir einen nutzerdefinierten Indikator erstellen, der diese Regime direkt auf dem Kurschart visualisiert.
Erstellen eines nutzerdefinierten Indikators für die Regime-Visualisierung
Nachdem wir nun unsere Klasse „Market Regime Detector“ haben, können wir einen nutzerdefinierten Indikator erstellen, der die erkannten Regimes direkt im Preischart anzeigt. Dies bietet den Händlern eine intuitive Möglichkeit, Regimewechsel zu erkennen und ihre Strategien entsprechend anzupassen.
Der MarketRegimeIndicator
Unser nutzerdefinierter Indikator zeigt das aktuelle Marktregime, die Trendstärke und die Volatilität direkt auf dem Chart an. Hier ist die Umsetzung:#property indicator_chart_window #property indicator_buffers 3 #property indicator_plots 3 // Include the Market Regime Detector #include "MarketRegimeEnum.mqh" #include "MarketRegimeDetector.mqh" // Indicator input parameters input int LookbackPeriod = 100; // Lookback period for calculations input int SmoothingPeriod = 10; // Smoothing period for regime transitions input double TrendThreshold = 0.2; // Threshold for trend detection (0.1-0.5) input double VolatilityThreshold = 1.5; // Threshold for volatility detection (1.0-3.0) // Indicator buffers double RegimeBuffer[]; // Buffer for regime classification double TrendStrengthBuffer[]; // Buffer for trend strength double VolatilityBuffer[]; // Buffer for volatility // Global variables CMarketRegimeDetector *Detector = NULL;Der Indikator verwendet drei Puffer, um verschiedene Aspekte von Marktregimen zu speichern und anzuzeigen:
- RegimeBuffer - Speichert die numerische Darstellung des aktuellen Regimes
- TrendStrengthBuffer - Speichert die Werte der Trendstärke
- VolatilityBuffer - Speichert die Volatilitätswerte
Initialisierung des Indikators
Die Funktion OnInit() richtet die Indikatorpuffer ein und erstellt den Marktregime-Detektor:
int OnInit() { // Set indicator buffers SetIndexBuffer(0, RegimeBuffer, INDICATOR_DATA); SetIndexBuffer(1, TrendStrengthBuffer, INDICATOR_DATA); SetIndexBuffer(2, VolatilityBuffer, INDICATOR_DATA); // Set indicator labels PlotIndexSetString(0, PLOT_LABEL, "Market Regime"); PlotIndexSetString(1, PLOT_LABEL, "Trend Strength"); PlotIndexSetString(2, PLOT_LABEL, "Volatility"); // Set indicator styles PlotIndexSetInteger(0, PLOT_DRAW_TYPE, DRAW_LINE); PlotIndexSetInteger(1, PLOT_DRAW_TYPE, DRAW_LINE); PlotIndexSetInteger(2, PLOT_DRAW_TYPE, DRAW_LINE); // Set line colors PlotIndexSetInteger(1, PLOT_LINE_COLOR, clrBlue); PlotIndexSetInteger(2, PLOT_LINE_COLOR, clrRed); // Set line styles PlotIndexSetInteger(1, PLOT_LINE_STYLE, STYLE_SOLID); PlotIndexSetInteger(2, PLOT_LINE_STYLE, STYLE_SOLID); // Set line widths PlotIndexSetInteger(1, PLOT_LINE_WIDTH, 1); PlotIndexSetInteger(2, PLOT_LINE_WIDTH, 1); // Create and initialize the Market Regime Detector Detector = new CMarketRegimeDetector(LookbackPeriod, SmoothingPeriod); if(Detector == NULL) { Print("Failed to create Market Regime Detector"); return INIT_FAILED; } // Configure the detector Detector.SetTrendThreshold(TrendThreshold); Detector.SetVolatilityThreshold(VolatilityThreshold); Detector.Initialize(); // Set indicator name IndicatorSetString(INDICATOR_SHORTNAME, "Market Regime Detector"); return INIT_SUCCEEDED; }Diese Funktion erfüllt mehrere wichtige Aufgaben:
- Sie bindet die Indikatorpuffer an die entsprechenden Arrays
- Sie legt die visuellen Eigenschaften des Indikators fest (Beschriftungen, Stile, Farben)
- Sie erstellt und konfiguriert den Market Regime Detector mit den vom Nutzer angegebenen Parametern
Die Verwendung von SetIndexBuffer() und verschiedenen PlotIndexSetXXX()-Befehlen ist Standardpraxis bei der Entwicklung von MQL5-Indikatoren. Diese Funktionen konfigurieren, wie der Indikator im Chart angezeigt werden soll.
Berechnung des Indikators
Die Funktion OnCalculate() verarbeitet Kursdaten und aktualisiert die Indikatorpuffer:
int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) { // Check if there's enough data if(rates_total < LookbackPeriod) return 0; // Process data with the detector if(!Detector.ProcessData(close, rates_total)) { Print("Failed to process data with Market Regime Detector"); return 0; } // Get the regime buffer Detector.GetRegimeBuffer(RegimeBuffer); // Get the trend strength buffer Detector.GetTrendStrengthBuffer(TrendStrengthBuffer); // Get the volatility buffer Detector.GetVolatilityBuffer(VolatilityBuffer); // Display current regime in the chart corner string regimeText = "Current Market Regime: " + Detector.GetRegimeDescription(); string trendText = "Trend Strength: " + DoubleToString(Detector.GetTrendStrength(), 4); string volatilityText = "Volatility: " + DoubleToString(Detector.GetVolatility(), 4); Comment(regimeText + "\n" + trendText + "\n" + volatilityText); // Return the number of calculated bars return rates_total; }Diese Funktion:
- Prüft, ob genügend Daten für die Berechnung vorhanden sind.
- Verarbeitet die Preisdaten mit dem Market Regime Detector.
- Ruft die Puffer für Regime, Trendstärke und Volatilität ab.
- Zeigt die Informationen zum aktuellen Regime in der Chartecke an.
- Gibt die Anzahl der berechneten Balken zurück.
Die Funktion OnCalculate() wird von der Plattform immer dann aufgerufen, wenn neue Kursdaten verfügbar sind oder wenn das Chart gescrollt wird. Er ist für die Aktualisierung der Indikatorpuffer zuständig, die dann auf dem Chart angezeigt werden.
Indikator Cleanup
Die Funktion OnDeinit() sorgt für eine ordnungsgemäße Bereinigung, wenn der Indikator entfernt wird:
void OnDeinit(const int reason) { // Clean up if(Detector != NULL) { delete Detector; Detector = NULL; } // Clear the comment Comment(""); }
Diese Funktion löscht das Market Regime Detector-Objekt, um Speicherlecks zu vermeiden, und löscht alle Kommentare aus dem Chart. Eine ordnungsgemäße Bereinigung ist bei der MQL5-Programmierung unerlässlich, um sicherzustellen, dass die Ressourcen freigegeben werden, wenn sie nicht mehr benötigt werden.
Interpretation des Indikators
Bei der Verwendung des Market Regime Indicator sollten Händler auf Folgendes achten:- Regime Line: Diese Linie stellt die derzeitige Marktordnung dar. Die Zahlenwerte entsprechen den verschiedenen Regimen:
- 0: Trending Up
- 1: Trending Down
- 2: Ranging
- 3: Volatile
- 4: Undefined
- Trendstärke-Linie: Diese blaue Linie zeigt die Stärke des Trends. Höhere positive Werte weisen auf stärkere Aufwärtstrends hin, während niedrigere negative Werte stärkere Abwärtstrends anzeigen. Werte nahe Null deuten auf einen schwachen oder keinen Trend hin.
- Volatilitätslinie: Diese rote Linie zeigt das aktuelle Volatilitätsniveau. Ausschläge in dieser Linie gehen häufig Regimewechsel voraus und können potenzielle Handelschancen oder -risiken signalisieren.
- Kommentar zur Tabelle: Der Indikator zeigt das aktuelle Regime, die Trendstärke und die Volatilitätswerte in der oberen linken Ecke des Charts an, um eine einfache Referenz zu ermöglichen.
Durch die Beobachtung dieser Elemente können die Händler das aktuelle Marktregime schnell erkennen und ihre Strategien entsprechend anpassen. So sollten beispielsweise Trendfolgestrategien während Trendphasen eingesetzt werden, während Strategien der Rückkehr zum Mittelwert in Schwankungsphasen besser geeignet sind. In Zeiten hoher Volatilität könnten Händler erwägen, die Positionsgrößen zu reduzieren oder sich ganz vom Markt fernzuhalten.
Hier können wir deutlich sehen, dass sich der aktuelle Markt in einer Schwankungsbreite befindet, wie wir auch auf dem Chart deutlich erkennen können.
Schlussfolgerung
In diesem Artikel haben wir uns auf den Weg gemacht, um eines der schwierigsten Probleme im algorithmischen Handel zu lösen: die Anpassung an sich ändernde Marktbedingungen. Wir begannen mit der Erkenntnis, dass sich die Märkte im Laufe der Zeit nicht gleichförmig verhalten, sondern zwischen verschiedenen Verhaltenszuständen oder „Regimen“ wechseln. Diese Erkenntnis hat uns dazu veranlasst, ein umfassendes System zur Erkennung von Marktregimen zu entwickeln, mit dem diese Übergänge erkannt werden können. Im nächsten Teil werden wir sehen, wie man Handelsstrategien entsprechend unserer Erkennung von Regimen anpassen kann.
Der Weg vom Problem zur Lösung
Als wir anfingen, stellten wir eine kritische Lücke in den meisten Handelssystemen fest: die Unfähigkeit, Marktbedingungen objektiv zu klassifizieren und sich an sie anzupassen. Herkömmliche Indikatoren und Strategien sind in der Regel für bestimmte Marktbedingungen optimiert, was zu einer uneinheitlichen Performance führt, wenn sich die Märkte weiterentwickeln. Das ist das Problem, mit dem Händler täglich konfrontiert sind - Strategien, die in einem Marktumfeld hervorragend funktionieren, können in einem anderen spektakulär scheitern.
Unsere Lösung für dieses Problem bestand darin, ein robustes System zur Erkennung von Marktregimen von Grund auf zu entwickeln. Wir begannen mit einer soliden statistischen Grundlage und implementierten Schlüsselmaße wie Autokorrelation und Volatilität, die das Marktverhalten objektiv klassifizieren können. Anschließend haben wir eine umfassende Market Regime Detector-Klasse entwickelt, die diese statistischen Maße zur Identifizierung von Trends, Schwankungen und volatilen Marktbedingungen nutzt.
Um dieses System praktisch und zugänglich zu machen, haben wir einen nutzerdefinierten Indikator entwickelt, der Regimewechsel direkt auf dem Preischart anzeigt und Händlern ein unmittelbares visuelles Feedback zu den aktuellen Marktbedingungen gibt. Anschließend haben wir gezeigt, wie man einen adaptiven Expert Advisor erstellt, der automatisch verschiedene Handelsstrategien auf der Grundlage des erkannten Systems auswählt und anwendet.
Im nächsten Teil des Artikels werden wir uns mit praktischen Überlegungen zur Implementierung und Optimierung des Systems befassen, einschließlich der Optimierung von Parametern, der Handhabung von Regimeübergängen und der Integration in bestehende Handelssysteme. Diese praktischen Einblicke werden Ihnen helfen, das Market Regime Detection System effektiv und automatisch in Ihrem eigenen Handel einzusetzen. In der Zwischenzeit spielen Sie mit dem manuellen Ansatz des Indikators herum.
Datei-Übersicht
Hier finden Sie eine Zusammenfassung aller in diesem Artikel erstellten Dateien: Dateiname | Beschreibung |
---|---|
MarketRegimeEnum.mqh | Definiert die im gesamten System verwendeten Aufzählungstypen der Marktordnung |
CStatistics.mqh | Klasse der statistischen Berechnungen zur Erkennung von Marktordnungen |
MarketRegimeDetector.mqh | Umsetzung der Kernmarktregelung |
MarketRegimeIndicator.mq5 | Nutzerdefinierter Indikator zur Visualisierung von Regimen in Charten |
Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/17737
Warnung: Alle Rechte sind von MetaQuotes Ltd. vorbehalten. Kopieren oder Vervielfältigen untersagt.
Dieser Artikel wurde von einem Nutzer der Website verfasst und gibt dessen persönliche Meinung wieder. MetaQuotes Ltd übernimmt keine Verantwortung für die Richtigkeit der dargestellten Informationen oder für Folgen, die sich aus der Anwendung der beschriebenen Lösungen, Strategien oder Empfehlungen ergeben.





- 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.
Ihr Code lässt sich nicht kompilieren.... fehlt IsStrongSignal(value) ...
Auf welche Datei beziehen Sie sich?
Der Marktregime-Indikator weist 24 Fehler und 1 Warnung auf, wenn ich versuche, ihn zu kompilieren:
'MarketRegimeIndicator.mq5' 1
Datei 'C:\Users\rauma\AppData\Roaming\MetaQuotes\Terminal\10CE948A1DFC9A8C27E56E827008EBD4\MQL5\Include\MarketRegimeEnum.mqh' nicht gefunden MarketRegimeIndicator.mq5 14 11
Datei 'C:\Benutzer\rauma\AppData\Roaming\MetaQuotes\Terminal\10CE948A1DFC9A8C27E56E827008EBD4\MQL5\Include\MarketRegimeDetector.mqh' nicht gefunden MarketRegimeIndicator.mq5 15 11
'CMarketRegimeDetector' - unerwartetes Token, wahrscheinlich fehlt der Typ? MarketRegimeIndicator.mq5 29 1
'*' - Semikolon erwartet MarketRegimeIndicator.mq5 29 23
'Detector' - nicht deklarierter Bezeichner MarketRegimeIndicator.mq5 64 5
'CMarketRegimeDetector' - Deklaration ohne Typ MarketRegimeIndicator.mq5 64 20
CMarketRegimeDetector' - Klassentyp erwartet MarketRegimeIndicator.mq5 64 20
Funktion nicht definiert MarketRegimeIndicator.mq5 64 20
'new' - Ausdruck vom Typ 'void' ist illegal MarketRegimeIndicator.mq5 64 16
'=' - Verwendung einer illegalen Operation MarketRegimeIndicator.mq5 64 14
'Detector' - nicht deklarierter Bezeichner MarketRegimeIndicator.mq5 65 8
'==' - illegale Operation MarketRegimeIndicator.mq5 65 17
Detector' - nicht deklarierter Bezeichner MarketRegimeIndicator.mq5 72 5
Detektor' - nicht deklarierter Bezeichner MarketRegimeIndicator.mq5 73 5
Detektor' - nicht deklarierter Bezeichner MarketRegimeIndicator.mq5 74 5
Detektor' - nicht deklarierter Bezeichner MarketRegimeIndicator.mq5 101 9
';' - unerwartetes Token MarketRegimeIndicator.mq5 103 68
'(' - unausgewogene linke Klammer MarketRegimeIndicator.mq5 101 7
leere kontrollierte Anweisung gefunden MarketRegimeIndicator.mq5 103 68
'Detector' - nicht deklarierter Bezeichner MarketRegimeIndicator.mq5 133 8
'!=' - illegale Operation MarketRegimeIndicator.mq5 133 17
'Detector' - nicht deklarierter Bezeichner MarketRegimeIndicator.mq5 135 16
'Detector' - Objektzeiger erwartet MarketRegimeIndicator.mq5 135 16
Detektor' - nicht deklarierter Bezeichner MarketRegimeIndicator.mq5 136 9
'=' - unzulässige Verwendung einer Operation MarketRegimeIndicator.mq5 136 18
24 Fehler, 1 Warnung 25 2
Der Marktregime-Indikator hat 24 Fehler und 1 Warnung, wenn ich versuche, ihn zu kompilieren:
'MarketRegimeIndicator.mq5' 1
Datei 'C:\Benutzer\rauma\AppData\Roaming\MetaQuotes\Terminal\10CE948A1DFC9A8C27E56E827008EBD4\MQL5\Include\MarketRegimeEnum.mqh' nicht gefunden MarketRegimeIndicator.mq5 14 11
Datei 'C:\Benutzer\rauma\AppData\Roaming\MetaQuotes\Terminal\10CE948A1DFC9A8C27E56E827008EBD4\MQL5\Include\MarketRegimeDetector.mqh' nicht gefunden MarketRegimeIndicator.mq5 15 11
Der Indikator sucht nach diesen Dateien im Ordner C:\Users\rauma\AppData\Roaming\MetaQuotes\Terminal\10CE948A1DFC9A8C27E56E827008EBD4\MQL5\Include\
Auf welche Datei beziehen Sie sich?
bei Zeile 472
Ich nehme an, Sie beziehen sich auf
IsStrongSignal' - nicht deklarierter Bezeichner MarketRegimeDetector.mqh 472 16