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,325 @@
# Build 001 — Внутренняя модель Instrument Reference Data
**Проект:** Dzentra
**Подсистема:** Market Data Acquisition
**Миграция:** Instrument Reference Data
**Статус:** ✅ Завершён
**Дата:** 2026-07-10
---
# Цель Build
Создать независимую внутреннюю модель Instrument Reference Data.
На данном этапе запрещается:
- изменять ExchangeService;
- изменять существующий runtime;
- менять Telegram UI;
- менять Symbol Validation;
- подключать новую модель к production-коду.
Build создаёт исключительно новую внутреннюю модель, которая станет целевой моделью для последующего mapper.
---
# Причина выполнения Build
В утверждённой архитектуре Dzentra модель предметной области должна существовать отдельно от:
- REST API Dzengi;
- parser;
- mapper;
- ExchangeService;
- Telegram UI;
- runtime.
Поэтому сначала создаётся независимая модель Instrument, а только затем будут строиться parser и mapper.
---
# Проанализированные файлы
В ходе Build были полностью проанализированы:
```text
app/src/integrations/exchange/service.py
app/src/integrations/exchange/models.py
app/src/integrations/exchange/symbol_utils.py
app/src/integrations/exchange/rest_client.py
app/src/integrations/exchange/status.py
app/src/telegram/ui/currency_ui.py
docs/stages/stage-03_3-exchange_info.md
docs/decisions/0007-symbol-validation.md
```
Также были проанализированы:
- сохранённый runtime-ответ `/exchangeInfo`;
- OpenAPI Dzengi;
- все текущие потребители ExchangeSymbol;
- результаты grep по всему проекту.
---
# Основные выводы анализа
Установлено:
- ExchangeSymbol создаётся только в одном месте;
- parser и mapper сейчас объединены внутри ExchangeService;
- SymbolValidationResult используется только ExchangeService;
- normalize_symbol() и symbol_candidates() централизованы;
- отдельного parser ещё не существует;
- отдельного mapper ещё не существует;
- кэш справочника представляет собой неуправляемый singleton без TTL.
Также подтверждено:
- новый Build не должен менять существующий ExchangeService;
- новая модель не должна зависеть от Telegram UI;
- runtime-статусы не являются частью Instrument Reference Data.
---
# Анализ реального ответа exchangeInfo
Подтверждено наличие следующих полей:
Обязательные:
- symbol
- name
- status
- baseAsset
- quoteAsset
- marketModes
- marketType
- tickSize
Через filters:
- stepSize
- minQty
- maxQty
- minNotional
Также обнаружены дополнительные справочные поля:
- assetType
- orderTypes
- baseAssetPrecision
- quotePrecision
- tickValue
- country
- sector
- industry
- tradingHours
---
# Принятые архитектурные решения
## Новая модель не копирует ExchangeSymbol
Новая модель является самостоятельной внутренней моделью предметной области.
---
## Runtime не входит в Instrument
Из модели исключены:
- title
- message
- ui_line
- reason
- is_open
- is_available
- is_auth_ok
Эти поля относятся к Runtime Status.
---
## Использование Decimal
Для следующих значений принято использовать Decimal:
- tick_size
- tick_value
- step_size
- min_qty
- max_qty
- min_notional
Причина:
данные используются при нормализации цен и количества и не должны терять точность.
Поскольку модель пока нигде не используется, изменение не влияет на работающего бота.
Классификация:
**Улучшение надёжности.**
---
## Не включены в Instrument
Сознательно исключены:
- trading_fee
- long_rate
- short_rate
- swap_charge_interval
- min_sl_gap
- max_sl_gap
- min_tp_gap
- max_tp_gap
Причина:
данные относятся к другим предметным подсистемам.
---
# Созданные файлы
Создан:
```text
app/src/market_data/acquisition/models/instrument.py
```
Создан:
```text
app/tests/unit/market_data/acquisition/models/test_instrument.py
```
Другие production-файлы не изменялись.
---
# Проверки
Выполнены проверки.
## Unit Test новой модели
Статус:
✅ Passed
```
4 passed
```
---
## Импорт модели
Проверено:
- импорт проходит;
- dataclass создаётся;
- Decimal работает;
- tuple работают.
Статус:
✅ Passed
---
## Компиляция
Проверено:
```
python -m py_compile
```
Статус:
✅ Passed
---
## Legacy Compatibility
Проверено:
- ExchangeSymbol
- SymbolValidationResult
- ExchangeService
- normalize_symbol()
- symbol_candidates()
Статус:
✅ Полностью совместимо.
---
## Проверка отсутствия подключения новой модели
Подтверждено:
новая модель используется исключительно в unit-тестах.
Production-код её не импортирует.
Статус:
✅ Passed
---
## Полный набор тестов
Выполнено:
```
python -m pytest -q
```
Результат:
```
5 passed
```
Статус:
✅ Passed
---
# Итог Build
Build 001 завершён успешно.
Подтверждено:
- создана независимая модель Instrument;
- модель не зависит от legacy-кода;
- обратная совместимость полностью сохранена;
- работающий бот не изменён;
- новая архитектура готова к реализации Build 002.
---
# Следующий Build
Build 002
**Dzengi Raw Models**
Следующий этап создаст модели сырого ответа REST API Dzengi.
На этом этапе ExchangeService по-прежнему изменяться не будет.