Почему?
Несколько лет назад я заинтересовался получением пассивного дохода и решил попробовать инвестировать с помощью p2b-площадок. Через некоторое время стало заметно, что денежные средства оказались очень сильно фрагментированы по площадкам, банкам, долгам, и это затрудняло понимание ситуации. Я не мог ответить на два самых главных вопроса:
Сколько у меня денег?
Какой тренд? Я богатею, или беднею?
Нужно было как-то собрать информацию воедино и поддерживать ее в актуальном виде.
Варианты решения проблемы были следующие:
Таблица в Google Sheets
Преимущества: делается быстро, гибко, бесплатно
Недостатки: необходимость обновлять данные вручную
Первое время я пользовался этим вариантом, но постоянные трудозатраты на его поддержание утомляли: нужно было зайти во множество личных кабинетов и переписать оттуда данные. Кроме того, некоторые активы имели высокую волатильность, поэтому нерегулярность данных сказывалась на качестве принятия решений.
Специализированные решения
В большинстве случаев это те же таблицы, только с симпатичным/удобным интерфейсом.
В редких случаях есть интеграция с несколькими банками, но во всех случаях что я пробовал — она была нестабильной и ненадежной. Также отпугивала необходимость отдавать свой логин/пароль от интернет-банка и отсутствие интеграции с нестандартными источниками данных.
Стало очевидно, что подходящий сервис придется писать самому — только так можно полностью автоматизировать получение финансовых данных, и в то же время не беспокоиться о передаче реквизитов третьей стороне. Кроме того, это позволило бы реализовать любой желаемый интерфейс. Так начался проект BudgetTracker, которым я успешно пользуюсь уже два года. Его можно скачать в виде исходников и/или установить на собственный сервер как готовый docker-контейнер.
Основная идея
Есть две разные стороны, как можно смотреть на финансы. С одной стороны есть текущее состояние (условно — сейчас на счету “Х” находится “У” денег), с другой стороны есть транзакции (условно — покупка “ХХ” за “УУУ” денег в момент времени Т).
Эти две стороны финансовпрактически независят друг от друга, но являются необходимыми что понимать общий тренд. Простой пример — у нас есть актив, похожий на депозит (например, облигации), который мы периодически докупаем.
Для того, чтобы построить график изменения стоимости такого актива(и прогноз) важно не учитывать докупки.
Источники данных
Существуют разные провайдеры — источники данных, например собирающие данные из банк-клиента.
- FX — курсы валют: EUR, USD
- LiveCoin — криптобиржа
- Penenza
- АльфаБанк
- АльфаКапитал
- АльфаДирект
- АльфаПоток
- МодульБанк
- МодульДеньги
- Райффайзен
- Долги и ссуды (для вручную заведенных долгов)
- POST-api для получения произвольных данных из внешних систем
Так как часть провайдеров требуют SMS-аутентификацию, то есть также интеграция с SMS через IFTTT (только для Android-телефонов).
Провайдер каждые сутки собирает состояние каждого из счетов и список всех транзакций и сохраняет их в базу. Для этого запускается Chrome, и с помощью Selenium извлекаются нужные данные из онлайн-банков.
Счета
Состояния каждого из счетов формируют таблицу вида:
Это дает возможность видеть детали и состояние каждого из счетов, но это не помогает видеть общую картину, и не дает ответа на простой вопрос "сколько у меня денег?".
Для того, чтобы ответить на этот вопрос была добавлена поддержка “вычисляемых столбцов”, в которых можно задать формулу, например:
Но помимо конкретного значения хочется видеть также тренд, выбросы, прогнозы — иными словами видеть динамику этого значения (а иногда и не только его одного).
Для этого существует концепт “главной страницы” где можно настраивать отдельные виджеты для того, чтобы акцентировать внимание на конкретных столбцах / трендах.
Виджеты
Существуют несколько видов виджетов:
- “Пончик” с тратами (из транзакций)
- “Последнее значение” — график-линия для произвольных столбцов, показывает прогнозируемое изменение в годовых (%), и фактическое за последний день (%). Бывает так же в "компактном" режиме, когда показывает только текущее(последнее) значение.
- “Дельта” — показывает изменения столбца в цифрах за последние 24ч, 48ч, 1 неделю и 1 месяц
- “Пончик” — для вычисляемых столбцов
- “График” — для вычисляемых столбцов
Каждый тип виджета имеет свой размер, и их можно двигать относительно друг друга, используя "стрелочки". По-умолчанию они скрыты, и появляются по нажатию кнопки "глаз" в верхней части страницы:
Также при создании или редактирования виджета есть возможность изменить какие-либо его настройки:
Транзакции
Для работы с транзакциями, или ДДС, есть отдельная страница, где видно все транзакции, сгруппированные по категориям.
У каждой транзакции есть “тип” транзакции — это “доход”, “расход”, или “перевод”. Перевод выставляется вручную, чтобы исключить переводы из графиков с главной страницы.
Это может быть удобно, чтобы сгладить график для активов от провайдеров, которые не имеют транзакций. Например — фондовый рынок. Можно купить акции, а ещё они могут вырасти в цене, и на графике часто хочется видеть только второй тип событий.
В таком случае удобно добавить автогенерацию транзакций в свойствах столбца, и в момент покупки отредактировать транзакцию в которой покупали акции и поставить ей тип “перевод”.
Категории и типы можно выставлять как вручную (придётся их сначала завести), так и на основе правил. При установке категории на транзакцию — она автоматом установится также на все другие транзакции с таким же описанием (и в будущем будет также применяться на подобные транзакции). Помимо ручной установки категории на транзакцию можно добавить правило в виде регулярного выражения или вхождению подстроки для автоматической установки категории на все подходящие транзакции.
Также существует отдельный раздел “Долги”, куда можно вносить вручную долги. Для каждого долга можно аналогично установить шаблон для транзакции, чтобы при появлении новых ДДС, относящихся к этому долгу — оставшаяся сумма обновлялась.
Технологический стек
В настоящий момент бекенд работает на .NET Core 3, фронтенд на Svelte 3.
Для хранения данных используется ObjectRepository + LiteDB.
Для интеграции с источниками данных используется связка Selenium + Chrome.
Изначально всё писалось полностью на .NET Core, но некоторое время назад фронтенд был переписан на Svelte.
Из-за этого наследия — общение с сервером было сделано не оптимально и есть планы переписать эту часть проекта на реактивную модель.
Как попробовать
docker-compose.yml файл в репозитории поможет:
version: "3.3"
services:
budgettracker:
image: diverofdark/budgettracker:master
restart: unless-stopped
environment:
Properties__IsProduction: 'true' # true если необходимо сохранять изменения в базу.
ConnectionStrings__LiteDb: '/data/budgettracker.db'
volumes:
- /dev/shm:/dev/shm # Для использования Google Chrome
- /root/bt:/data
ports:
- "80:80"
networks:
public: {}
networks:
public:
driver: bridge
Автор: DiverOfDark