2026-01-18 11:08:57 +08:00
|
|
|
# Lowkey Backtest
|
|
|
|
|
|
|
|
|
|
A backtesting framework supporting multiple market types (spot, perpetual) with realistic trading simulation including leverage, funding, and shorts.
|
|
|
|
|
|
|
|
|
|
## Requirements
|
|
|
|
|
|
2025-08-12 10:33:17 +08:00
|
|
|
- Python 3.12+
|
2026-01-18 11:08:57 +08:00
|
|
|
- Package manager: `uv`
|
2025-08-12 10:33:17 +08:00
|
|
|
|
2026-01-18 11:08:57 +08:00
|
|
|
## Installation
|
2025-08-12 10:33:17 +08:00
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
uv sync
|
|
|
|
|
```
|
|
|
|
|
|
2026-01-18 11:08:57 +08:00
|
|
|
## Quick Reference
|
|
|
|
|
|
|
|
|
|
| Command | Description |
|
|
|
|
|
|---------|-------------|
|
|
|
|
|
| `uv run python main.py download -p BTC-USDT` | Download data |
|
|
|
|
|
| `uv run python main.py backtest -s meta_st -p BTC-USDT` | Run backtest |
|
|
|
|
|
| `uv run python main.py wfa -s regime -p BTC-USDT` | Walk-forward analysis |
|
|
|
|
|
| `uv run python train_model.py --download` | Train/retrain ML model |
|
|
|
|
|
| `uv run python research/regime_detection.py` | Run research script |
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Backtest CLI
|
|
|
|
|
|
|
|
|
|
The main entry point is `main.py` which provides three commands: `download`, `backtest`, and `wfa`.
|
|
|
|
|
|
|
|
|
|
### Download Data
|
|
|
|
|
|
|
|
|
|
Download historical OHLCV data from exchanges.
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
uv run python main.py download -p BTC-USDT -t 1h
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**Options:**
|
|
|
|
|
- `-p, --pair` (required): Trading pair (e.g., `BTC-USDT`, `ETH-USDT`)
|
|
|
|
|
- `-t, --timeframe`: Timeframe (default: `1m`)
|
|
|
|
|
- `-e, --exchange`: Exchange (default: `okx`)
|
|
|
|
|
- `-m, --market`: Market type: `spot` or `perpetual` (default: `spot`)
|
|
|
|
|
- `--start`: Start date in `YYYY-MM-DD` format
|
|
|
|
|
|
|
|
|
|
**Examples:**
|
|
|
|
|
```bash
|
|
|
|
|
# Download 1-hour spot data
|
|
|
|
|
uv run python main.py download -p ETH-USDT -t 1h
|
|
|
|
|
|
|
|
|
|
# Download perpetual data from a specific date
|
|
|
|
|
uv run python main.py download -p BTC-USDT -m perpetual --start 2024-01-01
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Run Backtest
|
|
|
|
|
|
|
|
|
|
Run a backtest with a specific strategy.
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
uv run python main.py backtest -s <strategy> -p <pair> [options]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**Available Strategies:**
|
|
|
|
|
- `meta_st` - Meta Supertrend (triple supertrend consensus)
|
|
|
|
|
- `regime` - Regime Reversion (ML-based spread trading)
|
|
|
|
|
- `rsi` - RSI overbought/oversold
|
|
|
|
|
- `macross` - Moving Average Crossover
|
|
|
|
|
|
|
|
|
|
**Options:**
|
|
|
|
|
- `-s, --strategy` (required): Strategy name
|
|
|
|
|
- `-p, --pair` (required): Trading pair
|
|
|
|
|
- `-t, --timeframe`: Timeframe (default: `1m`)
|
|
|
|
|
- `--start`: Start date
|
|
|
|
|
- `--end`: End date
|
|
|
|
|
- `-g, --grid`: Run grid search optimization
|
|
|
|
|
- `--plot`: Show equity curve plot
|
|
|
|
|
- `--sl`: Stop loss percentage
|
|
|
|
|
- `--tp`: Take profit percentage
|
|
|
|
|
- `--trail`: Enable trailing stop
|
|
|
|
|
- `--fees`: Override fee rate
|
|
|
|
|
- `--slippage`: Slippage (default: `0.001`)
|
|
|
|
|
- `-l, --leverage`: Leverage multiplier
|
|
|
|
|
|
|
|
|
|
**Examples:**
|
|
|
|
|
```bash
|
|
|
|
|
# Basic backtest with Meta Supertrend
|
|
|
|
|
uv run python main.py backtest -s meta_st -p BTC-USDT -t 1h
|
|
|
|
|
|
|
|
|
|
# Backtest with date range and plot
|
|
|
|
|
uv run python main.py backtest -s meta_st -p BTC-USDT --start 2024-01-01 --end 2024-12-31 --plot
|
|
|
|
|
|
|
|
|
|
# Grid search optimization
|
|
|
|
|
uv run python main.py backtest -s meta_st -p BTC-USDT -t 4h -g
|
|
|
|
|
|
|
|
|
|
# Backtest with risk parameters
|
|
|
|
|
uv run python main.py backtest -s meta_st -p BTC-USDT --sl 0.05 --tp 0.10 --trail
|
|
|
|
|
|
|
|
|
|
# Regime strategy on ETH/BTC spread
|
|
|
|
|
uv run python main.py backtest -s regime -p ETH-USDT -t 1h
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Walk-Forward Analysis (WFA)
|
|
|
|
|
|
|
|
|
|
Run walk-forward optimization to avoid overfitting.
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
uv run python main.py wfa -s <strategy> -p <pair> [options]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**Options:**
|
|
|
|
|
- `-s, --strategy` (required): Strategy name
|
|
|
|
|
- `-p, --pair` (required): Trading pair
|
|
|
|
|
- `-t, --timeframe`: Timeframe (default: `1d`)
|
|
|
|
|
- `-w, --windows`: Number of walk-forward windows (default: `10`)
|
|
|
|
|
- `--plot`: Show WFA results plot
|
|
|
|
|
|
|
|
|
|
**Examples:**
|
|
|
|
|
```bash
|
|
|
|
|
# Walk-forward analysis with 10 windows
|
|
|
|
|
uv run python main.py wfa -s meta_st -p BTC-USDT -t 1d -w 10
|
|
|
|
|
|
|
|
|
|
# WFA with plot output
|
|
|
|
|
uv run python main.py wfa -s regime -p ETH-USDT --plot
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
2025-08-12 10:33:17 +08:00
|
|
|
|
2026-01-18 11:08:57 +08:00
|
|
|
## Research Scripts
|
|
|
|
|
|
|
|
|
|
Research scripts are located in the `research/` directory for experimental analysis.
|
|
|
|
|
|
|
|
|
|
### Regime Detection Research
|
|
|
|
|
|
|
|
|
|
Tests multiple holding horizons for the regime reversion strategy using walk-forward training.
|
2025-08-12 10:33:17 +08:00
|
|
|
|
|
|
|
|
```bash
|
2026-01-18 11:08:57 +08:00
|
|
|
uv run python research/regime_detection.py
|
2025-08-12 10:33:17 +08:00
|
|
|
```
|
|
|
|
|
|
2026-01-18 11:08:57 +08:00
|
|
|
**Options:**
|
|
|
|
|
- `--days DAYS`: Number of days of historical data (default: 90)
|
|
|
|
|
- `--start DATE`: Start date (YYYY-MM-DD), overrides `--days`
|
|
|
|
|
- `--end DATE`: End date (YYYY-MM-DD), defaults to now
|
|
|
|
|
- `--output PATH`: Output CSV path
|
|
|
|
|
|
|
|
|
|
**Examples:**
|
|
|
|
|
```bash
|
|
|
|
|
# Use last 90 days (default)
|
|
|
|
|
uv run python research/regime_detection.py
|
|
|
|
|
|
|
|
|
|
# Use last 180 days
|
|
|
|
|
uv run python research/regime_detection.py --days 180
|
|
|
|
|
|
|
|
|
|
# Specific date range
|
|
|
|
|
uv run python research/regime_detection.py --start 2025-07-01 --end 2025-12-31
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**What it does:**
|
|
|
|
|
- Loads BTC and ETH hourly data
|
|
|
|
|
- Calculates spread features (Z-score, RSI, volume ratios)
|
|
|
|
|
- Trains RandomForest classifier with walk-forward methodology
|
|
|
|
|
- Tests horizons from 6h to 150h
|
|
|
|
|
- Outputs best parameters by F1 score, Net PnL, and MAE
|
|
|
|
|
|
|
|
|
|
**Output:**
|
|
|
|
|
- Console: Summary of results for each horizon
|
|
|
|
|
- File: `research/horizon_optimization_results.csv`
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## ML Model Training
|
|
|
|
|
|
|
|
|
|
The `regime` strategy uses a RandomForest classifier that can be trained with new data.
|
|
|
|
|
|
|
|
|
|
### Train Model
|
|
|
|
|
|
|
|
|
|
Train or retrain the ML model with latest data:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
uv run python train_model.py [options]
|
2025-08-12 10:33:17 +08:00
|
|
|
```
|
|
|
|
|
|
2026-01-18 11:08:57 +08:00
|
|
|
**Options:**
|
|
|
|
|
- `--days DAYS`: Days of historical data (default: 90)
|
|
|
|
|
- `--pair PAIR`: Base pair for context (default: BTC-USDT)
|
|
|
|
|
- `--spread-pair PAIR`: Trading pair (default: ETH-USDT)
|
|
|
|
|
- `--timeframe TF`: Timeframe (default: 1h)
|
|
|
|
|
- `--market TYPE`: Market type: `spot` or `perpetual` (default: perpetual)
|
|
|
|
|
- `--output PATH`: Model output path (default: `data/regime_model.pkl`)
|
|
|
|
|
- `--train-ratio R`: Train/test split ratio (default: 0.7)
|
|
|
|
|
- `--horizon H`: Prediction horizon in bars (default: 102)
|
|
|
|
|
- `--download`: Download latest data before training
|
|
|
|
|
- `--dry-run`: Run without saving model
|
2025-08-12 10:33:17 +08:00
|
|
|
|
2026-01-18 11:08:57 +08:00
|
|
|
**Examples:**
|
|
|
|
|
```bash
|
|
|
|
|
# Train with last 90 days of data
|
|
|
|
|
uv run python train_model.py
|
|
|
|
|
|
|
|
|
|
# Download fresh data and train
|
|
|
|
|
uv run python train_model.py --download
|
|
|
|
|
|
|
|
|
|
# Train with 180 days of data
|
|
|
|
|
uv run python train_model.py --days 180
|
2025-07-29 20:51:11 +00:00
|
|
|
|
2026-01-18 11:08:57 +08:00
|
|
|
# Train on spot market data
|
|
|
|
|
uv run python train_model.py --market spot
|
|
|
|
|
|
|
|
|
|
# Dry run to see metrics without saving
|
|
|
|
|
uv run python train_model.py --dry-run
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Daily Retraining (Cron)
|
|
|
|
|
|
|
|
|
|
To automate daily model retraining, add a cron job:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
# Edit crontab
|
|
|
|
|
crontab -e
|
|
|
|
|
|
|
|
|
|
# Add entry to retrain daily at 00:30 UTC
|
|
|
|
|
30 0 * * * cd /path/to/lowkey_backtest_live && uv run python train_model.py --download >> logs/training.log 2>&1
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Model Files
|
|
|
|
|
|
|
|
|
|
| File | Description |
|
|
|
|
|
|------|-------------|
|
|
|
|
|
| `data/regime_model.pkl` | Current production model |
|
|
|
|
|
| `data/regime_model_YYYYMMDD_HHMMSS.pkl` | Versioned model snapshots |
|
|
|
|
|
|
|
|
|
|
The model file contains:
|
|
|
|
|
- Trained RandomForest classifier
|
|
|
|
|
- Feature column names
|
|
|
|
|
- Training metrics (F1 score, sample counts)
|
|
|
|
|
- Training timestamp
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Output Files
|
|
|
|
|
|
|
|
|
|
| Location | Description |
|
|
|
|
|
|----------|-------------|
|
|
|
|
|
| `backtest_logs/` | Trade logs and WFA results |
|
|
|
|
|
| `research/` | Research output files |
|
|
|
|
|
| `data/` | Downloaded OHLCV data and ML models |
|
|
|
|
|
| `data/regime_model.pkl` | Trained ML model for regime strategy |
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Running Tests
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
uv run pytest tests/
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Run a specific test file:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
uv run pytest tests/test_data_manager.py
|
|
|
|
|
```
|