def atr(self, n_days, date_=None, as_price=True): ''' Returns a StockPrice list with the average true range (ATR) indicator. By default the list contains the ATR as a price, set <as_price> to False in order to return a list with the ATR as percentage of the close price. Because of the EMA this indicator cannot be calculated for a single <date_>, the entire list is kept in cache. NOTE: the cache is a potential risk for memory overflows. ''' if not hasattr(self, '_cache'): self._cache = {} key = ('ATR', n_days, as_price) if key not in self._cache: if not isinstance(n_days, int): raise TypeError, 'n_days must be an integer' if n_days < 1: raise ValueError, 'n_days must be > 0' tr = [] for date in self.close.dates: yest_close = self.close.offset(date, -1) day_range = max(yest_close, self.high[date]) - min(yest_close, self.low[date]) if not as_price: day_range = day_range / self.close[date] tr.append(day_range) self._cache[key] = StockPrice(calc_ema(tr, n_days), self.close.dates) if date_: return self._cache[key][date_] else: return self._cache[key]
def dma(self, n_points, mpl=0.5, n_ma=None, date=None): ''' Dynamic Moving Average. Period is based on atr Default multiplier (mpl) = 0.5, so we are looking at a range of 1 atr (0.5 above, 0.5 below). ''' if not isinstance(n_points, int): raise TypeError, 'n_points must be an integer' if n_points < 1: raise ValueError, 'n_points must be > 0' dma = [] dates = self.close.dates if date is None else [date] for startdate in dates: startprice = self.close[startdate] i_start = self.close.index(startdate) i = 0 for date in self.close.dates[i_start::-1]: atr = mpl * self.atr(10)[date] if self.low[date] <= startprice - atr: factor = (startprice - self.low[date]) // atr startprice -= factor * atr i += factor elif self.high[date] > startprice + atr: factor = (self.high[date] - startprice) // atr startprice += factor * atr i += factor if i >= n_points: break ma_list = self.close[date:startdate] dma.append(sum(ma_list)/len(ma_list)) if len(dma) == 1: return dma[0] else: if n_ma: #smoothen if desired dma = calc_ema(dma, n_ma) return StockPrice(dma, self.close.dates)