349 lines
11 KiB
Markdown
349 lines
11 KiB
Markdown
|
|
# 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**
|