English
preview
MQL5-Handelswerkzeuge (Teil 3): Aufbau eines Multi-Timeframe Scanner Dashboards für den strategischen Handel

MQL5-Handelswerkzeuge (Teil 3): Aufbau eines Multi-Timeframe Scanner Dashboards für den strategischen Handel

MetaTrader 5Handel |
34 0
Allan Munene Mutiiria
Allan Munene Mutiiria

Einführung

In unserem letzten Artikel, Teil 2, haben wir ein Handels-Tool in MetaQuotes Language 5 (MQL5) mit dynamischem visuellem Feedback für verbesserte Interaktivität erweitert. Jetzt konzentrieren wir uns auf den Aufbau eines Multi-Timeframe-Scanner-Dashboards, das Handelssignale in Echtzeit für strategische Entscheidungen liefert. Wir stellen eine rasterbasierte Schnittstelle mit indikatorgesteuerten Signalen und einer Schaltfläche zum Schließen vor und behandeln diese Fortschritte in den folgenden Unterthemen:

  1. Der Plan des Scanner Dashboards
  2. Implementation in MQL5
  3. Backtests
  4. Schlussfolgerung

Diese Abschnitte führen uns zur Erstellung eines intuitiven und leistungsstarken Dashboards für den Handel.


Der Plan des Scanner Dashboards

Unser Ziel ist es, einen Multi-Timeframe-Scanner zu entwickeln, der klare Handelssignale in Echtzeit liefert, um die strategische Entscheidungsfindung zu verbessern. Das Dashboard wird ein Rasterlayout aufweisen, das Kauf- und Verkaufssignale über mehrere Zeitrahmen hinweg anzeigt, sodass wir die Marktbedingungen schnell beurteilen können, ohne die Charts wechseln zu müssen. Es wird eine Schaltfläche zum Schließen enthalten sein, die ein einfaches Verlassen des Panels ermöglicht, um eine saubere und flexible Nutzererfahrung zu gewährleisten, die sich an unsere Handelsanforderungen anpasst.

Wir werden Signale von Schlüsselindikatoren wie dem Relative Strength Index (RSI), Stochastic Oscillator (STOCH), Commodity Channel Index (CCI), Average Directional Index (ADX) und Awesome Oscillator (AO) einbeziehen, die dazu dienen, potenzielle Handelsmöglichkeiten mit anpassbaren Schwellenwerten zu identifizieren. Die Wahl der zu verwendenden Indikatoren oder Preisaktionsdaten liegt jedoch bei Ihnen. Dieses Setup hilft uns, Trends und Umkehrungen über verschiedene Zeitrahmen hinweg zu erkennen und unterstützt sowohl kurzfristige als auch langfristige Strategien. Unser Ziel ist ein schlankes, intuitives Tool, das verwertbare Erkenntnisse liefert und gleichzeitig nutzerfreundlich ist und den Weg für künftige Erweiterungen wie automatische Warnmeldungen oder zusätzliche Indikatoren ebnet. Nachstehend finden Sie eine Visualisierung dessen, was wir erreichen wollen.

UMSETZUNGSPLAN


Implementation in MQL5

Um das Programm in MQL5 zu erstellen, müssen wir die Programm-Metadaten definieren und dann einige Objektnamenskonstanten festlegen, die uns helfen, auf die Dashboard-Objekte zu verweisen und sie einfach zu verwalten.

//+------------------------------------------------------------------+
//|                             TimeframeScanner Dashboard EA.mq5    |
//|                           Copyright 2025, Allan Munene Mutiiria. |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, Allan Munene Mutiiria."
#property link      "https://t.me/Forex_Algo_Trader"
#property version   "1.00"

// Define identifiers and properties for UI elements
#define MAIN_PANEL              "PANEL_MAIN"                     //--- Main panel rectangle identifier
#define HEADER_PANEL            "PANEL_HEADER"                   //--- Header panel rectangle identifier
#define HEADER_PANEL_ICON       "PANEL_HEADER_ICON"              //--- Header icon label identifier
#define HEADER_PANEL_TEXT       "PANEL_HEADER_TEXT"              //--- Header title label identifier
#define CLOSE_BUTTON            "BUTTON_CLOSE"                   //--- Close button identifier
#define SYMBOL_RECTANGLE        "SYMBOL_HEADER"                  //--- Symbol rectangle identifier
#define SYMBOL_TEXT             "SYMBOL_TEXT"                    //--- Symbol text label identifier
#define TIMEFRAME_RECTANGLE     "TIMEFRAME_"                     //--- Timeframe rectangle prefix
#define TIMEFRAME_TEXT          "TIMEFRAME_TEXT_"                //--- Timeframe text label prefix
#define HEADER_RECTANGLE        "HEADER_"                        //--- Header rectangle prefix
#define HEADER_TEXT             "HEADER_TEXT_"                   //--- Header text label prefix
#define RSI_RECTANGLE           "RSI_"                           //--- RSI rectangle prefix
#define RSI_TEXT                "RSI_TEXT_"                      //--- RSI text label prefix
#define STOCH_RECTANGLE         "STOCH_"                         //--- Stochastic rectangle prefix
#define STOCH_TEXT              "STOCH_TEXT_"                    //--- Stochastic text label prefix
#define CCI_RECTANGLE           "CCI_"                           //--- CCI rectangle prefix
#define CCI_TEXT                "CCI_TEXT_"                      //--- CCI text label prefix
#define ADX_RECTANGLE           "ADX_"                           //--- ADX rectangle prefix
#define ADX_TEXT                "ADX_TEXT_"                      //--- ADX text label prefix
#define AO_RECTANGLE            "AO_"                            //--- AO rectangle prefix
#define AO_TEXT                 "AO_TEXT_"                       //--- AO text label prefix
#define BUY_RECTANGLE           "BUY_"                           //--- Buy rectangle prefix
#define BUY_TEXT                "BUY_TEXT_"                      //--- Buy text label prefix
#define SELL_RECTANGLE          "SELL_"                          //--- Sell rectangle prefix
#define SELL_TEXT               "SELL_TEXT_"                     //--- Sell text label prefix
#define WIDTH_TIMEFRAME         90                               //--- Width of timeframe and symbol rectangles
#define WIDTH_INDICATOR         70                               //--- Width of indicator rectangles
#define WIDTH_SIGNAL            90                               //--- Width of BUY/SELL signal rectangles
#define HEIGHT_RECTANGLE        25                               //--- Height of all rectangles
#define COLOR_WHITE             clrWhite                         //--- White color for text and backgrounds
#define COLOR_BLACK             clrBlack                         //--- Black color for borders and text
#define COLOR_LIGHT_GRAY        C'230,230,230'                   //--- Light gray color for signal backgrounds
#define COLOR_DARK_GRAY         C'105,105,105'                   //--- Dark gray color for indicator backgrounds

Wir beginnen damit, das Gerüst der Nutzeroberfläche für unser Multi-Timeframe-Scanner-Dashboard zu erstellen, indem wir die Direktive #define verwenden, um Konstanten wie „MAIN_PANEL“ und „HEADER_PANEL“ für die Rechtecke des Haupt- und des Kopfbereichs sowie „HEADER_PANEL_ICON“, „HEADER_PANEL_TEXT“ und „CLOSE_BUTTON“ für das Symbol, den Titel und die Schaltfläche zum Schließen des Kopfbereichs.

Wir definieren Bezeichner für die Gitterstruktur des Dashboards. Für das Symbol werden die Präfixe „SYMBOL_RECTANGLE“ und „SYMBOL_TEXT“ gesetzt, während die Präfixe „TIMEFRAME_RECTANGLE“ und „TIMEFRAME_TEXT“ Zeitrahmenzeilen behandeln. Wir verwenden die Präfixe „HEADER_RECTANGLE“ und „HEADER_TEXT“ für Spaltenüberschriften, und Präfixe wie „RSI_RECTANGLE“, „STOCH_RECTANGLE“ und „BUY_RECTANGLE“ mit den entsprechenden „RSI_TEXT“, „STOCH_TEXT“ und „BUY_TEXT“ für Indikator- und Signalzellen.

Wir konfigurieren Größen mit „WIDTH_TIMEFRAME“ (90 Pixel), „WIDTH_INDICATOR“ (70 Pixel), „WIDTH_SIGNAL“ (90 Pixel) und „HEIGHT_RECTANGLE“ (25 Pixel). Wir definieren Farben mit „COLOR_WHITE“ und „COLOR_BLACK“ für Text und Ränder, „COLOR_LIGHT_GRAY“ („C'230,230,230'“) für Signalhintergründe und „COLOR_DARK_GRAY“ („C'105,105,105'“) für Indikatoren, um ein einheitliches und klares Layout zu gewährleisten. Anschließend müssen wir einige weitere globale Variablen definieren, die wir im gesamten Programm verwenden werden.

bool panel_is_visible = true;                                    //--- Flag to control panel visibility

// Define the timeframes to be used
ENUM_TIMEFRAMES timeframes_array[] = {PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M20, PERIOD_M30, 
                                      PERIOD_H1, PERIOD_H2, PERIOD_H3, PERIOD_H4, PERIOD_H8, 
                                      PERIOD_H12, PERIOD_D1, PERIOD_W1}; //--- Array of timeframes for scanning

// Global variables for indicator values
double rsi_values[];                                             //--- Array to store RSI values
double stochastic_values[];                                      //--- Array to store Stochastic signal line values
double cci_values[];                                             //--- Array to store CCI values
double adx_values[];                                             //--- Array to store ADX values
double ao_values[];                                              //--- Array to store AO values

Hier deklarieren wir die boolesche Variable panel_is_visible“ und setzen sie auf true, was bestimmt, ob das Dashboard im Chart angezeigt wird. Mit diesem Flag können wir die Sichtbarkeit des Dashboards nach Bedarf umschalten, insbesondere wenn wir keine Datenaktualisierungen benötigen. Dann definieren wir das Array „timeframes_array“ unter Verwendung des Typs ENUM_TIMEFRAMES, das Zeiträume von „PERIOD_M1“ (1 Minute) bis „PERIOD_W1“ (wöchentlich) auflistet. Dieses Array legt die Zeiträume fest, die das Dashboard analysiert, und ermöglicht es uns, Marktsignale über mehrere Zeithorizonte hinweg auf strukturierte Weise zu überprüfen. Wenn Sie keine brauchen oder eine Verdrehung benötigen, ändern Sie einfach die Enumerationen.

Zum Speichern von Indikatordaten werden doppelte Arrays „rsi_values“, „stochastic_values“, „cci_values“, „adx_values“ und „ao_values“ angelegt. Diese Arrays enthalten die berechneten Werte für den Relative Strength Index, den Stochastic Oscillator, den Commodity Channel Index, den Average Directional Index bzw. den Awesome Oscillator, sodass wir die Handelssignale für jeden Zeitrahmen effizient verarbeiten und anzeigen können. Wir können nun einige Hilfsfunktionen definieren, mit denen wir die Richtung und die Abschneidung des abgerufenen Chartsymbols wie folgt bestimmen.

//+------------------------------------------------------------------+
//| Truncate timeframe enum to display string                        |
//+------------------------------------------------------------------+
string truncate_timeframe_name(int timeframe_index)              //--- Function to format timeframe name
{
   string timeframe_string = StringSubstr(EnumToString(timeframes_array[timeframe_index]), 7); //--- Extract timeframe name
   return timeframe_string;                                      //--- Return formatted name
}

//+------------------------------------------------------------------+
//| Calculate signal strength for buy/sell                           |
//+------------------------------------------------------------------+
string calculate_signal_strength(double rsi, double stochastic, double cci, double adx, double ao, bool is_buy) //--- Function to compute signal strength
{
   int signal_strength = 0;                                      //--- Initialize signal strength counter
   
   if(is_buy && rsi < 40) signal_strength++;                     //--- Increment for buy if RSI is oversold
   else if(!is_buy && rsi > 60) signal_strength++;               //--- Increment for sell if RSI is overbought
   
   if(is_buy && stochastic < 40) signal_strength++;              //--- Increment for buy if Stochastic is oversold
   else if(!is_buy && stochastic > 60) signal_strength++;        //--- Increment for sell if Stochastic is overbought
   
   if(is_buy && cci < -70) signal_strength++;                    //--- Increment for buy if CCI is oversold
   else if(!is_buy && cci > 70) signal_strength++;               //--- Increment for sell if CCI is overbought
   
   if(adx > 40) signal_strength++;                               //--- Increment if ADX indicates strong trend
   
   if(is_buy && ao > 0) signal_strength++;                       //--- Increment for buy if AO is positive
   else if(!is_buy && ao < 0) signal_strength++;                 //--- Increment for sell if AO is negative
   
   if(signal_strength >= 3) return is_buy ? "Strong Buy" : "Strong Sell"; //--- Return strong signal if 3+ conditions met
   if(signal_strength >= 2) return is_buy ? "Buy" : "Sell";      //--- Return regular signal if 2 conditions met
   return "Neutral";                                             //--- Return neutral if insufficient conditions
}

Hier wird die Funktion „truncate_timeframe_name“ definiert, die einen ganzzahligen Parameter „timeframe_index“ zur Formatierung von Zeitrahmennamen für die Anzeige benötigt. Darin verwenden wir die Funktion StringSubstr, um eine Teilzeichenkette aus dem Ergebnis der Funktion EnumToString zu extrahieren, die auf „timeframes_array[timeframe_index]“ angewendet wurde, beginnend an Position 7, und speichern sie in „timeframe_string“. Wir geben dann „timeframe_string“ zurück, was einen sauberen, für den Nutzer lesbaren Zeitrahmennamen ergibt.

Wir erstellen die Funktion „calculate_signal_strength“, um Kauf- oder Verkaufssignale auf der Grundlage von Indikatorwerten zu ermitteln. Wir initialisieren eine ganze Zahl „signal_strength“ auf Null, um übereinstimmende Bedingungen zu zählen. Für den Relative Strength Index wird „signal_strength“ erhöht, wenn „is_buy“ wahr und „rsi“ unter 40 (überverkauft) ist oder wenn „is_buy“ falsch und „rsi“ über 60 (überkauft) ist. In ähnlicher Weise überprüfen wir „stochastic“ (unter 40 oder über 60), „CCI“ (unter -70 oder über 70) und „ao“ (positiv für Kauf, negativ für Verkauf), wobei wir „signal_strength“ für jede erfüllte Bedingung inkrementieren.

Wir werten auch den Average Directional Index aus und erhöhen „signal_strength“, wenn „adx“ 40 übersteigt, was auf einen starken Trend sowohl für Kauf- als auch für Verkaufsszenarien hinweist. Wenn „signal_strength“ den Wert 3 oder mehr erreicht, geben wir „Strong Buy“ für „is_buy“ true oder „Strong Sell“ andernfalls zurück. Bei 2 wird „Buy“ oder „Sell“ zurückgegeben, bei weniger wird „Neutral“ zurückgegeben, was eine eindeutige Signalklassifizierung für das Dashboard ermöglicht. Abschließend können wir nun die Funktionen definieren, mit denen wir die Objekte erstellen können.

//+------------------------------------------------------------------+
//| Create a rectangle for the UI                                    |
//+------------------------------------------------------------------+
bool create_rectangle(string object_name, int x_distance, int y_distance, int x_size, int y_size, 
                      color background_color, color border_color = COLOR_BLACK) //--- Function to create a rectangle
{
   ResetLastError();                                                            //--- Reset error code
   if(!ObjectCreate(0, object_name, OBJ_RECTANGLE_LABEL, 0, 0, 0)) {            //--- Create rectangle object
      Print(__FUNCTION__, ": failed to create Rectangle: ERR Code: ", GetLastError()); //--- Log creation failure
      return(false);                                                            //--- Return failure
   }
   ObjectSetInteger(0, object_name, OBJPROP_XDISTANCE, x_distance);             //--- Set x position
   ObjectSetInteger(0, object_name, OBJPROP_YDISTANCE, y_distance);             //--- Set y position
   ObjectSetInteger(0, object_name, OBJPROP_XSIZE, x_size);                     //--- Set width
   ObjectSetInteger(0, object_name, OBJPROP_YSIZE, y_size);                     //--- Set height
   ObjectSetInteger(0, object_name, OBJPROP_CORNER, CORNER_RIGHT_UPPER);        //--- Set corner to top-right
   ObjectSetInteger(0, object_name, OBJPROP_BGCOLOR, background_color);         //--- Set background color
   ObjectSetInteger(0, object_name, OBJPROP_BORDER_COLOR, border_color);        //--- Set border color
   ObjectSetInteger(0, object_name, OBJPROP_BORDER_TYPE, BORDER_FLAT);          //--- Set flat border style
   ObjectSetInteger(0, object_name, OBJPROP_BACK, false);                       //--- Set to foreground
   
   ChartRedraw(0);                                                              //--- Redraw chart
   return(true);                                                                //--- Return success
}

//+------------------------------------------------------------------+
//| Create a text label for the UI                                   |
//+------------------------------------------------------------------+
bool create_label(string object_name, string text, int x_distance, int y_distance, int font_size = 12, 
                  color text_color = COLOR_BLACK, string font = "Arial Rounded MT Bold") //--- Function to create a label
{
   ResetLastError();                                                               //--- Reset error code
   if(!ObjectCreate(0, object_name, OBJ_LABEL, 0, 0, 0)) {                         //--- Create label object
      Print(__FUNCTION__, ": failed to create Label: ERR Code: ", GetLastError()); //--- Log creation failure
      return(false);                                                               //--- Return failure
   }
   ObjectSetInteger(0, object_name, OBJPROP_XDISTANCE, x_distance);                //--- Set x position
   ObjectSetInteger(0, object_name, OBJPROP_YDISTANCE, y_distance);                //--- Set y position
   ObjectSetInteger(0, object_name, OBJPROP_CORNER, CORNER_RIGHT_UPPER);           //--- Set corner to top-right
   ObjectSetString(0, object_name, OBJPROP_TEXT, text);                            //--- Set label text
   ObjectSetString(0, object_name, OBJPROP_FONT, font);                            //--- Set font
   ObjectSetInteger(0, object_name, OBJPROP_FONTSIZE, font_size);                  //--- Set font size
   ObjectSetInteger(0, object_name, OBJPROP_COLOR, text_color);                    //--- Set text color
   ObjectSetInteger(0, object_name, OBJPROP_ANCHOR, ANCHOR_CENTER);                //--- Center text
   
   ChartRedraw(0);                                                                 //--- Redraw chart
   return(true);                                                                   //--- Return success
}

Um die Erstellung der Objekte zu ermöglichen, definieren wir die Funktion „create_rectangle“ mit den Parametern „object_name“, „x_distance“, „y_distance“, „x_size“, „y_size“, „background_color“, und „border_color“. Wir verwenden die Funktion ResetLastError, erstellen ein OBJ_RECTANGLE_LABEL mit der Funktion ObjectCreate und protokollieren Fehler mit der Funktion „Print“, wenn sie fehlschlägt und false zurückgibt.

Wir setzen die Eigenschaften des Rechtecks mit der Funktion ObjectSetInteger für die Position, die Größe, „CORNER_RIGHT_UPPER“, „background_color“, „border_color“ und „BORDER_FLAT“, um die Darstellung im Vordergrund zu gewährleisten. Wir verwenden die Funktion ChartRedraw und geben true zurück. Für Text definieren wir die Funktion „create_label“ mit „object_name“, „text“, „x_distance“, „y_distance“, „font_size“, „text_color“ und „font“.

Wir verwenden die Funktion „ResetLastError“, erstellen ein „OBJ_LABEL“ mit der Funktion „ObjectCreate“ und protokollieren Fehler, wenn es fehlschlägt. Wir verwenden die Funktion „ObjectSetInteger“ für Position, Größe, Farbe und „ANCHOR_CENTER“ und die Funktion ObjectSetString für „text“ und „font“. Wir verwenden die Funktion „ChartRedraw“ und geben true zurück. Mit diesen Funktionen können wir nun die ersten Panel-Objekte erstellen, um einen Ausgangspunkt für die Funktion „OnInit“ zu haben.

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()                                                                             //--- Initialize EA
{
   create_rectangle(MAIN_PANEL, 632, 40, 617, 374, C'30,30,30', BORDER_FLAT);            //--- Create main panel background
   create_rectangle(HEADER_PANEL, 632, 40, 617, 27, C'60,60,60', BORDER_FLAT);           //--- Create header panel background
   create_label(HEADER_PANEL_ICON, CharToString(91), 620, 54, 18, clrAqua, "Wingdings"); //--- Create header icon
   create_label(HEADER_PANEL_TEXT, "TimeframeScanner", 527, 52, 13, COLOR_WHITE);        //--- Create header title
   create_label(CLOSE_BUTTON, CharToString('r'), 32, 54, 18, clrYellow, "Webdings");     //--- Create close button

   // Create header rectangle and label
   create_rectangle(SYMBOL_RECTANGLE, 630, 75, WIDTH_TIMEFRAME, HEIGHT_RECTANGLE, clrGray); //--- Create symbol rectangle
   create_label(SYMBOL_TEXT, _Symbol, 585, 85, 11, COLOR_WHITE); //--- Create symbol label
   
   // Create summary and indicator headers (rectangles and labels)
   string header_names[] = {"BUY", "SELL", "RSI", "STOCH", "CCI", "ADX", "AO"};            //--- Define header titles
   for(int header_index = 0; header_index < ArraySize(header_names); header_index++) {     //--- Loop through headers
      int x_offset = (630 - WIDTH_TIMEFRAME) - (header_index < 2 ? header_index * WIDTH_SIGNAL : 2 * WIDTH_SIGNAL + (header_index - 2) * WIDTH_INDICATOR) + (1 + header_index); //--- Calculate x position
      int width = (header_index < 2 ? WIDTH_SIGNAL : WIDTH_INDICATOR);                     //--- Set width based on header type
      create_rectangle(HEADER_RECTANGLE + IntegerToString(header_index), x_offset, 75, width, HEIGHT_RECTANGLE, clrGray);             //--- Create header rectangle
      create_label(HEADER_TEXT + IntegerToString(header_index), header_names[header_index], x_offset - width/2, 85, 11, COLOR_WHITE); //--- Create header label
   }
   
   // Create timeframe rectangles and labels, and summary/indicator cells
   for(int timeframe_index = 0; timeframe_index < ArraySize(timeframes_array); timeframe_index++) {            //--- Loop through timeframes
      // Highlight current timeframe
      color timeframe_background = (timeframes_array[timeframe_index] == _Period) ? clrLimeGreen : clrGray;    //--- Set background color for current timeframe
      color timeframe_text_color = (timeframes_array[timeframe_index] == _Period) ? COLOR_BLACK : COLOR_WHITE; //--- Set text color for current timeframe
      
      create_rectangle(TIMEFRAME_RECTANGLE + IntegerToString(timeframe_index), 630, (75 + HEIGHT_RECTANGLE) + timeframe_index * HEIGHT_RECTANGLE - (1 + timeframe_index), WIDTH_TIMEFRAME, HEIGHT_RECTANGLE, timeframe_background);   //--- Create timeframe rectangle
      create_label(TIMEFRAME_TEXT + IntegerToString(timeframe_index), truncate_timeframe_name(timeframe_index), 585, (85 + HEIGHT_RECTANGLE) + timeframe_index * HEIGHT_RECTANGLE - (1 + timeframe_index), 11, timeframe_text_color); //--- Create timeframe label
                  
      // Create summary and indicator cells
      for(int header_index = 0; header_index < ArraySize(header_names); header_index++) { //--- Loop through headers for cells
         string cell_rectangle_name, cell_text_name;                                      //--- Declare cell name and label variables
         color cell_background = (header_index < 2) ? COLOR_LIGHT_GRAY : COLOR_BLACK;     //--- Set cell background color
         switch(header_index) {                                   //--- Select cell type
            case 0: cell_rectangle_name = BUY_RECTANGLE + IntegerToString(timeframe_index); cell_text_name = BUY_TEXT + IntegerToString(timeframe_index); break;     //--- Buy cell
            case 1: cell_rectangle_name = SELL_RECTANGLE + IntegerToString(timeframe_index); cell_text_name = SELL_TEXT + IntegerToString(timeframe_index); break;   //--- Sell cell
            case 2: cell_rectangle_name = RSI_RECTANGLE + IntegerToString(timeframe_index); cell_text_name = RSI_TEXT + IntegerToString(timeframe_index); break;     //--- RSI cell
            case 3: cell_rectangle_name = STOCH_RECTANGLE + IntegerToString(timeframe_index); cell_text_name = STOCH_TEXT + IntegerToString(timeframe_index); break; //--- Stochastic cell
            case 4: cell_rectangle_name = CCI_RECTANGLE + IntegerToString(timeframe_index); cell_text_name = CCI_TEXT + IntegerToString(timeframe_index); break;     //--- CCI cell
            case 5: cell_rectangle_name = ADX_RECTANGLE + IntegerToString(timeframe_index); cell_text_name = ADX_TEXT + IntegerToString(timeframe_index); break;     //--- ADX cell
            case 6: cell_rectangle_name = AO_RECTANGLE + IntegerToString(timeframe_index); cell_text_name = AO_TEXT + IntegerToString(timeframe_index); break;       //--- AO cell
         }
         int x_offset = (630 - WIDTH_TIMEFRAME) - (header_index < 2 ? header_index * WIDTH_SIGNAL : 2 * WIDTH_SIGNAL + (header_index - 2) * WIDTH_INDICATOR) + (1 + header_index);        //--- Calculate x position
         int width = (header_index < 2 ? WIDTH_SIGNAL : WIDTH_INDICATOR); //--- Set width based on cell type
         create_rectangle(cell_rectangle_name, x_offset, (75 + HEIGHT_RECTANGLE) + timeframe_index * HEIGHT_RECTANGLE - (1 + timeframe_index), width, HEIGHT_RECTANGLE, cell_background); //--- Create cell rectangle
         create_label(cell_text_name, "-/-", x_offset - width/2, (85 + HEIGHT_RECTANGLE) + timeframe_index * HEIGHT_RECTANGLE - (1 + timeframe_index), 10, COLOR_WHITE);                  //--- Create cell label
      }
   }
   
   // Initialize indicator arrays
   ArraySetAsSeries(rsi_values, true);                       //--- Set RSI array as timeseries
   ArraySetAsSeries(stochastic_values, true);                //--- Set Stochastic array as timeseries
   ArraySetAsSeries(cci_values, true);                       //--- Set CCI array as timeseries
   ArraySetAsSeries(adx_values, true);                       //--- Set ADX array as timeseries
   ArraySetAsSeries(ao_values, true);                        //--- Set AO array as timeseries
    
   return(INIT_SUCCEEDED);                                   //--- Return initialization success
}

In OnInit initialisieren wir die Nutzeroberfläche des Multi-Zeitrahmen-Scanners Dashboard. Wir verwenden die Funktion „create_rectangle“, um das „MAIN_PANEL“ an (632, 40) mit einer Größe von 617x374 Pixeln in „C'30,30,30'“ und das „HEADER_PANEL“ an derselben Position mit einer Höhe von 27 Pixeln in „C'60,60,60'“ zu zeichnen. Wir verwenden die Funktion „create_label“, um das „HEADER_PANEL_ICON“ mit einem Wingdings-Zeichen bei (620, 54) hinzuzufügen. Wir verwenden die Standardzeichen in MQL5 und nutzen die Funktion CharToString, um den Zeichencode in eine Zeichenkette umzuwandeln. Hier ist der von uns verwendete Zeichencode 91, aber Sie können jeden beliebigen Code verwenden.

MQL5 FÜHRUNGSRINGE

Dann erstellen wir den „HEADER_PANEL_TEXT“ mit „TimeframeScanner“ an (527, 52) und „CLOSE_BUTTON“ an (32, 54), aber dieses Mal verwenden wir eine andere Schriftart und ordnen der Zeichenfolge den Buchstaben „r“ zu. Hier sehen Sie eine Visualisierung der verschiedenen Schriftsymbole, die Sie verwenden können.

FONT DER SYMBOLE

Wir richten die Symboldarstellung mit der Funktion „create_rectangle“ für das „SYMBOL_RECTANGLE“ bei (630, 75) in der Größe „WIDTH_TIMEFRAME“ mal „HEIGHT_RECTANGLE“ in Grau ein. Wir verwenden die Funktion „create_label“, um den „SYMBOL_TEXT“ bei (585, 85) mit dem aktuellen Symbol zu platzieren. Für die Kopfzeilen definieren wir das Array „header_names“ mit Titeln wie „BUY“ und „RSI“ und erstellen in einer Schleife „HEADER_RECTANGLE“ bei y=75 mit x-Offsets basierend auf „WIDTH_SIGNAL“ und „WIDTH_INDICATOR“ sowie „HEADER_TEXT“-Beschriftungen bei y=85 mit der Funktion „create_label“.

Wir erstellen das Zeitraster, indem wir eine Schleife durch „timeframes_array“ ziehen. Wir verwenden die Funktion „create_rectangle“ für „TIMEFRAME_RECTANGLE“ bei x=630, y-Offsets von (75 + „HEIGHT_RECTANGLE“) angepasst um -(1 + „timeframe_index“), eingefärbt mit „timeframe_background“. Wir verwenden die Funktion „create_label“ für „TIMEFRAME_TEXT“ mit Namen aus der Funktion „truncate_timeframe_name“. Für die Zellen erstellen wir in einer Schleife „BUY_RECTANGLE“, „RSI_RECTANGLE“ usw. mit der Funktion „create_rectangle“ unter Verwendung von „cell_background“ und fügen „-/-“-Beschriftungen mit der Funktion „create_label“ hinzu. Wir initialisieren Indikator-Arrays wie „rsi_values“ mit der Funktion ArraySetAsSeries und setzen sie als Zeitreihen für die Datenverarbeitung. Wir geben INIT_SUCCEEDED zurück, um die erfolgreiche Initialisierung zu bestätigen und das Layout und die Datenstruktur des Dashboards einzurichten. Nach der Kompilierung erhalten wir folgendes Ergebnis.

STATISCHES DASHBOARD

Aus dem Bild können wir ersehen, dass das Dashboard fertig ist. Jetzt müssen wir nur noch die Indikatorwerte hinzufügen und sie für die Analyse verwenden. Wir haben bereits eine Funktion für die Analyse, wir müssen nur noch die Daten bekommen. Um dies auf einfache Weise zu erreichen, erstellen wir eine Funktion, die die gesamte dynamische Aktualisierungslogik übernimmt.

//+------------------------------------------------------------------+
//| Update indicator values                                          |
//+------------------------------------------------------------------+
void updateIndicators()                                                                               //--- Update dashboard indicators
{
   for(int timeframe_index = 0; timeframe_index < ArraySize(timeframes_array); timeframe_index++) {   //--- Loop through timeframes
      // Initialize indicator handles
      int rsi_indicator_handle = iRSI(_Symbol, timeframes_array[timeframe_index], 14, PRICE_CLOSE);   //--- Create RSI handle
      int stochastic_indicator_handle = iStochastic(_Symbol, timeframes_array[timeframe_index], 14, 3, 3, MODE_SMA, STO_LOWHIGH); //--- Create Stochastic handle
      int cci_indicator_handle = iCCI(_Symbol, timeframes_array[timeframe_index], 20, PRICE_TYPICAL); //--- Create CCI handle
      int adx_indicator_handle = iADX(_Symbol, timeframes_array[timeframe_index], 14);                //--- Create ADX handle
      int ao_indicator_handle = iAO(_Symbol, timeframes_array[timeframe_index]);                      //--- Create AO handle
      
      // Check for valid handles
      if(rsi_indicator_handle == INVALID_HANDLE || stochastic_indicator_handle == INVALID_HANDLE || 
         cci_indicator_handle == INVALID_HANDLE || adx_indicator_handle == INVALID_HANDLE || 
         ao_indicator_handle == INVALID_HANDLE) {                                                             //--- Check if any handle is invalid
         Print("Failed to create indicator handle for timeframe ", truncate_timeframe_name(timeframe_index)); //--- Log failure
         continue;                                                                                            //--- Skip to next timeframe
      }
      
      // Copy indicator values
      if(CopyBuffer(rsi_indicator_handle, 0, 0, 1, rsi_values) <= 0 ||                            //--- Copy RSI value
         CopyBuffer(stochastic_indicator_handle, 1, 0, 1, stochastic_values) <= 0 ||              //--- Copy Stochastic signal line value
         CopyBuffer(cci_indicator_handle, 0, 0, 1, cci_values) <= 0 ||                            //--- Copy CCI value
         CopyBuffer(adx_indicator_handle, 0, 0, 1, adx_values) <= 0 ||                            //--- Copy ADX value
         CopyBuffer(ao_indicator_handle, 0, 0, 1, ao_values) <= 0) {                              //--- Copy AO value
         Print("Failed to copy buffer for timeframe ", truncate_timeframe_name(timeframe_index)); //--- Log copy failure
         continue;                                                                                //--- Skip to next timeframe
      }
      
      // Update RSI
      color rsi_text_color = (rsi_values[0] < 30) ? clrBlue : (rsi_values[0] > 70) ? clrRed : COLOR_WHITE;         //--- Set RSI text color
      update_label(RSI_TEXT + IntegerToString(timeframe_index), DoubleToString(rsi_values[0], 2), rsi_text_color); //--- Update RSI label
      
      // Update Stochastic (Signal Line only)
      color stochastic_text_color = (stochastic_values[0] < 20) ? clrBlue : (stochastic_values[0] > 80) ? clrRed : COLOR_WHITE;    //--- Set Stochastic text color
      update_label(STOCH_TEXT + IntegerToString(timeframe_index), DoubleToString(stochastic_values[0], 2), stochastic_text_color); //--- Update Stochastic label
      
      // Update CCI
      color cci_text_color = (cci_values[0] < -100) ? clrBlue : (cci_values[0] > 100) ? clrRed : COLOR_WHITE;      //--- Set CCI text color
      update_label(CCI_TEXT + IntegerToString(timeframe_index), DoubleToString(cci_values[0], 2), cci_text_color); //--- Update CCI label
      
      // Update ADX
      color adx_text_color = (adx_values[0] > 25) ? clrBlue : COLOR_WHITE;                                         //--- Set ADX text color
      update_label(ADX_TEXT + IntegerToString(timeframe_index), DoubleToString(adx_values[0], 2), adx_text_color); //--- Update ADX label
      
      // Update AO
      color ao_text_color = (ao_values[0] > 0) ? clrGreen : (ao_values[0] < 0) ? clrRed : COLOR_WHITE;          //--- Set AO text color
      update_label(AO_TEXT + IntegerToString(timeframe_index), DoubleToString(ao_values[0], 2), ao_text_color); //--- Update AO label
      
      // Update Buy/Sell signals
      string buy_signal = calculate_signal_strength(rsi_values[0], stochastic_values[0], cci_values[0], 
                                                   adx_values[0], ao_values[0], true);                          //--- Calculate buy signal
      string sell_signal = calculate_signal_strength(rsi_values[0], stochastic_values[0], cci_values[0], 
                                                    adx_values[0], ao_values[0], false);                        //--- Calculate sell signal
      
      color buy_text_color = (buy_signal == "Strong Buy") ? COLOR_WHITE : COLOR_WHITE;                          //--- Set buy text color
      color buy_background = (buy_signal == "Strong Buy") ? clrGreen : 
                            (buy_signal == "Buy") ? clrSeaGreen : COLOR_DARK_GRAY;                              //--- Set buy background color
      update_rectangle(BUY_RECTANGLE + IntegerToString(timeframe_index), buy_background);                       //--- Update buy rectangle
      update_label(BUY_TEXT + IntegerToString(timeframe_index), buy_signal, buy_text_color);                    //--- Update buy label
      
      color sell_text_color = (sell_signal == "Strong Sell") ? COLOR_WHITE : COLOR_WHITE;                       //--- Set sell text color
      color sell_background = (sell_signal == "Strong Sell") ? clrRed : 
                             (sell_signal == "Sell") ? clrSalmon : COLOR_DARK_GRAY;                             //--- Set sell background color
      update_rectangle(SELL_RECTANGLE + IntegerToString(timeframe_index), sell_background);                     //--- Update sell rectangle
      update_label(SELL_TEXT + IntegerToString(timeframe_index), sell_signal, sell_text_color);                 //--- Update sell label
      
      // Release indicator handles
      IndicatorRelease(rsi_indicator_handle);                   //--- Release RSI handle
      IndicatorRelease(stochastic_indicator_handle);            //--- Release Stochastic handle
      IndicatorRelease(cci_indicator_handle);                   //--- Release CCI handle
      IndicatorRelease(adx_indicator_handle);                   //--- Release ADX handle
      IndicatorRelease(ao_indicator_handle);                    //--- Release AO handle
   }
}

Um die Aktualisierung der Dashboard-Werte zu vereinfachen, implementieren wir die Funktion „updateIndicators“ zur Aktualisierung der Indikatorwerte und Signale. Wir durchlaufen „timeframes_array“ mit Hilfe von „timeframe_index“ in einer Schleife und verarbeiten jeden Zeitrahmen. Wir verwenden die Funktionen „iRSI“, „iStochastic“, „iCCI“, „iADX“ und „iAO“, um Indikator-Handles wie „rsi_indicator_handle“ für das aktuelle Symbol und den aktuellen Zeitrahmen zu erstellen und Parameter wie einen RSI mit 14 Perioden und einen CCI mit 20 Perioden zu konfigurieren. Alle Indikatoreinstellungen können an Ihre Bedürfnisse angepasst werden, beschränken Sie sich also nicht auf die Standardwerte.

Anschließend wird geprüft, ob ein Handle, wie z. B. „rsi_indicator_handle“, gleich INVALID_HANDLE ist, was auf einen Erstellungsfehler hinweist. Wenn dies der Fall ist, protokollieren wir mit der Funktion „Print“ den Fehler mit der Ausgabe der Funktion „truncate_timeframe_name“ und fahren mit dem nächsten Zeitrahmen fort. Wir verwenden CopyBuffer, um die neuesten Werte in Arrays wie „rsi_values“ zu holen, und wenn einer davon fehlschlägt, protokollieren wir den Fehler und fahren fort. Wir aktualisieren die Indikatoren der Indikatoren mit der Funktion „update_label“. Zum Beispiel setzen wir „rsi_text_color“ auf der Grundlage von „rsi_values[0]“ (blau wenn <30, rot wenn >70, sonst „COLOR_WHITE“) und aktualisieren „RSI_TEXT“ mit dem formatierten Wert der Funktion „DoubleToString“. Wir wiederholen dies für „stochastic_values“, „cci_values“, „adx_values“ und „ao_values“, wobei wir eine Farblogik anwenden (z. B. grün für positive „ao_values“).

Wir berechnen die Signale mit der Funktion „calculate_signal_strength“ und übergeben „rsi_values[0]“ und andere, um „buy_signal“ und „sell_signal“ zu erhalten. Wir setzen „buy_background“ (z. B. grün für „Strong Buy“) und verwenden die Funktion „update_rectangle“ für „BUY_RECTANGLE“, wobei „BUY_TEXT“ mit „update_label“ aktualisiert wird. Dasselbe gilt für „sell_background“ und „SELL_TEXT“. Schließlich verwenden wir die Funktion IndicatorRelease, um Handles wie „rsi_indicator_handle“ freizugeben und eine effiziente Ressourcenverwaltung zu gewährleisten. Die von uns verwendeten Hilfsfunktionen sind wie folgt definiert.

//+------------------------------------------------------------------+
//| Update rectangle background color                                |
//+------------------------------------------------------------------+
bool update_rectangle(string object_name, color background_color)//--- Function to update rectangle color
{
   int found = ObjectFind(0, object_name);                       //--- Find rectangle object
   if(found < 0) {                                               //--- Check if object not found
      ResetLastError();                                          //--- Reset error code
      Print("UNABLE TO FIND THE RECTANGLE: ", object_name, ". ERR Code: ", GetLastError()); //--- Log error
      return(false);                                             //--- Return failure
   }
   ObjectSetInteger(0, object_name, OBJPROP_BGCOLOR, background_color); //--- Set background color
   
   ChartRedraw(0);                                               //--- Redraw chart
   return(true);                                                 //--- Return success
}

//+------------------------------------------------------------------+
//| Update label text and color                                      |
//+------------------------------------------------------------------+
bool update_label(string object_name, string text, color text_color) //--- Function to update label
{
   int found = ObjectFind(0, object_name);                       //--- Find label object
   if(found < 0) {                                               //--- Check if object not found
      ResetLastError();                                          //--- Reset error code
      Print("UNABLE TO FIND THE LABEL: ", object_name, ". ERR Code: ", GetLastError()); //--- Log error
      return(false);                                             //--- Return failure
   }
   ObjectSetString(0, object_name, OBJPROP_TEXT, text);          //--- Set label text
   ObjectSetInteger(0, object_name, OBJPROP_COLOR, text_color);  //--- Set text color
   
   ChartRedraw(0);                                               //--- Redraw chart
   return(true);                                                 //--- Return success
}

Wir definieren die Funktion „update_rectangle“ mit den Parametern „object_name“ und „background_color“, um das Aussehen eines Rechtecks zu ändern. Wir verwenden die Funktion ObjectFind, um das Rechteck zu finden, und speichern das Ergebnis in „found“. Wenn „found“ kleiner als 0 ist, was bedeutet, dass das Objekt fehlt, verwenden wir die Funktion ResetLastError, protokollieren den Fehler mit der Funktion „Print“ und „GetLastError“ und geben false zurück. Wir aktualisieren den Hintergrund des Rechtecks, indem wir die Funktion „ObjectSetInteger“ verwenden, um „OBJPROP_BGCOLOR“ auf „background_color“ zu setzen. Wir verwenden die Funktion ChartRedraw, um das Chart zu aktualisieren, und geben bei Erfolg true zurück. Für Textaktualisierungen definieren wir die Funktion „update_label“ mit den Parametern „object_name“, „text“ und „text_color“.

Wir verwenden die Funktion „ObjectFind“, um zu prüfen, ob das Etikett vorhanden ist, und wenn „found“ negativ ist, verwenden wir die Funktion „ResetLastError“, protokollieren den Fehler mit der Funktion „Print“ und geben false zurück. Wir verwenden die Funktion ObjectSetString, um „OBJPROP_TEXT“ auf „text“ zu setzen und die Funktion ObjectSetInteger, um „OBJPROP_COLOR“ auf „text_color“ zu setzen. Wir verwenden die Funktion „ChartRedraw“, um das Chart zu aktualisieren, und geben „true“ zurück, um die dynamische Aktualisierung der Beschriftung zu ermöglichen. Wir können nun die Aktualisierungsfunktion für das Tick aufrufen, um das Dashboard zu aktualisieren.

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()                                                    //--- Handle tick events
{
   if (panel_is_visible) {                                       //--- Check if panel is visible
      updateIndicators();                                        //--- Update indicators
   }
}

Hier, in OnTick, rufen wir einfach die Funktion „updateIndicators“ auf, wenn das Panel sichtbar ist, um die Aktualisierungen anzuwenden. Schließlich müssen wir die von uns erstellten Objekte löschen, damit sie aus dem Chart entfernt werden, wenn wir sie nicht mehr benötigen.

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)                                  //--- Deinitialize EA
{
   ObjectDelete(0, MAIN_PANEL);                                  //--- Delete main panel
   ObjectDelete(0, HEADER_PANEL);                                //--- Delete header panel
   ObjectDelete(0, HEADER_PANEL_ICON);                           //--- Delete header icon
   ObjectDelete(0, HEADER_PANEL_TEXT);                           //--- Delete header title
   ObjectDelete(0, CLOSE_BUTTON);                                //--- Delete close button

   ObjectsDeleteAll(0, SYMBOL_RECTANGLE);                        //--- Delete all symbol rectangles
   ObjectsDeleteAll(0, SYMBOL_TEXT);                             //--- Delete all symbol labels
   ObjectsDeleteAll(0, TIMEFRAME_RECTANGLE);                     //--- Delete all timeframe rectangles
   ObjectsDeleteAll(0, TIMEFRAME_TEXT);                          //--- Delete all timeframe labels
   ObjectsDeleteAll(0, HEADER_RECTANGLE);                        //--- Delete all header rectangles
   ObjectsDeleteAll(0, HEADER_TEXT);                             //--- Delete all header labels
   ObjectsDeleteAll(0, RSI_RECTANGLE);                           //--- Delete all RSI rectangles
   ObjectsDeleteAll(0, RSI_TEXT);                                //--- Delete all RSI labels
   ObjectsDeleteAll(0, STOCH_RECTANGLE);                         //--- Delete all Stochastic rectangles
   ObjectsDeleteAll(0, STOCH_TEXT);                              //--- Delete all Stochastic labels
   ObjectsDeleteAll(0, CCI_RECTANGLE);                           //--- Delete all CCI rectangles
   ObjectsDeleteAll(0, CCI_TEXT);                                //--- Delete all CCI labels
   ObjectsDeleteAll(0, ADX_RECTANGLE);                           //--- Delete all ADX rectangles
   ObjectsDeleteAll(0, ADX_TEXT);                                //--- Delete all ADX labels
   ObjectsDeleteAll(0, AO_RECTANGLE);                            //--- Delete all AO rectangles
   ObjectsDeleteAll(0, AO_TEXT);                                 //--- Delete all AO labels
   ObjectsDeleteAll(0, BUY_RECTANGLE);                           //--- Delete all buy rectangles
   ObjectsDeleteAll(0, BUY_TEXT);                                //--- Delete all buy labels
   ObjectsDeleteAll(0, SELL_RECTANGLE);                          //--- Delete all sell rectangles
   ObjectsDeleteAll(0, SELL_TEXT);                               //--- Delete all sell labels
   
   ChartRedraw(0);                                               //--- Redraw chart
}

Schließlich implementieren wir den Bereinigungsprozess mithilfe der Funktion OnDeinit, die ausgeführt wird, wenn der Expert Advisor entfernt wird. Wir verwenden die Funktion ObjectDelete, um einzelne UI-Elemente zu entfernen, beginnend mit dem Rechteck „MAIN_PANEL“, gefolgt von „HEADER_PANEL“, „HEADER_PANEL_ICON“, „HEADER_PANEL_TEXT“ und „CLOSE_BUTTON“, um sicherzustellen, dass das Hauptpanel und die Header-Komponenten aus dem Chart gelöscht werden.

Wir entfernen systematisch alle Dashboard-Objekte, indem wir die Funktion ObjectsDeleteAll für jeden Elementtyp verwenden. Wir löschen alle Rechtecke und Beschriftungen, die mit „SYMBOL_RECTANGLE“ und „SYMBOL_TEXT“, „TIMEFRAME_RECTANGLE“ und „TIMEFRAME_TEXT“ sowie „HEADER_RECTANGLE“ und „HEADER_TEXT“ verbunden sind, und löschen die Symbol-, Zeitrahmen- und Kopfzeilenanzeigen. Wir entfernen auch indikatorbezogene Objekte, einschließlich „RSI_RECTANGLE“, „STOCH_RECTANGLE“, „CCI_RECTANGLE“, „ADX_RECTANGLE“ und „AO_RECTANGLE“, zusammen mit ihren jeweiligen Textbezeichnungen wie „RSI_TEXT“.

Wir schließen die Bereinigung ab, indem wir die Funktion „ObjectsDeleteAll“ verwenden, um alle „BUY_RECTANGLE“- und „SELL_RECTANGLE“-Objekte zusammen mit ihren „BUY_TEXT“- und „SELL_TEXT“-Beschriftungen zu löschen und alle signalbezogenen Elemente zu entfernen. Schließlich verwenden wir die Funktion ChartRedraw, um das Chart zu aktualisieren und einen sauberen visuellen Zustand nach der Deinitialisierung zu gewährleisten. Schließlich müssen wir uns um die Schaltfläche „Abbrechen“ kümmern, damit das Dashboard beim Anklicken geschlossen und weitere Aktualisierungen deaktiviert werden.

//+------------------------------------------------------------------+
//| Expert chart event handler                                       |
//+------------------------------------------------------------------+
void OnChartEvent(const int       event_id,                      //--- Event ID
                  const long&     long_param,                    //--- Long parameter
                  const double&   double_param,                  //--- Double parameter
                  const string&   string_param)                  //--- String parameter
{
   if (event_id == CHARTEVENT_OBJECT_CLICK) {                    //--- Check for object click event
      if (string_param == CLOSE_BUTTON) {                        //--- Check if close button clicked
         Print("Closing the panel now");                         //--- Log panel closure
         PlaySound("alert.wav");                                 //--- Play alert sound
         panel_is_visible = false;                               //--- Hide panel
         
         ObjectDelete(0, MAIN_PANEL);                            //--- Delete main panel
         ObjectDelete(0, HEADER_PANEL);                          //--- Delete header panel
         ObjectDelete(0, HEADER_PANEL_ICON);                     //--- Delete header icon
         ObjectDelete(0, HEADER_PANEL_TEXT);                     //--- Delete header title
         ObjectDelete(0, CLOSE_BUTTON);                          //--- Delete close button
      
         ObjectsDeleteAll(0, SYMBOL_RECTANGLE);                  //--- Delete all symbol rectangles
         ObjectsDeleteAll(0, SYMBOL_TEXT);                       //--- Delete all symbol labels
         ObjectsDeleteAll(0, TIMEFRAME_RECTANGLE);               //--- Delete all timeframe rectangles
         ObjectsDeleteAll(0, TIMEFRAME_TEXT);                    //--- Delete all timeframe labels
         ObjectsDeleteAll(0, HEADER_RECTANGLE);                  //--- Delete all header rectangles
         ObjectsDeleteAll(0, HEADER_TEXT);                       //--- Delete all header labels
         ObjectsDeleteAll(0, RSI_RECTANGLE);                     //--- Delete all RSI rectangles
         ObjectsDeleteAll(0, RSI_TEXT);                          //--- Delete all RSI labels
         ObjectsDeleteAll(0, STOCH_RECTANGLE);                   //--- Delete all Stochastic rectangles
         ObjectsDeleteAll(0, STOCH_TEXT);                        //--- Delete all Stochastic labels
         ObjectsDeleteAll(0, CCI_RECTANGLE);                     //--- Delete all CCI rectangles
         ObjectsDeleteAll(0, CCI_TEXT);                          //--- Delete all CCI labels
         ObjectsDeleteAll(0, ADX_RECTANGLE);                     //--- Delete all ADX rectangles
         ObjectsDeleteAll(0, ADX_TEXT);                          //--- Delete all ADX labels
         ObjectsDeleteAll(0, AO_RECTANGLE);                      //--- Delete all AO rectangles
         ObjectsDeleteAll(0, AO_TEXT);                           //--- Delete all AO labels
         ObjectsDeleteAll(0, BUY_RECTANGLE);                     //--- Delete all buy rectangles
         ObjectsDeleteAll(0, BUY_TEXT);                          //--- Delete all buy labels
         ObjectsDeleteAll(0, SELL_RECTANGLE);                    //--- Delete all sell rectangles
         ObjectsDeleteAll(0, SELL_TEXT);                         //--- Delete all sell labels
         
         ChartRedraw(0);                                         //--- Redraw chart
      }
   }
}

In der Ereignisbehandlung von OnChartEvent hören wir auf Objektklicks, wenn die Ereigniskennung CHARTEVENT_OBJECT_CLICK lautet und das angeklickte Objekt die Abbrechen-Schaltfläche ist, und wir spielen einen Warnton mit der Funktion PlaySound ab, um den Nutzer darauf hinzuweisen, dass das Panel deaktiviert wird, deaktivieren dann die Sichtbarkeit des Panels und verwenden dieselbe Logik, die wir zum Löschen des Charts bei OnDeinit verwendet haben, um das Dashboard zu löschen. Nach der Kompilierung erhalten wir folgendes Ergebnis.

AKTUALISIERTES DASHBOARD

Auf dem Bild können wir sehen, dass das Dashboard mit den Indikatordaten und den angezeigten Handelsrichtungen aktualisiert wurde. Nun bleibt nur noch die Prüfung der Durchführbarkeit des Projekts, die im vorangegangenen Abschnitt behandelt wurde.


Backtests

Wir haben die Tests durchgeführt, und unten sehen Sie die kompilierte Visualisierung in einem einzigen Bitmap-Bildformat im Graphics Interchange Format (GIF).

TESTING GIF


Schlussfolgerung

Abschließend haben wir ein Multi-Timeframe-Scanner-Dashboard in MQL5 entwickelt, das ein strukturiertes Grid-Layout, Echtzeit-Indikatorensignale und eine interaktive Schaltfläche zum Schließen integriert, um strategische Handelsentscheidungen zu verbessern. Wir haben das Design und die Implementierung dieser Funktionen gezeigt und ihre Effektivität durch robuste Initialisierung und dynamische Aktualisierungen, die auf unsere Handelsanforderungen zugeschnitten sind, sichergestellt. Sie können dieses Dashboard an Ihre Präferenzen anpassen und so Ihre Fähigkeit, Marktsignale über mehrere Zeitrahmen hinweg zu überwachen und darauf zu reagieren, erheblich verbessern.

Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/18319

Entwicklung des Price Action Analysis Toolkit (Teil 25): Dual EMA Fractal Breaker Entwicklung des Price Action Analysis Toolkit (Teil 25): Dual EMA Fractal Breaker
Die Preisaktion ist ein grundlegender Ansatz zur Identifizierung profitabler Handels-Setups. Die manuelle Überwachung von Kursbewegungen und -mustern kann jedoch schwierig und zeitaufwändig sein. Deshalb entwickeln wir Tools, die das Kursgeschehen automatisch analysieren und rechtzeitig Signale geben, wenn sich potenzielle Chancen ergeben. In diesem Artikel wird ein robustes Tool vorgestellt, das fraktale Ausbrüche zusammen mit dem EMA 14 und dem EMA 200 nutzt, um zuverlässige Handelssignale zu generieren, die Händlern helfen, fundierte Entscheidungen mit größerer Zuversicht zu treffen.
Entwicklung des Price Action Analysis Toolkit (Teil 24): Analyse-Tool zur Quantifizierung von Preisaktionen Entwicklung des Price Action Analysis Toolkit (Teil 24): Analyse-Tool zur Quantifizierung von Preisaktionen
Kerzenmuster bieten wertvolle Einblicke in potenzielle Marktbewegungen. Einige einzelne Kerzen signalisieren die Fortsetzung des aktuellen Trends, während andere, je nach ihrer Position innerhalb der Kursbewegung, Umkehrungen vorhersagen. In diesem Artikel wird ein EA vorgestellt, der automatisch vier wichtige Kerzen-Formationen identifiziert. In den folgenden Abschnitten erfahren Sie, wie dieses Tool Ihre Preis-Aktions-Analyse verbessern kann.
Datenwissenschaft und ML (Teil 41): Mustererkennung mit YOLOv8 im Forex und den Aktienmärkten Datenwissenschaft und ML (Teil 41): Mustererkennung mit YOLOv8 im Forex und den Aktienmärkten
Die Erkennung von Mustern auf den Finanzmärkten ist eine Herausforderung, denn dazu muss man sehen, was auf dem Chart zu sehen ist, und das ist in MQL5 aufgrund der Bildbeschränkungen schwierig zu bewerkstelligen. In diesem Artikel werden wir ein anständiges Modell in Python besprechen, das uns hilft, mit minimalem Aufwand Muster im Chart zu erkennen.
MQL5-Assistenten-Techniken, die Sie kennen sollten (Teil 68):  Verwendung von TRIX-Mustern und des Williams Percent Range mit einem Cosinus-Kernel-Netzwerk MQL5-Assistenten-Techniken, die Sie kennen sollten (Teil 68): Verwendung von TRIX-Mustern und des Williams Percent Range mit einem Cosinus-Kernel-Netzwerk
Wir knüpfen an unseren letzten Artikel an, in dem wir das Indikatorpaar TRIX und Williams Percent Range vorstellten, und überlegen, wie dieses Indikatorpaar durch maschinelles Lernen erweitert werden kann. TRIX und Williams Percent sind ein Trend- und Unterstützungs-/Widerstandspaar, das sich gegenseitig ergänzt. Unser Ansatz des maschinellen Lernens verwendet ein neuronales Faltungsnetzwerk, das bei der Feinabstimmung der Prognosen dieses Indikatorpaares den Kosinus-Kernel in seine Architektur einbezieht. Wie immer wird dies in einer nutzerdefinierten Signalklassendatei durchgeführt, die mit dem MQL5-Assistenten arbeitet, um einen Expert Advisor zusammenzustellen.