A simple, extensible Python backtesting engine for evaluating trading strategies on historical market data.
Screenshots from the output can be seen below:
- π§βπ» Tech Stack
- π Background: What is Backtesting?
- π Strategies Currently Supported
- π Configuration File
- π Results
- π¦ Getting Started
- ππ» Contributing
- π¬ Contact
Backtesting is the process of evaluating a trading strategy using historical price data to simulate how it would have performed in the past. It helps quantify the effectiveness, risk, and robustness of an strategy before deploying it with real capital.
By simulating trades over time, backtesting allows quants and traders to:
- Validate strategy logic (e.g. moving average crossover, momentum, mean reversion)
- Estimate historical returns, drawdowns, and volatility
- Compare strategies using objective metrics like Sharpe Ratio or Win Rate
- Test the impact of transaction costs and slippage
- Avoid overfitting through walk-forward analysis or out-of-sample testing
- Buy & Hold
- Mean Reversion
- Momentum
- SMA Crossover
A JSON config file is the only imput required for the backtesting engine. It defines a batch of simulations under a simGroup, with global settings like outputDirLocation and author. Each simulation in the sims array includes a unique simId, a strategy with its parameters, data source details (e.g. ticker, date range), and a simConfig block for initial cash, slippage, and commission. This structure allows easy setup and parallel execution of multiple strategy runs via multiprocessing.
Simulations are defined in a single JSON file with the following structure:
{
"sim_group": "example_sim_group",
"output_dir_location": "./out",
"author": "Tom Aston",
"sims": [
{
"sim_id": "001",
"strategy": {
"type": "SMACrossover",
"fields": {
"short_window": 50,
"long_window": 100
}
},
"data": {
"source": "yfinance",
"ticker": "AAPL",
"start_date": "2020-01-02",
"end_date": "2023-01-01",
},
"sim_config": {
"initial_cash": 100000,
"slippage": 0.01,
"commission": 0.001
}
},
{
"sim_id": "002",
"strategy": {
"type": "BuyAndHold",
},
"data": {...},
"sim_config": {...}
}
]
}The simulation results are organized by simGroup and ticker symbol. Inside each ticker folder, youβll find all relevant files for each simulation named using the format <simId>_<strategy>_<artifact>.
Each simulation produces the following outputs:
strategy_vs_buy_and_holdplot comparing strategy performance against buy-and-holddaily_returnsplot showing daily portfolio returnsdrawdownplot highlighting peak-to-trough lossesperformance_metrics.txtsummarizing key performance statisticsresult.csvcontaining detailed time series data of portfolio value and positions
out/
βββ my_sim_group/
βββ AAPL/
β βββ 001_SMACrossover_strategy_vs_buy_and_hold.png
β βββ 001_SMACrossover_daily_returns.png
β βββ 001_SMACrossover_drawdown.png
β βββ 001_SMACrossover_performance_metrics.txt
β βββ 001_SMACrossover_result.csv
β βββ 002_BuyAndHold_strategy_vs_buy_and_hold.png
β βββ 002_BuyAndHold_daily_returns.png
β βββ 002_BuyAndHold_drawdown.png
β βββ 002_BuyAndHold_performance_metrics.txt
β βββ 002_BuyAndHold_result.csv
βββ MSFT/
βββ 003_SMACrossover_strategy_vs_buy_and_hold.png
βββ 003_SMACrossover_daily_returns.png
βββ 003_SMACrossover_drawdown.png
βββ 003_SMACrossover_performance_metrics.txt
βββ 003_SMACrossover_result.csv
βββ 004_BuyAndHold_strategy_vs_buy_and_hold.png
βββ 004_BuyAndHold_daily_returns.png
βββ 004_BuyAndHold_drawdown.png
βββ 004_BuyAndHold_performance_metrics.txt
βββ 004_BuyAndHold_result.csvThis project uses uv for dependency management and virtual environments. Please ensure uv is installed before proceeding.
Set up your virtual environment and install dependencies:
π» Windows, MacOS, or Linux
uv venv
uv syncOr, if you're on MacOS or Linux, you can use the Makefile:
make installTo execute unit and integration tests
For Windows systems:
invoke testFor MacOS/Linux systems:
make testTo run the app (main.py) locally
For Windows systems:
invoke runFor MacOS/Linux systems:
make runuv add <package>
uv syncuv add --dev <package>
uv sync