Skip to main content

A simple backtesting framework to quickly and easily optimise strategies

Project description

backspaceAlpha

License PyPI

A simple, customisable, easy-to-use backtesting framework with example strategies to quickly and effectively track a strategies' impact and improve it

Contents:

  1. Overview
  2. Installation
  3. Usage
  4. Documentation
    1. Framework
      1. backtest.py
      2. broker.py
      3. loader.py
      4. strategy.py
    2. Functions
  5. Attribution

1. Overview

backspaceAlpha is a backtesting framework, that aims to improve customisability and simplify the backtesting process by implementing functionality in the same way as real trading. It does this by having a small number of incredibly versatile functions/classes and splitting the functionality between 4 main modules:

  • backtester - Handles all things related to running the backtest and displaying its resuls
  • broker - Operates in the same way as a real broker, by maintaining an order book and handling order conflicts
  • loader - Operates in the same way as a market data provider by aggregating data from exchanges and sending them to brokers in an intuitive format
  • strategy - Handles all things related to what a strategy may entail

It is aimed at everyone from trading beginners to industry veterans and provides many useful examples for a range of strategies, to help users understand the framework. It is designed to be intuitive and allow for new users to start experimenting with functions and customisability quickly

2. Installation

This project is available on PyPi at the following link and can be installed with:

$ pip install backspaceAlpha

3. Usage

The easiest way to get started with backspaceAlpha is to import strategies from the example folder and run backtests on them. This can be done as demonstrated by the files in this folder or as shown below:

from backspaceAlpha.framework import BackTest
from backspaceAlpha.examples import MeanReversionStrategy

#Run the backtest on the strategy
backtest = BackTest(MeanReversionStrategy(), ('2000-01-01', '2025-10-19'), 10000)

#Graphs the equity of the strategy over time
backtest.graph_variable("My Graph 1", {
    "strategy": "MeanReversionStrategy",
    "variable": "Equity"
})
#Graphs the SPY stock over time and order markers
backtest.graph_variable("My Graph 2", {
    "strategy": "MeanReversionStrategy",
    "variable": ["--ticker(SPY)", "--order(SPY)()"]
})

#Show results of the backtest
backtest.show_results()

In this example, we use a simple mean reversion strategy which is predefined in the example folder to run on SPY. We choose to run the backtest over 25 years with a starting capital of $10,000. After the backtest completes, we then graph:

  • the equity of the strategy over time
  • the SPY alongside our order markers

We then show the results of the backtest which will include metrics such as profit, return, max drawdown, sharpe ratio etc.

4. Documentation

In this section, we go in depth into the workings of the backtester and how each component of each script works. We split it by folder and within each folder, we explore the functions of each script

4.1 - Framework

This section includes scripts with the main functionality of the backtester. It is split into different scripts in the same way discussed in the overview)

4.1.1 - backtest.py

This module can be imported into the project using:

from backspaceAlpha.framework import *

This script defines two main classes that are both used to run the backtest effectively. It also handles the versatile graphing functions which allow for practically any variable to be plotted and any graph to be created. It brings together all other classes.

Imports MultiDataFeed, Broker, Strategy, matplotlib, numpy, tqdm, datetime

Classes BaseBackTest, BackTest


BaseBackTest

The internal engine that actually runs the backtest. It handles a single strategy and only is capable of running one backtest. It simulates the whole trading environment and each tick realistically before outputting logs.

Constructor

Initialises the backtest and all classes that are needed to make it run. Also intialises the strategy.

BaseBackTest(strategy, time_frame, start=10000, source="YAHOO", interval="1D", verbose=False, hedging=False)
  • strategy - Strategy: This is the strategy that the backtest will run on
  • time_frame - (YYYY-MM-DD, YYYY-MM-DD): This is the time frame on which the backtest will run on where the first element of the tuple is the start date, and the last element, the end date
  • start - (optional) float: This is the amount of money the strategy will start with
  • source - (optional) str: This is the source from where the data is pulled (only current working option is YAHOO)
  • interval - (optional) str: This is how often the strategy is to be run. Can choose from 1D, 1W and 1M for daily, weekly and monthly respectively
  • verbose - (optional) bool: Turning this on causes the broker to log updates to console every tick. Useful for debugging strategies and shows all orders and how they were handled that tick
  • hedging - (optional) bool: Turning this on causes the broker to simulate a broker which allows hedging. This means certain order conflicts are handled differently (and generally more leniently)

run

Heart of the backtest and run it with the basic loop: Updates data feed by 1 tick, sends new data to broker first, then sends same data to strategy, allows broker to respond to new orders from strategy

run(pbar = None)
  • pbar - (optional) tqdm: If the current backtest is part of a series of backtests that is being run on different strategies, the progress of the backtest is updated on the progress bar given in the parameter. This allows for the progress bar to show the progress of a backtest on multiple strategies more effectively

BackTest

This is the main class to be used when running any backtest. It makes use of the BaseBackTest class to run multiple strategies simultaneously and provides additional functions for showing results.

Constructor

Initialises the backtest, the loading bar and all classes that are needed to make it run. Also intialises the strategy. Once everything is intialised, it proceeds to run the backtest on all available strategies

BackTest(strategy, time_frame, start=10000, source="YAHOO", interval="1D", verbose=False, hedging=False)
  • strategy - Strategy: This is the strategy that the backtest will run on
  • time_frame - (YYYY-MM-DD, YYYY-MM-DD): This is the time frame on which the backtest will run on where the first element of the tuple is the start date, and the last element, the end date
  • start - (optional) float: This is the amount of money the strategy will start with
  • source - (optional) str: This is the source from where the data is pulled (only current working option is YAHOO)
  • interval - (optional) str: This is how often the strategy is to be run. Can choose from 1D, 1W and 1M for daily, weekly and monthly respectively
  • verbose - (optional) bool: Turning this on causes the broker to log updates to console every tick. Useful for debugging strategies and shows all orders and how they were handled that tick
  • hedging - (optional) bool: Turning this on causes the broker to simulate a broker which allows hedging. This means certain order conflicts are handled differently (and generally more leniently)

graph_variable

This versatile function is used to graph any variable created, used or accessed in the backtest against time using matplotlib. There are many built in variables that can be used but users can also create their own variables to graph too using strategy.log().

graph_variable(title, variable_names):
  • title - str: This will be the title of the graph being made
  • variable_names - [{strategy: [Strategy, ...], variable: [str, ...]}, ...]: This is a powerful parameter that allows you to quickly log any variable from any strategy. It can be used with or without the use of arrays as the numerous valid examples below:
#Single strategy with single variable
graph_variable("1", {strategy: "MyStrategy", variable: "Equity"})

#Single strategy with multiple variables
graph_variable("2", {strategy: "MyStrategy", variable: ["Equity", "Risk-Free Rate"]})

#Multiple strategies with different variables
graph_variable("3", [
    {strategy: "MyStrategy1", variable: "Equity"},
    {strategy: "MyStrategy2", variable: "Portfolio"}
])

#Multiple strategies with multiple different variables
graph_variable("4", [
    {strategy: "MyStrategy1", variable: ["Equity", "Risk-Free Rate"]},
    {strategy: "MyStrategy2", variable: "Portfolio"}
])

#Multiple strategies with the same single variable
graph_variable("5", {strategy: ["MyStrategy1", "MyStrategy2"], variable: "Equity"})

#Combination
graph_variable("Combination", [
    {strategy: ["MyStrategy1", "MyStrategy2"], variable: "Equity"},
    {strategy: "MyStrategy1", variable: "Portfolio"},
])

Hopefully the above demonstrates how powerful this function can be and provides a good understanding of how to format parameters for the function. For each {strategy: "", variable: ""} object, there are restrictions on what values they can take.

  • strategy - The given strategy name(s) has to be of a strategy present in the backtest object that graph_variable is being called from
  • variable - The given variable name(s) has to be present in all the strategies in the strategy part of the object. There are some built in values (case-sensitive) that can be used for this
    • Equity - Variable containing the equity of the portolfio
    • Portfolio - Variable containing the value of open positions
    • Risk-Free Rate - Variable containing the RFR on that day based on treasury bills
    • --ticker() - Special variable that allows you to plot the price of a ticker. The only argument is the ticker code (eg. --ticker(AAPL))
    • --order()() - Special variable that allows you to plot the orders. The first argument is which ticker you want to log the orders for and the second argument, is what variable, you want the order markers to be plotted on. (eg. --order(SPY)(Equity)). There are 4 main actions represrented by this function:
      • Buy: Represented by a green upwards arrow when asset is bought
      • Sell: Represented by a red downwards arrow when asset is sold
      • Long: Represented by a green upwards arrow when the long position is initiated. A dashed line starts from this arrow and continues until the position is closed. Another arrow is positioned at the close time and points in the direction of the stock. It will be green if the position made money, and red if it didn't
      • Short: Represented by a red downwards arrow when the short position is initiated. A dashed line starts from this arrow and continues until the position is closed. Another arrow is positioned at the close time and points in the direction of the stock. It will be green if the position made money, and red if it didn't.

4.1.2 - broker.py

This module can be imported into the project using:

from backspaceAlpha.broker import *

This script defines the broker class which acts like a real-life broker. It takes in data from a Loader (exchange) and uses it to set prices for assets. Strategies can then interact with it by calling its numerous functions. It then updates its order books and can keep track of any open positions. It also allows strategies to use stop-losses and take-profits

Imports numpy

Classes Broker


Broker

This class is used to initiate the broker and gives access to all its features. It is automatically loaded in with strategies so that strategies can access it and its features using self.broker

Constructor

Used to initialise the broker and determine what kind of broker it is. It allows for hedging and for alerts in the terminal everytime orders are handled. Also sets up the order books and prepares the logs for incoming data. Keeps track of cash as well and intitliases it with intial cash value

Broker(portfolio, initial, hedging = False, verbose = True)
  • portfolio - [str]: A list of tickers, whose price data needs to be tracked. This variable is normally handled and formatted by the Strategy class
  • intitial - float: The initial value of the portfolio in cash
  • hedging - (optional) bool: Automatically set to False. When enabled, allows for certain order combinations to be passed through like longing and shorting or other conflicting orders on the same stock.
  • verbose - (optional) bool: Automatically

4.1.3 - loader.py

4.1.4 - strategy.py

4.2 - Functions

This section includes a certain type of script, called functions, that can be used with graph_function. These are used for more complex graphs that require access to the whole log.

5. Attribution

This software is licensed under the BackspaceAlpha License v1.0.
Use of this software requires attribution Modifications must be submitted via the official GitHub repository.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

backspacealpha-0.2.4.tar.gz (21.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

backspacealpha-0.2.4-py3-none-any.whl (20.8 kB view details)

Uploaded Python 3

File details

Details for the file backspacealpha-0.2.4.tar.gz.

File metadata

  • Download URL: backspacealpha-0.2.4.tar.gz
  • Upload date:
  • Size: 21.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.14

File hashes

Hashes for backspacealpha-0.2.4.tar.gz
Algorithm Hash digest
SHA256 1a066b6364541a9474a75a6334416c936f3dfe6ee9e1224e0d0caf3a13c2d187
MD5 68990c8d415b277a537c793c5fa0f5c4
BLAKE2b-256 1e1290484742d5cd2f3c618f6203614a2f59cc31c118313ede8ff216fad11282

See more details on using hashes here.

File details

Details for the file backspacealpha-0.2.4-py3-none-any.whl.

File metadata

  • Download URL: backspacealpha-0.2.4-py3-none-any.whl
  • Upload date:
  • Size: 20.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.14

File hashes

Hashes for backspacealpha-0.2.4-py3-none-any.whl
Algorithm Hash digest
SHA256 86a6af1c306bd2b80f644b5f128603c68c8fab1182e82d4dffac571e18ab80d9
MD5 57738dffea1c3d704c2af9000ac3681e
BLAKE2b-256 c81e077c9303fb0e2f685fc5aed8b214f83b09877631056ea9e7bb332c15b51c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page