Build 060.11: add WebSocket Trade Parser

This commit is contained in:
2026-07-19 17:51:47 +03:00
parent 034f5984ca
commit d3f8680921
3 changed files with 1348 additions and 0 deletions

View File

@@ -22,6 +22,7 @@ from src.market_data.acquisition.adapters.dzengi.models import (
DzengiTicker24hrResponse,
DzengiWebSocketOhlcEvent,
DzengiWebSocketQuoteResponse,
DzengiWebSocketTradeEvent,
)
from src.market_data.acquisition.exceptions import (
CandleParseError,
@@ -37,6 +38,7 @@ from src.market_data.acquisition.validation.schema import (
ValidatedRestAggTradesDocument,
ValidatedWebSocketOhlcDocument,
ValidatedWebSocketQuoteDocument,
ValidatedWebSocketTradeDocument,
)
@@ -820,6 +822,110 @@ def _websocket_ohlc_required_raw_numeric(
return value
# Преобразовать структурно проверенное событие WebSocket Trade
# в транспортную модель адаптера Dzengi.
def parse_dzengi_websocket_trade(
document: ValidatedWebSocketTradeDocument,
) -> DzengiWebSocketTradeEvent:
"""
Преобразовать проверенный payload события ``internal.trade``
в transport-модель Dzengi.
Функция не выполняет предметную проверку значений, не проверяет
допустимость цены, размера сделки или timestamp, не интерпретирует
сторону сделки и не выполняет mapping во внутреннюю модель Dzentra.
"""
payload = document.payload
return DzengiWebSocketTradeEvent(
trade_id=_websocket_trade_required_int(
payload.get("id"),
path="$.payload.id",
),
price=_websocket_trade_required_raw_numeric(
payload.get("price"),
path="$.payload.price",
),
size=_websocket_trade_required_raw_numeric(
payload.get("size"),
path="$.payload.size",
),
timestamp=_websocket_trade_required_int(
payload.get("ts"),
path="$.payload.ts",
),
symbol=_websocket_trade_required_string(
payload.get("symbol"),
path="$.payload.symbol",
),
buyer=_websocket_trade_required_bool(
payload.get("buyer"),
path="$.payload.buyer",
),
order_id=_websocket_trade_required_string(
payload.get("orderId"),
path="$.payload.orderId",
),
)
def _websocket_trade_required_string(
value: object,
*,
path: str,
) -> str:
if not isinstance(value, str):
raise TradeParseError(
f"{path} должен быть строкой, "
f"получен {type(value).__name__}."
)
return value
def _websocket_trade_required_int(
value: object,
*,
path: str,
) -> int:
if isinstance(value, bool) or not isinstance(value, int):
raise TradeParseError(
f"{path} должен быть целым числом, "
f"получен {type(value).__name__}."
)
return value
def _websocket_trade_required_bool(
value: object,
*,
path: str,
) -> bool:
if not isinstance(value, bool):
raise TradeParseError(
f"{path} должен быть булевым значением, "
f"получен {type(value).__name__}."
)
return value
def _websocket_trade_required_raw_numeric(
value: object,
*,
path: str,
) -> DzengiRawNumeric:
if isinstance(value, bool) or not isinstance(value, (str, int, float)):
raise TradeParseError(
f"{path} должен быть строкой или числом, "
f"получен {type(value).__name__}."
)
return value
# Преобразовать структурно проверенный ответ klines в raw-модели Dzengi.
def parse_candles(
document: ValidatedCandlesDocument,