Использование технических индикаторов на графиках K’s Candlestick Chart в качестве усилителя уверенности.

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

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



Графики обычных свечей

Свечи - это быстрый способ понять данные OHLC и обнаружить закономерности. Это очень просто и легко интерпретируется. Бычья (обычно зеленая) свеча - это когда рынок закрывается выше цены открытия. Медвежья (обычно красная) свеча - это когда рынок закрывается ниже цены открытия.

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

def ohlc_plot(Data, window, name):
      
    Chosen = Data[-window:, ]
    
    for i in range(len(Chosen)):
        
        plt.vlines(x = i, ymin = Chosen[i, 2], ymax = Chosen[i, 1], color = 'black', linewidth = 1)  
        
        if Chosen[i, 3] > Chosen[i, 0]:
            color_chosen = 'green'
            plt.vlines(x = i, ymin = Chosen[i, 0], ymax = Chosen[i, 3], color = color_chosen, linewidth = 2)        
        if Chosen[i, 3] < Chosen[i, 0]:
            color_chosen = 'red'
            plt.vlines(x = i, ymin = Chosen[i, 3], ymax = Chosen[i, 0], color = color_chosen, linewidth = 2)  
            
        if Chosen[i, 3] == Chosen[i, 0]:
            color_chosen = 'black'
            plt.vlines(x = i, ymin = Chosen[i, 3], ymax = Chosen[i, 0], color = color_chosen, linewidth = 2)  
            
    plt.grid()
    plt.title(name)

Приведенный выше код строит свечной график, как показано. Требуется массив данных OHLC. Переменная окна указывает, сколько наблюдений будет показано на диаграмме.

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



Свечные графики K’s

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

  • Рассчитайте двух- или трехпериодное простое скользящее среднее для цены открытия.
  • Рассчитайте двух- или трехпериодное простое скользящее среднее для максимальной цены.
  • Рассчитайте двух- или трехпериодное простое скользящее среднее для минимальной цены.
  • Рассчитайте двух- или трехпериодное простое скользящее среднее цены закрытия.

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

На приведенных выше графиках показаны разные графики EURUSD. Используемый период - 3. Мы можем заметить, насколько более плавный график свечей K по сравнению с шумным обычным графиком. Под шумным здесь подразумевается интерпретируемость тренда. Когда последовательно наблюдаются красные или зеленые свечи, легче определить тренд.

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

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

  • Интерпретируемость тренда. Подобно Heikin-Ashi, график K’s Candlestick сглаживает данные, чтобы удалить краткосрочный шум и предоставить более четкую картину текущего тренда.
  • Распознавание паттернов. Доджи и паттерны истощения более распространены в свечах K и, следовательно, добавляют фактор подтверждения. По моему опыту, они также работают лучше, чем в обычных графиках.

Но также еще одна интересная вещь, которую мы увидим в этой статье, - это сигналы, генерируемые индексом относительной силы. Мы разработаем систему, которая генерирует указанные сигналы на графиках K’s Candlestick и накладывает их на обычные графики, чтобы визуально интерпретировать сигналы. Вам остается проверить их эффективность.

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 k_candlesticks(Data, opening, high, low, close, lookback, where):
    
    # Adding the necessary columns
    Data = adder(Data, 4)
    
    # Averaging the Open
    Data = ma(Data, lookback, opening, where)
     
    # Averaging the High
    Data = ma(Data, lookback, high, where + 1)
       
    # Averaging the Low
    Data = ma(Data, lookback, low, where + 2)
       
    # Averaging the Close
    Data = ma(Data, lookback, close, where + 3)
    
    return Data

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



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

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

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

Для расчета индекса относительной силы нам понадобится массив 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

Создание стратегии

Идея ясна, используя 14-периодный простой индекс относительной силы через значения на графиках свечи K для определения сигналов. Однако, поскольку графики K представляют собой простое преобразование обычных ценовых данных, мы можем добавить еще одно условие, чтобы превратить его в более полную стратегию. Ниже приведены подробные условия:

  • Сначала нам нужно найти шаблоны доджи. Это свечи, которые выглядят как знак плюса. Они сигнализируют о нерешительности и развороте рынка.
  • Во-вторых, нам нужно, чтобы 14-периодный RSI (примененный на графике K) был меньше 25 для бычьего сигнала и больше 75 для медвежьего сигнала.

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

# Creating the K's Candlestick Chart based on an OHLC Dataset where K's OHLC starts at column 5
my_data = k_candlesticks(my_data, 0, 1, 2, 3, 3, 5)
# Calculating a 5-period Simple RSI on the closing prices of the K's Candlestick Chart
my_data= rsi(my_data, 14, 8, 9, genre = 'Simple')

# The function to plot the above chart
def indicator_plot_double(Data, opening, high, low, close, second_panel, window = 250):
  fig, ax = plt.subplots(2, figsize = (10, 5))
  Chosen = Data[-window:, ]
    
    for i in range(len(Chosen)):
        
        ax[0].vlines(x = i, ymin = Chosen[i, low], ymax = Chosen[i, high], color = 'black', linewidth = 1)  
        
        if Chosen[i, close] > Chosen[i, opening]:
            color_chosen = 'green'
            ax[0].vlines(x = i, ymin = Chosen[i, opening], ymax = Chosen[i, close], color = color_chosen, linewidth = 2)
        if Chosen[i, close] < Chosen[i, opening]:
            color_chosen = 'red'
            ax[0].vlines(x = i, ymin = Chosen[i, close], ymax = Chosen[i, opening], color = color_chosen, linewidth = 2)  
            
        if Chosen[i, close] == Chosen[i, opening]:
            color_chosen = 'black'
            ax[0].vlines(x = i, ymin = Chosen[i, close], ymax = Chosen[i, opening], color = color_chosen, linewidth = 2)  
   
    ax[0].grid() 
     
    ax[1].plot(Data[-window:, second_panel], color = 'black', linewidth = 1)
    ax[1].grid()
    ax[1].legend()

Как объяснялось выше, условиями стратегии являются:

  • Открывайте длинную позицию (покупайте), когда 14-периодный RSI находится на уровне 25 или ниже, в то время как рынок (отраженный свечным графиком K) только что закрылся по паттерну Доджи в то же время. Это означает, что цена закрытия должна быть доджи, а соответствующее значение RSI - 25 или ниже.
  • Открывайте короткую позицию (продавайте), когда 14-периодный RSI находится на уровне 75 или выше, в то время как рынок (отраженный свечным графиком K) только что одновременно закрылся по паттерну доджи. Это означает, что цена закрытия должна быть доджи, а соответствующее значение RSI должно быть не ниже 75.
def signal(Data, rsi_col, opening, close, buy, sell):
    
    Data = adder(Data, 10)
    Data = rounding(Data, 4) # Important for the Doji detection
    
    for i in range(len(Data)):
            
        if Data[i, rsi_col] <= lower_barrier and Data[i, opening] == Data[i, close]:
            Data[i, buy] = 1
            
        elif Data[i, rsi_col] >= upper_barrier and Data[i, opening] == Data[i, close]:
            Data[i, sell] = -1    
            
    return Data

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

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

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

Рамки оценки стратегии

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

В приведенной выше таблице говорится, что нам нужен индикатор или генератор сигналов в столбце 4 или 5 (помните, индексирование в Python начинается с нуля). Сигнал покупки (константа = 1) в столбце с индексом 6 и сигнал короткой продажи (константа = -1) в столбце с индексом 7. Это гарантирует, что оставшаяся часть приведенного ниже кода работает так, как должна работать. Причина этого в том, что в данных OHLC у нас уже заняты первые 4 столбца, поэтому нам остается 1 или 2 столбца для размещения наших индикаторов, прежде чем появятся два столбца сигналов. Использование функции удаления, показанной выше, может помочь вам достичь этого порядка, если индикаторы занимают более 2 столбцов.

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

def holding(Data, buy, sell, buy_return, sell_return):for i in range(len(Data)):
        try:
            if Data[i, buy] == 1: 
               for a in range(i + 1, i + 1000):                        
                  if Data[a, buy] != 0 or Data[a, sell] != 0:
                     Data[a, buy_return] = (Data[a, 3] - Data[i, 3])
                        break                        
                    else:
                        continue
                
            elif Data[i, sell] == -1:        
               for a in range(i + 1, i + 1000):                        
                  if Data[a, buy] != 0 or Data[a, sell] != 0:
                    Data[a, sell_return] = (Data[i, 3] - Data[a, 3])
                        break                                        
                    else:
                        continue                                         
        except IndexError:
            pass
# Using the function
holding(my_data, 6, 7, 8, 9)

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

def indexer(Data, expected_cost, lot, investment):
    
    # Charting portfolio evolution  
    indexer = Data[:, 8:10]    
    
    # Creating a combined array for long and short returns
    z = np.zeros((len(Data), 1), dtype = float)
    indexer = np.append(indexer, z, axis = 1)
    
    # Combining Returns
    for i in range(len(indexer)):
        try:    
          if indexer[i, 0] != 0:
             indexer[i, 2] = indexer[i, 0] - (expected_cost / lot)
                
          if indexer[i, 1] != 0:
             indexer[i, 2] = indexer[i, 1] - (expected_cost / lot)
        except IndexError:
            pass
        
    # Switching to monetary values
    indexer[:, 2] = indexer[:, 2] * lot
    
    # Creating a portfolio balance array
    indexer = np.append(indexer, z, axis = 1)
    indexer[:, 3] = investment 
    
    # Adding returns to the balance    
    for i in range(len(indexer)):
    
        indexer[i, 3] = indexer[i - 1, 3] + (indexer[i, 2])
    
    indexer = np.array(indexer)
    
    return np.array(indexer)# Using the function for a 0.1 lot strategy on $10,000 investment
expected_cost = 0.5 * (lot / 10000) # 0.5 pip spread
investment    = 10000                  
lot           = 10000
equity_curve = indexer(my_data, expected_cost, lot, investment)

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

plt.plot(equity_curve[:, 3], linewidth = 1, label = 'EURUSD)
plt.grid()
plt.legend()
plt.axhline(y = investment, color = 'black’, linewidth = 1)
plt.title(’Strategy’, fontsize = 20)

Теперь пора начать оценивать производительность с помощью других мер.

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

Hit ratio       =  42.28 % # Simulated Ratio

Коэффициент попадания чрезвычайно прост в использовании. Это просто количество прибыльных сделок по сравнению с общим количеством заключенных сделок. Например, если в течение 5 лет у нас было 1359 сделок и 711 из них были прибыльными, то наш коэффициент совпадения (точность) составляет 711/1359 = 52,31%.

Чистая прибыль - это просто последнее значение кривой капитала за вычетом комиссий за вычетом начального баланса. Это просто добавленная стоимость суммы, которую мы инвестировали вначале.

Net profit      =  $ 1209.4 # Simulated Profit

Показатель чистой прибыли - это ваша прибыль на ваши инвестиции или собственный капитал. Если вы начали с 1000 долларов, а в конце года на вашем балансе будет 1300 долларов, то вы заработали бы здоровые 30%.

Net Return      =  30.01% # Simulated Return

Быстрый взгляд на среднюю прибыль по сделкам и средний убыток может помочь нам лучше управлять нашими рисками. Например, если наша средняя прибыль составляет 1,20 доллара, а средний убыток - 4,02 доллара, то мы знаем, что что-то не так, поскольку мы рискуем слишком большими деньгами в обмен на слишком маленькую прибыль.

Average Gain    =  $ 56.95 per trade # Simulated Average Gain
Average Loss    =  $ -41.14 per trade # Simulated Average Loss

После этого мы можем рассчитать две меры:

  • Теоретическое соотношение риска и прибыли: это желаемое отношение средней прибыли к средним потерям. Коэффициент 2,0 означает, что мы нацелены вдвое больше, чем рискуем.
  • Реализованное соотношение риска и прибыли: это фактическое отношение средней прибыли к средним потерям. Коэффициент 0,75 означает, что мы нацелены на три четверти того, чем мы рискуем.
Theoretical Risk Reward = 2.00 # Simulated Ratio
Realized Risk Reward    = 0.75 # Simulated Ratio

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

Profit factor   =  1.34 # Simulated Profit Factor

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

Expectancy      =  $ 1.33 per trade # Simulated Expectancy

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

Trades          = 3697 # Simulated Number

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

def performance(indexer, Data, name):
    
    # Profitability index
    indexer = np.delete(indexer, 0, axis = 1)
    indexer = np.delete(indexer, 0, axis = 1)
    
    profits = []
    losses  = []
    np.count_nonzero(Data[:, 7])
    np.count_nonzero(Data[:, 8])
    
    for i in range(len(indexer)):
        
        if indexer[i, 0] > 0:
            value    = indexer[i, 0]
            profits  = np.append(profits, value)
            
        if indexer[i, 0] < 0:
            value    = indexer[i, 0]
            losses   = np.append(losses, value)
    
    # Hit ratio calculation
    hit_ratio = round((len(profits) / (len(profits) + len(losses))) * 100, 2)
    
    realized_risk_reward = round(abs(profits.mean() / losses.mean()), 2)
    
    # Expected and total profits / losses
    expected_profits = np.mean(profits)
    expected_losses  = np.abs(np.mean(losses))
    total_profits    = round(np.sum(profits), 3)
    total_losses     = round(np.abs(np.sum(losses)), 3)
    
    # Expectancy
    expectancy    = round((expected_profits * (hit_ratio / 100)) \
                   - (expected_losses * (1 - (hit_ratio / 100))), 2)
        
    # Largest Win and Largest Loss
    largest_win = round(max(profits), 2)
    largest_loss = round(min(losses), 2)    
    # Total Return
    indexer = Data[:, 10:12]    
    
    # Creating a combined array for long and short returns
    z = np.zeros((len(Data), 1), dtype = float)
    indexer = np.append(indexer, z, axis = 1)
    
    # Combining Returns
    for i in range(len(indexer)):
        try:    
          if indexer[i, 0] != 0:
             indexer[i, 2] = indexer[i, 0] - (expected_cost / lot)
                
          if indexer[i, 1] != 0:
             indexer[i, 2] = indexer[i, 1] - (expected_cost / lot)
        except IndexError:
            pass
        
    # Switching to monetary values
    indexer[:, 2] = indexer[:, 2] * lot
    
    # Creating a portfolio balance array
    indexer = np.append(indexer, z, axis = 1)
    indexer[:, 3] = investment 
    
    # Adding returns to the balance    
    for i in range(len(indexer)):
    
        indexer[i, 3] = indexer[i - 1, 3] + (indexer[i, 2])
    
    indexer = np.array(indexer)
    
    total_return = (indexer[-1, 3] / indexer[0, 3]) - 1
    total_return = total_return * 100
    
    
    print('-----------Performance-----------', name)
    print('Hit ratio       = ', hit_ratio, '%')
    print('Net profit      = ', '$', round(indexer[-1, 3] - indexer[0, 3], 2))
    print('Expectancy      = ', '$', expectancy, 'per trade')
    print('Profit factor   = ' , round(total_profits / total_losses, 2)) 
    print('Total Return    = ', round(total_return, 2), '%')
    print('')    
    print('Average Gain    = ', '$', round((expected_profits), 2), 'per trade')
    print('Average Loss    = ', '$', round((expected_losses * -1), 2), 'per trade')
    print('Largest Gain    = ', '$', largest_win)
    print('Largest Loss    = ', '$', largest_loss)    
    print('')
    print('Realized RR     = ', realized_risk_reward)
    print('Minimum         =', '$', round(min(indexer[:, 3]), 2))
    print('Maximum         =', '$', round(max(indexer[:, 3]), 2))
    print('Trades          =', len(profits) + len(losses))
# Using the function
performance(equity_curve, my_data, 'EURUSD)

Это должно дать нам что-то вроде следующего:

-----------Performance----------- EURUSD
Hit ratio       =  42.28 %
Net profit      =  $ 1209.4
Expectancy      =  $ 0.33 per trade
Profit factor   =  1.01
Total Return    =  120.94 %
Average Gain    =  $ 56.95 per trade
Average Loss    =  $ -41.14 per trade
Largest Gain    =  $ 347.5
Largest Loss    =  $ -311.6Realized RR     =  1.38
Minimum         = $ -1957.6
Maximum         = $ 4004.2
Trades          = 3697
# All of the above are simulated results and do not reflect the presented strategy or indicator

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

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

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

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