English 中文 Español Deutsch 日本語 Português
preview
Пример стохастической оптимизации и оптимального управления

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

MetaTrader 5Трейдинг |
465 0
Javier Santiago Gaston De Iriarte Cabrera
Javier Santiago Gaston De Iriarte Cabrera

Введение в стохастическое моделирование и оптимизацию управления

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

Стохастическое моделирование используется для описания систем со случайными элементами, такими как движение цен на фондовом рынке или очередь в ресторане. Оно основано на случайных переменных, распределениях вероятностей и стохастических процессах. Такие методы, как Монте-Карло (Monte Carlo) и цепи Маркова (Markov chains), позволяют моделировать эти процессы и прогнозировать их поведение.

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

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


Советник

В советнике SMOC (Smart Money Optimal Control (Оптимальное управление умными деньгами) используется комбинация технических индикаторов, математических моделей и методов управления рисками для принятия торговых решений на рынке Форекс в качестве простого примера, демонстрирующего его возможности.

Основные характеристики:

  1. Прогнозирующая модель управления: Советник использует оптимальный алгоритм управления для прогнозирования будущих движений цены и принятия торговых решений.
  2. Адаптивные параметры: система корректирует горизонт прогноза и размер лота в зависимости от волатильности рынка и просадки счета.
  3. Множественные технические индикаторы: Включают в себя простые скользящие средние (SMA), parabolic SAR, индекс относительной силы (RSI) и средний истинный диапазон (ATR) для анализа тренда и волатильности.
  4. Динамический уровень стоп-лосс и тейк-профит: Советник рассчитывает и обновляет уровни SL и TP на основе волатильности рынка.
  5. Управление рисками: Включает в себя функции для регулировки размера позиции в зависимости от баланса и просадки счета.

Возможные области применения:

  • Среднесрочные и долгосрочные торговые стратегии
  • Рынки с ярко выраженными тенденциями
  • Портфели, требующие комплексного управления рисками

Преимущества:

  1. Адаптивный подход: система адаптируется к изменяющимся рыночным условиям, что потенциально повышает ее устойчивость.
  2. Комплексный анализ: объединяя множество индикаторов и математических моделей, он направлен на отражение различных аспектов поведения рынка.
  3. Учет рисков: советник включает в себя защиту от просадок и динамическое определение размера позиции.
  4. Подробное ведение журнала: Журнал регистрации ведется для анализа эффективности и отладки.

Недостатки:

  1. Сложность: Сложные алгоритмы могут затруднить понимание и оптимизацию системы.
  2. Интенсивные вычисления: Расчеты оптимального управления могут быть трудоемкими с точки зрения вычислений, что потенциально ограничивает их использование в менее мощных системах.
  3. Потенциальное переобучение: При большом количестве параметров и индикаторов существует риск чрезмерной адаптации к историческим данным.
  4. Рыночное допущение: Эффективность стратегии основана на предположении, что поведение цен в прошлом может предсказать будущие изменения, что не всегда верно на финансовых рынках.


Основные характеристики советника SMOC

Управление на основе прогнозирующих моделей (MPC): Советник использует оптимальный алгоритм управления для прогнозирования будущих движений цены и принятия торговых решений. Это реализовано в функции OptimalControl().
//+------------------------------------------------------------------+
//| Function for optimal control using Model Predictive Control      |
//+------------------------------------------------------------------+
int OptimalControl( double currentPrice)
  {
   int predictionHorizon = CalculateAdaptiveHorizon();
   double mu = EstimateDrift();
   double sigma = EstimateVolatility();
   double baseThreshold = 0.001 ;
   double decisionThreshold = baseThreshold * ( 1 + ( 1 - successRate));
   double dt = 1.0 / 1440.0 ;

   double bestExpectedReturn = - DBL_MAX ;
   int bestDecision = 0 ;
   double bestU1 = 0 , bestU2 = 0 ;

// Optimize the search space
   double u1Start = 0.01 , u1End = 0.99 , u1Step = 0.01 ;
   double u2Start = 0.01 , u2End = 0.99 , u2Step = 0.01 ;

// Calculate historical average price
   int lookbackPeriod = 20 ; // You can adjust this
   double historicalPrices[];
   ArraySetAsSeries (historicalPrices, true );
   CopyClose ( Symbol (), PERIOD_CURRENT , 0 , lookbackPeriod, historicalPrices);
   double avgHistoricalPrice = ArraySum(historicalPrices) / lookbackPeriod;

   for ( double u1 = u1Start; u1 <= u1End; u1 += u1Step)
     {
       for ( double u2 = u2Start; u2 <= u2End; u2 += u2Step)
        {
         double expectedReturn = CalculateExpectedReturn(currentPrice, mu, sigma, dt, predictionHorizon, u1, u2);

         // Compare with historical average
         if (currentPrice > avgHistoricalPrice)
           {
            expectedReturn *= - 1 ; // Invert expected return to favor selling when price is high
           }

         if (expectedReturn > bestExpectedReturn)
           {
            bestExpectedReturn = expectedReturn;
            bestU1 = u1;
            bestU2 = u2;
           }
        }
     }

   LogMessage( StringFormat ( "OptimalControl - Best u1: %f, Best u2: %f, Best Expected Return: %f, Decision Threshold %f" ,
                           bestU1, bestU2, bestExpectedReturn, decisionThreshold));

   if (bestExpectedReturn > decisionThreshold)
       return 1 ; // Buy
   if (bestExpectedReturn < decisionThreshold)
       return - 1 ; // Sell
   return 0 ; // Hold
  }

Для принятия оптимальных торговых решений используется Управление на основе прогнозирующих моделей (MPC). Функция OptimalControl является ядром этого алгоритма, предназначенного для определения того, покупать, продавать или придерживать, исходя из текущих рыночных условий и прогнозов.

Функция OptimalControl принимает текущую цену в качестве входных данных и возвращает целое число, представляющее торговое решение:

  • 1 на покупку
  • -1 на продажу
  • 0 на удержание

Ключевые компоненты
  1. Адаптивный горизонт прогнозирования: Функция вычисляет адаптивный горизонт прогнозирования, позволяя алгоритму корректировать диапазон прогноза в зависимости от рыночных условий.
  2. Оценка рыночных параметров: Оценивает ключевые параметры рынка:
    • Дрейф (μ): Ожидаемая доходность актива
    • Волатильность (σ): скорость изменения цены актива.
  3. Порог принятия решения: Динамический порог рассчитывается на основе базового порога и коэффициента успешного выполнения алгоритма. Он адаптирует чувствительность алгоритма к изменениям на рынке.
  4. Процесс оптимизации: Функция использует поиск по сетке для оптимизации двух управляющих параметров (u1 и u2) в определенном пространстве поиска.
  5. Историческое сравнение цен: Текущая цена сравнивается со средним значением за прошлые периоды, чтобы скорректировать стратегию в зависимости от того, является ли текущая цена относительно высокой или низкой.
  6. Расчет ожидаемой доходности: Для каждой комбинации управляющих параметров ожидаемая доходность вычисляется с помощью отдельной функции (не показанной в этом фрагменте кода).
  7. Принятие решений: На основе наилучшей ожидаемой доходности и порога принятия решения, принимается решение о покупке, продаже или удержании актива.
Подробный обзор
  1. Функция запускается с инициализации переменных и вычисления необходимых параметров.
  2. Затем она вводит вложенный цикл для поиска оптимальных параметров управления (u1 и u2).
  3. Для каждой комбинации u1 и u2 вычисляется ожидаемая доходность.
  4. Если текущая цена выше средней за прошлые периоды, ожидаемая доходность меняется на противоположную. Это создает предубеждение в пользу продажи при высоких ценах и покупки при низких.
  5. Она отслеживает наилучшую ожидаемую доходность и соответствующие контрольные показатели.
  6. После оптимизации регистрируются наилучшие параметры и ожидаемая прибыльность.
  7. Наконец, она сравнивает наилучшую ожидаемую доходность с пороговым значением для принятия торгового решения.
Ключевые идеи
  • Алгоритм адаптируется к рыночным условиям, используя адаптивный горизонт и динамический порог.
  • Это включает в себя как краткосрочную оптимизацию (с использованием подхода MPC), так и долгосрочное понимание тенденций (с использованием исторических сравнений цен).
  • Использование сетевого поиска для оптимизации позволяет тщательно изучить пространство параметров, что потенциально ведёт к принятию более надежных решений.
Возможные улучшения
  1. Для повышения производительности поиск по сетке может быть заменен более эффективным алгоритмом оптимизации.
  2. Сравнение исторических цен можно сделать более сложным, возможно, включив в него множественные таймфреймы.
  3. Чтобы сбалансировать оптимизацию доходности с минимизацией рисков, можно добавить функции управления рисками.
 /+------------------------------------------------------------------+
//| Calculate expected return for given parameters                   |
//+------------------------------------------------------------------+
double CalculateExpectedReturn( double currentPrice, double mu, double sigma, double dt, int horizon, double u1, double u2)
  {
   double tempPrice = currentPrice;
   double totalReturn = 0 ;

   for ( int i = 0 ; i < horizon; i++)
     {
       double Z = MathSqrt (- 2.0 * MathLog (u1)) * MathCos ( 2.0 * M_PI * u2);
       double nextPrice = tempPrice * MathExp ((mu - 0.5 * sigma * sigma) * dt + sigma * MathSqrt (dt) * Z);
      totalReturn += nextPrice - tempPrice;
      tempPrice = nextPrice;
     }

   return totalReturn / horizon;
  }

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

 double CalculateExpectedReturn( double currentPrice, double mu, double sigma, double dt, int horizon, double u1, double u2)
Параметры
  1. currentPrice : Текущая цена актива
  2. mu : Параметр сноса (ожидаемая доходность)
  3. sigma: параметр волатильности
  4. dt: Временной шаг (обычно 1/количество шагов в год)
  5. Horizon: Количество временных шагов для моделирования.
  6. u1, u2: Случайные числа, используемые для генерации нормально распределенных случайных переменных.

Обзор функций

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

Подробное объяснение
  1. Инициализация:
    • tempPrice инициализируется до текущей цены.
    • totalReturn устанавливается на 0 для накопления прибыли.
  2. Цикл моделирования: Функция входит в цикл, который пересекает горизонт времени. В каждой итерации: Генерирует случайную нормальную переменную :
 double Z = MathSqrt (- 2.0 * MathLog (u1)) * MathCos ( 2.0 * M_PI * u2);

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

Расчет следующей цены:

 double nextPrice = tempPrice * MathExp ((mu - 0.5 * sigma * sigma) * dt + sigma * MathSqrt (dt) * Z);
Данная строка реализует формулу геометрического броуновского движения:
  • (mu - 0.5 * sigma * sigma) * dt - компонент дрейфа
  • sigma * MathSqrt(dt) * Z - случайный компонент потрясений

Совокупный доход:

totalReturn += nextPrice - tempPrice;

Функция вычисляет и накапливает доход за каждый шаг.

Обновление цены:

tempPrice = nextPrice;

Текущая цена обновляется для следующей итерации.

Расчет среднего дохода:

 return totalReturn / horizon;

Функция возвращает среднюю доходность за моделируемый горизонт.

Важность финансового моделирования
  1. Оценка рисков: Моделируя множество траекторий изменения цен, данная функция помогает оценить потенциальные риски, связанные с активом.
  2. Ценообразование опционов: Этот тип моделирования является основополагающим в моделях ценообразования опционов, особенно в методах Монте-Карло.
  3. Оптимизация портфеля: Ожидаемая доходность является ключевым фактором в алгоритмах оптимизации портфеля.
  4. Торговые стратегии: Алгоритмические торговые стратегии часто используют ожидаемую доходность для принятия решений о покупке/продаже.


Ограничения и нюансы

  1. Допущения модели: Модель GBM предполагает, что доход обычно распределен и независим, что не всегда может быть правдой на реальных рынках.
  2. Оценка параметров: Точность функции во многом зависит от корректной оценки значений mu и sigma.
  3. Однократное моделирование: Данная функция выполняет однократное моделирование. На практике для получения более надежной оценки часто проводится многократное моделирование.
  4. Временной горизонт: Выбор horizon и dt может существенно повлиять на результаты и должен быть тщательно подобран в зависимости от конкретного случая использования.

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

Адаптивные параметры: система корректирует горизонт прогноза и размер лота на основании волатильности рынка и просадки счета. Это достигается при использовании таких функций, как CalculateAdaptiveHorizon() и AdjustLotSizeForDrawdown().

//+------------------------------------------------------------------+
//| Calculate adaptive horizon                                       |
//+------------------------------------------------------------------+
int CalculateAdaptiveHorizon()
  {
   double currentVolatility = EstimateVolatility();
   int baseHorizon = 5 ;
   return MathMax (baseHorizon, MathMin ( 20 , ( int )(baseHorizon * ( 1 + currentVolatility))));
  }
 // Función para ajustar el tamaño del lote basado en drawdown
double AdjustLotSizeForDrawdown()
  {
   static int consecutiveLosses = 0 ;
   static double maxBalance = 0 ;

   double currentBalance = AccountInfoDouble ( ACCOUNT_BALANCE );
   double currentEquity = AccountInfoDouble ( ACCOUNT_EQUITY );

   if (currentBalance > maxBalance)
      maxBalance = currentBalance;

   double drawdown = (maxBalance - currentEquity) / maxBalance;

   double baseLotSize = CalculateDynamicLotSize();

   if (drawdown > 0.1 ) // 10% drawdown
     {
       return baseLotSize * 0.5 ; // Reducir el tamaño del lote a la mitad
     }
   else
       if (consecutiveLosses > 3 )
        {
         return baseLotSize * 0.75 ; // Reducir el tamaño del lote en un 25%
        }

   return baseLotSize;
  }

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


Обзор функций

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

  1. Текущая просадка торгового счета
  2. Количество последовательных поражений
Ключевые компоненты
  1. Статические переменные:
    • consecutiveLosses: отслеживает количество последовательных убыточных сделок
    • maxBalance: поддерживает максимальный баланс, достигнутый на счете
  2. Информация по счету:
    • currentBalance: Текущее сальдо торгового счета
    • currentEquity: Текущий объем собственного капитала на торговом счете
  3. Расчет просадки: Просадка рассчитывается как процентное уменьшение от максимального сальдо до текущего значения собственного капитала.
  4. Базовый размер лота: Функция вызывает CalculateDynamicLotSize() (не показано в этом фрагменте) для определения базового размера лота.
  5. Регулировка размера лота: Функция регулирует размер лота в зависимости от двух условий:
    • Если просадка превышает 10%
    • Если было более 3 последовательных убытков

Подробное объяснение

Максимальное обновление баланса:
 if (currentBalance > maxBalance)
   maxBalance = currentBalance;

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

Расчет просадки:

 double drawdown = (maxBalance - currentEquity) / maxBalance;

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

Получение базового размера лота:

 double baseLotSize = CalculateDynamicLotSize();

Вызывается отдельная функция для расчета начального размера лота.

Корректировка на большую просадку:

 if (drawdown > 0.1 ) // 10% drawdown
  {
   return baseLotSize * 0.5 ; // Reduce lot size by half
  }

Если просадка превышает 10%, функция уменьшает размер лота вдвое, чтобы снизить риск.

Корректировка последовательных убытков:

 else if (consecutiveLosses > 3 )
  {
   return baseLotSize * 0.75 ; // Reduce lot size by 25%
  }

Если было более 3 последовательных убытков, функция снижает размер лота на 25%.

Возврат значения по умолчанию: Если ни одно из условий не выполняется, функция возвращает базовый размер лота без корректировки.

Важность в управлении рисками:
  1. Защита от просадки: Уменьшая размер лота во время значительных просадок, эта функция помогает защитить счет от дальнейших убытков при неблагоприятных рыночных условиях.
  2. Управление полосами неудач: Корректировка на последовательные убытки помогает смягчить последствия череды неудач, которые могут быть разрушительными в психологическом и финансовом плане.
  3. Динамическая корректировка рисков: Данная функция позволяет динамично управлять своими рисками, приспосабливаясь к текущим рыночным условиям и результатам торговли.


Соображения и возможные улучшения

  1. Постепенная корректировка: Данная функция может быть изменена для реализации более постепенной корректировки размеров лотов на основании различных уровней просадки.
  2. Механизм восстановления: Можно добавить дополнительный механизм для постепенного увеличения размера лота по мере восстановления счета после просадки.
  3. Максимальный размер лота: Введение ограничения на максимальный размер лота может обеспечить дополнительный уровень управления рисками.
  4. Трекинг выигрышей: Данная функция может быть расширена для отслеживания последовательных выигрышей и потенциального увеличения размеров лотов в течение благоприятных периодов.

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

Несколько технических индикаторов: советник включает в себя несколько технических индикаторов для анализа:
  • Простая скользящая средняя (SMA)
  • Parabolic SAR
  • Индекс относительной силы (RSI)
  • Средний истинный диапазон (ATR)
 // Initialize indicator handles
   smaHandle = iMA ( Symbol (), PERIOD_CURRENT , 50 , 0 , MODE_SMA , PRICE_CLOSE );
   psarHandle = iSAR ( Symbol (), PERIOD_CURRENT , 0.02 , 0.2 );
   rsiHandle = iRSI ( Symbol (), PERIOD_CURRENT , 14 , PRICE_CLOSE );
   atrHandle = iATR ( Symbol (), PERIOD_CURRENT , 14 );
Динамический уровень стоп-лосс и тейк-профит: Советник рассчитывает и обновляет уровни SL и TP на основе волатильности рынка с помощью функций CalculateDynamicSL() и CalculateDynamicTP().
     double CalculateDynamicSL( double price, int decision)
      {
       double atrValue[];
       if ( CopyBuffer (atrHandle, 0 , 0 , 1 , atrValue) <= 0 )
         {
          LogMessage( StringFormat ( "Error getting ATR values: %d" , GetLastError ()));
           return 0.0 ;
         }
       double volatility = atrValue[ 0 ];
       double dynamicSL = (decision == 1 ) ? price - (volatility * multi * 1.2 ) : price + (volatility * multi * 0.8 );
    
       return NormalizeDouble (dynamicSL, _Digits );
      }
    
    
    double CalculateDynamicTP( double price, int decision)
      {
       double atrValue[];
       if ( CopyBuffer (atrHandle, 0 , 0 , 1 , atrValue) <= 0 )
         {
          LogMessage( StringFormat ( "Error getting ATR values: %d" , GetLastError ()));
           return 0.0 ;
         }
       double volatility = atrValue[ 0 ];
       double dynamicTP = (decision == 1 ) ? price + (volatility * multi * 1.8 ) : price - (volatility * multi * 2.2 );
    
       return NormalizeDouble (dynamicTP, _Digits );
      }

    Данная функция рассчитывает динамические уровни стоп-лосса (SL) и тейк-профита (TP) на основе текущей волатильности рынка, улучшая управление рисками и потенциально улучшая результаты торговли.


    Обзоры функций

    Обе функции используют индикатор Средний истинный диапазон (ATR) для измерения волатильности рынка и соответствующей корректировки уровней SL и TP. Они учитывают, является ли сделка решением на покупку (1) или продажу (-1).

     double CalculateDynamicSL( double price, int decision)

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

     double CalculateDynamicTP( double price, int decision)

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

    Ключевые компоненты
    1. Индикатор ATR: Обе функции используют индикатор ATR для измерения волатильности рынка.
    2. Цена: Текущая рыночная цена актива.
    3. Решение: Целое число (1 для покупки, предположительно -1 для продажи), указывающее направление торговли.
    4. Множитель: Глобальная переменная multi используется для корректировки влияния волатильности.


    Подробное объяснение

    Функция CalculateDynamicSL

    Получим значение ATR :

     double atrValue[];
    if ( CopyBuffer (atrHandle, 0 , 0 , 1 , atrValue) <= 0 )
    {
       LogMessage( StringFormat ( "Error getting ATR values: %d" , GetLastError ()));
       return 0.0 ;
    }
    double volatility = atrValue[ 0 ];

    Данный код извлекает последнее значение ATR, отражающее волатильность рынка.

    Рассчитаем динамический SL :

     double dynamicSL = (decision == 1 ) ? price - (volatility * multi * 1.2 ) : price + (volatility * multi * 0.8 );
  1. Для сделки на покупку (решение== 1) он устанавливает SL ниже текущей цены.
  2. Для сделки на продажу SL устанавливается выше текущей цены.
  3. Расстояние рассчитывается как кратное ATR, скорректированное с использованием переменной multi и коэффициента (1,2 для покупок, 0,8 для продаж, я сделал это, чтобы показать разницу в статье).
  4. Нормализуем и вернем:

     return NormalizeDouble (dynamicSL, _Digits );

    Значение SL нормализуется до соответствующего количества знаков после запятой для торгуемого инструмента.


    Функция CalculateDynamicTP

    Получим значение ATR: Эта часть идентична функции SL.

      Рассчитаем динамический TP:
       double dynamicTP = (decision == 1 ) ? price + (volatility * multi * 1.8 ) : price - (volatility * multi * 2.2 );
    1. Для сделки на покупку TP устанавливается выше текущей цены.
    2. Для сделки на продажу TP устанавливается ниже текущей цены.
    3. Расстояние рассчитывается как кратное ATR, скорректированное переменной multi и коэффициента (1,8 для покупок, 2,2 для продаж, я сделал это, чтобы показать разницу, вы можете это делать по мере надобности).

    4. Нормализуем и вернем: аналогично функции SL.


      Важность в трейде

      1. Управление рисками на основе волатильности : Используя ATR, эти функции адаптируют уровни SL и TP к текущим рыночным условиям, обеспечивая более адекватное управление рисками.
      2. Асимметричное соотношение риска и прибыли : Уровни TP устанавливаются дальше от цены входа, чем уровни SL, что потенциально создает благоприятное соотношение риска и прибыли.
      3. Динамическая корректировка: По мере изменения волатильности рынка эти функции автоматически корректируют уровни SL и TP для новых сделок.
      Соображения и возможные улучшения
      1. Обработка ошибок : Обе функции имеют базовую обработку ошибок для получения ATR, но ее можно расширить.
      2. Настройка : Множители (1.2, 0.8, 1.8, 2.2) можно преобразовать в параметры для упрощения настройки.
      3. Минимальное расстояние : Соблюдение минимального расстояния для SL и TP может предотвратить проблемы в условиях чрезвычайно низкой волатильности.
      4. Максимальное расстояние : Аналогичным образом, можно ввести максимальное расстояние, чтобы ограничить риск в крайне нестабильных условиях.

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

      Управление рисками: Включает в себя функции для регулировки размера позиции в зависимости от сальдо счета и просадки, реализованные в AdjustLotSizeForDrawdown() и CalculateDynamicLotSize().

       // Function to adjust the lot size based on drawdown
      double AdjustLotSizeForDrawdown()
      {
         // Static variables to keep track of consecutive losses and maximum balance
         static int consecutiveLosses = 0 ;
         static double maxBalance = 0 ;
      
         // Get current account balance and equity
         double currentBalance = AccountInfoDouble ( ACCOUNT_BALANCE );
         double currentEquity = AccountInfoDouble ( ACCOUNT_EQUITY );
      
         // Update the maximum balance if current balance is higher
         if (currentBalance > maxBalance)
            maxBalance = currentBalance;
      
         // Calculate the current drawdown as a percentage
         double drawdown = (maxBalance - currentEquity) / maxBalance;
      
         // Calculate the base lot size using a separate function
         double baseLotSize = CalculateDynamicLotSize();
      
         // If drawdown is greater than 10%, reduce lot size by half
         if (drawdown > 0.1 ) // 10% drawdown
         {
             return baseLotSize * 0.5 ; // Reduce lot size by half
         }
         else if (consecutiveLosses > 3 )
         {
             return baseLotSize * 0.75 ; // Reduce lot size by 25% after 3 consecutive losses
         }
      
         // Return the base lot size if no adjustments are needed
         return baseLotSize;
      }

      Функция AdjustLotSizeForDrawdown() предназначена для динамической настройки размера торгового лота в зависимости от просадки счета и последних показателей. Вот краткое описание её основных функций:

      1. Она использует статические переменные для отслеживания последовательных убытков и достижения максимального сальдо.
      2. Она рассчитывает текущую просадку, сравнивая максимальное сальдо с текущим капиталом.
      3. Эта функция реализует две стратегии управления рисками:
        • Если просадка превышает 10%, размер лота уменьшается вдвое.
        • Если было более 3 последовательных убытков, размер лота уменьшается на 25%.
      4. Базовый размер лота рассчитывается с помощью другой функции, называемой CalculateDynamicLotSize(), которая не показана в этом фрагменте.
      5. Если ни одно из условий риска не выполняется, функция возвращает базовый размер лота без корректировки.

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

       // Function to dynamically calculate the lot size
      double CalculateDynamicLotSize()
      {
         // Get current account balance and equity
         double accountBalance = AccountInfoDouble ( ACCOUNT_BALANCE );
         double equity = AccountInfoDouble ( ACCOUNT_EQUITY );
         double riskPercentage = 0.01 ; // 1% risk per trade
      
         // Use the lower value between balance and equity to be conservative
         double baseAmount = MathMin (accountBalance, equity);
      
         // Calculate the value of a pip for the current symbol
         double tickSize = SymbolInfoDouble ( _Symbol , SYMBOL_TRADE_TICK_SIZE );
         double tickValue = SymbolInfoDouble ( _Symbol , SYMBOL_TRADE_TICK_VALUE );
         double pipValue = (tickValue / tickSize) * 10 ; // Assuming a pip is 10 ticks
      
         // Calculate lot size based on desired risk
         double riskAmount = baseAmount * riskPercentage;
         double stopLossPips = 50 ; // Adjust according to your strategy
      
         double lotSize1 = NormalizeDouble (riskAmount / (stopLossPips * pipValue), 2 );
      
         // Ensure the lotSize is within the allowed limits
         double minLot = SymbolInfoDouble ( _Symbol , SYMBOL_VOLUME_MIN );
         double maxLot = SymbolInfoDouble ( _Symbol , SYMBOL_VOLUME_MAX );
         double lotSize2 = MathMax (minLot, MathMin (maxLot, lotSize1));
      
         return lotSize2;
      }

      Данная функция CalculateDynamicLotSize() предназначена для расчета подходящего размера лота для торговли на основе сальдо вашего счета, толерантности к риску и текущих рыночных условий. Вот краткое описание её основных функций:

      1. Она извлекает баланс текущего счета и собственный капитал, используя меньшее из двух значений для более консервативного подхода.
      2. Функция использует фиксированный процент риска по сделке, в данном случае установленный на уровне 1%.
      3. Она вычисляет значение пипса для текущего торгового инструмента, предполагая, что пипс эквивалентен 10 тикам.
      4. Затем размер пакета рассчитывается на основе:
        • Величина риска (1% от базовой величины)
        • Предопределенный стоп-лосс в пипсах (в данном примере он установлен на 50 пипсов)
        • Расчётное значение элемента
      5. Функция гарантирует, что рассчитанный размер лота находится в пределах минимального и максимального размеров лота, разрешенных для торгового инструмента.
      6. Возвращается окончательный размер лота, нормализованный до двух знаков после запятой.

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

      Сочетание этих двух функций обеспечивает надежную систему управления рисками, которая:

      1. Корректирует размеры позиций в зависимости от эффективности и просадки счета
      2. Поддерживает постоянный процент риска на сделку
      3. Адаптируется к изменяющимся остаткам на счетах и рыночным условиям

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


      Важные характеристики:

      1. OptimalControl(double currentPrice): Это основная функция советника по принятию решений. Она использует прогнозирующее управление моделью, чтобы определить, следует ли покупать, продавать или удерживать. Она вычисляет ожидаемую доходность за прогнозируемый период и сравнивает ее с порогом принятия решения.
      2. CalculateExpectedReturn(...): Данная функция вычисляет ожидаемую доходность для заданного набора параметров, используемых в функции OptimalControl.
      3. ManageOpenOrder(int decision): Управляет существующими открытыми ордерами, решая, закрывать ли их в зависимости от количества открытых баров или если текущее решение противоречит открытой позиции.
      4. ExecuteTrade(int decision): выполняет новую сделку на основе решения OptimalControl, устанавливая соответствующие уровни стоп-лосса и тейк-профита.
      5. UpdateSLTP(ulong ticket, int decision): Обновляет уровни стоп-лосса и тейк-профита для существующей позиции в зависимости от текущих рыночных условий.
      6. EstimateDrift() и EstimateVolatility(): Эти функции оценивают дрейф цены и волатильность, которые используются при расчетах оптимального управления.
      7. IsTrendFavorable(int decision) и IsLongTermTrendFavorable(int decision): Эти функции проверяют, соответствует ли текущий рыночный тренд торговому решению, используя скользящие средние и RSI.
      8. AdjustLotSizeForDrawdown() и CalculateDynamicLotSize(): Эти функции регулируют торговый объем в зависимости от текущей просадки и сальдо счета, реализуя динамическое управление рисками.
      9. LogMessage(string message): Регистрирует важные события и решения в файл для последующего анализа и отладки.


      Результаты

      Период в 1 день

      Период в 1 день

      Период в 1 час

      Период в 1 час

      Период в 4 часа

      Период в 4 часа

      Бэктестинг в течение 4-часового периода

      Период в 6 часов

      Таймфрейм 6 часов

      Бэктестинг в течение 6-часового периода


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


      Заключение

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

      И напоследок: это всего лишь простой пример передового советника.


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

      Прикрепленные файлы |
      SMOC_final.mq5 (40.29 KB)
      Своп-арбитраж на Форекс: Собираем синтетический портфель и создаем стабильный своп-поток Своп-арбитраж на Форекс: Собираем синтетический портфель и создаем стабильный своп-поток
      Хотите узнать, как извлекать выгоду из разницы в процентных ставках? В статье мы посмотрим, как использовать своп-арбитраж на Форексе, чтобы каждую ночь получать стабильный доход, создавая портфель, устойчивый к рыночным колебаниям.
      Нейросети в трейдинге: Выявление аномалий в частотной области (CATCH) Нейросети в трейдинге: Выявление аномалий в частотной области (CATCH)
      Фреймворк CATCH сочетает преобразование Фурье и частотный патчинг для точного выявления рыночных аномалий, недоступных традиционным методам. В данной работе мы рассмотрим, как этот подход раскрывает скрытые закономерности в финансовых данных.
      Разработка трендовых торговых стратегий на основе машинного обучения Разработка трендовых торговых стратегий на основе машинного обучения
      В данной статье предложен оригинальный подход к разработке трендовых стратегий. Вы узнаете, как можно делать разметку обучающих примеров и обучать на них классификаторы. На выходе получатся готовые торговые системы, работающие под управлением терминала MetaTrader 5.
      MQL5-советник, интегрированный в Telegram (Часть 5): Отправка команд из Telegram в MQL5 и получение ответов в реальном времени MQL5-советник, интегрированный в Telegram (Часть 5): Отправка команд из Telegram в MQL5 и получение ответов в реальном времени
      В этой статье мы создадим несколько классов для облегчения взаимодействия в реальном времени между MQL5 и Telegram. Мы займемся извлечением команд из Telegram, их декодированием и интерпретацией, а также отправкой соответствующих ответов. Под конец мы протестируем эти взаимодействия и убедимся в их правильной работе в торговой среде.