Написание торговой стратегии обратного RSI на Python.
Это будет небольшая статья, в которой обсуждается альтернативная теория индекса относительной силы, опубликованная в нескольких местах. Цель статьи - представить это так, чтобы читатель узнал о нем и, при необходимости, протестировал его на исторических данных.
Я только что опубликовал новую книгу после успеха моей предыдущей «Новые технические индикаторы на Python». Он содержит более полное описание и добавление структурированных торговых стратегий со страницей GitHub, посвященной постоянно обновляемому коду. Если вы считаете, что это вас заинтересует, перейдите по ссылке ниже или, если вы предпочитаете купить версию в формате PDF, вы можете связаться со мной через LinkedIn.
Индекс относительной силы
RSI, без сомнения, является самым известным индикатором импульса, и этого следовало ожидать, поскольку у него много сильных сторон, особенно на ранжированных рынках. Он также ограничен диапазоном от 0 до 100, что упрощает интерпретацию. Кроме того, тот факт, что он известен, увеличивает его потенциал.
Это связано с тем, что чем больше трейдеров и управляющих портфелем будут смотреть на RSI, тем больше людей будет реагировать на его сигналы, а это, в свою очередь, может подтолкнуть рыночные цены. Конечно, мы не можем доказать эту идею, но она интуитивно понятна, поскольку одна из основ технического анализа заключается в том, что она самореализируется.
RSI рассчитывается довольно простым способом. Сначала мы берем разницу в ценах за один период. Это означает, что мы должны вычесть каждую цену закрытия из предыдущей. Затем мы вычислим сглаженное среднее положительных разностей и разделим его на сглаженное среднее отрицательных разностей. Последний расчет дает нам относительную силу, которая затем используется в формуле RSI для преобразования в меру от 0 до 100.
Для расчета индекса относительной силы нам понадобится массив OHLC (а не фрейм данных). Это означает, что мы будем смотреть на массив из 4 столбцов. Таким образом, функция индекса относительной силы:
# The function to add a number of columns inside an array def adder(Data, times): for i in range(1, times + 1): new_col = np.zeros((len(Data), 1), dtype = float) Data = np.append(Data, new_col, axis = 1) return Data # The function to delete a number of columns starting from an index 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 number of rows from the beginning def jump(Data, jump): Data = Data[jump:, ] return Data # Example of adding 3 empty columns to an array my_ohlc_array = adder(my_ohlc_array, 3) # Example of deleting the 2 columns after the column indexed at 3 my_ohlc_array = deleter(my_ohlc_array, 3, 2) # Example of deleting the first 20 rows my_ohlc_array = jump(my_ohlc_array, 20) # Remember, OHLC is an abbreviation of Open, High, Low, and Close and it refers to the standard historical data file 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 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
Если вы хотите поддержать меня и статьи, которые я регулярно публикую, рассмотрите возможность подписки на мой ЕЖЕДНЕВНЫЙ информационный бюллетень (доступен бесплатный план) по приведенной ниже ссылке. В нем есть некоторые из моих статей о Medium, другие торговые стратегии и уроки программирования, связанные с исследованиями и анализом. Оформив подписку, вы можете рассчитывать на 5–7 статей в неделю. Это поможет мне продолжать делиться своими исследованиями. Спасибо!
Создание стратегии
Наиболее распространенной стратегией, используемой для RSI, является возврат к среднему, когда трейдер должен обнаруживать экстремумы импульса, которые сигнализируют о развороте.
- Уровень перепроданности - это порог в Индексе относительной силы, при котором рынок воспринимается как перепроданный и готовый к бычьей реакции. Идея состоит в том, что произошло слишком много продаж и рынок должен ненадолго восстановиться.
- Уровень перекупленности - это порог в Индексе относительной силы, при котором рынок воспринимается как перекупленный и готовый к медвежьей реакции. Идея состоит в том, что произошло слишком много покупок, и рынок должен ненадолго остановиться.
Существует другая теория, которая утверждает, что RSI - это скорее стратегия подтверждения импульса, и поэтому уровень перекупленности на самом деле является сигналом покупки, а перепроданность - сигналом продажи. Теперь все зависит от управления рисками и периода удержания стратегии, но результаты этих двух противоположных методов смешаны с уклоном в сторону исходной. Однако мы можем просто взглянуть на то, как закодировать этот альтернативный способ использования RSI.
Чтобы закодировать функцию, которая выдает сигналы о перепроданности и перекупленности, можно написать следующий код:
lookback = 13 upper_barrier = 70 lower_barrier = 30 def signal(Data, rsi_col, buy, sell): Data = adder(Data, 10) for i in range(len(Data)): if Data[i, rsi_col] >= upper_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] <= lower_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
Метод, примененный ко многим рынкам, не дал хороших результатов, и альтернативная стратегия, основанная на бэк-тестах, вряд ли будет хороша, если не будет сильно модифицирована и смешана с другими индикаторами. На приведенном выше графике показаны сигналы, сгенерированные на основе 13-периодного RSI и экстремальных уровней 70/30.
my_data = rsi(my_data, lookback, 3, 4) my_data = signal(my_data, 4, 6, 7)
Если вас также интересуют другие технические индикаторы и использование Python для создания стратегий, то мой бестселлер по техническим индикаторам может вас заинтересовать:
Заключение
Не забывайте всегда проводить тесты на исторических данных. Вы всегда должны верить, что другие люди неправы. Мои индикаторы и стиль торговли могут работать на меня, но может не на вас.
Я твердо убежден, что нельзя кормить с ложечки. Я научился на практике, а не копируя. Вы должны понять идею, функцию, интуицию, условия стратегии, а затем разработать (даже лучше) одну из них самостоятельно, чтобы вы протестировали и улучшили ее, прежде чем принимать решение о том, чтобы применить ее вживую или отказаться от нее. Мой выбор в пользу отказа от предоставления конкретных результатов тестирования на истории должен побудить читателя лучше изучить стратегию и больше работать над ней.
Medium - это центр множества интересных чтений. Я прочитал много статей, прежде чем решил начать писать. Рассмотрите возможность присоединения к Medium!
Подводя итог, можно ли сказать, что стратегии, которые я предлагаю, реалистичны? Да, но только путем оптимизации среды (надежный алгоритм, низкие затраты, честный брокер, надлежащее управление рисками и управление заказами). Предусмотрены ли стратегии исключительно для торговли? Нет, это нужно для стимулирования мозгового штурма и получения новых торговых идей, поскольку мы все устали слышать о перепроданности RSI как о причине для открытия короткой позиции или о преодолении сопротивления как о причине идти долго. Я пытаюсь представить новую область под названием «Объективный технический анализ», в которой мы используем достоверные данные для оценки наших методов, а не полагаемся на устаревшие классические методы.