docs: reorganize system knowledge by domain

This commit is contained in:
2026-09-12 14:45:42 +03:00
parent 3a99af1a6e
commit f20c3f47bc
83 changed files with 2229 additions and 7335 deletions
+142
View File
@@ -0,0 +1,142 @@
# Облигации
Страница облигации объясняет условия конкретного выпуска, его рыночную цену,
купонный календарь и личную позицию. Денежная оценка покупки, текущая купонная
доходность, доходность источника к целевой дате и результат открытой позиции
имеют разный смысл. Раздел сохраняет их отдельно, вместе с валютой,
датой и ограничениями исходных данных.
## Поиск и идентификация выпуска
Раздел «Облигации» открывает `/bonds`: поиск по названию, тикеру или ISIN
с двух символов. `/bonds/:identifier` принимает UID или точный тикер.
Название и логотип облигации в портфеле счёта и «Всех счетах» ведут на её
страницу по точному UID без предварительной загрузки карточек всех позиций.
При открытии выпуска проверенный однозначный тикер заменяет UID в адресе,
сохраняя период графика и фильтр событий.
Поиск выбирает один режим на нормализованный ISIN, сохраняя разные выпуски
и записи без ISIN отдельно. Приоритет: доступность API, точный тикер, TQOB,
затем UID. Ограничение — 30 результатов после выбора режима. Цена и ссылка
принадлежат выбранному UID. Прямая ссылка из портфеля сохраняет исходный UID,
если поиск предпочитает другой режим. Неоднозначный точный тикер возвращает
`409 BOND_TICKER_AMBIGUOUS`; интерфейс предлагает выбрать выпуск через поиск.
Поиск загружает параметры выпусков и котировки, но оставляет ссылки по UID:
отдельная проверка тикера для каждого результата не выполняется.
## Содержание
Карточка показывает цену в процентах от номинала, время котировки и статус
торгов. Изменение выражено в процентных пунктах относительно последней
завершённой дневной свечи до московской даты котировки; база ищется за 20 дней.
Денежная оценка без НКД равна цене в процентах, умноженной на текущий номинал
и делённой на 100. Она округляется до девяти десятичных знаков. Оценка с НКД
добавляет текущий накопленный купонный доход только при совпадении валют.
Это ориентир без комиссии: котировка может быть старше текущего номинала и НКД.
FX-конвертация не выполняется, первоначальный номинал не заменяет текущий.
Условия выпуска: текущий и первоначальный номинал, погашение, оферта,
количество купонов в год, лот. Отдельно отмечены плавающий купон,
амортизация, бессрочность и субординация. Неизвестные даты и суммы показываются
как недоступные.
Сводка «Купон, рейтинг и доходность» показывает ближайший купон на одну
облигацию, дату выплаты и тип из календаря Т-Банка. Неизвестная сумма ближайшей
выплаты не заменяется суммой более позднего купона. Флаг плавающего купона
используется только как запасной признак типа; отсутствие флага не означает
фиксированный купон.
Текущая купонная доходность — ближайший купон × 365 / длительность его периода
в днях / денежная цена без НКД × 100 %. Decimal-расчёт округляется до четырёх
знаков. Требуются известная неотрицательная выплата, положительные цена и
период и одинаковая валюта выплаты и цены. Это годовая оценка при сохранении
размера купона и номинала, без налогов, комиссий и реинвестирования; она не
является доходностью к погашению. Время котировки показывается отдельно.
Эффективная доходность берётся из `marketdata_yields.EFFECTIVEYIELD` [MOEX ISS](../../integrations/moex.md),
с проверкой точных SECID, ISIN и BOARDID. Показываются собственная цена
расчёта, дата торгов и целевая дата (погашение, оферта или другая дата источника).
Котировка MOEX может отличаться от котировки Т-Банка и поступать с задержкой.
Доходность не рассчитывается из неполного календаря будущих выплат.
Кредитный рейтинг выпуска читается по точному ISIN из публичного
[реестра НКР](../../integrations/nkr.md). Отображаются агентство,
дата рейтингового действия, время получения реестра и ссылка на выпуск.
Отзыв показывается явно; уровень риска Т-Банка и рейтинг эмитента не
подставляются вместо рейтинга выпуска. Отсутствие записи в НКР не означает
отсутствия рейтингов других агентств. Причины выбора источника и пределы
покрытия сохранены в [ADR 013](../../adr/013-nkr-bond-credit-ratings.md).
HTML-источник, общий кэш и поведение при изменении реестра описаны в
[интеграции НКР](../../integrations/nkr.md#загрузка-кэш-и-отказ-источника).
График и таблица дневных цен сохраняют проценты от номинала и признак
завершённости свечи. Исторические котировки не пересчитываются в деньги
по сегодняшнему номиналу. Денежная средняя покупки не наносится на процентную
шкалу. Периоды: месяц, полгода, год и вся известная история. Окна upstream
не превышают 365 дней, одинаковые границы дедуплицируются. Если начало истории
неизвестно, запрос «вся история» возвращает `BOND_HISTORY_START_UNAVAILABLE`.
Позиция агрегирует только `BOND` с точным UID по доступным счетам, используя
[снимок портфеля](../portfolio/overview.md) и decimal-арифметику. Средняя покупка взвешена
по количеству. Неполные или разновалютные суммы недоступны; общая средняя
и процент доступны только при положительных включённых позициях. Для
коротких позиций и сочетания длинных с короткими эти показатели не синтезируются.
Результат открытой позиции не включает выплаченные купоны и продажи и не
называется доходностью к погашению. При отсутствии позиции блок скрыт.
## Купоны и личные события
Календарь охватывает пять прошлых лет и следующий год. Будущие купоны
сортируются по дате выплаты, прошедшие и недатированные доступны отдельно.
Показаны сумма на облигацию, номер, тип, длительность периода и дата реестра,
если они известны. Неопределённый будущий купон не заменяется нулём.
Личная оценка доступна только при положительных позициях, известной сумме,
будущей выплате и известном ещё не прошедшем реестре. Она не подтверждает право
на выплату и не учитывает налоги и будущие сделки. Время позиции и устаревание
снимка показываются отдельно от календаря выпуска.
Личная история использует [журнал операций](../operations/overview.md) всех счетов с точным
`instrumentUid`, включая прошлые годы. Фильтры: все, сделки, купоны, прочее.
Смена фильтра сбрасывает пагинацию; истёкший курсор восстанавливается запросом
первой страницы. Выплаты выпуска не подменяют личные зачисления.
## Получение данных и восстановление
Страницу облигации обслуживает инвестиционная подсистема backend.
Запросы `/api/v1/bonds` требуют действующей сессии с Bearer token и текущего
подключения T-Bank. Backend разрешает идентификатор и получает условия
выпуска, котировку, свечи, позицию, купоны и показатели. Точную форму
транспортного контракта задаёт [HTTP API](../../architecture/http-api.md).
`BondBy`, `FindInstrument` и `GetBondCoupons` используют способ
декодирования, сохраняющий отсутствие полей. Рыночные RPC проходят
общие TLS, очередь, ограничение частоты, deadline и повторные попытки. Кэш успешных и совместных
незавершённых запросов ограничен LRU и сроком 30 секунд по пользователю,
поколению подключения и параметрам. Ошибки не кэшируются; ошибки авторизации
не подавляются при дополнительной загрузке данных поиска.
Исходный ответ `BondBy` совместно используется поиском, карточкой, котировкой,
графиком, купонами и сводкой показателей в пределах того же пользователя, поколения и TTL.
Одновременная загрузка секций вызывает один `BondBy` на UID. Календарь
и сводка совместно используют один запрос купонов; котировка переиспользуется
при расчёте купонной доходности. MOEX и НКР загружаются только для открытого
выпуска, независимо от поиска. Для 30 новых
результатов поиск выполняет 32 RPC до повторных попыток: один `FindInstrument`,
30 `BondBy` и один пакетный запрос цен. Общий ограничитель backend не заменяет
квоты Т-Банка; при их исчерпании сохраняется `TBANK_UNAVAILABLE`.
Разделы загружаются независимо, показывают каркас загрузки и локальную повторную попытку.
Ошибка фонового обновления сохраняет последние данные. Смена подключения
сбрасывает поддерево клиентских запросов облигаций вместе с остальными финансовыми запросами;
выход очищает кэш сессии. Общие график, позиция и личные события
имеют общее представление на страницах акций и облигаций.
Основные спецификации [портфеля](../../../specs/openspec/specs/portfolio-view/spec.md)
и [журнала](../../../specs/openspec/specs/brokerage-account-ledger/spec.md)
описывают исходные финансовые понятия. Отдельная основная спецификация
страницы облигации в текущем OpenSpec Store не найдена; условия вычислений
подтверждены [сервисом облигаций](../../../backend/src/tbank/bond.service.ts)
и его [проверками](../../../backend/src/tbank/bond.service.spec.ts).
Границы источников описаны в [разделе интеграций](../../integrations/README.md),
сходное разделение рыночных и личных данных — в [акциях](stocks.md).
+172
View File
@@ -0,0 +1,172 @@
# Акции
Страница акции связывает три разных вида сведений: публичные данные
конкретного выпуска и компании, текущую личную позицию и исполненную
историю операций. Публичная цена и календарь дивидендов доступны даже без
открытой позиции; личная часть относится только к счетам текущего
подключения T-Bank. Эти сведения не заменяют друг друга и имеют разное время
наблюдения.
## Поиск и точная бумага
Авторизованный пользователь открывает `/stocks/SBERP` по тикеру. Старые
адреса `/stocks/:uid` продолжают работать. Сервер возвращает `slug`: проверенный
однозначный тикер либо исходный UID. При открытии UUID-ссылки страница заменяет
адрес на тикер только при совпадении UID, сохраняя период и фильтр событий.
Прямое открытие и обновление страницы с тикером сначала разрешает его в UID;
цены, позиция и личные операции затем запрашиваются только по этому UID.
Ссылки находятся в названиях и логотипах акций отдельного портфеля и обзора
«Все счета». Названия сохраняют обычный цвет текста; буквенная заглушка
логотипа также ведёт на страницу акции. Карточки получают проверенный `slug`
через запрос акции по UID: при подтверждённом тикере обе ссылки используют
его, иначе сохраняют UID. Одинаковые UID в разных счетах используют один запрос и общий
кэш страницы акции. До загрузки и при ошибке остаётся рабочая ссылка по UID;
загрузка адресов не блокирует портфель.
Раздел «Акции» в боковой и мобильной навигации ведёт на `/stocks`: поиск
по названию или тикеру через каталог Т-Банка, начиная с двух символов.
Результаты разных выпусков, включая обыкновенные и привилегированные акции,
имеют отдельные UID. Карточка результата показывает логотип, последнюю цену
с её временем, тип бумаги, площадку, код режима, ISIN и доступность торгов через
API. Поиск показывает одну карточку на нормализованный ISIN. До ограничения
в 30 результатов выбирается представитель выпуска: доступность через API,
точное совпадение тикера, затем режим TQBR; равные варианты упорядочены по UID.
Записи без ISIN сохраняются отдельно по UID. Обыкновенные и привилегированные
акции с разными ISIN не объединяются. Цена и ссылка принадлежат выбранному
UID; данные разных режимов не смешиваются. Прямые ссылки из портфеля сохраняют
исходный UID, даже если поиск выбрал другой режим этого выпуска; такая страница
сохраняет UUID в адресе. Если один точный тикер относится к разным выпускам,
сервер возвращает `409 STOCK_TICKER_AMBIGUOUS`, а страница предлагает поиск.
Поиск тикера нечувствителен к регистру, но использует точное совпадение:
SBER не заменяется на SBERP. Однобуквенные тикеры также поддерживаются.
Прямая ссылка не требует предварительного открытия портфеля. Хлебные крошки
«Акции → название» возвращают к поиску.
## Содержание и состояния
Верхний блок объединяет название, тип акции, текущую цену и показатели компании.
Денежные показатели используют символ валюты; описание компании видно сразу
под логотипом и названием, перед ценой. Далее идут график, моя позиция, предстоящие
дивиденды и личная история событий.
Логотип загружается из публичного CDN; при отсутствии изображения показывается буквенная заглушка.
Позиция отсутствующей или полностью проданной бумаги не создаёт пустого блока;
рыночные данные и личная история остаются доступны.
Каждый раздел загружается независимо. Первичная загрузка показывает каркас
раздела, ошибка — локальную повторную попытку. При ошибке фонового обновления
сохраняются предыдущие данные и предупреждение. Цена содержит собственное время
UTC, которое может быть старше времени получения ответа. Статус торгов не
выводится из свежести цены. Отсутствующее значение не заменяется нулём.
## Связь с портфелем и операциями
Серверная инвестиционная подсистема предоставляет поиск, карточку инструмента,
котировку, дневные свечи, сводку позиции, дивиденды и доступные данные компании.
Все запросы `/api/v1/stocks` требуют действующей сессии с Bearer token и актуального подключения
T-Bank; точные маршруты и поля принадлежат [HTTP API](../../architecture/http-api.md).
Frontend не получает брокерский токен и не обращается к T-Bank напрямую.
Личная история использует существующий
`GET /api/v1/brokerage-accounts/all/operations?instrumentUid=...`.
Фильтр UID валидируется и передаётся upstream как `instrumentId`; ответ также
проверяется по UID. Без `from` такой запрос начинается с самой ранней известной
даты открытия доступных счетов; если даты неполны, нижняя граница — Unix epoch.
Обычный журнал без фильтра инструмента сохраняет начало текущего года.
UID включён в ключ кэша и подпись общего курсора: курсор другой бумаги,
пользователя, поколения подключения или фильтра отклоняется. Истечение курсора
восстанавливается переходом на первую страницу с повторным запросом.
[Портфель](../portfolio/overview.md) остаётся владельцем снимков и оценки позиций. Сводка
фильтрует `STOCK` по точному UID и использует точную десятичную арифметику, без конвертации валют.
Средняя цена равна сумме количеств, умноженных на средние цены, делённой на
общее количество; она округляется сервером до девяти знаков, проценты — до шести.
Неполные или разновалютные денежные итоги недоступны. Общая средняя и процент доступны только если все включённые позиции
положительны; для нулевого количества, коротких позиций и сочетания
длинных с короткими они не синтезируются.
Результат открытой позиции исключает продажи и дивиденды и не называется полной
доходностью. Время и `isStale` сохраняют семантику исходного Portfolio Snapshot.
## Рыночная цена и график
Изменение рассчитывается относительно последней завершённой дневной свечи
строго до календарной даты последней цены по Москве. Поиск базы охватывает
20 дней до последней цены; если подходящей свечи нет, сравнение недоступно.
Дата базы указана рядом с изменением. `GetClosePrices` не используется:
его основное закрытие может относиться к текущему дню.
График показывает дневные `close`, сохраняет `isComplete` и предупреждает
о формирующейся свече. Окна RPC не превышают 365 дней, общие границы
дедуплицируются. «Вся история» начинается с `first_1dayCandleDate`; если источник
не сообщает начало истории, этот период недоступен, остальные работают.
Пустое окно до начала торгов не считается ошибкой. Линия текущей средней
покупки доступна только в валюте графика; шкала включает её значение.
Таблица цен раскрывается под графиком: новые даты первыми, валюта в цене,
статус завершённости свечи, закреплённая шапка и прокрутка с клавиатуры.
Стили графиков подключены на уровне приложения и каталога, поэтому оформление
подсказки не зависит от ранее посещённых страниц.
Метки старых сделок и дивидендов на графике не добавлены: соответствие шкалы
после корпоративных изменений не подтверждено. Лента использует дату операции;
количество сделки берётся из `quantityDone`, а не порученного `quantity`.
Отсутствующее исполненное количество не подменяется порученным. Сами исполнения
не превращаются в точные точки графика.
## Дивиденды и финансовые показатели
События компании отделены от личных зачислений. Известные будущие выплаты
определяются по `paymentDate`, при её отсутствии — по `recordDate`; прошедшие
и недатированные события помещены в отдельную историю компании. Отменённые
события исключаются. Личная оценка умножает сумму на акцию на текущее положительное
количество. Для уже прошедшего реестра оценка не строится. Время позиции и
предупреждение об устаревшем снимке или недоступной оценке показаны отдельно.
Оценка не доказывает право на выплату, не учитывает будущие сделки и не обещает
индивидуальную дату зачисления. Статусы «рекомендован/утверждён», сумма отдельного
зачисления после налога и налоговый смысл `dividend_net` не выводятся из API.
Пустой список означает отсутствие известных событий только за указанный период.
`GetAssetFundamentals` использует отдельный способ декодирования ответа,
который сохраняет отсутствие полей (`defaults: false`). Это важно для
отличия неизвестного показателя от известного нуля; настройка остальных
клиентов при этом не изменяется. Финансовый сектор
показывает капитализацию, P/E, P/B, ROE и чистую прибыль; остальные — капитализацию,
P/E, выручку, EBITDA, чистую прибыль, общий долг и чистый долг / EBITDA, если
значения доступны. Денежные показатели без валюты не показываются.
TTM означает последние 12 месяцев, MRQ — последний отчётный квартал;
время получения не выдаётся за дату отчётности. Годовых финансовых рядов нет.
## Получение данных и ограничения
Запросы T-Bank проходят общую серверную интеграцию с TLS, лимитом частоты,
очередью, предельным временем ожидания и повторными попытками. Проверка доступа
и расшифровка token выполняются только backend. Успешные ответы и совместные незавершённые запросы кэшируются
в ограниченном кэше LRU на 30 секунд по пользователю, поколению подключения и параметрам.
Для поиска `FindInstrument` дополняется сведениями `ShareBy` через тот же
кэш карточки инструмента и одним пакетным `GetLastPrices` для списка. Ошибка
дополнительной загрузки или исчезнувшая карточка не скрывает исходную запись
каталога; недоступные логотипы и цены имеют заглушки. Ошибки авторизации
не подавляются.
Ошибка целого запроса не кэшируется; отсутствие дополнительного источника
обозначается в ответе. Поддерево клиентских запросов акций сбрасывается вместе с финансовыми
данными при изменении подключения; выход очищает кэш сессии.
Полные даты в интерфейсе имеют формат ДД.ММ.ГГГГ; ISO-формат транспорта и
временные зоны расчётов не меняются. Личная история использует общий с портфелем формат строки операции,
дополненный количеством, ценой и ссылкой на счёт. История
дивидендов компании раскрывается в оформленном блоке с отдельными карточками
выплат, датой реестра, доступной датой выплаты и суммой на акцию.
Ограничения источника требуют различать отсутствие финансового поля и ноль.
Время получения не подтверждает дату отчётности, а совпадение даты не позволяет
однозначно связать налог с отдельным дивидендом.
Алгоритм корректировки исторических цен после корпоративных событий не
подтверждён, поэтому точное наложение старых личных сделок на график не обещается.
Доступность данных по отдельным бумагам не доказывает полноту покрытия рынка.
История открытых счетов не обещает полную историю владения, включая закрытые
счета, переводы и универсальные корпоративные события.
Основные спецификации [портфеля](../../../specs/openspec/specs/portfolio-view/spec.md)
и [журнала](../../../specs/openspec/specs/brokerage-account-ledger/spec.md)
задают исходные финансовые понятия. Отдельная основная спецификация страницы
акции в текущем OpenSpec Store не найдена; описанные механизмы проверяются
по [сервису акций](../../../backend/src/tbank/stock.service.ts) и его
[проверкам](../../../backend/src/tbank/stock.service.spec.ts).
Сопоставление с облигациями — на [странице облигаций](bonds.md).