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.5.tar.gz (21.5 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.5-py3-none-any.whl (20.8 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: backspacealpha-0.2.5.tar.gz
  • Upload date:
  • Size: 21.5 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.5.tar.gz
Algorithm Hash digest
SHA256 1015a4d0dfc2a250bc71e0cd16b5b951ffd10b517f69b61b93516a2d0230808b
MD5 b5c4c0205b9044a468d92a76acabc75b
BLAKE2b-256 2c01dc19155a900d64496eb4e18a6492c6158a35e6f9e507f234c80f2b8cfa50

See more details on using hashes here.

File details

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

File metadata

  • Download URL: backspacealpha-0.2.5-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.5-py3-none-any.whl
Algorithm Hash digest
SHA256 f227efc695acd228e6d0fb880099a74e636ab5c91533d3930314e5f7879de53a
MD5 d36c92863ada0636e705698a62c0766d
BLAKE2b-256 384cef00edfca7e48e41078aa77d4eafecd8af21c0a3202d49dbc02df8385e9a

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