English 中文 Deutsch 日本語
preview
Торговые инструменты на MQL5 (Часть 3): Создание панели сканера по нескольким таймфреймам для стратегической торговли

Торговые инструменты на MQL5 (Часть 3): Создание панели сканера по нескольким таймфреймам для стратегической торговли

MetaTrader 5Трейдинг |
88 0
Allan Munene Mutiiria
Allan Munene Mutiiria

Введение

В своей предыдущей статье, Часть 2, мы дополнили инструмент Trade Assistant на MetaQuotes Language 5 (MQL5) динамической визуальной обратной связью для улучшения интерактивности. Теперь мы сосредоточимся на создании панели сканера по нескольким таймфреймам, которая будет предоставлять торговые сигналы в режиме реального времени для принятия стратегических решений. Мы представляем интерфейс на основе сетки с сигналами, управляемыми индикаторами, и кнопкой закрытия, описывая эти достижения в следующих подразделах:

  1. Схема информационной панели сканера
  2. Реализация средствами MQL5
  3. Тестирование на истории
  4. Заключение

Эти разделы помогут нам создать интуитивно понятную и мощную информационную панель управления торговлей.


Схема информационной панели сканера

Мы стремимся создать панель сканера по нескольким таймфреймам, предоставляющую четкие торговые сигналы в режиме реального времени для улучшения процесса принятия стратегических решений. Панель будет представлена в виде сетки, отображающей сигналы на покупку и продажу на нескольких таймфреймах, что позволит нам быстро оценивать рыночные условия, не переключая графики. Будет включена кнопка закрытия, позволяющая легко закрывать панель, обеспечивая понятный и гибкий пользовательский интерфейс, адаптируемый к нашим торговым потребностям.

Мы будем использовать сигналы от ключевых индикаторов, включая Индекс относительной силы (RSI), Стохастический осциллятор (STOCH), Индекс товарного канала (CCI), Индекс среднего направленного движения (ADX), а также Awesome Oscillator (Чудесный осциллятор) (AO), которые предназначены для определения потенциальных торговых возможностей с настраиваемыми пороговыми значениями силы. Тем не менее, выбор используемых индикаторов или данных о ценовом движении остается за вами. Такая настройка поможет определять тренды и развороты на разных таймфреймах, поддерживая как краткосрочные, так и долгосрочные стратегии. Наша цель - создать оптимизированный и интуитивно понятный инструмент, предоставляющий полезную информацию, оставаясь при этом удобным для пользователя, и проложит путь для будущих улучшений, таких как автоматические оповещения или дополнительные индикаторы. Ниже приведена визуализация того, к чему мы стремимся.

IMPLEMENTATION PLAN


Реализация средствами MQL5

Для создания программы на MQL5 нам нужно будет задать метаданные программы, а затем определить некоторые константы имен объектов, которые помогут ссылаться на объекты информационной панели и легко управлять ими.

//+------------------------------------------------------------------+
//|                             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

Начинаем с создания структуры пользовательского интерфейса для нашей панели сканера по нескольким таймфреймам, используя директиву #define для создания таких констант, как "MAIN_PANEL" и "HEADER_PANEL" для прямоугольников главной панели и панели заголовка, а также "HEADER_PANEL_ICON", "HEADER_PANEL_TEXT" и "CLOSE_BUTTON" для значка, наименования заголовка и элементов кнопок закрытия.

Определяем идентификаторы для сеточной структуры информационной панели. Для инструмента задаем "SYMBOL_RECTANGLE" и "SYMBOL_TEXT", в то время как префиксы "TIMEFRAME_RECTANGLE" и "TIMEFRAME_TEXT" обрабатывают ряды таймфреймов. Используем префиксы "HEADER_RECTANGLE" и "HEADER_TEXT" для заголовков столбцов, а также префиксы типа "RSI_RECTANGLE", "STOCH_RECTANGLE", "BUY_RECTANGLE" с соответствующими "RSI_TEXT", "STOCH_TEXT" и "BUY_TEXT" для индикаторных и сигнальных ячеек.

Настраиваем размеры с помощью "WIDTH_TIMEFRAME" (90 пикселей), "WIDTH_INDICATOR" (70 пикселей), "WIDTH_SIGNAL" (90 пикселей) и "HEIGHT_RECTANGLE" (25 пикселей). Определяем цвета, используя "COLOR_WHITE" и "COLOR_BLACK" для текста и границ, "COLOR_LIGHT_GRAY" ("C'230,230,230'") для фона сигналов и "COLOR_DARK_GRAY" ("C'105,105,105'") для индикаторов, обеспечивая единообразное и понятное расположение. Затем нужно определить еще несколько глобальных переменных, которые мы будем использовать на протяжении всей программы.

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

Здесь мы объявляем логическую переменную "panel_is_visible" и присваиваем ей значение true, определяющее, будет ли информационная панель отображаться на графике. Этот флаг позволяет изменять видимость информационной панели по мере необходимости, особенно когда нам не нужны обновления данных. Затем определяем массив "timeframes_array", используя тип ENUM_TIMEFRAMES, в котором перечисляются периоды от "PERIOD_M1" (1 минута) до "PERIOD_W1" (неделя). Этот массив определяет таймфреймы, которые будет анализировать информационная панель, что позволяет нам структурированно сканировать рыночные сигналы на нескольких временных горизонтах. Если какие-то таймфреймы вам не нужны или вы хотите изменить набор, просто отредактируйте перечисления.

Для хранения данных индикатора создаем двойные массивы "rsi_values", "stochastic_values", "cci_values", "adx_values" и "ao_values". Эти массивы содержат рассчитанные значения для Индекса относительной силы, Стохастического осциллятора, Индекса товарного канала, Индекса среднего направленного движения и Awesome Oscillator соответственно, что позволяет нам эффективно обрабатывать и отображать торговые сигналы для каждого таймфрейма. Теперь мы можем определить некоторые вспомогательные функции, которые будем использовать для определения направления сигнала и сокращённого отображения имени таймфрейма.

//+------------------------------------------------------------------+
//| 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
}

Здесь определяем функцию "truncate_timeframe_name", которая принимает целочисленный параметр "timeframe_index" для форматирования названий таймфреймов для отображения. Внутри мы используем StringSubstr для извлечения подстроки из результата функции EnumToString, примененной к "timeframes_array[timeframe_index]", начиная с позиции 7, и сохранить ее в "timeframe_string". Затем возвращаем "timeframe_string", предоставляя чистое, понятное пользователю название таймфрейма.

Создаем функцию "calculate_signal_strength" для определения сигналов на покупку или продажу на основе значений индикатора. Инициализируем целое число "signal_strength" равным нулю, чтобы подсчитать совпадающие условия. Для Индекса относительной силы увеличиваем значение "signal_strength", если значение "is_buy" равно true, а "rsi" ниже 40 (перепроданность), или если значение "is_buy" равно false, а "rsi" превышает 60 (перекупленность). Аналогично, проверяем "stochastic" (ниже 40 или выше 60), "CCI" (ниже -70 или выше 70) и "ao" (положительный для покупки, отрицательный для продажи), увеличивая "signal_strength" для каждого выполненного условия.

Мы также оцениваем Индекс среднего направленного движения, увеличивая значение "signal_strength", если значение "adx" превышает 40, что указывает на сильный тренд как для сценариев покупки, так и продажи. Если значение "signal_strength" достигает 3 или более, возвращаем значение “Strong Buy” для "is_buy" true или “Strong Sell” в противном случае. Если значение равно 2, возвращаем “Buy” или “Sell”, а при меньшем количестве - “Neutral”, что позволяет четко классифицировать сигналы информационной панели. Теперь мы можем определить функции, которые позволят нам создавать объекты.

//+------------------------------------------------------------------+
//| 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
}

Для возможности создания объектов определяем функцию "create_rectangle" с параметрами "object_name", "x_distance", "y_distance", "x_size", "y_size", "background_color", и "border_color". Используем ResetLastError,  создаем OBJ_RECTANGLE_LABEL с помощью функции ObjectCreate и регистрируем ошибки с помощью функции "Print", если это не удается, возвращая значение false.

Задаем свойства прямоугольника с помощью функции ObjectSetInteger для положения, размера, "CORNER_RIGHT_UPPER", "background_color", "border_color" и "BORDER_FLAT", обеспечивая отображение на переднем плане. Используем ChartRedraw и возвращаем значение true. Для текста определяем функцию "create_label" с параметрами "object_name", "text", "x_distance", "y_distance", "font_size", "text_color" и "font".

Используем "ResetLastError", создаем "OBJ_LABEL" с помощью функции "ObjectCreate" и регистрируем ошибки, если это не удается. Используем "ObjectSetInteger" для определения положения, размера, цвета и "ANCHOR_CENTER", а функцию ObjectSetString - для "text" и "font". Используем "ChartRedraw" и возвращаем значение true. Вооружившись этими функциями, теперь мы можем создать начальные объекты панели, которые послужат нам начальной точкой в обработчике "OnInit".

//+------------------------------------------------------------------+
//| 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
}

В обработчике OnInit инициализируем пользовательский интерфейс панели сканера по нескольким таймфреймам. Используем "create_rectangle", чтобы нарисовать "MAIN_PANEL" в точке (632, 40) размером 617x374 пикселя в “C’30,30,30’” и "HEADER_PANEL" в той же позиции с высотой 27 пикселей в “C’60,60,60’”. Используем "create_label", чтобы добавить "HEADER_PANEL_ICON" с символом Wingdings в точку (620, 54). Используем символы по умолчанию на MQL5 и используем функцию CharToString для преобразования кода символа в строку. Вот код символа, который мы использовали - 91, но вы можете использовать любой, какой вам больше нравится.

MQL5 WINGDINGS

Затем создаем "HEADER_PANEL_TEXT" с “TimeframeScanner” в (527, 52) и "CLOSE_BUTTON" в (32, 54), но на этот раз используем другой шрифт и сопоставляем букву "r" со строкой. Вот визуализация различных символов шрифта, которые можно использовать.

SYMBOLS FONT

Настраиваем отображение символа, используя функцию "create_rectangle" для "SYMBOL_RECTANGLE" в (630, 75), размером "WIDTH_TIMEFRAME" на "HEIGHT_RECTANGLE", серым цветом. Используем "create_label", чтобы поместить "SYMBOL_TEXT" в координату (585, 85) с текущим символом. Для заголовков определяем массив "header_names" с заголовками типа “BUY” и “RSI”, в цикле создаем "HEADER_RECTANGLE" при y=75 с x-смещениями на основе "WIDTH_SIGNAL" и "WIDTH_INDICATOR" и меток "HEADER_TEXT" при y=85, с помощью функции "create_label".

Создаём сетку таймфреймов, перебирая "timeframes_array". Используем "create_rectangle" для "TIMEFRAME_RECTANGLE" при x=630, y-смещениях от (75 + "HEIGHT_RECTANGLE"), скорректированную на -(1 + "timeframe_index"), окрашенную с помощью "timeframe_background". Используем "create_label" для "TIMEFRAME_TEXT" с именами из функции "truncate_timeframe_name". Для ячеек создаем цикл "BUY_RECTANGLE", "RSI_RECTANGLE" и т.д. с помощью функции "create_rectangle", используя "cell_background", и добавляем метки “-/-” с помощью функции "create_label". Инициализируем массивы индикаторов типа "rsi_values" с помощью функции ArraySetAsSeries, задавая их как временные ряды для обработки данных. Возвращаем INIT_SUCCEEDED для подтверждения успешной инициализации, формирования структуры информационной панели и структуры данных. После компиляции получаем следующий результат.

STATIC DASHBOARD

На изображении видно, что информационная панель у нас готова. Все, что нам сейчас нужно сделать, это добавить значения индикаторов и использовать их для анализа. У нас уже есть функция для анализа, нам просто нужно получить данные. Чтобы легко добиться этого, создаем функцию для обработки всей логики динамического обновления.

//+------------------------------------------------------------------+
//| 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
   }
}

Чтобы упростить управление обновлением значений на информационной панели, реализуем функцию "updateIndicators" для обновления значений индикаторов и сигналов. В цикле перебираем "timeframes_array", используя "timeframe_index", обрабатывая каждый таймфрейм. Используем функции iRSI, "iStochastic", "iCCI", iADX и "iAO" для создания хэндлов индикаторов типа "rsi_indicator_handle" для текущего инструмента и таймфрейма, настраивая такие параметры, как 14-периодный RSI и 20-периодный CCI. Все настройки индикаторов настраиваются в соответствии с вашими потребностями, поэтому не ограничивайте себя значениями по умолчанию.

Затем проверяем, равен ли какой-либо хэндл, такой как "rsi_indicator_handle", значению INVALID_HANDLE, что указывает на ошибку при создании. Если это так, используем "Print", чтобы вывести сообщение об ошибке с выводом функции "truncate_timeframe_name" и перейти к следующему таймфрейму. Используем CopyBuffer для извлечения последних значений в массивы типа "rsi_values", и в случае сбоя выводим сообщение об ошибке и продолжаем. Обновляем отображение индикаторов с помощью функции "update_label". Например, устанавливаем "rsi_text_color" на основе "rsi_values[0]" (синий, если <30, красный, если >70, иначе "COLOR_WHITE") и обновляем "RSI_TEXT" форматированным значением функции "DoubleToString". Повторяем это для "stochastic_values", "cci_values", "adx_values" и "ao_values", применяя цветовую логику (например, зеленый для положительных "ao_values").

Вычисляем сигналы, используя функцию "calculate_signal_strength", передавая "rsi_values[0]" и другие, чтобы получить "buy_signal" и "sell_signal". Производим настройку "buy_background" (например, зелёный для “Strong Buy”) и используем "update_rectangle" для "BUY_RECTANGLE", обновляя "BUY_TEXT" с помощью "update_label". Точно также делаем для "sell_background" и "SELL_TEXT". Наконец, используем IndicatorRelease для освобождения хэндлов, таких как "rsi_indicator_handle", обеспечивая эффективное управление ресурсами. Вспомогательные функции, которые мы использовали, определены следующим образом.

//+------------------------------------------------------------------+
//| 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
}

Определяем функцию "update_rectangle", принимая "object_name" и "background_color" в качестве параметров для изменения внешнего вида прямоугольников. Используем ObjectFind, чтобы найти прямоугольник, сохраняя результат в поле "found". Если значение "found" меньше 0, что указывает на отсутствие объекта, используем ResetLastError, выводим сообщение об ошибке с помощью функций "Print" и "GetLastError" и возвращаем значение false. Обновляем фон прямоугольника, используя функцию "ObjectSetInteger", чтобы установить для "OBJPROP_BGCOLOR" значение "background_color". Используем ChartRedraw, чтобы обновить график и возвращаем значение true в случае успеха. Для обновления текста определяем функцию "update_label" с помощью параметров "object_name", "text" и "text_color".

Используем "ObjectFind" для проверки существования метки, и если значение "found" отрицательное, используем "ResetLastError", выводим сообщение об ошибке с помощью функции "Print" и возвращаем значение false. Используем ObjectSetString, чтобы присвоить "OBJPROP_TEXT" значение "text", а функцию ObjectSetInteger - чтобы присвоить "OBJPROP_COLOR" значение "text_color". Используем "ChartRedraw" для обновления графика и возврата значения true, что позволяет динамически обновлять метки. Теперь мы можем вызвать функцию обновления на тике, чтобы внести изменения в информационную панель.

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

Здесь, в обработчике OnTick, просто вызываем функцию "updateIndicators", если панель видна, чтобы применить обновления. В конце концов, нам надо удалить созданные нами объекты так, чтобы они удалялись с этого графика тогда, когда они нам больше не нужны.

//+------------------------------------------------------------------+
//| 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
}

Наконец, мы реализуем процесс очистки с помощью функции OnDeinit, которая запускается при удалении советника. Используем ObjectDelete для удаления отдельных элементов пользовательского интерфейса, начиная с прямоугольника "MAIN_PANEL", за которым следуют "HEADER_PANEL", "HEADER_PANEL_ICON", "HEADER_PANEL_TEXT" и "CLOSE_BUTTON", гарантируя, что компоненты главной панели и заголовка будут удалены с графика.

Мы систематически удаляем все объекты информационной панели, используя функцию ObjectsDeleteAll для каждого типа элементов. Удаляем все прямоугольники и метки, связанные с "SYMBOL_RECTANGLE" и "SYMBOL_TEXT", "TIMEFRAME_RECTANGLE" и "TIMEFRAME_TEXT", а также "HEADER_RECTANGLE" и "HEADER_TEXT", очищая отображения символа, таймфрейма и заголовка. Также удаляем объекты, связанные с индикаторами, включая "RSI_RECTANGLE", "STOCH_RECTANGLE", "CCI_RECTANGLE", "ADX_RECTANGLE" и "AO_RECTANGLE", вместе с соответствующими текстовыми метками, такими как "RSI_TEXT".

Завершаем очистку, используя функцию "ObjectsDeleteAll", чтобы удалить все объекты "BUY_RECTANGLE" и "SELL_RECTANGLE" вместе с их метками "BUY_TEXT" и "SELL_TEXT", удалив все элементы, связанные с сигналом. Наконец, используем ChartRedraw для обновления графика, обеспечивая чистый вид после деинициализации. В итоге, нужно позаботиться о кнопке отмены, чтобы при нажатии на нее мы закрывали информационную панель и отключали дальнейшие обновления.

//+------------------------------------------------------------------+
//| 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
      }
   }
}

В обработчике OnChartEvent слушаем щелчки по объекту, когда идентификатором события является CHARTEVENT_OBJECT_CLICK, а нажатым объектом является кнопка отмены, и воспроизводим звуковой сигнал оповещения, используя PlaySound, чтобы оповестить пользователя о том, что панель отключается. Затем отключаем видимость панели и используем ту же логику, которую использовали для очистки графика в OnDeinit, чтобы очистить информационную панель. После компиляции получаем следующий результат.

UPDATED DASHBOARD

На изображении мы видим, что информационная панель обновлена с указанием данных индикатора и направлений торговли. Теперь остается только протестировать работоспособность проекта, и это рассматривается в следующем разделе.


Тестирование на истории

Мы провели тестирование, а ниже представлена скомпилированная визуализация в едином формате растрового изображения Graphics Interchange Format (GIF).

TESTING GIF


Заключение

В заключение, мы разработали панель сканера по нескольким таймфреймам на MQL5, объединяющую структурированную сеточную компоновку, сигналы индикаторов в режиме реального времени и интерактивную кнопку закрытия для улучшения стратегических торговых решений. Мы продемонстрировали дизайн и реализацию этих функций, гарантируя их эффективность благодаря надежной инициализации и динамическим обновлениям, адаптированным к нашим торговым требованиям. Можно адаптировать эту информационную панель в соответствии со своими предпочтениями, что значительно улучшит вашу способность отслеживать рыночные сигналы и действовать в соответствии с ними на нескольких таймфреймах.

Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/18319

Прикрепленные файлы |
Моделирование рынка (Часть 17): Сокеты (XI) Моделирование рынка (Часть 17): Сокеты (XI)
Реализация той части кода, которая будет работать в MetaTrader 5, не представляет сложности. Однако есть несколько моментов, которые нужно учитывать. Это необходимо для того, чтобы вы смогли заставить систему работать. Запомните одну важную вещь: будет запущена не одна программа. В реальности нам придётся запускать три программы одновременно. Важно реализовать и построить каждую из них так, чтобы они могли взаимодействовать и общаться одна с другой, и чтобы каждая из них понимала, что пытается или хочет сделать другая.
Нейросети в трейдинге: Адаптивная факторная токенизация (MTmixAtt) Нейросети в трейдинге: Адаптивная факторная токенизация (MTmixAtt)
Статья разбирает архитектуру MTmixAtt для адаптивной структуризации признаков и показывает первый шаг практической реализации в MQL5 — модуль AutoToken. Описаны выравнивание эмбеддингов, матрица выбора, механизм Top‑K и разреженная селекция. Приведен класс CNeuronAutoToken на базе OpenCL. Читатель получает работающий блок компрессии признакового пространства и основу для дальнейшего смешивания токенов и MoE.
Индикатор CandleCode: Формализация свечных моделей в MQL5 Индикатор CandleCode: Формализация свечных моделей в MQL5
В статье показана практическая реализация CandleCode для MetaTrader 5: расчет кодов свечей по методу Лиховидова с адаптацией порогов к волатильности (Bollinger Bands) и гистограммное отображение. Дополнительно представлен советник, который строит базу исторических паттернов по ZigZag, сравнивает их с текущим "слепком" через ATR и выдает статистику совпадений на панели.
Возможности Мастера MQL5, которые вам нужно знать (Часть 64): Использование паттернов каналов Демарка и конвертов с ядром белого шума Возможности Мастера MQL5, которые вам нужно знать (Часть 64): Использование паттернов каналов Демарка и конвертов с ядром белого шума
Осциллятор Демарка (DeMarker Oscillator) и конверты (Envelopes) — это инструменты, определяющие импульс и уровни поддержки/сопротивления, которые можно использовать в паре при разработке советника. В предыдущей статье были представлены эти два индикатора. Здесь же мы добавим к ним машинное обучение. Мы используем рекуррентную нейронную сеть, которая применяет ядро белого шума (white-noise kernel) для обработки векторизованных сигналов от этих двух индикаторов. Это делается в пользовательском файле класса сигналов (signal class), который взаимодействует с Мастером MQL5 для создания советника.