return "HOLD";
}
-function safeLevel(level: any): AlertLevel {
- const l = String(level ?? "INFO").toUpperCase();
- if (l === "CRITICAL" || l === "WARNING") return l as AlertLevel;
+function confidenceToLevel(conf: number): AlertLevel {
+ if (conf >= 0.85) return "CRITICAL";
+ if (conf >= 0.65) return "WARNING";
return "INFO";
}
+function toNumber(x: any, fallback = 0): number {
+ const n = typeof x === "number" ? x : Number(x);
+ return Number.isFinite(n) ? n : fallback;
+}
+
export async function getDashboardSummary(): Promise<DashboardSummary> {
const session = await loadSession();
const userId = session?.userId;
if (!userId) throw new Error("Session absente : impossible de charger le dashboard.");
const settings = await loadSettings();
- const quote = settings.currency === "USDT" ? "USDT" : "EUR";
+ const quote: "EUR" | "USDT" = settings.currency === "USDT" ? "USDT" : "EUR";
const pair = `BTC/${quote}`;
- const price = await getCurrentPrice(pair);
+ // 1) Prix (toujours OK)
+ const priceRes = await getCurrentPrice(pair);
+ // 2) Signal (peut être null)
const sig = await apiGet<any>(
`/signal/current?userId=${encodeURIComponent(userId)}&pair=${encodeURIComponent(pair)}`
);
- const data = sig ?? null;
+ // serveur renvoie { ok:true, data: ... } => http.ts unwrap => sig = data
+ if (!sig) {
+ // pas de signal récent : on renvoie un dashboard “HOLD” propre
+ return {
+ pair,
+ price: priceRes.price,
+ strategy: settings.selectedStrategyKey,
+ decision: "HOLD",
+ confidence: 0,
+ reason: "Aucun signal récent pour le moment.",
+ alertLevel: "INFO",
+ timestamp: priceRes.timestampMs,
+ };
+ }
+
+ // Champs réels observés :
+ // action, confidence (string), reason, timestamp_ms, pair_code
+ const decision = safeDecision(sig.action ?? sig.decision);
+ const confidence = toNumber(sig.confidence, 0);
+ const reason = String(sig.reason ?? sig.message ?? "—");
+
+ const timestamp =
+ toNumber(sig.timestamp_ms, 0) ||
+ toNumber(sig.timestamp, 0) ||
+ priceRes.timestampMs;
+
+ const alertLevel =
+ (String(sig.alertLevel ?? sig.criticality ?? "").toUpperCase() as AlertLevel) ||
+ confidenceToLevel(confidence);
+
+ // pair_code si présent, sinon pair demandé
+ const pairOut = String(sig.pair_code ?? sig.pair ?? pair);
return {
- pair,
- price: price.price,
+ pair: pairOut,
+ price: priceRes.price,
strategy: settings.selectedStrategyKey,
- decision: safeDecision(data?.action ?? data?.decision),
- confidence: typeof data?.confidence === "number" ? data.confidence : 0,
- reason: String(data?.reason ?? data?.message ?? "—"),
- alertLevel: safeLevel(data?.alertLevel ?? data?.level ?? data?.criticality),
- timestamp:
- typeof data?.timestamp_ms === "number"
- ? data.timestamp_ms
- : typeof data?.timestamp === "number"
- ? data.timestamp
- : price.timestampMs,
+ decision,
+ confidence,
+ reason,
+ alertLevel: alertLevel === "CRITICAL" || alertLevel === "WARNING" || alertLevel === "INFO"
+ ? alertLevel
+ : confidenceToLevel(confidence),
+ timestamp,
};
}
\ No newline at end of file