Stage 03.1 - mock exchange integration

This commit is contained in:
2026-04-13 22:54:01 +03:00
parent aa21342116
commit 9166022b3c
11 changed files with 421 additions and 17 deletions

View File

@@ -0,0 +1 @@
"""Exchange integration package."""

View File

@@ -0,0 +1,37 @@
from __future__ import annotations
from datetime import datetime, timezone
from src.integrations.exchange.models import BalanceSummary, ExchangeHealth, TickerPrice
def mock_exchange_health() -> ExchangeHealth:
return ExchangeHealth(
ok=True,
mode="mock",
message="Биржа работает в mock mode. Реальный API пока не подключен.",
)
def mock_ticker_price(symbol: str) -> TickerPrice:
symbol = symbol.upper().strip()
fake_prices = {
"BTCUSDT": 68425.10,
"ETHUSDT": 3521.44,
"BNBUSDT": 612.33,
}
price = fake_prices.get(symbol, 100.00)
updated_at = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S UTC")
return TickerPrice(
symbol=symbol,
price=price,
source="mock",
updated_at=updated_at,
)
def mock_balance_summary() -> list[BalanceSummary]:
return [
BalanceSummary(currency="USDT", available=1500.00, locked=0.0, source="mock"),
BalanceSummary(currency="BTC", available=0.025, locked=0.0, source="mock"),
]

View File

@@ -0,0 +1,26 @@
from __future__ import annotations
from dataclasses import dataclass
@dataclass(slots=True)
class ExchangeHealth:
ok: bool
mode: str
message: str
@dataclass(slots=True)
class TickerPrice:
symbol: str
price: float
source: str
updated_at: str
@dataclass(slots=True)
class BalanceSummary:
currency: str
available: float
locked: float
source: str

View File

@@ -0,0 +1,38 @@
from __future__ import annotations
from src.core.config import load_settings
from src.integrations.exchange.mock_data import (
mock_balance_summary,
mock_exchange_health,
mock_ticker_price,
)
from src.integrations.exchange.models import BalanceSummary, ExchangeHealth, TickerPrice
class ExchangeService:
def __init__(self) -> None:
self.settings = load_settings()
def get_health(self) -> ExchangeHealth:
if not self.settings.exchange_enabled:
return mock_exchange_health()
if not self.settings.exchange_api_key or not self.settings.exchange_api_secret:
return ExchangeHealth(
ok=False,
mode="configured_without_keys",
message="Интеграция включена, но API key / secret не заданы.",
)
return ExchangeHealth(
ok=False,
mode="real_pending",
message="Реальный REST client еще не подключен. Пока доступен только mock mode.",
)
def get_price(self, symbol: str | None = None) -> TickerPrice:
symbol_to_use = symbol or self.settings.default_symbol
return mock_ticker_price(symbol_to_use)
def get_balance_summary(self) -> list[BalanceSummary]:
return mock_balance_summary()