Средняя стратегия реверсии с использованием Python

Знакомство

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

Что такое возврат к среднему значению

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

Недостатки использования Mean Reversion

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

  1. Если акция выпадает по основной причине; Например, структурные изменения или если есть реальные новости, меняющие правила игры, шансы на то, что эти акции быстро отскочат и принесут вам прибыль, намного меньше.
  2. Импульс — враг этой стратегии.
  3. Сильные ценовые движения могут продолжаться очень долго, а разворот может не произойти в течение длительного периода
  4. Вместо того, чтобы цена развернулась и снова встретилась со скользящей средней, часто цена просто консолидируется после сильного движения, и движение догоняет цену

Разработка стратегии

Чтобы разработать нашу торговую стратегию, мы рассмотрим 200-дневную скользящую среднюю в качестве руководящего принципа. Если мы возьмем за основу акции Bharti Airtel (NSE: BHARTIARTL) и посмотрим на ее ценовое действие за последний 1 год, мы увидим, что всякий раз, когда цена акций отклоняется от своего долгосрочного среднего значения, рано или поздно она возвращается к долгосрочному среднему значению.

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

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

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

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

  1. 52-недельный минимум: самая низкая цена, по которой торговались акции за последние 52 недели.
  2. Максимум за 52 недели: самая высокая цена, по которой торговались акции за последние 52 недели.
  3. Diff: 52-недельный максимум — 52-недельный минимум
  4. Расстояние: Цена закрытия — значение 200 МА
  5. 200-дневная скользящая средняя: 200-дневная скользящая средняя (MA) — это просто средняя цена закрытия акции за последние 200 дней. Они используются в качестве трендовых индикаторов, отражающих динамику цены актива.

Наша система сгенерирует сигнал на покупку, когда будут выполнены все следующие условия:

  1. (52-недельный минимум + разница * 0,2) < цена акций < (52-недельный минимум + разница * 0,8)

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

2. Цена акций < 200 дней MA

Это дает акциям шанс скорректироваться и вернуться к своему среднему значению, которое выше их текущей цены.

3. Расстояние находится в верхнем 5 процентиле

Это гарантирует, что отклонение от среднего значения будет значительным, и ожидается, что цена акций значительно вырастет.

Принимая во внимание, что сигнал на продажу генерируется, если:

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

Кодирование стратегии

Источники данных

  • Мы получаем данные о вселенной NIFTY 50 (тикеры) с собственного веб-сайта nifty.

#NIFTY Вселенная 50nifty_50_ticker_url = ‘https://www1.nseindia.com/content/indices/ind_nifty50list.csv’
nifty_50 = pd.read_csv(nifty_50_ticker_url)

  • Теперь, когда у нас есть список тикеров, мы получаем исторические данные для тикеров из библиотеки Python под названием yfinance.

#Downloading historic data from yfinance
historic_price = yf.download((nifty_50.Symbol + ‘.NS’).to_list(), progress=True)[‘Adj Close’]

Подготовка данных

  • У нас есть исторические данные по 50 акциям из NIFTY 50, доступные у нас, с помощью которых мы рассчитаем скользящую среднюю всех акций.

#calculate 200 days moving average
moving_avg = historic_price.rolling(200).mean()

  • Теперь мы создаем словарь python для хранения обновленных наборов данных, чтобы мы могли легко получить к ним доступ.

#Creating a dictionary of data with Ticker as the Key and merged df as value
final_data = {}
for ticker in nifty_50.Symbol:
ticker = ticker + ‘.NS’
merged_df = pd.merge(historic_price[ticker], moving_avg[ticker], left_index=True, right_index=True)
merged_df.columns = [‘Adj Close’, ‘200MA’]
merged_df[‘distance’] = merged_df[‘Adj Close’] — merged_df[‘200MA’]#((merged_df[‘Adj Close’] — merged_df[‘200MA’])*100)/merged_df[‘200MA’]
data_dict = {
‘price_df’: merged_df,
’52w_data’ : price_df.loc[ticker.split(‘.’)[0]]
}
final_data[ticker] = data_dict

Основной алгоритм

Здесь мы кодируем основной алгоритм с помощью Python.

Этот фрагмент кода

  • Создает дополнительные столбцы во фрейме данных для хранения данных о покупках и продажах
  • Вычисляет max_price и min_price за последние 52 недели для каждого наблюдения.
  • Генерирует сигнал на покупку, когда все условия выполнены.
  • Генерирует сигнал на продажу при обнаружении стоп-лосса.
  • Генерирует сигнал на продажу при достижении максимального предела прибыли.

cum_pnl = 0
txns = []

#condition 1
#Adj Close value between 20-60%
for ticker in final_data:
df = final_data[ticker][‘price_df’]
df = df.iloc[-1250:,:]
df[’52w_max’] = np.nan
df[’52w_min’] = np.nan
df[‘diff’] = np.nan
df[‘top_5’] = np.nan

for i in range(len(df)):
# slice the dataframe to get the last 250 rows
sliced_df = df.iloc[max(0, i-250):i+1]
# calculate the maximum and minimum price in the sliced dataframe
max_price = sliced_df[‘Adj Close’].max()
min_price = sliced_df[‘Adj Close’].min()
diff = max_price — min_price
# do something with the maximum and minimum price
df.iloc[i,3] = max_price
df.iloc[i,4] = min_price
df.iloc[i,5] = diff
df.iloc[i,6] = df.iloc[i,2] < np.percentile(sliced_df.distance, 5)

state = ‘out’ # state can be ‘out’, ‘long’ or ‘short’
profit = 0
stop_loss = 0

for index, row in df.iterrows():
# check if the state is ‘out’ and the current price goes below 200MA
if state == ‘out’ and ((row[‘Adj Close’] > (row[’52w_min’] + 0.2* row[‘diff’])) & (row[‘Adj Close’] < (row[’52w_min’] + 0.6*row[‘diff’]))) & (row[‘200MA’] > row[‘Adj Close’]) & (row[‘top_5’]):
state = ‘long’
buy_price = row[‘Adj Close’]
stop_loss = buy_price * 0.9
print(‘Bought {} on {} at {}’.format(ticker, index, buy_price))

# check if the state is ‘long’ and the current price goes below stop loss
if state == ‘long’ and row[‘Adj Close’] < stop_loss:
state = ‘out’
sell_price = row[‘Adj Close’]
profit = sell_price — buy_price
cum_pnl += profit
txns.append([index, ticker, profit])
print(‘Sold {} on {} at {} for a profit of {}’.format(ticker, index, sell_price, profit))

# check if the state is ‘long’ and the profit is more than 20%
if state == ‘long’ and (row[‘Adj Close’] — buy_price) / buy_price > 0.2:
state = ‘out’
sell_price = row[‘Adj Close’]
profit = sell_price — buy_price
cum_pnl += profit
txns.append([index, ticker, profit])
print(‘Sold {} on {} at {} for a profit of {}’.format(ticker, index, sell_price, profit))
print(‘final profit/loss is rs: {}’.format(cum_pnl))

Тестирование на истории

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

Поскольку мы взяли все компании из нынешнего NIFTY 50 в нашем портфеле, мы не можем так глубоко обосновать наши данные, поэтому мы тестируем наши данные за последние 5 лет и берем их в качестве ориентира для сравнения с данными за последний 1 год.

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

Глядя на приведенную выше таблицу, мы видим, что самая прибыльная установка среди всех — это когда мы принимаем стоп-лосс равным 15%, а целевой показатель прибыли — 29%. Он принес доход в размере 18000 рупий. в промежутке времени 5 лет.

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

Ниже представлен график совокупных прибылей и убытков нашей самой успешной стратегии.

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

Заключение

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

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

Иточник