For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/
Returns Volatility Indicator
-
Hey, dear community !
Building volatility targeting strategies, I found that this relevant indicator is missing.
You could find more about this here:
https://quantpedia.com/an-introduction-to-volatility-targeting/#:~:text=Volatility target is the level,volatility is easier to predict.Hope this helps. Comments?
PS: GARCH implementation for the next version but literature says it's expensive and you get similar results using faster EWMA
class StdDevReturns(bt.Indicator): lines = ('stddev',) params = dict( method="simple", # or ewma_pd or ewma_np annualized = True, period=20, alpha=0.06, # only for ewma adjust=True, # only for ewma_pd trading_year_days=252, ) def __init__(self): self.addminperiod(self.params.period + 2) if self.p.annualized: self.annualized = self.p.trading_year_days ** (1 / 2) else: self.annualized = 1 def next(self): returns = self.Returns(self.data0.get(size=self.p.period)) if self.p.method == "simple": self.lines.stddev[0] = returns.std() * self.annualized elif self.p.method == "ewma_pd": data = pd.DataFrame(returns) self.lines.stddev[0] = data.ewm(alpha=self.p.alpha, adjust= self.p.adjust).std().iloc[-1][0] * self.annualized elif self.p.method == "ewma_np": self.lines.stddev[0] = self.CalculateEWMAVol(returns, 1 - self.p.alpha) * self.annualized def Returns(self, prices): return np.diff(np.log(prices)) #np.diff(prices) / prices[1:] def CalculateEWMAVol(self, returns, _lambda): period = len(returns) average_returns = returns.mean() e = np.arange(period-1, -1, -1) r = np.repeat(_lambda, period) vector_lambda = np.power(r, e) sxxewm = (np.power(returns - average_returns, 2) * vector_lambda).sum() Vart = sxxewm/vector_lambda.sum() EWMAVol = math.sqrt(Vart) return EWMAVol