Compare commits

...

3 Commits

Author SHA1 Message Date
Ajasra
d8cc1a3192 parameter optimisation for strategies (can run a matrix of strategy with different parameters) 2025-05-29 14:23:18 +08:00
Ajasra
df19ef32db bactester for strategies 2025-05-29 14:22:50 +08:00
Ajasra
b0ea701020 Enhance DataLoader and MinuteDataBuffer for improved data handling
- Added error handling in DataLoader to attempt reading CSV files with a fallback to the Python engine if the default engine fails.
- Converted numpy float32 columns to Python float for compatibility in DataLoader.
- Updated MinuteDataBuffer to accept both Python and numpy numeric types, ensuring consistent data validation and conversion.
2025-05-29 14:21:16 +08:00
12 changed files with 2901 additions and 3 deletions

2
.gitignore vendored
View File

@ -172,7 +172,7 @@ cython_debug/
An introduction to trading cycles.pdf
An introduction to trading cycles.txt
README.md
.vscode/launch.json
data/*

268
IncrementalTrader/README.md Normal file
View File

@ -0,0 +1,268 @@
# IncrementalTrader
A high-performance, memory-efficient trading framework designed for real-time algorithmic trading and backtesting. Built around the principle of **incremental computation**, IncrementalTrader processes new data points efficiently without recalculating entire histories.
## 🚀 Key Features
- **Incremental Computation**: Constant memory usage and O(1) processing time per data point
- **Real-time Capable**: Designed for live trading with minimal latency
- **Modular Architecture**: Clean separation between strategies, execution, and testing
- **Built-in Strategies**: MetaTrend, BBRS, and Random strategies included
- **Comprehensive Backtesting**: Multi-threaded backtesting with parameter optimization
- **Rich Indicators**: Supertrend, Bollinger Bands, RSI, Moving Averages, and more
- **Performance Tracking**: Detailed metrics and portfolio analysis
## 📦 Installation
```bash
# Clone the repository
git clone <repository-url>
cd Cycles
# Install dependencies
pip install -r requirements.txt
# Import the module
from IncrementalTrader import *
```
## 🏃‍♂️ Quick Start
### Basic Strategy Usage
```python
from IncrementalTrader import MetaTrendStrategy, IncTrader
import pandas as pd
# Load your data
data = pd.read_csv('your_data.csv')
# Create strategy
strategy = MetaTrendStrategy("metatrend", params={
"timeframe": "15min",
"supertrend_periods": [10, 20, 30],
"supertrend_multipliers": [2.0, 3.0, 4.0]
})
# Create trader
trader = IncTrader(strategy, initial_usd=10000)
# Process data
for _, row in data.iterrows():
trader.process_data_point(
timestamp=row['timestamp'],
ohlcv=(row['open'], row['high'], row['low'], row['close'], row['volume'])
)
# Get results
results = trader.get_results()
print(f"Final Portfolio Value: ${results['final_portfolio_value']:.2f}")
print(f"Total Return: {results['total_return_pct']:.2f}%")
```
### Backtesting
```python
from IncrementalTrader import IncBacktester, BacktestConfig
# Configure backtest
config = BacktestConfig(
initial_usd=10000,
stop_loss_pct=0.03,
take_profit_pct=0.06,
start_date="2024-01-01",
end_date="2024-12-31"
)
# Run backtest
backtester = IncBacktester()
results = backtester.run_single_strategy(
strategy_class=MetaTrendStrategy,
strategy_params={"timeframe": "15min"},
config=config,
data_file="data/BTCUSDT_1m.csv"
)
# Analyze results
print(f"Sharpe Ratio: {results['performance_metrics']['sharpe_ratio']:.2f}")
print(f"Max Drawdown: {results['performance_metrics']['max_drawdown_pct']:.2f}%")
```
## 📊 Available Strategies
### MetaTrend Strategy
A sophisticated trend-following strategy that uses multiple Supertrend indicators to detect market trends.
```python
strategy = MetaTrendStrategy("metatrend", params={
"timeframe": "15min",
"supertrend_periods": [10, 20, 30],
"supertrend_multipliers": [2.0, 3.0, 4.0],
"min_trend_agreement": 0.6
})
```
### BBRS Strategy
Combines Bollinger Bands and RSI with market regime detection for adaptive trading.
```python
strategy = BBRSStrategy("bbrs", params={
"timeframe": "15min",
"bb_period": 20,
"bb_std": 2.0,
"rsi_period": 14,
"volume_ma_period": 20
})
```
### Random Strategy
A testing strategy that generates random signals for framework validation.
```python
strategy = RandomStrategy("random", params={
"timeframe": "15min",
"buy_probability": 0.1,
"sell_probability": 0.1
})
```
## 🔧 Technical Indicators
All indicators are designed for incremental computation:
```python
from IncrementalTrader.strategies.indicators import *
# Moving Averages
sma = MovingAverageState(period=20)
ema = ExponentialMovingAverageState(period=20, alpha=0.1)
# Volatility
atr = ATRState(period=14)
# Trend
supertrend = SupertrendState(period=10, multiplier=3.0)
# Oscillators
rsi = RSIState(period=14)
bb = BollingerBandsState(period=20, std_dev=2.0)
# Update with new data
for price in price_data:
sma.update(price)
current_sma = sma.get_value()
```
## 🧪 Parameter Optimization
```python
from IncrementalTrader import OptimizationConfig
# Define parameter ranges
param_ranges = {
"supertrend_periods": [[10, 20, 30], [15, 25, 35], [20, 30, 40]],
"supertrend_multipliers": [[2.0, 3.0, 4.0], [1.5, 2.5, 3.5]],
"min_trend_agreement": [0.5, 0.6, 0.7, 0.8]
}
# Configure optimization
opt_config = OptimizationConfig(
base_config=config,
param_ranges=param_ranges,
max_workers=4
)
# Run optimization
results = backtester.optimize_strategy(
strategy_class=MetaTrendStrategy,
optimization_config=opt_config,
data_file="data/BTCUSDT_1m.csv"
)
# Get best parameters
best_params = results['best_params']
best_performance = results['best_performance']
```
## 📈 Performance Analysis
```python
# Get detailed performance metrics
performance = results['performance_metrics']
print(f"Total Trades: {performance['total_trades']}")
print(f"Win Rate: {performance['win_rate']:.2f}%")
print(f"Profit Factor: {performance['profit_factor']:.2f}")
print(f"Sharpe Ratio: {performance['sharpe_ratio']:.2f}")
print(f"Max Drawdown: {performance['max_drawdown_pct']:.2f}%")
print(f"Calmar Ratio: {performance['calmar_ratio']:.2f}")
# Access trade history
trades = results['trades']
for trade in trades[-5:]: # Last 5 trades
print(f"Trade: {trade['side']} at {trade['price']} - P&L: {trade['pnl']:.2f}")
```
## 🏗️ Architecture
IncrementalTrader follows a modular architecture:
```
IncrementalTrader/
├── strategies/ # Trading strategies and indicators
│ ├── base.py # Base classes and framework
│ ├── metatrend.py # MetaTrend strategy
│ ├── bbrs.py # BBRS strategy
│ ├── random.py # Random strategy
│ └── indicators/ # Technical indicators
├── trader/ # Trade execution and position management
│ ├── trader.py # Main trader implementation
│ └── position.py # Position management
├── backtester/ # Backtesting framework
│ ├── backtester.py # Main backtesting engine
│ ├── config.py # Configuration management
│ └── utils.py # Utilities and helpers
└── docs/ # Documentation
```
## 🔍 Memory Efficiency
Traditional batch processing vs. IncrementalTrader:
| Aspect | Batch Processing | IncrementalTrader |
|--------|------------------|-------------------|
| Memory Usage | O(n) - grows with data | O(1) - constant |
| Processing Time | O(n) - recalculates all | O(1) - per data point |
| Real-time Capable | No - too slow | Yes - designed for it |
| Scalability | Poor - memory limited | Excellent - unlimited data |
## 📚 Documentation
- [Architecture Overview](docs/architecture.md) - Detailed system design
- [Strategy Development Guide](docs/strategies/strategies.md) - How to create custom strategies
- [Indicator Reference](docs/indicators/base.md) - Complete indicator documentation
- [Backtesting Guide](docs/backtesting.md) - Advanced backtesting features
- [API Reference](docs/api/api.md) - Complete API documentation
## 🤝 Contributing
1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Add tests for new functionality
5. Submit a pull request
## 📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
## 🆘 Support
For questions, issues, or contributions:
- Open an issue on GitHub
- Check the documentation in the `docs/` folder
- Review the examples in the `examples/` folder
---
**IncrementalTrader** - Efficient, scalable, and production-ready algorithmic trading framework.

View File

@ -98,7 +98,11 @@ class DataLoader:
}
# Read data with original capitalized column names
data = pd.read_csv(file_path, dtype=dtypes)
try:
data = pd.read_csv(file_path, dtype=dtypes)
except Exception as e:
logger.warning(f"Failed to read CSV with default engine, trying python engine: {e}")
data = pd.read_csv(file_path, dtype=dtypes, engine='python')
# Handle timestamp column
if 'Timestamp' in data.columns:
@ -107,6 +111,13 @@ class DataLoader:
data = data[(data['Timestamp'] >= start_date) & (data['Timestamp'] <= end_date)]
# Convert column names to lowercase
data.columns = data.columns.str.lower()
# Convert numpy float32 to Python float for compatibility
numeric_columns = ['open', 'high', 'low', 'close', 'volume']
for col in numeric_columns:
if col in data.columns:
data[col] = data[col].astype(float)
logger.info(f"CSV data loaded: {len(data)} rows for {start_date} to {end_date}")
return data.set_index('timestamp')
else:
@ -115,6 +126,13 @@ class DataLoader:
data['timestamp'] = pd.to_datetime(data['timestamp'], unit='s')
data = data[(data['timestamp'] >= start_date) & (data['timestamp'] <= end_date)]
data.columns = data.columns.str.lower()
# Convert numpy float32 to Python float for compatibility
numeric_columns = ['open', 'high', 'low', 'close', 'volume']
for col in numeric_columns:
if col in data.columns:
data[col] = data[col].astype(float)
logger.info(f"CSV data loaded (first column as timestamp): {len(data)} rows for {start_date} to {end_date}")
return data.set_index('timestamp')

View File

@ -319,8 +319,13 @@ class MinuteDataBuffer:
for field in required_fields:
if field not in ohlcv_data:
raise ValueError(f"Missing required field: {field}")
if not isinstance(ohlcv_data[field], (int, float)):
# Accept both Python numeric types and numpy numeric types
if not isinstance(ohlcv_data[field], (int, float, np.number)):
raise ValueError(f"Field {field} must be numeric, got {type(ohlcv_data[field])}")
# Convert numpy types to Python types to ensure compatibility
if isinstance(ohlcv_data[field], np.number):
ohlcv_data[field] = float(ohlcv_data[field])
# Check timestamp ordering (allow equal timestamps for updates)
if self._last_timestamp is not None and timestamp < self._last_timestamp:

View File

@ -0,0 +1,34 @@
{
"backtest_settings": {
"data_file": "btcusd_1-min_data.csv",
"data_dir": "data",
"start_date": "2023-01-01",
"end_date": "2023-01-02",
"initial_usd": 10000
},
"strategies": [
{
"name": "Valid_Strategy",
"type": "random",
"params": {
"signal_probability": 0.001,
"timeframe": "15min"
},
"trader_params": {
"stop_loss_pct": 0.02,
"portfolio_percent_per_trade": 0.5
}
},
{
"name": "Invalid_Strategy",
"type": "nonexistent_strategy",
"params": {
"some_param": 42
},
"trader_params": {
"stop_loss_pct": 0.02,
"portfolio_percent_per_trade": 0.5
}
}
]
}

View File

@ -0,0 +1,83 @@
{
"backtest_settings": {
"data_file": "btcusd_1-min_data.csv",
"data_dir": "data",
"start_date": "2023-01-01",
"end_date": "2023-01-31",
"initial_usd": 10000
},
"strategies": [
{
"name": "MetaTrend_Conservative",
"type": "metatrend",
"params": {
"supertrend_periods": [
12,
10,
11
],
"supertrend_multipliers": [
3.0,
1.0,
2.0
],
"min_trend_agreement": 0.8,
"timeframe": "15min"
},
"trader_params": {
"stop_loss_pct": 0.02,
"portfolio_percent_per_trade": 1.0
}
},
{
"name": "MetaTrend_Aggressive",
"type": "metatrend",
"params": {
"supertrend_periods": [
10,
8,
9
],
"supertrend_multipliers": [
2.0,
1.0,
1.5
],
"min_trend_agreement": 0.5,
"timeframe": "5min"
},
"trader_params": {
"stop_loss_pct": 0.03,
"portfolio_percent_per_trade": 1.0
}
},
{
"name": "BBRS_Default",
"type": "bbrs",
"params": {
"bb_length": 20,
"bb_std": 2.0,
"rsi_length": 14,
"rsi_overbought": 70,
"rsi_oversold": 30,
"timeframe": "15min"
},
"trader_params": {
"stop_loss_pct": 0.025,
"portfolio_percent_per_trade": 1.0
}
},
{
"name": "Random_Baseline",
"type": "random",
"params": {
"signal_probability": 0.001,
"timeframe": "15min"
},
"trader_params": {
"stop_loss_pct": 0.02,
"portfolio_percent_per_trade": 1.0
}
}
]
}

View File

@ -0,0 +1,37 @@
{
"backtest_settings": {
"data_file": "btcusd_1-min_data.csv",
"data_dir": "data",
"start_date": "2025-01-01",
"end_date": "2025-03-01",
"initial_usd": 10000
},
"strategies": [
{
"name": "MetaTrend_Quick_Test",
"type": "metatrend",
"params": {
"supertrend_periods": [12, 10, 11],
"supertrend_multipliers": [3.0, 1.0, 2.0],
"min_trend_agreement": 0.5,
"timeframe": "15min"
},
"trader_params": {
"stop_loss_pct": 0.02,
"portfolio_percent_per_trade": 1.0
}
},
{
"name": "Random_Baseline",
"type": "random",
"params": {
"signal_probability": 0.001,
"timeframe": "15min"
},
"trader_params": {
"stop_loss_pct": 0.02,
"portfolio_percent_per_trade": 1.0
}
}
]
}

333
test/backtest/README.md Normal file
View File

@ -0,0 +1,333 @@
# Strategy Backtest Runner
A comprehensive and efficient backtest runner for executing predefined trading strategies with advanced visualization and analysis capabilities.
## Overview
The Strategy Backtest Runner (`strategy_run.py`) executes specific trading strategies with predefined parameters defined in a JSON configuration file. Unlike the parameter optimization script, this runner focuses on testing and comparing specific strategy configurations with detailed market analysis and visualization.
## Features
- **JSON Configuration**: Define strategies and parameters in easy-to-edit JSON files
- **Multiple Strategy Support**: Run multiple strategies in sequence with a single command
- **All Strategy Types**: Support for MetaTrend, BBRS, and Random strategies
- **Organized Results**: Automatic folder structure creation for each run
- **Advanced Visualization**: Detailed plots showing portfolio performance and market context
- **Full Market Data Integration**: Continuous price charts with buy/sell signals overlay
- **Signal Export**: Complete buy/sell signal data exported to CSV files
- **Real-time File Saving**: Individual strategy results saved immediately upon completion
- **Comprehensive Analysis**: Multiple plot types for thorough performance analysis
- **Detailed Results**: Comprehensive result reporting with CSV and JSON export
- **Result Analysis**: Automatic summary generation and performance comparison
- **Error Handling**: Robust error handling with detailed logging
- **Flexible Configuration**: Support for different data files, date ranges, and trader parameters
## Usage
### Basic Usage
```bash
# Run strategies from a configuration file
python test/backtest/strategy_run.py --config configs/strategy/example_strategies.json
# Save results to a custom directory
python test/backtest/strategy_run.py --config configs/strategy/my_strategies.json --results-dir my_results
# Enable verbose logging
python test/backtest/strategy_run.py --config configs/strategy/example_strategies.json --verbose
```
### Enhanced Analysis Features
Each run automatically generates:
- **Organized folder structure** with timestamp for easy management
- **Real-time file saving** - results saved immediately after each strategy completes
- **Full market data visualization** - continuous price charts show complete market context
- **Signal tracking** - all buy/sell decisions exported with precise timing and pricing
- **Multi-layered analysis** - from individual trade details to portfolio-wide comparisons
- **Professional plots** - high-resolution (300 DPI) charts suitable for reports and presentations
### Create Example Configuration
```bash
# Create an example configuration file
python test/backtest/strategy_run.py --create-example configs/example_strategies.json
```
## Configuration File Format
The configuration file uses JSON format with two main sections:
### Backtest Settings
```json
{
"backtest_settings": {
"data_file": "btcusd_1-min_data.csv",
"data_dir": "data",
"start_date": "2023-01-01",
"end_date": "2023-01-31",
"initial_usd": 10000
}
}
```
### Strategy Definitions
```json
{
"strategies": [
{
"name": "MetaTrend_Conservative",
"type": "metatrend",
"params": {
"supertrend_periods": [12, 10, 11],
"supertrend_multipliers": [3.0, 1.0, 2.0],
"min_trend_agreement": 0.8,
"timeframe": "15min"
},
"trader_params": {
"stop_loss_pct": 0.02,
"portfolio_percent_per_trade": 0.5
}
}
]
}
```
## Strategy Types
### MetaTrend Strategy
Parameters:
- `supertrend_periods`: List of periods for multiple supertrend indicators
- `supertrend_multipliers`: List of multipliers for supertrend indicators
- `min_trend_agreement`: Minimum agreement threshold between indicators (0.0-1.0)
- `timeframe`: Data aggregation timeframe ("1min", "5min", "15min", "30min", "1h")
### BBRS Strategy
Parameters:
- `bb_length`: Bollinger Bands period
- `bb_std`: Bollinger Bands standard deviation multiplier
- `rsi_length`: RSI period
- `rsi_overbought`: RSI overbought threshold
- `rsi_oversold`: RSI oversold threshold
- `timeframe`: Data aggregation timeframe
### Random Strategy
Parameters:
- `signal_probability`: Probability of generating a signal (0.0-1.0)
- `timeframe`: Data aggregation timeframe
## Trader Parameters
All strategies support these trader parameters:
- `stop_loss_pct`: Stop loss percentage (e.g., 0.02 for 2%)
- `portfolio_percent_per_trade`: Percentage of portfolio to use per trade (0.0-1.0)
## Results Organization
Each run creates an organized folder structure for easy navigation and analysis:
```
results/
└── [config_name]_[timestamp]/
├── strategy_1_[strategy_name].json # Individual strategy data
├── strategy_1_[strategy_name]_plot.png # 4-panel performance plot
├── strategy_1_[strategy_name]_detailed_plot.png # 3-panel market analysis
├── strategy_1_[strategy_name]_trades.csv # Trade details
├── strategy_1_[strategy_name]_signals.csv # All buy/sell signals
├── strategy_2_[strategy_name].* # Second strategy files
├── ... # Additional strategies
├── summary.csv # Strategy comparison table
├── summary_plot.png # Multi-strategy comparison
└── summary_*.json # Comprehensive results
```
## Visualization Types
The runner generates three types of plots for comprehensive analysis:
### 1. Individual Strategy Plot (4-Panel)
- **Equity Curve**: Portfolio value over time
- **Trade P&L**: Individual trade profits/losses
- **Drawdown**: Portfolio drawdown visualization
- **Statistics**: Strategy performance summary
### 2. Detailed Market Analysis Plot (3-Panel)
- **Portfolio Signals**: Portfolio value with buy/sell signal markers
- **Market Price**: Full continuous market price with entry/exit points
- **Combined View**: Dual-axis plot showing market vs portfolio performance
### 3. Summary Comparison Plot (4-Panel)
- **Returns Comparison**: Total returns across all strategies
- **Trade Counts**: Number of trades per strategy
- **Risk vs Return**: Win rate vs maximum drawdown scatter plot
- **Statistics Table**: Comprehensive performance metrics
## Output Files
The runner generates comprehensive output files organized in dedicated folders:
### Individual Strategy Files (per strategy)
- `strategy_N_[name].json`: Complete strategy data and metadata
- `strategy_N_[name]_plot.png`: 4-panel performance analysis plot
- `strategy_N_[name]_detailed_plot.png`: 3-panel market context plot
- `strategy_N_[name]_trades.csv`: Detailed trade information
- `strategy_N_[name]_signals.csv`: All buy/sell signals with timestamps
### Summary Files (per run)
- `summary.csv`: Strategy comparison table
- `summary_plot.png`: Multi-strategy comparison visualization
- `summary_*.json`: Comprehensive results and metadata
### Signal Data Format
Each signal CSV contains:
- `signal_id`: Unique signal identifier
- `signal_type`: BUY or SELL
- `time`: Signal timestamp
- `price`: Execution price
- `trade_id`: Associated trade number
- `quantity`: Trade quantity
- `value`: Trade value (quantity × price)
- `strategy`: Strategy name
## Example Configurations
### Simple MetaTrend Test
```json
{
"backtest_settings": {
"data_file": "btcusd_1-min_data.csv",
"start_date": "2023-01-01",
"end_date": "2023-01-07",
"initial_usd": 10000
},
"strategies": [
{
"name": "MetaTrend_Test",
"type": "metatrend",
"params": {
"supertrend_periods": [12, 10],
"supertrend_multipliers": [3.0, 1.0],
"min_trend_agreement": 0.5,
"timeframe": "15min"
},
"trader_params": {
"stop_loss_pct": 0.02,
"portfolio_percent_per_trade": 0.5
}
}
]
}
```
### Multiple Strategy Comparison
```json
{
"backtest_settings": {
"data_file": "btcusd_1-min_data.csv",
"start_date": "2023-01-01",
"end_date": "2023-01-31",
"initial_usd": 10000
},
"strategies": [
{
"name": "Conservative_MetaTrend",
"type": "metatrend",
"params": {
"supertrend_periods": [12, 10, 11],
"supertrend_multipliers": [3.0, 1.0, 2.0],
"min_trend_agreement": 0.8,
"timeframe": "15min"
},
"trader_params": {
"stop_loss_pct": 0.02,
"portfolio_percent_per_trade": 0.5
}
},
{
"name": "Aggressive_MetaTrend",
"type": "metatrend",
"params": {
"supertrend_periods": [10, 8],
"supertrend_multipliers": [2.0, 1.0],
"min_trend_agreement": 0.5,
"timeframe": "5min"
},
"trader_params": {
"stop_loss_pct": 0.03,
"portfolio_percent_per_trade": 0.8
}
},
{
"name": "BBRS_Baseline",
"type": "bbrs",
"params": {
"bb_length": 20,
"bb_std": 2.0,
"rsi_length": 14,
"rsi_overbought": 70,
"rsi_oversold": 30,
"timeframe": "15min"
},
"trader_params": {
"stop_loss_pct": 0.025,
"portfolio_percent_per_trade": 0.6
}
}
]
}
```
## Command Line Options
- `--config`: Path to JSON configuration file (required)
- `--results-dir`: Directory for saving results (default: "results")
- `--create-example`: Create example config file at specified path
- `--verbose`: Enable verbose logging for debugging
## Error Handling
The runner includes comprehensive error handling:
- **Configuration Validation**: Validates JSON structure and required fields
- **Data File Verification**: Checks if data files exist before running
- **Strategy Creation**: Handles unknown strategy types gracefully
- **Backtest Execution**: Captures and logs individual strategy failures
- **Result Saving**: Ensures results are saved even if some strategies fail
## Integration
This runner integrates seamlessly with the existing IncrementalTrader framework:
- Uses the same `IncBacktester` and strategy classes
- Compatible with all existing data formats
- Leverages the same result saving utilities
- Maintains consistency with optimization scripts
## Performance
- **Sequential Execution**: Strategies run one after another for clear logging
- **Real-time Results**: Individual strategy files saved immediately upon completion
- **Efficient Data Loading**: Market data loaded once per run for all visualizations
- **Progress Tracking**: Clear progress indication for long-running backtests
- **Detailed Timing**: Individual strategy execution times are tracked
- **High-Quality Output**: Professional 300 DPI plots suitable for presentations
## Best Practices
1. **Start Small**: Test with short date ranges first
2. **Validate Data**: Ensure data files exist and cover the specified date range
3. **Monitor Resources**: Watch memory usage for very long backtests
4. **Save Configs**: Keep configuration files organized for reproducibility
5. **Use Descriptive Names**: Give strategies clear, descriptive names
6. **Test Incrementally**: Add strategies one by one when debugging
7. **Leverage Visualizations**: Use detailed plots to understand market context and strategy behavior
8. **Analyze Signals**: Review signal CSV files to understand strategy decision patterns
9. **Compare Runs**: Use organized folder structure to compare different parameter sets
10. **Monitor Execution**: Watch real-time progress as individual strategies complete

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,333 @@
# Strategy Parameter Optimization
This directory contains comprehensive tools for optimizing trading strategy parameters using the IncrementalTrader framework.
## Overview
The strategy optimization script provides:
- **Parallel Parameter Testing**: Uses multiple CPU cores for efficient optimization
- **Configurable Supertrend Parameters**: Test different period and multiplier combinations
- **Risk Management Optimization**: Optimize stop-loss and take-profit settings
- **Multiple Timeframes**: Test strategies across different timeframes
- **Comprehensive Results**: Detailed analysis and sensitivity reports
- **Custom Parameter Ranges**: Support for custom parameter configurations
## Files
- `strategy_parameter_optimization.py` - Main optimization script
- `custom_params_example.json` - Example custom parameter configuration
- `README.md` - This documentation
## Quick Start
### 1. Basic Quick Test
Run a quick test with a smaller parameter space:
```bash
python tasks/strategy_parameter_optimization.py --quick-test --create-sample-data
```
This will:
- Create sample data if it doesn't exist
- Test a limited set of parameters for faster execution
- Use the optimal number of CPU cores automatically
### 2. Full Optimization
Run comprehensive parameter optimization:
```bash
python tasks/strategy_parameter_optimization.py \
--data-file "your_data.csv" \
--start-date "2024-01-01" \
--end-date "2024-12-31" \
--optimization-metric "sharpe_ratio"
```
### 3. Custom Parameter Ranges
Create a custom parameter file and use it:
```bash
python tasks/strategy_parameter_optimization.py \
--custom-params "tasks/custom_params_example.json" \
--max-workers 4
```
## Parameter Configuration
### Strategy Parameters
The MetaTrend strategy now supports the following configurable parameters:
| Parameter | Type | Description | Example Values |
|-----------|------|-------------|----------------|
| `timeframe` | str | Analysis timeframe | `"5min"`, `"15min"`, `"30min"`, `"1h"` |
| `supertrend_periods` | List[int] | Periods for Supertrend indicators | `[10, 12, 14]`, `[12, 15, 18]` |
| `supertrend_multipliers` | List[float] | Multipliers for Supertrend indicators | `[2.0, 2.5, 3.0]`, `[1.5, 2.0, 2.5]` |
| `min_trend_agreement` | float | Minimum agreement threshold (0.0-1.0) | `0.6`, `0.8`, `1.0` |
### Risk Management Parameters
| Parameter | Type | Description | Example Values |
|-----------|------|-------------|----------------|
| `stop_loss_pct` | float | Stop loss percentage | `0.02` (2%), `0.03` (3%) |
| `take_profit_pct` | float | Take profit percentage | `0.04` (4%), `0.06` (6%) |
### Understanding min_trend_agreement
The `min_trend_agreement` parameter controls how many Supertrend indicators must agree:
- `1.0` - All indicators must agree (original behavior)
- `0.8` - 80% of indicators must agree
- `0.6` - 60% of indicators must agree
- `0.5` - Simple majority must agree
## Usage Examples
### Example 1: Test Different Timeframes
```json
{
"timeframe": ["5min", "15min", "30min", "1h"],
"min_trend_agreement": [1.0],
"stop_loss_pct": [0.03],
"take_profit_pct": [0.06]
}
```
### Example 2: Optimize Supertrend Parameters
```json
{
"timeframe": ["15min"],
"supertrend_periods": [
[8, 10, 12],
[10, 12, 14],
[12, 15, 18],
[15, 20, 25]
],
"supertrend_multipliers": [
[1.5, 2.0, 2.5],
[2.0, 2.5, 3.0],
[2.5, 3.0, 3.5]
],
"min_trend_agreement": [0.6, 0.8, 1.0]
}
```
### Example 3: Risk Management Focus
```json
{
"timeframe": ["15min"],
"stop_loss_pct": [0.01, 0.015, 0.02, 0.025, 0.03, 0.04, 0.05],
"take_profit_pct": [0.02, 0.03, 0.04, 0.05, 0.06, 0.08, 0.10]
}
```
## Command Line Options
```bash
python tasks/strategy_parameter_optimization.py [OPTIONS]
```
### Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `--data-file` | str | `sample_btc_1min.csv` | Data file for backtesting |
| `--data-dir` | str | `data` | Directory containing data files |
| `--results-dir` | str | `results` | Directory for saving results |
| `--start-date` | str | `2024-01-01` | Start date (YYYY-MM-DD) |
| `--end-date` | str | `2024-03-31` | End date (YYYY-MM-DD) |
| `--initial-usd` | float | `10000` | Initial USD balance |
| `--max-workers` | int | `auto` | Maximum parallel workers |
| `--quick-test` | flag | `false` | Use smaller parameter space |
| `--optimization-metric` | str | `sharpe_ratio` | Metric to optimize |
| `--create-sample-data` | flag | `false` | Create sample data |
| `--custom-params` | str | `none` | JSON file with custom ranges |
### Optimization Metrics
Available optimization metrics:
- `profit_ratio` - Total profit ratio
- `sharpe_ratio` - Risk-adjusted return (recommended)
- `sortino_ratio` - Downside risk-adjusted return
- `calmar_ratio` - Return to max drawdown ratio
## Output Files
The script generates several output files in the results directory:
### 1. Summary Report
`optimization_MetaTrendStrategy_sharpe_ratio_TIMESTAMP_summary.json`
Contains:
- Best performing parameters
- Summary statistics across all runs
- Session information
### 2. Detailed Results
`optimization_MetaTrendStrategy_sharpe_ratio_TIMESTAMP_detailed.csv`
Contains:
- All parameter combinations tested
- Performance metrics for each combination
- Success/failure status
### 3. Individual Strategy Results
`optimization_MetaTrendStrategy_sharpe_ratio_TIMESTAMP_strategy_N_metatrend.json`
Contains:
- Detailed results for each parameter combination
- Trade-by-trade breakdown
- Strategy-specific metrics
### 4. Sensitivity Analysis
`sensitivity_analysis_TIMESTAMP.json`
Contains:
- Parameter correlation analysis
- Performance impact of each parameter
- Top performing configurations
### 5. Master Index
`optimization_MetaTrendStrategy_sharpe_ratio_TIMESTAMP_index.json`
Contains:
- File index for easy navigation
- Quick statistics summary
- Session metadata
## Performance Considerations
### System Resources
The script automatically detects your system capabilities and uses optimal worker counts:
- **CPU Cores**: Uses ~75% of available cores
- **Memory**: Limits workers based on available RAM
- **I/O**: Handles large result datasets efficiently
### Parameter Space Size
Be aware of exponential growth in parameter combinations:
- Quick test: ~48 combinations
- Full test: ~5,000+ combinations
- Custom ranges: Varies based on configuration
### Execution Time
Approximate execution times (varies by system and data size):
- Quick test: 2-10 minutes
- Medium test: 30-60 minutes
- Full test: 2-8 hours
## Data Requirements
### Data Format
The script expects CSV data with columns:
- `timestamp` - Unix timestamp in milliseconds
- `open` - Opening price
- `high` - Highest price
- `low` - Lowest price
- `close` - Closing price
- `volume` - Trading volume
### Sample Data
Use `--create-sample-data` to generate sample data for testing:
```bash
python tasks/strategy_parameter_optimization.py --create-sample-data --quick-test
```
## Advanced Usage
### 1. Distributed Optimization
For very large parameter spaces, consider running multiple instances:
```bash
# Terminal 1 - Test timeframes 5min, 15min
python tasks/strategy_parameter_optimization.py --custom-params timeframe_5_15.json
# Terminal 2 - Test timeframes 30min, 1h
python tasks/strategy_parameter_optimization.py --custom-params timeframe_30_1h.json
```
### 2. Walk-Forward Analysis
For more robust results, test across multiple time periods:
```bash
# Q1 2024
python tasks/strategy_parameter_optimization.py --start-date 2024-01-01 --end-date 2024-03-31
# Q2 2024
python tasks/strategy_parameter_optimization.py --start-date 2024-04-01 --end-date 2024-06-30
```
### 3. Custom Metrics
The script supports custom optimization metrics. See the documentation for implementation details.
## Troubleshooting
### Common Issues
1. **Memory Errors**: Reduce `--max-workers` or use `--quick-test`
2. **Data Not Found**: Use `--create-sample-data` or check file path
3. **Import Errors**: Ensure IncrementalTrader is properly installed
4. **Slow Performance**: Check system resources and reduce parameter space
### Logging
The script provides detailed logging. For debug information:
```python
import logging
logging.getLogger().setLevel(logging.DEBUG)
```
## Examples
### Quick Start Example
```bash
# Run quick optimization with sample data
python tasks/strategy_parameter_optimization.py \
--quick-test \
--create-sample-data \
--optimization-metric sharpe_ratio \
--max-workers 4
```
### Production Example
```bash
# Run comprehensive optimization with real data
python tasks/strategy_parameter_optimization.py \
--data-file "BTCUSDT_1m_2024.csv" \
--start-date "2024-01-01" \
--end-date "2024-12-31" \
--optimization-metric calmar_ratio \
--custom-params "production_params.json"
```
This comprehensive setup allows you to:
1. **Test the modified MetaTrend strategy** with configurable Supertrend parameters
2. **Run parameter optimization in parallel** using system utilities from utils.py
3. **Test multiple timeframes and risk management settings**
4. **Get detailed analysis and sensitivity reports**
5. **Use custom parameter ranges** for focused optimization
The script leverages the existing IncrementalTrader framework and integrates with the utilities you already have in place.

View File

@ -0,0 +1,18 @@
{
"timeframe": ["15min", "30min"],
"supertrend_periods": [
[8, 12, 16],
[10, 15, 20],
[12, 18, 24],
[14, 21, 28]
],
"supertrend_multipliers": [
[1.5, 2.0, 2.5],
[2.0, 3.0, 4.0],
[1.0, 2.0, 3.0],
[1.0, 2.0, 3.0]
],
"min_trend_agreement": [0.6, 0.7, 0.8, 1.0, 1.0],
"stop_loss_pct": [0.02, 0.03, 0.04, 0.05],
"take_profit_pct": [0.00, 0.00, 0.00, 0.00]
}

View File

@ -0,0 +1,466 @@
#!/usr/bin/env python3
"""
Strategy Parameter Optimization Script for IncrementalTrader
This script provides comprehensive parameter optimization for trading strategies,
specifically designed for testing MetaTrend strategy with various configurations
including supertrend parameters, timeframes, and risk management settings.
Features:
- Parallel execution using multiple CPU cores
- Configurable parameter grids for strategy and risk management
- Comprehensive results analysis and reporting
- Support for custom optimization metrics
- Detailed logging and progress tracking
- Individual strategy plotting and analysis
Usage:
python tasks/strategy_parameter_optimization.py --help
"""
import os
import sys
import argparse
import logging
import json
import time
import traceback
from datetime import datetime, timedelta
from typing import Dict, List, Any, Optional, Tuple
from concurrent.futures import ProcessPoolExecutor, as_completed
from itertools import product
import pandas as pd
import numpy as np
from tqdm import tqdm
# Import plotting libraries for result visualization
try:
import matplotlib.pyplot as plt
import seaborn as sns
plt.style.use('default')
PLOTTING_AVAILABLE = True
except ImportError:
PLOTTING_AVAILABLE = False
# Add project root to path
project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, project_root)
# Import IncrementalTrader components
from IncrementalTrader.backtester import IncBacktester, BacktestConfig
from IncrementalTrader.backtester.utils import DataLoader, SystemUtils, ResultsSaver
from IncrementalTrader.strategies import MetaTrendStrategy
from IncrementalTrader.trader import IncTrader
# Set up logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.StreamHandler(sys.stdout),
logging.FileHandler('optimization.log')
]
)
logger = logging.getLogger(__name__)
# Reduce verbosity for entry/exit logging
logging.getLogger('IncrementalTrader.strategies').setLevel(logging.WARNING)
logging.getLogger('IncrementalTrader.trader').setLevel(logging.WARNING)
class StrategyOptimizer:
"""
Advanced parameter optimization for IncrementalTrader strategies.
This class provides comprehensive parameter optimization with parallel processing,
sensitivity analysis, and detailed result reporting.
"""
def __init__(self):
"""Initialize the StrategyOptimizer."""
# Initialize utilities
self.system_utils = SystemUtils()
# Session tracking
self.session_start_time = datetime.now()
self.optimization_results = []
logger.info(f"StrategyOptimizer initialized")
logger.info(f"System info: {self.system_utils.get_system_info()}")
def generate_parameter_combinations(self, params_dict: Dict[str, List]) -> List[Dict[str, Dict]]:
"""
Generate all possible parameter combinations.
Args:
params_dict: Dictionary with strategy_params and trader_params lists
Returns:
List of parameter combinations
"""
strategy_params = params_dict.get('strategy_params', {})
trader_params = params_dict.get('trader_params', {})
# Generate all combinations
combinations = []
# Get all strategy parameter combinations
strategy_keys = list(strategy_params.keys())
strategy_values = list(strategy_params.values())
trader_keys = list(trader_params.keys())
trader_values = list(trader_params.values())
for strategy_combo in product(*strategy_values):
strategy_dict = dict(zip(strategy_keys, strategy_combo))
for trader_combo in product(*trader_values):
trader_dict = dict(zip(trader_keys, trader_combo))
combinations.append({
'strategy_params': strategy_dict,
'trader_params': trader_dict
})
return combinations
def get_quick_test_params(self) -> Dict[str, List]:
"""
Get parameters for quick testing (smaller parameter space for faster execution).
Returns:
Dictionary with parameter ranges for quick testing
"""
return {
"strategy_params": {
"supertrend_periods": [[12, 10], [10, 8]], # Only 2 period combinations
"supertrend_multipliers": [[3.0, 1.0], [2.0, 1.5]], # Only 2 multiplier combinations
"min_trend_agreement": [0.5, 0.8], # Only 2 agreement levels
"timeframe": ["5min", "15min"] # Only 2 timeframes
},
"trader_params": {
"stop_loss_pct": [0.02, 0.05], # Only 2 stop loss levels
"portfolio_percent_per_trade": [0.8, 0.9] # Only 2 position sizes
}
}
def get_comprehensive_params(self) -> Dict[str, List]:
"""
Get parameters for comprehensive optimization (larger parameter space).
Returns:
Dictionary with parameter ranges for comprehensive optimization
"""
return {
"strategy_params": {
"supertrend_periods": [
[12, 10, 11], [10, 8, 9], [14, 12, 13],
[16, 14, 15], [20, 18, 19]
],
"supertrend_multipliers": [
[3.0, 1.0, 2.0], [2.5, 1.5, 2.0], [3.5, 2.0, 2.5],
[2.0, 1.0, 1.5], [4.0, 2.5, 3.0]
],
"min_trend_agreement": [0.33, 0.5, 0.67, 0.8, 1.0],
"timeframe": ["1min", "5min", "15min", "30min", "1h"]
},
"trader_params": {
"stop_loss_pct": [0.01, 0.015, 0.02, 0.025, 0.03, 0.04, 0.05],
"portfolio_percent_per_trade": [0.1, 0.2, 0.3, 0.5, 0.8, 0.9, 1.0]
}
}
def run_single_backtest(self, params: Dict[str, Any]) -> Dict[str, Any]:
"""
Run a single backtest with given parameters.
Args:
params: Dictionary containing all parameters for the backtest
Returns:
Dictionary with backtest results
"""
try:
start_time = time.time()
# Extract parameters
strategy_params = params['strategy_params']
trader_params = params['trader_params']
data_file = params['data_file']
start_date = params['start_date']
end_date = params['end_date']
data_dir = params['data_dir']
# Create strategy name for identification
strategy_name = f"MetaTrend_TF{strategy_params['timeframe']}_ST{len(strategy_params['supertrend_periods'])}_SL{trader_params['stop_loss_pct']}_POS{trader_params['portfolio_percent_per_trade']}"
# Create strategy
strategy = MetaTrendStrategy(name="metatrend", params=strategy_params)
# Create backtest config (only with BacktestConfig-supported parameters)
config = BacktestConfig(
data_file=data_file,
start_date=start_date,
end_date=end_date,
initial_usd=10000,
data_dir=data_dir,
stop_loss_pct=trader_params.get('stop_loss_pct', 0.0)
)
# Create backtester
backtester = IncBacktester(config)
# Run backtest with trader-specific parameters
results = backtester.run_single_strategy(strategy, trader_params)
# Calculate additional metrics
end_time = time.time()
backtest_duration = end_time - start_time
# Format results
formatted_results = {
"success": True,
"strategy_name": strategy_name,
"strategy_params": strategy_params,
"trader_params": trader_params,
"initial_usd": results["initial_usd"],
"final_usd": results["final_usd"],
"profit_ratio": results["profit_ratio"],
"n_trades": results["n_trades"],
"win_rate": results["win_rate"],
"max_drawdown": results["max_drawdown"],
"avg_trade": results["avg_trade"],
"total_fees_usd": results["total_fees_usd"],
"backtest_duration_seconds": backtest_duration,
"data_points_processed": results.get("data_points", 0),
"warmup_complete": results.get("warmup_complete", False),
"trades": results.get("trades", [])
}
return formatted_results
except Exception as e:
logger.error(f"Error in backtest {params.get('strategy_params', {}).get('timeframe', 'unknown')}: {e}")
return {
"success": False,
"error": str(e),
"strategy_name": strategy_name if 'strategy_name' in locals() else "Unknown",
"strategy_params": params.get('strategy_params', {}),
"trader_params": params.get('trader_params', {}),
"traceback": traceback.format_exc()
}
def optimize_parallel(self, params_dict: Dict[str, List],
data_file: str, start_date: str, end_date: str,
data_dir: str = "data", max_workers: Optional[int] = None) -> List[Dict[str, Any]]:
"""
Run parameter optimization using parallel processing with progress tracking.
Args:
params_dict: Dictionary with parameter ranges
data_file: Data file for backtesting
start_date: Start date for backtesting
end_date: End date for backtesting
data_dir: Directory containing data files
max_workers: Maximum number of worker processes
Returns:
List of backtest results
"""
# Generate parameter combinations
param_combinations = self.generate_parameter_combinations(params_dict)
total_combinations = len(param_combinations)
logger.info(f"Starting optimization with {total_combinations} parameter combinations")
logger.info(f"Using {max_workers or self.system_utils.get_optimal_workers()} worker processes")
# Prepare jobs
jobs = []
for combo in param_combinations:
job_params = {
'strategy_params': combo['strategy_params'],
'trader_params': combo['trader_params'],
'data_file': data_file,
'start_date': start_date,
'end_date': end_date,
'data_dir': data_dir
}
jobs.append(job_params)
# Run parallel optimization with progress bar
results = []
failed_jobs = []
max_workers = max_workers or self.system_utils.get_optimal_workers()
with ProcessPoolExecutor(max_workers=max_workers) as executor:
# Submit all jobs
future_to_params = {executor.submit(self.run_single_backtest, job): job for job in jobs}
# Process results with progress bar
with tqdm(total=total_combinations, desc="Optimizing strategies", unit="strategy") as pbar:
for future in as_completed(future_to_params):
try:
result = future.result(timeout=300) # 5 minute timeout per job
results.append(result)
if result['success']:
pbar.set_postfix({
'Success': f"{len([r for r in results if r['success']])}/{len(results)}",
'Best Profit': f"{max([r.get('profit_ratio', 0) for r in results if r['success']], default=0):.1%}"
})
else:
failed_jobs.append(future_to_params[future])
except Exception as e:
logger.error(f"Job failed with exception: {e}")
failed_jobs.append(future_to_params[future])
results.append({
"success": False,
"error": f"Job exception: {e}",
"strategy_name": "Failed",
"strategy_params": future_to_params[future].get('strategy_params', {}),
"trader_params": future_to_params[future].get('trader_params', {})
})
pbar.update(1)
# Log summary
successful_results = [r for r in results if r['success']]
logger.info(f"Optimization completed: {len(successful_results)}/{total_combinations} successful")
if failed_jobs:
logger.warning(f"{len(failed_jobs)} jobs failed")
return results
def main():
"""Main function for running parameter optimization."""
parser = argparse.ArgumentParser(description="Strategy Parameter Optimization")
parser.add_argument("--data-file", type=str, default="btcusd_1-min_data.csv",
help="Data file for backtesting")
parser.add_argument("--data-dir", type=str, default="data",
help="Directory containing data files")
parser.add_argument("--results-dir", type=str, default="results",
help="Directory for saving results")
parser.add_argument("--start-date", type=str, default="2023-01-01",
help="Start date for backtesting (YYYY-MM-DD)")
parser.add_argument("--end-date", type=str, default="2023-01-31",
help="End date for backtesting (YYYY-MM-DD)")
parser.add_argument("--max-workers", type=int, default=None,
help="Maximum number of worker processes")
parser.add_argument("--quick-test", action="store_true",
help="Run quick test with smaller parameter space")
parser.add_argument("--custom-params", type=str, default=None,
help="Path to custom parameter configuration JSON file")
args = parser.parse_args()
# Adjust dates for quick test - use only 3 days for very fast testing
if args.quick_test:
args.start_date = "2023-01-01"
args.end_date = "2023-01-03" # Only 3 days for quick test
logger.info("Quick test mode: Using shortened time period (2023-01-01 to 2023-01-03)")
# Create optimizer
optimizer = StrategyOptimizer()
# Determine parameter configuration
if args.custom_params:
# Load custom parameters from JSON file
if not os.path.exists(args.custom_params):
logger.error(f"Custom parameter file not found: {args.custom_params}")
return
with open(args.custom_params, 'r') as f:
params_dict = json.load(f)
logger.info(f"Using custom parameters from: {args.custom_params}")
elif args.quick_test:
# Quick test parameters
params_dict = optimizer.get_quick_test_params()
logger.info("Using quick test parameter configuration")
else:
# Comprehensive optimization parameters
params_dict = optimizer.get_comprehensive_params()
logger.info("Using comprehensive optimization parameter configuration")
# Log optimization details
total_combinations = len(optimizer.generate_parameter_combinations(params_dict))
logger.info(f"Total parameter combinations: {total_combinations}")
logger.info(f"Data file: {args.data_file}")
logger.info(f"Date range: {args.start_date} to {args.end_date}")
logger.info(f"Results directory: {args.results_dir}")
# Check if data file exists
data_path = os.path.join(args.data_dir, args.data_file)
if not os.path.exists(data_path):
logger.error(f"Data file not found: {data_path}")
return
# Create results directory
os.makedirs(args.results_dir, exist_ok=True)
try:
# Run optimization
session_start_time = datetime.now()
logger.info("Starting parameter optimization...")
results = optimizer.optimize_parallel(
params_dict=params_dict,
data_file=args.data_file,
start_date=args.start_date,
end_date=args.end_date,
data_dir=args.data_dir,
max_workers=args.max_workers
)
# Save results
saver = ResultsSaver(args.results_dir)
# Generate base filename
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
test_type = "quick_test" if args.quick_test else "comprehensive"
base_filename = f"metatrend_optimization_{test_type}"
# Save comprehensive results
saver.save_comprehensive_results(
results=results,
base_filename=base_filename,
session_start_time=session_start_time
)
# Calculate and display summary statistics
successful_results = [r for r in results if r['success']]
if successful_results:
# Sort by profit ratio
sorted_results = sorted(successful_results, key=lambda x: x['profit_ratio'], reverse=True)
print(f"\nOptimization Summary:")
print(f" Successful runs: {len(successful_results)}/{len(results)}")
print(f" Total duration: {(datetime.now() - session_start_time).total_seconds():.1f} seconds")
print(f"\nTop 5 Strategies:")
for i, result in enumerate(sorted_results[:5], 1):
print(f" {i}. {result['strategy_name']}")
print(f" Profit: {result['profit_ratio']:.1%} (${result['final_usd']:.2f})")
print(f" Trades: {result['n_trades']} | Win Rate: {result['win_rate']:.1%}")
print(f" Max DD: {result['max_drawdown']:.1%}")
else:
print(f"\nNo successful optimization runs completed")
logger.error("All optimization runs failed")
print(f"\nFull results saved to: {args.results_dir}/")
except KeyboardInterrupt:
logger.info("Optimization interrupted by user")
except Exception as e:
logger.error(f"Optimization failed: {e}")
traceback.print_exc()
if __name__ == "__main__":
main()