English
preview
Разработка объектно-ориентированного сканера разрывов справедливой стоимости (FVG) на MQL5

Разработка объектно-ориентированного сканера разрывов справедливой стоимости (FVG) на MQL5

MetaTrader 5 — Торговые системы |
63 0
Amanda Vitoria De Paula Pereira
Amanda Vitoria De Paula Pereira

Разработка объектно-ориентированного сканера разрывов справедливой стоимости (FVG) на MQL5

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

Один из наиболее значимых следов институционального потока ордеров — разрыв справедливой стоимости (Fair Value Gap), обычно обозначаемый как FVG или называемый разрывом ликвидности. Автоматизация обнаружения этих дисбалансов позволяет алгоритмическим системам без запаздывания получать высокоточные зоны интереса для определения точек входа и выхода без запаздывания. В этой статье описывается, как создать объектно-ориентированный сканер разрывов справедливой стоимости на языке MQL5. Мы задаем геометрию формации из трех свечей, загружаем данные с помощью CopyRates, обеспечиваем безопасное управление графическими объектами и добавляем проверки митигации, чтобы определять моменты заполнения разрывов.


Микроструктура и математическая геометрия дисбалансов

Прежде чем выразить эту концепцию средствами синтаксиса MQL5, необходимо строго определить геометрию разрыва справедливой стоимости, чтобы избежать ложных срабатываний. Разрыв справедливой стоимости — это формация строго из трех свечей, указывающая на временный дефицит ликвидности на одной из сторон стакана заявок. На бычьем макроэкономическом фоне бычий FVG возникает, когда максимум первой свечи не перекрывается с минимумом третьей, так что все тело крупной второй свечи остается без противодействия со стороны продавцов. Определите индексы следующим образом: 1 — последняя закрытая свеча, 2 — импульсная свеча, 3 — исходная свеча. Бычий дисбаланс — это диапазон между максимумом свечи с индексом 3 и минимумом свечи с индексом 1.

И наоборот, медвежий разрыв ликвидности возникает во время резкого импульсного движения вниз. В этом случае минимум исходной свечи (индекс 3) остается значительно выше максимума последней закрытой свечи (индекс 1). Немитигированная область между этими двумя ценовыми уровнями отражает серьезный дефицит ликвидности со стороны покупателей. Институциональные алгоритмы ориентируются на эти ценовые уровни, поскольку цена часто возвращается в зону разрыва, чтобы заполнить ордера, после чего продолжает движение по основному тренду. Основа нашей архитектуры сканирования — жестко заданная в коде логика сравнения именно этих трех свечей.

Print



Фрактальная ликвидность и согласование таймфреймов

Финансовые рынки имеют строго фрактальную природу: микроструктурные дисбалансы, обнаруженные на минутном графике, математически и функционально идентичны тем, которые формируются на недельном таймфрейме. Однако разрабатывать алгоритмическую систему для торговли по внутридневному разрыву справедливой стоимости в полной изоляции от остального рыночного контекста — серьезный статистический просчет. Институциональные модели накладывают матрицу нескольких таймфреймов и требуют подтверждать бычий FVG микроуровня только в том случае, если он формируется в зоне премии/дисконта блока ордеров старшего таймфрейма.

Такое фрактальное согласование служит основным фильтром направления и помогает снизить вызванное рыночным шумом падение доли прибыльных сделок. Разработчикам, использующим наш базовый класс сканера FVG для дальнейшего развития, настоятельно рекомендуется создавать два отдельных объекта: один сканер — для анализа часового таймфрейма, другой — для работы на пятиминутном графике, на котором выполняются торговые операции. Прежде чем разрешать какую-либо отрисовку на экране терминала, следует убедиться, что локальный геометрический дисбаланс имеет весомую поддержку со стороны макроэкономической динамики.


Объектно-ориентированная инкапсуляция ценового движения (Price Action)

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

//+------------------------------------------------------------------+
//| Class: CFVGScanner                                               |
//| Purpose: Detects, draws, and manages Fair Value Gaps             |
//+------------------------------------------------------------------+
class CFVGScanner
  {
private:
   string            m_symbol;            // Target symbol for the scanner
   ENUM_TIMEFRAMES   m_timeframe;         // Target timeframe
   int               m_history_bars;      // Depth of historical scan
   string            m_obj_prefix;        // Prefix for graphical objects
   
   color             m_color_bullish;     // Color for bullish imbalances
   color             m_color_bearish;     // Color for bearish imbalances

   void              DrawRectangle(string name, datetime time1, double price1, datetime time2, double price2, color clr);
   void              ClearOldObjects(void);

public:
                     CFVGScanner(string symbol, ENUM_TIMEFRAMES tf, int depth);
                    ~CFVGScanner(void);
                    
   void              ScanAndDraw(void);
   void              SetColors(color bull, color bear);
  };

//+------------------------------------------------------------------+
//| Constructor: Initializes the environment and routing variables   |
//+------------------------------------------------------------------+
CFVGScanner::CFVGScanner(string symbol, ENUM_TIMEFRAMES tf, int depth)
  {
   m_symbol = (symbol == "") ? _Symbol : symbol;
   m_timeframe = tf;
   m_history_bars = (depth < 10) ? 10 : depth;
   m_obj_prefix = "FVG_" + m_symbol + "_" + EnumToString(m_timeframe) + "_";
   
   m_color_bullish = clrDarkGreen;
   m_color_bearish = clrMaroon;
  }



Синхронизация динамических массивов с помощью CopyRates

Для оценки структурной геометрии рынка алгоритм должен получать исходные данные о ценах открытия и закрытия, максимумах и минимумах (OHLC) непосредственно из кэша исторических данных на сервере брокера. Для этой операции в MQL5 предусмотрена высокооптимизированная функция CopyRates, которая заполняет массив структур MqlRates. Поскольку мы анализируем последовательность из трех свечей, необходимо динамически получать данные при появлении каждого нового бара. Мы используем функцию ArraySetAsSeries чтобы задать массиву формат временного ряда с обратной индексацией. Функция ArraySetAsSeries задает обратный порядок индексации: индекс 0 соответствует текущей незавершенной свече, значения которой продолжают меняться, а индекс 1 — последнему полностью сформированному историческому бару.

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


Механизм сканирования и логика митигации

Основной цикл сканирования обходит в обратном направлении корректно заполненный массив структур MqlRates. Для каждой подтвержденной свечи механизм сканирования анализирует соотношение данных свечей с индексами i (исходная свеча), i-1 (импульсная свеча) и i-2 (подтверждающая свеча). Если максимум исходной свечи строго ниже минимума подтверждающей свечи, математически подтверждается бычий разрыв ликвидности. Однако обнаружение разрыва — это лишь первый логический этап. Финансовые рынки динамичны, и через несколько часов или дней последующая динамика цены часто приводит к митигации или заполнению этих разрывов.

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

//+------------------------------------------------------------------+
//| Core Engine: Extracts data, evaluates geometry, and filters voids|
//+------------------------------------------------------------------+
void CFVGScanner::ScanAndDraw(void)
  {
   MqlRates rates[];
   ArraySetAsSeries(rates, true);
   
   if(CopyRates(m_symbol, m_timeframe, 0, m_history_bars, rates) < m_history_bars)
     {
      PrintFormat("Warning: Failed to synchronize %s history for FVG scanner.", m_symbol);
      return;
     }
     
   ClearOldObjects();
   
   for(int i = m_history_bars - 1; i >= 3; i--)
     {
      double origin_high = rates[i].high;
      double origin_low  = rates[i].low;
      
      double confirm_high = rates[i-2].high;
      double confirm_low  = rates[i-2].low;
      
      bool is_bullish_fvg = (origin_high < confirm_low);
      bool is_bearish_fvg = (origin_low > confirm_high);
      
      if(is_bullish_fvg)
        {
         bool is_mitigated = false;
         for(int j = i - 3; j >= 1; j--)
           {
            if(rates[j].low <= origin_high) 
              { is_mitigated = true; break; }
           }
           
         if(!is_mitigated)
           {
            string name = m_obj_prefix + "BULL_" + IntegerToString(i);
            DrawRectangle(name, rates[i].time, confirm_low, rates[1].time, origin_high, m_color_bullish);
           }
        }
        
      if(is_bearish_fvg)
        {
         bool is_mitigated = false;
         for(int j = i - 3; j >= 1; j--)
           {
            if(rates[j].high >= origin_low) 
              { is_mitigated = true; break; }
           }
           
         if(!is_mitigated)
           {
            string name = m_obj_prefix + "BEAR_" + IntegerToString(i);
            DrawRectangle(name, rates[i].time, origin_low, rates[1].time, confirm_high, m_color_bearish);
           }
        }
     }
  }



Вычислительная сложность и эффективность обхода массива

При работе с огромными массивами, содержащими тысячи структур MqlRates с историческими данными, задержка выполнения алгоритма становится критическим ограничением производительности. В неэффективно реализованных сканерах часто используются вложенные циклы полного перебора, которые на каждом тике анализируют всю историю графика от начала до конца. Их асимптотическая сложность — O(N²), то есть квадратичная. Такое катастрофическое архитектурное решение приводит к полному зависанию терминала во время инициализации и резко снижает частоту кадров пользовательского интерфейса.

В нашей архитектуре сканирования намеренно используется один основной цикл с математически заданными границами обхода, проходящий массив в обратном направлении, что обеспечивает строго линейную сложность O(N). Кроме того, вложенный цикл проверки митигации прерывается ровно в ту миллисекунду, когда подтверждается касание тенью свечи, означающее митигацию, что позволяет избежать лишних тактов процессора. Такой высокопроизводительный обход памяти гарантирует, что механизм сканирования сможет без сбоев обрабатывать тиковые данные за десятилетия, не создавая задержек при исполнении сделок.


Импульс, подтвержденный объемом, и проверка институционального участия

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

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


Механика алгоритмического исполнения: лимитные ордера и подтверждение для входа по рынку

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

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


Динамика спреда Bid-Ask и явления фронтраннинга

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

Если алгоритм разрешает вход в рынок только при абсолютно точном касании ценового экстремума исходной свечи, он будет систематически упускать высокоприбыльные макроэкономические развороты. Профессиональные разработчики учитывают эту асимметрию проскальзывания, добавляя непосредственно к графическим координатам допуск в размере доли спреда и искусственно расширяя зону интереса на 1-2 пункта. Этот программно заданный допуск компенсирует задержки и гарантирует участие советника в институциональной волне митигации, даже если рыночная цена не достигает абсолютного структурного равновесия на бесконечно малую величину.


Управление памятью при работе с графическими прямоугольниками

Отображение визуальных элементов непосредственно на графике MetaTrader 5 требует точной настройки параметров ObjectCreate и ObjectSet. Разрыв справедливой стоимости лучше всего представлять объектом класса OBJ_RECTANGLE, для построения ограничивающего прямоугольника которого нужны две разные временные и две разные ценовые координаты. Мы протягиваем прямоугольник по оси времени от исходной свечи вперед до последней закрытой свечи, чтобы визуально обозначить протяженность зоны на экране. Для профессионального оформления мы явно отключаем заливку и настраиваем линии границ так, чтобы случайные щелчки пользователя не могли их изменить.

При программном создании графических объектов управление памятью и жизненным циклом объектов имеет решающее значение. Алгоритм, работающий на минутном таймфрейме, будет выполнять цикл сканирования более тысячи раз в день. Если старые прямоугольники не удалять, в терминале могут накопиться тысячи объектов. Это может привести к исчерпанию ресурсов и зависанию терминала (а возможно, и операционной системы). Мы реализуем специальный деструктор и метод очистки перед сканированием. С помощью функции ObjectsDeleteAll и нашего уникального строкового префикса механизм сканирования точно определяет и удаляет только ранее созданные им прямоугольники, не затрагивая трендовые линии, построенные пользователем вручную.

//+------------------------------------------------------------------+
//| Renders the institutional imbalance zone on the chart canvas     |
//+------------------------------------------------------------------+
void CFVGScanner::DrawRectangle(string name, datetime time1, double price1, datetime time2, double price2, color clr)
  {
   if(ObjectFind(0, name) < 0)
     {
      ObjectCreate(0, name, OBJ_RECTANGLE, 0, time1, price1, time2, price2);
      ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
      ObjectSetInteger(0, name, OBJPROP_STYLE, STYLE_SOLID);
      ObjectSetInteger(0, name, OBJPROP_WIDTH, 1);
      ObjectSetInteger(0, name, OBJPROP_BACK, false);
      ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
      ObjectSetInteger(0, name, OBJPROP_HIDDEN, true);
     }
   else
     {
      ObjectSetInteger(0, name, OBJPROP_TIME, 1, time2);
     }
  }

//+------------------------------------------------------------------+
//| Prevents memory leaks by purging outdated graphical objects      |
//+------------------------------------------------------------------+
void CFVGScanner::ClearOldObjects(void)
  {
   ObjectsDeleteAll(0, m_obj_prefix);
  }

//+------------------------------------------------------------------+
//| Public method to allow developers to customize the visual output |
//+------------------------------------------------------------------+
void CFVGScanner::SetColors(color bull, color bear)
  {
   m_color_bullish = bull;
   m_color_bearish = bear;
  }



Переход к институциональному подходу и итоговая архитектура

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

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

//+------------------------------------------------------------------+
//|                                              EA_FVG_Scanner.mq5  |
//|                                  Copyright 2026, MetaQuotes Ltd. |
//+------------------------------------------------------------------+
#property copyright "Open Source"
#property version   "1.00"

//--- Input Parameters for the Scanner Engine
input int InpHistoryDepth = 100; // Historical Bars to Evaluate

//--- Global Pointer to the encapsulated scanner object
CFVGScanner *g_fvg_engine;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   g_fvg_engine = new CFVGScanner(_Symbol, PERIOD_CURRENT, InpHistoryDepth);
   g_fvg_engine.SetColors(clrLimeGreen, clrRed);
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   if(CheckPointer(g_fvg_engine) == POINTER_DYNAMIC)
     {
      delete g_fvg_engine;
     }
  }

//+------------------------------------------------------------------+
//| Expert tick function with strict CPU optimization                |
//+------------------------------------------------------------------+
void OnTick()
  {
   static datetime last_bar_time = 0;
   datetime current_bar_time = iTime(_Symbol, PERIOD_CURRENT, 0);
   
   if(current_bar_time != last_bar_time)
     {
      last_bar_time = current_bar_time;
      
      if(CheckPointer(g_fvg_engine) != POINTER_INVALID)
        {
         g_fvg_engine.ScanAndDraw();
        }
     }
  }
//+------------------------------------------------------------------+


Заключение

В соответствии с изложенными требованиями в статье представлена компактная и расширяемая реализация, которая переводит концепцию в готовое к использованию решение. Среди предоставленных в статье решений и гарантий — объектно-ориентированный класс CFVGScanner, который инкапсулирует обнаружение, отрисовку и управление жизненным циклом. В нем можно настроить символ, таймфрейм и глубину истории. Он обеспечивает детерминированное определение геометрии FVG на основе строгого сравнения трех свечей для бычьих и медвежьих разрывов ликвидности.

Архитектура обеспечивает надежную обработку данных с помощью CopyRates и ArraySetAsSeries, предусматривая проверку и корректное прерывание сканирования при недостатке исторических данных, чтобы предотвратить выход за пределы массива. Кроме того, фильтр митигации использует вложенный цикл просмотра последующих свечей, чтобы отсеивать разрывы, которых цена уже коснулась после их формирования. Это гарантирует отображение только активных немитигированных зон. Безопасная отрисовка на графике обеспечивается присвоением объектам имен с уникальным префиксом и их выборочным удалением, что позволяет не затрагивать пользовательские построения и предотвращать утечки ресурсов. Наконец, защита процессора гарантируется тем, что при интеграции в советник метод ScanAndDraw запускается только при появлении нового бара, а не на каждом тике.

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

Имя файла
Описание
EA_FVG_Scanner.mq5
Полный исходный код, объединяющий класс FVG и цикл оптимизации нагрузки на процессор.

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

Прикрепленные файлы |
EA_FVG_Scanner.mq5 (7.32 KB)
Нейросети в трейдинге: Habi — быстрое принятие решений без сложного планирования (вероятностное представление) Нейросети в трейдинге: Habi — быстрое принятие решений без сложного планирования (вероятностное представление)
Рассматриваем реализацию вероятностных компонентов Habi на MQL5 и OpenCL: обработку рыночных наблюдений, преобразование параметров нормального распределения и пакетное семплирование латентных векторов. На примере CNeuronHabiObservationOCL, CNeuronHabiGaussianOCL и CNeuronHabiVAEOCL разбираем архитектуру, инициализацию, прямой и обратный проходы. Показываем согласование Prior и Posterior через условную KL-дивергенцию и накопление градиентов от нескольких выборок. Полученные компоненты создают основу для последующей генерации торговых действий.
Создание системы торговой аналитики (Часть 3): Сохранение данных о сделках MetaTrader 5 в SQLite Создание системы торговой аналитики (Часть 3): Сохранение данных о сделках MetaTrader 5 в SQLite
В этой статье мы расширим бэкенд на Flask, чтобы надежно принимать, проверять и сохранять данные о закрытых сделках из MetaTrader 5 с помощью SQLite и Flask-SQLAlchemy. В нем реализованы проверка обязательных полей, преобразование временных меток, сохранение данных в транзакциях с откатом при ошибке и работающие эндпоинты получения всех сделок, отдельных записей и базовой сводки. В результате получается полноценный пайплайн данных с локальным тестированием: он сохраняет записи о сделках и предоставляет доступ к ним через структурированный API для дальнейшего анализа.
Особенности написания экспертов Особенности написания экспертов
Написание и тестирование экспертов в торговой системе MetaTrader 4.
Renko внутри советника: построение по тикам без offline-графика Renko внутри советника: построение по тикам без offline-графика
Покажу, как строить Renko прямо внутри советника на MQL5 — без offline-графиков и пользовательских символов. Разберём развороты на один и два кирпича, обработку нескольких кирпичей за тик и типичные ошибки. Проверим повторяемость построения и выгрузим результат в CSV. К статье приложены класс CRenkoBuilder и демонстрационный советник.