# ACB v5 Implementation on Nautilus-Dolphin **Date:** 2026-02-19 **Version:** v5 (Empirically Validated) **Status:** Production Ready --- ## Overview The Adaptive Circuit Breaker (ACB) v5 has been integrated into the Nautilus-Dolphin trading stack. This implementation provides position-sizing protection based on external market stress indicators. ### Key Features - **Position Sizing Only**: Affects trade size, not trade selection (win rate invariant at 46.1%) - **External Factor Based**: Uses funding rates, DVOL, FNG, taker ratio - **Empirically Validated**: 1% fine sweep across 0-80% (62 cut rates tested) - **v5 Configuration**: 0/15/45/55/75/80 cut rates (beats v2 by ~$150 on $10k) --- ## ACB v5 Configuration ### Cut Rates by Signal Count | Signals | Cut Rate | Description | |---------|----------|-------------| | 0 | 0% | No protection (normal market) | | 1 | 15% | Light protection (mild stress) | | 2 | 45% | Moderate protection | | 3 | 55% | High protection (crash level) | | 4 | 75% | Very high protection | | 5+ | 80% | Extreme protection | ### External Factors Monitored | Factor | Threshold | Weight | |--------|-----------|--------| | Funding (BTC) | <-0.0001 (very bearish) | High | | DVOL (BTC) | >80 (extreme), >55 (elevated) | High | | FNG (Fear & Greed) | <25 (extreme fear) | Medium (needs confirmation) | | Taker Ratio | <0.8 (selling pressure) | Medium | --- ## Files Added/Modified ### New Files 1. **`nautilus/adaptive_circuit_breaker.py`** - `AdaptiveCircuitBreaker`: Core ACB logic - `ACBConfig`: Configuration dataclass - `ACBPositionSizer`: Integration wrapper - `get_acb_cut_for_date()`: Convenience function 2. **`tests/test_adaptive_circuit_breaker.py`** - Comprehensive unit tests - Integration tests (Feb 6 scenario) - Validation tests ### Modified Files 1. **`nautilus/strategy.py`** - Added ACB integration in `DolphinExecutionStrategy` - Modified `calculate_position_size()` to apply ACB cuts - Added ACB stats logging in `on_stop()` --- ## Usage ### Basic Usage (Automatic) The ACB is **enabled by default** and automatically applies cuts to position sizing: ```python # In your strategy config config = { 'acb_enabled': True, # Default: True # ... other config } strategy = DolphinExecutionStrategy(config) ``` When a signal is received, the strategy will: 1. Calculate base position size (balance × fraction × leverage) 2. Query ACB for current cut rate based on external factors 3. Apply cut: `final_size = base_size × (1 - cut_rate)` 4. Log the ACB application ### Manual Usage ```python from nautilus_dolphin.nautilus.adaptive_circuit_breaker import ( AdaptiveCircuitBreaker, get_acb_cut_for_date ) # Method 1: Direct usage acb = AdaptiveCircuitBreaker() cut_info = acb.get_cut_for_date('2026-02-06') print(f"Cut: {cut_info['cut']*100:.0f}%, Signals: {cut_info['signals']}") position_size = base_size * (1 - cut_info['cut']) # Method 2: Convenience function cut_info = get_acb_cut_for_date('2026-02-06') ``` ### Disabling ACB ```python config = { 'acb_enabled': False, # Disable ACB # ... other config } ``` --- ## Empirical Validation ### Test Results (1% Fine Sweep) | Cut Rate | ROI | MaxDD | Sharpe | |----------|-----|-------|--------| | 0% | 8.62% | 18.3% | 1.52 | | 15% | 7.42% | 15.8% | 1.51 | | 45% | 4.83% | 10.5% | 1.46 | | 55% | 3.93% | 8.6% | 1.43 | | 75% | 2.01% | 5.0% | 1.28 | | 80% | 1.50% | 4.1% | 1.19 | ### v5 vs v2 Comparison | Config | Ending Capital | MaxDD | Winner | |--------|----------------|-------|--------| | v5 (0/15/45/55/75/80) | **$10,782** | 14.3% | **v5** | | v2 (0/30/45/55/65/75) | $10,580 | 11.7% | | **v5 wins by $202 (1.9%)** - validated across multiple market scenarios. ### Feb 6/8 Crash Validation - **Feb 6**: 3+ signals detected → 55% cut applied → Saved $2,528 vs no-CB - **Feb 8**: 3+ signals detected → 55% cut applied → Saved $468 vs no-CB --- ## Configuration Options ### ACBConfig Parameters ```python from nautilus_dolphin.nautilus.adaptive_circuit_breaker import ACBConfig config = ACBConfig( # Cut rates (v5 optimal - empirically validated) CUT_RATES={ 0: 0.00, 1: 0.15, 2: 0.45, 3: 0.55, 4: 0.75, 5: 0.80, }, # Signal thresholds FUNDING_VERY_BEARISH=-0.0001, FUNDING_BEARISH=0.0, DVOL_EXTREME=80, DVOL_ELEVATED=55, FNG_EXTREME_FEAR=25, FNG_FEAR=40, TAKER_SELLING=0.8, TAKER_MILD_SELLING=0.9, # Data path EIGENVALUES_PATH=Path('.../correlation_arb512/eigenvalues') ) ``` --- ## Monitoring and Logging ### Log Output Example ``` [INFO] ACB applied: cut=55%, signals=3.0, size=1000.00->450.00 [INFO] Position opened: BTCUSDT, entry=$96,450, TP=$95,495 ... [INFO] ACB stats: calls=48, cache_hits=45, cut_distribution={0: 25, 0.15: 10, 0.45: 8, 0.55: 4, 0.75: 1} ``` ### Statistics Available ```python # Get ACB statistics stats = strategy.acb_sizer.acb.get_stats() print(f"Total calls: {stats['total_calls']}") print(f"Cache hit rate: {stats['cache_hit_rate']:.1%}") print(f"Cut distribution: {stats['cut_distribution']}") ``` --- ## Testing ### Run Unit Tests ```bash cd nautilus_dolphin python -m pytest tests/test_adaptive_circuit_breaker.py -v ``` ### Test Scenarios 1. **Normal Market**: 0 signals → 0% cut 2. **Mild Stress**: 1 signal → 15% cut 3. **Moderate Stress**: 2 signals → 45% cut 4. **High Stress**: 3 signals → 55% cut 5. **Extreme Stress**: 4+ signals → 75-80% cut ### Feb 6 Integration Test ```python # Simulate Feb 6 conditions cut_info = get_acb_cut_for_date('2026-02-06') assert cut_info['signals'] >= 2.0 assert cut_info['cut'] >= 0.45 ``` --- ## Architecture ``` ┌─────────────────────────────────────────────────────────────┐ │ DolphinExecutionStrategy │ ├─────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────────┐ ┌─────────────────────────────┐ │ │ │ Signal Received │─────>│ calculate_position_size() │ │ │ └─────────────────┘ └─────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────────────────┐ │ │ │ ACBPositionSizer │ │ │ │ - get_cut_for_date() │ │ │ │ - apply_cut_to_size() │ │ │ └─────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────────────────┐ │ │ │ AdaptiveCircuitBreaker │ │ │ │ - load_external_factors() │ │ │ │ - calculate_signals() │ │ │ │ - get_cut_from_signals() │ │ │ └─────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────────────────┐ │ │ │ External Factor Files │ │ │ │ (correlation_arb512/...) │ │ │ └─────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────┘ ``` --- ## Best Practices ### 1. Always Keep ACB Enabled ```python # DON'T disable ACB unless you have a specific reason config = {'acb_enabled': False} # NOT recommended ``` ### 2. Monitor Cut Distribution ```python # Check that cuts are being applied reasonably stats = acb.get_stats() if stats['cut_distribution'][0.80] > 10: # Too many extreme cuts print("Warning: High frequency of extreme cuts") ``` ### 3. Cache Hit Rate ```python # Cache should be >80% for same-day lookups assert stats['cache_hit_rate'] > 0.8 ``` --- ## Troubleshooting ### Issue: ACB Not Applying Cuts **Symptoms**: All trades at full size, no ACB logs **Solutions**: 1. Check `acb_enabled` is True in config 2. Verify external factor files exist in `EIGENVALUES_PATH` 3. Check logs for "ACB applied" messages ### Issue: Always 0% Cut **Symptoms**: ACB always returns 0% cut **Solutions**: 1. Check external factor files are being loaded 2. Verify factor values (funding, DVOL, FNG, taker) 3. Check signal calculation thresholds ### Issue: Too Many Extreme Cuts **Symptoms**: Frequent 75-80% cuts **Solutions**: 1. Check external factor data quality 2. Verify FNG confirmation logic (requires other signals) 3. Adjust thresholds if needed --- ## References - **Original Analysis**: `ACB_1PCT_SWEEP_COMPLETE_ANALYSIS.md` - **v2 vs v5 Comparison**: `analyze_v2_vs_v5_capital.py` - **Empirical Results**: `vbt_results/acb_1pct_sweep_*.json` - **Feb 6/8 Validation**: `ACB_CUT_RATE_EMPRICAL_RESULTS.md` --- ## Contact For issues or questions about the ACB implementation, refer to: - `nautilus_dolphin/nautilus/adaptive_circuit_breaker.py` - `nautilus_dolphin/tests/test_adaptive_circuit_breaker.py` --- **End of ACB Implementation Documentation**