Replay Feature is fetching higher timeframe instead of lower timeframe
edesmars opened this issue · 3 comments
Hi,
Thanks for the help on the previous issue. Works perfectly ;)
So going through my backtesting, I wanted to use the replay function to backtest a strategy based on 15Min candles using 1Min candles for the ticks.
Though when using the oandav20feed, the data retrieved is already the replay dataframe / compression. In my example, the data fetch was 15Min instead of 1Min. That means that the tick (calling next on strategy) are not using M1 data but M15 so the same as if i don't use replay.
I did a bit of debug and was able to find out that the replay filter will override self._timeframe and self._compression from the data feed. Though in my case a simple override of the replay function in the oandav20feed seems to have fixed the issue with the following code:
def replay(self, **kwargs):
# save original timeframe and compression to fetch data
# they will be overriden when calling replay
orig_timeframe = self._timeframe
orig_compression = self._compression
#setting up replay configuration
super(DataBase, self).replay(**kwargs)
#putting back original timeframe and compression to fetch correct data
#the replay configuration will still use the correct dataframe and compression for strategy
self._timeframe = orig_timeframe
self._compression = orig_compression
You can reproduce the issue by using a modified replay sample files as below (fetch day data to use on a strategy for weeks):
#!/usr/bin/env python
# -*- coding: utf-8; py-indent-offset:4 -*-
###############################################################################
#
# Copyright (C) 2015, 2016 Daniel Rodriguez
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
from __future__ import (absolute_import, division, print_function,
unicode_literals)
import argparse
import backtrader as bt
import backtrader.feeds as btfeeds
import backtrader.indicators as btind
import btoandav20
import datetime
class SMAStrategy(bt.Strategy):
params = (
('period', 10),
('onlydaily', False),
)
def __init__(self):
self.sma = btind.SMA(self.data, period=self.p.period)
def start(self):
self.counter = 0
def prenext(self):
self.counter += 1
print('prenext len %d - counter %d' % (len(self), self.counter))
def next(self):
self.counter += 1
print('---next len %d - counter %d' % (len(self), self.counter))
def runstrat():
# Create a cerebro entity
cerebro = bt.Cerebro(stdstats=False)
StoreCls = btoandav20.stores.OandaV20Store
cerebro.addstrategy(SMAStrategy)
# Load the Data
storekwargs = dict(
token="xxxxxxxxxxx",
account="yyyyyyyyyyy",
practice=True
)
store = StoreCls(**storekwargs)
DataFactory = store.getdata
dtformat = '%Y-%m-%dT%H:%M:%S'
fromdate = datetime.datetime.strptime("2010-01-01T00:00:00", dtformat)
todate = datetime.datetime.strptime("2010-01-31T00:00:00", dtformat)
datakwargs = dict(
timeframe=bt.TimeFrame.Days,
compression=1,
qcheck=0.5,
historical=True,
fromdate=fromdate,
todate=todate,
bidask=True,
)
data = DataFactory(dataname="EUR_USD", **datakwargs)
# Prepare the data for replay at higher timeframe
data.replay(
timeframe=bt.TimeFrame.Weeks,
compression=1)
# First add the original data - smaller timeframe
cerebro.adddata(data)
# Run over everything
cerebro.run(preload=False)
if __name__ == '__main__':
runstrat()
Warning: With the fix proposed, on my system, the values don't correspond between oanda data and replaying the data. I believe it must be some timezone issues between the data coming back from Oanda and the timing of replayed data. But it could simply be another issue on replaying.
I have added your method to the repository. I did not have time to check the code, but will do so in a few days.
Thank you, let me know if you need any help when you are looking into it. ;)
seems to be working fine