#!/usr/bin/env python3 """ Test Script for Real-time RL COB Trader This script tests the real-time reinforcement learning system to ensure: 1. Proper model initialization and parameter count (~1B parameters) 2. COB data integration and feature extraction 3. Real-time inference pipeline 4. Signal accumulation and consensus 5. Training loop functionality 6. Trade execution integration Run this before deploying the live system. """ import asyncio import logging import numpy as np import torch import time import json from datetime import datetime from typing import Dict, Any # Local imports from core.realtime_rl_cob_trader import RealtimeRLCOBTrader, MassiveRLNetwork, PredictionResult from core.trading_executor import TradingExecutor # Configure logging logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) logger = logging.getLogger(__name__) class RealtimeRLTester: """ Comprehensive tester for Real-time RL COB Trader """ def __init__(self): self.test_results = {} self.trader = None self.trading_executor = None async def run_all_tests(self): """Run all tests and generate report""" logger.info("=" * 60) logger.info("REAL-TIME RL COB TRADER TESTING SUITE") logger.info("=" * 60) tests = [ self.test_model_initialization, self.test_model_parameter_count, self.test_feature_extraction, self.test_inference_performance, self.test_signal_accumulation, self.test_training_pipeline, self.test_trading_integration, self.test_performance_monitoring ] for test in tests: try: await test() except Exception as e: logger.error(f"Test {test.__name__} failed: {e}") self.test_results[test.__name__] = {'status': 'FAILED', 'error': str(e)} await self.generate_test_report() async def test_model_initialization(self): """Test model initialization and architecture""" logger.info("🧠 Testing Model Initialization...") try: # Test model creation model = MassiveRLNetwork(input_size=2000, hidden_size=4096, num_layers=12) # Check if CUDA is available device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') model = model.to(device) # Test forward pass batch_size = 4 test_input = torch.randn(batch_size, 2000).to(device) with torch.no_grad(): outputs = model(test_input) # Verify outputs assert 'price_logits' in outputs assert 'value' in outputs assert 'confidence' in outputs assert 'features' in outputs assert outputs['price_logits'].shape == (batch_size, 3) # DOWN, SIDEWAYS, UP assert outputs['value'].shape == (batch_size, 1) assert outputs['confidence'].shape == (batch_size, 1) self.test_results['test_model_initialization'] = { 'status': 'PASSED', 'device': str(device), 'output_shapes': {k: list(v.shape) for k, v in outputs.items()} } logger.info("āœ… Model initialization test PASSED") except Exception as e: self.test_results['test_model_initialization'] = {'status': 'FAILED', 'error': str(e)} raise async def test_model_parameter_count(self): """Test that model has approximately 1B parameters""" logger.info("šŸ”¢ Testing Model Parameter Count...") try: model = MassiveRLNetwork(input_size=2000, hidden_size=4096, num_layers=12) total_params = sum(p.numel() for p in model.parameters()) trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad) logger.info(f"Total parameters: {total_params:,}") logger.info(f"Trainable parameters: {trainable_params:,}") self.test_results['test_model_parameter_count'] = { 'status': 'PASSED', 'total_parameters': total_params, 'trainable_parameters': trainable_params, 'parameter_size_gb': (total_params * 4) / (1024**3), # 4 bytes per float32 'is_massive': total_params > 100_000_000 # At least 100M parameters } logger.info(f"āœ… Model has {total_params:,} parameters ({total_params/1e9:.2f}B)") except Exception as e: self.test_results['test_model_parameter_count'] = {'status': 'FAILED', 'error': str(e)} raise async def test_feature_extraction(self): """Test feature extraction from COB data""" logger.info("šŸ” Testing Feature Extraction...") try: # Initialize trader self.trading_executor = TradingExecutor(simulation_mode=True) self.trader = RealtimeRLCOBTrader( symbols=['BTC/USDT'], trading_executor=self.trading_executor, inference_interval_ms=1000 # Slower for testing ) # Create mock COB data mock_cob_data = { 'state': np.random.randn(1500), # Mock state features 'timestamp': datetime.now(), 'type': 'cob_state' } # Test feature extraction features = self.trader._extract_features('BTC/USDT', mock_cob_data) assert features is not None assert len(features) == 2000 # Target feature size assert features.dtype == np.float32 assert not np.any(np.isnan(features)) assert not np.any(np.isinf(features)) # Test normalization assert np.abs(np.mean(features)) < 1.0 # Roughly normalized assert np.std(features) < 10.0 # Not too spread out self.test_results['test_feature_extraction'] = { 'status': 'PASSED', 'feature_size': len(features), 'feature_range': [float(np.min(features)), float(np.max(features))], 'feature_stats': { 'mean': float(np.mean(features)), 'std': float(np.std(features)), 'median': float(np.median(features)) } } logger.info("āœ… Feature extraction test PASSED") except Exception as e: self.test_results['test_feature_extraction'] = {'status': 'FAILED', 'error': str(e)} raise async def test_inference_performance(self): """Test inference speed and quality""" logger.info("⚔ Testing Inference Performance...") try: if not self.trader: self.trading_executor = TradingExecutor(simulation_mode=True) self.trader = RealtimeRLCOBTrader( symbols=['BTC/USDT'], trading_executor=self.trading_executor ) # Test multiple inferences num_tests = 10 inference_times = [] for i in range(num_tests): # Create test features test_features = np.random.randn(2000).astype(np.float32) test_features = self.trader._normalize_features(test_features) # Time inference start_time = time.time() prediction = self.trader._predict('BTC/USDT', test_features) inference_time = (time.time() - start_time) * 1000 inference_times.append(inference_time) # Verify prediction structure assert 'direction' in prediction assert 'confidence' in prediction assert 'change' in prediction assert 'value' in prediction assert 0 <= prediction['direction'] <= 2 assert 0.0 <= prediction['confidence'] <= 1.0 assert isinstance(prediction['change'], float) assert isinstance(prediction['value'], float) avg_inference_time = np.mean(inference_times) max_inference_time = np.max(inference_times) # Check if inference is fast enough (target: <50ms per inference) inference_target_ms = 50.0 self.test_results['test_inference_performance'] = { 'status': 'PASSED' if avg_inference_time < inference_target_ms else 'WARNING', 'average_inference_time_ms': float(avg_inference_time), 'max_inference_time_ms': float(max_inference_time), 'target_time_ms': inference_target_ms, 'meets_target': avg_inference_time < inference_target_ms, 'inferences_per_second': 1000.0 / avg_inference_time } logger.info(f"āœ… Average inference time: {avg_inference_time:.2f}ms") logger.info(f"āœ… Max inference time: {max_inference_time:.2f}ms") logger.info(f"āœ… Inferences per second: {1000.0/avg_inference_time:.1f}") except Exception as e: self.test_results['test_inference_performance'] = {'status': 'FAILED', 'error': str(e)} raise async def test_signal_accumulation(self): """Test signal accumulation and consensus logic""" logger.info("šŸŽÆ Testing Signal Accumulation...") try: if not self.trader: self.trading_executor = TradingExecutor(simulation_mode=True) self.trader = RealtimeRLCOBTrader( symbols=['BTC/USDT'], trading_executor=self.trading_executor, required_confident_predictions=3 ) symbol = 'BTC/USDT' accumulator = self.trader.signal_accumulators[symbol] # Test adding signals test_predictions = [] for i in range(5): prediction = PredictionResult( timestamp=datetime.now(), symbol=symbol, predicted_direction=2, # UP confidence=0.8, predicted_change=0.001, features=np.random.randn(2000).astype(np.float32) ) test_predictions.append(prediction) self.trader._add_signal(symbol, prediction) # Check accumulator state assert len(accumulator.signals) == 5 assert accumulator.confidence_sum == 5 * 0.8 assert accumulator.total_predictions == 5 # Test consensus logic (simulate processing) recent_signals = list(accumulator.signals)[-3:] directions = [signal.predicted_direction for signal in recent_signals] # All should be direction 2 (UP) direction_counts = {0: 0, 1: 0, 2: 0} for direction in directions: direction_counts[direction] += 1 dominant_direction = max(direction_counts, key=direction_counts.get) consensus_count = direction_counts[dominant_direction] assert dominant_direction == 2 assert consensus_count == 3 self.test_results['test_signal_accumulation'] = { 'status': 'PASSED', 'signals_added': len(accumulator.signals), 'confidence_sum': accumulator.confidence_sum, 'consensus_direction': dominant_direction, 'consensus_count': consensus_count } logger.info("āœ… Signal accumulation test PASSED") except Exception as e: self.test_results['test_signal_accumulation'] = {'status': 'FAILED', 'error': str(e)} raise async def test_training_pipeline(self): """Test training pipeline functionality""" logger.info("🧠 Testing Training Pipeline...") try: if not self.trader: self.trading_executor = TradingExecutor(simulation_mode=True) self.trader = RealtimeRLCOBTrader( symbols=['BTC/USDT'], trading_executor=self.trading_executor ) symbol = 'BTC/USDT' # Create mock training data test_predictions = [] for i in range(10): prediction = PredictionResult( timestamp=datetime.now(), symbol=symbol, predicted_direction=np.random.randint(0, 3), confidence=np.random.uniform(0.5, 1.0), predicted_change=np.random.uniform(-0.001, 0.001), features=np.random.randn(2000).astype(np.float32), actual_direction=np.random.randint(0, 3), actual_change=np.random.uniform(-0.001, 0.001), reward=np.random.uniform(-1.0, 1.0) ) test_predictions.append(prediction) # Test training batch loss = await self.trader._train_batch(symbol, test_predictions) assert isinstance(loss, float) assert not np.isnan(loss) assert not np.isinf(loss) assert loss >= 0.0 # Loss should be non-negative self.test_results['test_training_pipeline'] = { 'status': 'PASSED', 'training_loss': float(loss), 'batch_size': len(test_predictions), 'training_successful': True } logger.info(f"āœ… Training pipeline test PASSED (loss: {loss:.6f})") except Exception as e: self.test_results['test_training_pipeline'] = {'status': 'FAILED', 'error': str(e)} raise async def test_trading_integration(self): """Test integration with trading executor""" logger.info("šŸ’° Testing Trading Integration...") try: # Initialize with simulation mode trading_executor = TradingExecutor(simulation_mode=True) # Test signal execution success = trading_executor.execute_signal( symbol='BTC/USDT', action='BUY', confidence=0.8, current_price=50000.0 ) # In simulation mode, this should always succeed assert success == True # Check positions positions = trading_executor.get_positions() assert 'BTC/USDT' in positions # Test sell signal success = trading_executor.execute_signal( symbol='BTC/USDT', action='SELL', confidence=0.8, current_price=50100.0 ) assert success == True # Check trade history trade_history = trading_executor.get_trade_history() assert len(trade_history) > 0 last_trade = trade_history[-1] assert last_trade.symbol == 'BTC/USDT' assert last_trade.pnl != 0 # Should have some P&L self.test_results['test_trading_integration'] = { 'status': 'PASSED', 'simulation_mode': True, 'trades_executed': len(trade_history), 'last_trade_pnl': float(last_trade.pnl) } logger.info("āœ… Trading integration test PASSED") except Exception as e: self.test_results['test_trading_integration'] = {'status': 'FAILED', 'error': str(e)} raise async def test_performance_monitoring(self): """Test performance monitoring and statistics""" logger.info("šŸ“Š Testing Performance Monitoring...") try: if not self.trader: self.trading_executor = TradingExecutor(simulation_mode=True) self.trader = RealtimeRLCOBTrader( symbols=['BTC/USDT', 'ETH/USDT'], trading_executor=self.trading_executor ) # Get performance stats stats = self.trader.get_performance_stats() # Verify structure assert 'symbols' in stats assert 'training_stats' in stats assert 'inference_stats' in stats assert 'signal_stats' in stats assert 'model_info' in stats # Check symbols assert 'BTC/USDT' in stats['symbols'] assert 'ETH/USDT' in stats['symbols'] # Check model info for symbol in stats['symbols']: assert symbol in stats['model_info'] model_info = stats['model_info'][symbol] assert 'total_parameters' in model_info assert 'trainable_parameters' in model_info assert model_info['total_parameters'] > 0 self.test_results['test_performance_monitoring'] = { 'status': 'PASSED', 'stats_structure_valid': True, 'symbols_tracked': len(stats['symbols']), 'model_info_available': len(stats['model_info']) } logger.info("āœ… Performance monitoring test PASSED") except Exception as e: self.test_results['test_performance_monitoring'] = {'status': 'FAILED', 'error': str(e)} raise async def generate_test_report(self): """Generate comprehensive test report""" logger.info("=" * 60) logger.info("REAL-TIME RL COB TRADER TEST REPORT") logger.info("=" * 60) total_tests = len(self.test_results) passed_tests = sum(1 for result in self.test_results.values() if result['status'] == 'PASSED') failed_tests = sum(1 for result in self.test_results.values() if result['status'] == 'FAILED') warning_tests = sum(1 for result in self.test_results.values() if result['status'] == 'WARNING') logger.info(f"šŸ“Š Test Summary:") logger.info(f" Total Tests: {total_tests}") logger.info(f" āœ… Passed: {passed_tests}") logger.info(f" āš ļø Warnings: {warning_tests}") logger.info(f" āŒ Failed: {failed_tests}") success_rate = (passed_tests / total_tests) * 100 if total_tests > 0 else 0 logger.info(f" Success Rate: {success_rate:.1f}%") logger.info("\nšŸ“‹ Detailed Results:") for test_name, result in self.test_results.items(): status_icon = "āœ…" if result['status'] == 'PASSED' else "āš ļø" if result['status'] == 'WARNING' else "āŒ" logger.info(f" {status_icon} {test_name}: {result['status']}") if result['status'] == 'FAILED': logger.error(f" Error: {result.get('error', 'Unknown error')}") # System readiness assessment logger.info("\nšŸŽÆ System Readiness Assessment:") if failed_tests == 0: if warning_tests == 0: logger.info(" 🟢 SYSTEM READY FOR DEPLOYMENT") logger.info(" All tests passed. The real-time RL COB trader is ready for live operation.") else: logger.info(" 🟔 SYSTEM READY WITH WARNINGS") logger.info(" System is functional but some performance warnings exist.") else: logger.info(" šŸ”“ SYSTEM NOT READY") logger.info(" Critical issues found. Fix errors before deployment.") # Save detailed report report_data = { 'timestamp': datetime.now().isoformat(), 'test_summary': { 'total_tests': total_tests, 'passed_tests': passed_tests, 'warning_tests': warning_tests, 'failed_tests': failed_tests, 'success_rate': success_rate }, 'test_results': self.test_results, 'system_readiness': 'READY' if failed_tests == 0 else 'NOT_READY' } report_file = f"test_reports/realtime_rl_test_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json" import os os.makedirs('test_reports', exist_ok=True) with open(report_file, 'w') as f: json.dump(report_data, f, indent=2, default=str) logger.info(f"\nšŸ“„ Detailed report saved to: {report_file}") logger.info("=" * 60) async def main(): """Main test entry point""" logger.info("Starting Real-time RL COB Trader Test Suite...") tester = RealtimeRLTester() await tester.run_all_tests() if __name__ == "__main__": # Set event loop policy for Windows compatibility if hasattr(asyncio, 'WindowsProactorEventLoopPolicy'): asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy()) asyncio.run(main())