#!/usr/bin/env python3 """ Health Check Client for Signal Generator Query the running signal generator status """ import socket import sys import json def check_health(socket_path="/tmp/signals_health.sock"): """Query signal generator health status""" try: sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) sock.settimeout(5) sock.connect(socket_path) # Receive response response = b"" while True: chunk = sock.recv(4096) if not chunk: break response += chunk sock.close() # Parse and display health = json.loads(response.decode('utf-8')) print("=" * 60) print("SIGNAL GENERATOR HEALTH STATUS") print("=" * 60) print(f"Status: {health['status']}") print(f"Personality: {health['personality']}") print(f"Timeframes: {', '.join(health['timeframes'])}") print(f"Uptime: {health['uptime_seconds']}s ({health['uptime_seconds']//60}m)") print(f"Total Signals: {health['total_signals']}") print(f" - Buy: {health['buy_signals']}") print(f" - Sell: {health['sell_signals']}") print(f"Last Signal: {health['last_signal'] or 'None'}") print(f"Errors: {health['errors']}") print(f"Connected Clients: {health['connected_clients']}") # Database Status print("\n" + "=" * 70) print("DATABASE STATUS") print("=" * 70) db = health.get('databases', {}) # Candles DB candles = db.get('candles_db', {}) print(f"Candles DB: {'✓ OK' if candles.get('accessible') else '✗ FAILED'}") if candles.get('error'): print(f" Error: {candles['error']}") else: print(f" Total Rows: {candles.get('row_count', 0)}") for tf, info in candles.get('timeframes', {}).items(): age = info.get('age_seconds') age_str = f"{age}s ago" if age else "N/A" print(f" [{tf}]: {info['count']} rows, latest: {age_str}") # Analysis DB analysis = db.get('analysis_db', {}) print(f"Analysis DB: {'✓ OK' if analysis.get('accessible') else '✗ FAILED'}") if analysis.get('error'): print(f" Error: {analysis['error']}") else: print(f" Total Rows: {analysis.get('row_count', 0)}") for tf, info in analysis.get('timeframes', {}).items(): age = info.get('age_seconds') age_str = f"{age}s ago" if age else "N/A" print(f" [{tf}]: {info['count']} rows, latest: {age_str}") # Configuration print("\n" + "=" * 70) print("CONFIGURATION") print("=" * 70) cfg = health.get('config', {}) print(f"Min Confidence: {cfg.get('min_confidence', 'N/A')}") print(f"Cooldown: {cfg.get('cooldown_seconds', 'N/A')}s") print(f"Lookback: {cfg.get('lookback', 'N/A')} candles") if cfg.get('weights'): print(f"Weights:") for indicator, weight in cfg['weights'].items(): print(f" {indicator:12s} {weight}") if health['recent_signals']: print("\n" + "=" * 60) print("RECENT SIGNALS") print("=" * 60) for sig in health['recent_signals']: print(f" [{sig['timeframe']}] {sig['signal']} @ ${sig['price']:.2f} " f"(conf: {sig['confidence']:.2f})") print(f" Reasons: {', '.join(sig['reasons'])}") print("=" * 60) return 0 except FileNotFoundError: print(f"Error: Socket not found at {socket_path}") print("Is the signal generator running?") return 1 except ConnectionRefusedError: print(f"Error: Connection refused at {socket_path}") return 1 except Exception as e: print(f"Error: {e}") return 1 if __name__ == "__main__": socket_path = sys.argv[1] if len(sys.argv) > 1 else "/tmp/signals_health.sock" sys.exit(check_health(socket_path))