""" dashboard.py — MoneyMaker live monitoring dashboard. Usage: python dashboard.py # starts on http://localhost:5001 python dashboard.py --port 5002 Auto-refreshes every 60 seconds. Shows: • Portfolio P&L + C25 benchmark • Open positions with live prices • Closed trades (win/loss) • Signal accuracy • Recent runner log tail """ import argparse import json import os import time from datetime import datetime, timezone from pathlib import Path import yfinance as yf from flask import Flask, render_template_string from db import get_conn, DB_TYPE from report import _c25_day_return, _unrealised_pnl, _realised_pnl, _total_fees, _signal_accuracy CAPITAL = 10_000 LOG_DIR = Path(os.getenv("LOG_DIR", str(Path(__file__).parent / "logs"))) REFRESH = 60 # seconds app = Flask(__name__) # ── HTML template ──────────────────────────────────────────────────────────── TEMPLATE = """
| Ticker | Antal | Købt | Nu | P&L | Ændring | Stop | Take | Status |
|---|---|---|---|---|---|---|---|---|
| {{ p.ticker }} | {{ "{:.0f}".format(p.shares) }} | {{ "{:,.0f}".format(p.entry) }} | {{ "{:,.0f}".format(p.last) }} | {{ "{:+,.0f}".format(p.unreal) }} | {{ "{:+.1f}%".format(p.pct) }} | {{ "{:,.0f}".format(p.stop) }} | {{ "{:,.0f}".format(p.take) }} | {% if p.stop_hit %}🔴 STOP {% elif p.take_hit %}🟡 TAKE {% else %}⏳ HOLD{% endif %} |
Ingen åbne positioner.
{% endif %}| Ticker | Handling | Antal | Kurs | Total | P&L | Signal | Dato |
|---|---|---|---|---|---|---|---|
| {{ t.ticker }} | {{ t.action.upper() }} | {{ "{:.0f}".format(t.shares) }} | {{ "{:,.0f}".format(t.price) }} | {{ "{:,.0f}".format(t.total_dkk) }} | {{ "{:+,.0f}".format(t.pnl_dkk) if t.pnl_dkk is not none else "—" }} | {% if t.signal_correct == 1 %}✅ korrekt {% elif t.signal_correct == 0 %}❌ forkert {% else %}—{% endif %} | {{ t.event_date }} |
Ingen handler endnu.
{% endif %}| Analyserede signaler | Alert-triggers (≥threshold) | Gns. score |
|---|---|---|
| {{ sig.total }} | {{ sig.alerts }} | {{ "{:.3f}".format(sig.avg_score) }} |
{{ log_tail }}