English Deutsch 日本語
preview
Возможности Мастера MQL5, которые вам нужно знать (Часть 61): Использование паттернов ADX и CCI с обучением с учителем

Возможности Мастера MQL5, которые вам нужно знать (Часть 61): Использование паттернов ADX и CCI с обучением с учителем

MetaTrader 5Торговые системы |
82 0
Stephen Njuki
Stephen Njuki

Введение

Мы продолжаем рассматривать, как пары индикаторов, отслеживающих различные аспекты рынков, могут быть объединены с машинным обучением для построения торговой системы. В следующих статьях мы рассмотрим сочетание осциллятора Average Directional Index (ADX) с индексом Commodity Channel Index (CCI). Индикатор ADX преимущественно подтверждает тренд, тогда как индикатор CCI является индикатором импульса. Мы уже затрагивали эти два свойства, когда рассматривали закономерности отдельных показателей в предыдущих статьях, например в этой. Подводя итог, можно сказать, что подтверждение тренда измеряет силу данного ценового тренда; сила тренда указывает на пригодность для входа в сделку. С другой стороны, индикаторы импульса измеряют темп изменения цен. Чем быстрее цена меняется в заданном направлении, тем меньше вероятность возникновения неблагоприятных колебаний.

logo



Commodity Channel Index (индекс товарного канала, CCI)

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

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

def CCI(df, period=14):
    """
    Calculate Commodity Channel Index (CCI)
    :param df: pandas DataFrame with columns ['high', 'low', 'close']
    :param period: lookback period (default 20)
    :return: Series with CCI values
    """
    # Calculate Typical Price
    typical_price = (df['high'] + df['low'] + df['close']) / 3
    
    # Calculate Simple Moving Average of Typical Price
    sma = typical_price.rolling(window=period).mean()
    
    # Calculate Mean Deviation
    mean_deviation = typical_price.rolling(window=period).apply(
        lambda x: np.mean(np.abs(x - np.mean(x))), raw=True)
    
    # Calculate CCI
    df['cci'] = (typical_price - sma) / (0.015 * mean_deviation)
    
    return df[['cci']]

CCI - осциллятор, который измеряет, насколько цена актива отклоняется от своего статистического среднего значения. На первый взгляд, это может быть полезно трейдерам для выявления условий перекупленности или перепроданности. Приведенная выше функция принимает фрейм данных pandas, содержащий столбцы с ценами high (максимум), low (минимум) и close (закрытие), а также период ретроспективного анализа (по умолчанию 14) для вычисления значений CCI. Расчет Typical Price (типичная цена) устанавливает среднее значение максимальной, минимальной цены и цены закрытия таким образом, чтобы оно отражало/покрывало большую часть ценовых колебаний за усредненный период. Это арифметическое среднее трех основных цен для каждого таймфрейма, и оно помогает упростить данные о ценах, сводя их к одному репрезентативному значению. Это помогает снизить уровень шума, вызванного внутрисуточными колебаниями. Этот шаг имеет основополагающее значение, поскольку CCI основан на отклонениях от типичной цены, и использование всех трех показателей (максимум, минимум и цена закрытия) помогает обеспечить сбалансированное представление о динамике цен. Поэтому необходимо убедиться, что фрейм данных Pandas, извлекающий данные о ценах брокеров через модуль MetaTrader 5, содержит все эти столбцы, поскольку пропущенные значения приведут к ошибкам.

Простая скользящая средняя (SMA) сглаживает типичную цену за указанный период, чтобы установить базовый уровень. Это достигается путем вычисления SMA за указанный входной период (по умолчанию 14), чтобы он мог выступать в качестве эталонного значения. Это важно, потому что краткосрочные колебания цен сглаживаются, обеспечивая таким образом репрезентативный «нормальный» уровень цен. Для вычисления корректной скользящей средней (SMA) повторяющаяся функция требует достаточного количества точек данных (как минимум, равного квадрату входного периода). Если набор данных слишком короткий, то для работы с начальными значениями NaN может потребоваться специальная обработка (с помощью таких функций, как dropna()… и т.д.).

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

Формула CCI, таким образом, объединяет все вышеперечисленные компоненты для вычисления значения, которое затем масштабируется на константу 0,015 для нормализации. Константа 0,015 — это стандартный масштабный коэффициент, который призван поддерживать значения CCI в диапазоне ±100. Однако это не всегда удается, но это и есть цель. Это является ключевым элементом формулы CCI, поскольку она преобразует исходные отклонения цен в стандартизированный осциллятор. Значения выше +100 будут указывать на перекупленность, а значения ниже -100 — на перепроданность. При использовании этой формулы следует обращать внимание на ошибки деления на ноль, если среднее отклонение равно нулю. Хотя это и редкость, такой сценарий возможен при низкой волатильности. При необходимости, к знаменателю можно добавить небольшое значение эпсилон (например, 1e-10), чтобы смягчить этот эффект. 

Оператор return возвращает фрейм данных, содержащий только столбец cci. Если для отладки или дополнительного анализа требуются дополнительные столбцы (например, typical_price), то это выражение можно изменить, чтобы включить их.



Индекс среднего направленного движения (Average Directional Index, ADX)

Индикатор ADX измеряет силу тренда независимо от его направления. Это достигается с помощью индекса направленного движения, который в основном состоит из двух буферов (+DI и -DI). Эта функция, как и описанная выше CCI, принимает фрейм данных pandas со столбцами high, low и close и периодом ретроспективного анализа (по умолчанию 14) для вычисления значений ADX, +DI и -DI. Ее реализация на Python выглядит так:

def ADX(df, period=14):
    """
    Calculate Average Directional Index (ADX)
    :param df: pandas DataFrame with columns ['high', 'low', 'close']
    :param period: lookback period (default 14)
    :return: DataFrame with ADX, +DI, -DI columns
    """
    # Calculate +DM, -DM, and True Range
    df['up_move'] = df['high'] - df['high'].shift(1)
    df['down_move'] = df['low'].shift(1) - df['low']
    df['+dm'] = np.where(
        (df['up_move'] > df['down_move']) & (df['up_move'] > 0),
        df['up_move'],
        0.0
    )
    df['-dm'] = np.where(
        (df['down_move'] > df['up_move']) & (df['down_move'] > 0),
        df['down_move'],
        0.0
    )
    
    # Calculate True Range
    df['tr'] = np.maximum(
        df['high'] - df['low'],
        np.maximum(
            abs(df['high'] - df['close'].shift(1)),
            abs(df['low'] - df['close'].shift(1))
    ))
    
    # Smooth the values using Wilder's smoothing method (EMA with alpha=1/period)
    df['+dm_smoothed'] = df['+dm'].ewm(alpha=1/period, adjust=False).mean()
    df['-dm_smoothed'] = df['-dm'].ewm(alpha=1/period, adjust=False).mean()
    df['tr_smoothed'] = df['tr'].ewm(alpha=1/period, adjust=False).mean()
    
    # Calculate +DI and -DI
    df['+di'] = 100 * (df['+dm_smoothed'] / df['tr_smoothed'])
    df['-di'] = 100 * (df['-dm_smoothed'] / df['tr_smoothed'])
    
    # Calculate DX
    df['dx'] = 100 * (abs(df['+di'] - df['-di']) / (df['+di'] + df['-di']))
    
    # Calculate ADX
    df['adx'] = df['dx'].ewm(alpha=1/period, adjust=False).mean()
    
    # Return the relevant columns
    return df[['adx', '+di', '-di']]

Два вычисленных буфера для направленного движения (+DM, -DM) позволяют оценить величину восходящих и нисходящих движений цены и силу направленного движения. Они вычисляются на основе разницы между последовательными повышающимися движениями (движение вверх) и противоположной разностью между последовательными понижающимися движениями (движение вниз). Это важно, потому что это строительные блоки для +DM и -DM, которые, в свою очередь, определяют направленный импульс. Используя смещенные значения, мы сравниваем данные за разные периоды. Присвоение +DM значения восходящего движения происходит, когда оно превышает нисходящее движение и является положительным; в противном случае +DM равно 0. Аналогично, значение -DM уменьшается, когда превышает восходящее значение. Это помогает отфильтровать слабые движения.

Функция NumPy where() эффективна для векторизованных операций, поэтому необходимо убедиться в импорте NumPy. Проверка правильности расчетов движения вверх и вниз также важна для предотвращения неправильной классификации движений. Использование shift(1) приводит к появлению NaN в первой строке, что требует обработки в последующих вычислениях или при возврате результатов. Крайне важно всегда следить за тем, чтобы значения в столбцах high и low были числовыми.

Истинный диапазон (true range, TR) измеряет волатильность цен и помогает учитывать ценовые разрывы и внутридневные диапазоны. Вычисление выполняется путем выбора наибольшего из трех значений: диапазона максимума-минимума, диапазона абсолютного максимума и предыдущего закрытия и диапазона абсолютного минимума и предыдущего закрытия. Это помогает учитывать ценовые разрывы и волатильность. Этот показатель волатильности активов важен, поскольку он служит знаменателем для нормализации +DI и -DI. Это означает, что ADX отражает силу тренда относительно движения цены. Функция maximum в NumPy гарантирует выбор наибольшего диапазона значений. Также следует обратить внимание на обработку значений NaN при shift(1).

Метод сглаживания Уайлдера использует экспоненциальное скользящее среднее с определенным значением альфа для сглаживания +DM, -DM и TR. Значение Alpha равно 1/period, а использование значения False для параметра adjust означает, что больший вес придается недавним данным, что имитирует оригинальный метод Уайлдера. Сглаживание помогает снизить уровень шума, что делает наборы данных индикаторов более надежными для анализа трендов. Функция ewm эффективна, но чувствительна к параметру альфа. 

Направленные индикаторы нормализуют сглаженные движения по истинному диапазону, чтобы сравнить силу бычьего и медвежьего трендов. Увеличение масштаба на 100 помогает выразить их в процентах. Это важно, поскольку +DI и -DI дают числовое представление о том, насколько бычьим или медвежьим является тренд относительно волатильности. Таким образом, пересечения между +DI и -DI сигнализируют о потенциальных изменениях тренда. Защита от деления на ноль может быть обеспечена добавлением небольшого значения эпсилон. Для удобства интерпретации стандартным является коэффициент масштабирования 100.

Буфер DX определяет масштабированную абсолютную разницу между +DI и -DI, деленную на их сумму. Это имеет решающее значение для оценки относительной силы направленного движения. DX — важный промежуточный этап перед ADX, задача которого — определить "интенсивность" тренда (бычий или медвежий). Следует проявлять осторожность при обработке случаев, когда +di + -di равны нулю, чтобы избежать ошибок деления. Можно вернуть ноль или пропустить вычисление.

Наконец, ADX усредняет направленный индекс для оценки общей силы тренда. Сглаживание значений DX при использовании экспоненциальной скользящей средней Уайлдера для расчета ADX, как правило, отражает силу тренда в долгосрочной перспективе. Это окончательный результат работы индикатора: значения выше 25 указывают на сильный тренд, а значения ниже 20 — на слабый или колебательный рынок. Важно обеспечить последовательность значений альфа на всех этапах сглаживания для обеспечения согласованности.

Оператор return возвращает DataFrame со столбцами adx, +di и -di, которые представляют собой полный набор буферов индикатора ADX. Это предоставляет трейдерам необходимые метрики для анализа трендов, а добавление промежуточных столбцов dx или tr позволяет отлаживать или настраивать индикатор.



Признаки

Мы объединяем показания этих двух функций для создания многомерного сигнального массива, который, по сути, сочетает ADX (для определения силы тренда) и CCI (для определения импульса) для выявления конкретных рыночных условий, таких как начало тренда, развороты или состояния перекупленности/перепроданности. Сигналы, генерируемые путем объединения этих двух показателей, мы в более широком смысле называем характеристиками. Напомним, что в предыдущих 4 статьях мы использовали 5 основных наборов данных при рассмотрении пары скользящей средней и стохастического осциллятора. Это были признаки (Features), состояния (States), действия (Actions), награды (Rewards) и кодировки (Encodings). Таким образом, эти характеристики здесь эквивалентны тому, что у нас было тогда. 

Сочетание этих двух индикаторов используется исходя из предположения, что на основе их комбинации можно сгенерировать 10 шаблонов признаков. Конечно, их могло бы быть больше, но для наших целей этого числа будет достаточно. Мы присваиваем функцию каждому паттерну. Каждая функция возвращает массив NumPy, в каждом столбце которого представлено условие (измерение), где 1 означает, что условие выполнено, и 0 — в противном случае. В качестве входных данных эти функции будут принимать фреймы данных pandas. Эти входные данные обозначены как adx_df (со столбцами adx, +di, -di); cci_df (со столбцом cci); и, при необходимости, price_df (со столбцами high, low, close).

Мы реализовали эти функции на Python для ускорения процесса тестирования, но нам также необходима аналогичная реализация на MQL5 для развертывания/использования нашего финального советника. Встроенная в MQL5 обработка указанных выше точек индикатора в CCI и ADX означает, что они не будут создавать проблем при использовании советника. Вкратце, для Python необходимо проверять поля adx_df и cci_df, чтобы убедиться в наличии необходимых столбцов, а также обрабатывать значения NaN с помощью команд drop или fill во избежание ошибок при сравнении. Операции сдвига, такие как shift(1), неизбежно приводят к появлению значений NaN в первой строке. Поэтому установка значения 0 в первой строке — это стандартный способ управления этим процессом. Векторизованные операции в идеале следует вводить для больших наборов данных, поскольку используемые функции NumPy where() и astype(int) могут оказаться недостаточными.

Все признаки были протестированы/обучены на валютной паре EURUSD на дневном таймфрейме в период с 01.01.2020 по 01.01.2024. Форвард-период: с 2024.01.01 по 2025.01.01. Только признаки 2, 3 и 4 прошли форвард-тестирование, поэтому их результаты приведены вместе с соответствующими описаниями.



Признак 0

Это паттерн, основанный на ADX > 25 и пересечениях CCI в пределах ±100. Это подтверждает прорыв тренда или его начало. Уровень 25 имеет важное значение для ADX, поэтому при его пересечении вместе с ключевым уровнем CCI 100 высока вероятность возникновения нового тренда. Использование этих двух индикаторов помогает отфильтровать шум. При поиске тренда всегда важно дождаться, пока ADX протестирует уровень 25. Следует избегать всего, что ниже 20. Это высоковероятная инвестиционная стратегия для активов, известных своей тенденцией к росту, таких как некоторые фондовые индексы и т. д.

Полученный из этих сигналов вектор признаков представляет собой 6-мерный вектор. Реализация на Python и MQL5 выглядит так:

def feature_0(adx_df, cci_df):
    """
    Creates a 3D signal array with the following dimensions:
    1. ADX > 25 crossover (1 when crosses above 25, else 0)
    2. CCI > +100 crossover (1 when crosses above +100, else 0)
    3. CCI < -100 crossover (1 when crosses below -100, else 0)
    """
    # Initialize empty array with 3 dimensions and same length as input
    feature = np.zeros((len(adx_df), 6))
    
    # Dimension 1: ADX > 25 crossover
    feature[:, 0] = (adx_df['adx'] > 25).astype(int)
    feature[:, 1] = (adx_df['adx'].shift(1) <= 25).astype(int)
    
    # Dimension 2: CCI > +100 crossover
    feature[:, 2] = (cci_df['cci'] > 100).astype(int)
    feature[:, 3] = (cci_df['cci'].shift(1) <= 100).astype(int)
    
    # Dimension 3: CCI < -100 crossover
    feature[:, 4] = (cci_df['cci'] < -100).astype(int)
    feature[:, 5] = (cci_df['cci'].shift(1) >= -100).astype(int)
    
    # Set first row to 0 (no previous values to compare)
    feature[0, :] = 0
    
    return feature
   if(Index == 0)
   {  if(CopyBuffer(A.Handle(), 0, T, 2, _adx) >= 2 && CopyBuffer(C.Handle(), 0, T, 1, _cci) >= 2)
      {  _features[0] = (_adx[0] > 25 ? 1.0f : 0.0f);
         _features[1] = (_adx[1] <= 25 ? 1.0f : 0.0f);
         _features[2] = (_cci[0] > 100 ? 1.0f : 0.0f);
         _features[3] = (_cci[1] <= 100 ? 1.0f : 0.0f);
         _features[4] = (_cci[0] < -100 ? 1.0f : 0.0f);
         _features[5] = (_cci[1] >= -100 ? 1.0f : 0.0f);
      }
   }

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

Традиционно бычий сценарий формируется, когда индикатор ADX пересекает отметку ниже 25 и закрывается выше неё, а затем индикатор CCI также пересекает отметку ниже +100 и закрывается выше +100. Аналогично, медвежий паттерн будет наблюдаться, если ADX снова пересечет уровень 25 и закроется выше него, а CCI пересечет уровень -100 сверху и закроется ниже него. Если бы мы создали строгие векторы, которые проверяют только эти "истинные" бычьи или медвежьи сценарии, то наш входной вектор имел бы размер 3, что привело бы к меньшей изменчивости в огромном объеме тестовых данных. Выбранный нами вариант 6-мерных входных данных позволяет учитывать как традиционные метрики, так и "непрерывные" данные, которые в противном случае были бы проигнорированы при более "дискретной"/"традиционной" настройке.



Признак 1

Этот паттерн формируется вокруг значений ADX > 25 и пересечений CCI уровней ±50 с противоположных сторон. Это возвращение к прежнему тренду с сохранением прежнего импульса. Оно идеально подходит для сделок на продолжение тренда после коррекции, поскольку ADX подтверждает целостность тренда, а CCI обнаруживает восстановление после короткого контртренда. Этот паттерн подходит для тех, кто следует за трендом и стремится войти в тренд после коррекции. Пересечение линии CCI на нулевой границе также является важным сигналом, который не следует игнорировать. Трейлинг-стопы также можно устанавливать по этому сигналу для трейдеров, уже находящихся в тренде и стремящихся защитить прибыль. Реализация на Python и MQL5 выглядит так:

def feature_1(adx_df, cci_df):
    """
    Creates a modified 3D signal array with:
    1. ADX > 25 (1 when above 25, else 0)
    2. CCI crosses from below 0 to above +50 (1 when condition met, else 0)
    3. CCI crosses from above 0 to below -50 (1 when condition met, else 0)
    """
    # Initialize empty array with 3 dimensions
    feature = np.zeros((len(adx_df), 5))
    
    # Dimension 1: ADX above 25 (continuous, not just crossover)
    feature[:, 0] = (adx_df['adx'] > 25).astype(int)
    
    # Dimension 2: CCI crosses from <0 to >+50
    feature[:, 1] = (cci_df['cci'] > 50).astype(int)
    feature[:, 2] = (cci_df['cci'].shift(1) < 0).astype(int)
    
    # Dimension 3: CCI crosses from >0 to <-50
    feature[:, 3] = (cci_df['cci'] < -50).astype(int)
    feature[:, 4] = (cci_df['cci'].shift(1) > 0).astype(int)
    
    # Set first row to 0 (no previous values to compare)
    feature[0, :] = 0
    
    return feature
   else if(Index == 1)
   {  if(CopyBuffer(A.Handle(), 0, T, 2, _adx) >= 2 && CopyBuffer(C.Handle(), 0, T, 1, _cci) >= 2)
      {  _features[0] = (_adx[0] > 25 ? 1.0f : 0.0f);
         _features[1] = (_cci[0] > 50 ? 1.0f : 0.0f);
         _features[2] = (_cci[1] < 0 ? 1.0f : 0.0f);
         _features[3] = (_cci[0] < -50 ? 1.0f : 0.0f);
         _features[4] = (_cci[1] > 0 ? 1.0f : 0.0f);
      }
   }

Наша функция генерирует 5-мерный выходной вектор бинарных значений, составляющими которого являются: превышает ли ADX уровень 25, превышал ли предыдущий CCI 0; равен ли текущий CCI -50 или меньше; был ли предыдущий CCI ниже 0; равен ли текущий CCI 50 или больше. Традиционно бычий сценарий развития событий — это когда ADX находится выше 25, а CCI ранее был ниже нуля, а теперь превышает 50. Медвежий сценарий будет иметь место, если ADX снова окажется выше 25, а CCI ранее был выше 0, а теперь ниже или равен -50. Указанные выше соображения относительно перехода от дискретного отображения к более непрерывному/регрессивному отображению также применимы и здесь.



Признак-2

Паттерн основан на значении ADX > 25, при этом дивергенции обеспечиваются ценой и индексом CCI. Это также может быть дивергенция или разворот тренда. В нем используется классический паттерн "импульс-дивергенция" с ADX в качестве фильтра тренда. Это указывает на потенциальный разворот тренда, даже несмотря на то, что тренд остается активным. Этот паттерн лучше всего подходит для ситуаций, когда сочетается с анализом ценового движения или уровнями поддержки/сопротивления для более надежного подтверждения. Этот метод также идеально подходит в ситуациях, когда расхождение образуется после длительного перемещения. Однако следует проявлять осторожность, поскольку дивергенция часто является лишь ранним сигналом, так как многие из них оказываются неэффективными, если они возникают после очень сильного тренда. Реализация на Python и MQL5 выглядит так:

def feature_2(adx_df, cci_df, price_df):
    """
    Creates a 5D signal array with:
    1. ADX > 25 (1 when above 25, else 0)
    2. Lower low (1 when current low < previous low, else 0)
    3. Higher CCI (1 when current CCI > previous CCI, else 0)
    4. Higher high (1 when current high > previous high, else 0)
    5. Lower CCI (1 when current CCI < previous CCI, else 0)
    """
    # Initialize empty array with 5 dimensions
    feature = np.zeros((len(price_df), 5))
    
    # Dimension 1: ADX above 25
    feature[:, 0] = (adx_df['adx'] > 25).astype(int)
    
    # Dimension 2: Lower low
    feature[:, 1] = (price_df['low'] < price_df['low'].shift(1)).astype(int)
    
    # Dimension 3: Higher CCI
    feature[:, 2] = (cci_df['cci'] > cci_df['cci'].shift(1)).astype(int)
    
    # Dimension 4: Higher high
    feature[:, 3] = (price_df['high'] > price_df['high'].shift(1)).astype(int)
    
    # Dimension 5: Lower CCI
    feature[:, 4] = (cci_df['cci'] < cci_df['cci'].shift(1)).astype(int)
    
    # Set first row to 0 (no previous values to compare)
    feature[0, :] = 0
    
    return feature
   else if(Index == 2)
   {  if(CopyBuffer(A.Handle(), 0, T, 2, _adx) >= 2 && CopyBuffer(C.Handle(), 0, T, 1, _cci) >= 2 && CopyRates(Symbol(),Period(),T, 2, _r) >= 2)
      {  _features[0] = (_adx[0] > 25 ? 1.0f : 0.0f);
         _features[1] = (_r[0].low <= _r[1].low ? 1.0f : 0.0f);
         _features[2] = (_cci[0] > _cci[1] ? 1.0f : 0.0f);
         _features[3] = (_r[0].high > _r[1].high ? 1.0f : 0.0f);
         _features[4] = (_cci[0] < _cci[1] ? 1.0f : 0.0f);
      }
   }

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

r2

c2



Признак 3

Паттерн сочетает в себе рост ADX и CCI в нейтральных зонах. Он служит для подтверждения тренда, имея нейтральную зону CCI. Основное внимание уделяется устойчивому импульсу в восходящем или нисходящем тренде. Когда CCI находится в нейтральной зоне (от 0 до +/-100), это часто означает, что цена совершает стабильные, но не экстремальные движения. Как правило, это безопаснее, чем сигналы перекупленности/перепроданности, поскольку риск ложных входов ниже. В условиях менее волатильных рынков паттерн можно рассматривать как подтверждение того, что "тренд — ваш друг". В сочетании с выравниванием по скользящим средним или изменением ценовой структуры паттерн может обеспечить большую безопасность. Реализация на Python и MQL5 выглядит так:

def feature_3(adx_df, cci_df):
    """
    Creates a 3D signal array with:
    1. ADX rising (1 when current ADX > previous ADX, else 0)
    2. CCI between 0 and +100 (1 when in range, else 0)
    3. CCI between 0 and -100 (1 when in range, else 0)
    """
    # Initialize empty array with 3 dimensions
    feature = np.zeros((len(adx_df), 5))
    
    # Dimension 1: ADX rising
    feature[:, 0] = (adx_df['adx'] > adx_df['adx'].shift(1)).astype(int)
    
    # Dimension 2: CCI between 0 and +100
    feature[:, 1] = (cci_df['cci'] > 0).astype(int)
    feature[:, 2] = (cci_df['cci'] < 100).astype(int)
    
    # Dimension 3: CCI between 0 and -100
    feature[:, 3] = (cci_df['cci'] < 0).astype(int)
    feature[:, 4] = (cci_df['cci'] > -100).astype(int)
    
    # Set first row to 0 (no previous ADX value to compare)
    feature[0, :] = 0
    
    return feature
   else if(Index == 3)
   {  if(CopyBuffer(A.Handle(), 0, T, 2, _adx) >= 2 && CopyBuffer(C.Handle(), 0, T, 1, _cci) >= 2)
      {  _features[0] = (_adx[0] > _adx[1] ? 1.0f : 0.0f);
         _features[1] = (_cci[0] > 0 ? 1.0f : 0.0f);
         _features[2] = (_cci[1] < 100 ? 1.0f : 0.0f);
         _features[3] = (_cci[0] < 0 ? 1.0f : 0.0f);
         _features[4] = (_cci[1] > -100 ? 1.0f : 0.0f);
      }
   }

Наша функция генерирует 5-мерный вектор, состоящий из следующих элементов: увеличился ли показатель ADX; превышает ли CCI 0; ниже ли CCI +100; ниже ли CCI 0; и выше ли CCI -100. Традиционный бычий сценарий в данном случае — это растущий ADX при CCI выше 0, но ниже +100. В результате перевернутого медвежьего паттерна также наблюдается рост ADX, но CCI находится ниже 0, однако выше -100. Паттерн подчеркивает рост ADX (а не просто > 25). Кроме того, нейтральные диапазоны CCI, как правило, ориентированы на ранние фазы развития тренда, в отличие, например, от экстремального пересечения признака 0.

r3



Признак 4

В этом паттерне используются конфигурации, где ADX > 25 с восстановлением CCI из экстремальных значений. Это неудачное колебание. Паттерн выявляет ловушки импульса, когда CCI пробивает экстремальный уровень, но затем не может продолжить движение. Добавление ADX гарантирует, что в рамках консолидации не наблюдается резких колебаний цен. Паттерн часто наблюдается перед разворотами или резкими скачками назад. Его лучше всего использовать во время волатильных торговых сессий (или в периоды выхода новостей, таких как объявления о занятости в несельскохозяйственном секторе). Однако ключевой момент здесь — наблюдение за пин-барами в дни неудачных колебаний для более убедительного подтверждения. Реализация на Python и MQL5 выглядит так:

def feature_4(adx_df, cci_df):
    """
    Creates a 3D signal array with:
    1. ADX > 25 (1 when above 25, else 0)
    2. CCI dips below -100 then closes above it (1 when condition met, else 0)
    3. CCI breaks above +100 then closes below it (1 when condition met, else 0)
    """
    feature = np.zeros((len(cci_df), 5))
    
    # Dimension 1: ADX above 25
    feature[:, 0] = (adx_df['adx'] > 25).astype(int)
    
    # Dimension 2: CCI dips below -100 then closes above it
    feature[:, 1] = (cci_df['cci'].shift(1) < -100).astype(int)
    feature[:, 2] = (cci_df['cci'] > -100).astype(int)
    
    # Dimension 3: CCI breaks above +100 then closes below it
    feature[:, 3] = (cci_df['cci'].shift(1) > 100).astype(int)
    feature[:, 4] = (cci_df['cci'] < 100).astype(int)
    
    return feature
   else if(Index == 4)
   {  if(CopyBuffer(A.Handle(), 0, T, 2, _adx) >= 2 && CopyBuffer(C.Handle(), 0, T, 1, _cci) >= 2)
      {  _features[0] = (_adx[0] > 25 ? 1.0f : 0.0f);
         _features[1] = (_cci[0] < -100 ? 1.0f : 0.0f);
         _features[2] = (_cci[1] > -100 ? 1.0f : 0.0f);
         _features[3] = (_cci[0] > 100 ? 1.0f : 0.0f);
         _features[4] = (_cci[1] < 100 ? 1.0f : 0.0f);
      }
   }

Признак 4 выдает пятимерный вектор, который отображает бинарные значения 1 и 0 в зависимости от того, находится ли ADX ниже 20; CCI был ниже -100; CCI теперь выше -100; CCI был выше +100; и расположен ли CCI теперь ниже +100. Типичным бычьим сигналом, указывающим на изменение импульса, будет ситуация, когда ADX находится ниже 20, а CCI перемещается из области ниже -100 в область выше -100. Таким образом, медвежий паттерн также будет наблюдаться, если ADX снова окажется ниже 20, сигнализируя о слабом преобладающем тренде, а CCI будет сигнализировать о снижении положительного импульса, переместившись с уровня выше +100 на уровень ниже +100.

r4

c4



Признак 5

В этом паттерне используется простое значение ADX < 20 с экстремальными выбросами CCI. Паттерн служит низковолатильным предшественником резкого скачка импульса. Он помогает выявлять ранние пробои, отслеживая пробои CCI во время фазы с низким уровнем ADX. Более того, он призван помочь трейдерам открывать позиции до начала тренда. При реализации этого паттерна часто целесообразно использовать жесткие стоп-лоссы, поскольку множество пиков могут ввести в заблуждение. Паттерн может дать дополнительное преимущество в сочетании с другими индикаторами, такими как сжатие полос Боллинджера или прорывы объема. Однако этот метод лучше подходит для более коротких таймфреймов (например, с 15-й недели по 1-ю неделю), поскольку они лучше способствуют быстрой торговле на основе импульса. Реализация на Python и MQL5 выглядит так:

def feature_5(adx_df, cci_df):
    """
    Creates a 3D signal array with:
    1. ADX < 20 (1 when below 20, else 0) - indicates weak trend
    2. CCI spikes above 150 (1 when condition met, else 0) - extreme overbought
    3. CCI drops below -150 (1 when condition met, else 0) - extreme oversold
    """
    # Initialize array
    feature = np.zeros((len(cci_df), 5))
    
    # Dimension 1: ADX below 20 (weak trend)
    feature[:, 0] = (adx_df['adx'] < 20).astype(int)
    
    # Dimension 2: CCI spikes above 150 (sudden extreme overbought)
    # Using 2-bar momentum to detect "sudden" spikes
    feature[:, 1] = (cci_df['cci'] > 150).astype(int)
    feature[:, 2] = (cci_df['cci'].shift(1) < 130).astype(int)
    
    # Dimension 3: CCI drops below -150 (sudden extreme oversold)
    # Using 2-bar momentum to detect "sudden" drops
    feature[:, 3] = (cci_df['cci'] < -150).astype(int)
    feature[:, 4] = (cci_df['cci'].shift(1) > -130).astype(int)
    
    return feature
   else if(Index == 5)
   {  if(CopyBuffer(A.Handle(), 0, T, 2, _adx) >= 2 && CopyBuffer(C.Handle(), 0, T, 1, _cci) >= 2)
      {  _features[0] = (_adx[0] < 20? 1.0f : 0.0f);
         _features[1] = (_cci[0] > 150 ? 1.0f : 0.0f);
         _features[2] = (_cci[1] < 130 ? 1.0f : 0.0f);
         _features[3] = (_cci[0] < -150 ? 1.0f : 0.0f);
         _features[4] = (_cci[1] > -130 ? 1.0f : 0.0f);
      }
   }

Наша функция генерирует 5-мерный вектор для подачи в многослойный перцептрон (MLP). Зафиксированные сигналы включают: расположен ли ADX ниже 20; превышает ли значение CCI +150; было ли значение CCI ранее ниже +130; ниже ли значение CCI -150; и, наконец, превысило ли значение CCI -130. Он использует показатель ADX, превышающий 25, для подтверждения наличия сильного тренда, направлен на выявление восстановления CCI с экстремальных уровней и в целом фокусируется на разворотах или изменениях импульса.

Типичный бычий сценарий — это когда ADX находится выше 25, CCI был ниже +130, а сейчас находится на уровне +150. Аналогично, для медвежьего сценария также потребуется, чтобы ADX был выше 25, при этом CCI должен в данный момент находиться на уровне -150, хотя ранее тестировался на уровне -130.



Признак 6

Предназначен для обнаружения пересечений ADX ниже 40 с пересечениями CCI. Этот паттерн, являющийся сигналом выхода при истощении тренда, характеризуется падающей линией ADX, которая сигнализирует об ослаблении тренда. Если индекс CCI также возвращается в нейтральное положение или переходит в противоположную сторону, это также предвещает ослабление динамики. Это можно рассматривать как сигнал снижения риска, служащий ориентиром для корректировки скользящего стоп-лосса или фиксации прибыли. Его также можно комбинировать с паттернами свечей для более чистых выходов, однако вход в новые сделки при наличии такой модели часто нецелесообразен. Реализация на Python и MQL5 выглядит так:

def feature_6(adx_df, cci_df):
    """
    Creates a 3D signal array with:
    1. ADX crosses below 40 (1 when crosses down, else 0)
    2. CCI crosses below +100 (1 when crosses down, else 0)
    3. CCI crosses above -100 (1 when crosses up, else 0)
    """
    # Initialize array with zeros
    feature = np.zeros((len(cci_df), 6))
    
    # Dimension 1: ADX crosses below 40
    feature[:, 0] = (adx_df['adx'] < 40).astype(int)
    feature[:, 1] = (adx_df['adx'].shift(1) >= 40).astype(int)
    
    # Dimension 2: CCI crosses below +100
    feature[:, 2] = (cci_df['cci'] < 100).astype(int)
    feature[:, 3] = (cci_df['cci'].shift(1) >= 100).astype(int)
    
    # Dimension 3: CCI crosses above -100
    feature[:, 4] = (cci_df['cci'] > -100).astype(int)
    feature[:, 5] = (cci_df['cci'].shift(1) <= -100).astype(int)
    
    return feature
   else if(Index == 6)
   {  if(CopyBuffer(A.Handle(), 0, T, 2, _adx) >= 2 && CopyBuffer(C.Handle(), 0, T, 1, _cci) >= 2)
      {  _features[0] = (_adx[0] < 40? 1.0f : 0.0f);
         _features[1] = (_adx[1] < 40? 1.0f : 0.0f);
         _features[2] = (_cci[0] < 100 ? 1.0f : 0.0f);
         _features[3] = (_cci[1] >= 100 ? 1.0f : 0.0f);
         _features[4] = (_cci[0] > -100 ? 1.0f : 0.0f);
         _features[5] = (_cci[1] <= -100 ? 1.0f : 0.0f);
      }
   } 

Функция выдает 6-мерный вектор, содержащий следующие данные: расположен ли ADX ниже 40; было ли значение ADX ранее выше 40; является ли значение CCI ниже 100; было ли значение CCI ранее выше 100; расположен ли CCI выше -100; и, наконец, было ли значение CCI ранее ниже -100. Медвежий завершающий паттерн (эквивалент бычьего) — это когда ADX падает с 40 до уровня ниже 40, а CCI ранее был ниже -100, но теперь находится выше этого уровня. И наоборот, бычий паттерн завершения (эквивалентный медвежьему) возникает, когда ADX снова падает с уровня 40, а CCI также снижается с +100 и опускается ниже этого уровня. Этот вариант лучше всего подходит в качестве сигнала выхода или предупреждения о выходе, однако здесь он включен исключительно в качестве сигнала входа для целей тестирования.



Принак 7

ADX > 25 с пересечениями нулевой линии CCI. Начинает ловить тренды, как только индекс CCI пересекает нулевую отметку. Это происходит потому, что пересечение нулевой линии индексом CCI действует как точка опоры импульса. Поскольку индикатор ADX также подтверждает силу тренда, эта ситуация предлагает четкие точки входа в середине тренда. Этот паттерн, как правило, более надежен, когда цена формирует более высокие максимумы или более низкие минимумы. Стоит рассмотреть возможность входа в систему в нескольких точках с использованием этого паттерна в качестве сигнала. Для проверки соответствия времени или диапазона волатильности торговой сессии необходимо тестирование на истории. Реализация на Python и MQL5 выглядит так:

def feature_7(adx_df, cci_df):
    """
    Creates Feature-7 3D signal array with:
    1. ADX > 25 (1 when above 25, else 0) - trend strength
    2. CCI crosses above 0 (1 when bullish crossover, else 0)
    3. CCI crosses below 0 (1 when bearish crossover, else 0)
    """
    # Initialize array with zeros
    feature = np.zeros((len(cci_df), 5))
    
    # Dimension 1: ADX above 25 (continuous signal)
    feature[:, 0] = (adx_df['adx'] > 25).astype(int)
    
    # Dimension 2: CCI crosses above 0 (bullish)
    feature[:, 1] = (cci_df['cci'] > 0).astype(int)
    feature[:, 2] = (cci_df['cci'].shift(1) <= 0).astype(int)
    
    # Dimension 3: CCI crosses below 0 (bearish)
    feature[:, 3] = (cci_df['cci'] < 0).astype(int)
    feature[:, 4] = (cci_df['cci'].shift(1) >= 0).astype(int)
    
    return feature
   else if(Index == 7)
   {  if(CopyBuffer(A.Handle(), 0, T, 2, _adx) >= 2 && CopyBuffer(C.Handle(), 0, T, 1, _cci) >= 2)
      {  _features[0] = (_adx[0] > 25? 1.0f : 0.0f);
         _features[1] = (_cci[0] > 0? 1.0f : 0.0f);
         _features[2] = (_cci[1] <= 0 ? 1.0f : 0.0f);
         _features[3] = (_cci[0] < 0 ? 1.0f : 0.0f);
         _features[4] = (_cci[1] >= 0 ? 1.0f : 0.0f);
      }
   } 

Функция также возвращает 5-мерный выходной вектор. Вектор регистрирует: значение ADX выше 25; значение CCI выше 0; значение CCI, которое ранее было ниже или равно 0; значение CCI, которое сейчас ниже 0; и, наконец, значение CCI, которое ранее было выше или равно 0. Типичные паттерны для вывода показывают, что бычий сигнал возникает, если ADX находится выше 25, а CCI ранее был ниже 0, а теперь находится выше 0. Аналогично, медвежий паттерн возникает, если ADX снова окажется выше 25, а CCI теперь будет ниже 0, хотя ранее он был выше 0.


Признак 8

ADX < 20 с экстремальными откатами CCI. По сути, это фильтр силы ADX плюс индикатор разворота перекупленности/перепроданности CCI. Классический случай инверсии диапазона, который фильтруется ADX. На рынках со слабым трендом или резкими колебаниями котировок развороты индикатора CCI, как правило, показывают лучшие результаты. В идеале его следует использовать только тогда, когда ADX действительно низкий (ниже 20), и не следует применять на трендовых рынках. Для подтверждения с помощью нескольких индикаторов паттерн можно сочетать с полосами Боллинджера или RSI. Такая модель разворота может идеально подойти для активов, ориентированных на возврат к среднему значению, таких как сырьевые товары или валютные пары. Реализация на Python и MQL5 выглядит так:

def feature_8(adx_df, cci_df):
    """
    Creates a 3D signal array with:
    1. ADX < 20 (1 when below 20, else 0) - weak trend
    2. CCI rises from -200 to -100 (1 when condition met, else 0) - extreme oversold bounce
    3. CCI falls from +200 to +100 (1 when condition met, else 0) - extreme overbought pullback
    """
    # Initialize array with zeros
    feature = np.zeros((len(cci_df), 5))
    
    # Dimension 1: ADX below 20 (weak trend)
    feature[:, 0] = (adx_df['adx'] < 20).astype(int)
    
    # Dimension 2: CCI rises from -200 to -100
    # Using 2-bar lookback to detect the move
    feature[:, 1] = (cci_df['cci'] > -100).astype(int)
    feature[:, 2] = (cci_df['cci'].shift(1) <= -200).astype(int)
    
    # Dimension 3: CCI falls from +200 to +100
    # Using 2-bar lookback to detect the move
    feature[:, 3] = (cci_df['cci'] < 100).astype(int)
    feature[:, 4] = (cci_df['cci'].shift(1) >= 200).astype(int)
    
    return feature
   else if(Index == 8)
   {  if(CopyBuffer(A.Handle(), 0, T, 2, _adx) >= 2 && CopyBuffer(C.Handle(), 0, T, 1, _cci) >= 2)
      {  _features[0] = (_adx[0] < 20? 1.0f : 0.0f);
         _features[1] = (_cci[0] > -100? 1.0f : 0.0f);
         _features[2] = (_cci[1] <= -200 ? 1.0f : 0.0f);
         _features[3] = (_cci[0] < 100 ? 1.0f : 0.0f);
         _features[4] = (_cci[1] >= 200 ? 1.0f : 0.0f);
      }
   }

Вывод функции также представляют собой 5-мерный вектор бинарных значений. Вектор регистрирует значения: ADX ниже 20; CCI выше -100; CCI ниже -200; CCI ниже +100; CCI выше +200. Таким образом, бычий сигнал, на основе которого формируются эти паттерны, возникает, когда ADX ниже 20, а CCI пересекает отметку -100, предварительно протестировав -200. И наоборот, медвежий паттерн возникает, когда ADX снова оказывается ниже 20, а CCI пересекает отметку ниже +100, хотя ранее был выше +200.



Признак 9

ADX > 25 с отложенными пересечениями CCI. Этот паттерн представляет собой противодействующее подавление сигнала или фильтр-ловушку. Он умеет распознавать ложные прорывы доминирующего тренда. В подобных ситуациях цена часто указывает на разворот тренда, однако CCI отвергает это предположение, подтверждая преобладающий тренд. Подходит для защиты от трендовых ловушек. Его можно комбинировать с подтверждением свечных графиков или падением объема после ложного пробоя. Подходит для трейдеров, которые уже обжигались на ложных сигналах и нуждаются в фильтре для большей достоверности. Реализация на Python и MQL5 выглядит так:

def feature_9(adx_df, cci_df):
    feature = np.zeros((len(cci_df), 7))
    cci = cci_df['cci'].values
    
    # Dimension 1
    feature[:, 0] = (adx_df['adx'] > 25).astype(int)
    
    # Dimension 2: Below 0 then above +50 within 20 periods
    feature[:, 1] = (cci < 0).astype(int)
    feature[:, 2] = (np.roll(cci, 1) >= 0).astype(int)
    below_zero = (feature[:, 1]==1) & (feature[:, 2]==1)
    feature[:, 3] = 0
    for i in np.where(below_zero)[0]:
        if i+20 < len(cci) and np.max(cci[i+1:i+21]) > 50:
            feature[:, 3] = 1
            break
    
    # Dimension 3: Above 0 then below -50 within 20 periods
    feature[:, 4] = (cci > 0).astype(int)
    feature[:, 5] = (np.roll(cci, 1) <= 0).astype(int)
    feature[:, 6] = 0
    above_zero = (feature[:, 4]==1) & (feature[:, 5]==1)
    for i in np.where(above_zero)[0]:
        if i+20 < len(cci) and np.min(cci[i+1:i+21]) < -50:
            feature[:, 6] = 1
            break
    
    return feature
   else if(Index == 9)
   {  if(CopyBuffer(A.Handle(), 0, T, 2, _adx) >= 2 && CopyBuffer(C.Handle(), 0, T, 1, _cci) >= 21)
      {  _features[0] = (_adx[0] > 25? 1.0f : 0.0f);
         _features[1] = (_cci[0] < 0? 1.0f : 0.0f);
         _features[2] = (_cci[1] >= 0 ? 1.0f : 0.0f);
         _features[3] = (_cci[ArrayMaximum(_cci,1,20)] > 50 ? 1.0f : 0.0f);
         _features[4] = (_cci[0] > 0? 1.0f : 0.0f);
         _features[5] = (_cci[1] <= 0 ? 1.0f : 0.0f);
         _features[6] = (_cci[ArrayMinimum(_cci,1,20)] < -50 ? 1.0f : 0.0f);
      }
   } 

Паттерн генерирует 7-мерный вектор, отображающий: значение ADX выше 25; значение CCI ниже 0; значение CCI выше 0 за предыдущий период; значение CCI выше 50 за период в 20 баров до последнего; значение CCI выше 0; значение CCI ниже 0 за предыдущий период; и, наконец, значение CCI ниже -50 за период в 20 баров до последнего.

Указанные сигнальные паттерны, на основе которых генерируются эти сигналы, следующие. Для бычьего сигнала ADX должен быть выше 25, а CCI должен повторно протестировать положительный уровень выше 0, опустившись ниже него, при этом максимальное значение должно составлять до 50 за 20 баров до падения. Аналогично, медвежий паттерн возникает, когда индекс CCI только что опустился ниже 0, хотя ранее он был выше этого значения, и за 20 баров до скачка выше 0 наблюдался еще один минимум не менее -50. Результаты тестирования для этого паттерна не прошли форвард-тестирование, поэтому они не публикуются, но исходный код прилагается внизу для дальнейшего независимого тестирования.



Заключение

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

Имя Описание
61_0.onnx MLP для паттерна 0
61_1.onnx MLP для паттерна 1
61_2.onnx MLP для паттерна 2
61_3.onnx MLP для паттерна 3
61_4.onnx MLP для паттерна 4
61_5.onnx MLP для паттерна 5
61_6.onnx MLP для паттерна 6
61_7.0nnx MLP для паттерна 7
61_8.onnx MLP для паттерна 8
61_9.onnx MLP для паттерна 9
61_x.mqh Файл обработки паттернов
SignalWZ_61.mqh Файл класса сигнала
wz_61.mq5 Советник, созданный в Мастере, для отображения включенных файлов

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

Прикрепленные файлы |
61_0.onnx (265.8 KB)
61_1.onnx (264.8 KB)
61_2.onnx (264.8 KB)
61_3.onnx (264.8 KB)
61_4.onnx (264.8 KB)
61_5.onnx (264.8 KB)
61_6.onnx (265.8 KB)
61_7.onnx (264.8 KB)
61_8.onnx (264.8 KB)
61_9.onnx (266.8 KB)
61_X.mqh (5.67 KB)
SignalWZ_61.mqh (15.85 KB)
wz_61.mq5 (8.06 KB)
Создание и форвардное тестирование автономного LLM агента для трейдинга с SEAL Создание и форвардное тестирование автономного LLM агента для трейдинга с SEAL
Гибридная архитектура на базе Llama 3.2 и SEAL тестируется на восьми валютных парах (M15) с форвардной изоляцией данных и контролем утечки информации. Методология объединяет adversarial self-play, curriculum learning и балансировку классов для стабильного обучения. Эксперименты подтверждают разрыв между точностью прогноза и реальной доходностью, что дает читателю практические ориентиры по проверке стратегий и корректной оценке их обобщающей способности.
Машинное обучение и Data Science (Часть 37): Использование моделей свечных графиков и ИИ в трейдинге Машинное обучение и Data Science (Часть 37): Использование моделей свечных графиков и ИИ в трейдинге
Свечные модели помогают трейдерам понимать психологию рынка и выявлять тренды на финансовых рынках. Они позволяют принимать более обоснованные торговые решения, которые могут привести к лучшим результатам. В этой статье мы рассмотрим, как использовать свечные паттерны в сочетании с моделями искусственного интеллекта для достижения оптимальных результатов в трейдинге.
Нейросети в трейдинге: Гибридные модели прогнозирования с управляемой смесью распределений (Основные компоненты) Нейросети в трейдинге: Гибридные модели прогнозирования с управляемой смесью распределений (Основные компоненты)
В статье представлена практическая реализация модуля адаптивного прогнозирования, объединяющего подходы Lattice и Tail-Aware моделирования для финансовых временных рядов. Читатель увидит, как система адаптивно выбирает архетипы рынка, оценивает релевантность экспертов и формирует взвешенные прогнозные распределения с учётом тяжёлых хвостов и локальных экстремумов.
Нейросети в трейдинге: Гибридные модели прогнозирования с управляемой смесью распределений (Lattice) Нейросети в трейдинге: Гибридные модели прогнозирования с управляемой смесью распределений (Lattice)
Статья разбирает гибридную систему Lattice: базовый LSTM, архетипы, soft/hard assignment и confidence-based binary gating для управления неопределённостью. Включён Tail-Aware модуль для моделирования тяжёлых хвостов и локально взрывных участков. Приведена реализация в MQL5 с выносом вычислительно тяжёлых частей в OpenCL и GPU (смесь экспертов, генерация и градиенты). Практический эффект — более надёжные сигналы входа/выхода и количественная поддержка риск-контроля.