build 049: expose canonical candles through ExchangeService

This commit is contained in:
2026-07-15 20:54:24 +03:00
parent 3a253d89a9
commit 16ed64f7c6
3 changed files with 1010 additions and 7 deletions

View File

@@ -500,15 +500,15 @@ class ExchangeService:
def _runtime_key(self, runtime_key: str | None) -> str:
return (runtime_key or self._default_runtime_key).strip().lower()
# Получить свечи инструмента через канонический Candles Feed.
def get_klines(
# Получить канонические свечи инструмента через Candles Feed.
def get_candles(
self,
symbol: str | None = None,
*,
interval: str = "1m",
limit: int = 200,
price_type: str = "bid",
) -> KlineBatch:
) -> tuple[Candle, ...]:
symbol_to_use = symbol or self.settings.default_symbol
if limit <= 0:
@@ -526,14 +526,16 @@ class ExchangeService:
normalized_price_type = "bid"
if not self.settings.exchange_enabled:
raise ExchangeError("Klines are not available in mock exchange mode.")
raise ExchangeError(
"Candles are not available in mock exchange mode."
)
validation = self.validate_symbol(symbol_to_use)
if not validation.is_valid:
raise ExchangeError(validation.message)
try:
canonical_candles = self._load_candles_via_acquisition(
return self._load_candles_via_acquisition(
symbol=validation.normalized_symbol,
interval=interval,
limit=limit,
@@ -552,13 +554,54 @@ class ExchangeService:
)
raise ExchangeError(str(exc)) from exc
# Сохранить legacy KlineBatch как compatibility-фасад над canonical Candle.
def get_klines(
self,
symbol: str | None = None,
*,
interval: str = "1m",
limit: int = 200,
price_type: str = "bid",
) -> KlineBatch:
symbol_to_use = symbol or self.settings.default_symbol
if not self.settings.exchange_enabled:
raise ExchangeError(
"Klines are not available in mock exchange mode."
)
if limit <= 0:
normalized_limit = 200
elif limit > 200:
normalized_limit = 200
else:
normalized_limit = limit
normalized_price_type = price_type.strip().lower()
if normalized_price_type not in {"bid", "ask"}:
normalized_price_type = "bid"
canonical_candles = self.get_candles(
symbol=symbol_to_use,
interval=interval,
limit=normalized_limit,
price_type=normalized_price_type,
)
candles = [
self._kline_from_candle(candle)
for candle in canonical_candles[-limit:]
for candle in canonical_candles[-normalized_limit:]
]
normalized_symbol = (
canonical_candles[0].symbol
if canonical_candles
else normalize_symbol(symbol_to_use)
)
return KlineBatch(
symbol=validation.normalized_symbol,
symbol=normalized_symbol,
interval=interval,
candles=candles,
source=f"rest_klines:{normalized_price_type}",