diff --git a/src/web_dashboard.py b/src/web_dashboard.py
index 87e4a96..7091fd3 100644
--- a/src/web_dashboard.py
+++ b/src/web_dashboard.py
@@ -1,9 +1,11 @@
#!/usr/bin/env python3
+"""Trading Bot Dashboard v0.5.1 (RSI + Bollinger Bands HYBRID) - Auto-load 1-Day chart on page load"""
+import sqlite3
from fastapi import FastAPI
from fastapi.responses import HTMLResponse
from binance.client import Client
from datetime import datetime
-import json, os, time, sqlite3
+import json, os, time
app = FastAPI()
@@ -16,49 +18,318 @@ with open('/home/marc/bot-deploy/.env') as f:
binance = Client(env.get('BINANCE_API_KEY_LIVE'), env.get('BINANCE_API_SECRET_LIVE'))
DB = '/home/marc/bot-deploy/pnl_charts.db'
-def get_chart_data(days=1):
- conn = sqlite3.connect(DB)
- rows = conn.execute(f"""SELECT ts, pv, pp FROM history WHERE ts > {int(time.time()) - days*86400} ORDER BY ts""").fetchall()
- conn.close()
- return [(datetime.fromtimestamp(r[0]).strftime('%H:%M'), r[2]) for r in rows]
+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()
-@app.get('/')
-async def root():
- chart_1d = get_chart_data(1)
- chart_7d = get_chart_data(7)
- chart_30d = get_chart_data(30)
-
- html = f'''
-
Trading Bot v0.6
-
-
-
-
-
Analytics
-
1-Day Chart: {len(chart_1d)} points
-
7-Day Chart: {len(chart_7d)} points
-
30-Day Chart: {len(chart_30d)} points
-
-
-
-
-
1D Performance
+{chart_1d[-1][1] if chart_1d else 0:.2f}%
-
7D Performance
+{chart_7d[-1][1] if chart_7d else 0:.2f}%
-
30D Performance
+{chart_30d[-1][1] if chart_30d else 0:.2f}%
-
-
-
-
'''
- return HTMLResponse(html)
+init_db()
@app.get('/api/state')
async def state():
try:
acc = binance.get_account()
- portfolio = sum(float(b['free']) * (1.0 if b['asset']=='USDT' else 0) for b in acc['balances'])
- return {'portfolio': portfolio, 'status': 'ok'}
- except:
- return {'error': 'failed'}
+ 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)
+ # Get latest P&L from database
+ try:
+ conn = sqlite3.connect('/home/marc/bot-deploy/pnl_charts.db')
+ row = conn.execute('SELECT pu, pp FROM history ORDER BY ts DESC LIMIT 1').fetchone()
+ conn.close()
+ if row:
+ pu, pp = row[0], row[1]
+ else:
+ pu, pp = 0.0, 0.0
+ except:
+ pu, pp = 0.0, 0.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 = [], [], []
+ seen_ts = set()
+
+ for t, p, u in rows:
+ dt = datetime.fromtimestamp(t)
+
+ if hours <= 24:
+ ts = dt.strftime('%H:00')
+ else:
+ ts = dt.strftime('%d.%m.%y')
+
+ if ts in seen_ts:
+ continue
+
+ seen_ts.add(ts)
+ ts_list.append(ts)
+ 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, 'current_usdt': usdts[-1] if usdts else 0,
+ 'min_pct': min(pcts) if pcts else 0, 'min_usdt': min(usdts) if usdts else 0,
+ 'max_pct': max(pcts) if pcts else 0, 'max_usdt': max(usdts) if usdts else 0,
+ 'avg_pct': sum(pcts)/len(pcts) if pcts else 0, 'avg_usdt': sum(usdts)/len(usdts) if usdts else 0}
+
+@app.get('/')
+async def dashboard():
+ html = """
+
+
+
+
+Trading Bot v0.5.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
📈 P&L Performance (Live)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+"""
+ return HTMLResponse(content=html)
if __name__ == '__main__':
import uvicorn