build 059.6: map websocket OHLC close events
This commit is contained in:
@@ -14,19 +14,23 @@ from src.market_data.acquisition.adapters.dzengi.models import (
|
||||
DzengiMinNotionalFilter,
|
||||
DzengiRawNumeric,
|
||||
DzengiTicker24hrResponse,
|
||||
DzengiWebSocketOhlcEvent,
|
||||
DzengiWebSocketQuoteResponse,
|
||||
)
|
||||
from src.market_data.acquisition.exceptions import (
|
||||
CandleMappingError,
|
||||
CandleWebSocketMappingError,
|
||||
InstrumentReferenceMappingError,
|
||||
QuoteMappingError,
|
||||
)
|
||||
from src.market_data.acquisition.models.candle import Candle
|
||||
from src.market_data.acquisition.models.candle_close import CandleCloseEvent
|
||||
from src.market_data.acquisition.models.instrument import Instrument
|
||||
from src.market_data.acquisition.models.quote import Quote
|
||||
|
||||
|
||||
_DZENGI_SOURCE_NAME = "dzengi"
|
||||
_DZENGI_WEBSOCKET_OHLC_SOURCE_NAME = "dzengi_websocket_ohlc"
|
||||
|
||||
|
||||
def map_dzengi_symbol_to_instrument(
|
||||
@@ -318,6 +322,104 @@ def map_dzengi_websocket_quote_to_quote(
|
||||
source=_DZENGI_SOURCE_NAME,
|
||||
)
|
||||
|
||||
|
||||
def map_dzengi_websocket_ohlc_to_candle_close_event(
|
||||
event: DzengiWebSocketOhlcEvent,
|
||||
*,
|
||||
received_at: datetime,
|
||||
) -> CandleCloseEvent:
|
||||
"""
|
||||
Преобразовать проверенное Dzengi WebSocket OHLC-событие
|
||||
во внутреннюю модель CandleCloseEvent.
|
||||
|
||||
Функция предполагает, что до mapper уже были выполнены:
|
||||
schema validation, parsing и value validation.
|
||||
"""
|
||||
|
||||
normalized_received_at = _require_websocket_ohlc_aware_datetime(
|
||||
received_at,
|
||||
field_name="received_at",
|
||||
)
|
||||
|
||||
return CandleCloseEvent(
|
||||
symbol=event.symbol.strip(),
|
||||
interval=event.interval,
|
||||
candle_type=event.candle_type,
|
||||
open_time=_websocket_ohlc_timestamp_ms_to_utc_datetime(
|
||||
event.open_time,
|
||||
),
|
||||
received_at=normalized_received_at,
|
||||
open_price=_required_websocket_ohlc_decimal(
|
||||
event.open_price,
|
||||
field_name="open",
|
||||
),
|
||||
high_price=_required_websocket_ohlc_decimal(
|
||||
event.high_price,
|
||||
field_name="high",
|
||||
),
|
||||
low_price=_required_websocket_ohlc_decimal(
|
||||
event.low_price,
|
||||
field_name="low",
|
||||
),
|
||||
close_price=_required_websocket_ohlc_decimal(
|
||||
event.close_price,
|
||||
field_name="close",
|
||||
),
|
||||
source=_DZENGI_WEBSOCKET_OHLC_SOURCE_NAME,
|
||||
)
|
||||
|
||||
|
||||
def _websocket_ohlc_timestamp_ms_to_utc_datetime(
|
||||
value: int,
|
||||
) -> datetime:
|
||||
try:
|
||||
return datetime.fromtimestamp(
|
||||
value / 1000,
|
||||
tz=timezone.utc,
|
||||
)
|
||||
except (OverflowError, OSError, ValueError) as exc:
|
||||
raise CandleWebSocketMappingError(
|
||||
"Поле t WebSocket OHLC-события невозможно "
|
||||
"преобразовать в UTC datetime."
|
||||
) from exc
|
||||
|
||||
|
||||
def _required_websocket_ohlc_decimal(
|
||||
value: DzengiRawNumeric,
|
||||
*,
|
||||
field_name: str,
|
||||
) -> Decimal:
|
||||
try:
|
||||
result = Decimal(str(value))
|
||||
except (InvalidOperation, ValueError) as exc:
|
||||
raise CandleWebSocketMappingError(
|
||||
f"Поле {field_name} WebSocket OHLC-события невозможно "
|
||||
"преобразовать в Decimal."
|
||||
) from exc
|
||||
|
||||
if not result.is_finite():
|
||||
raise CandleWebSocketMappingError(
|
||||
f"Поле {field_name} WebSocket OHLC-события должно быть "
|
||||
"конечным числом."
|
||||
)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def _require_websocket_ohlc_aware_datetime(
|
||||
value: datetime,
|
||||
*,
|
||||
field_name: str,
|
||||
) -> datetime:
|
||||
if value.tzinfo is None or value.utcoffset() is None:
|
||||
raise CandleWebSocketMappingError(
|
||||
f"Поле {field_name} должно содержать "
|
||||
"timezone-aware datetime."
|
||||
)
|
||||
|
||||
return value
|
||||
|
||||
|
||||
def map_dzengi_klines_to_candles(
|
||||
response: DzengiKlinesResponse,
|
||||
*,
|
||||
|
||||
@@ -93,6 +93,12 @@ class CandleWebSocketValueError(MarketDataAcquisitionError):
|
||||
pass
|
||||
|
||||
|
||||
# Ошибка преобразования WebSocket OHLC-события
|
||||
# во внутреннюю модель уведомления о закрытии свечи.
|
||||
class CandleWebSocketMappingError(MarketDataAcquisitionError):
|
||||
pass
|
||||
|
||||
|
||||
# Ошибка преобразования проверенного документа в raw-модели свечей.
|
||||
class CandleParseError(MarketDataAcquisitionError):
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user