English Deutsch 日本語
preview
Рыночные секреты Ларри Уильямса (Часть 5): Автоматизация стратегии волатильного пробоя на MQL5

Рыночные секреты Ларри Уильямса (Часть 5): Автоматизация стратегии волатильного пробоя на MQL5

MetaTrader 5Индикаторы |
83 2
Chacha Ian Maroa
Chacha Ian Maroa

Введение

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

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

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


Понимание концепции волатильного пробоя

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

Измерение вчерашнего диапазона

Для начала мы смотрим на диапазон предыдущего дня, то есть просто на разницу между максимумом и минимумом предыдущего торгового дня.

Вчерашний диапазон

Этот диапазон служит ориентиром для выявления потенциальных пробоев. 

Почему важен диапазон предыдущего дня

Диапазон предыдущего дня дает нам точку отсчета. Когда сегодняшнее ценовое движение превышает определенный процент вчерашнего диапазона, это указывает на то, что рынок, вероятно, продолжит движение в этом направлении.

Как рассчитываются уровни пробоя от цены открытия текущего дня

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

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

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


Правила торговли

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

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

Когда диапазон известен, цена открытия текущего дня становится нашей точкой отсчета. От этой цены открытия мы рассчитываем два уровня: один выше открытия для потенциальной покупки и один ниже открытия для потенциальной продажи. Каждый уровень рассчитывается путем применения заданного пользователем процента вчерашнего диапазона. Эти расчетные уровни служат порогами волатильности: ценовое движение должно быть достаточно сильным, чтобы достичь их, прежде чем можно будет открыть сделку.

Расчетные уровни покупки и продажи

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

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

Затем уровень Take Profit рассчитывается на основе соотношения риск/прибыль. Расстояние между ценой входа и Stop Loss определяет риск. Заданный пользователем множитель прибыли определяет, насколько цель по прибыли должна быть больше относительно этого риска. Это гарантирует, что каждая сделка имеет измеримую и осознанную структуру потенциальной отдачи.

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

Суть этих правил проста: измерить волатильность, дождаться расширения, определить риск из того же источника волатильности и позволить цене подтвердить торговый сигнал. Именно эта простота делает стратегию пригодной для автоматизации и устойчивой на разных рынках.


Программирование стратегии волатильного пробоя

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

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

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

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

Теперь перейдем к практике. Откройте MetaEditor 5, создайте новый советник, выберите пустой шаблон, задайте ему любое имя и вставьте предоставленный исходный код.

//+------------------------------------------------------------------+
//|                                   lwVolatilityBreakoutExpert.mq5 |
//|          Copyright 2026, MetaQuotes Ltd. Developer is Chacha Ian |
//|                          https://www.mql5.com/en/users/chachaian |
//+------------------------------------------------------------------+

#property copyright "Copyright 2026, MetaQuotes Ltd. Developer is Chacha Ian"
#property link      "https://www.mql5.com/en/users/chachaian"
#property version   "1.00"

//+------------------------------------------------------------------+
//| Standard Libraries                                               |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>

//--- CUSTOM ENUMERATIONS
enum ENUM_TRADE_DIRECTION  
{ 
   ONLY_LONG, 
   ONLY_SHORT, 
   TRADE_BOTH 
};

enum ENUM_LOT_SIZE_INPUT_MODE 
{ 
   MODE_MANUAL, 
   MODE_AUTO 
};

//+------------------------------------------------------------------+
//| User input variables                                             |
//+------------------------------------------------------------------+
input group "Information"
input ulong magicNumber         = 254700680002;                 
input ENUM_TIMEFRAMES timeframe = PERIOD_CURRENT;

input group "Volatility Breakout Parameters"
input double inpBuyRangeMultiplier   = 0.50;   
input double inpSellRangeMultiplier  = 0.50;   
input double inpStopRangeMultiplier  = 0.50;
input double inpRewardValue          = 4.0;

input group "Trade and Risk Management"
input ENUM_TRADE_DIRECTION direction        = TRADE_BOTH;
input ENUM_LOT_SIZE_INPUT_MODE lotSizeMode  = MODE_AUTO;
input double riskPerTradePercent            = 1.0;
input double positionSize                   = 0.1;

//+------------------------------------------------------------------+
//| Global Variables                                                 |
//+------------------------------------------------------------------+
//--- Create a CTrade object to handle trading operations
CTrade Trade;

//--- Bid and Ask
double   askPrice;
double   bidPrice;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit(){

   //---  Assign a unique magic number to identify trades opened by this EA
   Trade.SetExpertMagicNumber(magicNumber);

   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason){

   //--- Notify why the program stopped running
   Print("Program terminated! Reason code: ", reason);

}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick(){

   //--- Retrieve current market prices for trade execution
   askPrice      = SymbolInfoDouble (_Symbol, SYMBOL_ASK);
   bidPrice      = SymbolInfoDouble (_Symbol, SYMBOL_BID);

}

//+------------------------------------------------------------------+
//| TradeTransaction function                                        |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction& trans,
                        const MqlTradeRequest& request,
                        const MqlTradeResult& result)
{
}

//--- UTILITY FUNCTIONS

//+------------------------------------------------------------------+

Этот файл служит базовым шаблоном, на котором будет построена вся стратегия.

Понимание структуры базового шаблона

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

Раздел заголовка содержит метаданные: имя файла, информацию об авторе, номер версии и ссылки.

//+------------------------------------------------------------------+
//|                                   lwVolatilityBreakoutExpert.mq5 |
//|          Copyright 2026, MetaQuotes Ltd. Developer is Chacha Ian |
//|                          https://www.mql5.com/en/users/chachaian |
//+------------------------------------------------------------------+

#property copyright "Copyright 2026, MetaQuotes Ltd. Developer is Chacha Ian"
#property link      "https://www.mql5.com/en/users/chachaian"
#property version   "1.00"

Хотя это не влияет на торговое поведение, это хорошая практика, особенно при передаче или публикации кода.

Раздел стандартных библиотек подключает библиотеку Trade.mqh.

//+------------------------------------------------------------------+
//| Standard Libraries                                               |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>

Это дает нам доступ к классу CTrade, который значительно упрощает исполнение ордеров и управление сделками. Использование классов стандартной библиотеки рекомендуется, поскольку они оптимизированы и поддерживаются компанией MetaQuotes.

Раздел пользовательских перечислений определяет контролируемые варианты входных параметров.

//--- CUSTOM ENUMERATIONS
enum ENUM_TRADE_DIRECTION  
{ 
   ONLY_LONG, 
   ONLY_SHORT, 
   TRADE_BOTH 
};

enum ENUM_LOT_SIZE_INPUT_MODE 
{ 
   MODE_MANUAL, 
   MODE_AUTO 
};

Например, направление торговли ограничено вариантами: только длинные позиции, только короткие позиции или оба направления. Аналогично режим размера лота позволяет переключаться между ручным заданием объема позиции и автоматическим расчетом на основе риска. Перечисления делают пользовательские параметры безопаснее и точнее.

Входные параметры пользователя и их роль

Входные переменные сгруппированы для ясности и удобства использования в панели настроек советника.

Раздел Information содержит magic number и timeframe.

//+------------------------------------------------------------------+
//| User input variables                                             |
//+------------------------------------------------------------------+
input group "Information"
input ulong magicNumber         = 254700680002;                 
input ENUM_TIMEFRAMES timeframe = PERIOD_CURRENT;

Magic number однозначно идентифицирует сделки, открытые этим советником, что крайне важно при программном управлении позициями. Параметр timeframe определяет, какие данные графика используются при измерении волатильности. Это напрямую связано с работой Ларри Уильямса, где диапазон предыдущего дня является центральным элементом стратегии.

Раздел Volatility Breakout Parameters содержит основные настройки стратегии.

input group "Volatility Breakout Parameters"
input double inpBuyRangeMultiplier   = 0.50;   
input double inpSellRangeMultiplier  = 0.50;   
input double inpStopRangeMultiplier  = 0.50;
input double inpRewardValue          = 4.0;

Параметры buy и sell range multipliers определяют, насколько далеко цена должна отойти от сегодняшнего открытия относительно вчерашнего диапазона, прежде чем будет достигнут уровень входа. Эти значения выражаются как доли диапазона предыдущего дня. Это отражает концепцию Ларри Уильямса: входить только после значимого расширения, а не после случайного ценового движения.

Параметр stop range multiplier управляет тем, как расстояние до Stop Loss рассчитывается на основе того же измерения волатильности. Привязывая стопы к волатильности, а не к фиксированному числу пунктов, стратегия естественно адаптируется к изменяющимся рыночным условиям.

Параметр reward value задает соотношение риск/прибыль. В подходе Ларри Уильямса выходы не являются произвольными. Они структурированы так, чтобы успешные волатильные расширения компенсировали несколько неудачных попыток.

Раздел Trade and Risk Management определяет, как контролируются сделки и рассчитывается их объем.

input group "Trade and Risk Management"
input ENUM_TRADE_DIRECTION direction        = TRADE_BOTH;
input ENUM_LOT_SIZE_INPUT_MODE lotSizeMode  = MODE_AUTO;
input double riskPerTradePercent            = 1.0;
input double positionSize                   = 0.1;

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

Параметр lot size mode определяет, будет ли размер позиции задан вручную или автоматически рассчитан на основе заранее заданного риска. При использовании автоматического расчета процент риска на сделку определяет долю баланса счета, которой трейдер рискует в каждой сделке. Это усиливает один из важнейших принципов в работе Ларри Уильямса: выживание через дисциплинированный контроль риска. Ручной размер позиции используется только тогда, когда автоматический расчет отключен.

Каждый из этих входных параметров будет использован позже, когда мы начнем рассчитывать уровни волатильности, цены входа, Stop Loss и цели Take Profit. 

Глобальные переменные и основные функции

Раздел глобальных переменных инициализирует объекты и общие данные, используемые во всем советнике. Объект CTrade обрабатывает все торговые операции. Цены Bid и Ask хранятся глобально для эффективного доступа во время выполнения.

//+------------------------------------------------------------------+
//| Global Variables                                                 |
//+------------------------------------------------------------------+
//--- Create a CTrade object to handle trading operations
CTrade Trade;

//--- Bid and Ask
double   askPrice;
double   bidPrice;

Функция OnInit выполняется один раз при загрузке советника. Здесь мы назначаем magic number, чтобы все сделки были правильно помечены.

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit(){

   //---  Assign a unique magic number to identify trades opened by this EA
   Trade.SetExpertMagicNumber(magicNumber);

   return(INIT_SUCCEEDED);
}

Функция OnDeinit выполняется при удалении советника или закрытии платформы. Запись причины завершения полезна при тестировании и отладке.

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason){

   //--- Notify why the program stopped running
   Print("Program terminated! Reason code: ", reason);

}

Функция OnTick — это обработчик, в котором советник реагирует на поступающие ценовые данные. На этом этапе она просто получает текущие цены Bid и Ask. Позже эта функция станет сердцем стратегии, где рассчитываются уровни волатильности и оцениваются торговые условия.

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick(){

   //--- Retrieve current market prices for trade execution
   askPrice      = SymbolInfoDouble (_Symbol, SYMBOL_ASK);
   bidPrice      = SymbolInfoDouble (_Symbol, SYMBOL_BID);

}

Функция OnTradeTransaction зарезервирована для обработки событий, связанных с торговлей.

//+------------------------------------------------------------------+
//| TradeTransaction function                                        |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction& trans,
                        const MqlTradeRequest& request,
                        const MqlTradeResult& result)
{
}

Пока она пуста, но позже будет полезна для мониторинга исполнений, закрытий и возможной логики управления сделками.

Наконец, раздел Utility Functions — это место, куда мы постепенно будем добавлять пользовательские вспомогательные функции.

//--- UTILITY FUNCTIONS

//+------------------------------------------------------------------+

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

Пересчет дневных уровней волатильности на новом баре

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

Для этой стратегии мы рассчитываем семь ключевых ценовых уровней. Первый — это вчерашний диапазон, представляющий собой разницу между максимумом и минимумом предыдущего бара. Из этого диапазона мы рассчитываем цены входа для длинной и короткой позиции. Затем рассчитываем соответствующие уровни Stop Loss для обоих направлений. Наконец, мы вычисляем уровни Take Profit с использованием заранее заданного множителя прибыли. Поскольку эти уровни должны пересчитываться только один раз в день, нам нужен надежный способ определить, что в выбранном таймфрейме сформировался новый бар.

Определение формирования нового бара

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

//--- UTILITY FUNCTIONS
//+------------------------------------------------------------------+
//| Function to check if there's a new bar on a given chart timeframe|
//+------------------------------------------------------------------+
bool IsNewBar(string symbol, ENUM_TIMEFRAMES tf, datetime &lastTm){

   datetime currentTm = iTime(symbol, tf, 0);
   if(currentTm != lastTm){
      lastTm       = currentTm;
      return true;
   }  
   return false;
   
}

Функция получает время открытия самого последнего бара с помощью функции iTime . Затем она сравнивает это значение с сохраненной временной меткой, представляющей последний обработанный бар. Если время изменилось, значит сформировался новый бар. Функция обновляет сохраненную временную метку и сигнализирует об этом изменении, возвращая true.

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

//--- To help track new bar open
datetime lastBarOpenTime;

Эта переменная отслеживает время открытия последнего обработанного бара и служит памятью, предотвращающей повторные расчеты в тот же день.

Во время инициализации советника эта переменная явно устанавливается в ноль.

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit(){
   ...
   
   //--- Initialize global variables
   lastBarOpenTime       = 0;

   return(INIT_SUCCEEDED);
}

Инициализация обеспечивает предсказуемое поведение при запуске советника и предотвращает случайное повторное использование старых значений.

Хранение дневных уровней волатильности в памяти

Поскольку рассчитанные уровни должны повторно использоваться в течение торгового дня, мы сохраняем их в структурированном контейнере, а не пересчитываем многократно. Для этой цели мы определяем пользовательскую структуру с именем MqlLwVolatilityLevels. Эта структура группирует все ценовые уровни, связанные с волатильностью, в одну логическую единицу. Она включает поля для вчерашнего диапазона, обеих цен входа, обоих уровней Stop Loss и обоих уровней Take Profit.

//--- Holds all price levels derived from Larry Williams' volatility breakout calculations
struct MqlLwVolatilityLevels
{
   double yesterdayRange;      
   double buyEntryPrice;       
   double sellEntryPrice;   
   double bullishStopLoss;   
   double bearishStopLoss;    
   double bullishTakeProfit;
   double bearishTakeProfit;
};

MqlLwVolatilityLevels lwVolatilityLevels;

После определения структуры мы создаем один глобальный экземпляр с именем lwVolatilityLevels. Этот экземпляр хранит активные дневные уровни и делает их легко доступными во всем советнике.

Во время инициализации мы устанавливаем все поля этой структуры в ноль с помощью функции ZeroMemory .

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit(){

   ...
   
   //--- Reset Larry Williams' volatility levels 
   ZeroMemory(lwVolatilityLevels);

   return(INIT_SUCCEEDED);
}

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

Расчет вчерашнего диапазона

Основа стратегии — вчерашний ценовой диапазон. Для его вычисления мы определяем вспомогательную функцию с именем GetBarRange.

//+------------------------------------------------------------------+
//| Returns the price range (high - low) of a bar at the given index |
//+------------------------------------------------------------------+
double GetBarRange(const string symbol, ENUM_TIMEFRAMES tf, int index){

   double high = iHigh(symbol, tf, index);
   double low  = iLow (symbol, tf, index);

   if(high == 0.0 || low == 0.0){
      return 0.0;
   }

   return NormalizeDouble(high - low, Digits());
}

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

Вычисление цен входа по пробою

Используя доступный диапазон, мы рассчитываем цены входа по пробою. Цена входа в длинную позицию рассчитывается путем прибавления доли вчерашнего диапазона к сегодняшней цене открытия. Эта логика реализована в функции CalculateBuyEntryPrice .

//+------------------------------------------------------------------+
//| Calculates the bullish breakout entry price using today's open and yesterday's range |
//+------------------------------------------------------------------+
double CalculateBuyEntryPrice(double todayOpen, double yesterdayRange, double buyMultiplier){

   return todayOpen + (yesterdayRange * buyMultiplier);
}

Входной множитель позволяет трейдеру управлять тем, насколько агрессивным или консервативным должен быть уровень пробоя.

Аналогично цена входа в короткую позицию вычисляется путем вычитания доли вчерашнего диапазона из цены открытия текущего дня. Эта логика обрабатывается функцией CalculateSellEntryPrice .

//+------------------------------------------------------------------+
//| Calculates the bearish breakout entry price using today's open and yesterday's range |
//+------------------------------------------------------------------+
double CalculateSellEntryPrice(double todayOpen, double yesterdayRange, double sellMultiplier){

   return todayOpen - (yesterdayRange * sellMultiplier);
}

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

Расчет уровней Stop Loss

Контроль риска занимает центральное место в методологии Ларри Уильямса. Уровни Stop Loss задаются относительно цены входа с использованием той же меры волатильности.

Для длинных сделок Stop Loss размещается ниже цены входа на заданную долю вчерашнего диапазона. Этот расчет выполняется функцией CalculateBullishStopLoss .

//+------------------------------------------------------------------+
//| Calculates the stop-loss price for a bullish position based on entry price and yesterday's range |
//+------------------------------------------------------------------+
double CalculateBullishStopLoss(double entryPrice, double yesterdayRange, double stopMultiplier){

   return entryPrice - (yesterdayRange * stopMultiplier);
}

Для коротких сделок Stop Loss размещается выше цены входа по той же логике, реализованной в функции CalculateBearishStopLoss .

//+------------------------------------------------------------------+
//| Calculates the stop-loss price for a bearish position based on entry price and yesterday's range |
//+------------------------------------------------------------------+
double CalculateBearishStopLoss(double entryPrice, double yesterdayRange, double stopMultiplier){

   return entryPrice + (yesterdayRange * stopMultiplier);
}

Использование стопов на основе волатильности гарантирует, что риск адаптируется к изменяющимся рыночным условиям, а не остается фиксированным.

Расчет уровней Take Profit

Уровни Take Profit рассчитываются на основе соотношения риска и прибыли, а не произвольной ценовой цели. Для длинных сделок расстояние между ценой входа и Stop Loss определяет риск. Это расстояние умножается на множитель прибыли для определения цели. Функция CalculateBullishTakeProfit применяет эту логику и размещает Take Profit выше цены входа.

//+------------------------------------------------------------------+
//| Calculates take-profit level for a bullish trade using risk-reward logic |                               
//+------------------------------------------------------------------+
double CalculateBullishTakeProfit(double entryPrice, double stopLossPrice, double rewardValue){

   double stopDistance   = entryPrice - stopLossPrice;
   double rewardDistance = stopDistance * rewardValue;
   return NormalizeDouble(entryPrice + rewardDistance, Digits());
}

Для коротких сделок та же логика применяется в обратном направлении. Функция CalculateBearishTakeProfit вычисляет расстояние прибыли и вычитает его из цены входа.

//+------------------------------------------------------------------+
//| Calculates take-profit level for a bearish trade using risk-reward logic |                               
//+------------------------------------------------------------------+
double CalculateBearishTakeProfit(double entryPrice, double stopLossPrice, double rewardValue){

   double stopDistance   = stopLossPrice - entryPrice;
   double rewardDistance = stopDistance * rewardValue;
   return NormalizeDouble(entryPrice - rewardDistance, Digits());
}

Такой подход сохраняет прибыль пропорциональной риску и соответствует принципам дисциплинированного управления сделками.

Объединение всего на новом баре

Когда все вспомогательные функции готовы, мы объединяем их внутри функции OnTick . Всякий раз, когда в терминал поступают новые ценовые данные, советник сначала обновляет текущие цены Bid и Ask. Затем он проверяет, сформировался ли новый бар, используя функцию IsNewBar.

Когда обнаружен новый бар, советник пересчитывает все уровни волатильности в ясной и логичной последовательности.

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick(){

   ...  
   
   //--- Run this block only when a new bar is detected on the selected timeframe
   if(IsNewBar(_Symbol, timeframe, lastBarOpenTime)){
      lwVolatilityLevels.yesterdayRange    = GetBarRange(_Symbol, timeframe, 1);
      lwVolatilityLevels.buyEntryPrice     = CalculateBuyEntryPrice (askPrice, lwVolatilityLevels.yesterdayRange, inpBuyRangeMultiplier );
      lwVolatilityLevels.sellEntryPrice    = CalculateSellEntryPrice(bidPrice, lwVolatilityLevels.yesterdayRange, inpSellRangeMultiplier);
      lwVolatilityLevels.bullishStopLoss   = CalculateBullishStopLoss(lwVolatilityLevels.buyEntryPrice, lwVolatilityLevels.yesterdayRange,  inpStopRangeMultiplier);
      lwVolatilityLevels.bearishStopLoss   = CalculateBearishStopLoss(lwVolatilityLevels.sellEntryPrice, lwVolatilityLevels.yesterdayRange, inpStopRangeMultiplier);
      lwVolatilityLevels.bullishTakeProfit = CalculateBullishTakeProfit(lwVolatilityLevels.buyEntryPrice, lwVolatilityLevels.bullishStopLoss,  inpRewardValue);
      lwVolatilityLevels.bearishTakeProfit = CalculateBearishTakeProfit(lwVolatilityLevels.sellEntryPrice, lwVolatilityLevels.bearishStopLoss, inpRewardValue);
   }
}

Сначала вычисляется вчерашний диапазон. Затем этот диапазон используется для расчета цен входа, после чего рассчитываются уровни Stop Loss и, наконец, уровни Take Profit. Каждое вычисленное значение сохраняется внутри структуры lwVolatilityLevels. С этого момента эти значения остаются постоянными в течение дня и могут эффективно использоваться логикой исполнения сделок.

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

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

Завершение торговой логики и исполнение сделок

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

Логика волатильного пробоя Ларри Уильямса проста в исполнении. Как только цена выходит за заранее заданный уровень, рынок сигнализирует о намерении. Мы не прогнозируем направление, а реагируем на расширение. Это означает, что наш советник не действует, пока цена явно не пересечет уровень входа для длинной или короткой позиции. Чтобы сделать это надежно, сначала нужно научить советник распознавать событие пересечения цены.

Определение пересечения вверх

Первая вспомогательная функция, которую мы вводим, определяет, когда цена пересекает определенный уровень снизу вверх. Именно это запускает потенциальную длинную сделку.

//+------------------------------------------------------------------+
//| To detect a crossover at a given price level                     |                               
//+------------------------------------------------------------------+
bool IsCrossOver(const double price, const double &closePriceMinsData[]){
   if(closePriceMinsData[1] <= price && closePriceMinsData[0] > price){
      return true;
   }
   return false;
}

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

Определение пересечения вниз

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

//+------------------------------------------------------------------+
//| To detect a crossunder at a given price level                    |                               
//+------------------------------------------------------------------+
bool IsCrossUnder(const double price, const double &closePriceMinsData[]){
   if(closePriceMinsData[1] >= price && closePriceMinsData[0] < price){
      return true;
   }
   return false;
}

Здесь предыдущее закрытие должно быть выше уровня или равно ему, а самое последнее закрытие должно быть ниже него. Это подтверждает медвежье расширение и становится триггером для короткой сделки.

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

Чтобы это было возможно, массив объявляется в глобальной области видимости, чтобы к нему можно было обращаться из любой части советника.

//--- To store minutes data
double closePriceMinutesData [];

Во время инициализации советника он явно устанавливается как временной ряд.

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit(){
   ...
   
   //--- Treat the following arrays as timeseries (index 0 becomes the most recent bar)
   ArraySetAsSeries(closePriceMinutesData, true);

   return(INIT_SUCCEEDED);
}

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

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

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick(){

   ...
   
   //--- Get some minutes data
   if(CopyClose(_Symbol, PERIOD_M1, 0, 7, closePriceMinutesData) == -1){
      Print("Error while copying minutes datas ", GetLastError());
      return;
   }
}

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

Предотвращение нескольких одновременных сделок

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

За это отвечают две вспомогательные функции. Первая просматривает все открытые позиции и проверяет, есть ли активная позиция на покупку, открытая этим советником.

//+------------------------------------------------------------------+
//| To verify whether this EA currently has an active buy position.  |                                 |
//+------------------------------------------------------------------+
bool IsThereAnActiveBuyPosition(ulong magic){
   
   for(int i = PositionsTotal() - 1; i >= 0; i--){
      ulong ticket = PositionGetTicket(i);
      if(ticket == 0){
         Print("Error while fetching position ticket ", _LastError);
         continue;
      }else{
         if(PositionGetInteger(POSITION_MAGIC) == magic && PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY){
            return true;
         }
      }
   }
   
   return false;
}

Она делает это, сравнивая magic number позиции и тип позиции. Если найдена соответствующая позиция на покупку, функция возвращает true. Вторая функция делает то же самое для позиций на продажу.

//+------------------------------------------------------------------+
//| To verify whether this EA currently has an active sell position. |                                 |
//+------------------------------------------------------------------+
bool IsThereAnActiveSellPosition(ulong magic){
   
   for(int i = PositionsTotal() - 1; i >= 0; i--){
      ulong ticket = PositionGetTicket(i);
      if(ticket == 0){
         Print("Error while fetching position ticket ", _LastError);
         continue;
      }else{
         if(PositionGetInteger(POSITION_MAGIC) == magic && PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL){
            return true;
         }
      }
   }
   
   return false;
}

Разделение проверок покупки и продажи оставляет логику простой для дальнейшего расширения, если позже будут добавлены дополнительные фильтры или правила.

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

Автоматический расчет размера позиции

Управление риском — ключевая часть работы Ларри Уильямса. Вместо торговли произвольными размерами лота риск определяется как процент от баланса счета. Функция расчета размера позиции напрямую реализует эту концепцию.

//+------------------------------------------------------------------+
//| Calculates position size based on a fixed percentage risk of the account balance |
//+------------------------------------------------------------------+
double CalculatePositionSizeByRisk(double stopDistance){
   double amountAtRisk = (riskPerTradePercent / 100.0) * AccountInfoDouble(ACCOUNT_BALANCE);
   double contractSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_CONTRACT_SIZE);
   double volume       = amountAtRisk / (contractSize * stopDistance);
   return NormalizeDouble(volume, 2);
}

Сначала она вычисляет денежную сумму, которой трейдер готов рискнуть, исходя из баланса счета и настроенного процента риска. Затем она преобразует этот риск в объем, учитывая размер контракта торгуемого инструмента и расстояние до Stop Loss. Это гарантирует, что в каждой сделке под риском находится постоянная доля счета независимо от рыночной волатильности или размера Stop Loss. Итоговое значение нормализуется до нужной точности, обеспечивая совместимость с требованиями брокера к объему.

Открытие позиции на покупку

Функция исполнения покупки обрабатывает все, что требуется для открытия длинной сделки.

//+------------------------------------------------------------------+
//| Function to open a market buy position                           |
//+------------------------------------------------------------------+
bool OpenBuy(double entryPrice, double stopLoss, double takeProfit, double lotSize){
   
   if(lotSizeMode == MODE_AUTO){
      lotSize = CalculatePositionSizeByRisk(lwVolatilityLevels.buyEntryPrice - lwVolatilityLevels.bullishStopLoss);
   }
   
   if(!Trade.Buy(lotSize, _Symbol, entryPrice, stopLoss, takeProfit)){
      Print("Error while executing a market buy order: ", GetLastError());
      Print(Trade.ResultRetcode());
      Print(Trade.ResultComment());
      return false;
   }
   return true;
}

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

Открытие позиции на продажу

Функция исполнения продажи зеркально повторяет логику покупки, но с противоположным направлением.

//+------------------------------------------------------------------+
//| Function to open a market sell position                          |
//+------------------------------------------------------------------+
bool OpenSel(double entryPrice, double stopLoss, double takeProfit, double lotSize){
   
   if(lotSizeMode == MODE_AUTO){
      lotSize = CalculatePositionSizeByRisk(lwVolatilityLevels.bearishStopLoss - lwVolatilityLevels.sellEntryPrice);
   }
   
   if(!Trade.Sell(lotSize, _Symbol, entryPrice, stopLoss, takeProfit)){
      Print("Error while executing a market sell order: ", GetLastError());
      Print(Trade.ResultRetcode());
      Print(Trade.ResultComment());
      return false;
   }
   return true;
}

Она рассчитывает размер позиции с использованием расстояния до медвежьего стопа и отправляет рыночный ордер на продажу с соответствующей ценой входа, Stop Loss и Take Profit. Эта симметрия гарантирует единообразную обработку длинных и коротких сделок, снижая вероятность логических ошибок и упрощая сопровождение кода.

Объединение всего в функции тика

Когда все компоненты готовы, функция тика становится центром управления советником.

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick(){

   ...
   
   //--- Long position logic
   if(direction == TRADE_BOTH || direction == ONLY_LONG){
      if(IsCrossOver(lwVolatilityLevels.buyEntryPrice, closePriceMinutesData)){
         if(!IsThereAnActiveBuyPosition(magicNumber) && !IsThereAnActiveSellPosition(magicNumber)){
            OpenBuy(askPrice, lwVolatilityLevels.bullishStopLoss, lwVolatilityLevels.bullishTakeProfit, positionSize);
         }
      }
   }
   
   //--- Short position logic
   if(direction == TRADE_BOTH || direction == ONLY_SHORT){
      if(IsCrossUnder(lwVolatilityLevels.sellEntryPrice, closePriceMinutesData)){
         if(!IsThereAnActiveBuyPosition(magicNumber) && !IsThereAnActiveSellPosition(magicNumber)){
            OpenSel(bidPrice, lwVolatilityLevels.bearishStopLoss, lwVolatilityLevels.bearishTakeProfit, positionSize);
         }
      }
   }
}

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

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

Повышение визуальной ясности во время тестирования

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

//+------------------------------------------------------------------+
//| This function configures the chart's appearance.                 |
//+------------------------------------------------------------------+
bool ConfigureChartAppearance()
{
   if(!ChartSetInteger(0, CHART_COLOR_BACKGROUND, clrWhite)){
      Print("Error while setting chart background, ", GetLastError());
      return false;
   }
   
   if(!ChartSetInteger(0, CHART_SHOW_GRID, false)){
      Print("Error while setting chart grid, ", GetLastError());
      return false;
   }
   
   if(!ChartSetInteger(0, CHART_MODE, CHART_CANDLES)){
      Print("Error while setting chart mode, ", GetLastError());
      return false;
   }

   if(!ChartSetInteger(0, CHART_COLOR_FOREGROUND, clrBlack)){
      Print("Error while setting chart foreground, ", GetLastError());
      return false;
   }

   if(!ChartSetInteger(0, CHART_COLOR_CANDLE_BULL, clrSeaGreen)){
      Print("Error while setting bullish candles color, ", GetLastError());
      return false;
   }
      
   if(!ChartSetInteger(0, CHART_COLOR_CANDLE_BEAR, clrBlack)){
      Print("Error while setting bearish candles color, ", GetLastError());
      return false;
   }
   
   if(!ChartSetInteger(0, CHART_COLOR_CHART_UP, clrSeaGreen)){
      Print("Error while setting bearish candles color, ", GetLastError());
      return false;
   }
   
   if(!ChartSetInteger(0, CHART_COLOR_CHART_DOWN, clrBlack)){
      Print("Error while setting bearish candles color, ", GetLastError());
      return false;
   }
   
   return true;
}

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

Функция вызывается во время инициализации.

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit(){

   ...
   
   //--- To configure the chart's appearance
   if(!ConfigureChartAppearance()){
      Print("Error while configuring chart appearance", GetLastError());
      return INIT_FAILED;
   }

   return(INIT_SUCCEEDED);
}

Если настройка графика завершается ошибкой, советник прекращает загрузку. Это гарантирует, что среда правильно подготовлена до начала торговли.

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


Результаты бэктестинга

Чтобы проверить стратегию в реалистичной среде, советник был протестирован на золоте XAUUSD с использованием дневного таймфрейма. Период бэктеста охватывает время с 1 января 2025 года по 30 ноября 2025 года, то есть одиннадцать месяцев недавней рыночной активности на момент написания статьи.

Результаты обнадеживают. При начальном балансе десять тысяч долларов США система достигла роста чуть более 60% за период тестирования. Реализованная прибыль составила шесть тысяч двести три доллара и сорок девять центов.

Tester Results

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

Equity Curve

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

Чтобы вам было проще воспроизвести похожие результаты, к этой статье прикреплены два файла. Файл configurations.ini содержит настройки тестовой среды, а файл parameters.set содержит входные значения, использованные во время бэктеста. Вы можете загрузить эти файлы непосредственно в тестер стратегий MetaTrader 5 и запустить тот же тест у себя.

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

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

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


Заключение

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

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

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

В таблице ниже приведено краткое описание всех файлов, прикрепленных к этой статье.


Имя файла Описание
1 lwVolatilityBreakoutExpert.mq5 Полный исходный код советника Volatility Breakout на MQL5, пошагово разработанного в этой статье.
2 configurations.ini Файл конфигурации тестера стратегий используется во время бэктестинга для воспроизведения тестовой среды.
3 parameters.set Файл входных параметров, использованный для бэктеста, результаты которого обсуждаются в этой статье.

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

Прикрепленные файлы |
configurations.ini (1.61 KB)
parameters.set (1.49 KB)
Последние комментарии | Перейти к обсуждению на форуме трейдеров (2)
ronh_pm
ronh_pm | 8 февр. 2026 в 16:50
Добрый день,

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

Всего хорошего!
Chacha Ian Maroa
Chacha Ian Maroa | 27 апр. 2026 в 11:40
ronh_pm # : Думаю, есть много читателей, подобных мне, которые с огромным удовольствием следят за вашим постоянным накоплением знаний, уроками и обменem открытиями по всем темам, которые вы освещаете. Спасибо.




Я уверен, что так и есть.
От начального до среднего уровня: FileSave и FileLoad От начального до среднего уровня: FileSave и FileLoad
В сегодняшней статье рассмотрим некоторые способы работы с библиотечными функциями FileSave и FileLoad. Хотя многие считают их малоперспективными из-за некоторых ограничений или трудностей, которые они вызывают в определенных сценариях, правильное понимание того, как работают эти две функции, может сэкономить нам много работы в определенные моменты. Кроме того, они являются отличным способом работы с лог-файлами.
Преодоление проблем доступности в торговых инструментах на MQL5 (Часть II): Включению голосовых функций в советнике с помощью Python-движка синтеза речи Преодоление проблем доступности в торговых инструментах на MQL5 (Часть II): Включению голосовых функций в советнике с помощью Python-движка синтеза речи
Давайте обсудим, как можно сделать наших советников разговорчивыми, используя технологию преобразования текста в речь, при совместном применении Python и MQL5. После прочтения этой статьи вы ознакомитесь с рабочим примером советника, который озвучивает динамическую рыночную информацию. Вы освоите применение TTS (преобразование текста в речь), функции WebRequest, и узнаете, как библиотеки Python интегрируются с языком MQL5 для создания по‑настоящему голосового торгового инструмента.
Нейросети в трейдинге: Когнитивная инерция в анализе финансовых рынков (CogDriver) Нейросети в трейдинге: Когнитивная инерция в анализе финансовых рынков (CogDriver)
В статье показана адаптация фреймворка CogDriver из автономного вождения к анализу финансовых рынков с упором на когнитивную инерцию и временную согласованность решений. Разбирается удержание рыночной гипотезы и её проверка на новых данных для снижения дрожания сигналов. Практический раздел вводит класс CNeuronCogDriverData, который нормализует признаки, накапливает стек состояний и формирует MarketStateDensity-представления как фундамент дальнейшего планирования.
Архитектура прибыльной торговли с усиленной многоуровневой защитой счёта Архитектура прибыльной торговли с усиленной многоуровневой защитой счёта
В этом материале мы представляем структурированную многоуровневую систему защиты, нацеленную на достижение амбициозных показателей прибыли при одновременном снижении риска катастрофических потерь. Основное внимание уделяется сочетанию агрессивной торговой логики с защитными механизмами на каждом этапе торгового процесса. Идея состоит в том, чтобы создать советника, который ведёт себя как «хищник, осознающий риск»: способен находить торговые возможности с высоким потенциалом, но всегда имеет несколько защитных слоёв, не позволяющих системе «ослепнуть» при внезапном рыночном стрессе.