For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/

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)[1]:
                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!



  • 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)
        
    

    Thanks again.


Log in to reply
 

});