Пошаговое руководство по этому известному индикатору и его стратегиям на Python.

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

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



Построение индекса относительной силы

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

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

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

Для расчета индекса относительной силы нам понадобится массив OHLC (а не фрейм данных). Это означает, что мы будем смотреть на массив из 4 столбцов. Таким образом, функция индекса относительной силы:

def rsi(Data, lookback, close, where, width = 1, genre = 'Smoothed'):
    
    # Adding a few columns
    Data = adder(Data, 7)
    
    # Calculating Differences
    for i in range(len(Data)):
        
        Data[i, where] = Data[i, close] - Data[i - width, close]
     
    # Calculating the Up and Down absolute values
    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 + 2] = abs(Data[i, where])
            
    # Calculating the Smoothed Moving Average on Up and Down
    absolute values    
    if genre == 'Smoothed':                    lookback = (lookback * 2) - 1 # From exponential to smoothed
      Data = ema(Data, 2, lookback, where + 1, where + 3)
      Data = ema(Data, 2, lookback, where + 2, where + 4)
    
    if genre == 'Simple':                    Data = ma(Data, lookback, where + 1, where + 3)
      Data = ma(Data, lookback, where + 2, where + 4)
    
    # Calculating the Relative Strength
    Data[:, where + 5] = Data[:, where + 3] / Data[:, where + 4]
    
    # Calculate the Relative Strength Index
    Data[:, where + 6] = (100 - (100 / (1 + Data[:, where + 5])))  
    
    # Cleaning
    Data = deleter(Data, where, 6)
    Data = jump(Data, lookback)                    
    return Data

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

# The function to add a certain 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
# The function to deleter a certain number of columns
def deleter(Data, index, times):
    
    for i in range(1, times + 1):
    
        Data = np.delete(Data, index, axis = 1)               
    
    return Data
# The function to delete a certain number of rows from the beginning
def jump(Data, jump):
    
    Data = Data[jump:, ]
    
    return Data

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



Обсуждение стратегии: техника перепроданности / перекупленности

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

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

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

lookback         = 21
upper_barrier    = 80
lower_barrier    = 20
def signal(Data, rsi_col, buy, sell):
    
    for i in range(len(Data)):
            
        if Data[i, rsi_col] < lower_barrier and Data[i - 1, buy] == 0 and Data[i - 2, buy] == 0 and Data[i - 3, buy] == 0 and Data[i - 4, buy] == 0:
            Data[i, buy] = 1
            
        elif Data[i, rsi_col] > upper_barrier and Data[i - 1, sell] == 0 and Data[i - 2, sell] == 0 and Data[i - 3, sell] == 0 and Data[i - 4, sell] == 0:
            Data[i, sell] = -1    
            
    return Data

Обсуждение стратегии: техника дивергенции

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

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

Приведенный выше график показывает EURUSD на первой панели и 21-периодный RSI на второй панели. Медвежьи расхождения окрашены в красный цвет там, где мы должны ожидать некоторой формы консолидации, а бычьи расхождения окрашены в синий цвет, где мы должны ожидать некоторой формы восходящей реакции.

Дивергенцию предпочтительно рассматривать, когда индикатор находится около экстремумов. Обратите внимание, как в приведенном выше примере значения RSI ближе к 70 или 30, когда мы действительно обнаруживаем расхождения. Однако мы также можем рассматривать 60 или 40 как крайность.

def divergence(Data, indicator, lower_barrier, upper_barrier, width, buy, sell):
    
    for i in range(len(Data)):
        
        try:
            if Data[i, indicator] < lower_barrier:
                
                for a in range(i + 1, i + width):
                    
                    # First trough
                    if Data[a, indicator] > lower_barrier:
                        
                        for r in range(a + 1, a + width):
                            
                            if Data[r, indicator] < lower_barrier and Data[r, indicator] > Data[i, indicator] and Data[r, 3] < Data[i, 3]:
                                
                                for s in range(r + 1, r + width):
                                    
                                    # Second trough
                                    if Data[s, indicator] > lower_barrier:
                                        Data[s, buy] = 1
                                        break
                                    
                                    else:
                                        break
                            else:
                                break
                        else:
                            break
                    else:
                        break
                    
        except IndexError:
            pass
      
    for i in range(len(Data)):
        
        try:
            if Data[i, indicator] > upper_barrier:
                
                for a in range(i + 1, i + width):
                    
                    # First trough
                    if Data[a, indicator] < upper_barrier:
                        for r in range(a + 1, a + width):
                            if Data[r, indicator] > upper_barrier and Data[r, indicator] < Data[i, indicator] and Data[r, 3] > Data[i, 3]:
                                for s in range(r + 1, r + width):
                                    
                                    # Second trough
                                    if Data[s, indicator] < upper_barrier:
                                        Data[s, sell] = -1
                                        break
                                    else:
                                        break
                            else:
                                break
                        else:
                            break
                    else:
                        break
        except IndexError:
            pass
 
    return Data

Обсуждение стратегии: техника продолжительности

Сначала я представил RSI, потому что Extreme Duration - это просто дополнение к любому ограниченному индикатору. Это не индикатор сам по себе, а просто способ увидеть, как долго индикатор находится в состоянии перекупленности или перепроданности. Мы понимаем, что:

  • Индикатор перекупленности говорит о том, что бычий импульс скоро исчезнет, ​​и мы можем увидеть коррекцию или даже разворот вниз.
  • Индикатор перепроданности говорит о том, что медвежий импульс должен скоро исчезнуть, и мы можем увидеть коррекцию или даже разворот вверх.

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

На приведенном выше графике показан расчет экстремальной продолжительности на основе 5-периодного RSI с барьерами на уровне 70 и 30. Когда экстремальная продолжительность показывает значение 5, это означает, что 5-периодный RSI превышает 70 пятый раз подряд ( т.е. превзошла 70 и держалась выше 5 единиц времени). Мы привыкли анализировать эти показатели по стоимости, на этот раз мы хотим проанализировать их по времени.

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

# Calculate the RSI on OHLC array (composed of 4 columns)
my_data= rsi(my_data, lookback, 3, 4, genre = 'Smoothed')
# Add a few spare columns to be populated with whatever you want
my_data = adder(my_data, 20)
# Define the Barriers (Oversold and Overbought zones)
upper_barrier    = 70
lower_barrier    = 30
# Define the Extreme Duration
def extreme_duration(Data, indicator, upper_barrier, lower_barrier, where_upward_extreme, where_downward_extreme):
        
    # Time Spent Overbought 
    for i in range(len(Data)):      
      if Data[i, indicator] > upper_barrier:
            Data[i, where_upward_extreme] = Data[i - 1,   where_upward_extreme] + 1
            
        else:
            a = 0
            Data[i, where_upward_extreme] = a
            
    # Time Spent Oversold   
    for i in range(len(Data)):
        
      if Data[i, indicator] < lower_barrier:
            Data[i, where_downward_extreme] = Data[i - 1, where_downward_extreme] + 1
            
        else:
            a = 0
            Data[i, where_downward_extreme] = a
    
    Data[:, where_downward_extreme] = -1 * Data[:, where_downward_extreme]
    
    return Data
# Calculating the Extreme Duration
my_data = extreme_duration(my_data, 4, upper_barrier, lower_barrier, 5, 6)

Давайте теперь попробуем использовать Extreme Duration для генерации сигналов на основе этой гипотезы:

«Что, если среднее время, потраченное на крайности, может помочь нам понять, когда индикатор будет существовать в этих упомянутых крайностях?»

Основываясь на историческом анализе, средняя продолжительность 5-периодного RSI составляет от 3 до 4. Однако, основываясь на визуальном историческом представлении, она ближе к 5. Давайте установим временные барьеры на 5 и -5.

На приведенном выше графике показаны сигналы, генерируемые, когда 5-периодный RSI на почасовых данных EURUSD остается в течение как минимум 5 периодов на экстремумах.

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

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

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



Другие варианты: простой индекс относительной силы

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

my_data = rsi(my_data, 14, 3, 4, genre = 'Simple')
# The 14 refers to the lookback period on the RSI
# The 3 refers to the closing prices on the OHLC array
# The 4 refers to the index of the column where the RSI will be put

Чтобы функция индекса относительной силы работала, нам необходимо определить функции используемых скользящих средних:

def ma(Data, lookback, close, where): 
    Data = adder(Data, 1)
    for i in range(len(Data)):
            try:
                Data[i, where] = (Data[i - lookback + 1:i + 1, close].mean())
            except IndexError:
                pass
    # Cleaning
    Data = jump(Data, lookback)
    return Data
def ema(Data, alpha, lookback, what, where):
    
    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

Другие варианты: индекс адаптивной относительной силы

Наращивание ясное, мы хотим поменять сглаженную скользящую среднюю в приведенной выше функции RSI на KAMA и посмотреть, каковы будут результаты. Ясно, что здесь есть небольшая проблема: индикаторы в их стандартной форме работают хуже, да, но они остаются видимыми для многих участников рынка. Это то, что я называю феноменом вуали. Хотя визуально сигналы, генерируемые стандартным 14-периодным RSI, приятны и, кажется, чаще фиксируют вершины и основания, результаты бэк-тестирования катастрофичны. Это происходит из-за полуслучайной реакции рынка после генерации сигнала, что делает выход после сигнала хрупким и фиксированным, а не переменным в соответствии с текущими статистическими свойствами базового актива.

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

Вернемся к нашему индикатору. На графике ниже показано, чего мы хотим достичь:

Код Python для индекса адаптивной силы следующий:

def kama(Data, what, where, lookback):
    
    # lookback from previous period
    for i in range(len(Data)):
        Data[i, where] = abs(Data[i, what] - Data[i - 1, what])
    
    Data[0, where] = 0
    
    # Sum of lookbacks
    for i in range(len(Data)):
        Data[i, where + 1] = (Data[i - lookback + 1:i + 1, where].sum())   
        
    # Volatility    
    for i in range(len(Data)):
        Data[i, where + 2] = abs(Data[i, what] - Data[i - lookback, what])
        
    Data = Data[lookback + 1:, ]
    
    # Efficiency Ratio
    Data[:, where + 3] = Data[:, where + 2] / Data[:, where + 1]
    
    for i in range(len(Data)):
        Data[i, where + 4] = np.square(Data[i, where + 3] * 0.6666666666666666667)
        
    for i in range(len(Data)):
        Data[i, where + 5] = Data[i - 1, where + 5] + (Data[i, where + 4] * (Data[i, what] - Data[i - 1, where + 5]))
        Data[11, where + 5] = 0
        
    Data = deleter(Data, where, 5)
    Data = jump(Data, lookback * 2)
    
    return Data
# Selecting Lookbacks
lookback         = 5
lookback_ama     = 5
# Applying the Relative Strength Index on OHLC Array
Asset1 = rsi(Asset1, lookback, 3, 0)
# Adding a few columns
Asset1 = adder(Asset1, 10)
# Applying the KAMA as a Signal Line
Asset1 = kama(Asset1, 5, 6, lookback_ama)

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

Другие варианты: динамический индекс относительной силы

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

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

Самый основной тип волатильности - это стандартное отклонение. Это один из столпов описательной статистики и важный элемент некоторых технических индикаторов, таких как знаменитые полосы Боллинджера. Но сначала давайте определим, что такое дисперсия, прежде чем мы найдем стандартное отклонение.

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

Следуя сказанному, стандартное отклонение составляет:

def volatility(Data, lookback, what, where):
    
  for i in range(len(Data)):
    try:
      Data[i, where] = (Data[i - lookback + 1:i + 1, what].std())        except IndexError:
            pass
        
    return Data

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

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

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

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

  • Индекс относительной волатильности.
  • Индекс относительной силы.

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

lookback = 10def dynamic_relative_strength_index(Data, lookback, close, where):
    
    # Calculating the Relative Volatility Index
    Data = relative_volatility_index(Data, lookback, close, where)
    
    # Adding a column
    Data = adder(Data, 1)
        
    # Calculating the Lookback Periods on the Dynamic Relative Strength Index
    for i in range(len(Data)):
        
        if Data[i, where] >= 0 and Data[i, where] <= 10 :
            Data[i, where + 1] = 144
            
        if Data[i, where] > 10 and Data[i, where] <= 20 :
            Data[i, where + 1] = 89
            
        if Data[i, where] > 20 and Data[i, where] <= 30 :
            Data[i, where + 1] = 55
            
        if Data[i, where] > 30 and Data[i, where] <= 40 :
            Data[i, where + 1] = 34
            
        if Data[i, where] > 40 and Data[i, where] <= 50 :
            Data[i, where + 1] = 21
            
        if Data[i, where] > 50 and Data[i, where] <= 60 :
            Data[i, where + 1] = 13
            
        if Data[i, where] > 60 and Data[i, where] <= 70 :
            Data[i, where + 1] = 8
            
        if Data[i, where] > 70 and Data[i, where] <= 80 :
            Data[i, where + 1] = 5
            
        if Data[i, where] > 80 and Data[i, where] <= 90 :
            Data[i, where + 1] = 3
            
        if Data[i, where] > 90 and Data[i, where] <= 100 :
            Data[i, where + 1] = 2    
    # Calculating the Relative Strength Index
    Data = rsi(Data, 2, close, where + 2)
    Data = rsi(Data, 3, close, where + 3)
    Data = rsi(Data, 5, close, where + 4)
    Data = rsi(Data, 8, close, where + 5)
    Data = rsi(Data, 13, close, where + 6)
    Data = rsi(Data, 21, close, where + 7)
    Data = rsi(Data, 34, close, where + 8)
    Data = rsi(Data, 55, close, where + 9)
    Data = rsi(Data, 89, close, where + 10)
    Data = rsi(Data, 144, close, where + 11)
    
    # Adding a column
    Data = adder(Data, 1)
    
    # Dynamic Relative Strength Index
    for i in range(len(Data)):
        
        if Data[i, where + 1] == 2:
            Data[i, where + 12] = Data[i, where + 2]
            
        if Data[i, where + 1] == 3:
            Data[i, where + 12] = Data[i, where + 3]        
        if Data[i, where + 1] == 5:
            Data[i, where + 12] = Data[i, where + 4]        
        if Data[i, where + 1] == 8:
            Data[i, where + 12] = Data[i, where + 5]        
        if Data[i, where + 1] == 13:
            Data[i, where + 12] = Data[i, where + 6]        
        if Data[i, where + 1] == 21:
            Data[i, where + 12] = Data[i, where + 7]        
        if Data[i, where + 1] == 34:
            Data[i, where + 12] = Data[i, where + 8]        
        if Data[i, where + 1] == 55:
            Data[i, where + 12] = Data[i, where + 9]        
        if Data[i, where + 1] == 89:
            Data[i, where + 12] = Data[i, where + 10]        
        if Data[i, where + 1] == 144:
            Data[i, where + 12] = Data[i, where + 11]
            
    # Cleaning
    Data = deleter(Data, where, 12)
    
    return Data

Приведенный выше код просто вычисляет 10-периодный индекс относительной волатильности, а затем вычисляет массив RSI по рыночной цене, используя следующие периоды ретроспективного анализа {2, 3, 5, 8, 13, 21, 34, 55, 89, 144}, которая представляет собой просто последовательность Фибоначчи (Большой веер). Затем код будет перебирать данные и сегментировать индекс относительной волатильности на 10 частей, каждой из которых назначен период Фибоначчи. Например:

  • Если индекс относительной волатильности показывает значение 8, значит, он попадает в первую часть. При такой низкой волатильности ретроспективный прогноз, рассчитанный по RSI, составляет 144. Это необходимо для учета низкой текущей волатильности.
  • Если индекс относительной волатильности показывает значение 85, то он попадает в девятую часть. При такой высокой волатильности ретроспективный прогноз, рассчитанный по RSI, равен 89. Это объясняется высокой текущей волатильностью.

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

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



Другие варианты: RSI-Stochastic

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

def rsi_stoch(Data, lookback, high, low, close, where):
    
    # Adding a column
    Data = adder(Data, 1)
    
    for i in range(len(Data)):
        
        try:
            Data[i, where] = (Data[i, close] - min(Data[i - lookback + 1:i + 1, low])) / (max(Data[i - lookback + 1:i + 1, high]) - min(Data[i - lookback + 1:i + 1, low]))
        
        except ValueError:
            pass
    
    Data[:, where] = Data[:, where] * 100
    Data = jump(Data, lookback)    
    
    # Calculating RSI of the Closing prices
    Data = rsi(Data, lookback, where, 0)    
    # Cleaning    
    Data = deleter(Data, where, 1)
    
    return Data

Чтобы использовать функцию RSI Stochastic (из 5 периодов), нам просто нужен массив OHLC, а затем напишите следующую строку кода, которая вызывает функцию:

my_data = rsi_stoch(my_data, 5, 1, 2, 3, 4)

Другие варианты: индикатор RSI-Delta

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

Преобразование RSI Delta обеспечивает еще более возвращающийся к среднему значению индикатор, как показано ниже на графике.

Давайте теперь посчитаем корреляцию между RSI Delta и рыночной ценой, чтобы увидеть, остается ли она сильной или нет.

correlation = 0.51 # For the last 80 observations which is good

def rsi_delta(Data, lookback, what, where):
    
    Data = rsi(Data, lookback, what, 0)
    
    for i in range(len(Data)):
        Data[i, where] = Data[i, where - 1] - Data[i - lookback, where - 1]
        
    return Data

Давайте теперь протестируем обратную стратегию, которая в основном аналогична той, которую мы использовали бы на обычном RSI.

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

Заключение и важный отказ от ответственности

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

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

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