feat: add market data architecture and complete migration through build 039

This commit is contained in:
2026-07-14 09:58:16 +03:00
parent 26deb861bc
commit a996f2f797
443 changed files with 80452 additions and 1335 deletions

View File

@@ -0,0 +1,341 @@
# Stream Research Protocol — marketData.subscribe
## Контроль документа
| Свойство | Значение |
|----------|----------|
| Документ | Stream Research Protocol — marketData.subscribe |
| Тип документа | Research Protocol |
| Версия | 2.0 |
| Статус | Draft |
| Проект | Dzentra |
| Подсистема | Market Intelligence |
| Биржа | Dzengi |
| Endpoint | `marketData.subscribe` |
| Транспорт | WebSocket Stream |
| Основан на | Market Intelligence Stream Research Standard |
| Язык | Русский |
---
# 1. Исследование подключения
## 1.1 Подключение
### 1.1.1 Корректность подключения
- [x] корректность подключения — подтверждена.
#### Журнал исследования
Получено успешное подключение к WebSocket API Dzengi.
Получено подтверждение подписки.
После подтверждения подписки начинают поступать сообщения `internal.quote`.
---
### 1.1.2 Требования к соединению
- [x] URL подключения — соответствует документации.
- [x] используемый транспорт (WS/WSS) — соответствует документации.
#### Журнал исследования
**URL подключения**
Production: `wss://api-adapter.dzengi.com/connect`
Demo: `wss://demo-api-adapter.dzengi.com/connect`
**Используемый транспорт**
`WSS (WebSocket Secure)`
---
### 1.1.3 Требования к авторизации
- [x] требуется ли авторизация — соответствует документации.
- [x] механизм авторизации — соответствует документации.
- [x] обязательные заголовки авторизации — соответствует документации.
- [x] возможность работы без авторизации — соответствует документации.
#### Журнал исследования
Публичный поток `marketData.subscribe` доступен без передачи данных авторизации.
---
### 1.2 Подписка
- [x] формат подписки — частично соответствует документации;
- [x] подтверждение подписки — соответствует документации;
- [x] сообщения об ошибках — определено экспериментально;
- [х] повторная подписка — определено экспериментально;
- [x] подписка на несколько инструментов — определено экспериментально.
#### Журнал исследования
**Формат подписки**
Документация описывает только содержимое `payload`:
```
{
"symbols": [
"string"
]
}
```
Фактический формат сообщения, передаваемого через WebSocket /connect:
```
{
"correlationId": "...",
"destination": "marketData.subscribe",
"payload": {
"symbols": [
"BTC/USD_LEVERAGE"
]
}
}
```
**Подтверждение подписки**
```
{
"destination": "marketData.subscribe",
"status": "OK",
"payload": {
"subscriptions": {
"BTC/USD_LEVERAGE": "PROCESSED"
}
}
}
```
**Сообщения об ошибках**
Экспериментально зафиксированы варианты ошибок:
- `INVALID/SYMBOL` возвращает `status = OK`, но в `payload.subscriptions` указывается `ERROR: INVALID/SYMBOL not found`.
- пустой `symbols` возвращает `status = ERROR`, `code = -1128`.
- отсутствующий `symbols` возвращает `status = ERROR`, `code = -1128`.
- отсутствующий `payload` возвращает `status = ERROR`, `code = -1128`.
- неверный `destination` возвращает `status = ERROR`, `errorCode = BAD_REQUEST`.
**Повторная подписка**
- первая подписка получает статус `PROCESSED`;
- повторные подписки получают статус `ALREADY_SUBSCRIBED`;
- сообщения об ошибке не формируются;
- повторная подписка работает без предварительной отмены;
- в проведенных экспериментах признаков дублирования сообщений `internal.quote` не обнаружено.
**Подписка на несколько инструментов**
Экспериментально установлено:
- команда `marketData.subscribe` принимает несколько торговых инструментов;
- подтверждение подписки содержит отдельный статус для каждого инструмента;
- поток `internal.quote` передает сообщения для всех подписанных инструментов через одно WebSocket-соединение;
- принадлежность сообщения к инструменту определяется полем `payload.symbolName`.
---
# 2. Исследование структуры потока
## 2.1 Типы сообщений
- [ ] назначение;
- [ ] содержит ли рыночную информацию;
- [ ] содержит ли служебную информацию;
- [ ] содержит ли ошибки;
- [ ] содержит ли подтверждение подписки;
- [ ] содержит ли подтверждение отписки.
#### Журнал исследования
---
## 2.2 Структура сообщений
- [ ] обязательные поля;
- [ ] необязательные поля;
- [ ] тип каждого поля;
- [ ] допустимые значения;
- [ ] диапазоны значений;
- [ ] ограничения.
#### Журнал исследования
---
# 3. Классификация сообщений
- [ ] рыночное сообщение;
- [ ] служебное сообщение;
- [ ] сообщение управления;
- [ ] сообщение об ошибке;
- [ ] сообщение подтверждения.
#### Журнал исследования
---
# 4. Исследование семантики полей
- [ ] фактическое назначение;
- [ ] источник происхождения;
- [ ] обязательность;
- [ ] изменяемость;
- [ ] диапазон допустимых значений;
- [ ] взаимосвязь с другими полями;
- [ ] ограничения использования;
- [ ] степень подтверждения семантики.
#### Журнал исследования
---
# 5. Исследование информационных фактов
- [ ] какие информационные факты содержит сообщение;
- [ ] какие информационные факты могут быть вычислены непосредственно из сообщения;
- [ ] какие информационные факты отсутствуют;
- [ ] какие информационные факты являются первичными;
- [ ] какие информационные факты являются производными.
#### Журнал исследования
---
## 5.1 Первичные информационные факты
- [ ] источник происхождения;
- [ ] поле сообщения;
- [ ] степень подтверждения;
- [ ] ограничения использования.
#### Журнал исследования
---
## 5.2 Производные информационные факты
- [ ] формула вычисления;
- [ ] необходимые исходные данные;
- [ ] ограничения вычисления;
- [ ] степень достоверности.
#### Журнал исследования
---
# 6. Исследование поведения потока
## 6.1 Частота сообщений
- [ ] минимальная частота;
- [ ] максимальная частота;
- [ ] средняя частота;
- [ ] пиковая частота;
- [ ] условия изменения частоты.
#### Журнал исследования
---
## 6.2 Последовательность сообщений
- [ ] порядок поступления сообщений;
- [ ] последовательность timestamp;
- [ ] наличие пропусков;
- [ ] наличие повторяющихся сообщений;
- [ ] возможность нарушения порядка.
#### Журнал исследования
---
## 6.3 Полнота сообщений
- [ ] полный снимок состояния;
- [ ] инкрементальные изменения;
- [ ] смешанный режим передачи;
- [ ] обязательность всех полей;
- [ ] возможность частичных обновлений.
#### Журнал исследования
---
# 7. Исследование поведения данных
- [ ] условия появления;
- [ ] условия изменения;
- [ ] условия исчезновения;
- [ ] частота изменения;
- [ ] взаимосвязь с другими фактами.
---
## Дополнительно определить
- [ ] какие факты изменяются одновременно;
- [ ] какие факты никогда не изменяются одновременно;
- [ ] какие факты являются независимыми;
- [ ] какие факты являются производными от других.
#### Журнал исследования
---
# 8. Проверка эквивалентности
- [ ] существует ли аналогичный источник;
- [ ] полностью ли совпадает значение;
- [ ] совпадает ли семантика;
- [ ] совпадает ли точность;
- [ ] совпадает ли момент обновления;
- [ ] имеются ли расхождения.
#### Журнал исследования
---
## 8.1 Альтернативные источники
- [ ] REST endpoint;
- [ ] WebSocket Request;
- [ ] другие Stream;
- [ ] внутренние вычисления.
#### Журнал исследования
---
## 8.2 Приоритет источников
- [ ] основной источник;
- [ ] резервный источник;
- [ ] допустимые альтернативы;
- [ ] причины выбора приоритетного источника.
#### Журнал исследования
---
# 9. Исследование производительности
- [ ] средний размер сообщения;
- [ ] максимальный размер сообщения;
- [ ] средняя скорость передачи;
- [ ] максимальная скорость передачи;
- [ ] объём данных в минуту;
- [ ] объём данных в час.
#### Журнал исследования

View File

@@ -0,0 +1,46 @@
### 1.1.4 Дополнительные требования клиента
- [x] обязательный формат сообщений — частично соответствует документации;
- [ ] поддержание соединения;
- [x] heartbeat / keepalive / ping-pong — определено экспериментально;
- [ ] автоматическое закрытие соединения;
- [ ] idle timeout;
- [ ] требования к кодировке;
- [ ] другие обязательные требования.
#### Журнал исследования
**Обязательный формат сообщений**
Документация указывает формат payload (json):
```
{
"symbols": [
"string"
]
}
```
Фактический формат сообщения через WebSocket /connect:
```
{
"correlationId": "...",
"destination": "marketData.subscribe",
"payload": {
"symbols": ["BTC/USD_LEVERAGE"]
}
}
```
**Поддержание соединения**
Документация требований не содержит.
За время наблюдения получены сообщения только следующих типов:
- `marketData.subscribe`
- `internal.quote`
Специальные сообщения heartbeat / keepalive / ping / pong не обнаружены.

View File

@@ -0,0 +1,269 @@
# Dzengi API Endpoint Research — marketData.subscribe
## Контроль документа
| Свойство | Значение |
|----------|----------|
| Документ | Dzengi API Endpoint Research — marketData.subscribe |
| Тип документа | Endpoint Research |
| Версия | 1.0 |
| Статус | Draft |
| Степень верификации | Runtime Research |
| Проект | Dzentra |
| Подсистема | Market Intelligence |
| Источник | Dzengi API |
| Endpoint | `marketData.subscribe` |
| Транспорт | WebSocket Stream |
| Язык | Русский |
---
## Статус документа
Настоящий документ содержит результаты исследования endpoint `marketData.subscribe`, выполненного посредством анализа официальной документации Dzengi и фактических сообщений, полученных от биржи.
Документ предназначен для определения информационных сущностей, передаваемых данным endpoint, без интерпретации состояния рынка.
---
## Цель исследования
Цель настоящего исследования — определить:
- назначение endpoint;
- структуру протокола обмена сообщениями;
- типы сообщений;
- семантику сообщений;
- информационные сущности, содержащиеся в сообщениях;
- особенности поведения потока данных;
- взаимосвязь с другими endpoint API Dzengi.
---
## Основной вопрос исследования
> **Какую информацию о состоянии рынка предоставляет поток `marketData.subscribe`?**
---
## Источники исследования
Исследование основано на:
- официальной документации Dzengi;
- OpenAPI (Swagger);
- официальных примерах сообщений;
- фактических сообщениях, полученных посредством Dzengi API Probe.
---
# 1. Назначение endpoint
## Описание документации
Согласно документации Dzengi, endpoint `marketData.subscribe` предназначен для получения потока рыночных котировок выбранных торговых инструментов.
---
## Назначение по результатам исследования
Исследование подтверждает, что `marketData.subscribe` является командой подписки на поток рыночных котировок.
После успешного выполнения подписки биржа начинает передавать поток сообщений с актуальными котировками выбранных инструментов.
Сам endpoint не является типом рыночного сообщения.
---
# 2. Способ получения данных
| Свойство | Значение |
|----------|----------|
| Транспорт | WebSocket Stream |
| Тип взаимодействия | Подписка |
| Endpoint | `marketData.subscribe` |
| Формат сообщений | JSON |
---
# 3. Параметры подписки
| Параметр | Тип | Обязательный | Назначение |
|----------|-----|--------------|------------|
| symbols | array | Да | Список торговых инструментов |
---
# 4. Протокол взаимодействия
Исследование показало, что взаимодействие состоит из двух независимых этапов.
```text
Клиент
│ marketData.subscribe
Биржа
│ Subscription confirmation
Биржа
│ internal.quote
│ internal.quote
│ internal.quote
Клиент
```
Команда `marketData.subscribe` используется исключительно для оформления подписки.
Информация о состоянии рынка передается сообщениями другого типа — `internal.quote`.
---
# 5. Типы сообщений
## 5.1 Subscription confirmation
### Назначение
Подтверждение успешного оформления подписки.
### Пример сообщения
```json
{
"correlationId": "probe-market-data-subscribe",
"destination": "marketData.subscribe",
"payload": {
"subscriptions": {
"BTC/USD_LEVERAGE": "PROCESSED"
}
},
"status": "OK"
}
```
### Семантика
Сообщение подтверждает регистрацию подписки.
Рыночной информации не содержит.
---
## 5.2 Quote update (`internal.quote`)
### Назначение
Передача актуальных рыночных котировок.
### Пример сообщения
```json
{
"destination": "internal.quote",
"payload": {
"bid": 62055.80,
"bidQty": 5.0,
"ofr": 62055.90,
"ofrQty": 5.0,
"symbolName": "BTC/USD_LEVERAGE",
"timestamp": 1783537924352
},
"status": "OK"
}
```
---
# 6. Анализ структуры сообщения
| Поле | Тип | Изменяется | Назначение | Статус |
|------|-----|------------|------------|--------|
| bid | Number | Да | Лучшая цена покупки | Подтверждено |
| bidQty | Number | Да | Объем на лучшей цене покупки | Предварительно подтверждено |
| ofr | Number | Да | Лучшая цена продажи | Подтверждено |
| ofrQty | Number | Да | Объем на лучшей цене продажи | Предварительно подтверждено |
| symbolName | String | Нет | Торговый инструмент | Подтверждено |
| timestamp | Long | Да | Время формирования сообщения биржей | Подтверждено |
---
# 7. Информационные сущности, извлекаемые из сообщений
| Information ID | Источник (JSON Path) | Статус |
|----------------|----------------------|--------|
| best_bid_price | `payload.bid` | Подтверждено |
| best_bid_quantity | `payload.bidQty` | Предварительно подтверждено |
| best_ask_price | `payload.ofr` | Подтверждено |
| best_ask_quantity | `payload.ofrQty` | Предварительно подтверждено |
| instrument_symbol | `payload.symbolName` | Подтверждено |
| quote_timestamp | `payload.timestamp` | Подтверждено |
---
# 8. Поведение потока
## Подтвержденные наблюдения
- Подписка выполняется один раз.
- После подтверждения подписки биржа начинает передавать поток сообщений `internal.quote`.
- Каждое сообщение содержит полный набор исследованных полей.
- Сообщения поступают только при изменении котировки.
- Каждое сообщение относится к одному торговому инструменту.
---
## Требует дополнительного исследования
- Всегда ли `bidQty` соответствует объему первого уровня стакана.
- Всегда ли `ofrQty` соответствует объему первого уровня стакана.
- Возможны ли сообщения без изменения цены.
- Возможны ли сообщения с одинаковым `timestamp`.
---
# 9. Связь с другими endpoint
| Потенциальная информационная сущность | Endpoint | Поле | Статус |
|--------------------------------------|----------|------|--------|
| best_bid_price | REST `/api/v1/depth` | `bids[0][0]` | Подтверждено |
| best_bid_price | WSS `/api/v1/depth` | `payload.bids[0][0]` | Подтверждено |
| best_bid_price | `marketData.subscribe` | `payload.bid` | Подтверждено |
| best_ask_price | REST `/api/v1/depth` | `asks[0][0]` | Подтверждено |
| best_ask_price | WSS `/api/v1/depth` | `payload.asks[0][0]` | Подтверждено |
| best_ask_price | `marketData.subscribe` | `payload.ofr` | Подтверждено |
| best_bid_price | REST `/api/v1/ticker/24hr` | `bidPrice` | Требует исследования |
| best_ask_price | REST `/api/v1/ticker/24hr` | `askPrice` | Требует исследования |
---
# 10. Итоги исследования
По результатам исследования подтверждено, что endpoint `marketData.subscribe` не является источником отдельных запросов к бирже, а представляет собой механизм подписки на поток рыночных котировок.
Фактическая рыночная информация передается сообщениями типа `internal.quote`.
Исследование также подтвердило эквивалентность информационных сущностей `best_bid_price` и `best_ask_price`, получаемых посредством `marketData.subscribe`, REST `/api/v1/depth` и WSS `/api/v1/depth`.
Эквивалентность соответствующих полей endpoint `/api/v1/ticker/24hr` на момент подготовки настоящей редакции документа не подтверждена.
---
# 11. Связь с архитектурой Dzentra
Результаты настоящего исследования используются при формировании:
- Dzengi Market Intelligence Information Mapping;
- Dzentra Market Intelligence Information Model;
- Dzentra Market Knowledge Catalogue.
Настоящий документ не определяет:
- знания о рынке;
- интерпретацию состояния рынка;
- алгоритмы анализа;
- торговые стратегии;
- архитектуру Engine.