Docs security / security (pull_request) Successful in 6s
Docs verify / verify (pull_request) Successful in 11s
Conventional commits / commits (pull_request) Successful in 16s
Docs security / security (push) Successful in 9s
Docs verify / verify (push) Successful in 10s
180 lines
20 KiB
Markdown
180 lines
20 KiB
Markdown
# Акции
|
||
|
||
Страница акции связывает три разных вида сведений: публичные данные
|
||
конкретного выпуска и компании, текущую личную позицию и исполненную
|
||
историю операций. Публичная цена и календарь дивидендов доступны даже без
|
||
открытой позиции; личная часть относится только к счетам текущего
|
||
подключения T-Bank. Эти сведения не заменяют друг друга и имеют разное время
|
||
наблюдения.
|
||
|
||
## Поиск и точная бумага
|
||
|
||
Авторизованный пользователь открывает `/stocks/SBERP` по тикеру. Старые
|
||
адреса `/stocks/:uid` продолжают работать. Сервер возвращает `slug`: проверенный
|
||
однозначный тикер либо исходный UID. При открытии UUID-ссылки страница заменяет
|
||
адрес на тикер только при совпадении UID, сохраняя период и фильтр событий.
|
||
Прямое открытие и обновление страницы с тикером сначала разрешает его в UID;
|
||
цены, позиция и личные операции затем запрашиваются только по этому UID.
|
||
Ссылки находятся в названиях и логотипах акций отдельного портфеля и обзора
|
||
«Все счета». Названия сохраняют обычный цвет текста; буквенная заглушка
|
||
логотипа также ведёт на страницу акции. Карточки получают проверенный `slug`
|
||
через запрос акции по UID: при подтверждённом тикере обе ссылки используют
|
||
его, иначе сохраняют UID. Одинаковые UID в разных счетах используют один запрос и общий
|
||
кэш страницы акции. До загрузки и при ошибке остаётся рабочая ссылка по UID;
|
||
загрузка адресов не блокирует портфель.
|
||
|
||
Названия, тикеры, ISIN и логотипы карточек портфеля приходят в его серверном
|
||
ответе. Запрос страницы акции уточняет только ссылку и не подменяет эти поля
|
||
на frontend. Общее для акций и облигаций восстановление справочных данных
|
||
принадлежит [загрузке портфеля на backend](../portfolio/flows/portfolio-loading.md).
|
||
|
||
Раздел «Акции» в боковой и мобильной навигации ведёт на `/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-формат транспорта и
|
||
временные зоны расчётов не меняются. Личная история использует общий с портфелем формат строки операции,
|
||
дополненный количеством, ценой и ссылкой на счёт. История
|
||
дивидендов компании раскрывается в оформленном блоке с отдельными карточками
|
||
выплат, датой реестра, доступной датой выплаты и суммой на акцию.
|
||
Ограничения источника требуют различать отсутствие финансового поля и ноль.
|
||
Время получения не подтверждает дату отчётности, а совпадение даты не позволяет
|
||
однозначно связать налог с отдельным дивидендом.
|
||
Алгоритм корректировки исторических цен после корпоративных событий не
|
||
подтверждён, поэтому точное наложение старых личных сделок на график не обещается.
|
||
Доступность данных по отдельным бумагам не доказывает полноту покрытия рынка.
|
||
История открытых счетов не обещает полную историю владения, включая закрытые
|
||
счета, переводы и универсальные корпоративные события.
|
||
|
||
Основные спецификации [портфеля](https://git.personal.ksv741.ru/WealthLedger/specs/src/commit/9e227a563dda67620f0ad78228aa8a4c18bf35a0/openspec/specs/portfolio-view/spec.md)
|
||
и [журнала](https://git.personal.ksv741.ru/WealthLedger/specs/src/commit/9e227a563dda67620f0ad78228aa8a4c18bf35a0/openspec/specs/brokerage-account-ledger/spec.md)
|
||
задают исходные финансовые понятия. Отдельная основная спецификация страницы
|
||
акции в текущем OpenSpec Store не найдена; описанные механизмы проверяются
|
||
по [каталогу](https://git.personal.ksv741.ru/WealthLedger/backend/src/commit/016782657acfd35ff3fd755462007938fac35156/src/modules/investments/instruments/stocks/application/stock-catalog.service.ts),
|
||
[рыночным данным](https://git.personal.ksv741.ru/WealthLedger/backend/src/commit/016782657acfd35ff3fd755462007938fac35156/src/modules/investments/instruments/stocks/application/stock-market.service.ts),
|
||
[выплатам](https://git.personal.ksv741.ru/WealthLedger/backend/src/commit/016782657acfd35ff3fd755462007938fac35156/src/modules/investments/instruments/stocks/application/stock-income.service.ts) и [проверкам](https://git.personal.ksv741.ru/WealthLedger/backend/src/commit/016782657acfd35ff3fd755462007938fac35156/src/modules/investments/instruments/stocks/application/stock.spec.ts).
|
||
Сопоставление с облигациями — на [странице облигаций](bonds.md).
|