Создание простого противоположного технического индикатора. Исследование на Python.

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

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



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

Концепция нормализации

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

Мы можем попробовать закодировать эту формулу на Python. Следующая функция нормализует данный временной ряд типа OHLC:

def normalizer(Data, lookback, what, where):
        
    for i in range(len(Data)):
        
        try:
            Data[i, where] = (Data[i, what] - min(Data[i - lookback + 1:i + 1, what])) / (max(Data[i - lookback + 1:i + 1, what]) - min(Data[i - lookback + 1:i + 1, what]))
        
        except ValueError:
            pass
    
    Data[:, where] = Data[:, where] * 100    
return Data
    
# The what variable is what to normalize and the where variable is where to print the normalized values, i.e. which column.

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

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

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

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

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

def long_range_indicator(Data, lookback, high, low, where):
    
    Data = normalizer(Data, lookback, high, where)
    Data = normalizer(Data, lookback, low, where + 1)
return Data

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

Простой бэк-тест

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

  • Открывайте длинную позицию (Покупайте), когда индикатор длинного диапазона | Low касается нулевого уровня с двумя предыдущими значениями выше нуля. Удерживайте эту позицию до тех пор, пока не будет остановлен (положительный или отрицательный) или пока не появится новый сигнал.
  • Открывайте короткую позицию (продавайте) всякий раз, когда индикатор длинного диапазона | Максимум касается уровня 100 с двумя предыдущими значениями ниже 100. Удерживайте эту позицию до тех пор, пока не будет остановлен (положительный или отрицательный) или пока не появится новый сигнал.

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

def signal(Data, long_range_high, long_range_low, buy, sell):
    
    for i in range(len(Data)):
            
        if Data[i, long_range_low] == lower_barrier and Data[i - 1, long_range_low] > lower_barrier and Data[i - 2, long_range_low] > lower_barrier :
            Data[i, buy] = 1
            
        if Data[i, long_range_high] == upper_barrier and Data[i - 1, long_range_high] < upper_barrier and Data[i - 2, long_range_high] < upper_barrier :
            Data[i, sell] = -1

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



Сигнальная функция учитывает 5 переменных:

  • Переменная Data представляет собой временной ряд OHLC в форме массива, предпочтительно массива numpy.
  • Переменная long_range_high - это столбец индикатора дальнего диапазона, который применяется к максимумам.
  • Переменная long_range_low - это столбец индикатора длительного диапазона, который применяется к минимумам.
  • Переменные покупка и продажа - это столбцы, в которых размещаются заказы на покупку и продажу. Значение 1 относится к триггеру покупки, а значение -1 относится к триггеру продажи.

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

«Очевидно, что переменная upper_barrier должна быть 100, а переменная lower_barrier должна быть 0».

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

def indicator_plot(Data, first, second, third, name = '', window = 250, name_ind_one = '', name_ind_two = ''):
fig, ax = plt.subplots(3, figsize = (10, 5))
    
    ax[0].plot(Data[-window:, first], color = 'black', label = name)
    ax[0].grid()
    ax[0].legend()
    
    ax[1].plot(Data[-window:, second], color = 'cornflowerblue', label = name_ind_one)   
    ax[1].grid()
    ax[1].legend()
    
    ax[2].plot(Data[-window:, third], color = 'darkviolet', label = name_ind_two)
    ax[2].grid()
    ax[2].legend()
# Calling the function
indicator_plot(my_data, closing_price, LRI_H, LRI_L, name = 'AUDCAD', window = 250, name_ind_one = 'LRI | High', name_ind_two = 'LRI | Low')

Мы снова будем использовать систему управления рисками на основе ATR со стоимостью 0,2 пункта за раунд сделки. Проверенные на исторических данных данные представляют собой почасовые столбцы с января 2010 года. Система управления рисками намеренно неоптимальна, чтобы дать стратегиям время на передышку, и, таким образом, теоретическое соотношение риска и прибыли составляет 0,25. Мы будем использовать 4 периода на индикаторе Long Range, как упоминалось выше.

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

Работает ли простота?

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

Прежде всего, я постоянно публикую свои торговые журналы в Твиттере до и после запуска, чтобы показать результаты. Это обеспечивает прозрачность. Я также публикую в Твиттере каждые 1–3 месяца. Однако я никогда не гарантирую ни возврата, ни превосходного мастерства. Что касается индикаторов, которые я разрабатываю, я постоянно использую их в своей личной торговле. Следовательно, у меня нет мотива публиковать предвзятые исследования. Моя цель - поделиться тем, что я узнал, в онлайн-сообществе.

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

Рыночную цену невозможно предсказать или ее очень трудно предсказать более чем в 50% случаев. Но реакцию рынка вполне можно предсказать.

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

Пока мы обсуждаем эту тему, я должен отметить несколько моментов в моих тестах на истории и статьях:

  • Спред, который я использую, основан на институциональных котировках небольшой доли пунктов. Как правило, розничным трейдерам предоставляется колоссальный спред в 1-2 пункта за сделку. Это огромно. Я использую спред 0,2. Однако большинство стратегий, использующих часовой таймфрейм, по-прежнему работают со спредом в 1 пункт. Для тех, кто использует таймфреймы M15 или M5, они не могут быть прибыльными со спредом в 1 пункт.
  • Расчет периода владения, который я использую, близок к завершению в случае отсутствия процесса управления рисками.
  • Используемый мной процесс управления рисками основан на среднем истинном диапазоне. Я специально упоминаю, что метод, который я использую, неоптимален, потому что он обеспечивает теоретическое соотношение риска и прибыли 0,25, что означает, что я рискую 4 денежными единицами, чтобы получить 1 денежную единицу. Большинство стратегий, которые я публикую, таким образом превосходят по эффективности. Некоторые по-прежнему прибыльны.
  • Хотя я не рекомендую торговать только по одному индикатору, цифры не лгут. Я представляю то, что могло произойти, если принять во внимание низкий спред.
  • Некоторые из представленных мною тестов на истории неудачны, и они публикуются либо для того, чтобы развенчать миф о торговле, либо для того, чтобы представить интересные функции, которые читатели могут запрограммировать.
  • Наконец, я твердо убежден, что нельзя кормить учащихся с ложечки. Я научился на практике, а не копируя. Вы должны понять идею, функцию, интуицию, условия стратегии, а затем разработать (даже лучше) одну из них самостоятельно, чтобы вы протестировали ее на исторических данных и улучшили, прежде чем принять решение о том, чтобы применить ее вживую или отказаться от нее.

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