
MQL5-Handelswerkzeuge (Teil 3): Aufbau eines Multi-Timeframe Scanner Dashboards für den strategischen Handel
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:
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.
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.
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.
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.
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.
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).
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
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.