Создание и оценка индикатора наложения фракталов в Python.

Распознавание образов - это поиск и идентификация повторяющихся паттернов с примерно одинаковыми результатами. Это означает, что когда нам удается найти паттерн, у нас есть ожидаемый результат, который мы хотим видеть и действовать в соответствии с нашей торговлей. Например, паттерн «двойная вершина / дно» - это классический технический паттерн, который сигнализирует о неизбежном развороте тренда. Литература различается по предсказательной способности этой известной конфигурации. В этой статье мы обсудим объективную модель, которая может помочь найти прорывы, а не развороты. Я говорю «объективный», потому что он имеет четкие правила, в отличие от классических паттернов, таких как голова и плечи и двойная вершина / низ.

Я только что опубликовал новую книгу после успеха New Technical Indicators in Python. Он содержит более полное описание и добавление сложных торговых стратегий со страницей Github, посвященной постоянно обновляемому коду. Если вы считаете, что это вас заинтересует, не стесняйтесь перейти по приведенной ниже ссылке или, если вы предпочитаете купить версию в формате PDF, вы можете связаться со мной в Linkedin.



Создание фракталов

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

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

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

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

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

Кодирование фрактального паттерна

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

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

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

def fractals(Data, high, low, up, down):
    
    # Fractal Up
    for i in range(len(Data)):
        
        if Data[i, high] < Data[i - 2, high] and Data[i - 1, high] < Data[i - 2, high] and Data[i - 2, high] > Data[i - 3, high] and Data[i - 2, high] > Data[i - 4, high]:
                
                Data[i - 2, up] = 1
   
    # Fractal Down
    for i in range(len(Data)):
        
        if Data[i, low] > Data[i - 2, low] and Data[i - 1, low] > Data[i - 2, low] and Data[i - 2, low] < Data[i - 3, low] and Data[i - 2, low] < Data[i - 4, low]:
                
                Data[i - 2, down] = -1   
                
    return Data

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

  • Покупка (покупка) при подтверждении нисходящего фрактала. Это означает, что сигнал на покупку генерируется через два периода после появления фрактала вниз.
  • Продажа (продажа) при подтверждении фрактала вверх. Это означает, что сигнал на продажу генерируется через два периода после появления фрактала вверх.

def signal(Data):
    
    # Bullish Signal
    for i in range(len(Data)):
        
        if Data[i - 2, 5] != 0:
                
                Data[i, 6] = 1
   
    # Bearish Signal
    for i in range(len(Data)):
        
        if Data[i - 2, 4] != 0:
                
                Data[i, 7] = -1 
    return Data

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

def adder(Data, times):
    
    for i in range(1, times + 1):
    
        new = np.zeros((len(Data), 1), dtype = float)
        Data = np.append(Data, new, axis = 1)
    return Data
def deleter(Data, index, times):
    
    for i in range(1, times + 1):
    
        Data = np.delete(Data, index, axis = 1)
    return Data
   
def jump(Data, jump):
    
    Data = Data[jump:, ]
    
    return Data
# Adding Columns
my_data = adder(my_data, 10)
# Applying Fractals
my_data = fractals(my_data, 1, 2, 4, 5)
# Signal Function
my_data = signal(my_data)

Оценка сигналов

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

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

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

# Choosing a Holding Period for a trend-following strategy
period = 13
def signal_quality(Data, closing, buy, sell, period, where):
    
    Data = adder(Data, 1)
    
    for i in range(len(Data)):
        
        try:   
            
            if Data[i, buy] == 1:
                
                Data[i + period, where] = Data[i + period, closing] - Data[i, closing]
            
            if Data[i, sell] == -1:
                
                Data[i + period, where] = Data[i, closing] - Data[i + period, closing]
                
        except IndexError:
            
             pass
         
    return Data
# Applying the Signal Quality Function
my_data = signal_quality(my_data, 3, 6, 7, period, 8)
positives = my_data[my_data[:, 8] > 0]
negatives = my_data[my_data[:, 8] < 0]
# Calculating Signal Quality
signal_quality = len(positives) / (len(negatives) + len(positives))
print('Signal Quality = ', round(signal_quality * 100, 2), '%')
# Output Signal Quality EURUSD = 51.04% 
# Output Signal Quality USDCHF = 50.02%
# Output Signal Quality GBPUSD = 50.65%

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

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



Заключение

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

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

Подводя итог, можно ли сказать, что стратегии, которые я предлагаю, реалистичны? Да, но только путем оптимизации среды (надежный алгоритм, низкие затраты, честный брокер, надлежащее управление рисками и управление заказами). Предусмотрены ли стратегии исключительно для торговли? Нет, это нужно для стимулирования мозгового штурма и получения новых торговых идей, поскольку мы все устали слышать о перепроданности RSI как о причине для открытия короткой позиции или о преодолении сопротивления как о причине идти долго. Я пытаюсь представить новую область под названием «Объективный технический анализ», в которой мы используем достоверные данные для оценки наших методов, а не полагаемся на устаревшие классические методы.