Files
dzentra_bot/docs/migrations/build_002.md

8.3 KiB
Raw Blame History

Build 002 — Raw Models Dzengi exchangeInfo

Проект: Dzentra
Подсистема: Market Data Acquisition
Миграция: Instrument Reference Data
Статус: Завершён
Дата: 2026-07-10


Цель Build

Создать транспортные модели (Raw Models), полностью описывающие ответ REST API Dzengi exchangeInfo.

На данном этапе запрещалось:

  • изменять ExchangeService;
  • изменять ExchangeSymbol;
  • изменять SymbolValidationResult;
  • изменять runtime;
  • изменять Telegram UI;
  • выполнять parser JSON;
  • выполнять mapper в предметную модель Instrument.

Build создаёт исключительно транспортный контракт между REST API и будущим parser.


Причина выполнения Build

После Build 001 уже существует независимая предметная модель:

Instrument

Следующим архитектурным слоем является транспортная модель адаптера.

До начала Build 002 существующая реализация выглядела следующим образом:

REST
    ↓
dict
    ↓
ExchangeService
    ↓
ExchangeSymbol

Parser и mapper были объединены внутри ExchangeService.

Это нарушало принцип разделения ответственности.

После Build 002 появилась отдельная транспортная модель:

REST
    ↓
Raw Models

которая станет входом для parser в следующем Build.


Проанализированные материалы

Перед реализацией были полностью проанализированы:

app/tools/dzengi_probe/runtime_samples/rest/exchangeInfo/all.json
docs/market_intelligence/information/dzengi_openapi.json

Также были повторно использованы результаты анализа:

app/src/integrations/exchange/service.py
app/src/integrations/exchange/models.py

и результаты grep по использованию ExchangeSymbol.


Основные выводы анализа

Подтверждено:

реальный ответ API значительно богаче текущей модели ExchangeSymbol.

В ответе присутствуют:

  • symbol
  • name
  • status
  • assetType
  • baseAsset
  • baseAssetPrecision
  • quoteAsset
  • quoteAssetId
  • quotePrecision
  • orderTypes
  • marketModes
  • marketType
  • country
  • sector
  • industry
  • tradingHours
  • tickSize
  • tickValue
  • tradingFee
  • exchangeFee
  • longRate
  • shortRate
  • swapChargeInterval
  • minSLGap
  • maxSLGap
  • minTPGap
  • maxTPGap
  • filters
  • rateLimits
  • exchangeFilters

Часть этих данных ранее полностью терялась.


Принятые архитектурные решения

1. Raw Models полностью отделены от предметной модели

Созданы транспортные модели.

Они:

  • ничего не вычисляют;
  • ничего не нормализуют;
  • ничего не валидируют.

Они только описывают транспортный контракт.


2. Поддержка двух форматов ответа API

Поддерживаются оба варианта:

Wrapped

status
correlationId
payload

и

Unwrapped

timezone
serverTime
symbols

Parser следующего Build сможет привести оба формата к единому контракту.

Классификация:

Улучшение надёжности.


3. Decimal сознательно не используется

Raw Models сохраняют транспортный тип.

Например:

"stepSize": "0.001"

остаётся строкой.

Преобразование в Decimal является обязанностью mapper.


4. Filters представлены отдельной иерархией

Созданы:

DzengiLotSizeFilter
DzengiMinNotionalFilter
DzengiUnknownFilter

Неизвестные фильтры не приводят к ошибке.

Они сохраняются для дальнейшего анализа.

Классификация:

Улучшение надёжности.


5. Все коллекции являются immutable

Используются:

tuple

вместо

list

Причина:

Raw Models являются снимком транспортного ответа.

Их нельзя изменять после создания.


6. Все Raw Models являются immutable

Все dataclass объявлены как:

@dataclass(frozen=True, slots=True)

Это гарантирует неизменяемость транспортного контракта.


Созданные файлы

Создан:

app/src/market_data/acquisition/adapters/dzengi/models.py

Создан:

app/tests/unit/market_data/acquisition/adapters/dzengi/test_models.py

Другие production-файлы не изменялись.


Проверки

Выполнены все проверки Build.


Unit Test

Статус:

Passed

6 passed

Импорт полной транспортной модели

Проверено:

  • импортируются все классы;
  • создаётся полная иерархия объектов;
  • вложенные dataclass работают корректно.

Статус:

Passed


Компиляция

Проверено:

python -m py_compile

Статус:

Passed


Проверка отсутствия использования в production

Подтверждено:

Raw Models используются только:

src/market_data/acquisition/adapters/dzengi/models.py

tests/unit/market_data/acquisition/adapters/dzengi/test_models.py

ExchangeService их не использует.

Parser их ещё не использует.

Mapper их ещё не использует.

Статус:

Passed


Полный набор тестов

Выполнено:

python -m pytest -q

Результат:

11 passed

Статус:

Passed


Архитектурный результат

После Build 002 структура подсистемы стала выглядеть следующим образом:

Dzengi REST API
        │
        ▼
Raw Models

Следующие слои пока отсутствуют:

Parser
Mapper
Instrument
Handler
Feed
Service

Именно это соответствует утверждённому плану миграции.


Обратная совместимость

Полностью сохранена.

Не изменены:

  • ExchangeService
  • ExchangeSymbol
  • SymbolValidationResult
  • validate_symbol()
  • normalize_symbol()
  • symbol_candidates()
  • Runtime
  • Telegram UI

Новые Raw Models пока не подключены к работающему боту.


Итог Build

Build 002 завершён успешно.

Получен полноценный транспортный контракт REST API Dzengi.

Создан фундамент для следующих этапов миграции.

Работающий бот не изменил своего поведения.


Следующий Build

Build 003 — Структурная валидация exchangeInfo

Следующий этап реализует parser, который будет преобразовывать сырой JSON REST API в созданные транспортные модели.

На Build 003 по-прежнему:

  • ExchangeService изменяться не будет;
  • предметная модель Instrument использоваться не будет;
  • parser останется полностью независимым от бизнес-логики.