Team Ai
Modelpublic

ParallelLLC/algorithmic_trading

sourceHugging Faceapache-2.0updated 2mo agoView on Hugging Face
27likes32downloads
test_execution_agent.py300 linesDownload Raw Back to tests
1import pytest2import time3from unittest.mock import patch, MagicMock4from agentic_ai_system.execution_agent import ExecutionAgent5 6class TestExecutionAgent:7    """Test cases for ExecutionAgent"""8    9    @pytest.fixture10    def config(self):11        """Sample configuration for testing"""12        return {13            'execution': {14                'broker_api': 'paper',15                'order_size': 10,16                'delay_ms': 50,17                'success_rate': 0.9518            },19            'trading': {20                'symbol': 'AAPL',21                'timeframe': '1min',22                'capital': 10000023            },24            'risk': {25                'max_position': 100,26                'max_drawdown': 0.0527            }28        }29    30    @pytest.fixture31    def execution_agent(self, config):32        """Create an ExecutionAgent instance"""33        return ExecutionAgent(config)34    35    @pytest.fixture36    def valid_signal(self):37        """Create a valid trading signal"""38        return {39            'action': 'buy',40            'symbol': 'AAPL',41            'quantity': 10,42            'price': 150.0,43            'confidence': 0.844        }45    46    def test_initialization(self, execution_agent, config):47        """Test agent initialization"""48        assert execution_agent.broker_api == config['execution']['broker_api']49        assert execution_agent.order_size == config['execution']['order_size']50        assert execution_agent.execution_delay == config['execution']['delay_ms']51        assert execution_agent.success_rate == config['execution']['success_rate']52    53    def test_act_with_valid_signal(self, execution_agent, valid_signal):54        """Test order execution with valid signal"""55        result = execution_agent.act(valid_signal)56        57        # Check result structure58        assert isinstance(result, dict)59        assert 'order_id' in result60        assert 'status' in result61        assert 'action' in result62        assert 'symbol' in result63        assert 'quantity' in result64        assert 'price' in result65        assert 'execution_time' in result66        assert 'commission' in result67        assert 'total_value' in result68        assert 'success' in result69        assert 'error' in result70        71        # Check values72        assert result['action'] == valid_signal['action']73        assert result['symbol'] == valid_signal['symbol']74        assert result['quantity'] == valid_signal['quantity']75        assert result['price'] > 076        assert result['execution_time'] > 077        assert result['commission'] >= 078        assert result['total_value'] >= 079    80    def test_act_with_hold_signal(self, execution_agent):81        """Test order execution with hold signal"""82        hold_signal = {83            'action': 'hold',84            'symbol': 'AAPL',85            'quantity': 0,86            'price': 0,87            'confidence': 0.088        }89        90        result = execution_agent.act(hold_signal)91        92        assert result['action'] == 'hold'93        assert result['quantity'] == 094        assert result['success'] == True  # Hold should always succeed95    96    def test_validate_signal_valid(self, execution_agent, valid_signal):97        """Test signal validation with valid signal"""98        assert execution_agent._validate_signal(valid_signal) == True99    100    def test_validate_signal_missing_fields(self, execution_agent):101        """Test signal validation with missing fields"""102        invalid_signal = {'action': 'buy'}  # Missing symbol and quantity103        104        assert execution_agent._validate_signal(invalid_signal) == False105    106    def test_validate_signal_invalid_action(self, execution_agent):107        """Test signal validation with invalid action"""108        invalid_signal = {109            'action': 'invalid_action',110            'symbol': 'AAPL',111            'quantity': 10112        }113        114        assert execution_agent._validate_signal(invalid_signal) == False115    116    def test_validate_signal_invalid_quantity(self, execution_agent):117        """Test signal validation with invalid quantity"""118        invalid_signal = {119            'action': 'buy',120            'symbol': 'AAPL',121            'quantity': -5  # Negative quantity122        }123        124        assert execution_agent._validate_signal(invalid_signal) == False125    126    def test_validate_signal_invalid_symbol(self, execution_agent):127        """Test signal validation with invalid symbol"""128        invalid_signal = {129            'action': 'buy',130            'symbol': '',  # Empty symbol131            'quantity': 10132        }133        134        assert execution_agent._validate_signal(invalid_signal) == False135    136    def test_calculate_commission(self, execution_agent):137        """Test commission calculation"""138        # Test buy order139        buy_signal = {'action': 'buy', 'quantity': 10}140        commission_buy = execution_agent._calculate_commission(buy_signal)141        142        # Base commission ($1) + per share commission ($0.01 * 10) = $1.10143        expected_commission = 1.0 + (10 * 0.01)144        assert commission_buy == expected_commission145        146        # Test sell order147        sell_signal = {'action': 'sell', 'quantity': 5}148        commission_sell = execution_agent._calculate_commission(sell_signal)149        150        expected_commission = 1.0 + (5 * 0.01)151        assert commission_sell == expected_commission152        153        # Test hold order (no commission)154        hold_signal = {'action': 'hold', 'quantity': 0}155        commission_hold = execution_agent._calculate_commission(hold_signal)156        157        assert commission_hold == 0.0158    159    def test_generate_order_id(self, execution_agent):160        """Test order ID generation"""161        order_id = execution_agent._generate_order_id()162        163        assert isinstance(order_id, str)164        assert order_id.startswith('ORD_')165        assert len(order_id) == 12  # 'ORD_' + 8 hex characters166    167    def test_simulate_successful_execution(self, execution_agent, valid_signal):168        """Test successful execution simulation"""169        result = execution_agent._simulate_successful_execution(valid_signal)170        171        assert result['status'] == 'filled'172        assert result['success'] == True173        assert result['error'] is None174        assert result['order_id'] is not None175        assert result['price'] > 0176        assert result['total_value'] > 0177    178    def test_simulate_failed_execution(self, execution_agent, valid_signal):179        """Test failed execution simulation"""180        result = execution_agent._simulate_failed_execution(valid_signal)181        182        assert result['status'] == 'rejected'183        assert result['success'] == False184        assert result['error'] is not None185        assert result['order_id'] is None186        assert result['price'] == 0187        assert result['total_value'] == 0188    189    def test_generate_execution_result(self, execution_agent, valid_signal):190        """Test execution result generation"""191        # Test successful result192        success_result = execution_agent._generate_execution_result(valid_signal, True)193        194        assert success_result['status'] == 'filled'195        assert success_result['success'] == True196        assert success_result['order_id'] is not None197        198        # Test failed result199        failed_result = execution_agent._generate_execution_result(valid_signal, False, "Test error")200        201        assert failed_result['status'] == 'rejected'202        assert failed_result['success'] == False203        assert failed_result['error'] == "Test error"204        assert failed_result['order_id'] is None205    206    def test_execution_delay(self, execution_agent, valid_signal):207        """Test that execution delay is applied"""208        start_time = time.time()209        210        with patch('time.sleep') as mock_sleep:211            execution_agent._execute_order(valid_signal)212            mock_sleep.assert_called_once()213            214            # Check that sleep was called with the correct delay215            call_args = mock_sleep.call_args[0][0]216            expected_delay = execution_agent.execution_delay / 1000.0217            assert abs(call_args - expected_delay) < 0.001218    219    def test_success_rate_simulation(self, execution_agent, valid_signal):220        """Test success rate simulation"""221        # Set success rate to 0.0 (should always fail)222        execution_agent.success_rate = 0.0223        224        with patch('random.random', return_value=0.5):  # Always above 0.0225            result = execution_agent._execute_order(valid_signal)226            assert result['success'] == False227        228        # Set success rate to 1.0 (should always succeed)229        execution_agent.success_rate = 1.0230        231        with patch('random.random', return_value=0.5):  # Always below 1.0232            result = execution_agent._execute_order(valid_signal)233            assert result['success'] == True234    235    def test_error_handling_in_execution(self, execution_agent, valid_signal):236        """Test error handling during execution"""237        # Mock _simulate_successful_execution to raise an exception238        with patch.object(execution_agent, '_simulate_successful_execution', side_effect=Exception("Test error")):239            result = execution_agent._execute_order(valid_signal)240            241            assert result['success'] == False242            assert "Test error" in result['error']243    244    def test_get_execution_statistics(self, execution_agent):245        """Test execution statistics retrieval"""246        stats = execution_agent.get_execution_statistics()247        248        expected_keys = [249            'total_orders', 'successful_orders', 'failed_orders',250            'success_rate', 'average_execution_time', 'total_commission'251        ]252        253        for key in expected_keys:254            assert key in stats255        256        # Check default values257        assert stats['total_orders'] == 0258        assert stats['successful_orders'] == 0259        assert stats['failed_orders'] == 0260        assert stats['success_rate'] == 0.0261        assert stats['average_execution_time'] == 0.0262        assert stats['total_commission'] == 0.0263    264    def test_price_slippage_simulation(self, execution_agent, valid_signal):265        """Test price slippage simulation"""266        # Mock random.uniform to return a known slippage value267        with patch('random.uniform', return_value=0.001):  # 0.1% slippage268            result = execution_agent._simulate_successful_execution(valid_signal)269            270            # Price should be slightly different from original271            original_price = valid_signal['price']272            executed_price = result['price']273            274            # Should be within 0.2% of original price275            price_diff = abs(executed_price - original_price) / original_price276            assert price_diff <= 0.002277    278    def test_commission_calculation_edge_cases(self, execution_agent):279        """Test commission calculation edge cases"""280        # Test with zero quantity281        zero_signal = {'action': 'buy', 'quantity': 0}282        commission_zero = execution_agent._calculate_commission(zero_signal)283        assert commission_zero == 1.0  # Only base commission284        285        # Test with very large quantity286        large_signal = {'action': 'sell', 'quantity': 10000}287        commission_large = execution_agent._calculate_commission(large_signal)288        expected_large = 1.0 + (10000 * 0.01)289        assert commission_large == expected_large290    291    def test_order_id_uniqueness(self, execution_agent):292        """Test that order IDs are unique"""293        order_ids = set()294        295        for _ in range(100):296            order_id = execution_agent._generate_order_id()297            order_ids.add(order_id)298        299        # All order IDs should be unique300        assert len(order_ids) == 100