# Соглашения ## Деньги и валюты - Все суммы и количества — `Decimal`; в БД `NUMERIC(24,10)`; в JSON — строки. - Рядом с суммой всегда колонка валюты (`amount` + `currency`, `fee` + `fee_currency`). - Хранить в нативной валюте, **не конвертировать на записи**. - Конвертация — в аналитике по `fx_rate_daily` на дату операции; курсы ЦБ протянуты через выходные (`is_carried = true`); RUB→RUB = 1.0 на любую дату; нет курса → NULL + запись в `metric_data_quality`. - Float допустим только внутри расчётов, результат которых — коэффициент (XIRR, TWR, beta). ## Идемпотентность и источники - `raw_*` — append-only, upsert по стабильному id источника; повторный синк ничего не дублирует. - Каждая core-строка знает `source` и `source_id`. - `event.dedupe_key` UNIQUE: номер сделки, если брокер его даёт, иначе fingerprint. - У счёта один `primary_event_source`; события других источников — `status = shadow`. ## Время - Торговые даты (`trade_date`) — в MSK; T-Invest отдаёт UTC, конвертируем до вывода даты. - Все `timestamp` — `timestamptz`. ## Код - Python 3.12, типизация обязательна (pyright `standard`), ruff (`E F I UP B SIM RUF`). - Async везде, где есть I/O; SQLAlchemy 2.0 style (`Mapped`, `select()`). - Один модуль импортирует SDK T-Invest: `sources/tinvest/client.py`. - Парсеры отчётов — чистые функции `bytes -> ParsedReport`, без БД. - Тесты: pytest + pytest-asyncio, Postgres поднимается фикстурой; golden-числа для финансовой математики. - Комментарии и docstrings — по-английски (кириллица допустима в пользовательских строках), документация для людей и агентов — по-русски.