# 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 по-прежнему изменяться не будет.