# Nautilus-DOLPHIN / Alpha Engine Core — Implementation Specification **Version:** 1.0 **Date:** 2026-03-22 **Status:** Production-ready (paper trading); live deployment pending exchange integration **Environment:** siloqy-env (`/home/dolphin/siloqy_env/bin/activate`) **Stack:** nautilus_trader 1.219.0 · prefect 3.6.22 · hazelcast-python-client 5.6.0 · numba 0.61.2 --- ## 1. System Overview Nautilus-DOLPHIN is a production algorithmic trading system built on the NautilusTrader Rust-core HFT framework. It wraps a 7-layer alpha engine ("NDAlphaEngine") inside a NautilusTrader Strategy primitive ("DolphinActor"), supervised by Prefect for resilience and Hazelcast for distributed system memory. ### 1.1 Performance Specification (Champion — FROZEN) | Metric | Champion Value | |---|---| | ROI (backtest period) | +54.67% | | Profit Factor | 1.141 | | Sharpe Ratio | 2.84 | | Max Drawdown | 15.80% | | Win Rate | 49.5% | | Direction | SHORT only (blue deployment) | | Bar resolution | 5-second | | Markets | Binance Futures perpetuals (~48 assets) | These numbers are **invariants**. Any code change that causes a statistically significant deviation must be rejected. ### 1.2 Architecture Summary ``` ┌────────────────────────────────────────────────────────────────┐ │ Prefect Supervision Layer │ │ paper_trade_flow.py (00:05 UTC) nautilus_prefect_flow.py │ │ dolphin_nautilus_flow (00:10 UTC) │ └──────────────────────────────┬─────────────────────────────────┘ │ ┌──────────────────────────────▼─────────────────────────────────┐ │ NautilusTrader Execution Kernel │ │ BacktestEngine (paper) / TradingNode (live) │ │ │ │ ┌─────────────────────────────────────────┐ │ │ │ DolphinActor (Strategy) │ │ │ │ on_start() → connect HZ, ACB listener │ │ │ │ on_bar() → step_bar() per 5s tick │ │ │ │ on_stop() → cleanup, HZ shutdown │ │ │ └──────────────────────┬──────────────────┘ │ │ │ │ │ ┌───────────────────────▼──────────────────────────────────┐ │ │ │ NDAlphaEngine │ │ │ │ 7-layer alpha stack (see §4) │ │ │ │ begin_day() / step_bar() / end_day() │ │ │ └───────────────────────────────────────────────────────────┘ │ └──────────────────────────────┬─────────────────────────────────┘ │ ┌──────────────────────────────▼─────────────────────────────────┐ │ Hazelcast "System Memory" │ │ DOLPHIN_SAFETY → posture, Rm (survival stack) │ │ DOLPHIN_FEATURES → ACB boost, beta, eigen scan │ │ DOLPHIN_PNL_BLUE → daily trade results │ │ DOLPHIN_STATE_BLUE→ capital state (continuity) │ │ DOLPHIN_HEARTBEAT → liveness probes │ │ DOLPHIN_FEATURES_SHARD_00..09 → 400-asset feature shards │ └────────────────────────────────────────────────────────────────┘ ``` --- ## 2. File Map ``` /mnt/dolphinng5_predict/ │ ├── prod/ │ ├── paper_trade_flow.py # Primary daily Prefect flow (NDAlphaEngine direct) │ ├── nautilus_prefect_flow.py # Nautilus BacktestEngine Prefect flow (NEW) │ ├── run_nautilus.py # Standalone Nautilus CLI runner │ ├── configs/ │ │ ├── blue.yml # Champion SHORT config (FROZEN) │ │ └── green.yml # Bidirectional config (pending LONG validation) │ └── OBF_SUBSYSTEM.md # OBF architecture reference │ ├── nautilus_dolphin/ │ └── nautilus_dolphin/ │ └── nautilus/ │ ├── dolphin_actor.py # DolphinActor(Strategy) — Nautilus wrapper │ ├── esf_alpha_orchestrator.py # NDAlphaEngine — 7-layer core │ ├── proxy_boost_engine.py # ProxyBoostEngine wrapper (ACBv6 pre-compute) │ ├── adaptive_circuit_breaker.py # ACBv6 — 3-scale regime sizing │ ├── strategy.py # DolphinExecutionStrategy (signal-level) │ ├── strategy_config.py # DolphinStrategyConfig (StrategyConfig subclass) │ ├── launcher.py # NautilusDolphinLauncher (TradingNode) │ ├── ob_features.py # OBFeatureEngine — order book intelligence │ ├── hz_ob_provider.py # HZOBProvider — HZ-backed OB data source │ └── circuit_breaker.py # CircuitBreakerManager │ └── tests/ │ ├── test_0_nautilus_bootstrap.py # 11 foundation tests │ ├── test_dolphin_actor.py # 35 DolphinActor lifecycle tests (NEW) │ ├── test_strategy.py # DolphinExecutionStrategy filter tests │ ├── test_adaptive_circuit_breaker.py │ ├── test_circuit_breaker.py │ ├── test_volatility_detector.py │ └── [12 other test files] │ └── vbt_cache_klines/ # 5s OHLCV parquet files — daily replay source └── YYYY-MM-DD.parquet # cols: vel_div, v50/v150/v300/v750, instability_*, 48 assets ``` --- ## 3. Champion Parameters (FROZEN) These parameters are derived from the champion backtest and **must not be altered** without a full re-validation run showing performance preservation. | Parameter | Value | Description | |---|---|---| | `vel_div_threshold` | -0.02 | Primary signal gate: vd must be ≤ this to open a position | | `vel_div_extreme` | -0.05 | Extreme signal bucket threshold (max leverage tier) | | `fixed_tp_pct` | 0.0095 | Take-profit at 95 bps from entry (TP sweep 2026-03-06) | | `max_hold_bars` | 120 | Maximum holding period in 5s bars (= 10 minutes) | | `fraction` | 0.20 | Base position size fraction of capital | | `min_leverage` | 0.5 | Floor leverage (applied by AlphaBetSizer) | | `max_leverage` | 5.0 | Soft leverage ceiling | | `abs_max_leverage` | 6.0 | Hard leverage ceiling (Rm-scaled by Survival Stack) | | `leverage_convexity` | 3.0 | Cubic exponent for convex leverage scaling | | `dc_lookback_bars` | 7 | Direction confirmation lookback window | | `dc_min_magnitude_bps` | 0.75 | Minimum velocity magnitude for DC trigger | | `min_irp_alignment` | 0.45 | IRP asset selection threshold | | `sp_maker_entry_rate` | 0.62 | SmartPlacer: 62% maker fill rate at entry | | `sp_maker_exit_rate` | 0.50 | SmartPlacer: 50% maker fill rate at exit | | `seed` | 42 | NumPy / numba RNG seed (reproducibility invariant) | **Verification:** `nautilus_prefect_flow._CHAMPION_HASH` is computed at import time from these values. Any config drift triggers `ValueError` and aborts the flow. --- ## 4. Alpha Engine — 7-Layer Stack ### Layer 1: Velocity Divergence Signal Gate (`AlphaSignalGenerator`) **Input:** `vel_div = v50_lambda_max_velocity - v150_lambda_max_velocity` The primary alpha signal. `v50` is the 50-window eigenvalue velocity; `v150` the 150-window. Negative divergence signals short momentum. ``` Buckets: 0 (extreme): vel_div ≤ -0.075 → max leverage 1 (strong): vel_div ≤ -0.050 → high leverage 2 (moderate): vel_div ≤ -0.035 → normal leverage 3 (weak): vel_div ≤ -0.020 → min leverage ``` Only fires if `vel_div ≤ vel_div_threshold (-0.02)`. Includes direction confirmation (`dc_lookback_bars=7`, `dc_min_magnitude_bps=0.75`). ### Layer 2: Volatility Regime Filter (`VolatilityRegimeDetector`) Rolling 50-bar standard deviation of BTC returns. Positions are only opened when `dvol > vol_p60` (60th percentile threshold = 0.000099 from 55-day champion calibration). Prevents trading in dead-market microstructure. ### Layer 3: SmartPlacer Fee Model (`AlphaSignalGenerator`) Models maker vs taker execution costs: - `sp_maker_entry_rate=0.62`: 62% of entries assumed as maker (−0.02% fee) - `sp_maker_exit_rate=0.50`: 50% of exits as maker - Remaining fills incur taker fee (+0.04%) - Net fee per round trip ≈ 0.02–0.04% depending on fill mix Fee is charged per trade in `NDAlphaEngine.process_bar()`. No real order routing in paper mode — fee is applied analytically. ### Layer 4: OB Intelligence — 5 Sub-systems (`OBFeatureEngine` / `HZOBProvider`) Reads from `DOLPHIN_FEATURES_SHARD_{idx}` or `ob_cache/latest_ob_features.json`: | Sub-system | Key features | Effect | |---|---|---| | 1. Placement | `fill_probability`, `depth_quality`, `spread_proxy_bps` | Adjusts maker entry rate; gates entry if `fill_probability < 0.6` | | 2. Signal | `depth_asymmetry`, `imbalance_persistence`, `withdrawal_velocity` | OB-direction confirmation layer | | 3. Cross-asset | `agreement_pct`, `cascade_count`, `regime_signal` | Asset selection weighting in IRP | | 4. Macro | `macro_imbalance`, `macro_spread_bps` | Long-horizon baseline normalization | | 5. Raw depth | `bid/ask_notional_1-5pct`, `bid/ask_depth_1-5pct` | Notional depth vectors for all 5 levels | OB edge gate: `ob_edge_bps=5.0`, `ob_confirm_rate=0.40`. Entry only if OB confirms directional signal. ### Layer 5: IRP Asset Selection (`AlphaAssetSelector`) Inter-asset relative performance (IRP) selects which assets to trade each bar. Only assets where imbalance sign aligns with the directional view, and where `irp_alignment ≥ min_irp_alignment (0.45)`, are traded. ### Layer 6: Dynamic Cubic-Convex Leverage (`AlphaBetSizer`) ``` leverage = min_leverage + (max_leverage - min_leverage) × (signal_strength)^leverage_convexity signal_strength = (vel_div_threshold - vel_div) / (vel_div_threshold - vel_div_extreme) clamped to [0, 1] ``` Then scaled by `regime_size_mult` from ACBv6: ``` regime_size_mult = base_boost × (1 + beta × strength_cubic) × mc_scale ``` Final leverage clamped to `[min_leverage, abs_max_leverage × Rm]`. ### Layer 7: Exit Management (`AlphaExitManager`) Two primary exits (no stop loss in champion): 1. **Fixed TP:** Exit when `price_change_pct ≥ fixed_tp_pct (0.0095)` = 95 bps 2. **Max hold:** Force exit at `max_hold_bars (120)` × 5s = 10 minutes --- ## 5. DolphinActor — Nautilus Strategy Wrapper **File:** `nautilus_dolphin/nautilus/dolphin_actor.py` **Base class:** `nautilus_trader.trading.strategy.Strategy` **Lines:** 338 ### 5.1 Initialization ```python class DolphinActor(Strategy): def __init__(self, config: dict): super().__init__() # Nautilus Actor Cython init self.dolphin_config = config # full YAML config dict self.engine = None # NDAlphaEngine (created in on_start) self.hz_client = None # HazelcastClient self.current_date = None # tracks date boundary self.posture = 'APEX' # Survival Stack posture self._processed_dates = set() self._pending_acb: dict | None = None # pending ACB from HZ listener self._acb_lock = threading.Lock() # guards _pending_acb self._stale_state_events = 0 self.last_scan_number = -1 self._day_data = None # (df, asset_columns) for replay mode self._bar_idx_today = 0 ``` ### 5.2 on_start() Lifecycle ``` on_start(): 1. _connect_hz() → hazelcast.HazelcastClient(cluster_name="dolphin", ...) 2. _read_posture() → reads DOLPHIN_SAFETY (CP atomic ref or map fallback) 3. _setup_acb_listener() → add_entry_listener on DOLPHIN_FEATURES["acb_boost"] 4. create_boost_engine(mode=boost_mode, **engine_kwargs) → NDAlphaEngine 5. MC-Forewarner injection (gold-performance stack — enabled by default): mc_models_dir = config.get('mc_models_dir', _MC_MODELS_DIR_DEFAULT) DolphinForewarner(models_dir=mc_models_dir) → engine.set_mc_forewarner(fw, _MC_BASE_CFG) Graceful: logs warning + continues if models dir missing or import fails. Disable: set mc_models_dir=None or mc_models_dir='' in config. ``` HZ connection failure is non-fatal: `hz_client = None`, posture defaults to APEX. MC-Forewarner failure is non-fatal: logs warning, `_day_mc_scale` stays 1.0 (gate disabled). ### 5.3 on_bar() — Hot Loop ``` on_bar(bar: Bar): ① Apply pending ACB (under _acb_lock): pending = _pending_acb; _pending_acb = None if pending: engine.update_acb_boost(boost, beta) ② Date boundary detection: date_str = datetime.fromtimestamp(bar.ts_event / 1e9, UTC).strftime('%Y-%m-%d') if current_date != date_str: if current_date: engine.end_day() current_date = date_str posture = _read_posture() _bar_idx_today = 0 engine.begin_day(date_str, posture=posture, direction=±1) if not live_mode: _load_parquet_data(date_str) → _day_data ③ HIBERNATE guard: if posture == 'HIBERNATE': return # no position opened ④ Feature extraction (live HZ vs replay parquet): live_mode=True: _get_latest_hz_scan() → scan dict staleness check: abs(now_ns - scan_ts_ns) > 10s → warning dedup: scan_num == last_scan_number → skip live_mode=False: if _day_data empty → return (no step_bar with zeros) elif bar_idx >= len(df) → return (end of day) else: df.iloc[_bar_idx_today] → row vol_regime_ok = bar_idx >= 100 (warmup) ⑤ Stale-state snapshot (before): _snap = _GateSnap(acb_boost, acb_beta, posture, mc_gate_open) ⑥ Optional proxy_B pre-update (no-op for baseline engine): if hasattr(engine, 'pre_bar_proxy_update'): engine.pre_bar_proxy_update(...) ⑦ engine.step_bar(bar_idx, vel_div, prices, v50_vel, v750_vel, vol_regime_ok) _bar_idx_today += 1 ⑧ Stale-state snapshot (after): _snap_post = _GateSnap(acb_boost, acb_beta, _read_posture(), mc_gate_open) if _snap != _snap_post: stale_state_events++ log.warning("[STALE_STATE] ...") result['stale_state'] = True ⑨ _write_result_to_hz(date_str, result) ``` ### 5.4 ACB Thread Safety — Pending-Flag Pattern ``` HZ listener thread: _on_acb_event(event): parsed = json.loads(event.value) # parse OUTSIDE lock (pure CPU) with _acb_lock: _pending_acb = parsed # atomic assign under lock on_bar() (Nautilus event thread): with _acb_lock: pending = _pending_acb _pending_acb = None # consume atomically if pending: engine.update_acb_boost(...) # apply outside lock ``` This design minimizes lock hold time to a single pointer swap. There is no blocking I/O under the lock. ### 5.5 on_stop() ```python def on_stop(self): self._processed_dates.clear() # prevent stale date state on restart self._stale_state_events = 0 if self.hz_client: self.hz_client.shutdown() ``` --- ## 6. ACBv6 — Adaptive Circuit Breaker **File:** `nautilus_dolphin/nautilus/adaptive_circuit_breaker.py` ### 6.1 Three-Scale Architecture ``` regime_size_mult = base_boost × (1 + beta × strength_cubic) × mc_scale Scale 1 — Daily external factors (base_boost): preloaded from recent 60-day w750 velocity history p60 threshold determines whether current w750 is "high regime" base_boost ∈ [0.5, 2.0] typically Scale 2 — Per-bar meta-boost (beta × strength_cubic): beta: ACB sensitivity parameter from HZ DOLPHIN_FEATURES strength_cubic: (|vel_div| / threshold)^3 — convex response to signal strength Scale 3 — MC-Forewarner scale (mc_scale): DolphinForewarner ML model predicts MC regime mc_scale ∈ [0.5, 1.5] ``` ### 6.2 HZ Integration ACBv6 updates are pushed to `DOLPHIN_FEATURES["acb_boost"]` by an external Prefect flow. DolphinActor subscribes via `add_entry_listener` and receives push notifications. Updates are applied at the top of the next `on_bar()` call (pending-flag pattern, §5.4). ### 6.3 Cut-to-Position-Size API ```python acb.apply_cut_to_position_size(position_size, cut_pct) # cut_pct in [0.0, 0.15, 0.45, 0.55, 0.75, 0.80] # Returns position_size × (1 - cut_pct) ``` --- ## 7. Survival Stack (5-Sensor Posture) **HZ map:** `DOLPHIN_SAFETY` (CP atomic reference preferred, map fallback) ``` Rm ∈ [0, 1] — composite risk metric from 5 sensors Posture Rm threshold Behavior ───────── ──────────── ───────────────────────────────────────────── APEX Rm ≥ 0.90 Full operation; abs_max_leverage unrestricted STALKER Rm ≥ 0.75 max_leverage capped to 2.0 TURTLE Rm ≥ 0.50 position sizing reduced via abs_max_leverage × Rm HIBERNATE Rm < 0.50 on_bar() returns immediately; no new positions ``` Posture is re-read on every date change. In `paper_trade_flow.py`, Rm is applied directly to `engine.abs_max_leverage`: ```python engine.abs_max_leverage = max(1.0, engine.abs_max_leverage × Rm) if posture == 'STALKER': engine.abs_max_leverage = min(engine.abs_max_leverage, 2.0) ``` --- ## 8. NDAlphaEngine API **File:** `nautilus_dolphin/nautilus/esf_alpha_orchestrator.py` ### 8.1 Constructor Parameters See §3 Champion Parameters. Additional non-champion params: - `stop_pct=1.0` (effectively disabled — TP exits first) - `lookback=100` (price history window) - `use_alpha_layers=True` (enables OB/IRP/SP layers) - `use_dynamic_leverage=True` (enables cubic-convex sizing) ### 8.2 Day Lifecycle API ```python engine.begin_day(date_str: str, posture: str, direction: int) # Sets regime_direction, reads ACB for the day, resets per-day state for bar in bars: result = engine.step_bar( bar_idx=int, # 0-based index within day vel_div=float, # primary alpha signal prices=dict, # {symbol: float} current prices vol_regime_ok=bool, # volatility gate v50_vel=float, # w50 eigenvalue velocity (raw) v750_vel=float, # w750 eigenvalue velocity (ACB scale) ) -> dict result_dict = engine.end_day() # Returns: {pnl, trades, capital, boost, beta, mc_status, ...} ``` ### 8.3 State Fields | Field | Type | Description | |---|---|---| | `capital` | float | Current equity (updated after each trade) | | `_day_base_boost` | float | ACB base boost for today | | `_day_beta` | float | ACB beta sensitivity for today | | `_day_mc_scale` | float | MC-Forewarner scale for today | | `_global_bar_idx` | int | Lifetime bar counter (persists across days) | | `_price_histories` | dict | Per-asset price history lists (≤500 values) | | `position` | NDPosition | Current open position (None if flat) | | `trade_history` | list | All closed NDTradeRecord objects | | `regime_size_mult` | float | Current ACBv6 size multiplier | ### 8.4 Setter Methods ```python engine.set_ob_engine(ob_engine) # inject OBFeatureEngine engine.set_acb(acb) # inject AdaptiveCircuitBreaker engine.set_mc_forewarner(fw, base_cfg) # inject DolphinForewarner engine.update_acb_boost(boost, beta) # called by DolphinActor from HZ events ``` --- ## 9. Data Flow — Replay Mode (Paper Trading) ``` vbt_cache_klines/YYYY-MM-DD.parquet ↓ DolphinActor._load_parquet_data() ↓ pd.read_parquet() → DataFrame (1439 rows × ~57 cols) columns: timestamp, scan_number, vel_div, v50/v150/v300/v750_lambda_max_velocity, instability_50, instability_150, BTCUSDT, ETHUSDT, BNBUSDT, ... (48 assets) ↓ DolphinActor.on_bar() iterates rows via _bar_idx_today ↓ NDAlphaEngine.step_bar(bar_idx, vel_div, prices, ...) ↓ AlphaSignalGenerator → AlphaBetSizer → AlphaExitManager ↓ trade_history.append(NDTradeRecord) ↓ DolphinActor._write_result_to_hz() → DOLPHIN_PNL_BLUE[date] ``` ### 9.1 Live Mode Data Flow ``` Binance Futures WS → OBF prefect flow → Hazelcast DOLPHIN_FEATURES_SHARD_* Eigenvalue scanner → JSON scan files → Hazelcast DOLPHIN_FEATURES["latest_eigen_scan"] DolphinActor.on_bar(): scan = _get_latest_hz_scan() vel_div = scan["vel_div"] prices = scan["asset_prices"] → engine.step_bar(...) ``` --- ## 10. Hazelcast IMap Schema | Map name | Key | Value | Writer | Reader | |---|---|---|---|---| | `DOLPHIN_SAFETY` | "latest" | JSON `{posture, Rm, ...}` | Survival stack flow | DolphinActor, paper_trade_flow | | `DOLPHIN_FEATURES` | "acb_boost" | JSON `{boost, beta}` | ACB writer flow | DolphinActor (listener) | | `DOLPHIN_FEATURES` | "latest_eigen_scan" | JSON `{vel_div, scan_number, asset_prices, ...}` | Eigenvalue scanner | DolphinActor (live mode) | | `DOLPHIN_PNL_BLUE` | "YYYY-MM-DD" | JSON result dict | paper_trade_flow, DolphinActor | Analytics | | `DOLPHIN_STATE_BLUE` | "latest" | JSON `{capital, date, pnl, ...}` | paper_trade_flow | paper_trade_flow (restore) | | `DOLPHIN_STATE_BLUE` | "latest_nautilus" | JSON `{capital, param_hash, ...}` | nautilus_prefect_flow | nautilus_prefect_flow | | `DOLPHIN_HEARTBEAT` | "nautilus_flow_heartbeat" | JSON `{ts, phase, ...}` | nautilus_prefect_flow | Monitoring | | `DOLPHIN_FEATURES_SHARD_00..09` | symbol | JSON OB feature dict | OBF prefect flow | HZOBProvider | **Shard routing:** `shard_idx = sum(ord(c) for c in symbol) % 10` — stable, deterministic, no config needed. --- ## 11. Prefect Integration ### 11.1 paper_trade_flow.py (Primary — 00:05 UTC) Runs NDAlphaEngine directly (no Nautilus kernel). Tasks: - `load_config` — YAML config with retries=0 - `load_day_scans` — parquet (preferred) or JSON fallback, retries=2 - `run_engine_day` — NDAlphaEngine.begin_day/step_bar/end_day loop - `write_hz_state` — HZ persist, retries=3 - `log_pnl` — disk JSONL append ### 11.2 nautilus_prefect_flow.py (Nautilus Supervisor — 00:10 UTC) Wraps BacktestEngine + DolphinActor. Tasks: - `hz_probe_task` — verify HZ reachable, retries=3, timeout=30s - `validate_champion_params` — SHA256 hash check vs `_CHAMPION_PARAMS`, aborts on drift - `load_bar_data_task` — parquet load with validation, retries=2 - `read_posture_task` — DOLPHIN_SAFETY read, retries=2 - `restore_capital_task` — capital continuity from HZ state - `run_nautilus_backtest_task` — full BacktestEngine cycle, timeout=600s - `write_hz_result_task` — persist to DOLPHIN_PNL_BLUE + DOLPHIN_STATE_BLUE, retries=3 - `heartbeat_task` — liveness pulse at flow_start/engine_start/flow_end ### 11.3 Registration ```bash source /home/dolphin/siloqy_env/bin/activate PREFECT_API_URL=http://localhost:4200/api # Primary paper trade (existing): python prod/paper_trade_flow.py --register # Nautilus supervisor (new): python prod/nautilus_prefect_flow.py --register # → dolphin-nautilus-blue, daily 00:10 UTC, work_pool=dolphin ``` --- ## 12. Nautilus Kernel Backends ### 12.1 BacktestEngine (Paper / Replay) Used in `run_nautilus.py` and `nautilus_prefect_flow.py`. Processes synthetic bars (one bar per date triggers DolphinActor which then iterates over the full parquet day internally). No real exchange connectivity. ```python engine = BacktestEngine(config=BacktestEngineConfig(trader_id="DOLPHIN-NAUTILUS-001")) engine.add_strategy(DolphinActor(config=config)) engine.add_venue(Venue("BINANCE"), OmsType.HEDGING, AccountType.MARGIN, ...) engine.add_instrument(TestInstrumentProvider.default_fx_ccy("BTCUSD", venue)) engine.add_data([synthetic_bar]) engine.run() ``` ### 12.2 TradingNode (Live — Future) `NautilusDolphinLauncher` in `launcher.py` bootstraps a `TradingNode` with `BinanceExecClientConfig`. Requires Binance API keys and live WS data. Not currently active. ```python from nautilus_dolphin.nautilus.launcher import NautilusDolphinLauncher launcher = NautilusDolphinLauncher(config_path="prod/configs/blue.yml") launcher.start() # blocking — runs until SIGTERM ``` ### 12.3 Bar Type ``` "BTCUSD.BINANCE-5-SECOND-LAST-EXTERNAL" ``` `EXTERNAL` aggregation type: bars are not synthesized by Nautilus from ticks; they are injected directly. This is the correct type for replay from pre-aggregated parquet. --- ## 13. DolphinStrategyConfig **File:** `nautilus_dolphin/nautilus/strategy_config.py` ```python class DolphinStrategyConfig(StrategyConfig, kw_only=True, frozen=True): vel_div_threshold: float = -0.02 vel_div_extreme: float = -0.05 fixed_tp_pct: float = 0.0095 max_hold_bars: int = 120 fraction: float = 0.20 min_leverage: float = 0.5 max_leverage: float = 5.0 abs_max_leverage: float = 6.0 leverage_convexity: float = 3.0 dc_lookback_bars: int = 7 dc_min_magnitude_bps: float = 0.75 min_irp_alignment: float = 0.45 sp_maker_entry_rate: float = 0.62 sp_maker_exit_rate: float = 0.50 seed: int = 42 # ... ``` Factory methods: - `create_champion_config()` → excluded_assets=["TUSDUSDT","USDCUSDT"] - `create_conservative_config()` → reduced leverage/fraction - `create_growth_config()` → increased leverage - `create_aggressive_config()` → max leverage stack --- ## 14. Test Suite Summary | File | Tests | Coverage | |---|---|---| | `test_0_nautilus_bootstrap.py` | 11 | Import chain, NautilusKernelConfig, ACB, CircuitBreaker, launcher | | `test_dolphin_actor.py` | 35 | Champion params, ACB thread-safety, HIBERNATE guard, date change, HZ degradation, replay mode, on_stop, _GateSnap | | `test_strategy.py` | 4+ | DolphinExecutionStrategy signal filters | | `test_adaptive_circuit_breaker.py` | ~10 | ACBv6 scale computation, cut-to-size | | `test_circuit_breaker.py` | ~6 | CircuitBreakerManager is_tripped, can_open, status | | `test_volatility_detector.py` | ~6 | VolatilityRegimeDetector is_high_regime | | `test_position_manager.py` | ~5 | PositionManager state | | `test_smart_exec_algorithm.py` | ~6 | SmartExecAlgorithm routing | | `test_signal_bridge.py` | ~4 | SignalBridgeActor event handling | | `test_metrics_monitor.py` | ~4 | MetricsMonitor state | **Run all:** ```bash source /home/dolphin/siloqy_env/bin/activate cd /mnt/dolphinng5_predict python -m pytest nautilus_dolphin/tests/ -v ``` **Run DolphinActor tests only:** ```bash python -m pytest nautilus_dolphin/tests/test_dolphin_actor.py -v # 35/35 ``` --- ## 15. Deployment Procedures ### 15.1 siloqy-env Activation All production and test commands must run in siloqy-env: ```bash source /home/dolphin/siloqy_env/bin/activate # Verify: python -c "import nautilus_trader; print(nautilus_trader.__version__)" # Expected: 1.219.0 ``` ### 15.2 Daily Paper Trade (Manual) ```bash source /home/dolphin/siloqy_env/bin/activate cd /mnt/dolphinng5_predict PREFECT_API_URL=http://localhost:4200/api \ python prod/paper_trade_flow.py --config prod/configs/blue.yml --date 2026-03-21 ``` ### 15.3 Nautilus BacktestEngine Run (Manual) ```bash source /home/dolphin/siloqy_env/bin/activate cd /mnt/dolphinng5_predict python prod/run_nautilus.py --config prod/configs/blue.yml ``` ### 15.4 Nautilus Prefect Flow (Manual) ```bash source /home/dolphin/siloqy_env/bin/activate cd /mnt/dolphinng5_predict PREFECT_API_URL=http://localhost:4200/api \ python prod/nautilus_prefect_flow.py --date 2026-03-21 ``` ### 15.5 Dry Run (Data + Param Validation Only) ```bash python prod/nautilus_prefect_flow.py --date 2026-03-21 --dry-run ``` ### 15.6 Register Prefect Deployments ```bash PREFECT_API_URL=http://localhost:4200/api \ python prod/paper_trade_flow.py --register # dolphin-paper-blue, 00:05 UTC PREFECT_API_URL=http://localhost:4200/api \ python prod/nautilus_prefect_flow.py --register # dolphin-nautilus-blue, 00:10 UTC ``` ### 15.7 Prefect Worker ```bash source /home/dolphin/siloqy_env/bin/activate PREFECT_API_URL=http://localhost:4200/api \ prefect worker start --pool dolphin --type process ``` --- ## 16. HZ Sharded Feature Store **Map pattern:** `DOLPHIN_FEATURES_SHARD_{shard_idx}` **Shard count:** 10 **Routing:** ```python shard_idx = sum(ord(c) for c in symbol) % SHARD_COUNT imap_name = f"DOLPHIN_FEATURES_SHARD_{shard_idx:02d}" ``` The OBF flow writes per-asset OB features to the correct shard. `HZOBProvider` uses dynamic discovery (reads key_set from all 10 shards at startup) to find which assets are present. --- ## 17. Operational Invariants 1. **Champion param hash must match** at every flow start. `_CHAMPION_HASH = "..."` computed from `_CHAMPION_PARAMS` dict. Mismatch → `ValueError` → flow abort. 2. **Seed=42 is mandatory** for reproducibility. numba RNG uses Numba's internal PRNG initialized from seed. NumPy RandomState(42) used in NDAlphaEngine. Any change to seed invalidates backtest comparison. 3. **HIBERNATE is hard** — deliberately tight (Rm < 0.50). When posture=HIBERNATE, `on_bar()` returns immediately, no exceptions, no logging above WARNING. 4. **Stale-state events are logged but not fatal.** `_stale_state_events` counter increments; result dict gets `stale_state=True`. The trade result is written to HZ with a DO-NOT-USE flag in the log. Downstream systems must check this field. 5. **HZ unavailability is non-fatal.** If HZ is unreachable at on_start, `hz_client=None`, posture defaults to APEX. Flow continues with local state only. The `hz_probe_task` retries 3× before giving up with a warning (not an error). 6. **Capital continuity.** Each flow run restores capital from `DOLPHIN_STATE_BLUE["latest_nautilus"]`. If absent, falls back to `initial_capital` from config (25,000 USDT). 7. **Date boundary is ts_event-driven.** The Nautilus bar's `ts_event` nanoseconds are the authoritative source of truth for date detection. Wall clock is not used. --- ## 18. Known Limitations and Future Work | Item | Status | Notes | |---|---|---| | Live TradingNode (Binance) | Pending | launcher.py exists; requires API keys + WS data integration | | 0.1s (10 Hz) resolution | Blocked | 3 blockers: async HZ push, timeout reduction, lookback recalibration | | LONG validation (green config) | Pending | green.yml exists; needs backtest sign-off | | ML-MC Forewarner in Nautilus flow | **Done** | Wired in `DolphinActor.on_start()` — auto-injects for both flows; `_MC_BASE_CFG` frozen constant | | Full end-to-end Nautilus replay parity | In progress | test_nd_vs_standalone_comparison.py exists; champion param parity confirmed | --- *Spec version 1.0 — 2026-03-22 — Nautilus-DOLPHIN Alpha Engine Core*