Про ушедший 2023 🎄

2023 год завершился весьма успешно для российского инвестора: индекс ММВБ прибавил 45% частично скомпенсировав падение 2022 года. Таким образом, за последние 8 лет (с 2016 года) индекс показал доходность ~6.9%. Мои личные счета также зафиксировали рост в этом году, а за прошедшие 8 лет уже набежало 14-15% среднегодовых. Естественно, свою доходность я рассчитываю с учетом дивидендов и купонных выплат тогда как индекс ММВБ учитывает такие денежные потоки опосредованно. В любом случае, позитив на рынке и у меня лично присутствует, а это придает мотивации делиться своими соображениями о закономерностях, происходящих на финансовых рынках, подкрепленных каркасом из объективных данных.

Наверное многие слышали, что рынок бывает бычьим и еще медвежьим то есть существуют чуть ли не две мистические силы, которые толкают рынок вниз или вверх. Признаюсь, с эзотерическими практиками мои взаимоотношения не очень складываются. Мне нравится думать, что всему можно найти некое логическое объяснение. В моей картине мира носителями настроений являются люди, часть которых настроены всегда позитивно, часть всегда негативно к экономике РФ или даже к мировой экономике. Одни рисуют радужное будущее с розовыми пони, катающихся на радуге, другие – наоборот рисуют мрачный ужас пришествия четырех всадников апокалипсиса. Между этими двумя крайностями находится менее фанатичный слой людей, которых в зависимости от момента увлекают то медвежьи, то бычьи настроения. Где-то в стороне от этого всего тусуются профессиональные инвесторы, которые цинично рубят бабло, пока рынок бросает из жара в холод и обратно.

Ранее я уже упоминал, что медведям живется несколько сложнее, чем быкам в силу органичного роста рынка за счет инфляции и неустанного роста ВВП. Это конечно не значит, что механизм роста ВВП не может сломаться. В конечном итоге, все рано или поздно ломается, но хочется верить, что человечество найдет выход из любого тупика и рынки будут чаще расти чем падать. В такой картине финансового мира возникает вопрос: когда собственно входить и выходить в рынок? Для простоты я буду говорить о входе в рынок акций в противовес активам фиксированной доходности (облигации, вклады и тому подобное). Естественно, никто не отменяет личные нормативы ликвидности, которые позволят в любой рыночной ситуации вытащить деньги с рынка без ощутимых потерь и множество других вопросов типа налогообложения, крупных покупок типа квартиры, игры с плечом и прочее бу бу бу …

Валовый внутренний продукт 🛍️

Итак, для того чтобы понять когда оптимально входить в рынок акций или выходить нужен какой-то интегральный показатель, способный дать оценку всей экономики в совокупности, например ВВП. Насколько такой показатель будет уместен для бенчмарка с индексом ММВБ? Как известно, ВВП включает в себя итоги деятельности всех организаций и компаний, в то же время, далеко не все организации – являются публичными и осуществляют эмиссию акций на ММВБ. Более того, не все компании котирующиеся на бирже ММВБ попадают в листинг индекса ММВБ. С другой стороны, экономика – это нечто, напоминающее огромную сеть экономических агентов и эластичных взаимосвязей. Проблемы в одном секторе в некоторой степени перекидываются в другой сектор и наоборот. Действительно, если какой-то условный ларек “ИП Хомяков” закроется, то это сократит потребление услуг банков и продуктов нефтяных компаний, которые были поставщиками услуг/товаров для этого ларька. Конечно, эффект будет не существенный, если речь про один единственный ларек, но если их десятки тысяч … Естественно, если на место “ИП Хомяков” придет “ИП Бурундуков” или сетевой магазин “Десяточка”, то принципиально картина не изменится. Таким образом, в качестве условного ориентира, думаю, можно использовать ВВП.

Конечно, не достаточно просто выбрать ВВП в качестве равновесного ориентира, нужно также немного поколдовать с данными. Самые подробные подробности можно будет найти в кладовой кода R в самом низу ⬇️ заметки. Основные идеи крупными мазкам:

  1. Аннотация к данным по ВВП гласит: Валовой внутренний продукт (в ценах 2021 г. с исключением сезонного фактора, млрд.руб.) 2011-2023гг.. Это означает, что не нужно возиться с сезонностью: за меня это уже сделал Росстат и также не нужно дисконтировать рост ВВП на инфляцию потому как Росстат привел показатель к ценам 2021 года. Ну и замечательно.
  2. В распоряжении имеются сведения о ВВП с дискретностью по кварталам, в то время как индекс ММВБ за приличный период можно найти с дискретностью по месяцам. Поэтому график индекса ММВБ представлен как ступенчатая кривая со значениями на конец последнего дня месяца, а показатель ВВП будет представлен как ступенчатая кривая со значениями на конец последнего дня квартала.
  3. Индекс ММВБ следует очистить от инфляции для чего будет использован соответствующий индекс потребительских цен. Может возникнуть вопрос: почему не использовался дефлятор ВВП или индекс промышленных цен? Дело в том, что индекс ММВБ интересует меня как розничного инвестора и мне интересно следить за ростом собственного капитала, дисконтированного на размер моей т.е. потребительской инфляции.
  4. Сведения о ВВП публикуются с некоторым запозданием, например, на момент написания этой заметки (январь 2024) опубликованы данные только за 3-ий квартал 2023, что несколько удручает так как хочется знать насколько рынок относительно ВВП перекуплен или перепродан именно сейчас и на некоторый ощутимый горизонт будущего. Для того чтобы нивелировать этот момент можно использовать прогноз роста ВВП. Я решил взять прогноз ВВП от ЦБ РФ, который обычно является весьма консервативным.
  5. Наконец, для того чтобы индекс ММВБ наложить на показатель ВВП в едином масштабе необходимо найти некоторое равновесие, которое проще всего получить через простую линейную регрессию.

Выводы 🍪

В итоге получился симпатичный индекс ЭЙФОРИИ/ОТЧАЯНИЯ и вот, что можно с помощью этого индекса подметить:

  1. Рынок почти всегда предвкушает рост или падение ВВП, что не удивительно т.к. экономика – это весьма инерционный механизм. В то же время рынок почти всегда из стадии ЭЙФОРИИ сваливается в фазу ОТЧАЯНИЯ и наоборот. Этому есть вполне логичное объяснение: при наступления кризисных признаков компании прежде всего снижают дивидендные выплаты, что существенно бьет по настроениям инвесторов. Наоборот, при перспективах выхода из кризиса компании начинают резко увеличивать дивидендные выплаты.
  2. Очевидно, что лучше всего покупать акции на пике ОТЧАЯНИЯ и продавать на пике ЭЙФОРИИ, но точно такой момент определить достаточно сложно. Кроме того, нет никаких гарантий, что один цикл сменит другой. Например, период с 2013 года по 2019 год ознаменовался затяжной депрессией, хотя в экономике дела шли не так уж и плохо.
  3. В 2024 рынок может вырасти еще на 15%+ с текущих ~3100 пунктов к равновесному уровню ~3500-3600 и это будет неплохой точкой для фиксации прибыли и частичного выхода из рынка акций.

Исходный код заметки
# Необходимые библиотеки
library(rusquant)
library(tidyverse)
library(patchwork)

# Индекс потребительский цен (наиболее свежие только в виде Excel файла)
# https://rosstat.gov.ru/storage/mediabank/ipc_kv3_2005-2023.xlsx
PI <- c("109,50", "109,54", "108,11", "106,68", NA, "103,86", "103,82", "106,03", "106,53", NA, "107,12", "107,16", "106,35", "106,39", NA, "106,40", "107,58", "107,68", "109,58", NA, "116,20", "115,82", "115,69", "114,48", NA, "108,35", "107,35", "106,83", "105,75", NA, "104,63", "104,19", "103,37", "102,57", NA, "102,24", "102,37", "102,98", "103,87", NA, "105,16", "104,99", "104,29", "103,44", NA, "102,42", "103,11", "103,54", "104,44", NA, "105,55", "106,02", "106,85", "108,31", NA, "111,54", "116,94", "114,36", "112,18", NA, "108,62", "102,69", "105,15")

# Данные по ВВП (наиболее свежие только в виде Excel файла)
# https://rosstat.gov.ru/storage/mediabank/VVP_kvartal_s_1995.xlsx
GDP <- c("29 045,8", "29 287,4", "29 600,4", "29 865,0", "30 327,8", "30 394,4", "30 675,9", "30 671,9", "30 890,6", "30 997,8", "31 002,1", "31 227,4", "31 126,8", "31 339,6", "31 137,8", "31 152,0", "30 874,9", "30 738,0", "30 734,9", "30 655,0", "30 706,8", "30 744,7", "30 779,0", "30 992,6", "31 081,3", "31 245,7", "31 506,7", "31 511,1", "31 920,1", "32 011,5", "32 221,5", "32 360,5", "32 580,1", "32 678,4", "33 005,2", "32 909,8", "32 836,5", "30 377,5", "32 574,8", "32 841,0", "33 079,4", "33 604,7", "33 777,4", "34 116,4", "34 161,5", "32 594,2", "32 827,0", "33 210,2", "33 582,0", "33 895,1", "34 197,2")

# Пакет rusquant позволяет удобно забрать индекс ММВБ с сайта Finam с месячной дискретностью
IMOEX <-  getSymbols("IMOEX", from="2011-01-01", src = "Finam", period = "month", auto.assign = F)

# Подготовка индекса потребительской инфляции
PI1 <- na.omit(PI) |> 
  str_replace(",", ".") |>
  as.numeric() |> 
  tibble(PI=_) |>
  mutate(yearqtr = as.yearqtr(2011.25 + seq(0, 50)/4), qtr = quarter(yearqtr)) |> # создания индекса для дат 
  group_by(qtr) |> # Индекс дан год к году -> нужно перевести в индекс, накопленным итогом
  mutate(PI_cs = cumprod(PI/1e2)) # 1. получение накопленного итога 2. перевод из процентов в десятичный вид

# Подготовка индекса ММВБ инфляции
IMOEX1 <- na.locf(IMOEX) |>
  period.apply(INDEX = endpoints(IMOEX, "months"), last) |> # в каждом месяце остается последнее наблюдение
  as_tibble(rownames = "IMOEX") |>
  select(date = IMOEX, IMOEX = IMOEX.Close) |>
  mutate(date = as.Date(date))

# Подготовка данных ВВП
GDP1 <- str_replace(GDP, ",", ".") |> str_remove(" ") |>
  as.numeric() |> 
  tibble(GDP=_) |>
  mutate(yearqtr = as.yearqtr(2011 + seq(0, 50)/4)) # создания индекса для дат 

# Прогноз ВВП ЦБ 
# 2023 - 3.1%, 2024 - 1.3%
# https://cbr.ru/statistics/ddkp/mo_br/
pred <- tibble(date = as.yearqtr(2023.75 + seq(0, 5)/4)|> as.Date() - 1, 
               GDP_pred = slice_tail(GDP1, n=1)[["GDP"]]*c(1, 1.00775, 1.00775+0.00325*1:4))

# Объединение данных 
all <- left_join(GDP1, PI1, by = "yearqtr") |> # данные ВВП стыкуются с инфляцией по ключам год-квартал
  mutate(date = as.Date(yearqtr + .25) - 1) |> # квартальные даты - последний день квартала 
  full_join(IMOEX1, by = "date") |> # объединение по датам (все в кучу, но так и задумано)
  arrange(desc(date)) |> 
  mutate(across(c(GDP, IMOEX, PI_cs), ~accumulate(., \(out, input)if(is.na(input))out else input)), # заполнение пропусков 
         IMOEX = IMOEX/PI_cs) # дисконтирование индекса ММВБ на инфляцию

# Модель линейной регрессии 
fit <- lm(IMOEX ~ GDP, all)
# summary(fit) # коэффициент детерминации не велик, но значимость модели подтверждается
# plot(fit) # модель не идеальна: наблюдается гетероскедастичность
mdl <- coef(fit)

# График динамики показателей ВВП и индекса ММВБ
p1 <- mutate(all, GDP_mdl = GDP*mdl[2]+mdl[1],
             signal = GDP_mdl - IMOEX) |>
  ggplot(aes(x = date)) +
  geom_step(aes(y = GDP_mdl, col = "ВВП"), direction = "vh") + 
  geom_step(aes(y = IMOEX, col="ММВБ")) +
  geom_step(data = pred, aes(y = GDP_pred*mdl[2]+mdl[1], col="Прогноз ВВП"), linewidth = .3) +
  geom_point(data = pred, aes(y= GDP_pred*mdl[2]+mdl[1]), col=my_pal[6], size = .5) + 
  scale_y_continuous(sec.axis = sec_axis(name = "ВВП, трлн. ₽", ~(.-mdl[1])/mdl[2]/1e3)) + 
  scale_x_date(date_breaks = "1 year", date_labels = "%Y") +
  scale_color_manual(values = c("ВВП"=my_pal[2], "ММВБ"=my_pal[1], "Прогноз ВВП" = my_pal[6])) +
  labs(fill ="", col="", y = "Индекс ММВБ", x = "", caption = "Индекс ММВБ дисконтирован на инфляцию") +
  theme(legend.position = "top")

# График индекса эйфории и отчаяния 
p2 <- mutate(all, GDP_mdl = GDP*mdl[2]+mdl[1],
             signal = GDP_mdl - IMOEX) |>
  ggplot(aes(x = date)) +
  geom_col(aes(y = signal, col = if_else(signal < 0, "ЭЙФОРИЯ", "ОТЧАЯНИЕ"), 
               fill = if_else(signal < 0, "ЭЙФОРИЯ", "ОТЧАЯНИЕ"))) +
  annotate(x = as.Date("2020-01-01"), y = 200, geom = "text", label = "ЭЙФОРИЯ", col = my_pal[3], hjust=0) +
  annotate(x = as.Date("2022-03-01"), y = -200, geom = "text", label = "ОТЧАЯНИЕ", col = my_pal[5], hjust=0) +
  scale_color_manual(values = c("ЭЙФОРИЯ"=my_pal[3], "ОТЧАЯНИЕ"=my_pal[5])) +
  scale_x_date(date_breaks = "1 year", date_labels = "%Y", limits = c(as.Date("2011-01-01"), as.Date("2025-01-01"))) +
  scale_fill_manual(values = c("ЭЙФОРИЯ"=my_pal[3], "ОТЧАЯНИЕ"=my_pal[5])) + 
  labs(fill ="", col="", y = "Индекс ЭЙФОРИИ", x = "") +
  theme(legend.position = "top")

# Потребительская инфляция
p3 <- ggplot(all, aes(date, PI_cs)) + 
  geom_step(col = my_pal[1]) + 
  scale_y_continuous(limits=c(1, 2.5), labels = scales::label_percent()) + 
  scale_x_date(date_breaks = "1 year", date_labels = "%Y", limits = c(as.Date("2011-01-01"), as.Date("2025-01-01"))) +
  labs(y = "Индекс цен", x = "Квартал") 

# Итоговый график - все вместе
p1/p2/p3 + plot_layout(heights = c(4,1,1)) 

Простой способ узнать о новых публикациях – подписаться на Telegram-канал: