Closed FGU1 closed 3 years ago
I've tested this by finding all of the bad dates in one year, and then running them with the new code.
from datetime import timedelta, datetime
def dt_plus_duration(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)
# return dt.replace(year=dt.year + years, month=month + 1)
return dt.replace(year=dt.year + years, month=month + 1, day=1) + timedelta(dt.day - 1)
if dim == 'Y':
return dt.replace(year=dt.year + size)
return dt # could do nothing with it ... return it intact
if __name__ == '__main__':
dates = [
[datetime(2020, 7, 31), datetime(2020, 10, 1)],
[datetime(2020, 12, 29), datetime(2021, 3, 1)],
[datetime(2020, 12, 30), datetime(2021, 3, 2)],
[datetime(2020, 12, 31), datetime(2021, 3, 3)],
]
for date in dates:
calulate_date = dt_plus_duration(date[0], "2 M")
assert calulate_date == date[1]
print(f"Input date: {date[0].date()} Calculated date: "
f"{dt_plus_duration(date[0], '2 M').date()} Output date:{date[1].date()}")
Output:
Input date: 2020-07-31 Calculated date: 2020-10-01 Output date:2020-10-01
Input date: 2020-12-29 Calculated date: 2021-03-01 Output date:2021-03-01
Input date: 2020-12-30 Calculated date: 2021-03-02 Output date:2021-03-02
Input date: 2020-12-31 Calculated date: 2021-03-03 Output date:2021-03-03
This looks good to me. @vladisld Do you think we need a more integrated test?
I would add an additional problematic dates:
[datetime(2019, 12, 29), datetime(2020, 2, 29)],
[datetime(2019, 12, 30), datetime(2020, 3, 1)],
[datetime(2019, 12, 31), datetime(2020, 3, 2)],
Otherwise LGTM.
OK, dates then are:
dates = [
[datetime(2020, 7, 31), datetime(2020, 10, 1)],
[datetime(2020, 12, 29), datetime(2021, 3, 1)],
[datetime(2020, 12, 30), datetime(2021, 3, 2)],
[datetime(2020, 12, 31), datetime(2021, 3, 3)],
[datetime(2019, 12, 29), datetime(2020, 2, 29)],
[datetime(2019, 12, 30), datetime(2020, 3, 1)],
[datetime(2019, 12, 31), datetime(2020, 3, 2)],
]
And results are:
Input date: 2020-07-31 Calculated date: 2020-10-01 Output date:2020-10-01
Input date: 2020-12-29 Calculated date: 2021-03-01 Output date:2021-03-01
Input date: 2020-12-30 Calculated date: 2021-03-02 Output date:2021-03-02
Input date: 2020-12-31 Calculated date: 2021-03-03 Output date:2021-03-03
Input date: 2019-12-29 Calculated date: 2020-02-29 Output date:2020-02-29
Input date: 2019-12-30 Calculated date: 2020-03-01 Output date:2020-03-01
Input date: 2019-12-31 Calculated date: 2020-03-02 Output date:2020-03-02
I will go ahead and merge.
I don't see the above test committed as part of the fix and running as part of Travis CI - am I missing something ?
No you didn't miss it. I was asking above if the local test was good enough. I'm not sure how to test IBStores in Travis. Could you assist? Thanks.
Sure, np, I'll try to integrate it.
I guess this test would be ok ?
import datetime as dt
store = bt.stores.IBStore()
test_cases = [
(dt.datetime(2020, 7, 31), '2 M', dt.datetime(2020, 10, 1)),
(dt.datetime(2020, 12, 29), '2 M', dt.datetime(2021, 3, 1)),
(dt.datetime(2020, 12, 30), '2 M', dt.datetime(2021, 3, 2)),
(dt.datetime(2020, 12, 31), '2 M', dt.datetime(2021, 3, 3)),
(dt.datetime(2019, 12, 29), '2 M', dt.datetime(2020, 2, 29)),
(dt.datetime(2019, 12, 30), '2 M', dt.datetime(2020, 3, 1)),
(dt.datetime(2019, 12, 31), '2 M', dt.datetime(2020, 3, 2)),
(dt.datetime(1999, 12, 31), '2 M', dt.datetime(2000, 3, 2)),
(dt.datetime(2099, 12, 31), '2 M', dt.datetime(2100, 3, 3))
]
def test_run():
for src_dt, duration_str, trg_dt in test_cases:
calculated_dt = store.dt_plus_duration(src_dt, duration_str)
assert calculated_dt == trg_dt
yep, the only small issue I see is to run it in Travis - for that you need to instruct Travis CI to import the ibpy package first - otherwise IBStore class will not be available for you.
Hi, Just a small modification of ibstore.py to fix https://github.com/backtrader2/backtrader/issues/41 Month offset was done by changing the month number, which caused problem when for ex. the 31th of January was offset to February.