feat: enhance strategy parameter sweep with new CLI tool and bug fixes

- Added a new CLI tool `scripts/strategy_sweep.py` for executing parameter sweeps.
- Updated `get_signal()` and `_calc_signals()` methods to accept `signal_threshold`, `adx_threshold`, and `volume_multiplier` parameters for improved signal processing.
- Fixed a bug in `WalkForwardBacktester` that prevented proper propagation of signal parameters, ensuring accurate backtesting results.
- Updated documentation to reflect changes in parameter sweeps and results.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
21in7
2026-03-07 00:27:28 +09:00
parent d8d4bf3e20
commit 771b357f28

View File

@@ -13,63 +13,68 @@ Walk-forward backtest revealed the current XRP strategy is unprofitable (PF 0.71
## Parameters Swept ## Parameters Swept
| Parameter | Values | Description |
|-----------|--------|-------------| | Parameter | Values | Description |
| `atr_sl_mult` | 1.0, 1.5, 2.0 | Stop-loss ATR multiplier | | ------------------- | ------------- | ----------------------------------------- |
| `atr_tp_mult` | 2.0, 3.0, 4.0 | Take-profit ATR multiplier | | `atr_sl_mult` | 1.0, 1.5, 2.0 | Stop-loss ATR multiplier |
| `signal_threshold` | 3, 4, 5 | Min weighted indicator score for entry | | `atr_tp_mult` | 2.0, 3.0, 4.0 | Take-profit ATR multiplier |
| `adx_threshold` | 0, 20, 25, 30 | ADX filter (0=disabled, N=require ADX>=N) | | `signal_threshold` | 3, 4, 5 | Min weighted indicator score for entry |
| `volume_multiplier` | 1.5, 2.0, 2.5 | Volume surge detection multiplier | | `adx_threshold` | 0, 20, 25, 30 | ADX filter (0=disabled, N=require ADX>=N) |
| `volume_multiplier` | 1.5, 2.0, 2.5 | Volume surge detection multiplier |
Total combinations: 3 x 3 x 3 x 4 x 3 = **324** Total combinations: 3 x 3 x 3 x 4 x 3 = **324**
## Implementation ## Implementation
### Files Modified ### Files Modified
- `src/indicators.py``get_signal()` accepts `signal_threshold`, `adx_threshold`, `volume_multiplier` params - `src/indicators.py``get_signal()` accepts `signal_threshold`, `adx_threshold`, `volume_multiplier` params
- `src/dataset_builder.py``_calc_signals()` accepts same params for vectorized computation - `src/dataset_builder.py``_calc_signals()` accepts same params for vectorized computation
- `src/backtester.py``BacktestConfig` includes strategy params; `WalkForwardBacktester` propagates them to test folds - `src/backtester.py``BacktestConfig` includes strategy params; `WalkForwardBacktester` propagates them to test folds
### Files Created ### Files Created
- `scripts/strategy_sweep.py` — CLI tool for parameter grid sweep - `scripts/strategy_sweep.py` — CLI tool for parameter grid sweep
### Bug Fix ### Bug Fix
- `WalkForwardBacktester` was not passing `signal_threshold`, `adx_threshold`, `volume_multiplier`, or `use_ml` to fold `BacktestConfig`. All signal params were silently using defaults, making ADX/volume/threshold sweeps have zero effect. - `WalkForwardBacktester` was not passing `signal_threshold`, `adx_threshold`, `volume_multiplier`, or `use_ml` to fold `BacktestConfig`. All signal params were silently using defaults, making ADX/volume/threshold sweeps have zero effect.
## Results (XRPUSDT, Walk-Forward 3/1) ## Results (XRPUSDT, Walk-Forward 3/1)
### Top 10 Combinations ### Top 10 Combinations
| Rank | SL×ATR | TP×ATR | Signal | ADX | Vol | Trades | WinRate | PF | MDD | PnL | Sharpe |
|------|--------|--------|--------|-----|-----|--------|---------|-----|-----|------|--------| | Rank | SL×ATR | TP×ATR | Signal | ADX | Vol | Trades | WinRate | PF | MDD | PnL | Sharpe |
| 1 | 1.5 | 4.0 | 3 | 30 | 2.5 | 19 | 52.6% | 2.39 | 7.0% | +469 | 61.0 | | ---- | ------ | ------ | ------ | --- | --- | ------ | ------- | ---- | ----- | ---- | ------ |
| 2 | 1.5 | 2.0 | 3 | 30 | 2.5 | 19 | 68.4% | 2.23 | 6.5% | +282 | 61.2 | | 1 | 1.5 | 4.0 | 3 | 30 | 2.5 | 19 | 52.6% | 2.39 | 7.0% | +469 | 61.0 |
| 3 | 1.0 | 2.0 | 3 | 30 | 2.5 | 19 | 57.9% | 1.98 | 5.0% | +213 | 50.8 | | 2 | 1.5 | 2.0 | 3 | 30 | 2.5 | 19 | 68.4% | 2.23 | 6.5% | +282 | 61.2 |
| 4 | 1.0 | 4.0 | 3 | 30 | 2.5 | 19 | 36.8% | 1.80 | 7.7% | +248 | 37.1 | | 3 | 1.0 | 2.0 | 3 | 30 | 2.5 | 19 | 57.9% | 1.98 | 5.0% | +213 | 50.8 |
| 5 | 1.5 | 3.0 | 3 | 30 | 2.5 | 19 | 52.6% | 1.76 | 10.1% | +258 | 40.9 | | 4 | 1.0 | 4.0 | 3 | 30 | 2.5 | 19 | 36.8% | 1.80 | 7.7% | +248 | 37.1 |
| 6 | 1.5 | 4.0 | 3 | 25 | 2.5 | 28 | 42.9% | 1.75 | 13.1% | +381 | 36.8 | | 5 | 1.5 | 3.0 | 3 | 30 | 2.5 | 19 | 52.6% | 1.76 | 10.1% | +258 | 40.9 |
| 7 | 2.0 | 4.0 | 3 | 30 | 1.5 | 39 | 48.7% | 1.67 | 16.9% | +572 | 35.3 | | 6 | 1.5 | 4.0 | 3 | 25 | 2.5 | 28 | 42.9% | 1.75 | 13.1% | +381 | 36.8 |
| 8 | 1.0 | 2.0 | 3 | 25 | 2.5 | 28 | 50.0% | 1.64 | 5.8% | +205 | 35.7 | | 7 | 2.0 | 4.0 | 3 | 30 | 1.5 | 39 | 48.7% | 1.67 | 16.9% | +572 | 35.3 |
| 9 | 1.5 | 2.0 | 3 | 25 | 2.5 | 28 | 57.1% | 1.62 | 10.3% | +229 | 35.7 | | 8 | 1.0 | 2.0 | 3 | 25 | 2.5 | 28 | 50.0% | 1.64 | 5.8% | +205 | 35.7 |
| 10 | 2.0 | 2.0 | 3 | 25 | 2.5 | 27 | 66.7% | 1.57 | 12.0% | +217 | 33.3 | | 9 | 1.5 | 2.0 | 3 | 25 | 2.5 | 28 | 57.1% | 1.62 | 10.3% | +229 | 35.7 |
| 10 | 2.0 | 2.0 | 3 | 25 | 2.5 | 27 | 66.7% | 1.57 | 12.0% | +217 | 33.3 |
### Current Production (Rank 93/324) ### Current Production (Rank 93/324)
| SL×ATR | TP×ATR | Signal | ADX | Vol | Trades | WinRate | PF | MDD | PnL |
|--------|--------|--------|-----|-----|--------|---------|-----|-----|------|
| 1.5 | 3.0 | 3 | 0 | 1.5 | 118 | 30.5% | 0.71 | 65.9% | -641 | | SL×ATR | TP×ATR | Signal | ADX | Vol | Trades | WinRate | PF | MDD | PnL |
| ------ | ------ | ------ | --- | --- | ------ | ------- | ---- | ----- | ---- |
| 1.5 | 3.0 | 3 | 0 | 1.5 | 118 | 30.5% | 0.71 | 65.9% | -641 |
### Key Findings ### Key Findings
1. **ADX filter is the single most impactful parameter.** All top 10 results use ADX >= 25, with ADX=30 dominating the top 5. This filters out sideways/ranging markets where signals are noise. 1. **ADX filter is the single most impactful parameter.** All top 10 results use ADX >= 25, with ADX=30 dominating the top 5. This filters out sideways/ranging markets where signals are noise.
2. **Volume multiplier 2.5 dominates.** Higher volume thresholds ensure entries only on strong conviction (genuine breakouts vs. noise). 2. **Volume multiplier 2.5 dominates.** Higher volume thresholds ensure entries only on strong conviction (genuine breakouts vs. noise).
3. **Signal threshold 3 is optimal.** Higher thresholds (4, 5) produced too few trades or zero trades in most ADX-filtered regimes. 3. **Signal threshold 3 is optimal.** Higher thresholds (4, 5) produced too few trades or zero trades in most ADX-filtered regimes.
4. **SL/TP ratios matter less than entry filters.** The top results span all SL/TP combos, but all share ADX=25-30 + Vol=2.5. 4. **SL/TP ratios matter less than entry filters.** The top results span all SL/TP combos, but all share ADX=25-30 + Vol=2.5.
5. **Trade count drops significantly with filters.** Top combos have 19-39 trades vs. 118 for current. Fewer but higher quality entries. 5. **Trade count drops significantly with filters.** Top combos have 19-39 trades vs. 118 for current. Fewer but higher quality entries.
6. **41 combinations achieved PF >= 1.0** out of 324 total (12.7%). 6. **41 combinations achieved PF >= 1.0** out of 324 total (12.7%).
## Recommended Next Steps ## Recommended Next Steps
@@ -78,3 +83,4 @@ Total combinations: 3 x 3 x 3 x 4 x 3 = **324**
2. **Validate on TRXUSDT and DOGEUSDT** to confirm ADX filter is not XRP-specific 2. **Validate on TRXUSDT and DOGEUSDT** to confirm ADX filter is not XRP-specific
3. **Retrain ML models** with updated strategy params — the ML filter should now have a profitable base to improve upon 3. **Retrain ML models** with updated strategy params — the ML filter should now have a profitable base to improve upon
4. **Fine-tune sweep** around the profitable zone: ADX [25-35], Vol [2.0-3.0] 4. **Fine-tune sweep** around the profitable zone: ADX [25-35], Vol [2.0-3.0]