Strategy auto-generation
-
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
usingself.lines.line_name[0] = 5
, but would like to keep it in__init__
. -
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
. If5.0
happened to be another lines object, a binding would be created and any value written/calculated into the buffers of the lines object5.0
would later be written to the buffers ofline_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?
-
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 that5
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 processesdata feeds
automatically and thereforeCrossOver
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
andfunc
could also be taken in__init__
in both wrappers. Having them asparams
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 themain
.