Portfolio Performance я ставил, импортировал в него сделки и бросил. Две причины, и обе технические: он плохо работает с российскими брокерами, а свою логику в него выразить нельзя — только подстраиваться под чужую модель.
Где ломается готовое решение
Дело не в том, что инструмент плохой. Он закрывает задачу «посчитать портфель». Моя задача звучит иначе: посчитать портфель по моим правилам, с моими формулами и моими российскими брокерами. Разница в этом предложении — и она дороже, чем кажется.
Вот цепочка, которая в итоге выкинула готовый продукт:
- ZenMoney не умеет учитывать акции и облигации с переоценкой. Там удобно считать расходы и доходы, но бумаги живут по другим правилам.
- Tinkoff не отдаёт CSV. Данные по сделкам и ценам доступны только через API.
- Универсальный импортёр в такой схеме упирается в оба ограничения сразу.
Дальше вариантов два: подстраивать задачу под инструмент или написать свой код под задачу. Я выбрал второе, потому что подстройка обходится дороже — и в скорости, и в том, что результат всё равно пришлось бы пересчитывать руками.
Три источника, у каждого своя роль
Прежде чем писать код, я разделил ответственность. Это важнее, чем сам код.
| Инструмент | Что делает |
|---|---|
| ZenMoney | расходы, доходы, бюджеты, цели |
| Свой трекер (Python → markdown) | портфель, доли, ребаланс, формулы |
| Tinkoff API | источник правды по сделкам и ценам |
Ни один инструмент тут не делает всё. ZenMoney остаётся источником транзакций по деньгам, Tinkoff — источником правды по бумагам, а мой скрипт занимается только тем, что между ними: считает доли по правилам и раскладывает результат в markdown.
Третье — ключевое. Скрипт не хранит состояние. Он читает API, считает и кладёт результат в вики обычной markdown-страницей. Рядом лежат политика, цели и решения, на основе которых всё это посчитано. Отчёт и его основание живут в одном месте.
Что формулы умеют, а чужой инструмент — нет
У меня есть инвестиционный план, и в нём доли считаются по формуле, а не заданы числами:
резервный_фонд = 10%
генерация_фонд = 5%
акций_роста_фонд = 10%
индексный_фонд = 0%
дивидендный_фонд = 100 − резервный − генерация − акций_роста − индексный
= 75%
ядро_дивидендного = (100 − возраст) × доля_дивидендного / 100
Последняя строка — то, ради чего всё затевалось. Доля дивидендного фонда зависит от возраста: ядро пересчитывается каждый год, и внутри ядра активная и пассивная части делятся пополам.
Универсальный трекер про такое не знает. Он умеет показывать структуру портфеля, но не умеет взять мою формулу и применить её к моим же данным. Правила отбора фондов (ограничение на долю одного актива, требуемую доходность относительно ключевой ставки, распределение ядра по типам облигаций) живут в плане, и в чужой интерфейс это не влезает.
До и после
Пока трекер был в разработке, сверка портфеля выглядела так:
- 4 шага по 5 минут, около 15 минут в неделю
- вклады обновлялись вручную
- акции и облигации не сверялись вообще — нечем было
Сейчас:
- 4 шага по 1–2 минуты, около 5 минут в неделю
- скрипт запускается, читает данные брокера и пишет markdown
- отклонение долей от плана считается само
- если отклонение больше 5% — приходит алерт в задачник по ребалансу
Разница в минутах — не главное. Главное, что акции перестали быть слепой зоной. Полгода я знал, что по акциям и облигациям не сверяюсь, и это молчало до момента, когда перекос стал бы дорогим.
Отдельно: в трекер встроена синхронизация налогов, купонов и дивидендов с ZenMoney. Операции появляются в учёте сами, вручную их вносить не нужно. Весь этот кусок я собрал за один день — задача была конечной и проверяемой, и это единственное, что уберегло её от бесконечной полировки.
Почему всё это стоит в вики, а не в приложении
Отдельное приложение для учёта портфеля — это ещё один инструмент, который требует внимания. У него свой интерфейс, свои обновления, свои поломки и своя логика, которую надо сверять с логикой в плане.
Markdown-страница в базе знаний работает иначе. Данные приезжают скриптом, отчёт лежит рядом с политикой и целями, и в тот же файл я пишу записи из дневника. Ничего не нужно открывать, обновлять и синхронизировать — оно просто лежит и читается.
Минус честно: это не интерфейс для повседневного использования. Это отчёт, который смотришь раз в неделю. Мне этого хватает, потому что рутина всё равно уходит в фон, а не в глаза.
Вывод
Разница между «решить задачу» и «решить мою задачу» стоила мне одного готового инструмента и пары дней работы. Если ваш инструмент закрывает 90% задачи, это повод им пользоваться. Если оставшиеся 10% — это вся суть, дешевле написать своё, чем подстраиваться.
Код трекера открытый. Правила, по которым он считает, лежат рядом с ним же.