import pytest from okx_codex_trader.strategy import validate_signal @pytest.mark.parametrize( ("field_name", "field_value"), [ ("confidence", True), ("leverage", True), ("entry_price", True), ("take_profit_price", False), ("stop_loss_price", True), ], ) def test_validate_signal_rejects_boolean_numeric_fields(field_name, field_value): signal = { "action": "long", "confidence": 0.9, "leverage": 2, "entry_price": None, "take_profit_price": None, "stop_loss_price": None, "reason": "x", } signal[field_name] = field_value with pytest.raises(ValueError): validate_signal(signal) def test_validate_signal_rejects_leverage_out_of_range(): with pytest.raises(ValueError): validate_signal( { "action": "long", "confidence": 0.9, "leverage": 4, "entry_price": None, "take_profit_price": None, "stop_loss_price": None, "reason": "x", } ) def test_validate_signal_rejects_unknown_action(): with pytest.raises(ValueError): validate_signal( { "action": "hold", "confidence": 0.9, "leverage": 2, "entry_price": None, "take_profit_price": None, "stop_loss_price": None, "reason": "x", } ) def test_validate_signal_rejects_confidence_out_of_range(): with pytest.raises(ValueError): validate_signal( { "action": "long", "confidence": 1.2, "leverage": 2, "entry_price": None, "take_profit_price": None, "stop_loss_price": None, "reason": "x", } ) def test_validate_signal_requires_full_shape(): with pytest.raises(ValueError): validate_signal({"action": "long", "confidence": 0.9, "leverage": 2}) def test_validate_signal_returns_trade_signal(): signal = validate_signal( { "action": "short", "confidence": 0.75, "leverage": 3, "entry_price": 101.5, "take_profit_price": 98, "stop_loss_price": None, "reason": "trend", } ) assert signal.action == "short" assert signal.confidence == 0.75 assert signal.leverage == 3 assert signal.entry_price == 101.5 assert signal.take_profit_price == 98.0 assert signal.stop_loss_price is None assert signal.reason == "trend"