- Infra: Freqtrade (futures dry-run) + Redis + dashboard + Docker Compose - Couche IA: ai_analyzer (Claude via abonnement, MCP TradingView, backfill biais) - Stratégies: SampleStrategy, AiBiasStrategy, IchimokuLS (long/short, validée train/test + données vierges + walk-forward), MTFIchimoku, variantes hyperopt - Arbitrage CEX (dry-run), backtesting, walk-forward, volatility targeting - IchimokuLS en dry-run live (config_live.json) Claude-Session: https://claude.ai/code/session_01VHETcFacdnDhQzthLpdYFR
114 lines
4.1 KiB
Python
114 lines
4.1 KiB
Python
"""Dashboard MidasBot — panneau « Insights IA ».
|
|
|
|
Affiche les derniers biais de marché produits par Claude (lus depuis Redis) et
|
|
un lien vers FreqUI (positions / P&L / trades). Volontairement minimal et autonome
|
|
(pas de dépendance au package ai_analyzer).
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import os
|
|
from datetime import datetime, timezone
|
|
|
|
import redis
|
|
from fastapi import FastAPI
|
|
from fastapi.responses import HTMLResponse, JSONResponse
|
|
|
|
REDIS_URL = os.environ.get("REDIS_URL", "redis://localhost:6379/0")
|
|
FREQUI_URL = os.environ.get("FREQUI_URL", "http://127.0.0.1:8080")
|
|
|
|
app = FastAPI(title="MidasBot Dashboard")
|
|
|
|
|
|
def _redis() -> redis.Redis:
|
|
return redis.Redis.from_url(REDIS_URL, decode_responses=True)
|
|
|
|
|
|
def _read_biases() -> list[dict]:
|
|
r = _redis()
|
|
out: list[dict] = []
|
|
try:
|
|
for key in r.scan_iter("bias:*"):
|
|
raw = r.get(key)
|
|
if not raw:
|
|
continue
|
|
try:
|
|
out.append(json.loads(raw))
|
|
except json.JSONDecodeError:
|
|
continue
|
|
except redis.RedisError:
|
|
return []
|
|
out.sort(key=lambda b: b.get("pair", ""))
|
|
return out
|
|
|
|
|
|
@app.get("/api/biases")
|
|
def api_biases() -> JSONResponse:
|
|
return JSONResponse({"biases": _read_biases(), "generated_at": _now()})
|
|
|
|
|
|
@app.get("/api/health")
|
|
def health() -> dict:
|
|
try:
|
|
_redis().ping()
|
|
redis_ok = True
|
|
except redis.RedisError:
|
|
redis_ok = False
|
|
return {"status": "ok", "redis": redis_ok}
|
|
|
|
|
|
def _now() -> str:
|
|
return datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S UTC")
|
|
|
|
|
|
_COLORS = {"bullish": "#16a34a", "bearish": "#dc2626", "neutral": "#6b7280"}
|
|
|
|
|
|
@app.get("/", response_class=HTMLResponse)
|
|
def index() -> str:
|
|
biases = _read_biases()
|
|
if biases:
|
|
rows = "\n".join(
|
|
f"""<tr>
|
|
<td class="pair">{b.get('pair','?')}</td>
|
|
<td><span class="badge" style="background:{_COLORS.get(b.get('direction'),'#6b7280')}">{b.get('direction','?')}</span></td>
|
|
<td>{float(b.get('confidence',0)):.0%}</td>
|
|
<td class="rat">{b.get('rationale','')}</td>
|
|
<td>{b.get('key_support','—')}</td>
|
|
<td>{b.get('key_resistance','—')}</td>
|
|
</tr>"""
|
|
for b in biases
|
|
)
|
|
else:
|
|
rows = '<tr><td colspan="6" class="empty">Aucun biais en cache. Lance l\'analyzer (ai-analyzer).</td></tr>'
|
|
|
|
return f"""<!doctype html>
|
|
<html lang="fr"><head>
|
|
<meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<meta http-equiv="refresh" content="30">
|
|
<title>MidasBot — Insights IA</title>
|
|
<style>
|
|
:root {{ color-scheme: dark; }}
|
|
body {{ font-family: system-ui, sans-serif; background:#0b0e14; color:#e6e6e6; margin:0; padding:2rem; }}
|
|
h1 {{ margin:0 0 .25rem; font-size:1.5rem; }}
|
|
.sub {{ color:#8b95a7; margin-bottom:1.5rem; font-size:.9rem; }}
|
|
a {{ color:#60a5fa; }}
|
|
table {{ width:100%; border-collapse:collapse; background:#111722; border-radius:10px; overflow:hidden; }}
|
|
th, td {{ padding:.7rem .9rem; text-align:left; border-bottom:1px solid #1f2937; vertical-align:top; }}
|
|
th {{ background:#0f1521; color:#94a3b8; font-weight:600; font-size:.8rem; text-transform:uppercase; letter-spacing:.04em; }}
|
|
.pair {{ font-weight:700; }}
|
|
.rat {{ color:#cbd5e1; font-size:.9rem; max-width:520px; }}
|
|
.badge {{ color:#fff; padding:.15rem .55rem; border-radius:999px; font-size:.8rem; text-transform:capitalize; }}
|
|
.empty {{ color:#8b95a7; text-align:center; padding:2rem; }}
|
|
.links {{ margin-top:1.5rem; }}
|
|
</style></head>
|
|
<body>
|
|
<h1>🪙 MidasBot — Insights IA</h1>
|
|
<div class="sub">Biais de marché produits par Claude · {_now()} · rafraîchissement auto 30 s · <strong>DRY-RUN</strong></div>
|
|
<table>
|
|
<thead><tr><th>Paire</th><th>Biais</th><th>Confiance</th><th>Justification</th><th>Support</th><th>Résistance</th></tr></thead>
|
|
<tbody>{rows}</tbody>
|
|
</table>
|
|
<div class="links">📊 <a href="{FREQUI_URL}" target="_blank">Ouvrir FreqUI</a> (positions, P&L, trades) · <a href="/api/biases">API JSON</a></div>
|
|
</body></html>"""
|