Bollinger Band Squeeze momentum trading system for crypto. Deployed 24/7 on a VPS, trading perpetual futures on Coinbase Advanced Trade with leverage. Entry signals are derived from spot price series.
Backtest on all available data (~6 years for ETH, ~8 years for XRP). $10,000 initial capital. Commission 0.05%, slippage 0.02%.
| Asset | Trades | Win Rate | Profit Factor | Return | Max Drawdown |
|---|---|---|---|---|---|
| ETH | 170 | 60.0% | 2.06 | +78.0% | 4.9% |
| XRP | 104 | 58.7% | 1.70 | +42.3% | 9.4% |
| Combined | 274 | 59.5% | 1.90 | +120.3% | 8.1% |
| Trades | Win Rate | Profit Factor | Return | Max Drawdown | Monte Carlo p-value |
|---|---|---|---|---|---|
| 274 | 59.5% | 1.83 | +552.2% | 18.0% | 0.0000 |
Monte Carlo bootstrap (10,000 simulations) confirms statistical significance at p < 0.0001 for both spot and leveraged configurations.
Parameters are validated on holdout data never seen during optimization. Each candidate undergoes four tests: holdout backtest, Monte Carlo bootstrap, permutation test (shuffled price series), and sensitivity analysis (parameter perturbation +/-10%).
| Asset | Holdout Trades | Win Rate | PnL | Monte Carlo p | Sensitivity |
|---|---|---|---|---|---|
| ETH | 33 | 63.6% | +$1,588 | 0.002 | 8/8 pass |
| XRP | 25 | 64.0% | +$1,010 | 0.027 | 8/8 pass |
Signal logic is based on a BB Squeeze breakout:
- Bollinger Bands contract inside Keltner Channels (squeeze = price compression)
- Squeeze must persist for a minimum number of bars before entry is valid
- Momentum accelerates as the squeeze releases
- Volume confirms the breakout direction
- RSI filters entries at overbought/oversold extremes
- ATR-based stop loss and take profit are set at entry
- Trailing stop activates once price moves a configurable multiple of risk in favor
Each asset has independently optimized parameters. Position size scales with signal quality (squeeze duration x volume x momentum).
keltrader/
├── params.py # Single source of truth for per-asset strategy params
├── run_backtest.py # Backtest runner — spot and leveraged modes
├── optimizer.py # Walk-forward optimizer (random / CMA-ES / TPE)
├── validate_params.py # Post-optimization validation (holdout + MC + permutation)
├── run_live_multi_asset.py # Live trading entry point (multi-asset)
├── check_trade.py # Query open/closed positions from Coinbase
├── download_data.py # Fetch and cache OHLCV data from Coinbase
│
├── strategy/
│ ├── technical.py # BB, KC, squeeze state, momentum, RSI, volume indicators
│ └── signal_generator.py # Converts indicators → trade signals with SL/TP/size
│
├── core/
│ ├── backtester.py # Event-driven backtester (spot + leveraged futures)
│ ├── optimizer.py # Walk-forward optimizer internals
│ ├── permutation_test.py # Price-shuffle permutation test for significance
│ ├── monte_carlo.py # Bootstrap Monte Carlo for PnL robustness
│ ├── ensemble.py # Multi-param ensemble signal generation
│ └── experiment_tracker.py # SQLite log of backtest/optimization runs
│
├── live/
│ └── coinbase_live_trader.py # Live trading engine (orders, positions, Telegram alerts)
│
├── data/
│ └── data_utils.py # Multi-timeframe data fetching and caching
│
├── common/
│ └── utils.py # Shared utilities (colors, formatting, timeframe mapping)
│
└── tests/ # Pytest suite (51 tests)
python run_backtest.py # All default assets (spot)
python run_backtest.py --symbols ETH/USD # Single asset
python run_backtest.py --symbols ETH/USD,XRP/USD # Multiple assets
python run_backtest.py --leverage # Futures mode with leverage
python run_backtest.py --leverage --maintenance-margin 0.5 # Custom maintenance marginWalk-forward optimization using Optuna. Three methods available:
- Random (20,000 trials) — broad parameter space exploration
- CMA-ES — covariance matrix adaptation, converges around top seeds
- TPE — tree-structured Parzen estimator, warm-started from random trials
Scoring is Sharpe ratio on out-of-sample walk-forward folds with hard gates:
- PnL > 0, profit factor >= 1.2, max drawdown <= 25%, Sharpe > 0
- Minimum trades scaled by fold length (~4/year, floor of 3)
- Fold score = 0.3 x train Sharpe + 0.7 x test Sharpe
- Final WF score = mean(fold scores) — requires minimum 3 valid folds
Trials persist to SQLite so runs can be stopped and resumed.
python optimizer.py --symbol XRP --signal-tf 2h
python optimizer.py --symbol ETH --signal-tf 2h --method tpe --tpe-trials 3000
python optimizer.py --symbol BTC --show-best
python optimizer.py --symbol SOL --evaluate-holdoutValidates top-N parameter sets from the optimizer before deployment:
python validate_params.py --symbol XRP --signal-tf 2h --top 10Runs four tests per candidate:
- Holdout backtest — 2025-01-01 onward (unseen during optimization)
- Monte Carlo bootstrap — resamples holdout trades to test PnL stability
- Permutation test — shuffles price returns to confirm edge is not noise
- Sensitivity test — perturbs params +/-10% to check for overfitting
Outputs a ranked leaderboard with p-values and recommended params for params.py.
Requires Coinbase Advanced Trade API credentials:
export COINBASE_API_KEY="your_key"
export COINBASE_API_SECRET="your_secret"python run_live_multi_asset.py --symbols ETH,XRP # Trade specific assets
python run_live_multi_asset.py --paper # Paper trading (no real orders)
python run_live_multi_asset.py --list-futures # List available contractsThe live engine uses the same signal generator and per-asset params as the backtester. Parameters are defined once in params.py and shared by both. Telegram alerts on entries, exits, crashes, and shutdowns.
OHLCV data is fetched from Coinbase Advanced Trade API and cached locally. Supports 1min, 30min, 1h, 2h, 4h, 6h, 1d timeframes.
python download_data.py --symbol BTC --days 3650
python download_data.py --symbol ETH --timeframes 1min 2h 4hpip install -r requirements.txtpytest tests/51 tests covering scoring, signal generation, technical indicators, Monte Carlo, ensemble, and optimizer internals.
For informational purposes only. Cryptocurrency trading carries substantial risk of loss. Past backtest performance does not guarantee future results.
MIT
