A professional-grade backtesting system for intraday trading strategies built with C++ for high-performance execution and Python for comprehensive analytics.
This project provides a complete backtesting framework designed for testing trading strategies on large intraday datasets. It combines the speed of C++ with the analytical power of Python to deliver fast, reliable, and insightful strategy testing.
- β‘ High-Performance C++ Core: Optimized for speed with multithreaded execution
- π Modular Indicator System: Easy-to-extend framework for technical indicators
- π Parallel Parameter Optimization: Test multiple parameter combinations concurrently
- πΎ Efficient Data Storage: Uses Apache Parquet for fast I/O operations
- π Comprehensive Analytics: Python-based analysis with Sharpe, Sortino, Profit Factor, and more
- π¨ Rich Visualizations: Heatmaps, equity curves, and performance comparisons
- π Excel Reports: Detailed performance reports with multiple analysis sheets
The system follows a modular, layered architecture optimized for performance and extensibility:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β USER INTERFACE β
β Command Line / Configuration β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β DATA PREPROCESSING β
β CSV β Parquet Conversion (One-time) β
β DTE Calculation & Data Validation β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β BACKTEST ENGINE (C++) β
β βββββββββββββββββ ββββββββββββββββββ ββββββββββββββββββ β
β β Indicators β β Strategies β β Trade Logger β β
β β - EMA β β - Crossover β β - Parquet β β
β β - SMA β β - Supertrend β β - Buffering β β
β β - Supertrendβ β - Custom β β - Thread-safe β β
β β - Keltner β β β β β β
β βββββββββββββββββ ββββββββββββββββββ ββββββββββββββββββ β
β β β
β βββββββββββββββββββββββββββ β
β β Multithreaded Execution β β
β β - Parameter Grid β β
β β - DTE Filtering β β
β β - Position Management β β
β βββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β ANALYTICS LAYER (Python) β
β ββββββββββββββββββββ ββββββββββββββββββββββββββββββββ β
β β Performance β β Visualization β β
β β - Sharpe Ratio β β - Equity Curves β β
β β - Sortino Ratio β β - Performance Heatmaps β β
β β - Calmar Ratio β β - DTE Analysis β β
β β - Drawdown β β - Metric Comparisons β β
β β - Expectancy β β β β
β ββββββββββββββββββββ ββββββββββββββββββββββββββββββββ β
β β β
β βββββββββββββββββββββββ β
β β Excel Reports β β
β β PNG Charts β β
β βββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- Strategy Pattern: Modular strategy implementation allowing easy addition of new strategies
- Factory Pattern: Dynamic strategy creation based on configuration
- Template Method: Base indicator class with common calculation patterns
- Observer Pattern: Trade logging with thread-safe observers
- Builder Pattern: Complex parameter combination generation
All indicators inherit from IndicatorBase and implement:
calculate(): Compute indicator values for all barsgetValue(): Retrieve indicator value at specific indexisReady(): Check if indicator has enough data
Available Indicators:
- EMA (Exponential Moving Average): Trend-following indicator with faster response
- SMA (Simple Moving Average): Basic trend-following indicator
- ATR (Average True Range): Volatility measurement
- Supertrend: Trend-following indicator combining price and ATR
- Keltner Channel: Volatility-based channel indicator
Strategies implement signal generation logic:
EMA Crossover Strategy:
- Parameters: Fast EMA period, Slow EMA period
- Logic: Long when fast crosses above slow, Short when fast crosses below slow
Supertrend Strategy:
- Parameters: ATR period, Multiplier
- Logic: Follow trend direction indicated by Supertrend
Core features:
- Position Management: Automatic entry/exit with capital allocation
- DTE Filtering: Test specific days-to-expiry
- Time Filtering: Intraday trading hours (09:15 - 15:25)
- Square-off Logic: End-of-day position closure
- Performance Calculation: Real-time metric computation
DataLoader (src/data_loader.cpp):
- CSV to Parquet conversion (one-time, 10-50x faster subsequent loads)
- DTE calculation from expiry dates
- Memory-efficient data structures
TradeLogger (src/trade_logger.cpp):
- Thread-safe trade recording
- Batch Parquet writes for efficiency
- Minimal memory footprint
PerformanceAnalyzer (performance_analyzer.py):
- Comprehensive metric calculation
- Risk-adjusted returns (Sharpe, Sortino, Calmar)
- Drawdown analysis with duration
- Trade statistics
ResultsAnalyzer (analyze_results.py):
- Multi-strategy comparison
- DTE-based analysis
- Visualization generation
- Excel report creation
System Requirements:
- Linux/Unix-based system
- GCC 7+ or Clang 5+ (C++17 support)
- CMake 3.15+
- Python 3.8+
Required Libraries:
# Ubuntu/Debian
sudo apt-get update
sudo apt-get install -y \
build-essential \
cmake \
libarrow-dev \
libparquet-dev \
python3-pip
# CentOS/RHEL
sudo yum install -y \
gcc-c++ \
cmake \
arrow-devel \
parquet-devel \
python3-pip- Clone/Navigate to project directory:
cd "Backtest Engine"- Install Python dependencies:
pip3 install -r requirements.txt- Build C++ engine:
mkdir build
cd build
cmake ..
make -j$(nproc)
cd ..- Verify installation:
./build/backtest_engine --help- Convert CSV to Parquet (one-time):
./build/backtest_engine --convert-csv- Run parameter optimization:
./build/backtest_engine --strategy EMA_Crossover --optimize- Analyze results:
python3 analytics/analyze_results.py./build/backtest_engine [options]
Options:
--convert-csv Convert market_data.csv to Parquet format
--strategy NAME Strategy name (EMA_Crossover, Supertrend)
--params P1,P2,... Strategy parameters (comma-separated)
--dte N DTE filter (1-5, or -1 for all)
--optimize Run parameter optimization
--help Show help messageSingle Strategy Test:
# Test EMA Crossover with fast=10, slow=30 on DTE=2
./build/backtest_engine --strategy EMA_Crossover --params 10,30 --dte 2Full Optimization:
# Test all Supertrend combinations
./build/backtest_engine --strategy Supertrend --optimizeBoth Strategies:
# Optimize both strategies across all parameters
./build/backtest_engine --optimizeRequired columns (tab-separated):
timestamp open high low close date weekly_expiry_date DT
2023-08-25 09:15:00+05:30 19297.4 19301.15 19261.7 19269.25 25-08-2023 31-08-2023 DT-4
Trade Logs (output/trades/*.parquet):
- Entry/Exit timestamps and prices
- PnL and percentage returns
- Direction (LONG/SHORT)
- DTE and strategy parameters
Analysis Results (output/analysis/):
backtest_results.xlsx: Comprehensive Excel report*_heatmap.png: Performance heatmapstop_equity_curves.png: Equity curve visualizationmetric_comparisons.png: Side-by-side metric comparisondte_analysis.png: DTE-based performance analysis
- Total Trades: Number of completed trades
- Win Rate: Percentage of winning trades
- Profit Factor: Gross profit / Gross loss
- Expectancy: Average expected profit per trade
- Max Win/Loss: Largest winning/losing trade
- Sharpe Ratio: Risk-adjusted return (annualized)
- Sortino Ratio: Downside risk-adjusted return
- Calmar Ratio: Return / Maximum drawdown
- Maximum Drawdown: Largest peak-to-trough decline
- Consecutive Wins/Losses: Longest winning/losing streaks
- Average Trade Duration: Time in position (minutes)
- Recovery Duration: Time to recover from max drawdown
EMA Crossover:
- Fast Period: 5, 10, 15
- Slow Period: 20, 30, 40, 50
- Total combinations: 3 Γ 4 Γ 5 (DTE) = 60
Supertrend:
- Period: 7, 10, 14
- Multiplier: 1.5, 2.0, 2.5, 3.0
- Total combinations: 3 Γ 4 Γ 5 (DTE) = 60
- DTE 1: Expiry day trading
- DTE 2: One day before expiry
- DTE 3: Two days before expiry
- DTE 4: Three days before expiry
- DTE 5: Four+ days before expiry
- Entry Window: 09:15 - 15:25 IST
- Auto Square-off: 15:25 IST
- Always convert CSV to Parquet first - 10-50x faster loading
- Use multithreading for parameter optimization
- Limit parameter combinations to most relevant ranges
- Monitor memory usage on large datasets
- Start simple - Test basic logic first
- Validate indicators - Ensure calculations are correct
- Use proper DTE filtering - Options behavior varies by expiry
- Consider transaction costs - Add slippage/commissions for realism
- Don't overfit - Favor consistent performance over peak returns
- Check multiple metrics - Return alone isn't enough
- Analyze by DTE - Different DTEs may require different parameters
- Validate on out-of-sample data - Reserve data for final validation
Error: arrow/parquet not found
# Install Arrow/Parquet development libraries
sudo apt-get install libarrow-dev libparquet-devCMake version too old
# Install newer CMake
pip3 install cmake --upgradeSegmentation fault
- Check data file exists and is valid
- Ensure Parquet file was created successfully
- Verify strategy parameters are valid
No trades generated
- Check DTE filter matches data
- Verify indicator periods are smaller than data size
- Ensure trading hours overlap with data timestamps
Python import errors
pip3 install -r requirements.txt --upgrade