07.4.4.1.11 — Advanced Trend Quality & EMA Distance Layer

This commit is contained in:
2026-05-20 21:15:00 +03:00
parent 2c75f95b46
commit 06ea376cb5
36 changed files with 6260 additions and 2092 deletions

View File

@@ -22,6 +22,7 @@ class MarketRuntimeContext:
screen: str | None
action: str
runtime_label: str | None
last_market_status: str | None = None
class MarketDataRunner:
@@ -116,18 +117,29 @@ class MarketDataRunner:
):
MarketPriceCache.clear(cache_symbol)
#if previous_symbol is not None:
# cls._log_info(
# context,
# "market_symbol_changed",
# f"Инструмент автоторговли изменён: {cache_symbol}.",
# {
# "previous_symbol": previous_symbol,
# "symbol": symbol,
# "cache_symbol": cache_symbol,
# "ws_symbol": ws_symbol,
# },
# )
market_status = ExchangeService().get_symbol_market_status(symbol)
status_key = str(market_status.get("status") or "UNKNOWN")
if not bool(market_status.get("is_open")):
if context.last_market_status != status_key:
context.last_market_status = status_key
cls._log_warning(
context,
"market_closed",
"Рынок закрыт. Мониторинг рыночных данных временно приостановлен.",
{
"symbol": symbol,
"market_status": status_key,
"message": market_status.get("message"),
},
)
await asyncio.sleep(context.interval_seconds)
continue
context.last_market_status = status_key
try:
await cls._run_websocket(context, symbol)
except asyncio.CancelledError:

View File

@@ -36,6 +36,73 @@ class ExchangeService:
_execution_cache_max_age_seconds = 2.0
_default_runtime_key = "auto"
def get_symbol_market_status(self, symbol: str | None = None) -> dict[str, object]:
symbol_to_use = symbol or self.settings.default_symbol
if not self.settings.exchange_enabled:
return {
"symbol": symbol_to_use,
"is_open": True,
"status": "OPEN",
"message": "Mock market is open.",
}
validation = self.validate_symbol(symbol_to_use)
if not validation.is_valid:
return {
"symbol": symbol_to_use,
"is_open": False,
"status": "INVALID_SYMBOL",
"message": validation.message,
}
symbol_info = validation.symbol_info
raw_status = str(getattr(symbol_info, "status", "") or "").upper()
open_statuses = {
"TRADING",
"OPEN",
"ACTIVE",
"ENABLED",
"ONLINE",
}
closed_statuses = {
"BREAK",
"CLOSED",
"HALT",
"HALTED",
"PAUSED",
"SUSPENDED",
"DISABLED",
"SETTLING",
"POST_ONLY",
}
if raw_status in open_statuses:
return {
"symbol": validation.normalized_symbol,
"is_open": True,
"status": raw_status,
"message": "Рынок открыт.",
}
if raw_status in closed_statuses:
return {
"symbol": validation.normalized_symbol,
"is_open": False,
"status": raw_status,
"message": "Рынок закрыт или на паузе.",
}
return {
"symbol": validation.normalized_symbol,
"is_open": False,
"status": raw_status or "UNKNOWN",
"message": "Статус рынка не определён.",
}
def __init__(self) -> None:
self.settings = load_settings()
self.journal = JournalService()