dashboard: redesign signal workspace and refresh flow
This commit is contained in:
+34
-15
@@ -82,8 +82,7 @@ SUMMARY_PHP_FILE = "news_summary.php"
|
||||
# Repo files copied into the out dir at daemon start (git pull + restart
|
||||
# updates them). The PHP endpoint reads news.json in place, so it lives
|
||||
# next to the page.
|
||||
STATIC_FILES = [PAGE_FILE, "dashboard.css", "dashboard.js", "gauge.js",
|
||||
SUMMARY_PHP_FILE]
|
||||
STATIC_FILES = [PAGE_FILE, "dashboard.css", "dashboard.js", SUMMARY_PHP_FILE]
|
||||
|
||||
|
||||
# ══════════════════════════════════════════════════════════════════
|
||||
@@ -323,6 +322,7 @@ class DashboardPublisher:
|
||||
def __init__(self, out_dir: str):
|
||||
self.out_dir = out_dir
|
||||
self.snapshots: Dict[str, dict] = {}
|
||||
self._reports = {}
|
||||
self.news_payload: Optional[dict] = None
|
||||
self._dp = None
|
||||
self._news_engine: Optional[NewsEngine] = None
|
||||
@@ -359,13 +359,7 @@ class DashboardPublisher:
|
||||
try:
|
||||
report = produce_signal(XAUUSD, tf, self._provider(),
|
||||
CONFIRMATIONS[tf])
|
||||
# Advisory AI panel, post-hoc and display-only. Off unless
|
||||
# config.json agent_panel.dashboard is true. The reuse-TTL
|
||||
# cache + max_panels_per_day budget bound the spend against
|
||||
# this process's own DeepSeek cap (a persisting M5 signal
|
||||
# re-serves its cached verdict instead of re-running every
|
||||
# bar); a fresh panel adds ≤~25 s before this TF publishes.
|
||||
attach_panel(report, surface="dashboard")
|
||||
self._reports[tf.value] = report
|
||||
self.snapshots[tf.value] = {
|
||||
"status": "ok",
|
||||
"scanned_at": datetime.now(timezone.utc).isoformat(),
|
||||
@@ -377,16 +371,41 @@ class DashboardPublisher:
|
||||
logger.info(f"{tf.value}: {report.final_signal.name} "
|
||||
f"q={report.signal_quality or '-'} "
|
||||
f"({time.time() - started:.1f}s)")
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
# Keep the last good report; the page shows it with an
|
||||
# error badge instead of going blank.
|
||||
logger.exception(f"{tf.value} scan failed")
|
||||
self._reports.pop(tf.value, None)
|
||||
entry = self.snapshots.get(tf.value) or _empty_tf_entry()
|
||||
entry["status"] = "error"
|
||||
entry["error"] = f"{type(e).__name__}: {e}"
|
||||
# The public snapshot carries a stable message; exception
|
||||
# detail remains in dashboard.log for the operator.
|
||||
entry["error"] = "Scan unavailable"
|
||||
entry["error_at"] = datetime.now(timezone.utc).isoformat()
|
||||
self.snapshots[tf.value] = entry
|
||||
|
||||
def attach_panels(self, tfs: List[Timeframe]) -> bool:
|
||||
"""Add advisory panels after publishing the technical snapshot.
|
||||
|
||||
A panel is display-only and can take tens of seconds on a cold LLM
|
||||
request. Keeping its report object locally lets the page receive the
|
||||
candle-close signal first, then a second atomic snapshot only when a
|
||||
panel produced a result.
|
||||
"""
|
||||
updated = False
|
||||
for tf in tfs:
|
||||
report = self._reports.get(tf.value)
|
||||
if report is None:
|
||||
continue
|
||||
if not attach_panel(report, surface="dashboard"):
|
||||
continue
|
||||
entry = self.snapshots.get(tf.value)
|
||||
if entry is None or entry.get("status") != "ok":
|
||||
continue
|
||||
entry["report"] = report_to_webapp_dict(report)
|
||||
updated = True
|
||||
return updated
|
||||
|
||||
def refresh_news(self) -> None:
|
||||
try:
|
||||
ne = self._news()
|
||||
@@ -413,11 +432,11 @@ class DashboardPublisher:
|
||||
def run_cycle(self, tfs: List[Timeframe]) -> None:
|
||||
for tf in tfs: # sequential — see module docstring (cache dedup)
|
||||
self.scan_tf(tf)
|
||||
# Snapshot lands BEFORE the news refresh: when the news TTL has
|
||||
# expired, refresh_news does FF + 4 RSS fetches (and possibly
|
||||
# DeepSeek calls) — 20-30 s that must not keep fresh signals off
|
||||
# the page.
|
||||
# Technical signals land before any optional slow work. News and the
|
||||
# advisory panel are display-only and may take 20-30 seconds cold.
|
||||
self.publish_snapshot()
|
||||
if self.attach_panels(tfs):
|
||||
self.publish_snapshot()
|
||||
self.refresh_news()
|
||||
self.publish_news()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user