Data Resampling
When data is only available in a single timeframe and the analysis has to be done for a different timeframe, it’s time to do some resampling.
“Resampling” should actually be called “Upsampling” given that one goes from a source timeframe to a larger time frame (for example: days to weeks)
“Downsampling” is not yet possible.
backtrader
has built-in support for resampling by passing the original data
through a filter object which has intelligently been named: DataResampler
.
The class has two functionalities:
-
Change the timeframe
-
Compress bars
To do so the DataResampler
uses standard feed.DataBase
parameters during
construction:
-
timeframe
(default: bt.TimeFrame.Days)Destination timeframe which to be useful has to be equal or larger than the source
-
compression
(default: 1)Compress the selected value “n” to 1 bar
Let’s see an example from Daily to weekly with a handcrafted script:
$ ./data-resampling.py --timeframe weekly --compression 1
The output:
We can compare it to the original daily data:
$ ./data-resampling.py --timeframe daily --compression 1
The output:
The magic is done by executing the following steps:
-
Loading the data as usual
-
Feeding the data into a
DataResampler
with the desired-
timeframe
-
compression
-
The code in the sample (the entire script at the bottom).
# Load the Data datapath = args.dataname or '../datas/sample/2006-day-001.txt' data = btfeeds.BacktraderCSVData( dataname=datapath) # Handy dictionary for the argument timeframe conversion tframes = dict( daily=bt.TimeFrame.Days, weekly=bt.TimeFrame.Weeks, monthly=bt.TimeFrame.Months) # Resample the data data_resampled = bt.DataResampler( dataname=data, timeframe=tframes[args.timeframe], compression=args.compression) # Add the resample data instead of the original cerebro.adddata(data_resampled)
A last example in which we first change the time frame from daily to weekly and then apply a 3 to 1 compression:
$ ./data-resampling.py --timeframe weekly --compression 3
The output:
From the original 256 daily bars we end up with 18 3-week bars. The breakdown:
-
52 weeks
-
52 / 3 = 17.33 and therefore 18 bars
It doesn’t take much more. Of course intraday data can also be resampled.
The sample code for the resampling test script.
from __future__ import (absolute_import, division, print_function, unicode_literals) import argparse import backtrader as bt import backtrader.feeds as btfeeds def runstrat(): args = parse_args() # Create a cerebro entity cerebro = bt.Cerebro(stdstats=False) # Add a strategy cerebro.addstrategy(bt.Strategy) # Load the Data datapath = args.dataname or '../datas/sample/2006-day-001.txt' data = btfeeds.BacktraderCSVData( dataname=datapath) # Handy dictionary for the argument timeframe conversion tframes = dict( daily=bt.TimeFrame.Days, weekly=bt.TimeFrame.Weeks, monthly=bt.TimeFrame.Months) # Resample the data data_resampled = bt.DataResampler( dataname=data, timeframe=tframes[args.timeframe], compression=args.compression) # Add the resample data instead of the original cerebro.adddata(data_resampled) # Run over everything cerebro.run() # Plot the result cerebro.plot(style='bar') def parse_args(): parser = argparse.ArgumentParser( description='Pandas test script') parser.add_argument('--dataname', default='', required=False, help='File Data to Load') parser.add_argument('--timeframe', default='weekly', required=False, choices=['daily', 'weekly', 'monhtly'], help='Timeframe to resample to') parser.add_argument('--compression', default=1, required=False, type=int, help='Compress n bars into 1') return parser.parse_args() if __name__ == '__main__': runstrat()