#!/usr/bin/env python3 from fastapi import FastAPI from fastapi.responses import HTMLResponse from binance.client import Client from datetime import datetime import json, os, time, sqlite3 app = FastAPI() env = {} with open('/home/marc/bot-deploy/.env') as f: for line in f: k, _, v = line.partition('=') env[k.strip()] = v.strip() binance = Client(env.get('BINANCE_API_KEY_LIVE'), env.get('BINANCE_API_SECRET_LIVE')) DB = '/home/marc/bot-deploy/pnl_charts.db' def init_db(): c = sqlite3.connect(DB).cursor() c.execute("""CREATE TABLE IF NOT EXISTS history ( ts INTEGER PRIMARY KEY, pv REAL, pu REAL, pp REAL, uf REAL, ap INTEGER)""") sqlite3.connect(DB).commit() init_db() @app.get('/api/state') async def state(): try: acc = binance.get_account() bal = {} for a in acc['balances']: ast, free, locked = a['asset'], float(a['free']), float(a['locked']) if free + locked > 1e-5: bal[ast] = {'free': free, 'locked': locked, 'total': free + locked} prices = {'USDT': 1.0} for p in ['BTCUSDT', 'ETHUSDT', 'SOLUSDT', 'BNBUSDT', 'XRPUSDT']: try: t = binance.get_ticker(symbol=p) prices[p.replace('USDT', '')] = float(t['lastPrice']) except: pass pv = sum(bal.get(a, {}).get('total', 0) * prices.get(a, 0) for a in ['BTC', 'ETH', 'SOL', 'BNB', 'XRP', 'USDT']) uf = bal.get('USDT', {}).get('free', 0) pu = pv - 137.79 pp = (pu / 137.79 * 100) if pv > 0 else 0 ap = 0 try: with open('/home/marc/bot-deploy/active_trades.json') as f: ap = json.load(f).get('count', 0) except: pass conn = sqlite3.connect(DB) conn.execute("INSERT OR REPLACE INTO history VALUES (?, ?, ?, ?, ?, ?)", (int(time.time()), pv, pu, pp, uf, ap)) conn.commit() conn.close() return {'portfolio_value': round(pv, 2), 'pnl_usdt': round(pu, 2), 'pnl_pct': round(pp, 2), 'usdt_free': round(uf, 2), 'active_positions': ap, 'balance': bal, 'prices': prices} except Exception as e: return {'error': str(e)} @app.get('/api/pnl-history') async def history(hours: int = 24): conn = sqlite3.connect(DB) cutoff = int(time.time()) - hours * 3600 rows = conn.execute("SELECT ts, pp, pu FROM history WHERE ts > ? ORDER BY ts", (cutoff,)).fetchall() conn.close() ts_list, pcts, usdts = [], [], [] for t, p, u in rows: dt = datetime.fromtimestamp(t) ts_list.append(dt.strftime('%H:%M' if hours <= 24 else '%m-%d')) pcts.append(round(p, 2)) usdts.append(round(u, 2)) return {'timestamps': ts_list, 'pnl_pcts': pcts, 'pnl_usdts': usdts, 'current_pct': pcts[-1] if pcts else 0, 'min_pct': min(pcts) if pcts else 0, 'max_pct': max(pcts) if pcts else 0, 'avg_pct': sum(pcts)/len(pcts) if pcts else 0} @app.get('/') async def dashboard(): return HTMLResponse("""
P&L Analytics