Create an indicator based on an analyzer
-
Dear community,
I would like to create an indicator based on the daily returns of a data series. As far as I understand, the returns are not automatically "available", but first have to be calculated with an analyzer.
So here is my approach:
First, I load the data, then I create the analyzer called "myReturn":# Load data from a pre-specified dataframe data = bt.feeds.PandasData(dataname=dataframe) # Add data to cerebro cerebro.adddata(data) # Add analyzer cerebro.addanalyzer(bt.analyzers.TimeReturn, timeframe=bt.TimeFrame.Days, data=data, _name='myReturn')
After I run the strategy, I can access the analyzer (=returns), so that works well:
thestrats = cerebro.run() thestrat = thestrats[0] tret_analyzer = thestrat.analyzers.getbyname('myReturn') print(tret_analyzer.get_analysis())
However, when I would like to create an indicator based on the analyzer, I just can't figure out how to access it. As a simple example, I would like to create two moving averages:
- a moving average of the price of the last 15 days
- a moving average of the returns of the last 15 days
# Sample strategy from backtrader quickstart example class TestStrategy(bt.Strategy): params = ( ('maperiod', 15), ) def log(self, txt, dt=None): ''' Logging function fot this strategy''' dt = dt or self.datas[0].datetime.date(0) print('%s, %s' % (dt.isoformat(), txt)) def __init__(self): # Keep a reference to the "close" line in the data[0] dataseries self.dataclose = self.datas[0].close # To keep track of pending orders and buy price/commission self.order = None self.buyprice = None self.buycomm = None # Add a MovingAverageSimple indicator OF THE CLOSING PRICE self.pricesma = bt.indicators.SimpleMovingAverage( self.datas[0], period=self.params.maperiod) # Add a MovingAverageSimple indicator OF THE RETURNS (=ANALYZER) self.returnsma = bt.indicators.SimpleMovingAverage( self.analyzers[0], period=self.params.maperiod)
The problem is obviously the last line in the code, as this seems to be the wrong way to access the values of the analyzers.
Could anybody tell me how I correctly refer to an analyzer in order to create an indicator? That would be great!
Thanks a lot!
jf -
An
Analyzer
is not a data feed and cannot therefore be used as input for anIndicator
. In any case you are not calculating returns (as in the returns of your accounts) but the daily variations of the data.Why not use the
PercentChange
indicator on the data and then make aSimpleMovingAverage
of that?myind = bt.ind.SMA(bt.ind.PctChange(self.data), period=myperiod))
-
@backtrader: Ok great, thanks!
@community: I guess a standard number that traders are interested in is the volatility of returns, which can be used for portfolio construction approaches such as "equal contribution to risk", volatility based risk management, etc.
As backtrader explained above, it is best to implement this with an indicator based on an indicator. I currently implement return volatility calculation like this (using TA-LIB):
returnvola = bt.talib.STDDEV(bt.ind.PctChange(self.data.close), timeperiod=30, plot=True)
Would of course be interested to hear from you if somebody implements it differently, for example without TA-LIB... Also, has someone implemented this based on log-returns?
Thanks!
-
@jf said in Create an indicator based on an analyzer:
returnvola = bt.talib.STDDEV(bt.ind.PctChange(self.data.close), timeperiod=30, plot=True)
Would of course be interested to hear from you if somebody implements it differently, for example without TA-LIB
returnvola = bt.ind.StdDev(bt.ind.PctChange(self.data.close), period=30)
which you can shorten (to make it a lot more generic) to
returnvola = bt.ind.StdDev(bt.ind.PctChange(self.data), period=30)
or even
returnvola = bt.ind.StdDev(bt.ind.PctChange(), period=30)
-
Perfect, thanks!