import sys import os import json import math import signal from unittest.mock import MagicMock, patch if not hasattr(signal, 'SIGHUP'): signal.SIGHUP = 1 # Configure pathing for local test execution sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '../nautilus_dolphin'))) from nautilus_dolphin.nautilus.adaptive_circuit_breaker import AdaptiveCircuitBreaker, ACBConfig # 1. TEST ACB INTERNAL FUNCTIONING (Internal Logic Validity) def test_acb_internal_functioning(): print("\n--- Running ACBv6 Internal Unit Tests ---") acb = AdaptiveCircuitBreaker() # Simulate a HZ snapshot with some bearish values mock_snapshot = { 'funding_btc': -0.0002, # Very Bearish -> 1 signal 'dvol_btc': 85.0, # Extreme -> 1 signal 'fng': 20.0, # Extreme Fear -> 1 signal 'taker': 0.7, # Very high selling -> 1 signal '_staleness_s': {'funding_btc': 100} } # Calculate boost from these factors (which should generate max signal count = 4.0) info = acb.get_dynamic_boost_from_hz("2026-04-10", mock_snapshot, w750_velocity=0.005) assert info['cut'] == 0.0, "ACBv6 inverse mode should never cut position" assert info['signals'] == 4.0, f"Expected 4.0 signals, got {info['signals']}" # Mathematical confirmation of log_0.5 inverse boost curve expectations expected_boost = 1.0 + 0.5 * math.log1p(info['signals']) # 1.0 + 0.5 * ln(5) == 1.804 assert math.isclose(info['boost'], expected_boost, rel_tol=1e-3), ( f"Boost math failure. Expected '{expected_boost:.3f}', got '{info['boost']:.3f}'" ) # Test w750 velocity fallback/caching # Should be pre-cached now assert acb._w750_vel_cache["2026-04-10"] == 0.005, "w750_velocity should be correctly stored" print(f"ACB internal functions properly handle HZ conversion and log_0.5 boost (Yields ~{expected_boost:.3f}x leverage multiplier on 4-signal stress).") # 2. TEST NAUTILUS EVENT TRADER WIRING (Structural Pipeline Validation) def test_trader_acb_wiring(): print("\n--- Running DolphinLiveTrader ACB Wiring Tests ---") # We must patch thread pools and hz client to test DolphinLiveTrader in isolation with patch('concurrent.futures.ThreadPoolExecutor'): with patch('prod.nautilus_event_trader.create_d_liq_engine'): # Mock the Linux-only exit handler module so it imports locally on Windows mock_exit = MagicMock() sys.modules['dolphin_exit_handler'] = mock_exit import prod.nautilus_event_trader as net # Instantiate trader trader = net.DolphinLiveTrader() # Setup mock engine trader.eng = MagicMock() trader.current_day = "2026-04-10" trader.eng_lock = MagicMock() trader.acb = MagicMock() # Trigger exF listener manually mock_exf_snapshot = json.dumps({'dvol_btc': 55.0, 'taker': 0.8}) class MockEvent: def __init__(self, val): self.value = val trader.last_w750_vel = 0.001 trader.on_exf_update(MockEvent(mock_exf_snapshot)) # Ensure acb.get_dynamic_boost_from_hz was called with parameters trader.acb.get_dynamic_boost_from_hz.assert_called_once_with( date_str="2026-04-10", exf_snapshot={'dvol_btc': 55.0, 'taker': 0.8}, w750_velocity=0.001 ) # Ensure engine.update_acb_boost was called if hasattr(trader.eng, 'update_acb_boost'): trader.eng.update_acb_boost.assert_called_once() print("ACB pipeline successfully routes live EXF data into the engine loop.") if __name__ == "__main__": try: test_acb_internal_functioning() test_trader_acb_wiring() print("\nALL UNIT TESTS PASSED SUCCESSFULLY! ACBv6 is securely wired.") except AssertionError as e: print(f"FAILED: {e}") except Exception as e: print(f"ERROR: {e}")