b58ffb3aac6531b0b6136ef18424791fa1d5ecff
Каждое измерение покрывает ОДИН И ТОТ ЖЕ итог — бумаги плюс кэш. Четыре диаграммы одного портфеля обязаны быть одного размера, иначе экраны противоречат друг другу, поэтому кэш это бакет в каждом разрезе, а не то, что выброшено из тех, куда он неочевидно ложится. Исключение — валютный разрез: деньги в рубле лежат вместе с рублёвыми бумагами, потому что вопрос к этой диаграмме именно такой. Бакет хранится ключом, а не подписью: класс актива как есть, сектор и страна как их пишет источник, плюс два литерала — cash и unknown. Язык живёт в клиенте; зашивать его в данные значит зашивать один язык навсегда. Позиция без цены исключается, а не считается нулём: ноль тихо ужал бы все остальные веса. Короткая позиция сохраняет свою величину, но не уменьшает знаменатель — иначе длинная сторона вылезла бы за 100 %, что на круговой диаграмме не значит ничего. Derived-кэш вынесен в valuation.cash_balances(): одно определение «нашего кэша» для сверки со снапшотом брокера и для аллокации, с одним и тем же исключением покупок с карты, деньги которых баланс счёта никогда не видел.
fin-tracker
Личная аналитика финансов и инвестиций: ZenMoney (повседневные деньги) + брокеры (T-Invest API, отчёты Сбера и ВТБ) в одной базе, с XIRR/TWR, календарём дивидендов и купонов, аллокацией и net worth. Замена Snowball Income.
backend/— Python 3.12, FastAPI, PostgreSQL, worker с расписанием синков.app/— Flutter-клиент (web, Linux, Windows, Android) поверх REST/OpenAPI.deploy/— Caddy и сертификаты;docker-compose.yml— прод на VPS.
Для агентов: AGENTS.md. Команды: just --list.
Languages
Python
46.4%
Dart
40.9%
JavaScript
11%
C++
0.7%
CMake
0.6%
Other
0.2%