#!/usr/bin/env python3 """ CLEAN ARCHITECTURE - DOLPHIN PAPER TRADER ========================================== 🙏 God bless clean code and synchronized data 🙏 Architecture: ┌──────────────────────────────────────────────┐ │ CORE: TradingEngine (pure Python) │ │ - Business logic only │ │ - No external dependencies │ │ - Ready for Rust rewrite │ └──────────────────┬───────────────────────────┘ │ uses PORT ↓ ┌──────────────────────────────────────────────┐ │ PORT: DataFeedPort (interface) │ │ - Abstract interface │ │ - Easy to swap implementations │ └──────────────────┬───────────────────────────┘ │ implemented by ↓ ┌──────────────────────────────────────────────┐ │ ADAPTER: HazelcastDataFeed │ │ - Current implementation │ │ - Single source: DolphinNG6 → Hazelcast │ │ - No sync issues │ └──────────────────────────────────────────────┘ Evolution Path: Phase 1 (NOW): HazelcastDataFeed (this file) Phase 2: BinanceWebsocketFeed (direct connection) Phase 3: RustKernelFeed (in-kernel, zero-copy) Usage: python clean_arch/main.py """ import asyncio import sys import logging from pathlib import Path # Setup paths PROJECT_ROOT = Path(__file__).parent.parent sys.path.insert(0, str(PROJECT_ROOT / 'nautilus_dolphin')) sys.path.insert(0, str(PROJECT_ROOT)) sys.path.insert(0, str(Path(__file__).parent)) # Logging logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) logger = logging.getLogger("DOLPHIN-CLEAN-ARCH") # Import clean architecture components from adapters.hazelcast_feed import HazelcastDataFeed from core.trading_engine import TradingEngine # ============================================================================= # CONFIGURATION # ============================================================================= CONFIG = { 'trader_id': 'DOLPHIN-CLEAN-01', 'venue': 'BINANCE_FUTURES', # Hazelcast configuration (current adapter) 'hazelcast': { 'cluster': 'dolphin', 'host': 'localhost:5701', }, # Trading parameters 'initial_capital': 25000.0, 'max_leverage': 5.0, 'capital_fraction': 0.20, 'min_irp_alignment': 0.45, 'vel_div_threshold': -0.02, } async def main(): """ Main entry point - wires clean architecture together. """ logger.info("=" * 70) logger.info("🐬 DOLPHIN CLEAN ARCHITECTURE") logger.info("=" * 70) logger.info(f"Trader ID: {CONFIG['trader_id']}") logger.info(f"Venue: {CONFIG['venue']}") logger.info(f"Data Feed: Hazelcast (DolphinNG6)") logger.info(f"Architecture: Clean / Hexagonal") logger.info(f"Evolution Ready: Yes (in-kernel future)") logger.info("=" * 70) # ================================================================= # WIRE COMPONENTS # ================================================================= # 1. Create Data Feed Adapter (ADAPTER layer) # - Currently: Hazelcast # - Future: Can swap to BinanceWebsocket or RustKernel logger.info("[1/3] Creating data feed adapter...") data_feed = HazelcastDataFeed(CONFIG) logger.info(" ✓ Hazelcast adapter created") # 2. Create Trading Engine (CORE layer) # - Pure business logic # - No knowledge of Hazelcast # - Works with ANY DataFeedPort implementation logger.info("[2/3] Creating trading engine...") engine = TradingEngine(data_feed, CONFIG) logger.info(" ✓ Trading engine created") logger.info(" ✓ Core is adapter-agnostic") # 3. Start system logger.info("[3/3] Starting system...") logger.info("=" * 70) try: await engine.start() except KeyboardInterrupt: logger.info("\nShutdown requested...") await engine.stop() except Exception as e: logger.error(f"Fatal error: {e}") await engine.stop() raise if __name__ == "__main__": asyncio.run(main())