Feature: Live data monitoring tools - live_status.py (manual) + api_verifier.py (continuous 30s checks). Ensures Marc always has fresh portfolio data from Binance API (2026-07-09 20:30)
This commit is contained in:
parent
8b40fb5b30
commit
503d2a8a0a
|
|
@ -0,0 +1,66 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
REAL-TIME API Verification Dashboard
|
||||
Polls Binance every 30 seconds, compares bot state vs actual portfolio.
|
||||
Alerts on discrepancies IMMEDIATELY.
|
||||
"""
|
||||
import os
|
||||
import json
|
||||
import time
|
||||
from datetime import datetime
|
||||
from binance.client import Client
|
||||
from dotenv import load_dotenv
|
||||
|
||||
os.chdir('/home/marc/bot-deploy')
|
||||
load_dotenv()
|
||||
|
||||
client = Client(os.getenv('BINANCE_API_KEY_LIVE'), os.getenv('BINANCE_API_SECRET_LIVE'))
|
||||
TRACKED_ASSETS = {'USDT', 'BTC', 'ETH', 'BNB', 'XRP', 'SOL'}
|
||||
POLL_INTERVAL = 30 # seconds
|
||||
|
||||
def verify_state():
|
||||
"""Compare bot state vs Binance reality"""
|
||||
try:
|
||||
# Get Binance truth
|
||||
acc = client.get_account()
|
||||
binance_balances = {b['asset']: float(b['free']) + float(b['locked']) for b in acc['balances'] if float(b['free']) + float(b['locked']) > 0}
|
||||
tracked_binance = {k: v for k, v in binance_balances.items() if k in TRACKED_ASSETS}
|
||||
|
||||
# Get bot state
|
||||
try:
|
||||
with open('/home/marc/bot-deploy/active_trades.json') as f:
|
||||
bot_state = json.load(f)
|
||||
bot_trades = bot_state.get('active_trades', {})
|
||||
except:
|
||||
bot_trades = {}
|
||||
|
||||
# Compare
|
||||
timestamp = datetime.now().strftime("%H:%M:%S")
|
||||
|
||||
# Check 1: Trade count match
|
||||
holdings_count = len({k: v for k, v in tracked_binance.items() if k != 'USDT' and v > 0.0001})
|
||||
bot_count = len(bot_trades)
|
||||
|
||||
if holdings_count != bot_count:
|
||||
print(f"🔴 {timestamp} MISMATCH: Holdings={holdings_count} vs Bot={bot_count}")
|
||||
return False
|
||||
|
||||
# Check 2: USDT consistency
|
||||
usdt_binance = tracked_binance.get('USDT', 0)
|
||||
print(f"✅ {timestamp} Synced: {holdings_count} trades | USDT: ${usdt_binance:.2f}")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"🔴 {datetime.now().strftime('%H:%M:%S')} ERROR: {e}")
|
||||
return False
|
||||
|
||||
def main():
|
||||
print("🟢 Real-Time API Verification Dashboard (updating every 30s)")
|
||||
print("="*70)
|
||||
|
||||
while True:
|
||||
verify_state()
|
||||
time.sleep(POLL_INTERVAL)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Live Status Reporter — Always fresh data from Binance API + Bot State
|
||||
No caching, no stale data. Real-time updates.
|
||||
"""
|
||||
import os
|
||||
import json
|
||||
import time
|
||||
from datetime import datetime
|
||||
from binance.client import Client
|
||||
from dotenv import load_dotenv
|
||||
|
||||
os.chdir('/home/marc/bot-deploy')
|
||||
load_dotenv()
|
||||
|
||||
client = Client(os.getenv('BINANCE_API_KEY_LIVE'), os.getenv('BINANCE_API_SECRET_LIVE'))
|
||||
|
||||
# Bot's tracked symbols
|
||||
TRACKED_ASSETS = {'USDT', 'BTC', 'ETH', 'BNB', 'XRP', 'SOL'}
|
||||
|
||||
def get_live_data():
|
||||
"""Fetch ALWAYS FRESH data from Binance"""
|
||||
try:
|
||||
print(f'\n📊 LIVE DATA @ {datetime.now().strftime("%H:%M:%S CET")}')
|
||||
print('='*70)
|
||||
|
||||
# 1. Account balance (FRESH from API)
|
||||
acc = client.get_account()
|
||||
balances = {b['asset']: float(b['free']) + float(b['locked']) for b in acc['balances'] if float(b['free']) + float(b['locked']) > 0}
|
||||
|
||||
# Filter to ONLY tracked assets
|
||||
tracked_balances = {asset: qty for asset, qty in balances.items() if asset in TRACKED_ASSETS and qty > 0.0001}
|
||||
|
||||
usdt = tracked_balances.get('USDT', 0)
|
||||
usdt_free = sum(float(b['free']) for b in acc['balances'] if b['asset'] == 'USDT')
|
||||
usdt_locked = sum(float(b['locked']) for b in acc['balances'] if b['asset'] == 'USDT')
|
||||
|
||||
print(f'USDT Total: ${usdt:.2f} (Free: ${usdt_free:.2f} | Locked: ${usdt_locked:.2f})')
|
||||
|
||||
# 2. Holdings (ONLY tracked coins)
|
||||
holdings = {k: v for k, v in tracked_balances.items() if k != 'USDT'}
|
||||
|
||||
if holdings:
|
||||
print(f'\nActive Holdings:')
|
||||
for asset, qty in sorted(holdings.items()):
|
||||
print(f' {asset}: {qty:.8f}')
|
||||
else:
|
||||
print('Active Holdings: NONE')
|
||||
|
||||
# 3. Open orders (FRESH)
|
||||
orders = client.get_open_orders()
|
||||
print(f'\nOpen Orders (Pending): {len(orders)}')
|
||||
for o in orders:
|
||||
print(f' - {o["symbol"]}: {o["side"]} {o["origQty"]} @ {o["price"]}')
|
||||
|
||||
# 4. Bot state (active_trades.json)
|
||||
try:
|
||||
with open('/home/marc/bot-deploy/active_trades.json') as f:
|
||||
bot_state = json.load(f)
|
||||
print(f'\nBot Active Trades: {bot_state.get("count", 0)}')
|
||||
for symbol, trade in bot_state.get('active_trades', {}).items():
|
||||
print(f' - {symbol}: {trade["qty"]:.8f} @ {trade["entry_price"]:.2f}')
|
||||
except Exception as e:
|
||||
print(f'Bot State: ERROR - {e}')
|
||||
bot_state = {}
|
||||
|
||||
# 5. Verification
|
||||
print('\n✅ VERIFICATION:')
|
||||
if len(holdings) == bot_state.get('count', 0):
|
||||
print(f' ✅ Holdings ({len(holdings)}) matches Bot ({bot_state.get("count")}) ✅')
|
||||
else:
|
||||
print(f' ⚠️ MISMATCH: Holdings={len(holdings)} vs Bot={bot_state.get("count")}')
|
||||
|
||||
# 6. Check for garbage/orphaned coins
|
||||
garbage = {k: v for k, v in balances.items() if k not in TRACKED_ASSETS and v > 0.0001}
|
||||
if garbage:
|
||||
print(f'\n⚠️ GARBAGE/ORPHANED COINS:')
|
||||
for asset, qty in sorted(garbage.items()):
|
||||
print(f' {asset}: {qty:.8f} (not tracked by bot)')
|
||||
|
||||
print('='*70)
|
||||
|
||||
except Exception as e:
|
||||
print(f'ERROR: {e}')
|
||||
|
||||
if __name__ == '__main__':
|
||||
get_live_data()
|
||||
Loading…
Reference in New Issue