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

Strategy Selection Pattern



  • with in the article Strategy Selection you speak of how to run multiple strategies separately. The pattern you seem to be using is called the singleton pattern

        class StFetcher(object):
            _STRATS = [St0, St1]
        
            def __new__(cls, *args, **kwargs):
                idx = kwargs.pop('idx')
        
                obj = cls._STRATS[idx](*args, **kwargs)
                return obj
    

    this pattern is great for a strategy selection type use case. However, I want to be able to change the cerebro from optstrategy() to addstrategy() so that I can A: run the code live and B: be able to spin up multiple strategies at the same time on the same broker. Could you give me an example of how I could use the same pattern but instead of returning one strategy at a time, return as many as I need?

    Thanks,



  • @backtrader would the best pattern be something similar to attached code, the idea is this would allow the master to control sub strategies :

        class NewSubStrategy():
    
            def foo(self):
    
               ##Strategy code here
    
        class Master(bt.Strategy):
    
            def __init__(self):
    
                ##Lines here
                
                #Int new strategy (static version)
                self.st1 = NewSubStrategy
                self.st2 = NewSubStrategy
    
            def next(self):
    
                #Master strategy logic
    
                #call sub strategy on next()
                self.st1.foo(self)
                self.st2.foo(self)


  • after trying different things through out the day, I found the best pattern was to just make a strategy as a indicator and spawn a new instance of a indicator as needed.


  • administrators

    I don't think the StFetcher class is a singleton. It is simply a factory, which can be easily expressed in Python as an opaque class thanks to the fact that __new__ method can return instances of actually anything.

    @blonc said in Strategy Selection Pattern:

    I found the best pattern was to just make a strategy as a indicator and spawn a new instance of a indicator as needed

    But in this case, the strategy is just calculating output values for the defined lines, or are you also executing orders from it?



  • @backtrader singleton, in the sense that I believe it can only return one instance at a time of anything.

    The situation I am trying to achieve would also be executing orders. The concept I am trying to achieve is to have many strategies all being monitored by a master strategy. This way, the master strategy could be using a markov chain to monitor returns to turn on and off individual strategies based on the total returns of all strategies. It seems the best path is to , correct me if wrong, put the strategies logic into indicators and bring them into one master strategy.


  • administrators

    That's a factory returning a single item, but not a singleton (Store subclasses, for example IBStore for Interactive Brokers because only one connection to TWS is expected, are implemented as singletons, although someone could implement a Store which isn't a singleton)

    Sub-strategies is not a pattern which does exist in backtrader. Using Indicator instances could do the trick.

    • Pass the Strategy (actually self inside __init__) to the indicator as a named (and declared) parameter
    • Use that reference to the strategy to execute operations


  • @backtrader i keep getting the error of maximum recursion depth im sure this has to do with how things are set up in the backend. could you give me some simple sudo code with what you were talking:

    @backtrader said in Strategy Selection Pattern:

    Sub-strategies is not a pattern which does exist in backtrader. Using Indicator instances could do the trick.

    • Pass the Strategy (actually self inside __init__) to the indicator as a named (and declared) parameter
    • Use that reference to the strategy to execute operations

    just add the required to bellow sudo to bellow, no need to include lines or anything:

    class Sub(bt.Indicator):
        def __init__(self):
    
        def next(self):
    
    class Master(bt.Strategy):
        def __init__(self):
    
        def next(self):

  • administrators

    class Sub(bt.Indicator):
        params = dict(mystrategy=None)
        def __init__(self):
    
        def next(self):
    
    class Master(bt.Strategy):
        def __init__(self):
            theindicator = Sub(mystrategy=self)
    
        def next(self):
    

  • administrators

    Of course, the maximum recursion depth trace would/could help.



  • @backtrader thats perfect, the two way communication works brilliantly while still retaining all of the passing of datas and so on.



  • @backtrader framework question. Since, theindicator = Sub(mystrategy=self) is defined with-in __init__ of class Master(bt.Strategy) it seems to run through all of the lines provided for class Sub(bt.Indicator): before moving on to the next declared item in __init__ of Master. If receiving realtime data will class Sub(bt.Indicator): automatically update or will i need to call it with in the Master to let it know there is new info.



  • @backtrader for two way communication to happen IE one -> many and many->one i found the following gives the desired results. the issue i ended up finding with the method of using indicators was that when you initialize the theindicator = Sub(mystrategy=self) for a class with bt.Indicator . it would go up to that indicator and run through all lines with out stopping . ... creating a generic class and calling sub-strategy next() with in the master next() . if u know a better way let me know.

           class SubStrategy():
        
                def __init__(self,mystrategy,data_feed):
                    #passes update to master
                    self.master_comm = mystrategy
        
                def next(self):
                    #example to send buy signal
                    self.master_comm.buy()
        
        
            class Master(bt.Strategy):
        
                def __init__(self):
        
                    #removed bt.indicator from class Sub()
                    #the bellow seems to give desired results
                    self.st1 = SubStrategy(mystrategy=self, data_feed=self.data0)
        
        
                def next(self):
                    self.st1.next(self)

  • administrators

    You have to disable runonce to avoid pre-calculation of the indicators, which in your case have to tick like in real-time at the pace of the strategy.



  • @blonc said in Strategy Selection Pattern:

    The concept I am trying to achieve is to have many strategies all being monitored by a master strategy. This way, the master strategy could be using a markov chain to monitor returns to turn on and off individual strategies based on the total returns of all strategies. It seems the best path is to , correct me if wrong, put the strategies logic into indicators and bring them into one master strategy.

    @backtrader said in Strategy Selection Pattern:

    Sub-strategies is not a pattern which does exist in backtrader. Using Indicator instances could do the trick.

    Was also thinking about utilizing the concept of having a "master" strategy turning on and off "micro strategies", so I'm glad I found this post :)
    I can think of a lot of use cases for using a master strategy that based on a wide overview of a market/s can control what micro strategies are suited to be used.

    the idea of using indicators as sub-strategies seem brilliant (haven't tested it yet).
    but from my understanding strategies can be better analyzed and give valuable insights. I hope we can wider the discussion just to explore more solutions (as @backtrader mentioned nested strategies are not supported)

    one idea I have that I don't think break backtrader structure is:
    declaring a 'master' that run first and based on whatever user logic it creates a 'signal dictionary' that is then passed to all other micro strategies. allowing them to decide if to run or not in next().
    this way all strategies are kept in the same level of operation (not nested)