Перспективны ли просевшие акции? Проанализируем с помощью python

Проанализируем динамику акций аутсайдеров и лидеров

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

В данном исследовании рассмотрю

  1. динамику акций аутсайдеров и лидеров роста (период 30 дней)
  2. Имеет ли смысл покупать на просадках и играть на понижение после значительного роста

Важно! Я буду рассматривать абсолютно каждый день по всем акциям, соответственно многие просадки будут дивидендными гэпами (идея — рассмотреть все отклонения).

Буду рассматривать акции индекса Мосбиржы (только акции с долей в индексе >0,5%), а именно:

  • Газпром
  • Лукойл
  • Сбербанк
  • ГМК Норильский никель
  • НОВАТЭК
  • Магнит
  • Роснефть
  • Татнефть
  • МТС
  • ВТБ
  • Сургутнефтегаз
  • АЛРОСА
  • Сургутнефтегаз п
  • Московская Биржа
  • НЛМК
  • Северсталь
  • ЯНДЕКС
  • Polymetal International
  • Сбербанк России П
  • ИНТЕР РАО
  • РУСАЛ
  • Полюс
  • Транснефть п
  • РусГидро
  • ФосАгро
  • ММК
  • Аэрофлот
  • МегаФон
  • Татнефть п
  • Ростелеком

Период — 2018-2019 года.

Получение котировок акций

Для начала необходимо получить котировки акций за последние два года. Я скачал их с сайта Финам и просто импортировал csv.

Начнем собирать котировки внутри нашего файла

Импортируем Пандас:

import pandas as pd

Уберем ограничения на отображения в окне (мне необходимо это делать в PyCharm):


pd.set_option('display.max_columns', None)
pd.set_option('display.expand_frame_repr', False)
pd.set_option('max_colwidth', 80)
pd.set_option('max_rows', 60000)

Нужно подобным образом импортировать каждую акцию:


print('GAZP')
GAZP = pd.read_csv("GAZP_180101_191231.csv",sep=';', header=0, index_col='<DATE>', parse_dates=True)
GAZP = GAZP.sort_values(by='<DATE>')
# Добавление столбца изменения с использованием шифтинга
GAZP['30_days_growth']=((GAZP['<CLOSE>']/GAZP['<CLOSE>'].shift(30))-1)*100
GAZP['after_30_days_growth']=((GAZP['<CLOSE>'].shift(-30)/GAZP['<CLOSE>'])-1)*100
GAZP['ticket']='GAZP'
print(GAZP)

  1. Выводим название акции
  2. Читаем ее из файла
  3. Сортируем по дате
  4. Добавляем столбец с 30 дневным ростом акции в процентах
  5. Добавляем столбец с изменением стоимости в процентах за следующие 30 дней
  6. Добавляем столбец с тикетом. Это позволит объединять Датафреймы по столбцу с датой

Просмотр статистики по отдельным акциям

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

На скринах смотрите именно на столбцы 30_days_growth (изменение в процентах за последние 30 дней) и after_30_days_growth (сколько акция будет стоить спустя 30 дней)

На примере Газпрома посмотрим что произойдет с акциями после 30-дневного снижения больше 10%.

Выведем Газпром с сортировкой по 30-дневным изменениям


print(GAZP.sort_values(by='30_days_growth'))

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

А вот с другого конца все не так очевидно, так как новая дивидендная политика все “поломала”.

Откинем 2019 год, чтобы сделать выводы. Для этого выведу только первые 255 строк:


print(GAZP[:254].sort_values(by='30_days_growth'))

Получается, что при росте больше 10% есть смысл продавать

Посмотрим на Лукойл

Тут все уже не так очевидно:

Посмотрим финансовую сферу

Сбербанк

Сильные просадки как правило выкупаются. Но тут волатильность ого-го

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

Почти любая просадка Норникеля в последние два года — хорошая инвестиция 🙂

Вычисление средней доходности за 30 дней

Посмотрим какую в среднем доходность получим за месяц, если войдем в просадку ниже -5%

Создадим переменную с этими строками:


GMKN5 = GMKN[GMKN['30_days_growth']<-5]
print(GMKN5)

Выведем среднее:


print( GMKN5['after_30_days_growth'].mean())

Получим доходность за 30 дней 6.935553432942371%

Также посмотрим как прирастает стоимость за 14 дней

Добавим столбец:


GMKN['after_14_days_growth']=((GMKN['<CLOSE>'].shift(-14)/GMKN['<CLOSE>'])-1)*100

Посмотрим средний прирост за 14 дней:


print(GMKN5['after_14_days_growth'].mean())

Это 4.125%

Вычисление доходности всех акций с просадкой больше 15%

Теперь рассчитаем среднюю доходность за 30 дней по всех акциям, где просадка больше 15%

Нужно объединить все в один Датафрейм.

Для этого создадим лист со всеми акциями:


all_tickets = [GAZP,LKOH,SBER,SBERP,NVTK,MOEX,MGNT,MFON,MTSS,MAGN,GMKN,AFLT,POLY,ROSN,HYDR,RTKM,RUAL,YNDX,ALRS,VTBR,TATN,TATNP,SNGS,SNGSP,PLZL,NLMK,CHMF,IRAO,TRNFP,PHOR]

Объединим:


all_stocks = pd.concat(all_tickets)

Создадим Датафрейм в котором будут только строки с просадками больше 15%:


tickets15 = all_stocks[all_stocks['30_days_growth']<-15]
print(tickets15)

Посчитаем среднюю доходность:


print(tickets15['after_30_days_growth'].mean())

Получим 7.78570670526497%

Довольно неплохо учитывая такой уровень диверсификации.

Аналогично посчитаем доходность 10% просадок


tickets10 = all_stocks[all_stocks['30_days_growth']<-10]
print(tickets10)
print(tickets10['after_30_days_growth'].mean())

Получим 3,1%

А стоит ли играть на понижение акций, которые выросли за 30 дней на 15%+


tickets15plus = all_stocks[all_stocks['30_days_growth']>15]
print(tickets15plus)
print(tickets15plus['after_30_days_growth'].mean())

Получим рост в 2%. Получается что так мы не сможем получить выгоду, но тут видно, что потенциал в этом случае меньше. Но это и не удивительно.

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

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

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

Специально для сайта ITWORLD.UZ. Новость взята с сайта Хабр