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 auto-generation



  • @backtrader

    Is there any method to initialize lines with constant value in the __init__?
    I've tried to do the following:

    def __init__(self):
        self.lines.line_name = 5.0
    

    but it doesn't work. I know that I can do it in next using self.lines.line_name[0] = 5, but would like to keep it in __init__.


  • administrators

    No there isn't. There could be but no real use case was found to get code to put a constant into a line, because it is a constant and you can put it directly into the code.

    When you do

     self.lines.line_name = 5.0
    

    you actually don't initialize line_name. If 5.0 happened to be another lines object, a binding would be created and any value written/calculated into the buffers of the lines object 5.0 would later be written to the buffers of line_name.

    This allows to reuse the 5.0 lines object for several operations.

    Unfortunately your 5.0 is just a plain number (even if it's an object in the python world) and won't generate any binding, because there is no use case for it (as mentioned above)



  • hello Backtrader,
    in the case of :

    self.lines.line_name = 5.0
    

    it could be use to do a crossover between a line of 5 and a SMA for example.
    I understand how you manage to compare 2 lines.

    def __init__(self):
        self.crossover=btind.CrossOver(self.sma1, self.sma2)
    

    but this doesn't

    def __init__(self):
        self.crossover=btind.CrossOver(self.sma1, 5)
    

    how do you do the crossover of a lines with a constant?


  • administrators

    The problem there is defining the use case. CrossOver is awaiting 2 data feeds (which can be direct data feeds or derived ones like indicators)

    The question here is: Must CrossOver apply intelligence and decide that 5 has to be converted to a sort of constant lines object?

    Building this intelligence in CrossOver may also not be possible, because the background machinery processes data feeds automatically and therefore CrossOver is not actually expecting any *args (nor **kwargs)

    But since users may define custom indicators which take *args, the background machinery cannot blindly transform anything passed to the indicators to a lines object.

    The usual solution for such a case would be to define a constant indicator

    class ConstantValue(bt.Indicator):
        lines = ('constant',)
        params = (('constant', float('NaN')),)
    
        def next(self):
            self.lines.constant[0] = self.p.constant
    

    And then do the crossing as:

    bt.indicators.CrossOver(someotherdata, ConstantValue(constant=5.0))
    

    This could be further generalized to something like

    class FuncWrapper(bt.Indicator):
        lines = ('value',)
        params = (('func', None),)
    
        def next(self):
            self.lines.constant[0] = self.p.func()
    

    With the crossover now being realized as:

    bt.indicators.CrossOver(someotherdata, FuncWrapper(func=lambda x: 5.0))
    

    An automatic conversion can in any case be attempted behind the scenes, but a couple of corners have to be considered.

    Note: both constant and func could also be taken in __init__ in both wrappers. Having them as params is just the usual idiom in backtrader, which is more declarative.



  • Thank you,
    In this case i was obliged to create a line of constan like this:

    class ConstantValue(bt.Indicator):
        lines = ('constant',)
        params = (('constant', float('NaN')),)
    
        def next(self):
            self.lines.constant[0] = self.p.constant
    

    it worked



  • UPDATE: SOLVED @backtrader could you please delete this post?

    Need help from python experts with strategy parameters.
    I have a strategy defined as:

    class MyStrategy(bt.Strategy):
    
    params = (('param1', None), ('param2', None), ('param3', None), )
    
    def __init(self)___:
        ....
    
    def next(self):
        ....
    

    Also I have function defined for single backtest with strategy_params argument as list:

    def single_backtest(strategy_params):
    
        cerebro = bt.Cerebro()
        cerebro.addstrategy(MasterStrategy, ?????)
        cerebro.adddata(data)
        strats = cerebro.run()
    
        return cerebro
    

    And function call for single backtest as follows:

    if __name__ == '__main__':
        single_run_params = [10, 10, 10]
        cerebro = single_backtest(single_run_params)
    

    How this strategy_params list can be transformed (if necessary) and passed to .addstrategy() method? So in the future I just add/remove parameters in the strategy and change list in the main.


Log in to reply
 

});