Практические аспекты ранней пенсии FIRE movement в России

от автора

Ранний выход на пенсию является горячей темой в последнее время. Отчасти это связано с движением FIRE: «финансовая независимость и ранняя пенсия» — зарабатывать больше, тратить меньше и рано сбросить оковы работы.

Казалось бы причем здесь FIRE и habr.com? А при том, что невозможно добиться этой ранней пенсии НЕ имея и НЕ учитывая собственных диверсифицированных активов. А как показала многолетняя практика адекватных инструментов для учета акций, облигаций, недвижимости, монет и валют вкупе со страновой диверсификацией в одном окне практически нет. В небольшой предыстории рассказывал, что если у Вас есть, что учитывать, то сам учёт может занимать неоправданно много времени. Но тут на помощь приходит парсинг сайтов и это выводит управленческий учет собственного портфеля на новый уровень и, конечно же, приближает раннюю пенсию.

Важное замечание: эта статья для начинающего раннего пенсионера и новичка-парсера :). Мой опыт подразумевает использование данных с сайтов только для личных целей. Коснусь использования Microsoft Excel и Google Таблиц и совсем чуть-чуть KMyMoney. Начну в том порядке, в котором я сам столкнулся со всеми продуктами:

Часть 1. KMyMoney

Добавление нового актива в KMyMoney
Добавление нового актива в KMyMoney

Об этой программе незаслуженно мало информации на просторах интернета и особенно мало про её компонент парсинга цен. А ведь в инвестициях очень важно иметь актуальную картину перед глазами.

Настройка парсера в KMyMoney
Настройка парсера в KMyMoney

Также любопытно, что из версии в версию KMyMoney (я пользовался программой несколько лет) в настройках парсера кочуют какие-то неработающие ссылки, которыми практически невозможно воспользоваться и нет какого-то внятного описания компонента.

Указание использовать шаблон парсинга для конкретной бумаги
Указание использовать шаблон парсинга для конкретной бумаги

Предлагаю для примера какую-нибудь облигацию федерального займа (ОФЗ) — это рублёвые облигации, выпускаемые Министерством финансов Российской Федерации. Данные по этим облигациям можно посмотреть на множестве сайтов или через API Московской Биржи. Возьму ОФЗ-ПК 29012 (SU29012RMFS0), а цену буду смотреть на сайте одного из брокеров. Идентификатором станет не код ценной бумаги с биржи, а внутренний идентификатор с сайта. Так выглядит окно с уже скаченной котировкой предыдущего дня:

Результат работы парсера для бумаги
Результат работы парсера для бумаги

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

Конечно, KMyMoney позволяет иметь автоматические обновление курсов любых активов и это наверное единственная программа которая позволяет это делать, но как и у всех подобных учетных программ у неё есть определенные недостатки. А именно: раздражающий “бухгалтерский поиск” не сходящихся копеек (мне нужен обзорный инструмент) и огромное количество кликанья мышкой (в два клика ничего не сделать с инвестицией). Но эта программа наверное лучшее, если Вы хотите иметь учет личных финансов и инвестиций в одном окне и при этом иметь автоматические обновление курсов любых активов.

Часть 2. Microsoft Excel

Встроенных функций для парсинга в Excel нет и поэтому пользовался VBA, на основе найденных в интернете примеров (сам не особо разбирался в то время, чтобы написать с нуля) — код вероятно не самый лаконичный, но свои функции выполнял:

Редактор кода в Microsoft Excel
Редактор кода в Microsoft Excel

VBA код для парсинга цен облигаций федерального займа.

Public Function FinamPriceBondsCorporate(Optional ByVal ISIN) As Double     '//объявляем переменные     Dim sURI As String     Dim oHttp As Object     Dim htmlcode, outstr As String     Dim Num As Double      '//обращаемся к сайту     sURI = "https://bonds.finam.ru/issue/" & ISIN & "/default.asp?resultsType=5"     On Error Resume Next     Set oHttp = CreateObject("MSXML2.XMLHTTP")     If Err.Number <> 0 Then         Set oHttp = CreateObject("MSXML.XMLHTTPRequest")     End If     On Error GoTo 0     If oHttp Is Nothing Then         Exit Function     End If     oHttp.Open "GET", sURI, False     oHttp.Send     htmlcode = oHttp.responseText      '//попробовать regex!     outstr = Mid(htmlcode, InStr(1, htmlcode, "Сlose:</td>") + 57, 6) '//ищем значение в тексте     Set oHttp = Nothing      '//удаляем куски html разметки, если нужно     outstr = Replace(outstr, "&", "")     outstr = Replace(outstr, "n", "")     outstr = Replace(outstr, "b", "")     outstr = Replace(outstr, "s", "")     outstr = Replace(outstr, "p", "")     outstr = Replace(outstr, ";", "")     outstr = Replace(outstr, "-", "0")     Num = CDbl(outstr) '//число в текст      If Num = 0 Then  '//если нет цены закрытия берем другую     outstr = Mid(htmlcode, InStr(1, htmlcode, "Bid:</td>") + 54, 6) '//ищем значение в тексте     outstr = Replace(outstr, "&", "")     outstr = Replace(outstr, "n", "")     outstr = Replace(outstr, "b", "")     outstr = Replace(outstr, "s", "")     outstr = Replace(outstr, "p", "")     outstr = Replace(outstr, ";", "")     outstr = Replace(outstr, "-", "0")     Num = CDbl(outstr) '//число в текст     End If      FinamPriceBondsCorporate = Num      Exit Function ErrorHandler: 'Обработчик ошибок     FinamPriceBondsCorporate = 0     Err.Clear End Function

Для того, чтобы воспользоваться кодом, в самом Excel надо вызвать эту, только что написанную функцию FinamPriceBondsCorporate:

Excel и использование дополнительной функции парсинга
Excel и использование дополнительной функции парсинга

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

Часть 3. Google Таблицы

Котировки через IMPORTXML

Google Таблицы как оказалось представляют гораздо более широкий диапазон возможностей для парсинга. И первое с чем столкнулся — это была функция IMPORTXML, которая позволяла взять почти любую строку из веб-страницы. А для использования надо только было научиться писать xpath запрос. С ее помощью можно собирать нужные котировки и другую информацию без скриптов и интеграции с API.


Мой шаблон отчетной таблицы, которому дал название SilverFir: Investment Report

Примерно за полгода изысканий в 2018 году родилась окончательная версия моего шаблона, который стал отправной точкой для взрослого учёта диверсифицированных активов “в одном окне”.

Распределение активов в отчетной таблице SilverFir: Investment Report
Распределение активов в отчетной таблице SilverFir: Investment Report

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

Котировки через Google Apps Script

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

Google Apps Script приходит на помощь в FIRE movement
Google Apps Script приходит на помощь в FIRE movement

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

На гугл скриптах парсинг, на мой взгляд, выглядит лаконичнее, чем на VBA.

Google Apps Script для парсинга имени и котировки Pitney-Bowes-Anleihe (3,875% до 01.10.2021) с ISIN US724479AK60 и подобных.

function GetFinanzenNet(ISIN, id) {     var url = 'https://www.finanzen.net/suchergebnis.asp?_search=' + ISIN;     try {         var html = UrlFetchApp.fetch(url).getContentText();     } catch (error) {         Logger.log("GetFinanzenNet. Symbol = " + ISIN + ".\nОшибка чтения данных. URL: " + url + ". HTML:\n" + html);         return ""     }     if (id == "Price") { //цена акции - Quote/Price         var searchstring = 'text-sm-right text-nowrap">';         var index = html.search(searchstring);         if (index >= 0) {             var pos = index + searchstring.length             var rate = html.substring(pos, pos + 50);             rate = rate.split('<')[0];             rate = rate.replace(/\,/g, ".");             rate = rate.replace(/\%/g, "");             rate = +rate;             Logger.log("GetFinanzenNet. ID = " + id + ".\nPrice = " + rate + ". URL: " + url);             return rate         }     }     if (id == "Name") { //имя         var searchstring5 = '<title>';         var index5 = html.search(searchstring5);         if (index5 >= 0) {             var pos5 = index5 + searchstring5.length             var rate5 = html.substring(pos5, pos5 + 100);             try {                 rate5 = rate5.split(' | ')[1];                 rate5 = rate5.split(' | ')[0];                 var res = rate5.substring(0, 1); //первый символ                 if (res == "(") {                     rate5 = html.substring(pos5, pos5 + 100);                     rate5 = rate5.split(' | ')[0];                     rate5 = rate5.substring(0, 18);                 }             } catch (error) {                 return "";             }             Logger.log("GetFinanzenNet. Найден Name для Symbol " + ISIN + ".\nName = " + rate5 + ". URL: " + url);             return rate5         }     }     Logger.log("GetFinanzenNet. Symbol = " + ISIN + ".\nОшибка чтения данных. URL: " + url);     return "" }

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

Экосистема Google

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

Вот примеры функций, которые можно было реализовать на скриптах.

  • еженедельные отчёты на почту;


Пример фрагмента отчета на почте

  • события с выплатами в календаре;


Пример тестового события в Google Календарь

  • задачи посмотреть, что не так с теми или иными бумагами;


Пример Google Задач

  • ежемесячная презентация с итогами месяца;


Пример Google Презентации с изменениями на скриптах

  • Asset Allocation на основе данных с множества сайтов;


Промежуточные шаги для расчета диверсификации: типы и страны

  • дополнительные диаграммы и графики, которых нет в Таблицах;


Пример сгенерированного Word Trees Charts — очень наглядно раскидать собственный портфель (на скриншоте НЕ он) по валютам и классам активов.

  • напоминания об офертах и выплатах в телеграм;


Бот с напоминаниями

  • импорт данных от брокеров (у Российских брокеров как-то мне показалось сложно с этим, поскольку у каждого брокера свое видение отчёта, причем в большинстве случаев для инвестора недружественное).

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

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

Итог

Еще раз возвращаясь к практическим аспектам ранней пенсии FIRE movement в России — учёт имеет к ранней пенсии самое прямое отношение и именно грамотно поставленный учет позволяет держать руку на пульсе, в то же самое время не скатываясь до частого просмотра котировок и текущих цен.

Автор: Михаил Шардин,
25 ноября 2019 г.

Опрос №1. Прямо сейчас у Вас есть инвестиции?

  1. Да
  2. Нет

Опрос №2. Как Вы думаете, какой из вариантов выглядит оптимальным для многолетнего использования и учета всех инвестиций в одном окне?

  1. Онлайн-сервис *1
  2. Локальная программа
  3. Программа табличных данных

*1: Нашёл множество отличных сервисов, но все они локальные для конкретных рынков и ни в одном нельзя добавить что-то своё (в первую очередь страдает недвижимость).


ссылка на оригинал статьи https://habr.com/ru/post/477920/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *