# Build 060.12 — WebSocket Trade Value Validation **Engineering Migration Report** --- # Контроль документа | Свойство | Значение | |----------|----------| | Build | 060.12 | | Название | WebSocket Trade Value Validation | | Статус | Completed | | Проект | Dzentra | | Подсистема | Market Data Acquisition | | Компонент | Trades Feed | | Версия | 1.0 | --- # Цель Build После завершения Build 060.11 система получила полностью реализованный уровень **WebSocket Trade Parser**, преобразующий структурно корректный документ ```text ValidatedWebSocketTradeDocument ``` в транспортную модель ```text DzengiWebSocketTradeEvent ``` Parser гарантирует корректное построение транспортного объекта и минимальную проверку типов, необходимую для создания модели. Однако после завершения Parsing транспортная модель ещё не может считаться пригодной для дальнейшего использования в системе. Несмотря на корректность структуры и типов, отдельные значения транспортной модели могут оставаться недопустимыми с точки зрения предметной области. Например: - цена сделки может быть равна нулю; - объём сделки может быть отрицательным; - timestamp может иметь недопустимое значение; - идентификатор сделки может отсутствовать либо быть неположительным; - строковые поля могут содержать только пробельные символы; - числовые значения могут содержать `NaN` или бесконечность. Подобные ошибки уже не относятся к структуре документа и не должны обрабатываться Parser. Для их обработки в архитектуре Dzentra предусмотрен отдельный уровень Pipeline — **Value Validation**. Build 060.12 реализует данный уровень для WebSocket Trade. Основная задача Build — проверить корректность содержимого транспортной модели без выполнения каких-либо преобразований данных и без создания новых объектов. Данный Build ограничивается исключительно проверкой значений транспортной модели и не затрагивает: - Schema Validation; - Parser; - Mapper; - Runtime; - Routing; - Trades Feed. --- # Предпосылки К началу Build архитектура подсистемы Market Data Acquisition уже содержала полноценный конвейер обработки транспортных моделей Quote, OHLC и REST Trade. Для каждого из них использовалось одинаковое разделение ответственности между уровнями Pipeline. Общая последовательность обработки выглядела следующим образом. ```text Raw Source │ ▼ Schema Validation │ ▼ Transport Model │ ▼ Value Validation │ ▼ Mapper │ ▼ Domain Model ``` После завершения Build 060.11 аналогичный транспортный уровень появился и для WebSocket Trade. ```text ValidatedWebSocketTradeDocument │ ▼ Trade Parser │ ▼ DzengiWebSocketTradeEvent ``` Однако следующий обязательный этап — проверка корректности самих значений транспортной модели — ещё отсутствовал. Таким образом WebSocket-конвейер обработки сделок оставался архитектурно незавершённым. --- # Архитектурное основание Одним из базовых принципов архитектуры Dzentra является строгое разделение ответственности между последовательными уровнями Pipeline. Каждый уровень отвечает только за одну категорию задач. Для WebSocket Trade это разделение выглядит следующим образом. ```text Schema Validation ``` отвечает исключительно за проверку структуры документа. Она гарантирует: - наличие транспортной оболочки; - наличие объекта `payload`; - присутствие обязательных полей; - соответствие ожидаемым типам транспортного документа. Следующий уровень — ```text Parser ``` выполняет транспортное преобразование. Он: - извлекает значения из `payload`; - переименовывает транспортные поля; - создаёт immutable transport model. После этого ответственность Parser полностью заканчивается. Проверка корректности самих значений транспортной модели относится уже к следующему уровню — ```text Value Validation ``` Именно Value Validation отвечает за проверку предметной допустимости данных. На данном уровне анализируются: - допустимость числовых значений; - диапазоны значений; - корректность строковых идентификаторов; - невозможность использования специальных числовых значений (`NaN`, `Infinity`); - другие ограничения транспортного контракта. При этом Value Validation принципиально **не выполняет**: - преобразование типов; - Mapping; - создание модели `Trade`; - бизнес-логику; - обработку Runtime. Такое разделение позволяет каждому уровню Pipeline оставаться независимым и легко тестируемым. --- # Результаты архитектурного аудита Перед реализацией Build был выполнен аудит существующей подсистемы проверки значений. В ходе анализа подтверждено наличие следующих компонентов. Для Quote уже реализованы: ```text validate_dzengi_websocket_quote_values(...) ``` Для OHLC реализованы: ```text validate_dzengi_websocket_ohlc_values(...) ``` Для REST Trade реализованы: ```text validate_rest_agg_trade_values(...) ``` Также подтверждено существование общего набора вспомогательных функций проверки: ```text _trade_positive_int(...) _trade_positive_decimal(...) ``` Указанные helper-функции уже используются существующей реализацией REST Trade и полностью соответствуют требованиям нового Build. Одновременно аудит подтвердил отсутствие отдельной проверки значений транспортной модели ```text DzengiWebSocketTradeEvent ``` Таким образом единственным отсутствующим элементом архитектурной цепочки являлся собственный уровень Value Validation для WebSocket Trade. Build 060.12 полностью закрывает данный пробел и завершает ещё один архитектурный уровень серии Build 060. --- # Архитектурное решение По итогам проведённого аудита было принято решение не создавать новую модель данных и не вводить дополнительный слой между Parser и Mapper. Вместо этого реализован тот же архитектурный шаблон, который уже используется для Quote, OHLC и REST Trade. В систему добавлена функция ```text validate_dzengi_websocket_trade_values(...) ``` которая принимает ```text DzengiWebSocketTradeEvent ``` и выполняет проверку корректности значений транспортной модели. При успешном завершении проверки объект не изменяется и продолжает использоваться последующими этапами Pipeline. Таким образом транспортная модель проходит дополнительный уровень контроля без создания промежуточных объектов и без нарушения существующей архитектуры. Конвейер WebSocket Trade принимает следующий вид. ```text Raw WebSocket Object │ ▼ WebSocket Trade Schema Validation │ ▼ ValidatedWebSocketTradeDocument │ ▼ WebSocket Trade Parser │ ▼ DzengiWebSocketTradeEvent │ ▼ WebSocket Trade Value Validation │ ▼ DzengiWebSocketTradeEvent ``` Build 060.12 не изменяет архитектуру ранее реализованных компонентов и лишь завершает следующий обязательный уровень транспортного Pipeline. # Реализованный уровень Value Validation В файл ```text src/market_data/acquisition/validation/values.py ``` добавлена новая функция ```text validate_dzengi_websocket_trade_values(...) ``` Функция получает транспортную модель ```text DzengiWebSocketTradeEvent ``` и подтверждает корректность всех значений, необходимых для последующего Mapping. После успешного завершения проверки функция не изменяет объект и не создаёт новую транспортную модель. Таким образом следующий уровень Pipeline получает тот же экземпляр ```text DzengiWebSocketTradeEvent ``` который ранее был создан Parser. --- # Почему Value Validation не создаёт новую модель Во время архитектурного проектирования отдельно рассматривался вопрос о необходимости введения дополнительной модели ```text ValidatedTradeTransportEvent ``` которая могла бы использоваться после проверки значений. По результатам анализа было принято решение отказаться от подобного решения. Основные причины: - транспортная модель уже является immutable; - проверка значений не изменяет содержимое объекта; - повторное создание объекта не приносит дополнительных архитектурных преимуществ; - аналогичный подход уже используется для Quote, OHLC и REST Trade. В результате Value Validation подтверждает корректность существующего объекта и не создаёт новый экземпляр. Подобное решение уменьшает количество транспортных моделей в системе и делает Pipeline более простым без потери архитектурной строгости. --- # Проверяемая транспортная модель Проверка выполняется над объектом ```python @dataclass(frozen=True, slots=True) class DzengiWebSocketTradeEvent: trade_id: int price: DzengiRawNumeric size: DzengiRawNumeric timestamp: int symbol: str buyer: bool order_id: str ``` Value Validation рассматривает данный объект исключительно как транспортную модель. Никаких преобразований типов при этом не выполняется. --- # Проверка идентификатора сделки Поле ```text trade_id ``` обязательно должно содержать положительный целочисленный идентификатор сделки. Во время проверки подтверждается: - значение является целым числом; - значение больше нуля. При нарушении любого условия генерируется ```text TradeValueError ``` с указанием пути ```text $.payload.id ``` --- # Проверка цены сделки Поле ```text price ``` может поступать в различных транспортных представлениях. Например: ```text "63992.50" 63992 63992.50 ``` Во время проверки подтверждается: - возможность корректного преобразования в Decimal; - отсутствие NaN; - отсутствие Infinity; - значение больше нуля. При этом сама транспортная модель не изменяется. Строковое значение остаётся строковым. Преобразование в Decimal будет выполняться только на этапе Mapper. --- # Проверка объёма сделки Поле ```text size ``` проверяется аналогично цене. Подтверждается: - корректность числового представления; - отсутствие специальных значений; - положительное значение. При нарушении любого ограничения генерируется ```text TradeValueError ``` с указанием пути ```text $.payload.size ``` --- # Проверка временной метки Поле ```text timestamp ``` должно содержать положительное целое число. Value Validation подтверждает: - корректность типа; - значение больше нуля. Следует отметить, что Build 060.12 **не анализирует**, соответствует ли timestamp реальному времени. Подобные проверки относятся уже к предметной области и могут появиться на более высоких уровнях системы. --- # Проверка символа Поле ```text symbol ``` обязательно должно содержать непустую строку. Проверяется результат после применения ```python strip() ``` Таким образом значения ```text "" " " "\t" "\n" ``` считаются недопустимыми. --- # Проверка идентификатора ордера Аналогичная проверка выполняется для поля ```text order_id ``` После удаления пробельных символов строка должна оставаться непустой. В противном случае генерируется ```text TradeValueError ``` --- # Почему поле buyer не проверяется Во время архитектурного аудита отдельно анализировался вопрос дополнительной проверки поля ```text buyer ``` Было принято решение не выполнять каких-либо дополнительных ограничений. Причины следующие. Parser уже гарантирует: ```text bool ``` В транспортном контракте биржи оба значения ```text True False ``` являются допустимыми. Следовательно Value Validation не содержит никакой дополнительной логики для данного поля. Это полностью соответствует принципу разделения ответственности между Parser и Value Validation. --- # Повторное использование существующих helper-функций Build 060.12 не вводит новых механизмов проверки числовых значений. Вместо этого используются уже существующие функции проекта. ```text _trade_positive_int(...) ``` используется для проверки: - trade_id; - timestamp. --- ```text _trade_positive_decimal(...) ``` используется для проверки: - price; - size. Подобный подход обеспечивает единое поведение всех механизмов проверки Trade независимо от источника получения данных. --- # Использование TradeValueError Все ошибки проверки значений используют существующее исключение ```text TradeValueError ``` Build не вводит новых типов исключений. Это сохраняет единую архитектуру обработки ошибок Trade. Parser продолжает использовать ```text TradeParseError ``` а Value Validation использует исключительно ```text TradeValueError ``` Тем самым достигается чёткое разделение транспортных ошибок и ошибок корректности данных. --- # Изменённые файлы В рамках Build были изменены только два файла. ## Value Validation ```text src/market_data/acquisition/validation/values.py ``` Добавлена функция ```text validate_dzengi_websocket_trade_values(...) ``` Существующая логика проверки Quote, OHLC и REST Trade не изменялась. --- ## Unit-тесты ```text tests/unit/market_data/acquisition/validation/test_websocket_trade_values.py ``` Добавлен полный набор unit-тестов нового уровня Value Validation. --- # Добавленные тесты В рамках Build реализовано сорок семь unit-тестов, полностью покрывающих новую функциональность. ## Проверка корректных событий Подтверждается успешное прохождение проверки полностью корректной транспортной модели. --- ## Проверка buyer Подтверждается корректная работа для обоих допустимых значений: - `True`; - `False`. --- ## Проверка различных представлений чисел Отдельная серия тестов подтверждает корректную обработку: - строк; - целых чисел; - чисел с плавающей точкой. для полей: - price; - size. --- ## Проверка неположительных значений Реализованы параметризованные тесты для: - trade_id; - timestamp; - price; - size. Подтверждается генерация ```text TradeValueError ``` при попытке использования нуля либо отрицательных значений. --- ## Проверка специальных числовых значений Отдельная группа тестов подтверждает отклонение: ```text NaN Infinity -Infinity ``` как в строковом виде, так и после передачи соответствующих значений типа float. --- ## Проверка некорректных строк Реализованы проверки для значений: ```text "" "invalid" "--1" ``` Подтверждается корректная генерация исключений. --- ## Проверка строковых полей Отдельные тесты подтверждают отклонение пустых либо содержащих только пробельные символы значений: - symbol; - order_id. --- ## Проверка неизменяемости транспортной модели Отдельный тест подтверждает, что после успешной проверки объект ```text DzengiWebSocketTradeEvent ``` остаётся полностью неизменным. Value Validation не модифицирует транспортную модель. # Результаты тестирования После завершения реализации выполнен целевой запуск нового набора unit-тестов. ```bash python -m pytest \ tests/unit/market_data/acquisition/validation/test_websocket_trade_values.py \ -q ``` Результат: ```text 47 passed in 0.05s ``` Все проверки новой функциональности успешно завершены. Новый набор тестов полностью покрывает: - успешную проверку корректной транспортной модели; - обработку допустимых представлений числовых значений; - генерацию исключений для всех типов некорректных данных; - неизменяемость транспортной модели после успешной проверки. Параметризованные тесты позволили существенно сократить объём тестового кода без уменьшения покрытия и обеспечили единообразную проверку всех допустимых и недопустимых вариантов входных данных. --- # Регрессионное тестирование После завершения реализации выполнен полный запуск набора unit-тестов проекта. ```bash python -m pytest -q ``` Результат: ```text 1208 passed in 2.70s ``` Регрессий существующей функциональности не обнаружено. Все ранее реализованные Build продолжают работать без каких-либо изменений. Это подтверждает, что добавленная функциональность полностью изолирована и не влияет на существующие конвейеры обработки Quote, OHLC, REST Trade и остальные подсистемы проекта. --- # Проверка компиляции После завершения реализации выполнена полная проверка компиляции проекта. ```bash python -m compileall src tests ``` Компиляция завершилась успешно. Ошибок синтаксиса не обнаружено. Все изменённые файлы успешно компилируются и не нарушают целостность проекта. --- # Проверка Git diff После устранения замечаний форматирования выполнена финальная проверка изменений. ```bash git diff --check ``` Результат: ```text без замечаний ``` Проверка подтвердила отсутствие: - trailing whitespace; - ошибок окончания строк; - конфликтов diff; - нарушений форматирования. --- # Scope Build 060.12 В рамках данного Build реализован исключительно уровень ```text WebSocket Trade Value Validation ``` Build **не включает**: - WebSocket Trade Schema Validation; - WebSocket Trade Parser; - WebSocket Trade Mapper; - WebSocket Trade Adapter; - Runtime Integration; - Unified Routing; - Trades Feed. Подобное ограничение полностью соответствует принятому принципу атомарной реализации Build. Каждый этап дорожной карты реализует только один архитектурный уровень Pipeline. --- # Архитектурный результат После завершения Build система содержит полностью реализованные уровни транспортной обработки WebSocket Trade вплоть до проверки значений. Конвейер обработки принимает следующий вид. ```text Raw WebSocket Trade │ ▼ WebSocket Trade Schema Validation │ ▼ ValidatedWebSocketTradeDocument │ ▼ WebSocket Trade Parser │ ▼ DzengiWebSocketTradeEvent │ ▼ WebSocket Trade Value Validation │ ▼ DzengiWebSocketTradeEvent ``` Таким образом архитектура WebSocket Trade полностью повторяет ранее реализованные конвейеры Quote и OHLC. Каждый уровень Pipeline выполняет исключительно собственную задачу. --- # Состояние WebSocket Trade Pipeline После завершения Build 060.12 конвейер имеет следующий вид. ```text Raw WebSocket Trade │ ▼ ValidatedWebSocketTradeDocument │ ▼ DzengiWebSocketTradeEvent │ ▼ Value Validation │ ▼ Mapper │ ▼ Trade ``` Статус реализации компонентов: | Компонент | Build | Статус | |-----------|-------|--------| | Canonical Trade Model | 060.1 | ✔ Completed | | WebSocket Trade Transport Model | 060.9 | ✔ Completed | | WebSocket Trade Schema Validation | 060.10 | ✔ Completed | | WebSocket Trade Parser | 060.11 | ✔ Completed | | WebSocket Trade Value Validation | 060.12 | ✔ Completed | | WebSocket Trade Mapper | 060.13 | Pending | | WebSocket Trade Adapter | 060.14 | Pending | | Unified WebSocket Routing | 060.15 | Pending | --- # Соблюдение архитектурных принципов В рамках Build полностью сохранены архитектурные инварианты Dzentra. ## Локальность изменений Изменены только: - `validation/values.py`; - unit-тесты нового уровня Value Validation. Существующая логика Quote, OHLC и REST Trade не изменялась. --- ## Повторное использование архитектуры Новая реализация полностью повторяет существующий архитектурный шаблон проверки значений. Новая архитектура не проектировалась. Использован уже существующий подход, применяемый для остальных типов рыночных данных. --- ## Повторное использование инфраструктуры Для проверки числовых значений повторно использованы существующие helper-функции проекта. Build не вводит новых механизмов проверки и не дублирует уже реализованную функциональность. Это обеспечивает единообразие поведения всех уровней Value Validation. --- ## Разделение ответственности Value Validation отвечает исключительно за проверку корректности значений транспортной модели. Build не выполняет: - преобразование транспортных данных; - Mapping; - создание модели Trade; - Runtime Integration; - бизнес-логику. Все перечисленные задачи остаются ответственностью последующих Build. --- ## Обратная совместимость Существующая обработка: - Quote; - OHLC; - REST Trade; не изменилась. Добавленная функциональность полностью изолирована и не оказывает влияния на ранее реализованные компоненты системы. --- # Архитектурные решения Build (ADR) ## ADR-060.12-001 **Value Validation не создаёт новую транспортную модель.** После успешной проверки используется тот же экземпляр `DzengiWebSocketTradeEvent`, который ранее был создан Parser. Создание дополнительной модели признано избыточным и не дающим архитектурных преимуществ. --- ## ADR-060.12-002 **Value Validation не выполняет преобразование типов.** Проверка подтверждает только допустимость значений. Преобразование транспортных представлений (`str`, `int`, `float`) во внутренние типы (`Decimal`, `datetime` и другие) остаётся ответственностью Mapper. --- ## ADR-060.12-003 **Повторное использование существующих helper-функций является обязательным архитектурным принципом.** Для проверки числовых значений используются существующие функции: ```text _trade_positive_int() _trade_positive_decimal() ``` Создание новых helper-функций признано необоснованным. --- ## ADR-060.12-004 **Parser и Value Validation используют разные классы исключений.** Parser отвечает за транспортное преобразование и использует: ```text TradeParseError ``` Value Validation отвечает исключительно за корректность значений и использует: ```text TradeValueError ``` Подобное разделение обеспечивает прозрачную классификацию ошибок Pipeline. --- # Критерии завершения Build Build 060.12 считается завершённым, поскольку выполнены все поставленные задачи. - ✔ реализована функция `validate_dzengi_websocket_trade_values()`; - ✔ реализована проверка всех обязательных полей транспортной модели; - ✔ реализована проверка положительных числовых значений; - ✔ реализована проверка конечности числовых значений; - ✔ реализована проверка строковых идентификаторов; - ✔ повторно использованы существующие helper-функции; - ✔ используются существующие исключения `TradeValueError`; - ✔ транспортная модель остаётся неизменяемой; - ✔ реализовано 47 unit-тестов; - ✔ целевой набор тестов успешно проходит; - ✔ полное регрессионное тестирование успешно завершено; - ✔ проект успешно компилируется; - ✔ `git diff --check` не выявил замечаний; - ✔ изменения полностью укладываются в согласованный scope Build. --- # Следующий этап Следующим этапом дорожной карты является ```text Build 060.13 — WebSocket Trade Mapper ``` Цель следующего Build: - преобразование `DzengiWebSocketTradeEvent` в каноническую модель `Trade`; - преобразование транспортных числовых значений во внутренние типы; - формирование окончательной модели предметной области; - завершение транспортного конвейера обработки WebSocket Trade. --- # Итог Build 060.12 завершил реализацию уровня **Value Validation** для WebSocket Trade и сделал архитектуру транспортной обработки сделок полностью симметричной существующим конвейерам Quote, OHLC и REST Trade. Новая реализация основана на уже существующих архитектурных принципах Dzentra, повторно использует существующую инфраструктуру проверки значений, не создаёт дополнительных транспортных моделей и сохраняет строгое разделение ответственности между уровнями Pipeline. Build ограничен согласованным scope, успешно прошёл целевое и полное регрессионное тестирование, подтвердил отсутствие регрессий и создаёт необходимую основу для следующего этапа дорожной карты — **Build 060.13 — WebSocket Trade Mapper**.