Создание и кодирование экстремальной продолжительности торговли на рынках.

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

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



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

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

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

def rsi(Data, rsi_lookback, what1, what2):
    
    # From exponential to smoothed
    rsi_lookback = (rsi_lookback * 2) - 1  
        
    # Get the difference in price from previous step
    delta = []
   
    for i in range(len(Data)):
        try:
            diff = Data[i, what1] - Data[i - 1, what1] 
            delta = np.append(delta, diff)                  
        except IndexError:
            pass
        
    delta = np.insert(delta, 0, 0, axis = 0)               
    delta = delta[1:] 
    
    # Make the positive gains (up) and negative gains (down) Series
    up, down = delta.copy(), delta.copy()
    up[up < 0] = 0
    down[down > 0] = 0
    
    up = np.array(up)
    down = np.array(down)
    
    roll_up = up
    roll_down = down
    
    roll_up = np.reshape(roll_up, (-1, 1))
    roll_down = np.reshape(roll_down, (-1, 1))
    
    roll_up = adder(roll_up, 3)
    roll_down = adder(roll_down, 3)
    
    roll_up = ema(roll_up, 2, rsi_lookback, what2, 1)
    roll_down = ema(abs(roll_down), 2, rsi_lookback, what2, 1)
    
    roll_up = roll_up[rsi_lookback:, 1:2]
    roll_down = roll_down[rsi_lookback:, 1:2]
    Data = Data[rsi_lookback + 1:,]
    
    # Calculate the RS & RSI
    RS = roll_up / roll_down
    RSI = (100.0 - (100.0 / (1.0 + RS)))
    RSI = np.array(RSI)
    RSI = np.reshape(RSI, (-1, 1))
    RSI = RSI[1:,]
    
    Data = np.concatenate((Data, RSI), axis = 1)             
    return Data
# Using the funtion on OHLC Data
my_data = rsi(my_data, lookback 3, 0)

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

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

Чтобы иметь возможность манипулировать данными, нам сначала нужно иметь массив 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, потому что 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, 5, 3, 0)
# 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

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

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



Заключение

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

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

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

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

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

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