
Entwicklung eines Toolkit zur Analyse von Preisaktionen (Teil 17): Der TrendLoom EA
Inhalt
Einführung
Die Methoden der Marktanalyse und der Einstiegsbestätigung sind bei den Trendanalysten unterschiedlich. Viele Händler prüfen mehrere Zeitrahmen wie M1, M5 und M15 oder H1, H4 und W1, um ihre Eingaben zu validieren und die Zuverlässigkeit der Signale zu erhöhen. Anstatt den Zeitrahmen zu ändern, um den Gesamttrend abzuschätzen, drücken Sie einfach eine Taste und erhalten eine zeitnahe Aktualisierung oder werden automatisch aktualisiert. Haben Sie schon einmal einen Verkauf in einem niedrigeren Zeitrahmen gesehen, einen Handel abgeschlossen und dann einen Chart in einem höheren Zeitrahmen geöffnet, nur um einen Kauftrend zu entdecken?
TrendLoom EA wurde entwickelt, um diesen Fehler zu vermeiden. Es verfügt über ein Panel mit sieben Schaltflächen, die verschiedene Handelsstile darstellen. Jede Schaltfläche zeigt drei Zeitrahmen, die zusammen mit gleitenden Durchschnitten analysiert werden, um Signale wie KAUF, VERKAUF oder NEUTRAL zu erzeugen. Dieses robuste Tool bietet schnelle Bestätigungs-Updates und aktualisiert kontinuierlich relevante Signale, sobald sie erkannt werden.
Überblick über die Strategie
Der TrendLoom EA ist als grafische Oberfläche (Panel) aufgebaut. Das Panel enthält sieben Schaltflächen, die jeweils einer bestimmten Handelsstrategie entsprechen- Kurzfristiger Fokus (M1, M5, M15)
- Skalierung/Intraday (M5, M15, H1)
- Swing-Handel (M15, H1, H4)
- Trendhandel (H1, H4, D1)
- MTF Trend-Bestätigung (H1, H4, W1)
- Kurzfristiges Scalping/Mittelfristiger Trend (M5, H1, D1)
- Langfristiger Trend (H1, D1, W1)
Schauen wir uns an, wie der EA die Signale KAUFEN, VERKAUFEN oder NEUTRAL (BUY, SELL, NEUTRAL) erzeugt, wenn eine Schaltfläche gedrückt wird.
- Sammeln von Daten: Für jeden der drei Zeitrahmen (z. B. M1, M5 und M15) ruft der EA den Schlusskurs der letzten vollständig abgeschlossenen Kerze ab.
- Berechnung des SMA: Für jeden Zeitrahmen berechnet der EA einen einfachen gleitenden Durchschnitt (SMA) über 50 Perioden. Dieser SMA dient als Benchmark für den aktuellen Kurs.
- Liegt der Kurs über dem SMA, wird dies als Aufwärts-Zeichen gewertet und der Wert +1 zugewiesen.
- Liegt der Kurs unter dem SMA, wird dies als Abwärts-Zeichen gewertet und der Wert -1 zugewiesen.
- Wenn der Kurs dem SMA entspricht, ist das Signal neutral (0).
Kombinieren der Signale
- Die drei einzelnen Signale (eines aus jedem Zeitrahmen) werden addiert.
- Bestimmung des endgültigen Signals:
- Wenn die Summe 2 oder mehr beträgt, deutet dies auf ein starkes Aufwärts-Momentum hin. Der EA liefert das Signal für einen „KAUF“.
- Wenn die Summe -2 oder weniger beträgt, deutet dies auf ein starkes Abwärts-Momentum hin. Der EA liefert das Signal für einen „VERKAUF“.
- Andernfalls sind die Signale gemischt oder neutral, sodass der EA „NEUTRAL“ zurückgibt.
Zum besseren Verständnis des Prozesses betrachten wir das folgende Ablaufdiagramm.
Abb. 1. Ablaufdiagramm
MQL5-Implementierung
Ganz oben finden Sie die Kommentare in der Kopfzeile und die Eigenschaftsdefinitionen des EA. Diese Zeilen dienen als Metadaten für den EA, geben sein Copyright und seine Version an und verlinken ihn mit seiner Quelle. Die Direktive #property strict wird verwendet, um strengere Kompilierungsregeln zu erzwingen und so häufige Kodierungsfehler zu vermeiden.
//+------------------------------------------------------------------+ //| TrendLoom EA.mq5 | //| Copyright 2025, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, MetaQuotes Ltd." #property link "https://www.mql5.com/en/users/lynnchris" #property version "1.00" #property strict
Als Nächstes enthält der Code mehrere Header-Dateien, die Dialog-, Schaltflächen-, Label- und Panel-Steuerelemente bereitstellen. Außerdem können Sie mit den Steuerelementen für Chartobjekte Text im Chart anzeigen. Diese modulare Einbindung ermöglicht es dem EA, vorgefertigte Klassen für die Nutzeroberfläche zu verwenden.
Diese Include-Richtlinien verweisen auf Bibliotheken im Include-Ordner Ihres MetaEditors. Die Dateien im Unterordner Controls bieten integrierte Klassen für Dialoge und Schaltflächen. Sie bieten auch Klassen für Kennzeichnungen und Panels an. Dieses Design vereinfacht die Erstellung einer interaktiven Schnittstelle, ohne dass der Code umgeschrieben werden muss. Mit der Datei im Unterordner ChartObjects (ChartObjectsTxtControls.mqh) können Sie dynamischen Text im Chart anzeigen.
#include <Controls/Dialog.mqh> #include <Controls/Button.mqh> #include <Controls/Label.mqh> #include <Controls/Panel.mqh> #include <ChartObjects/ChartObjectsTxtControls.mqh> // Adjusted include path (singular folder)
Anschließend werden Konstanten für die Textausrichtung und ein Farbwert definiert. Diese Praxis verbessert die Klarheit und Wartbarkeit des Codes.
#ifndef ALIGN_LEFT #define ALIGN_LEFT 0 #endif #ifndef ALIGN_CENTER #define ALIGN_CENTER 1 #endif #ifndef ALIGN_RIGHT #define ALIGN_RIGHT 2 #endif #define clrSilver 0xC0C0C0
Der EA deklariert Eingabeparameter, die das Aussehen und die Position des Panels und seiner Schaltflächen anpassen. PanelX, PanelY und PanelWidth legen die Geometrie des Panels fest, während die Farbeingaben das visuelle Thema definieren. Die Abmessungen der Schaltflächen werden mit btnWidth, btnHeight und btnSpacing gesteuert, und mit EA können Sie sowohl das Layout als auch die Farben anpassen. Diese Konfiguration bietet Flexibilität, um die Nutzeroberfläche an Ihre Bedürfnisse anzupassen.
//---- Input parameters ----------------------------------------------- input int PanelX = 10; input int PanelY = 10; input int PanelWidth = 250; input int btnWidth = 220; input int btnHeight = 30; input int btnSpacing = 5; input color PanelBackgroundColor = clrDimGray; input color PanelHeaderColor = clrBlueViolet; input color ButtonBgColor = clrBlack; input color ButtonTextColor = clrBlueViolet; input color AnalysisTextColor = clrLime;
Arrays speichern die Schaltflächennamen und -texte, was das Aktualisieren oder Hinzufügen neuer Schaltflächen schnell und einfach macht. Dieses Design zentralisiert alle Informationen zu den Schaltflächen an einer Stelle, sodass Änderungen nur geringfügige Anpassungen erfordern. Außerdem wird die Konsistenz der Nutzeroberfläche verbessert und die Fehleranfälligkeit verringert. Die Methode bietet Flexibilität für zukünftige Erweiterungen und hält den Code sauber und übersichtlich.
//---- Button Names and Texts (7 analysis options) -------------------- string buttonNames[7] = { "btnShortTerm", "btnScalping", "btnSwing", "btnTrend", "btnMTFTrend", "btnShortScalper", "btnLongTerm" }; string buttonTexts[7] = { "Short Term Focus\n(M1, M5, M15)", "Scalping/Intraday\n(M5, M15, H1)", "Swing Trading\n(M15, H1, H4)", "Trend Trading\n(H1, H4, D1)", "MTF Trend Confirm\n(H1, H4, W1)", "Short Scalper/Mid Trend\n(M5, H1, D1)", "Long Term Trend\n(H1, D1, W1)" };
Globale Makros definieren die Namen für den Panelkopf und die Analysebeschriftung. Diese Makros gewährleisten die Konsistenz des gesamten Codes und dienen als eine einzige Quelle für diese Bezeichnungen. Durch die Zentralisierung dieser Namen wird die Aktualisierung der Komponenten des Panels einfacher und das Risiko von Tippfehlern verringert. Dieser Ansatz vereinfacht die Wartung und gewährleistet einen konsistenten, klaren Code.
// Global object names for panel header and analysis label #define PANEL_BG "PanelBG" #define PANEL_HEADER "PanelHeader" #define ANALYSIS_LABEL "AnalysisResult"
Der Code deklariert dann zwei Hilfsfunktionen: GetSMA berechnet den einfachen gleitenden Durchschnitt und AnalyzeTimeframes führt eine Marktanalyse über mehrere Zeitrahmen durch. Diese Funktionen bilden den Kern der Logik der Marktanalyse.
//--- Helper function declarations double GetSMA(string symbol, ENUM_TIMEFRAMES timeframe, int period, int shift); string AnalyzeTimeframes(ENUM_TIMEFRAMES tf1, ENUM_TIMEFRAMES tf2, ENUM_TIMEFRAMES tf3);
Die nutzerdefinierte Klasse CTrendLoomPanel wird von CAppDialog abgeleitet. Sie gruppiert alle Elemente der Nutzeroberfläche, wie z. B. die Kopfzeile, das Hauptfenster, die Schaltflächen und die Ergebnisliste. Dieses Design schafft eine modulare Schnittstelle, die leichter zu verwalten und zu erweitern ist.
Erstellen des Panels
Die Methode CreateTrendPanel erstellt zunächst ein Dialogfenster. Anschließend wird ein Kopftext mit nutzerdefiniertem Text, Farbe, Schriftgröße und Schriftart erstellt. Die Ausrichtung wird mit der Funktion ObjectSetInteger festgelegt.
bool CreateTrendPanel(const long chart, const string name, const int x1, const int y1, const int x2, const int y2) { if(!CAppDialog::Create(chart, name, 0, x1, y1, x2, y2)) { Print("Failed to create TrendLoom dialog."); return false; } if(!m_lblHeader.Create(0, "TrendLoomHeader", 0, 10, 10, x2 - x1 - 20, 30)) { Print("Failed to create header label."); return false; } m_lblHeader.Text("TrendLoom EA"); m_lblHeader.Color(PanelHeaderColor); m_lblHeader.FontSize(14); m_lblHeader.Font("Segoe UI"); Add(m_lblHeader); if(!ObjectSetInteger(0L, m_lblHeader.Name(), OBJPROP_ALIGN, (long)ALIGN_CENTER)) Print("Failed to set header alignment");
Die Methode fährt fort mit der Erstellung des Hauptpanels und der dynamischen Berechnung seiner Abmessungen. Anschließend werden die einzelnen Schaltflächen erstellt und nacheinander positioniert. Schließlich wird ein Ergebnisetikett unter den Schaltflächen hinzugefügt, um die Analyseergebnisse anzuzeigen.
Handhabung von Ereignissen
Die Methode OnEvent verarbeitet Nutzerinteraktionen. Wenn eine Schaltfläche angeklickt wird, ruft sie AnalyzeTimeframes mit den entsprechenden Zeitrahmenparametern auf. Das Analyseergebnis wird auf dem Bedienfeld aktualisiert und eine Warnmeldung wird angezeigt.
bool OnEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { if(sparam == "btnShortTerm") { string res = AnalyzeTimeframes(PERIOD_M1, PERIOD_M5, PERIOD_M15); string out = "Short Term Focus: " + res; UpdateResults(out); Alert(out); return true; } else if(sparam == "btnScalping") { string res = AnalyzeTimeframes(PERIOD_M5, PERIOD_M15, PERIOD_H1); string out = "Scalping/Intraday: " + res; UpdateResults(out); Alert(out); return true; } // Additional conditions for other buttons return false; }
Aktualisierung der Nutzeroberfläche
Mit der Methode UpdateResults wird das Ergebnis mit neuen Analysedaten aktualisiert. Anschließend wird ChartRedraw aufgerufen, damit die aktualisierten Informationen sofort angezeigt werden.
void UpdateResults(const string &result) { m_lblResults.Text("Analysis Result: " + result); ChartRedraw(); }
Zentrale Analysefunktionen
Berechnung des einfachen gleitenden Durchschnitts (SMA)
Die Funktion GetSMA berechnet den SMA, indem sie ein Indikator-Handle mit der Funktion iMA erstellt. Es kopiert die SMA-Werte aus dem Indikatorpuffer und gibt dann den Handle frei, um Ressourcen freizugeben.
double GetSMA(string symbol, ENUM_TIMEFRAMES timeframe, int period, int shift) { int handle = iMA(symbol, timeframe, period, 0, MODE_SMA, PRICE_CLOSE); if(handle == INVALID_HANDLE) { Print("Failed to create iMA handle for timeframe ", timeframe); return 0.0; } double sma[]; if(CopyBuffer(handle, 0, shift, 1, sma) <= 0) { Print("Failed to copy buffer for timeframe ", timeframe); IndicatorRelease(handle); return 0.0; } double result = sma[0]; IndicatorRelease(handle); return result; }
Analysieren mehrerer Zeitrahmen
Die Funktion AnalyzeTimeframes ruft den Schlusskurs und den SMA für drei Zeitrahmen ab und weist ein Aufwärtssignal zu, wenn der Kurs den SMA übersteigt, oder ein Aufwärtssignal, wenn er darunter fällt. Die einzelnen Signale werden addiert und ergeben eine endgültige Empfehlung: KAUFEN, wenn die Summe 2 oder höher ist, VERKAUFEN, wenn sie -2 oder niedriger ist und ansonsten NEUTRAL. Jeder Zeitrahmen wird unabhängig ausgewertet, um einen ausgewogenen Überblick über die Markttrends zu erhalten, während der Shift-Parameter sicherstellt, dass nur die letzte abgeschlossene Kerze für die Analyse verwendet wird. Durch die Kombination von Signalen aus mehreren Zeitrahmen werden die Auswirkungen des vorübergehenden Marktrauschens verringert, und durch die Anpassung der SMA-Periode wird die Empfindlichkeit der Handelssignale weiter verfeinert.
string AnalyzeTimeframes(ENUM_TIMEFRAMES tf1, ENUM_TIMEFRAMES tf2, ENUM_TIMEFRAMES tf3) { int period = 50; int shift = 1; // last completed candle double price1 = iClose(_Symbol, tf1, shift); double sma1 = GetSMA(_Symbol, tf1, period, shift); int signal1 = (price1 > sma1) ? 1 : (price1 < sma1 ? -1 : 0); double price2 = iClose(_Symbol, tf2, shift); double sma2 = GetSMA(_Symbol, tf2, period, shift); int signal2 = (price2 > sma2) ? 1 : (price2 < sma2 ? -1 : 0); double price3 = iClose(_Symbol, tf3, shift); double sma3 = GetSMA(_Symbol, tf3, period, shift); int signal3 = (price3 > sma3) ? 1 : (price3 < sma3 ? -1 : 0); int sum = signal1 + signal2 + signal3; if(sum >= 2) return "BUY"; else if(sum <= -2) return "SELL"; else return "NEUTRAL"; }Die Lebenszyklusfunktionen des EA übernehmen die Initialisierung, die Bereinigung und die Ereignisverarbeitung. Die Funktion OnInit erstellt das TrendLoom-Panel unter Verwendung der Eingabeparameter. Schlägt die Erstellung eines Panels fehl, gibt der EA einen Initialisierungsfehler zurück.
int OnInit() { if(!TrendPanel.CreateTrendPanel(0, "TrendLoom Panel", PanelX, PanelY, PanelX + PanelWidth + 20, PanelY + 400)) { Print("Failed to create TrendLoom Panel."); return INIT_FAILED; } return INIT_SUCCEEDED; }
Die Funktion OnDeinit löscht das Panel, wenn der EA entfernt oder das Chart geschlossen wird.
void OnDeinit(const int reason) { TrendPanel.Destroy(reason); }
Schließlich leitet die Funktion OnChartEvent Chartereignisse an den Event-Handler des Panels weiter, sodass die Schnittstelle reaktionsfähig bleibt.
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { TrendPanel.ChartEvent(id, lparam, dparam, sparam); }
In Ihrem MetaEditor werden die erforderlichen Dateien im Include-Ordner gespeichert. Um auf die angegebenen Dateien zuzugreifen, verweisen Sie auf die Unterordner, die in den folgenden Charts dargestellt sind. Diese Organisation stellt sicher, dass der Compiler die Dialog-, Schaltflächen-, Label- und Panel-Steuerungsdateien im Ordner include/Controls und die Chartobjektsteuerungen im Ordner include/ChartObjects findet.
#include <Controls/Dialog.mqh> #include <Controls/Button.mqh> #include <Controls/Label.mqh> #include <Controls/Panel.mqh> #include <ChartObjects/ChartObjectsTxtControls.mqh> // Adjusted include path (singular folder)
Schritt 1
Abb. 2. Schritt 1
Schritt 2
Abb. 3. Schritt 2
MQL5 Code
//+------------------------------------------------------------------+ //| TrendLoom EA.mq5 | //| Copyright 2025, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, MetaQuotes Ltd." #property link "https://www.mql5.com/en/users/lynnchris" #property version "1.00" #property strict #include <Controls/Dialog.mqh> #include <Controls/Button.mqh> #include <Controls/Label.mqh> #include <Controls/Panel.mqh> #include <ChartObjects/ChartObjectsTxtControls.mqh> // Adjusted include path (singular folder) // Define alignment constants if not already defined #ifndef ALIGN_LEFT #define ALIGN_LEFT 0 #endif #ifndef ALIGN_CENTER #define ALIGN_CENTER 1 #endif #ifndef ALIGN_RIGHT #define ALIGN_RIGHT 2 #endif #define clrSilver 0xC0C0C0 //---- Input parameters ----------------------------------------------- input int PanelX = 10; // Top-left X coordinate of panel input int PanelY = 10; // Top-left Y coordinate of panel input int PanelWidth = 250; // Panel width (for longer text) input int btnWidth = 220; // Button width input int btnHeight = 30; // Button height input int btnSpacing = 5; // Spacing between buttons input color PanelBackgroundColor = clrDimGray; // Panel background color input color PanelHeaderColor = clrBlueViolet; // Panel header text color input color ButtonBgColor = clrBlack; // Button background color input color ButtonTextColor = clrBlueViolet; // Button text color input color AnalysisTextColor = clrLime; // Analysis result text color //---- Button Names and Texts (7 analysis options) -------------------- string buttonNames[7] = { "btnShortTerm", "btnScalping", "btnSwing", "btnTrend", "btnMTFTrend", "btnShortScalper", "btnLongTerm" }; string buttonTexts[7] = { "Short Term Focus\n(M1, M5, M15)", "Scalping/Intraday\n(M5, M15, H1)", "Swing Trading\n(M15, H1, H4)", "Trend Trading\n(H1, H4, D1)", "MTF Trend Confirm\n(H1, H4, W1)", "Short Scalper/Mid Trend\n(M5, H1, D1)", "Long Term Trend\n(H1, D1, W1)" }; // Global object names for panel header and analysis label #define PANEL_BG "PanelBG" #define PANEL_HEADER "PanelHeader" #define ANALYSIS_LABEL "AnalysisResult" //--- Helper function declarations double GetSMA(string symbol, ENUM_TIMEFRAMES timeframe, int period, int shift); string AnalyzeTimeframes(ENUM_TIMEFRAMES tf1, ENUM_TIMEFRAMES tf2, ENUM_TIMEFRAMES tf3); //------------------------------------------------------------------------------ // CTrendLoomPanel class - A modern, modular panel for TrendLoom EA //------------------------------------------------------------------------------ class CTrendLoomPanel : public CAppDialog { private: CLabel m_lblHeader; CPanel m_panelMain; CButton m_btnShortTerm; CButton m_btnScalping; CButton m_btnSwing; CButton m_btnTrend; CButton m_btnMTFTrend; CButton m_btnShortScalper; CButton m_btnLongTerm; CLabel m_lblResults; public: // Create the TrendLoom Panel dialog bool CreateTrendPanel(const long chart, const string name, const int x1, const int y1, const int x2, const int y2) { if(!CAppDialog::Create(chart, name, 0, x1, y1, x2, y2)) { Print("Failed to create TrendLoom dialog."); return false; } // Create header label if(!m_lblHeader.Create(0, "TrendLoomHeader", 0, 10, 10, x2 - x1 - 20, 30)) { Print("Failed to create header label."); return false; } m_lblHeader.Text("TrendLoom EA"); m_lblHeader.Color(PanelHeaderColor); m_lblHeader.FontSize(14); m_lblHeader.Font("Segoe UI"); Add(m_lblHeader); // Set header text alignment to center using ObjectSetInteger if(!ObjectSetInteger(0L, m_lblHeader.Name(), OBJPROP_ALIGN, (long)ALIGN_CENTER)) Print("Failed to set header alignment"); // Create main panel background int panelBottom = 50 + (btnHeight + btnSpacing) * 7 + btnSpacing; if(!m_panelMain.Create(0, "TrendLoomPanel", 0, 10, 50, x2 - x1 - 10, panelBottom)) { Print("Failed to create main panel."); return false; } m_panelMain.Color(PanelBackgroundColor); m_panelMain.BorderType(BORDER_RAISED); m_panelMain.ColorBorder(clrSilver); Add(m_panelMain); // Starting coordinates for buttons int btnX = 20; // relative to dialog int btnY = 60; int buttonWidth = btnWidth; int buttonHeight = btnHeight; // Create each button with a modern look if(!m_btnShortTerm.Create(0, buttonNames[0], 0, btnX, btnY, btnX + buttonWidth, btnY + buttonHeight)) return false; m_btnShortTerm.Text(buttonTexts[0]); m_btnShortTerm.Font("Segoe UI"); m_btnShortTerm.FontSize(12); m_btnShortTerm.Color(ButtonBgColor); Add(m_btnShortTerm); btnY += buttonHeight + btnSpacing; if(!m_btnScalping.Create(0, buttonNames[1], 0, btnX, btnY, btnX + buttonWidth, btnY + buttonHeight)) return false; m_btnScalping.Text(buttonTexts[1]); m_btnScalping.Font("Segoe UI"); m_btnScalping.FontSize(12); m_btnScalping.Color(ButtonBgColor); Add(m_btnScalping); btnY += buttonHeight + btnSpacing; if(!m_btnSwing.Create(0, buttonNames[2], 0, btnX, btnY, btnX + buttonWidth, btnY + buttonHeight)) return false; m_btnSwing.Text(buttonTexts[2]); m_btnSwing.Font("Segoe UI"); m_btnSwing.FontSize(12); m_btnSwing.Color(ButtonBgColor); Add(m_btnSwing); btnY += buttonHeight + btnSpacing; if(!m_btnTrend.Create(0, buttonNames[3], 0, btnX, btnY, btnX + buttonWidth, btnY + buttonHeight)) return false; m_btnTrend.Text(buttonTexts[3]); m_btnTrend.Font("Segoe UI"); m_btnTrend.FontSize(12); m_btnTrend.Color(ButtonBgColor); Add(m_btnTrend); btnY += buttonHeight + btnSpacing; if(!m_btnMTFTrend.Create(0, buttonNames[4], 0, btnX, btnY, btnX + buttonWidth, btnY + buttonHeight)) return false; m_btnMTFTrend.Text(buttonTexts[4]); m_btnMTFTrend.Font("Segoe UI"); m_btnMTFTrend.FontSize(12); m_btnMTFTrend.Color(ButtonBgColor); Add(m_btnMTFTrend); btnY += buttonHeight + btnSpacing; if(!m_btnShortScalper.Create(0, buttonNames[5], 0, btnX, btnY, btnX + buttonWidth, btnY + buttonHeight)) return false; m_btnShortScalper.Text(buttonTexts[5]); m_btnShortScalper.Font("Segoe UI"); m_btnShortScalper.FontSize(12); m_btnShortScalper.Color(ButtonBgColor); Add(m_btnShortScalper); btnY += buttonHeight + btnSpacing; if(!m_btnLongTerm.Create(0, buttonNames[6], 0, btnX, btnY, btnX + buttonWidth, btnY + buttonHeight)) return false; m_btnLongTerm.Text(buttonTexts[6]); m_btnLongTerm.Font("Segoe UI"); m_btnLongTerm.FontSize(12); m_btnLongTerm.Color(ButtonBgColor); Add(m_btnLongTerm); btnY += buttonHeight + btnSpacing; // Create results label below the buttons if(!m_lblResults.Create(0, "TrendResults", 0, btnX, btnY, btnX + buttonWidth, btnY + 30)) return false; m_lblResults.Text("Analysis Result: [Waiting for Input]"); m_lblResults.Font("Segoe UI"); m_lblResults.FontSize(12); m_lblResults.Color(AnalysisTextColor); Add(m_lblResults); // Set results text alignment to left using ObjectSetInteger if(!ObjectSetInteger(0L, m_lblResults.Name(), OBJPROP_ALIGN, (long)ALIGN_LEFT)) Print("Failed to set results alignment"); Show(); return true; } // Process events (button clicks) bool OnEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { if(sparam == "btnShortTerm") { string res = AnalyzeTimeframes(PERIOD_M1, PERIOD_M5, PERIOD_M15); string out = "Short Term Focus: " + res; UpdateResults(out); Alert(out); return true; } else if(sparam == "btnScalping") { string res = AnalyzeTimeframes(PERIOD_M5, PERIOD_M15, PERIOD_H1); string out = "Scalping/Intraday: " + res; UpdateResults(out); Alert(out); return true; } else if(sparam == "btnSwing") { string res = AnalyzeTimeframes(PERIOD_M15, PERIOD_H1, PERIOD_H4); string out = "Swing Trading: " + res; UpdateResults(out); Alert(out); return true; } else if(sparam == "btnTrend") { string res = AnalyzeTimeframes(PERIOD_H1, PERIOD_H4, PERIOD_D1); string out = "Trend Trading: " + res; UpdateResults(out); Alert(out); return true; } else if(sparam == "btnMTFTrend") { string res = AnalyzeTimeframes(PERIOD_H1, PERIOD_H4, PERIOD_W1); string out = "MTF Trend Confirm: " + res; UpdateResults(out); Alert(out); return true; } else if(sparam == "btnShortScalper") { string res = AnalyzeTimeframes(PERIOD_M5, PERIOD_H1, PERIOD_D1); string out = "Short Scalper/Mid Trend: " + res; UpdateResults(out); Alert(out); return true; } else if(sparam == "btnLongTerm") { string res = AnalyzeTimeframes(PERIOD_H1, PERIOD_D1, PERIOD_W1); string out = "Long Term Trend: " + res; UpdateResults(out); Alert(out); return true; } return false; } bool ChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { return OnEvent(id, lparam, dparam, sparam); } // Update the results label and refresh the chart void UpdateResults(const string &result) { m_lblResults.Text("Analysis Result: " + result); ChartRedraw(); } }; // Global instance of the TrendLoom Panel CTrendLoomPanel TrendPanel; //------------------------------------------------------------------------------ // Helper functions (core analysis logic) //------------------------------------------------------------------------------ double GetSMA(string symbol, ENUM_TIMEFRAMES timeframe, int period, int shift) { int handle = iMA(symbol, timeframe, period, 0, MODE_SMA, PRICE_CLOSE); if(handle == INVALID_HANDLE) { Print("Failed to create iMA handle for timeframe ", timeframe); return 0.0; } double sma[]; // dynamic array to store SMA values if(CopyBuffer(handle, 0, shift, 1, sma) <= 0) { Print("Failed to copy buffer for timeframe ", timeframe); IndicatorRelease(handle); return 0.0; } double result = sma[0]; IndicatorRelease(handle); return result; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ string AnalyzeTimeframes(ENUM_TIMEFRAMES tf1, ENUM_TIMEFRAMES tf2, ENUM_TIMEFRAMES tf3) { int period = 50; int shift = 1; // last completed candle double price1 = iClose(_Symbol, tf1, shift); double sma1 = GetSMA(_Symbol, tf1, period, shift); int signal1 = (price1 > sma1) ? 1 : (price1 < sma1 ? -1 : 0); double price2 = iClose(_Symbol, tf2, shift); double sma2 = GetSMA(_Symbol, tf2, period, shift); int signal2 = (price2 > sma2) ? 1 : (price2 < sma2 ? -1 : 0); double price3 = iClose(_Symbol, tf3, shift); double sma3 = GetSMA(_Symbol, tf3, period, shift); int signal3 = (price3 > sma3) ? 1 : (price3 < sma3 ? -1 : 0); int sum = signal1 + signal2 + signal3; if(sum >= 2) return "BUY"; else if(sum <= -2) return "SELL"; else return "NEUTRAL"; } //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { if(!TrendPanel.CreateTrendPanel(0, "TrendLoom Panel", PanelX, PanelY, PanelX + PanelWidth + 20, PanelY + 400)) { Print("Failed to create TrendLoom Panel."); return INIT_FAILED; } return INIT_SUCCEEDED; } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { TrendPanel.Destroy(reason); } //+------------------------------------------------------------------+ //| Chart Event Handler | //+------------------------------------------------------------------+ void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { TrendPanel.ChartEvent(id, lparam, dparam, sparam); } //+------------------------------------------------------------------+
Ergebnisse
Es ist von entscheidender Bedeutung für jeden Händler, seine Systeme gründlich zu testen, bevor er sie im Live-Handel einsetzt. Das Testen beinhaltet Backtests mit historischen Daten, um zu sehen, wie das System ohne Risiko abgeschnitten hätte. Sie können auch Demo-Live-Konten verwenden, um die tatsächliche Leistung in Echtzeit zu beobachten. Dieser Prozess hilft Ihnen bei der Feinabstimmung und Entwicklung eines zuverlässigeren Tools, das Sie getrost auf einem Live-Konto einsetzen können. Ich persönlich ziehe es vor, viel Zeit mit dem Testen und Verfeinern des EA zu verbringen, um robustere Ergebnisse zu erzielen.
In diesem Abschnitt stelle ich die Testergebnisse des EA vor, der auf dem Chart läuft. Ich habe es an der Volatilität 75 (1s) getestet und es hat wunderbare und profitable Ergebnisse geliefert. Jede Taste funktioniert wie vorgesehen, und die Analyseergebnisse werden fast sofort aktualisiert, wenn Sie eine Taste drücken. Schauen wir uns den ersten Test unten an.
Abb. 4. Volatilität 75 (1s) Test
Das folgende Chart veranschaulicht, wie sich der Markt nach der Ausführung eines Handels auf der Grundlage des bereitgestellten Signals verhalten hat. Dieses Chart setzt den im obigen GIF gezeigten Handel fort. Ich habe den M1-Zeitrahmen verwendet, um einen breiteren Überblick über die Handelsgeschäfte zu erhalten.
Abb. 5. V 75 (1s) Prüfung
Schlussfolgerung
Nachdem ich den EA erstellt und getestet habe, kann ich getrost bestätigen, dass er sich positiv auf die Marktanalyse auswirkt. Die schnelle Signalverarbeitung und die allgemeine Trendauswertung haben bei den Volatilitätsindizes gute Ergebnisse erzielt. Dieses Instrument dient jedoch als ergänzendes Hilfsmittel und nicht als endgültiger Signalgeber. Ich möchte Sie ermutigen, das Programm gründlich zu testen und die Parameter Ihren Wünschen entsprechend anzupassen. Sie können sie auch weiter verändern, um das Aussehen der Schaltflächen anzupassen. Verwenden Sie es, um Ihre Gesamtstrategie zu bestätigen, ich habe gesehen, dass es auf diese Weise effektiv ist.
Datum | Name des Werkzeugs | Beschreibung | Version | Aktualisierungen | Hinweis |
---|---|---|---|---|---|
01/10/24 | Chart Projector | Skript zur Überlagerung der Kursentwicklung des Vortages mit Geistereffekt. | 1.0 | Erste Veröffentlichung | Toolkit Nummer 1 |
18/11/24 | Analytical Comment | Er liefert Informationen zum Vortag in Tabellenform und nimmt die zukünftige Marktentwicklung vorweg. | 1.0 | Erste Veröffentlichung | Toolkit Nummer 2 |
27/11/24 | Analytics Master | Reguläre Aktualisierung der Marktmetriken alle zwei Stunden. | 1.01 | Zweite Veröffentlichung | Toolkit Nummer 3 |
02/12/24 | Analytics Forecaster | Reguläre Aktualisierung der Marktmetriken alle zwei Stunden mit Telegram-Integration. | 1.1 | Dritte Auflage | Toolkit Nummer 4 |
09/12/24 | Volatility Navigator | Der EA analysiert die Marktbedingungen anhand der Indikatoren Bollinger Bands, RSI und ATR. | 1.0 | Erste Veröffentlichung | Toolkit Nummer 5 |
19/12/24 | Mean Reversion Signal Reaper | Analysiert den Markt anhand der Strategie „Umkehr zur Mitte“ und liefert Signale. | 1.0 | Erste Veröffentlichung | Toolkit Nummer 6 |
9/01/25 | Signal-Impuls | Analysator für mehrere Zeitrahmen. | 1.0 | Erste Veröffentlichung | Toolkit Nummer 7 |
17/01/25 | Metrics Board | Bedienfeld mit Taste für die Analyse. | 1.0 | Erste Veröffentlichung | Toolkit Nummer 8 |
21/01/25 | External Flow | Analytik durch externe Bibliotheken. | 1.0 | Erste Veröffentlichung | Toolkit Nummer 9 |
27/01/25 | VWAP | Volumengewichteter Durchschnittspreis | 1.3 | Erste Veröffentlichung | Toolkit Nummer 10 |
02/02/25 | Heikin Ashi | Trendglättung und Identifizierung von Umkehrsignalen | 1.0 | Erste Veröffentlichung | Toolkit Nummer 11 |
04/02/25 | FibVWAP | Signalerzeugung durch Python-Analyse | 1.0 | Erste Veröffentlichung | Toolkit Nummer 12 |
14/02/25 | RSI DIVERGENCE | Kursentwicklung versus RSI-Divergenzen | 1.0 | Erste Veröffentlichung | Toolkit Nummer 13 |
17/02/25 | Parabolischer Stopp und Umkehr (PSAR) | Automatisierung der PSAR-Strategie | 1.0 | Erste Veröffentlichung | Toolkit Nummer 14 |
20/02/25 | Quarters Drawer Script | Einzeichnen der Viertel- oder Quarter-Ebenen in die Tabelle | 1.0 | Erste Veröffentlichung | Toolkit Nummer 15 |
27/02/25 | Intrusion Detector | Erkennen und warnen, wenn der Preis ein Quarter-Niveau erreicht | 1.0 | Erste Veröffentlichung | Toolkit Nummer 16 |
27/02/25 | TrendLoom Tool | Analysepanel für mehrere Zeitrahmen | 1.0 | Erste Veröffentlichung | Toolkit Nummer 17 |
Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/17329





- 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.
Wow, phantastisch, ich kann sehen, dass da eine Menge Mühe hineingesteckt wurde. Danke, dass Sie Ihren Ansatz und Ihren Code mit uns teilen.