Пошаговое создание и оценка простой стратегии кроссовера на Python.

Пересечение скользящих средних - это один из простейших методов торговли, и, хотя у них есть свои недостатки, они выдержали испытание временем в отношении использования. В этой статье представлена ​​стратегия исследования пересечения скользящих средних от А до Я в Python.

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



Получение исторических данных OHLC

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

Первое, что нам нужно сделать, это просто скачать платформу с официального сайта. Затем, после создания демо-счета, мы готовы импортировать библиотеку на Python, которая позволяет импортировать данные OHLC из MetaTrader5.

Библиотека - это группа структурированных функций, которые можно импортировать в наш интерпретатор Python, откуда мы можем вызывать и использовать те, которые нам нужны.

Самый простой способ установить библиотеку MetaTrader5 - это перейти в командную строку Python на нашем компьютере и ввести:

pip install MetaTrader5

Это должно установить библиотеку в нашем локальном Python. Теперь мы хотим импортировать его в интерпретатор Python (например, Pycharm или SPYDER), чтобы мы могли его использовать. Давайте фактически импортируем все библиотеки, которые мы будем использовать для этого:

import datetime                 # Date acquiring
import pytz                     # Time zone management
import pandas            as pd  # Mostly for Data frame manipulation
import MetaTrader5       as mt5 # Importing OHLC data
import matplotlib.pyplot as plt # Plotting charts
import numpy             as np  # Mostly for array manipulation

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

Официальную документацию по библиотеке Metatrader5 можно найти здесь.

Первое, что мы можем сделать, это выбрать временные рамки, которые мы хотим импортировать. Предположим, что есть только два таймфрейма, 30-минутный и часовой бары. Таким образом, мы можем создавать переменные, которые содержат оператор, чтобы сообщить библиотеке MetaTrader5, какой временной интервал нам нужен.

# Choosing the 30-minute time frame
frame_M30  = mt5.TIMEFRAME_M30
# Choosing the hourly time frame
frame_H1   = mt5.TIMEFRAME_H1

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

# Defining the variable now to give out the current date
now = datetime.datetime.now()

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

def asset_list(asset_set):
    
    if asset_set == 'FX':        
      assets = ['EURUSD', 'USDCHF']        
    return assets

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

def get_quotes(time_frame, year = 2005, month = 1, day = 1, asset = "EURUSD"):
        
    # Establish connection to MetaTrader 5 
    if not mt5.initialize():
        print("initialize() failed, error code =", mt5.last_error())
        quit()
    
    timezone = pytz.timezone("Europe/Paris")
    
    utc_from = datetime.datetime(year, month, day, tzinfo = timezone)
    utc_to = datetime.datetime(now.year, now.month, now.day + 1, tzinfo = timezone)
    
    rates = mt5.copy_rates_range(asset, time_frame, utc_from, utc_to)
    
    rates_frame = pd.DataFrame(rates)    
    return rates_frame

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

def mass_import(asset, horizon):
        
 if horizon == 'M30':
   data = get_quotes(frame_M30, 2019, 1, 1, asset = assets[asset])
   data = data.iloc[:, 1:5].values
   data = data.round(decimals = 5) return data

Наконец, мы закончили сборку блоков, необходимых для импорта данных. Чтобы импортировать исторические данные EURUSD OHLC, мы просто используем следующую строку кода:

# Choosing the horizon
horizon = 'M30'
# Creating an array called EURUSD having M30 data since 2019
EURUSD = mass_import(0, horizon)

И вуаля, теперь у нас есть данные OHLC по EURUSD за 2019 год.

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

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

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

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

def adder(Data, times):
    
    for i in range(1, times + 1):
    
        new = np.zeros((len(Data), 1), dtype = float)
        Data = np.append(Data, new, axis = 1)    
    return Data
def deleter(Data, index, times):
    
    for i in range(1, times + 1):
    
        Data = np.delete(Data, index, axis = 1)    
    return Data
   
def jump(Data, jump):
    
    Data = Data[jump:, ]
    
    return Data
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
    
    return Data

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

my_data = ma(my_data, 200, 3, 4)

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

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

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

Чтобы создать это, мы можем следовать синтаксису ниже.

short_ma = 60
long_ma = 200
my_data = adder(my_data, 10)
my_data = ma(my_data, short_ma, 3, 4)
my_data = ma(my_data, long_ma, 3, 5)

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

def signal(Data, short_ma_col, long_ma_col, buy, sell):
    
    for i in range(len(Data)):    
        
       # Bullish Crossover
       if Data[i, short_ma_col]   > Data[i, long_ma_col] and Data[i - 1, short_ma_col] < Data[i - 1, long_ma_col]:
           
                Data[i, buy] = 1 
   
       # Bearish  Crossover
       elif Data[i, short_ma_col] < Data[i, long_ma_col] and Data[i - 1, short_ma_col] > Data[i - 1, long_ma_col]:
              
                Data[i, sell] = -1 
              
    return Data
my_data = signal(my_data, 4, 5, 6, 7)

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



Оценка стратегии

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

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

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

# Choosing a Holding Period for a trend-following strategy
period = 20
def signal_quality(Data, closing, buy, sell, period, where):
    
    Data = adder(Data, 1)
    
    for i in range(len(Data)):
        
        try:   
            
            if Data[i, buy] == 1:
                
                Data[i + period, where] = Data[i + period, closing] - Data[i, closing]
            
            if Data[i, sell] == -1:
                
                Data[i + period, where] = Data[i, closing] - Data[i + period, closing]
                
        except IndexError:
            
             pass
         
    return Data
# Applying the Signal Quality Function
my_data = signal_quality(my_data, 3, 6, 7, period, 8)
positives = my_data[my_data[:, 8] > 0]
negatives = my_data[my_data[:, 8] < 0]
# Calculating Signal Quality
signal_quality = len(positives) / (len(negatives) + len(positives))
print('Signal Quality = ', round(signal_quality * 100, 2), '%')
# Output Signal Quality EURUSD = 56.90% 
# Output Signal Quality USDCHF = 58.06%
# Output Signal Quality GBPUSD = 54.69%

Поскольку это стратегия следования за трендом, более длительные периоды владения должны соответствовать более высокому качеству. Качество сигнала 56,90% означает, что на 100 сделках мы склонны видеть прибыльный результат в 57 случаях без учета транзакционных издержек.

Вывод

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

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

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