build 039: complete Quotes Feed migration foundation
This commit is contained in:
999
docs/migrations/build_007.md
Normal file
999
docs/migrations/build_007.md
Normal file
@@ -0,0 +1,999 @@
|
||||
# Build 007 — Protocol и Exceptions
|
||||
|
||||
**Статус:** Завершён
|
||||
**Подсистема:** `market_data/acquisition`
|
||||
**Область:** Instrument Reference Data
|
||||
**Тип изменения:** Изолированное расширение новой архитектуры без подключения к production runtime
|
||||
**Результат полного набора тестов:** `113 passed`
|
||||
|
||||
---
|
||||
|
||||
## 1. Цель Build 007
|
||||
|
||||
Цель Build 007 — зафиксировать минимальные публичные контракты взаимодействия между следующими слоями новой подсистемы Instrument Reference Data:
|
||||
|
||||
```text
|
||||
Build 008 — Dzengi REST Adapter
|
||||
Build 009 — Instrument Handler
|
||||
Build 010 — Instrument Feed
|
||||
Build 011 — Registry
|
||||
Build 012 — Acquisition Service
|
||||
```
|
||||
|
||||
Также добавлена специализированная ошибка транспортного уровня для будущего REST adapter.
|
||||
|
||||
После завершения Build 007 архитектурная последовательность выглядит следующим образом:
|
||||
|
||||
```text
|
||||
InstrumentDocumentSource
|
||||
↓
|
||||
InstrumentDocumentHandler
|
||||
↓
|
||||
InstrumentFeedProtocol
|
||||
↓
|
||||
Registry
|
||||
↓
|
||||
Acquisition Service
|
||||
```
|
||||
|
||||
Build 007 не реализует получение или обработку данных и не подключает новую подсистему к существующему `ExchangeService`.
|
||||
|
||||
---
|
||||
|
||||
## 2. Почему Build 007 выполняется именно сейчас
|
||||
|
||||
До начала Build 007 были завершены предыдущие этапы:
|
||||
|
||||
```text
|
||||
Build 001 — внутренняя модель Instrument Reference Data
|
||||
Build 002 — raw-модели ответа Dzengi
|
||||
Build 003 — структурная валидация exchangeInfo
|
||||
Build 004 — parser exchangeInfo
|
||||
Build 005 — value validation
|
||||
Build 006 — mapper Dzengi → Instrument
|
||||
```
|
||||
|
||||
К началу Build 007 уже существовал полный pipeline преобразования заранее полученного JSON-документа:
|
||||
|
||||
```text
|
||||
raw JSON document
|
||||
↓
|
||||
Schema Validation
|
||||
↓
|
||||
Parser
|
||||
↓
|
||||
Dzengi Raw Models
|
||||
↓
|
||||
Value Validation
|
||||
↓
|
||||
Mapper
|
||||
↓
|
||||
tuple[Instrument, ...]
|
||||
```
|
||||
|
||||
Следующие Build должны добавить транспортный источник, handler, feed, registry и acquisition service.
|
||||
|
||||
Перед их реализацией необходимо было определить минимальные интерфейсы взаимодействия между этими слоями и добавить специализированную ошибку транспортного уровня.
|
||||
|
||||
---
|
||||
|
||||
## 3. Архитектурная граница Build 007
|
||||
|
||||
Build 007 отвечает только за:
|
||||
|
||||
```text
|
||||
определение контракта источника сырого документа;
|
||||
определение контракта обработчика сырого документа;
|
||||
определение контракта источника готовых Instrument;
|
||||
добавление ошибки транспортного уровня.
|
||||
```
|
||||
|
||||
Build 007 не выполняет:
|
||||
|
||||
```text
|
||||
HTTP-запросы;
|
||||
получение exchangeInfo;
|
||||
schema validation;
|
||||
parsing;
|
||||
value validation;
|
||||
mapping;
|
||||
создание конкретного Handler;
|
||||
создание конкретного Feed;
|
||||
создание Registry;
|
||||
создание Acquisition Service;
|
||||
кэширование;
|
||||
изменение ExchangeService;
|
||||
изменение runtime;
|
||||
изменение Telegram UI;
|
||||
изменение автоторговли.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Изменённые файлы
|
||||
|
||||
В рамках Build 007 изменены:
|
||||
|
||||
```text
|
||||
app/src/market_data/acquisition/protocol.py
|
||||
app/src/market_data/acquisition/exceptions.py
|
||||
```
|
||||
|
||||
Создан тестовый файл:
|
||||
|
||||
```text
|
||||
app/tests/unit/market_data/acquisition/test_protocol.py
|
||||
```
|
||||
|
||||
Не изменялись:
|
||||
|
||||
```text
|
||||
app/src/market_data/acquisition/adapters/dzengi/rest.py
|
||||
app/src/market_data/acquisition/handlers/instrument_handler.py
|
||||
app/src/market_data/acquisition/feeds/instrument_feed.py
|
||||
app/src/market_data/acquisition/registry.py
|
||||
app/src/market_data/acquisition/service.py
|
||||
|
||||
app/src/market_data/acquisition/adapters/dzengi/models.py
|
||||
app/src/market_data/acquisition/adapters/dzengi/parser.py
|
||||
app/src/market_data/acquisition/adapters/dzengi/mapper.py
|
||||
|
||||
app/src/market_data/acquisition/validation/schema.py
|
||||
app/src/market_data/acquisition/validation/values.py
|
||||
|
||||
app/src/integrations/exchange/*
|
||||
app/src/telegram/*
|
||||
app/src/trading/*
|
||||
```
|
||||
|
||||
Работающий legacy-код бота не изменён.
|
||||
|
||||
---
|
||||
|
||||
## 5. Созданные Protocol
|
||||
|
||||
В файле:
|
||||
|
||||
```text
|
||||
app/src/market_data/acquisition/protocol.py
|
||||
```
|
||||
|
||||
созданы три минимальных протокола:
|
||||
|
||||
```text
|
||||
InstrumentDocumentSource
|
||||
InstrumentDocumentHandler
|
||||
InstrumentFeedProtocol
|
||||
```
|
||||
|
||||
Все протоколы основаны на структурной типизации Python:
|
||||
|
||||
```python
|
||||
typing.Protocol
|
||||
```
|
||||
|
||||
и объявлены как:
|
||||
|
||||
```python
|
||||
@runtime_checkable
|
||||
```
|
||||
|
||||
Это позволяет использовать их как для статической типизации, так и для ограниченной runtime-проверки через `isinstance()`.
|
||||
|
||||
---
|
||||
|
||||
## 6. InstrumentDocumentSource
|
||||
|
||||
Контракт:
|
||||
|
||||
```python
|
||||
@runtime_checkable
|
||||
class InstrumentDocumentSource(Protocol):
|
||||
def fetch_instrument_document(self) -> object:
|
||||
...
|
||||
```
|
||||
|
||||
Назначение:
|
||||
|
||||
```text
|
||||
получить декодированный транспортный документ Instrument Reference Data.
|
||||
```
|
||||
|
||||
Предполагаемый конкретный потребитель этого контракта появится в:
|
||||
|
||||
```text
|
||||
Build 008 — Dzengi REST Adapter
|
||||
```
|
||||
|
||||
Будущий REST adapter должен реализовать метод:
|
||||
|
||||
```python
|
||||
fetch_instrument_document()
|
||||
```
|
||||
|
||||
и вернуть сырой декодированный документ.
|
||||
|
||||
---
|
||||
|
||||
## 7. Почему InstrumentDocumentSource возвращает object
|
||||
|
||||
Возвращаемый тип:
|
||||
|
||||
```python
|
||||
object
|
||||
```
|
||||
|
||||
выбран сознательно.
|
||||
|
||||
Транспортный источник не должен выполнять:
|
||||
|
||||
```text
|
||||
schema validation;
|
||||
parsing;
|
||||
value validation;
|
||||
mapping.
|
||||
```
|
||||
|
||||
На транспортной границе REST adapter может получить произвольное декодированное JSON-значение:
|
||||
|
||||
```text
|
||||
dict
|
||||
list
|
||||
str
|
||||
int
|
||||
float
|
||||
bool
|
||||
None
|
||||
```
|
||||
|
||||
Проверка структуры является обязанностью:
|
||||
|
||||
```text
|
||||
Schema Validation
|
||||
```
|
||||
|
||||
Поэтому транспортный слой не должен преждевременно утверждать, что полученный документ является корректным JSON-объектом нужной структуры.
|
||||
|
||||
Архитектурная граница остаётся следующей:
|
||||
|
||||
```text
|
||||
REST Adapter
|
||||
↓
|
||||
object
|
||||
↓
|
||||
Schema Validation
|
||||
↓
|
||||
ValidatedExchangeInfoDocument
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. InstrumentDocumentHandler
|
||||
|
||||
Контракт:
|
||||
|
||||
```python
|
||||
@runtime_checkable
|
||||
class InstrumentDocumentHandler(Protocol):
|
||||
def handle_instrument_document(
|
||||
self,
|
||||
document: object,
|
||||
) -> tuple[Instrument, ...]:
|
||||
...
|
||||
```
|
||||
|
||||
Назначение:
|
||||
|
||||
```text
|
||||
преобразовать сырой документ в проверенные внутренние модели Instrument.
|
||||
```
|
||||
|
||||
Конкретная реализация появится в:
|
||||
|
||||
```text
|
||||
Build 009 — Instrument Handler
|
||||
```
|
||||
|
||||
Handler должен объединить уже существующий pipeline:
|
||||
|
||||
```text
|
||||
object
|
||||
↓
|
||||
validate_exchange_info_schema()
|
||||
↓
|
||||
ValidatedExchangeInfoDocument
|
||||
↓
|
||||
parse_exchange_info()
|
||||
↓
|
||||
DzengiExchangeInfoResponse
|
||||
↓
|
||||
validate_exchange_info_values()
|
||||
↓
|
||||
map_dzengi_exchange_info_to_instruments()
|
||||
↓
|
||||
tuple[Instrument, ...]
|
||||
```
|
||||
|
||||
При этом Protocol не знает:
|
||||
|
||||
```text
|
||||
какая биржа является источником;
|
||||
какой parser используется;
|
||||
какой mapper используется;
|
||||
какие source-specific raw-модели существуют.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. InstrumentFeedProtocol
|
||||
|
||||
Контракт:
|
||||
|
||||
```python
|
||||
@runtime_checkable
|
||||
class InstrumentFeedProtocol(Protocol):
|
||||
def load_instruments(self) -> tuple[Instrument, ...]:
|
||||
...
|
||||
```
|
||||
|
||||
Назначение:
|
||||
|
||||
```text
|
||||
получить полный immutable-набор внутренних моделей Instrument.
|
||||
```
|
||||
|
||||
Конкретный Feed появится в:
|
||||
|
||||
```text
|
||||
Build 010 — Instrument Feed
|
||||
```
|
||||
|
||||
Предполагаемая композиция:
|
||||
|
||||
```text
|
||||
InstrumentFeed
|
||||
├── InstrumentDocumentSource
|
||||
└── InstrumentDocumentHandler
|
||||
```
|
||||
|
||||
Рабочая последовательность:
|
||||
|
||||
```text
|
||||
InstrumentFeed.load_instruments()
|
||||
↓
|
||||
InstrumentDocumentSource.fetch_instrument_document()
|
||||
↓
|
||||
object
|
||||
↓
|
||||
InstrumentDocumentHandler.handle_instrument_document()
|
||||
↓
|
||||
tuple[Instrument, ...]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. Почему протокол называется InstrumentFeedProtocol
|
||||
|
||||
Будущий файл:
|
||||
|
||||
```text
|
||||
app/src/market_data/acquisition/feeds/instrument_feed.py
|
||||
```
|
||||
|
||||
предназначен для конкретной реализации Feed.
|
||||
|
||||
Чтобы избежать конфликта между интерфейсом и конкретным классом, протокол получил имя:
|
||||
|
||||
```text
|
||||
InstrumentFeedProtocol
|
||||
```
|
||||
|
||||
Конкретная реализация в Build 010 сможет называться:
|
||||
|
||||
```text
|
||||
InstrumentFeed
|
||||
```
|
||||
|
||||
Таким образом:
|
||||
|
||||
```text
|
||||
InstrumentFeedProtocol
|
||||
контракт
|
||||
|
||||
InstrumentFeed
|
||||
конкретная реализация
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 11. Structural Typing
|
||||
|
||||
Реализации не обязаны наследоваться от Protocol напрямую.
|
||||
|
||||
Например:
|
||||
|
||||
```python
|
||||
class StubInstrumentDocumentSource:
|
||||
def fetch_instrument_document(self) -> object:
|
||||
return {
|
||||
"symbols": [],
|
||||
}
|
||||
```
|
||||
|
||||
Такой объект удовлетворяет контракту:
|
||||
|
||||
```text
|
||||
InstrumentDocumentSource
|
||||
```
|
||||
|
||||
без явного наследования:
|
||||
|
||||
```python
|
||||
class StubInstrumentDocumentSource(InstrumentDocumentSource):
|
||||
...
|
||||
```
|
||||
|
||||
Это уменьшает связанность между конкретными реализациями и интерфейсами.
|
||||
|
||||
---
|
||||
|
||||
## 12. Runtime Checkable
|
||||
|
||||
Все три Protocol объявлены с:
|
||||
|
||||
```python
|
||||
@runtime_checkable
|
||||
```
|
||||
|
||||
Благодаря этому допустима проверка:
|
||||
|
||||
```python
|
||||
isinstance(source, InstrumentDocumentSource)
|
||||
```
|
||||
|
||||
Тестами подтверждено:
|
||||
|
||||
```text
|
||||
объект с требуемым методом
|
||||
→ соответствует Protocol
|
||||
|
||||
объект без требуемого метода
|
||||
→ не соответствует Protocol
|
||||
```
|
||||
|
||||
Важно: runtime-проверка Protocol подтверждает структурное наличие требуемых атрибутов и методов, но не выполняет полную глубокую проверку всех аннотаций типов и фактических возвращаемых значений.
|
||||
|
||||
---
|
||||
|
||||
## 13. Новая транспортная ошибка
|
||||
|
||||
В файл:
|
||||
|
||||
```text
|
||||
app/src/market_data/acquisition/exceptions.py
|
||||
```
|
||||
|
||||
добавлена:
|
||||
|
||||
```python
|
||||
class InstrumentReferenceTransportError(
|
||||
MarketDataAcquisitionError
|
||||
):
|
||||
pass
|
||||
```
|
||||
|
||||
Она предназначена для будущего:
|
||||
|
||||
```text
|
||||
Build 008 — Dzengi REST Adapter
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 14. Назначение InstrumentReferenceTransportError
|
||||
|
||||
Ошибка предназначена для проблем получения Instrument Reference Data от внешнего источника.
|
||||
|
||||
Потенциальные случаи:
|
||||
|
||||
```text
|
||||
ошибка соединения;
|
||||
timeout;
|
||||
HTTP error;
|
||||
ошибка JSON decoding;
|
||||
непредвиденная ошибка REST-клиента.
|
||||
```
|
||||
|
||||
Она не используется для:
|
||||
|
||||
```text
|
||||
неверной структуры документа;
|
||||
ошибки parsing;
|
||||
недопустимых значений;
|
||||
ошибки mapping.
|
||||
```
|
||||
|
||||
Эти случаи уже имеют специализированные типы исключений.
|
||||
|
||||
---
|
||||
|
||||
## 15. Итоговая иерархия ошибок
|
||||
|
||||
После Build 007 иерархия выглядит следующим образом:
|
||||
|
||||
```text
|
||||
MarketDataAcquisitionError
|
||||
├── InstrumentReferenceTransportError
|
||||
├── InstrumentReferenceSchemaError
|
||||
├── InstrumentReferenceParseError
|
||||
├── InstrumentReferenceValueError
|
||||
└── InstrumentReferenceMappingError
|
||||
```
|
||||
|
||||
Назначение ошибок:
|
||||
|
||||
| Ошибка | Ответственность |
|
||||
|---|---|
|
||||
| `InstrumentReferenceTransportError` | Получение данных от внешнего источника |
|
||||
| `InstrumentReferenceSchemaError` | Структура исходного документа |
|
||||
| `InstrumentReferenceParseError` | Преобразование проверенного документа в raw-модели |
|
||||
| `InstrumentReferenceValueError` | Допустимость значений |
|
||||
| `InstrumentReferenceMappingError` | Преобразование raw-модели во внутреннюю модель `Instrument` |
|
||||
|
||||
---
|
||||
|
||||
## 16. Какие дополнительные Protocol не создавались
|
||||
|
||||
В Build 007 сознательно не создавались отдельные Protocol для:
|
||||
|
||||
```text
|
||||
Schema Validator
|
||||
Parser
|
||||
Value Validator
|
||||
Mapper
|
||||
Registry
|
||||
Acquisition Service
|
||||
```
|
||||
|
||||
Причины:
|
||||
|
||||
```text
|
||||
validators, parser и mapper уже реализованы как чистые функции;
|
||||
|
||||
Registry и Acquisition Service пока не имеют нескольких реализаций;
|
||||
|
||||
дополнительные интерфейсы сейчас не используются;
|
||||
|
||||
создание таких контрактов было бы преждевременной абстракцией.
|
||||
```
|
||||
|
||||
Это соответствует принципу:
|
||||
|
||||
```text
|
||||
не создавать абстракции «на будущее» без конкретного потребителя.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 17. Какие дополнительные Exceptions не создавались
|
||||
|
||||
В Build 007 сознательно не добавлялись:
|
||||
|
||||
```text
|
||||
InstrumentReferenceHandlerError
|
||||
InstrumentReferenceFeedError
|
||||
InstrumentReferenceRegistryError
|
||||
InstrumentReferenceServiceError
|
||||
```
|
||||
|
||||
Причины:
|
||||
|
||||
```text
|
||||
Handler может передавать точные ошибки Schema, Parser, Value и Mapping;
|
||||
|
||||
Feed может передавать точные ошибки Transport и Processing;
|
||||
|
||||
Registry ещё не реализован;
|
||||
|
||||
Acquisition Service ещё не реализован;
|
||||
|
||||
новые типы ошибок следует вводить только там, где появляется реальная новая категория отказа.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 18. Реализованные тестовые сценарии
|
||||
|
||||
Создан файл:
|
||||
|
||||
```text
|
||||
app/tests/unit/market_data/acquisition/test_protocol.py
|
||||
```
|
||||
|
||||
Реализовано 7 тестов.
|
||||
|
||||
Проверены:
|
||||
|
||||
1. соответствие корректного source объекта `InstrumentDocumentSource`;
|
||||
2. соответствие корректного handler объекта `InstrumentDocumentHandler`;
|
||||
3. соответствие корректного feed объекта `InstrumentFeedProtocol`;
|
||||
4. отклонение объектов без обязательных методов;
|
||||
5. structural typing без явного наследования;
|
||||
6. наследование `InstrumentReferenceTransportError` от `MarketDataAcquisitionError`;
|
||||
7. наличие общего базового типа у всех ошибок Instrument Reference Data.
|
||||
|
||||
---
|
||||
|
||||
## 19. Выполненные проверки
|
||||
|
||||
### Проверка 1 — unit-тесты Protocol и Exceptions
|
||||
|
||||
Команда:
|
||||
|
||||
```bash
|
||||
python -m pytest \
|
||||
tests/unit/market_data/acquisition/test_protocol.py \
|
||||
-q
|
||||
```
|
||||
|
||||
Результат:
|
||||
|
||||
```text
|
||||
....... [100%]
|
||||
7 passed in 0.01s
|
||||
```
|
||||
|
||||
Статус:
|
||||
|
||||
```text
|
||||
PASSED
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Проверка 2 — Python compilation
|
||||
|
||||
Команда:
|
||||
|
||||
```bash
|
||||
python -m py_compile \
|
||||
src/market_data/acquisition/protocol.py \
|
||||
src/market_data/acquisition/exceptions.py \
|
||||
tests/unit/market_data/acquisition/test_protocol.py
|
||||
```
|
||||
|
||||
Результат:
|
||||
|
||||
```text
|
||||
Команда завершилась без ошибок и без вывода.
|
||||
```
|
||||
|
||||
Статус:
|
||||
|
||||
```text
|
||||
PASSED
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Проверка 3 — полный набор тестов проекта
|
||||
|
||||
Команда:
|
||||
|
||||
```bash
|
||||
python -m pytest -q
|
||||
```
|
||||
|
||||
Результат:
|
||||
|
||||
```text
|
||||
................................................................................................................. [100%]
|
||||
113 passed in 0.06s
|
||||
```
|
||||
|
||||
Статус:
|
||||
|
||||
```text
|
||||
PASSED
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Проверка 4 — отсутствие преждевременной production-интеграции
|
||||
|
||||
Команда:
|
||||
|
||||
```bash
|
||||
grep -RIn \
|
||||
--exclude-dir="__pycache__" \
|
||||
--exclude="*.pyc" \
|
||||
-E "InstrumentDocumentSource|InstrumentDocumentHandler|InstrumentFeedProtocol|InstrumentReferenceTransportError" \
|
||||
src tests
|
||||
```
|
||||
|
||||
Подтверждено:
|
||||
|
||||
```text
|
||||
InstrumentDocumentSource
|
||||
используется только в protocol.py и unit-тестах
|
||||
|
||||
InstrumentDocumentHandler
|
||||
используется только в protocol.py и unit-тестах
|
||||
|
||||
InstrumentFeedProtocol
|
||||
используется только в protocol.py и unit-тестах
|
||||
|
||||
InstrumentReferenceTransportError
|
||||
объявлена в exceptions.py и используется только в unit-тестах
|
||||
```
|
||||
|
||||
Не обнаружено подключения к:
|
||||
|
||||
```text
|
||||
src/integrations/exchange/*
|
||||
src/telegram/*
|
||||
src/trading/*
|
||||
```
|
||||
|
||||
Статус:
|
||||
|
||||
```text
|
||||
PASSED
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 20. Архитектура после Build 007
|
||||
|
||||
После завершения Build 007 новая часть подсистемы имеет следующую структуру:
|
||||
|
||||
```text
|
||||
market_data/
|
||||
└── acquisition/
|
||||
├── exceptions.py
|
||||
│ ├── MarketDataAcquisitionError
|
||||
│ ├── InstrumentReferenceTransportError
|
||||
│ ├── InstrumentReferenceSchemaError
|
||||
│ ├── InstrumentReferenceParseError
|
||||
│ ├── InstrumentReferenceValueError
|
||||
│ └── InstrumentReferenceMappingError
|
||||
│
|
||||
├── protocol.py
|
||||
│ ├── InstrumentDocumentSource
|
||||
│ ├── InstrumentDocumentHandler
|
||||
│ └── InstrumentFeedProtocol
|
||||
│
|
||||
├── models/
|
||||
│ └── instrument.py
|
||||
│ └── Instrument
|
||||
│
|
||||
├── validation/
|
||||
│ ├── schema.py
|
||||
│ └── values.py
|
||||
│
|
||||
└── adapters/
|
||||
└── dzengi/
|
||||
├── models.py
|
||||
├── parser.py
|
||||
├── mapper.py
|
||||
└── rest.py
|
||||
```
|
||||
|
||||
На текущем этапе:
|
||||
|
||||
```text
|
||||
rest.py
|
||||
ещё не реализован
|
||||
|
||||
instrument_handler.py
|
||||
ещё не реализован
|
||||
|
||||
instrument_feed.py
|
||||
ещё не реализован
|
||||
|
||||
registry.py
|
||||
ещё не реализован
|
||||
|
||||
service.py
|
||||
ещё не реализован
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 21. Полная архитектурная цепочка после Build 007
|
||||
|
||||
Уже реализовано:
|
||||
|
||||
```text
|
||||
raw JSON document
|
||||
↓
|
||||
validate_exchange_info_schema()
|
||||
↓
|
||||
ValidatedExchangeInfoDocument
|
||||
↓
|
||||
parse_exchange_info()
|
||||
↓
|
||||
DzengiExchangeInfoResponse
|
||||
↓
|
||||
validate_exchange_info_values()
|
||||
↓
|
||||
map_dzengi_exchange_info_to_instruments()
|
||||
↓
|
||||
tuple[Instrument, ...]
|
||||
```
|
||||
|
||||
Зафиксированы контракты для будущей orchestration-цепочки:
|
||||
|
||||
```text
|
||||
InstrumentDocumentSource
|
||||
↓
|
||||
InstrumentDocumentHandler
|
||||
↓
|
||||
InstrumentFeedProtocol
|
||||
↓
|
||||
Registry
|
||||
↓
|
||||
Acquisition Service
|
||||
```
|
||||
|
||||
После реализации Build 008–012 предполагаемая полная цепочка будет выглядеть так:
|
||||
|
||||
```text
|
||||
Dzengi REST API
|
||||
↓
|
||||
Dzengi REST Adapter
|
||||
implements InstrumentDocumentSource
|
||||
↓
|
||||
object
|
||||
↓
|
||||
Instrument Handler
|
||||
implements InstrumentDocumentHandler
|
||||
↓
|
||||
tuple[Instrument, ...]
|
||||
↓
|
||||
Instrument Feed
|
||||
implements InstrumentFeedProtocol
|
||||
↓
|
||||
Registry
|
||||
↓
|
||||
Acquisition Service
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 22. Влияние на legacy-систему
|
||||
|
||||
Build 007 не подключён к существующим компонентам:
|
||||
|
||||
```text
|
||||
ExchangeService
|
||||
ExchangeSymbol
|
||||
SymbolValidationResult
|
||||
Telegram UI
|
||||
AutoTrade
|
||||
Market Stream
|
||||
Market Data Runner
|
||||
Execution Quality
|
||||
```
|
||||
|
||||
Не изменены:
|
||||
|
||||
```text
|
||||
ExchangeService.get_exchange_symbols()
|
||||
ExchangeService.validate_symbol()
|
||||
ExchangeService.get_symbol_runtime_status()
|
||||
normalize_symbol()
|
||||
symbol_candidates()
|
||||
```
|
||||
|
||||
Старый production-путь продолжает работать без изменений.
|
||||
|
||||
Новая подсистема развивается параллельно.
|
||||
|
||||
---
|
||||
|
||||
## 23. Обратная совместимость
|
||||
|
||||
Подтверждено сохранение:
|
||||
|
||||
```text
|
||||
сигнатур существующих методов;
|
||||
старых импортов;
|
||||
существующего формата ошибок;
|
||||
Telegram UI;
|
||||
автоторговли;
|
||||
runtime-поведения;
|
||||
legacy ExchangeSymbol;
|
||||
legacy-кэша.
|
||||
```
|
||||
|
||||
Build 007 имеет полную обратную совместимость.
|
||||
|
||||
---
|
||||
|
||||
## 24. Классификация изменений
|
||||
|
||||
| Изменение | Классификация |
|
||||
|---|---|
|
||||
| `InstrumentDocumentSource` | Обязательное архитектурное изменение |
|
||||
| `InstrumentDocumentHandler` | Обязательное архитектурное изменение |
|
||||
| `InstrumentFeedProtocol` | Обязательное архитектурное изменение |
|
||||
| `InstrumentReferenceTransportError` | Обязательное архитектурное изменение |
|
||||
| Structural typing | Улучшение архитектурной независимости |
|
||||
| `runtime_checkable` | Улучшение тестируемости и проверяемости контрактов |
|
||||
| Дополнительные преждевременные Protocol | Не создавались |
|
||||
| Дополнительные преждевременные Exceptions | Не создавались |
|
||||
| Изменение production-поведения | Отсутствует |
|
||||
|
||||
---
|
||||
|
||||
## 25. Итог Build 007
|
||||
|
||||
Build 007 завершён успешно.
|
||||
|
||||
Реализовано:
|
||||
|
||||
```text
|
||||
InstrumentDocumentSource
|
||||
InstrumentDocumentHandler
|
||||
InstrumentFeedProtocol
|
||||
InstrumentReferenceTransportError
|
||||
```
|
||||
|
||||
Подтверждено:
|
||||
|
||||
```text
|
||||
7 protocol tests passed
|
||||
113 total project tests passed
|
||||
Python compilation passed
|
||||
No production integration detected
|
||||
Legacy bot behavior unchanged
|
||||
```
|
||||
|
||||
Итоговый статус:
|
||||
|
||||
```text
|
||||
BUILD 007 — COMPLETE
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 26. Следующий этап
|
||||
|
||||
Следующий этап утверждённого плана:
|
||||
|
||||
```text
|
||||
Build 008 — Dzengi REST Adapter
|
||||
```
|
||||
|
||||
Его задача — реализовать конкретный транспортный источник, соответствующий контракту:
|
||||
|
||||
```text
|
||||
InstrumentDocumentSource
|
||||
```
|
||||
|
||||
Будущая граница Build 008:
|
||||
|
||||
```text
|
||||
Dzengi REST API
|
||||
↓
|
||||
Dzengi REST Adapter
|
||||
↓
|
||||
object
|
||||
```
|
||||
|
||||
Build 008 не должен выполнять:
|
||||
|
||||
```text
|
||||
schema validation;
|
||||
parsing;
|
||||
value validation;
|
||||
mapping;
|
||||
создание Instrument;
|
||||
создание Handler;
|
||||
создание Feed;
|
||||
создание Registry;
|
||||
создание Acquisition Service;
|
||||
изменение ExchangeService;
|
||||
production-подключение.
|
||||
```
|
||||
Reference in New Issue
Block a user