Fix dashboard TF key mismatch, increase refresh to 5s
Timeframe keys stored as enum values (15min/1h/4h) but dashboard looked for M15/1h/4h — GBP/USD showed no price or signal text. Now uses Timeframe enum directly with display labels. Reduced dashboard refresh from 60s to 5s with throttle guard. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+23
-12
@@ -325,6 +325,10 @@ _SHORT_SIGNAL = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_TF_DISPLAY = {"5min": "M5", "15min": "M15", "1h": "H1", "4h": "H4", "1d": "D1"}
|
||||||
|
_DASH_TFS = [Timeframe.M15, Timeframe.H1, Timeframe.H4]
|
||||||
|
|
||||||
|
|
||||||
def _format_stats_dashboard() -> str:
|
def _format_stats_dashboard() -> str:
|
||||||
if not _signal_stats:
|
if not _signal_stats:
|
||||||
return "📊 *Live Dashboard*\n\n_Waiting for first scan…_"
|
return "📊 *Live Dashboard*\n\n_Waiting for first scan…_"
|
||||||
@@ -332,17 +336,15 @@ def _format_stats_dashboard() -> str:
|
|||||||
now = datetime.now(timezone.utc).strftime("%H:%M:%S UTC")
|
now = datetime.now(timezone.utc).strftime("%H:%M:%S UTC")
|
||||||
lines = [f"📊 *Live Dashboard* — {now}", ""]
|
lines = [f"📊 *Live Dashboard* — {now}", ""]
|
||||||
|
|
||||||
tf_order = ["M15", "1h", "4h"]
|
|
||||||
|
|
||||||
for symbol in SCAN_PAIRS:
|
for symbol in SCAN_PAIRS:
|
||||||
display = PAIR_INFO.get(symbol, {}).get("display", symbol)
|
display = PAIR_INFO.get(symbol, {}).get("display", symbol)
|
||||||
pair_data = _signal_stats.get(symbol, {})
|
pair_data = _signal_stats.get(symbol, {})
|
||||||
|
|
||||||
ws_price = _last_prices.get(symbol)
|
ws_price = _last_prices.get(symbol)
|
||||||
latest = None
|
latest = None
|
||||||
for tf in reversed(tf_order):
|
for tf in reversed(_DASH_TFS):
|
||||||
if tf in pair_data:
|
if tf.value in pair_data:
|
||||||
latest = pair_data[tf]
|
latest = pair_data[tf.value]
|
||||||
break
|
break
|
||||||
|
|
||||||
price = ws_price or (latest.current_price if latest else 0)
|
price = ws_price or (latest.current_price if latest else 0)
|
||||||
@@ -354,14 +356,15 @@ def _format_stats_dashboard() -> str:
|
|||||||
regime = latest.market_regime.replace("_", " ").title() if latest else ""
|
regime = latest.market_regime.replace("_", " ").title() if latest else ""
|
||||||
|
|
||||||
tf_parts = []
|
tf_parts = []
|
||||||
for tf in tf_order:
|
for tf in _DASH_TFS:
|
||||||
r = pair_data.get(tf)
|
label = _TF_DISPLAY.get(tf.value, tf.value)
|
||||||
|
r = pair_data.get(tf.value)
|
||||||
if not r:
|
if not r:
|
||||||
tf_parts.append(f"{tf}: ⬜—")
|
tf_parts.append(f"{label}: ⬜—")
|
||||||
continue
|
continue
|
||||||
emoji = _SIGNAL_EMOJI.get(r.final_signal, "⬜")
|
emoji = _SIGNAL_EMOJI.get(r.final_signal, "⬜")
|
||||||
sig = _SHORT_SIGNAL.get(r.final_signal, "Neutral")
|
sig = _SHORT_SIGNAL.get(r.final_signal, "Neutral")
|
||||||
tf_parts.append(f"{tf}: {emoji}{sig}")
|
tf_parts.append(f"{label}: {emoji}{sig}")
|
||||||
|
|
||||||
lines.append(f"*{display}* {price_str} _{regime}_")
|
lines.append(f"*{display}* {price_str} _{regime}_")
|
||||||
lines.append(" | ".join(tf_parts))
|
lines.append(" | ".join(tf_parts))
|
||||||
@@ -377,7 +380,7 @@ def _format_stats_dashboard() -> str:
|
|||||||
|
|
||||||
lines.append("")
|
lines.append("")
|
||||||
|
|
||||||
lines.append("_🔄 auto-refresh 60s_")
|
lines.append("_🔄 live refresh_")
|
||||||
return "\n".join(lines)
|
return "\n".join(lines)
|
||||||
|
|
||||||
|
|
||||||
@@ -385,6 +388,8 @@ def _format_stats_dashboard() -> str:
|
|||||||
|
|
||||||
_dashboard_msg_ids: Dict[int, int] = {}
|
_dashboard_msg_ids: Dict[int, int] = {}
|
||||||
_dashboard_task: Optional[asyncio.Task] = None
|
_dashboard_task: Optional[asyncio.Task] = None
|
||||||
|
_last_dashboard_refresh: float = 0
|
||||||
|
_DASHBOARD_THROTTLE = 5
|
||||||
|
|
||||||
|
|
||||||
async def _send_dashboard(bot, chat_id: int) -> None:
|
async def _send_dashboard(bot, chat_id: int) -> None:
|
||||||
@@ -396,7 +401,13 @@ async def _send_dashboard(bot, chat_id: int) -> None:
|
|||||||
logger.exception(f"Failed to send dashboard to {chat_id}")
|
logger.exception(f"Failed to send dashboard to {chat_id}")
|
||||||
|
|
||||||
|
|
||||||
async def _refresh_dashboard(bot) -> None:
|
async def _refresh_dashboard(bot, force: bool = False) -> None:
|
||||||
|
global _last_dashboard_refresh
|
||||||
|
now = time.time()
|
||||||
|
if not force and (now - _last_dashboard_refresh) < _DASHBOARD_THROTTLE:
|
||||||
|
return
|
||||||
|
_last_dashboard_refresh = now
|
||||||
|
|
||||||
text = _format_stats_dashboard()
|
text = _format_stats_dashboard()
|
||||||
for chat_id in list(_autoscan_chats):
|
for chat_id in list(_autoscan_chats):
|
||||||
msg_id = _dashboard_msg_ids.get(chat_id)
|
msg_id = _dashboard_msg_ids.get(chat_id)
|
||||||
@@ -419,7 +430,7 @@ async def _refresh_dashboard(bot) -> None:
|
|||||||
async def _dashboard_loop(bot) -> None:
|
async def _dashboard_loop(bot) -> None:
|
||||||
try:
|
try:
|
||||||
while _autoscan_chats:
|
while _autoscan_chats:
|
||||||
await asyncio.sleep(60)
|
await asyncio.sleep(5)
|
||||||
if not _autoscan_chats:
|
if not _autoscan_chats:
|
||||||
break
|
break
|
||||||
await _refresh_dashboard(bot)
|
await _refresh_dashboard(bot)
|
||||||
|
|||||||
Reference in New Issue
Block a user