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

Dynamic values for strategy



  • Hi,
    I'm new to Backtrader and am really enjoying it! I searched the documentation, articles, and forum for anything about dynamically changing the strategy parameters after initialization. I could only find one example on dynamically changing the an indicator which I could not figure out...
    I am probably misunderstanding the Dynamic Indicators article. If this is the case, could someone please explain it to me with the example below.

    I am trying to add another indicator (EMA3cross) to the strategy - I want this indicator to be dynamically changed between the EMA1cross and EMA2cross proportionally according to the SMA indicator.

    class Test(bt.Strategy):
    
        params = (('ema1fast', 20), ('ema1slow', 40), ('ema2fast', 50), ('ema2slow', 100), ('sma', 50))
    
        def __init__(self):
            # EMAcross1
            self.e1f = btind.EMA(self.data, period=self.p.ema1fast)
            self.e1s = btind.EMA(self.data, period=self.p.ema1slow)
            # EMAcross2
            self.e2f = btind.EMA(self.data, period=self.p.ema2fast)
            self.e2s = btind.EMA(self.data, period=self.p.ema2slow)
            # SMA
            self.sma = btind.SMA(self.data, period=self.p.sma)
    
        def next(self):
            # EMA3cross
            self.ema3fast = (self.e1f._minperiod * self.sma)
            self.ema3slow = (self.e1s._minperiod * self.sma)
            EMA3fast = btind.EMA(self.data, period=self.ema3fast)
            EMA3slow = btind.EMA(self.data, period=self.ema3slow)
            self.buysig = btind.CrossOver(EMA3fast, EMA3slow)
            
            # Buy/Sell
            if self.buysig < 0:
                self.sell()
            elif self.buysig > 0:
                self.buy()
    
    

    Error:

    Traceback (most recent call last):
      File "dynamic1.py", line 97, in <module>
        thestrats = cerebro.run()
      File "/home/user1/.local/lib/python3.8/site-packages/backtrader/cerebro.py", line 1127, in run
        runstrat = self.runstrategies(iterstrat)
      File "/home/user1/.local/lib/python3.8/site-packages/backtrader/cerebro.py", line 1293, in runstrategies
        self._runonce(runstrats)
      File "/home/user1/.local/lib/python3.8/site-packages/backtrader/cerebro.py", line 1695, in _runonce
        strat._oncepost(dt0)
      File "/home/user1/.local/lib/python3.8/site-packages/backtrader/strategy.py", line 311, in _oncepost
        self.nextstart()  # only called for the 1st value
      File "/home/user1/.local/lib/python3.8/site-packages/backtrader/lineiterator.py", line 347, in nextstart
        self.next()
      File "dynamic1.py", line 47, in next
        if self.buysig < 0:
    TypeError: __bool__ should return bool, returned LineOwnOperation
    


  • @agog Try [0] to get the line at the current date.

    self.buysig[0]
    


  • @run-out, thanks for the help, but that did not work...

    Has anyone implemented something like this?

    I have some new code trying to make a MACD (MACD2) parameters dynamic:

    class Test(bt.Strategy):
    
        params = (('macdfast', 50), ('macdslow', 200),('macdsignal', 500), \
                  ('bbtimeperiod', 50), ('nbdevup', 1),('nbdevdn', 1))
    
        def __init__(self):
            # MACD1
            self.talib_macd = bt.talib.MACD(self.data, fastperiod=int(self.p.macdfast), slowperiod=int(self.p.macdslow), signalperiod=int(self.p.macdsignal))
            
            # BBANDS
            self.bb = bt.talib.BBANDS(self.data, timeperiod=self.p.bbtimeperiod, nbdevup=float(self.p.nbdevup), nbdevdn=float(self.p.nbdevdn), plot=True)
    
        def next(self):
            # MACD2 (Dynamic)
            macd2fast = self.p.macdfast * self.bb.upperband-self.bb.lowerband
            macd2slow = self.p.macdslow + self.p.macdslow * self.bb.upperband-self.bb.lowerband
            macd2signal = self.p.macdsignal + self.p.macdsignal * self.bb.upperband-self.bb.lowerband
    
            talib_macd2 = bt.talib.MACD(self.data, fastperiod=int(macd2fast), slowperiod=int(macd2slow), signalperiod=int(macd2signal), plot=False)
            
    # Getting MACD2 plotlines
            macd_line = talib_macd2.macd[0]
            signal_line = talib_macd2.macdsignal[0]
    
            # Buy/Sell
            if macd_line > signal_line:
                self.sell()
            elif macd_line < signal_line:
                self.buy()
    

    The error I am getting is this:

      File "dynamic3.py", line 41, in next
        macd_line = talib_macd2.macd[0]
      File "/home/user1/.local/lib/python3.8/site-packages/backtrader/linebuffer.py", line 163, in __getitem__
        return self.array[self.idx + ago]
    IndexError: array index out of range
    


  • @agog
    i am also facing same kind of issue "array index out of range" you were able to fix it



  • @agog said in Dynamic values for strategy:

    MACD2 (Dynamic)

        macd2fast = self.p.macdfast * self.bb.upperband-self.bb.lowerband
        macd2slow = self.p.macdslow + self.p.macdslow * self.bb.upperband-self.bb.lowerband
        macd2signal = self.p.macdsignal + self.p.macdsignal * self.bb.upperband-self.bb.lowerband
    
        talib_macd2 = bt.talib.MACD(self.data, fastperiod=int(macd2fast), slowperiod=int(macd2slow), signalperiod=int(macd2signal), plot=False)
    

    I think all of this needs to be in your init sections.


Log in to reply
 

});