Rebalancing at the end of the month with timers
I would like to rebalance on the last trading day of each month.
With timers, I'm not able to achieve this with just the "monthdays" parameter, since the day isn't fixed. So I thought about using the allow parameter to provide custom rules.
import calendar class EndOfMonth(object): def __call__(self, d): if d.day == calendar.monthrange(d.year, d.month): return True return False
While I'm able to get the last day of the month this way, it doesn't work as desired since the timer callback isn't called on weekends and more importantly, holidays (because my data feeds simply don't have these dates included). This results in the monthly rebalance to be ignored for certain months.
If I could somehow know in advance that the current day is the last available day of the month, by looking at next available date in the data feed, that might work, although the data feed doesn't seem to be passed as an argument to the callback.
Does anyone know how to approach this problem? Thanks!
vladisld last edited by
You may try to use the TradingCalendar class, supplied with backtrader. It has a last_monthday method that returns true if a given trading day is a last trading day of the month.
More docs here: https://www.backtrader.com/docu/tradingcalendar/tradingcalendar/
Thank you, that might do the trick. Although I can't quite figure out how to call the instance of the calendar inside a Strategy. Could you elaborate?
I've got it working, here's some boilerplate code:
class EndOfMonth(object): def __init__(self, cal): self.cal = cal def __call__(self, d): if self.cal.last_monthday(d): return True return False class AssetAllocation(bt.Strategy): params = ( ('cal', None), ) def __init__(self): self.add_timer( when=bt.Timer.SESSION_START, allow=EndOfMonth(self.p.cal), ) if __name__ == '__main__': # Create a cerebro entity cerebro = bt.Cerebro() cal = bt.TradingCalendar() cerebro.addcalendar(cal) # Add a strategy cerebro.addstrategy(AssetAllocation, cal=cal)