Stage 07.4.4.1.14 — Execution refactoring and runtime semantics
This commit is contained in:
@@ -48,8 +48,9 @@ class Settings:
|
||||
db_user: str
|
||||
db_password: str
|
||||
|
||||
# Debag helper
|
||||
# Debug helpers
|
||||
debug_enabled: bool
|
||||
journal_debug_enabled: bool
|
||||
|
||||
# helper: demo/live mode
|
||||
def is_demo_mode(self) -> bool:
|
||||
@@ -91,6 +92,9 @@ def load_settings() -> Settings:
|
||||
log_level=os.getenv("LOG_LEVEL", "INFO").strip().upper() or "INFO",
|
||||
tz=os.getenv("TZ", "Europe/Minsk").strip() or "Europe/Minsk",
|
||||
debug_enabled=_parse_bool(os.getenv("DEBUG_ENABLED", "false")),
|
||||
journal_debug_enabled=_parse_bool(
|
||||
os.getenv("JOURNAL_DEBUG_ENABLED", "false")
|
||||
),
|
||||
|
||||
# Exchange
|
||||
exchange_enabled=_parse_bool(os.getenv("EXCHANGE_ENABLED", "false")),
|
||||
@@ -101,8 +105,8 @@ def load_settings() -> Settings:
|
||||
exchange_api_secret=os.getenv("EXCHANGE_API_SECRET", "").strip(),
|
||||
exchange_timeout_sec=_parse_int(os.getenv("EXCHANGE_TIMEOUT_SEC", "10"), 10),
|
||||
exchange_testnet=_parse_bool(os.getenv("EXCHANGE_TESTNET", "false")),
|
||||
default_symbol=os.getenv("DEFAULT_SYMBOL", "BTC/USD_LEVERAGE").strip()
|
||||
or "BTC/USD_LEVERAGE",
|
||||
default_symbol=os.getenv("DEFAULT_SYMBOL", "ETH/USD_LEVERAGE").strip()
|
||||
or "ETH/USD_LEVERAGE",
|
||||
|
||||
# Database
|
||||
db_host=os.getenv("DB_HOST", "localhost").strip() or "localhost",
|
||||
|
||||
@@ -9,6 +9,8 @@ class EventBus:
|
||||
_version: int = 0
|
||||
_last_event_type: str | None = None
|
||||
_last_payload: dict[str, Any] = {}
|
||||
_events: list[tuple[int, str, dict[str, Any]]] = []
|
||||
_max_events: int = 100
|
||||
|
||||
# зафиксировать важное событие системы
|
||||
@classmethod
|
||||
@@ -17,6 +19,17 @@ class EventBus:
|
||||
cls._last_event_type = event_type
|
||||
cls._last_payload = payload or {}
|
||||
|
||||
cls._events.append(
|
||||
(
|
||||
cls._version,
|
||||
event_type,
|
||||
dict(cls._last_payload),
|
||||
)
|
||||
)
|
||||
|
||||
if len(cls._events) > cls._max_events:
|
||||
cls._events = cls._events[-cls._max_events:]
|
||||
|
||||
# текущая версия событий
|
||||
@classmethod
|
||||
def version(cls) -> int:
|
||||
@@ -25,4 +38,13 @@ class EventBus:
|
||||
# последнее событие
|
||||
@classmethod
|
||||
def last_event(cls) -> tuple[str | None, dict[str, Any]]:
|
||||
return cls._last_event_type, dict(cls._last_payload)
|
||||
return cls._last_event_type, dict(cls._last_payload)
|
||||
|
||||
# события после указанной версии
|
||||
@classmethod
|
||||
def events_after(cls, version: int) -> list[tuple[int, str, dict[str, Any]]]:
|
||||
return [
|
||||
(event_version, event_type, dict(payload))
|
||||
for event_version, event_type, payload in cls._events
|
||||
if event_version > version
|
||||
]
|
||||
@@ -55,6 +55,7 @@ EVENT_TITLES = {
|
||||
"journal_export_xlsx_success": "Журнал",
|
||||
"journal_export_xlsx_error": "Журнал",
|
||||
"journal_cleared_old": "Журнал",
|
||||
"journal_debug_changed": "Журнал",
|
||||
|
||||
"system_open_requested": "Система",
|
||||
"system_open_alert": "Система",
|
||||
@@ -84,6 +85,8 @@ EVENT_TITLES = {
|
||||
"market_closed": "Автоторговля",
|
||||
"market_rest_fallback_available": "Автоторговля",
|
||||
"market_rest_fallback_unavailable": "Автоторговля",
|
||||
|
||||
"ws_depth_alive": "WebSocket debug",
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
# app/src/core/numbers.py
|
||||
|
||||
# src/core/numbers.py
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from src.core.types import NumericLike
|
||||
|
||||
|
||||
def safe_float(
|
||||
value: object,
|
||||
@@ -20,4 +16,36 @@ def safe_float(
|
||||
try:
|
||||
return float(str(value).strip())
|
||||
except (TypeError, ValueError):
|
||||
return default
|
||||
return default
|
||||
|
||||
|
||||
def safe_round(
|
||||
value: object,
|
||||
digits: int,
|
||||
) -> float | None:
|
||||
"""
|
||||
Безопасное округление.
|
||||
|
||||
None -> None
|
||||
любое число -> round(...)
|
||||
"""
|
||||
number = safe_float(value)
|
||||
|
||||
if number is None:
|
||||
return None
|
||||
|
||||
return round(number, digits)
|
||||
|
||||
|
||||
def get_value(value: object) -> object | None:
|
||||
"""
|
||||
Возвращает значение Enum или сам объект.
|
||||
|
||||
Enum -> .value
|
||||
None -> None
|
||||
Остальные типы -> без изменений.
|
||||
"""
|
||||
if value is None:
|
||||
return None
|
||||
|
||||
return getattr(value, "value", value)
|
||||
Reference in New Issue
Block a user