Ранний выход на пенсию является горячей темой в последнее время. Отчасти это связано с движением FIRE: «финансовая независимость и ранняя пенсия» — зарабатывать больше, тратить меньше и рано сбросить оковы работы.
Казалось бы причем здесь FIRE и habr.com? А при том, что невозможно добиться этой ранней пенсии НЕ имея и НЕ учитывая собственных диверсифицированных активов. А как показала многолетняя практика адекватных инструментов для учета акций, облигаций, недвижимости, монет и валют вкупе со страновой диверсификацией в одном окне практически нет. В небольшой предыстории рассказывал, что если у Вас есть, что учитывать, то сам учёт может занимать неоправданно много времени. Но тут на помощь приходит парсинг сайтов и это выводит управленческий учет собственного портфеля на новый уровень и, конечно же, приближает раннюю пенсию.
Важное замечание: эта статья для начинающего раннего пенсионера и новичка-парсера :). Мой опыт подразумевает использование данных с сайтов только для личных целей. Коснусь использования Microsoft Excel и Google Таблиц и совсем чуть-чуть KMyMoney. Начну в том порядке, в котором я сам столкнулся со всеми продуктами:
Часть 1. KMyMoney
Добавление нового актива в KMyMoney
Об этой программе незаслуженно мало информации на просторах интернета и особенно мало про её компонент парсинга цен. А ведь в инвестициях очень важно иметь актуальную картину перед глазами.
Настройка парсера в KMyMoney
Также любопытно, что из версии в версию KMyMoney (я пользовался программой несколько лет) в настройках парсера кочуют какие-то неработающие ссылки, которыми практически невозможно воспользоваться и нет какого-то внятного описания компонента.
Указание использовать шаблон парсинга для конкретной бумаги
Предлагаю для примера какую-нибудь облигацию федерального займа (ОФЗ) — это рублёвые облигации, выпускаемые Министерством финансов Российской Федерации. Данные по этим облигациям можно посмотреть на множестве сайтов или через API Московской Биржи. Возьму ОФЗ-ПК 29012 (SU29012RMFS0), а цену буду смотреть на сайте одного из брокеров. Идентификатором станет не код ценной бумаги с биржи, а внутренний идентификатор с сайта. Так выглядит окно с уже скаченной котировкой предыдущего дня:
Результат работы парсера для бумаги
В свое время составил подобные шаблоны для парсинга с помощью KMyMoney под множество активов для разных сайтов — надеюсь это будет полезно.
Конечно, KMyMoney позволяет иметь автоматические обновление курсов любых активов и это наверное единственная программа которая позволяет это делать, но как и у всех подобных учетных программ у неё есть определенные недостатки. А именно: раздражающий “бухгалтерский поиск” не сходящихся копеек (мне нужен обзорный инструмент) и огромное количество кликанья мышкой (в два клика ничего не сделать с инвестицией). Но эта программа наверное лучшее, если Вы хотите иметь учет личных финансов и инвестиций в одном окне и при этом иметь автоматические обновление курсов любых активов.
Часть 2. Microsoft Excel
Встроенных функций для парсинга в Excel нет и поэтому пользовался VBA, на основе найденных в интернете примеров (сам не особо разбирался в то время, чтобы написать с нуля) — код вероятно не самый лаконичный, но свои функции выполнял:
Редактор кода в Microsoft Excel
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 (и учётный шаблон на её основе) оставалась удобным локальным вариантом, если хотел открыть её и что-то в ней посмотреть. Но котировки активов не могли обновляться без участия человека и уж тем более эта таблица не могла утром в понедельник послать отчет и еще создать мероприятия в календаре о выплатах на неделю вперед. В общем, пришлось двинуться дальше.
Часть 3. Google Таблицы
Котировки через IMPORTXML
Google Таблицы как оказалось представляют гораздо более широкий диапазон возможностей для парсинга. И первое с чем столкнулся — это была функция IMPORTXML, которая позволяла взять почти любую строку из веб-страницы. А для использования надо только было научиться писать xpath запрос. С ее помощью можно собирать нужные котировки и другую информацию без скриптов и интеграции с API.
Мой шаблон отчетной таблицы, которому дал название SilverFir: Investment Report
Примерно за полгода изысканий в 2018 году родилась окончательная версия моего шаблона, который стал отправной точкой для взрослого учёта диверсифицированных активов “в одном окне”.
Распределение активов в отчетной таблице SilverFir: Investment Report
К сожалению, когда в Таблице использовалось множество IMPORTXML приходилось слишком долго ждать загрузки всех результатов, а также обнаружилась невозможность использования данных полученных через IMPORTXML по расписанию в гугл скриптах (потому что они могли просто не успеть подгрузиться к моменту их использования).
Котировки через Google Apps Script
Когда стало понятно, что при большом количестве строк и запрашиваемых данных пользоваться отчетной Таблицей на IMPORTXML становится неудобно — пришлось смотреть дальше.
Google Apps Script приходит на помощь в FIRE movement
Поскольку всегда считал, что FIRE movement — это свобода заниматься тем что нравится, а не бухгалтерский поиск копеек и уж конечно не копипаста котировок с разных сайтов. Структура и компоновка отчетной таблицы получилась очень удачная (это отмечали и другие люди), а вот метод получения котировок пришлось опять менять.
На гугл скриптах парсинг, на мой взгляд, выглядит лаконичнее, чем на VBA.
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. Прямо сейчас у Вас есть инвестиции?
- Да
- Нет
Опрос №2. Как Вы думаете, какой из вариантов выглядит оптимальным для многолетнего использования и учета всех инвестиций в одном окне?
- Онлайн-сервис *1
- Локальная программа
- Программа табличных данных
*1: Нашёл множество отличных сервисов, но все они локальные для конкретных рынков и ни в одном нельзя добавить что-то своё (в первую очередь страдает недвижимость).
ссылка на оригинал статьи https://habr.com/ru/post/477920/
Добавить комментарий