Date issue with multiple data
There are 3 data in dataframe.
df0 is from 2016-03-16 to 2017-05-19
df1 is from 2016-01-04 to 2017-05-19
df2 is from 2016-01-04 to 2017-05-19
I want to get the current datetime at prenext. When I use self.data.datetime, it returns the last date of the data source but not the first date 2016-01-04. What is the best way to get the current date?
Below is the snippet.
: : data0 = bt.feeds.PandasData(dataname=df0) data1 = bt.feeds.PandasData(dataname=df1) data2 = bt.feeds.PandasData(dataname=df2) cerebro.adddata(data0) cerebro.adddata(data1) cerebro.adddata(data2) : : def log(self, txt, dt=None, always=True): if always and self.params.debug: dt = dt or self.data.datetime dt = bt.num2date(dt) out_txt = '%s %s (%d) - %s' % (dt.isoformat(), dt.strftime('%a'), len(self), txt) print(out_txt) def prenext(self): self.log('prenext data0', self.data0.datetime) self.log('prenext data1', self.data1.datetime) self.log('prenext data2', self.data2.datetime)
This is the output.
2017-05-19T00:00:00 Fri (1) - prenext data0
2016-01-04T00:00:00 Mon (1) - prenext data1
2016-01-04T00:00:00 Mon (1) - prenext data2
My second question is about how can I define the start and end date for the analyzers to calculate the Sharpe? Let say my strategy needs to go through all data from 2016-01-04 and start trading from 2017-01-04. Is there a way to specify the start and end date (2017-01-04, 2017-05-19) so that the Sharpe is calculated based on the period but not on the entire data range of the data?
You are being fooled by two factors:
- Yourself (it happens during the development of backtrader all the time and even more often than that)
- Data Preloading
1. Why Yourself?
prenextis where you can do dirty things, because it happens before the
nextphase is in effect. Data feeds and indicators may not be delivering values (or meaningful ones) because the corresponding minimum periods to deliver have not yet been met.
That means that accessing values should be done carefully and with several safeguarding measures in place. The most usual measure is to check if the object which is going to be checked has a positive length. As in:
def prenext(self): if len(self.data1): # is not zero print('it is then guaranteed that it has something like:', self.data.close)
Because the data feeds have different starting points they will start delivering at different times.
2. Why Data Preloading?
Because no safeguards are in place and the default (to speed up things) is to preload the data before doing anything, the python arithmetic for array indexing is taking you somewhere ... which happens to be the last value of the array.
The lifecycle of a
Strategyis documented: Docs - Strategy