Don't start next() until specific date
- algoguy235 last edited by algoguy235
In my strategy I'm using a 200 hour EMA, which means for different futures products that could take anywhere from 10 to 35 days of preloaded data. I have 1-minute data so it's not so simple to figure out exactly how many minute bars would be required to complete the 200-hour preload.
Instead, I want to just load 40 extra days of data for every product, and just make sure I don't start trading until my true start date.
I was thinking I could manipulate either start() or nextstart() to delay the strategy's 'change to adulthood'. But I couldn't figure it out.
class strat(bt.strategy): params = {start_date: datetime.datetime(1,1,1)} def __init__(self): pass def next(self): if self.data0.datetime.datetime() < self.p.start_date: return #strategy ....
This solution adds a lot of overhead to my next function, around 50% increase overall. I was hoping I could implement similar logic but instead put it into nextstart() or possibly start(). nextstart() didn't work, but this was my naive idea, to somehow overwrite the normal nextstart() functionality.
# NOT CORRECT USE OF NEXTSTART class strat(bt.strategy): params = {start_date: datetime.datetime(1,1,1)} def __init__(self): pass def nextstart(self): if self.data0.datetime.datetime() < self.p.start_date: return else: self.next() def next(self): #strategy ....
This is functionally what I would like to do. But is there a correct way do it?
- algoguy235 last edited by algoguy235
Ok here's the best I got to far, found a way to use the behind the scenes lines calculation during init. Definitely a performance improvement, but still looking for better.
class strat(bt.strategy): params = {start_date: datatime(1,1,1)} def __init__(self): self.trade_delay = self.data0.datetime < bt.date2num(self.p.start_date) def next(self): if self.trade_delay: return #strategy ...
- backtrader administrators last edited by
Getting into
next(adulthood) is not foreseen in terms of
datetime. The requirement is that all lines objects that play a role in the
Strategy(data feeds, indicators and those generated with, for example, arithmetic operations) deliver.
As such, the only actual way is to have a guard in
nextitself (and not in
nextstartwhich will be called only once by the system)
Something along the lines of (not dissimilar to what you have tried)
def next(self): if self.data.datetime.datetime(0) < self.minimum_date: return
I had a similar problem and resolved following way.
First, there is a base strategy class that can verify if date is within interval:
class StrategyBase(bt.Strategy): params = ( ('start_date', None), ('end_date', None), ) def within_range(self): date = self.data.datetime.datetime(0) if date >= self.p.start_date and date <= self.p.end_date: return True else: return False
The methold within_range() is called in self() of derived class:
def next(self): if not self.within_range(): return
Then I have a function to adjust the dates that will be loaded from the feed:
def adjust_start_date(date, *params): maximum = 0 for p in params: if isinstance(p, int): if p > maximum: maximum = p # For every week there are only 5 trading days (stocks) days = math.ceil(maximum * 7/5) adjusted = date - datetime.timedelta(days = days) return adjusted
This function is used to adjust the date of the feed. So there are two start dates: one for the feed, other for the strategy:
feed_start_date = adjust_start_date(start_date, param1, param2, param3) cerebro.adddata(bt.feeds.GenericCSVData(fromdate = feed_start_date, todate=end_date)) cerebro.addstrategy(Strategy, param1 = param1, param2 = param2, param3 = param3, start_date = feed_start_date, end_date = end_date )