Skip to content

In this repository, an event-driven backtester is implemented based on QuantStart articles. The backtester is programmed in Python featuring numerous improvements, in terms of coding structure, data handling, and simple trading strategies.

Notifications You must be signed in to change notification settings

DavidCico/Enhanced-Event-Driven-Backtester

Repository files navigation

Enhanced-QuantStart-Backtester-With-Some-Trading-Strategies

This repository consists of an event-driven backtester, based on a series of articles written by Michael Halls-Moore from the QuantStart website.

The code has been rewritten by hand, modified and improved for most parts. The author gave the direction on how to implement a backtester, but some additional work was necessary to make the code function properly.

Some additions have also been added in terms of data handling and strategies implemented:

  • YahooDataHandler that allows to get data directly from Yahoo Finance website and update the latest "bar" in a live manner.
  • HistoricMySQLDataHandler designed to read a MySQL database for each requested symbol from disk, and provides an interface to obtain the "latest" bar in a manner identical to a live trading interface.
  • MovingAverageCrossOverStrat to carry out a basic Moving Average Crossover strategy with a short/long simple weighted moving average.
  • ETFDailyForecastStrategy to carry out a forecast prediction of the price of an ETF on next day, and enter/exit trades based on that prediction.
  • OLSMRStratedy to generate signals on a trading pair (should follow a mean reversion pattern to be tested), using rolling OLS method to find the best hedging ratio between 2 assets timeseries. Position signals are then generated based on exceeding z_scores, whether we are currently having positions in the market, or needing to exit.

Getting Started

These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. See deployment for notes on how to deploy the project on a live system.

Prerequisites

You need Python 3.x to run the following code. You can have multiple Python versions (2.x and 3.x) installed on the same system without problems. Python needs to be first installed then SciPy and pymysql as there are dependencies on packages.

In Ubuntu, Mint and Debian you can install Python 3 like this:

sudo apt-get install python3 python3-pip

Alongside Python, the SciPy packages are also required. In Ubuntu and Debian, the SciPy ecosystem can be installed by:

sudo apt-get install python-numpy python-scipy python-matplotlib ipython ipython-notebook python-pandas python-sympy python-nose

The latest release of Scikit-Learn machine learning package, which can be installed with pip:

pip install -U scikit-learn

The pymysql package for connecting to MySQL databases using Python, which can be installed with pip:

pip install pymysql

For getting the data of price timeseries from Yahoo Finance, we use the yfinance package that can be installed using the pip package manager:

pip install yfinance

For other Linux flavors, OS X and Windows, packages are available at:

http://www.python.org/getit/ for Python
https://www.scipy.org/install.html for the SciPy ecosystem
https://scikit-learn.org/stable/install.html for Scikit-Learn
https://pypi.org/project/yfinance/ for the yfinance module

File descriptions

  • 'BacktesterLoop.py' in which the Backtest class hierarchy encapsulates the other classes, to carry out a nested while-loop event-driven system in order to handle the events placed on the Event Queue object.
  • 'DataHandler.py' which defines a class that gives all subclasses an interface for providing market data to the remaining components within the system. Data can be obtained directly from the web, a database or be read from CSV files for instance.
  • 'Events.py' with four types of events (market, signal, order and fill), which allow communication between the above components via an event queue, are implemented.
  • 'Execution.py' to simulate the order handling mechanism and ultimately tie into a brokerage or other means of market connectivity.
  • 'Main.py' which is the main Python program, englobing all the different subroutines, and where the different parameters to initialize the backtesting simulations are specified.
  • 'Performance.py' in which performance assessment criteria are implemented such as the Sharpe ratio and drawdowns.
  • 'PlotPerformance.py' to plot figures based on the equity curve obtained after backtesting.
  • 'Portfolio.py' that keeps track of the positions within a portfolio, and generates orders of a fixed quantity of stock based on signals.
  • 'RiskManagement.py' which would be the class for implementing risk management measures, as its name suggests such as VaR calculation, Kelly criterion for position sizing, etc.
  • 'Strategy.py' to generate a signal event from a particular strategy to communicate to the portfolio.
  • In the 'Strategies' directory, different trading strategies are implemented to be used for backtesting:
    • 'Buy_And_Hold_Strat.py' in which a simple buy and hold strategy is coded.
    • 'MAC_Strat.py' to generate signals from simple moving averages.
    • 'CreateLaggedSeries.py' to create lagged timeseries, to be used in the ETF forecast strategy (helper function).
    • 'ETF_Forecast.py' to generate signals on the current from previous days prices of an ETF.
    • 'OLS_MR_Strategy.py' to generate signals on a trading pair following a mean reversion pattern.

Running the program

The different ".py" files need to be placed in the same folder for the main script to be run. The code is then ready to be used, and just requires running the following command:

python Main.py

The code is well commented and easy to understand. The different parameters calculated and used for the simulations are:

if __name__ == "__main__":
    data_dir = Path.cwd() / 'DataDir'  # For reading from CSV files
    symbol_list = ['^OEX']
    initial_capital = 100000.0
    start_date = datetime(2016, 1, 1, 0, 0, 0)
    end_date = datetime(2021, 1, 1, 0, 0, 0)
    interval = '1d'
    heartbeat = 0.0  # necessary for live feed

    backtest = Backtest(data_dir,  # data directory of CSV files
                        symbol_list,  # list of symbols
                        initial_capital,  # initial capital available for trading
                        heartbeat,  # heartbeat to count time in real live trading simulation
                        start_date,  # starting time of the trading
                        end_date,  # ending time of the trading
                        interval,  # interval of the data
                        YahooDataHandler,  # data management method
                        SimpleSimulatedExecutionHandler,  # Type of execution in relationship to broker
                        Portfolio,  # portfolio management method
                        ETFDailyForecastStrategy)  # strategy chosen

    backtest.simulate_trading()

Running the backtester will generate a CSV file "equity.csv", with PnL curve, returns, drawdowns, etc. By running the following Python script, a plot can be generated to assess the strategy:

python PlotPerformance.py

The picture below shows an example with the parameters highlighted above.

Example_plot

Contributing

Please read CONTRIBUTING.md for details on our code of conduct, and the process for submitting pull requests to us.

Versioning

We use SemVer for versioning. For the versions available, see the tags on this repository.

Authors

See also the list of contributors who participated in this project.

About

In this repository, an event-driven backtester is implemented based on QuantStart articles. The backtester is programmed in Python featuring numerous improvements, in terms of coding structure, data handling, and simple trading strategies.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages