import importlib.util import sys import types from pathlib import Path def load_system_module(): system_path = Path(__file__).resolve().parents[1] / "app" / "api" / "system.py" if "app" not in sys.modules: app_pkg = types.ModuleType("app") app_pkg.__path__ = [str(system_path.parents[2] / "app")] sys.modules["app"] = app_pkg for pkg_name, pkg_path in [ ("app.api", system_path.parent), ("app.utils", system_path.parents[1] / "utils"), ("app.crypto_agent", system_path.parents[1] / "crypto_agent"), ("app.services", system_path.parents[1] / "services"), ]: if pkg_name not in sys.modules: pkg = types.ModuleType(pkg_name) pkg.__path__ = [str(pkg_path)] sys.modules[pkg_name] = pkg fastapi_module = types.ModuleType("fastapi") class DummyRouter: def get(self, *args, **kwargs): def decorator(fn): return fn return decorator class DummyHTTPException(Exception): pass fastapi_module.APIRouter = lambda: DummyRouter() fastapi_module.HTTPException = DummyHTTPException sys.modules["fastapi"] = fastapi_module logger_module = types.ModuleType("app.utils.logger") logger_module.logger = types.SimpleNamespace(error=lambda *a, **k: None, warning=lambda *a, **k: None) sys.modules["app.utils.logger"] = logger_module system_status_module = types.ModuleType("app.utils.system_status") system_status_module.get_system_monitor = lambda: None sys.modules["app.utils.system_status"] = system_status_module crypto_agent_module = types.ModuleType("app.crypto_agent.crypto_agent") crypto_agent_module.get_crypto_agent = lambda: None sys.modules["app.crypto_agent.crypto_agent"] = crypto_agent_module signal_db_module = types.ModuleType("app.services.signal_database_service") signal_db_module.get_signal_db_service = lambda: None sys.modules["app.services.signal_database_service"] = signal_db_module paper_module = types.ModuleType("app.services.paper_trading_service") paper_module.get_paper_trading_service = lambda: None sys.modules["app.services.paper_trading_service"] = paper_module bitget_module = types.ModuleType("app.services.bitget_live_trading_service") bitget_module.get_all_bitget_live_services = lambda: {} bitget_module.get_bitget_live_service = lambda: None sys.modules["app.services.bitget_live_trading_service"] = bitget_module module_name = "app.api.system_console_test" spec = importlib.util.spec_from_file_location(module_name, system_path) module = importlib.util.module_from_spec(spec) sys.modules[module_name] = module spec.loader.exec_module(module) return module def test_normalize_platform_position_preserves_setup_fields(): module = load_system_module() item = module._normalize_platform_position( "paper", { "symbol": "BTCUSDT", "side": "buy", "entry_price": 100.0, "mark_price": 101.0, "size": 1.2, "take_profit": 106.0, "stop_loss": 98.0, "setup_type": "trend_continuation_pullback", "setup_basis": "setup=trend_continuation_pullback | pullback_quality=healthy_pullback", "entry_basis": "pullback_into_trade_zone", }, ) assert item["setup_type"] == "trend_continuation_pullback" assert "healthy_pullback" in item["setup_basis"] assert item["entry_basis"] == "pullback_into_trade_zone" def test_normalize_platform_order_preserves_setup_fields(): module = load_system_module() item = module._normalize_platform_order( "bitget", { "symbol": "ETHUSDT", "side": "sell", "price": 2000.0, "size": 3, "status": "pending", "entry_type": "limit", "setup_type": "range_reversal", "setup_basis": "setup=range_reversal | location=near_range_resistance", "entry_basis": "reversal_from_near_range_resistance", }, ) assert item["setup_type"] == "range_reversal" assert "near_range_resistance" in item["setup_basis"] assert item["entry_basis"] == "reversal_from_near_range_resistance"