999 lines
24 KiB
Markdown
999 lines
24 KiB
Markdown
# 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-подключение.
|
||
``` |