Skip to content

Backtesting engine to simulate automated trading strategies using historical market data 🏦 Users are able to queue simulations, running them in parallel over multiple CPU cores for efficiency at scale.

License

Notifications You must be signed in to change notification settings

TomAston1996/backtesting-engine

Repository files navigation

Contributors Forks Stargazers Issues MIT License LinkedIn

πŸ“ˆ Quant Trading Backtesting Engine

A simple, extensible Python backtesting engine for evaluating trading strategies on historical market data.

Screenshots from the output can be seen below:

Example backtester plots

πŸ“‘ Table of Contents

πŸ§‘β€πŸ’» Tech Stack

Python Pandas NumPy Plotly

πŸ“– Background: What is Backtesting?

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

πŸ“Š Strategies Currently Supported

  • Buy & Hold
  • Mean Reversion
  • Momentum
  • SMA Crossover

πŸ“ Configuration File

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": {...}
        }
    ]
}

πŸ“ Results

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_hold plot comparing strategy performance against buy-and-hold
  • daily_returns plot showing daily portfolio returns
  • drawdown plot highlighting peak-to-trough losses
  • performance_metrics.txt summarizing key performance statistics
  • result.csv containing 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.csv

πŸ“¦ Getting Started

This project uses uv for dependency management and virtual environments. Please ensure uv is installed before proceeding.

πŸ”§ Installation

Set up your virtual environment and install dependencies:

πŸ’» Windows, MacOS, or Linux

uv venv
uv sync

Or, if you're on MacOS or Linux, you can use the Makefile:

make install

βœ… Running Tests

To execute unit and integration tests

For Windows systems:

invoke test

For MacOS/Linux systems:

make test

πŸš€ Running the App Locally

To run the app (main.py) locally

For Windows systems:

invoke run

For MacOS/Linux systems:

make run

πŸ‘­πŸ» Contributing

Adding Dependencies

uv add <package>
uv sync

Adding Dev Dependencies

uv add --dev <package>
uv sync

About

Backtesting engine to simulate automated trading strategies using historical market data 🏦 Users are able to queue simulations, running them in parallel over multiple CPU cores for efficiency at scale.

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published