Skip to content

Commit

Permalink
Added end-to-end integration test for the BacktestTradingSession. Che…
Browse files Browse the repository at this point in the history
…cks for correct transaction history, rebalance orders and final market values.
  • Loading branch information
mhallsmoore committed Nov 19, 2019
1 parent c17c2cb commit fce3df9
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 3 deletions.
7 changes: 4 additions & 3 deletions qstrader/trading/backtest.py
Expand Up @@ -289,7 +289,7 @@ def output_holdings(self):
self.broker.portfolios[self.portfolio_id].pos_handler.positions
)

def run(self):
def run(self, results=True):
"""
Execute the simulation engine by iterating over all
simulation events, rebalancing the quant trading
Expand All @@ -316,5 +316,6 @@ def run(self):

# At the end of the simulation output the
# holdings and plot the tearsheet
self.output_holdings()
self.statistics.plot_results()
if results:
self.output_holdings()
self.statistics.plot_results()
2 changes: 2 additions & 0 deletions requirements/base.txt
@@ -1,2 +1,4 @@
matplotlib>=3.1.1
numpy>=1.17.1
pandas>=0.25.1
seaborn>=0.9.0
8 changes: 8 additions & 0 deletions tests/integration/trading/conftest.py
@@ -0,0 +1,8 @@
import os

import pytest


@pytest.fixture
def etf_filepath():
return os.path.join(os.path.dirname(os.path.abspath(__file__)), 'fixtures')
32 changes: 32 additions & 0 deletions tests/integration/trading/fixtures/ABC.csv
@@ -0,0 +1,32 @@
Date,Open,Close,Adj Close
2019-01-01,125.39488969413745,125.33363233868549,125.33363233868549
2019-01-02,125.89917786834457,127.1721912191578,127.1721912191578
2019-01-03,127.03269234354691,126.89335971731924,126.89335971731924
2019-01-04,128.2221622649511,128.898717689565,128.898717689565
2019-01-05,128.56506784434282,129.05901039753346,129.05901039753346
2019-01-06,128.72989650195026,128.39973675354403,128.39973675354403
2019-01-07,128.6472480185127,127.14321774077997,127.14321774077997
2019-01-08,125.80715956180252,125.40757960383644,125.40757960383644
2019-01-09,124.65213403014167,124.94976128818058,124.94976128818058
2019-01-10,124.27975739478052,123.21814723382533,123.21814723382533
2019-01-11,124.41870894923085,124.28884175220395,124.28884175220395
2019-01-12,124.3905701266007,123.31826808213218,123.31826808213218
2019-01-13,122.94057017855258,123.07510425632478,123.07510425632478
2019-01-14,122.22642906451051,122.56608201304746,122.56608201304746
2019-01-15,122.14704603397041,121.96848618508807,121.96848618508807
2019-01-16,121.55066902505783,123.0366806223872,123.0366806223872
2019-01-17,123.074044758589,122.29779796065557,122.29779796065557
2019-01-18,122.98612535041893,122.08390158985783,122.08390158985783
2019-01-19,122.29353209546302,120.82818553641833,120.82818553641833
2019-01-20,119.86006492214325,120.05672639455736,120.05672639455736
2019-01-21,120.66799878776659,120.84642163141329,120.84642163141329
2019-01-22,120.80473402060616,120.62092871794115,120.62092871794115
2019-01-23,119.54029698162026,119.04146249233915,119.04146249233915
2019-01-24,118.7399896732252,119.5862919308,119.5862919308
2019-01-25,119.89418253725772,118.60558418524995,118.60558418524995
2019-01-26,118.8962006679204,118.65200942931968,118.65200942931968
2019-01-27,118.18909050165004,118.69525147026332,118.69525147026332
2019-01-28,119.5214070867766,120.27712713948456,120.27712713948456
2019-01-29,119.6844601374134,119.4962063012826,119.4962063012826
2019-01-30,119.79446631527424,120.58580275586421,120.58580275586421
2019-01-31,120.26626267876608,120.17133895023754,120.17133895023754
32 changes: 32 additions & 0 deletions tests/integration/trading/fixtures/DEF.csv
@@ -0,0 +1,32 @@
Date,Open,Close,Adj Close
2019-01-01,247.37936936736824,244.7660246428395,244.7660246428395
2019-01-02,246.85858308644677,250.26175730213362,250.26175730213362
2019-01-03,250.28369833170782,252.88309169825106,252.88309169825106
2019-01-04,253.9520439736528,252.59167186214754,252.59167186214754
2019-01-05,253.65881140916363,257.60141323702385,257.60141323702385
2019-01-06,257.7128041259375,261.78475332104443,261.78475332104443
2019-01-07,255.53083374870585,257.7384412686895,257.7384412686895
2019-01-08,258.15184721322674,257.61687087003514,257.61687087003514
2019-01-09,258.0416671434598,253.39841810004148,253.39841810004148
2019-01-10,253.0644536818734,254.1232232121341,254.1232232121341
2019-01-11,257.92524646745613,256.85374501816807,256.85374501816807
2019-01-12,255.08057960118802,254.06085339825603,254.06085339825603
2019-01-13,256.4840804329767,257.48758906092576,257.48758906092576
2019-01-14,256.38984436660866,257.84575530142945,257.84575530142945
2019-01-15,258.28400876096674,260.8797848994226,260.8797848994226
2019-01-16,259.3416255503608,258.7335559395058,258.7335559395058
2019-01-17,257.9685097696293,254.59424812784954,254.59424812784954
2019-01-18,255.51093524007868,256.34529073997334,256.34529073997334
2019-01-19,256.55616279980853,256.18163889572105,256.18163889572105
2019-01-20,252.94671795889766,252.1302402679711,252.1302402679711
2019-01-21,251.50301737992626,249.7815794913505,249.7815794913505
2019-01-22,249.5911481138543,250.74746707932877,250.74746707932877
2019-01-23,255.49065398540205,256.11389568676054,256.11389568676054
2019-01-24,256.9416422270286,256.9582071506607,256.9582071506607
2019-01-25,252.49986272511953,252.63145464771154,252.63145464771154
2019-01-26,252.97204400218808,259.177966418831,259.177966418831
2019-01-27,258.90372651929687,259.84936226235743,259.84936226235743
2019-01-28,259.96448429902085,257.28564297854126,257.28564297854126
2019-01-29,260.30288172848395,262.3767945115066,262.3767945115066
2019-01-30,264.56574136855073,262.4869617875856,262.4869617875856
2019-01-31,266.22361304141003,262.89573981277454,262.89573981277454
12 changes: 12 additions & 0 deletions tests/integration/trading/fixtures/history.dat
@@ -0,0 +1,12 @@
date,type,description,debit,credit,balance
,subscription,SUBSCRIPTION,0.00,1000000.0,1000000.0
,asset_transaction,LONG 4482 EQ:ABC 127.03 03/01/2019,569360.53,0.0,430639.47
,asset_transaction,LONG 1518 EQ:DEF 250.28 03/01/2019,379930.65,0.0,50708.82
,asset_transaction,SHORT -26.0 EQ:DEF 253.06 10/01/2019,0.0,6579.68,57288.49
,asset_transaction,LONG 58.0 EQ:ABC 124.28 10/01/2019,7208.23,0.0,50080.27
,asset_transaction,SHORT -32.0 EQ:DEF 257.97 17/01/2019,0.0,8254.99,58335.26
,asset_transaction,LONG 68.0 EQ:ABC 123.07 17/01/2019,8369.04,0.0,49966.23
,asset_transaction,SHORT -18.0 EQ:DEF 256.94 24/01/2019,0.0,4624.95,54591.18
,asset_transaction,LONG 48.0 EQ:ABC 118.74 24/01/2019,5699.52,0.0,48891.66
,asset_transaction,SHORT -11.0 EQ:DEF 266.22 31/01/2019,0.0,2928.46,51820.12
,asset_transaction,LONG 18.0 EQ:ABC 120.27 31/01/2019,2164.79,0.0,49655.32
60 changes: 60 additions & 0 deletions tests/integration/trading/test_backtest_e2e.py
@@ -0,0 +1,60 @@
import os

import pandas as pd
import pytz

from qstrader.alpha_model.fixed_signals import FixedSignalsAlphaModel
from qstrader.trading.backtest import BacktestTradingSession


def test_backtest_sixty_forty_no_corp_actions(etf_filepath):
"""
Ensures that a full end-to-end weekly rebalanced backtested
trading session with fixed proportion weights produces the
correct rebalance orders as well as correctly calculated
market values after a single month's worth of daily
backtesting.
"""
os.environ['QSTRADER_CSV_DATA_DIR'] = etf_filepath

assets = ['EQ:ABC', 'EQ:DEF']
signal_weights = {'EQ:ABC': 0.6, 'EQ:DEF': 0.4}
alpha_model = FixedSignalsAlphaModel(signal_weights)

start_dt = pd.Timestamp('2019-01-01 00:00:00', tz=pytz.UTC)
end_dt = pd.Timestamp('2019-01-31 23:59:00', tz=pytz.UTC)

backtest = BacktestTradingSession(
start_dt,
end_dt,
assets,
alpha_model,
rebalance='weekly',
)
backtest.run(results=False)

portfolio = backtest.broker.portfolios['000001']

portfolio_dict = portfolio.portfolio_to_dict()
expected_dict = {
'EQ:ABC': {
'book_cost': 592802.1002887912,
'gain': -31121.262035380933,
'market_value': 561680.8382534103,
'perc_gain': -5.249856911812527,
'quantity': 4674.0
},
'EQ:DEF': {
'book_cost': 358155.9723126739,
'gain': 18047.83135940641,
'market_value': 376203.80367208034,
'perc_gain': 5.03909825735098,
'quantity': 1431.0
}
}

history_df = portfolio.history_to_df().reset_index()
expected_df = pd.read_csv(os.path.join(etf_filepath, 'history.dat'))

pd.testing.assert_frame_equal(history_df, expected_df)
assert portfolio_dict == expected_dict

0 comments on commit fce3df9

Please sign in to comment.