Проанализируем динамику акций аутсайдеров и лидеров
Недавно прочитал статью о том, что акции-аутсайдеры (те, что максимально упали в цене за месяц) индекса Мосбиржи имеют бОльшие перспективы роста, нежели в среднем по индексу.
В данном исследовании рассмотрю
- динамику акций аутсайдеров и лидеров роста (период 30 дней)
- Имеет ли смысл покупать на просадках и играть на понижение после значительного роста
Важно! Я буду рассматривать абсолютно каждый день по всем акциям, соответственно многие просадки будут дивидендными гэпами (идея — рассмотреть все отклонения).
Буду рассматривать акции индекса Мосбиржы (только акции с долей в индексе >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)
- Выводим название акции
- Читаем ее из файла
- Сортируем по дате
- Добавляем столбец с 30 дневным ростом акции в процентах
- Добавляем столбец с изменением стоимости в процентах за следующие 30 дней
- Добавляем столбец с тикетом. Это позволит объединять Датафреймы по столбцу с датой
Просмотр статистики по отдельным акциям
Сейчас посмотрим на отдельные акции. Важно смотреть на акции отдельно так как волатильность может совершенно иначе вести себя в разных случаях (например, просадки по Детскому Миру и Норникелю выкупают быстро, а нефтянку в сложные времена могут вообще игнорировать)
На скринах смотрите именно на столбцы 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%. Получается что так мы не сможем получить выгоду, но тут видно, что потенциал в этом случае меньше. Но это и не удивительно.
Цифры, конечно, интересные, но стоит учесть, что это в большей степени бенчмарк, так как эту доходность мы получим в случае покупки всех просадок каждый день, пока они находятся в необходимом диапазоне.
Требуется убрать строки, с близкими датами, чтобы не было дублирования одной и той же просадки, но это уже другая история.
Также следует учитывать причины всех отклонений. Очевидно, что, если Газпром вводит новую дивполитику, ждать падений в ближайшее время не стоит.
empenoso
А почему такой маленький рассматриваемый период?
Lubiviy_Alexander Автор
Хотел рассмотреть именно растущий тренд без всяких отклонений типа обвала рубля и коронавируса.
Я предполагаю, что подобный анализ в рамках, например, обвала рубля покажет другие цифры, в результате чего статистика не будет столь показательна
Yager
Среднюю вы так считать конечно можете… но «доходность» из этого не получится, по 10 дней подряд будете покупать? Очевидно следует выкидывать период от срабатывания условия до окончания периода.