diff --git a/src/web_dashboard.py b/src/web_dashboard.py index 8c7ae5c..af13956 100644 --- a/src/web_dashboard.py +++ b/src/web_dashboard.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 from fastapi import FastAPI, Response from binance.client import Client -import json, os +import json, os, time from datetime import datetime app = FastAPI() @@ -14,8 +14,17 @@ with open('/home/marc/bot-deploy/.env') as f: binance = Client(env.get('BINANCE_API_KEY_LIVE'), env.get('BINANCE_API_SECRET_LIVE')) +# CACHE for prices (update every 5 seconds) +price_cache = {'prices': {}, 'timestamp': 0} + def get_live_prices(): - """Get LIVE prices from Binance API""" + """Get LIVE prices from Binance API with 5-second cache""" + global price_cache + + # Return cached if less than 5 seconds old + if time.time() - price_cache['timestamp'] < 5: + return price_cache['prices'] + prices = {'USDT': 1.0} pairs = ['BTCUSDT', 'ETHUSDT', 'SOLUSDT', 'BNBUSDT', 'XRPUSDT'] @@ -24,24 +33,31 @@ def get_live_prices(): ticker = binance.get_ticker(symbol=pair) asset = pair.replace('USDT', '') prices[asset] = float(ticker['lastPrice']) - except: + except Exception as e: pass + # Update cache + price_cache['prices'] = prices + price_cache['timestamp'] = time.time() + return prices def load_bot_state(): """Load bot state from file""" state_file = '/home/marc/bot-deploy/trades.json' if os.path.exists(state_file): - with open(state_file) as f: - return json.load(f) + try: + with open(state_file) as f: + return json.load(f) + except: + pass return {'current': {}, 'completed': [], 'balance': {}} @app.get('/api/state') async def get_state(): - """Return complete bot state with LIVE prices from Binance""" + """Return complete bot state with LIVE prices""" try: - # Get balance from Binance (LIVE) + # Get balance from Binance ONCE (not per asset) account = binance.get_account() balance = {} @@ -51,42 +67,52 @@ async def get_state(): locked = float(asset_data['locked']) total = free + locked - if total > 0: + # Only include meaningful balances + if total > 0.00001: balance[asset] = { 'free': free, 'locked': locked, 'total': total } - # Get LIVE prices from Binance (CRITICAL FIX) + # Get cached prices (5-second update) prices = get_live_prices() # Calculate portfolio value with LIVE prices + # ONLY for known trading pairs (exclude junk tokens) portfolio_value = 0 - for asset, data in balance.items(): - price = prices.get(asset, 0) - portfolio_value += data['total'] * price + tracked_assets = ['BTC', 'ETH', 'SOL', 'BNB', 'XRP', 'USDT', 'USDC'] + + for asset in tracked_assets: + if asset in balance: + data = balance[asset] + price = prices.get(asset, 0) + portfolio_value += data['total'] * price + + # Get USDT free specifically + usdt_free = balance.get('USDT', {}).get('free', 0) # Load trade state trades = load_bot_state() return { 'balance': balance, - 'portfolio_value': portfolio_value, + 'portfolio_value': round(portfolio_value, 2), + 'usdt_free': round(usdt_free, 2), 'current_trades': trades.get('current', {}), 'completed_trades': trades.get('completed', []), 'prices': prices, 'timestamp': datetime.now().isoformat(), - 'note': 'Portfolio calculated with LIVE Binance prices' + 'note': 'Portfolio calculated with LIVE Binance prices (tracked assets only, excludes junk tokens)' } except Exception as e: - return {'error': str(e), 'portfolio_value': 0} + return {'error': str(e), 'portfolio_value': 0, 'usdt_free': 0} @app.get('/') async def root(): state = await get_state() portfolio_val = state.get('portfolio_value', 0) - usdt_free = state.get('balance', {}).get('USDT', {}).get('free', 0) + usdt_free = state.get('usdt_free', 0) trades_count = len(state.get('current_trades', {})) prices = state.get('prices', {}) @@ -156,44 +182,41 @@ tr:nth-child(even) {{ background: #0d0d0d; }} html += ''' -
| Pair | -Qty | -Entry Price | -Current Price | -Position Value | -SL Level | -TP Level | +Asset | +Free | +Locked | +Total | +Value |
|---|---|---|---|---|---|---|---|---|---|---|---|
| {pair} | -{qty:.6f} | -${entry:.4f} | -${current_price:.4f} | + tracked = ['BTC', 'ETH', 'SOL', 'BNB', 'XRP', 'USDT', 'USDC'] + balance = state.get('balance', {}) + + for asset in tracked: + if asset in balance: + data = balance[asset] + price = prices.get(asset, 0) + value = data['total'] * price + html += f'''||||||||
| {asset} | +{data['free']:.6f} | +{data['locked']:.6f} | +{data['total']:.6f} | ${value:.2f} | -${sl:.4f} | -${tp:.4f} |