Бэк-тестирование и сравнение Hull RSI с RSI Уайлдера.

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

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



Концепция скользящей средней Халла

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

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

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

С математической точки зрения это можно записать как:

По сути, если у нас есть набор данных, состоящий из двух чисел [1, 2], и мы хотим вычислить линейное средневзвешенное значение, то мы сделаем следующее:

  • (2 x 2) + (1 x 1) = 5
  • 5 / 3 = 1.66

Это предполагает, что временной ряд с номером 2 является самым последним наблюдением.

import numpy as np
def lwma(Data, lookback):
    
    weighted = []
    for i in range(len(Data)):
            try:
                total = np.arange(1, lookback + 1, 1)
                
                matrix = Data[i - lookback + 1: i + 1, 3:4]
                matrix = np.ndarray.flatten(matrix)
                matrix = total * matrix
                wma = (matrix.sum()) / (total.sum())
                weighted = np.append(weighted, wma)              except ValueError:
                pass
    
    Data = Data[lookback - 1:, ]
    weighted = np.reshape(weighted, (-1, 1)) 
    Data = np.concatenate((Data, weighted), axis = 1)   
    
    return Data
# For this function to work, you need to have an OHLC array composed of the four usual columns, then you can use the below syntax to get a data array with the weighted moving average using the lookback you need
my_ohlc_data = lwma(my_ohlc_data, 20)

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

Скользящая средняя Халла использует взвешенную скользящую среднюю в качестве строительных блоков и рассчитывается следующим образом:

  • Выберите период ретроспективного анализа, например 20 или 100, и рассчитайте взвешенное скользящее среднее цены закрытия.
  • Разделите период ретроспективного анализа, найденный на первом этапе, и рассчитайте взвешенное скользящее среднее цены закрытия, используя этот новый период ретроспективного анализа. Если число не может быть разделено на два, выберите ближайшее число перед запятой (например, ретроспективный анализ 15 может быть 7 или 8 как второй ретроспективный анализ).
  • Умножьте вторую взвешенную скользящую среднюю на два и вычтите из нее первую взвешенную скользящую среднюю.
  • В качестве последнего шага извлеките квадратный корень из первого ретроспективного анализа (например, если вы выбрали ретроспективный анализ, равный 100, то третий период ретроспективного анализа равен 10) и вычислите взвешенное скользящее среднее для последнего результата, который мы получили в третий шаг. Будьте осторожны, чтобы не рассчитывать его на основе рыночных цен.

Следовательно, если мы выберем период ретроспективного анализа 100, мы будем рассчитывать период ретроспективного анализа 100, затем 50 и, наконец, 10 применительно к последнему результату.

# To add a number of columns
def adder(Data, times):
    
    for i in range(1, times + 1):
    
        z = np.zeros((len(Data), 1), dtype = float)
        Data = np.append(Data, z, axis = 1)
    return Data
# To delete a number of columns
def deleter(Data, index, times):
    
    for i in range(1, times + 1):
    
        Data = np.delete(Data, index, axis = 1)
def hull_moving_average(Data, what, lookback, where):
    
    Data = lwma(Data, lookback, what)
    
    second_lookback = round((lookback / 2), 1)
    second_lookback = int(second_lookback) 
    
    Data = lwma(Data, second_lookback, what)
    
    Data = adder(Data, 1)
    Data[:, where + 2] = ((2 * Data[:, where + 1]) - Data[:, where])
    third_lookback = round(np.sqrt(lookback), 1)
    third_lookback = int(third_lookback)    
    Data = lwma(Data, third_lookback, where + 2)
    return Data

Индекс относительной силы

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

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

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



Индекс относительной прочности корпуса

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

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

def hull_rsi(Data, close, where):
    # Taking price differences
    Data = adder(Data, 3)
    
    for i in range(len(Data)):
        
        Data[i, where] = Data[i, close] - Data[i - 1, close]
    
    Data = Data[1:, ]
    
    # Finding up and down columns
    for i in range(len(Data)):
        
        if Data[i, where] > 0:
            Data[i, where + 1] = Data[i, where]
        elif Data[i, where] < 0:
            Data[i, where + 1] = 0
        if Data[i, where] < 0:
            Data[i, where + 2] = Data[i, where]
        elif Data[i, where] > 0:
            Data[i, where + 2] = 0    
            
    Data[:, where + 2] = abs(Data[:, where + 2])
    
    # Taking the Hull Moving Average of UP Periods
    Data = lwma(Data, lookback, 6)
    
    second_lookback = round((lookback / 2), 1)
    second_lookback = int(second_lookback) 
    
    Data = lwma(Data, second_lookback, 6)
    
    Data = adder(Data, 1)
    Data[:, 10] = ((2 * Data[:, 9]) - Data[:, 6])
    third_lookback = round(np.sqrt(lookback), 1)
    third_lookback = int(third_lookback)
    Data = lwma(Data, third_lookback, 10)
    Data[:, 11] = abs(Data[:, 11])
    
    for i in range(len(Data)):
        
        if Data[i, 11] == 0:
            Data[i, 11] = Data[i - 1, 11]
            
    Data = deleter(Data, 5, 1)
    Data = deleter(Data, 7, 3)
    
    # Taking the Hull Moving Average of DOWN Periods
    Data = lwma(Data, lookback, 6)
    
    second_lookback = round((lookback / 2), 1)
    second_lookback = int(second_lookback) 
    
    Data = lwma(Data, second_lookback, 6)
    
    Data = adder(Data, 1)
    Data[:, 10] = ((2 * Data[:, 9]) - Data[:, 8])
    third_lookback = round(np.sqrt(lookback), 1)
    third_lookback = int(third_lookback)
    Data = lwma(Data, third_lookback, 10)
    Data[:, 11] = abs(Data[:, 11])
    for i in range(len(Data)):
        
        if Data[i, 11] == 0:
            Data[i, 11] = Data[i - 1, 11]
    
    Data = deleter(Data, 8, 3)   
    Data = deleter(Data, 5, 2)
    
    # Calculating the Hull RSI
    Data = adder(Data, 2)
    
    Data[:, 7] = Data[:, 5] / Data[:, 6]
    
    for i in range(len(Data)):
        
        Data[i, 8] = (100.0 - (100.0 / (1.0 + Data[i, 7])))
    
    Data = deleter(Data, 5, 3)
    
    return Data

Бэк-тестирование стратегии

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

Условия такие, как ожидалось:

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

Функцию сигнала можно записать следующим образом (для обоих типов RSI):

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

Ниже приведены сводные результаты по эффективности для обоих типов стратегий на указанном ниже индикаторе RSI:

  • RSI Уайлдера с периодом ретроспективного анализа 5 с использованием 90 и 10 в качестве барьеров перепроданности / перекупленности.
  • RSI Халла с периодом ретроспективного анализа 5 с использованием 90 и 10 в качестве барьеров перепроданности / перекупленности.

Заявление об ограничении ответственности: Алан Халл, выдающийся специалист в области финансов и создатель скользящей средней Халла, не является создателем индекса относительной силы Халла.

Транзакционные издержки для вышеупомянутого бэк-теста, если сделка составляет 0,5 пункта за раунд с теоретическим соотношением риска и вознаграждения 0,25, установленным системой ATR.

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

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



Слово об управлении рисками

Когда я говорю, что использую систему управления рисками на основе ATR (средний истинный диапазон), это означает, что алгоритм будет выполнять следующие шаги в отношении занимаемой позиции.

Длинная позиция (покупка):

  • Алгоритм инициирует ордер на покупку после того, как был сгенерирован сигнал по определенной стратегии.
  • Затем алгоритм будет отслеживать тики, и всякий раз, когда максимум равен определенной константе, умноженной на значение ATR во время открытия сделки, инициируется ордер выхода (с прибылью). Одновременно, если виден минимум, равный определенной константе, умноженной на значение ATR на момент открытия сделки, инициируется выход (с убытком). Первым встреченный выход является, естественно, принятым событием.

Короткая (продажа) позиция:

  • Алгоритм инициирует короткий ордер на продажу после того, как был сгенерирован сигнал в соответствии с определенной стратегией.
  • Затем алгоритм будет отслеживать тики, и всякий раз, когда минимум равен определенной константе, умноженной на значение ATR во время открытия сделки, инициируется ордер выхода (с прибылью). Одновременно, если виден максимум, равный определенной константе, умноженной на значение ATR на момент открытия сделки, инициируется выход (с убытком). Первым встреченный выход является, естественно, принятым событием.

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

Взгляните на последнее значение ATR. Это около 0,0014 (14 пунктов). Если мы инициируем ордер на покупку, следуя простому соотношению риска и прибыли 2,00 (рискуя половиной того, что мы ожидаем получить), мы можем разместить ордер следующим образом:

  • Купить по текущей рыночной цене.
  • Тейк-профит по текущей рыночной цене + (2 x 14 пунктов).
  • Остановите позицию по текущей рыночной цене - (1 x 14 пунктов).

Код, который я использую для индикатора среднего истинного диапазона, выглядит следующим образом:

def ema(Data, alpha, lookback, what, where):
    
    # alpha is the smoothing factor
    # window is the lookback period
    # what is the column that needs to have its average calculated
    # where is where to put the exponential moving average
    
    alpha = alpha / (lookback + 1.0)
    beta  = 1 - alpha
    
    # First value is a simple SMA
    Data = ma(Data, lookback, what, where)
    
    # Calculating first EMA
    Data[lookback + 1, where] = (Data[lookback + 1, what] * alpha) + (Data[lookback, where] * beta)        
    # Calculating the rest of EMA
    for i in range(lookback + 2, len(Data)):
            try:
                Data[i, where] = (Data[i, what] * alpha) + (Data[i - 1, where] * beta)
        
            except IndexError:
                pass
    return Data
def eATR(Data, lookback, high, low, close, where):
    
    # TR
    for i in range(len(Data)):
        try:
            
            Data[i, where] = max(Data[i, high] - Data[i, low],
                               abs(Data[i, high] - Data[i - 1, close]),
                               abs(Data[i, low] - Data[i - 1, close]))
            
        except ValueError:
            pass
        
    Data[0, where] = 0    
    Data = ema(Data, 2, lookback, where, where + 1)
     return Data

Заключение

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

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

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

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

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

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

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

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