Exception has occurred: ValueError day is out of range for month File "F:\IBBackTradeLiveDataEx.py", line 165, in <module> cerebro.run()
-
Getting above error. Trying to replay data, higherTF=Daily, LowerTimeFrame=5 min
Code below:from future import absolute_import, division, print_function, unicode_literals
import backtrader as bt
from backtrader import Order
import matplotlib as plt
import datetime
import pytz
import tacerebro = bt.Cerebro()
store = bt.stores.IBStore(host="127.0.0.1", port=7496, clientId= 4)
cerebro.addstrategy(IntraTrendStrategy)
stockkwargs = dict(
timeframe=bt.TimeFrame.Minutes,
compression=5,
rtbar=False, # use RealTime 5 seconds bars
historical=True, # only historical download
qcheck=0.5, # timeout in seconds (float) to check for events
fromdate=datetime.datetime(2020, 1, 1), # get data from..
todate=datetime.datetime(2020, 9, 20), # get data from..
latethrough=False, # let late samples through
tradename=None, # use a different asset as order target
tz="Asia/Kolkata"
)data0 = store.getdata(dataname="TCS-STK-NSE-INR", **stockkwargs)
cerebro.replaydata(data0, timeframe=bt.TimeFrame.Days, compression=1)
cerebro.broker.setcash(100000.0)
cerebro.broker.setcommission(commission=0.001)
print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())cerebro.run()
print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
-
Seems to be an embarrassing bug in the way the IBStore calculates the minimal possible number of historical requests.
BTW it doesn't crash if you just use the different
fromdate
likedatetime(2020,1,2)
for example.The problem is with the following code in IBStore.py:
def dt_plus_duration(self, dt, duration): size, dim = duration.split() size = int(size) if dim == 'S': return dt + timedelta(seconds=size) if dim == 'D': return dt + timedelta(days=size) if dim == 'W': return dt + timedelta(days=size * 7) if dim == 'M': month = dt.month - 1 + size # -1 to make it 0 based, readd below years, month = divmod(month, 12) try: return dt.replace(year=dt.year + years, month=month + 1) # <=-- the bug is here except: pass if dim == 'Y': return dt.replace(year=dt.year + size) return dt # could do nothing with it ... return it intact
It's plain wrong to replace the month of the date without taking care of the day of the month. In our case the date '2019.12.31' was replaced with '2020.02.31' which is definitely wrong.
-
New issue submitted: https://github.com/backtrader2/backtrader/issues/41
-
Thank you!