class EMAVolume(Indicator): def __init__(self, period, cache_size=None): self._ema = EMA(period) super().__init__({ 'args': [period], 'id': 'emavol', 'name': 'EMA Vol(%f)' % period, 'seed_period': period, 'data_type': 'candle', 'data_key': '*', 'cache_size': cache_size }) def reset(self): super().reset() self._ema.reset() def update(self, candle): self._ema.update(candle['vol']) ema = self._ema.v() if isfinite(ema): super().update(ema) return self.v() def add(self, candle): self._ema.add(candle['vol']) ema = self._ema.v() if isfinite(ema): super().add(ema) return self.v()
class ChaikinOsc(Indicator): def __init__(self, short, long, cache_size=None): self._shortEMA = EMA(short, cache_size) self._longEMA = EMA(long, cache_size) self._adl = AccumulationDistribution() super().__init__({ 'args': [short, long, cache_size], 'id': 'chaikinosc', 'name': 'ChaikinOsc(%f, %f)' % (short, long), 'seed_period': max([short, long]), 'data_type': 'candle', 'data_key': '*', 'cache_size': cache_size }) def reset(self): super().reset() self._shortEMA.reset() self._longEMA.reset() self._adl.reset() def update(self, candle): self._adl.update(candle) adl = self._adl.v() if not isfinite(adl): return self._shortEMA.update(adl) self._longEMA.update(adl) short = self._shortEMA.v() long = self._longEMA.v() if (isfinite(short) and isfinite(long)): super().update(short - long) return self.v() def add(self, candle): self._adl.add(candle) adl = self._adl.v() if not isfinite(adl): return self._shortEMA.add(adl) self._longEMA.add(adl) short = self._shortEMA.v() long = self._longEMA.v() if (isfinite(short) and isfinite(long)): super().add(short - long) return self.v()
class MassIndex(Indicator): def __init__(self, args=[]): [period] = args self._smoothing = period self._singleEMA = EMA([9]) self._doubleEMA = EMA([9]) self._buffer = [] super().__init__({ 'args': args, 'id': 'mi', 'name': 'Mass Index(%f)' % period, 'seed_period': 9 + period, 'data_type': 'candle', 'data_key': '*' }) def reset(self): super().reset() self._singleEMA.reset() self._doubleEMA.reset() self._buffer = [] def update(self, candle): high = candle['high'] low = candle['low'] self._singleEMA.update(high - low) self._doubleEMA.update(self._singleEMA.v()) if len(self._buffer) == 0: self._buffer.append(self._singleEMA.v() / self._doubleEMA.v()) else: self._buffer[-1] = self._singleEMA.v() / self._doubleEMA.v() if len(self._buffer) < self._smoothing: return self.v() return super().update(sum(self._buffer)) def add(self, candle): high = candle['high'] low = candle['low'] self._singleEMA.add(high - low) self._doubleEMA.add(self._singleEMA.v()) self._buffer.append(self._singleEMA.v() / self._doubleEMA.v()) if len(self._buffer) > self._smoothing: del self._buffer[0] elif len(self._buffer) < self._smoothing: return self.v() return super().add(sum(self._buffer))
class VO(Indicator): def __init__(self, args=[]): [shortPeriod, longPeriod] = args self._shortEMA = EMA([shortPeriod]) self._longEMA = EMA([longPeriod]) super().__init__({ 'args': args, 'id': 'vo', 'name': 'VO(%f, %f)' % (shortPeriod, longPeriod), 'seed_period': longPeriod, 'data_type': 'candle', 'data_key': '*' }) def reset(self): super().reset() self._shortEMA.reset() self._longEMA.reset() def update(self, candle): vol = candle['vol'] self._shortEMA.update(vol) self._longEMA.update(vol) short = self._shortEMA.v() long = self._longEMA.v() if long == 0: return super().update(0) return super().update(((short - long) / long) * 100) def add(self, candle): vol = candle['vol'] self._shortEMA.add(vol) self._longEMA.add(vol) short = self._shortEMA.v() long = self._longEMA.v() if long == 0: return super().add(0) return super().add(((short - long) / long) * 100)
class TRIX(Indicator): def __init__(self, args = []): [ period ] = args self._emaFirst = EMA([period]) self._emaSecond = EMA([period]) self._emaThird = EMA([period]) super().__init__({ 'args': args, 'id': 'trix', 'name': 'TRIX(%f)' % (period), 'seed_period': (period * 3) + 1 }) def reset(self): super().reset() self._emaFirst.reset() self._emaSecond.reset() self._emaThird.reset() def update(self, v): self._emaFirst.update(v) self._emaSecond.update(self._emaFirst.v()) self._emaThird.update(self._emaSecond.v()) curr = self._emaThird.v() if not isfinite(curr) or self._emaThird.l() < 2: return self.v() prev = self._emaThird.prev() return super().update(((curr / prev) - 1) * 10000) def add(self, v): self._emaFirst.add(v) self._emaSecond.add(self._emaFirst.v()) self._emaThird.add(self._emaSecond.v()) curr = self._emaThird.v() if not isfinite(curr) or self._emaThird.l() < 2: return self.v() prev = self._emaThird.prev() return super().add(((curr / prev) - 1) * 10000)
class PPO(Indicator): def __init__(self, args=[]): [shortPeriod, longPeriod] = args self._shortEMA = EMA([shortPeriod]) self._longEMA = EMA([longPeriod]) self._signalEMA = EMA([9]) super().__init__({ 'args': args, 'id': 'ppo', 'name': 'PPO(%f, %f)' % (shortPeriod, longPeriod), 'seed_period': longPeriod }) def reset(self): super().reset() self._shortEMA.reset() self._longEMA.reset() self._signalEMA.reset() def update(self, v): self._shortEMA.update(v) self._longEMA.update(v) short = self._shortEMA.v() long = self._longEMA.v() ppo = 0 if long == 0 else ((short - long) / long) * 100 self._signalEMA.update(ppo) return super().update(self._signalEMA.v()) def add(self, v): self._shortEMA.add(v) self._longEMA.add(v) short = self._shortEMA.v() long = self._longEMA.v() ppo = 0 if long == 0 else ((short - long) / long) * 100 self._signalEMA.add(ppo) return super().add(self._signalEMA.v())
class PPO(Indicator): def __init__(self, shortPeriod, longPeriod, cache_size=None): self._shortEMA = EMA(shortPeriod, cache_size) self._longEMA = EMA(longPeriod, cache_size) self._signalEMA = EMA(9, cache_size) super().__init__({ 'args': [shortPeriod, longPeriod, cache_size], 'id': 'ppo', 'name': 'PPO(%f, %f)' % (shortPeriod, longPeriod), 'seed_period': longPeriod, 'cache_size': cache_size }) def reset(self): super().reset() self._shortEMA.reset() self._longEMA.reset() self._signalEMA.reset() def update(self, v): self._shortEMA.update(v) self._longEMA.update(v) short = self._shortEMA.v() long = self._longEMA.v() ppo = 0 if long == 0 else ((short - long) / long) * 100 self._signalEMA.update(ppo) return super().update(self._signalEMA.v()) def add(self, v): self._shortEMA.add(v) self._longEMA.add(v) short = self._shortEMA.v() long = self._longEMA.v() ppo = 0 if long == 0 else ((short - long) / long) * 100 self._signalEMA.add(ppo) return super().add(self._signalEMA.v())
class RSI(Indicator): def __init__(self, period, cache_size=None): self._p = period self._uEMA = EMA(period, cache_size) self._dEMA = EMA(period, cache_size) self._prevInputValue = None super().__init__({ 'args': [period, cache_size], 'id': 'rsi', 'name': 'RSI(%f)' % (period), 'seed_period': period, 'cache_size': cache_size }) def reset(self): super().reset() self._prevInputValue = None self._uEMA.reset() self._dEMA.reset() def _ud(self, v): delta = 0 if self._prevInputValue is None: delta = v - self._prevInputValue return { 'u': delta if delta > 0 else 0, 'd': -delta if delta < 0 else 0 } def _rs(self): uAvg = self._uEMA.v() dAvg = self._dEMA.v() if not isfinite(uAvg) or not isfinite(dAvg) or dAvg == 0: return None else: return uAvg / dAvg def update(self, v): if self._prevInputValue is None: return ud = self._ud(v) self._uEMA.update(ud['u']) self._dEMA.update(ud['d']) rs = self._rs() if rs is not None: super().update(100 - (100 / (1 + rs))) return self.v() def add(self, v): if self._prevInputValue is None: self._prevInputValue = v ud = self._ud(v) self._uEMA.add(ud['u']) self._dEMA.add(ud['d']) rs = self._rs() if rs is not None: super().add(100 - (100 / (1 + rs))) self._prevInputValue = v return self.v()
class MACD(Indicator): def __init__(self, fastMA, slowMA, signalMA, cache_size=None): self._slowEMA = EMA([slowMA]) self._fastEMA = EMA([fastMA]) self._signalEMA = EMA([signalMA]) super().__init__({ 'args': [fastMA, slowMA, signalMA, cache_size], 'id': 'macd', 'name': 'MACD(%f, %f, %f)' % (fastMA, slowMA, signalMA), 'seed_period': max([fastMA, slowMA]) + signalMA, 'cache_size': cache_size }) def reset(self): super().reset() self._slowEMA.reset() self._fastEMA.reset() self._signalEMA.reset() def update(self, v): slowEMA = self._slowEMA.update(v) fastEMA = self._fastEMA.update(v) if not isfinite(slowEMA) or not isfinite(fastEMA): return macd = fastEMA - slowEMA signalEMA = self._signalEMA.update(macd) if not isfinite(signalEMA): return histogram = macd - signalEMA super().update({ 'macd': macd, 'signal': signalEMA, 'histogram': histogram }) return self.v() def add(self, v): slowEMA = self._slowEMA.add(v) fastEMA = self._fastEMA.add(v) if not isfinite(slowEMA) or not isfinite(fastEMA): return macd = fastEMA - slowEMA signalEMA = self._signalEMA.add(macd) if not isfinite(signalEMA): return histogram = macd - signalEMA super().add({ 'macd': macd, 'signal': signalEMA, 'histogram': histogram }) return self.v()
class RVI(Indicator): def __init__(self, period, cache_size=None): self._stddev = StdDeviation(period, cache_size) self._uEMA = EMA(period, cache_size) self._dEMA = EMA(period, cache_size) self._prevInputValue = None super().__init__({ 'args': [period, cache_size], 'id': 'rvi', 'name': 'RVI(%f)' % period, 'seed_period': period, 'cache_size': cache_size }) def reset(self): super().reset() self._prevInputValue = None self._stddev.reset() self._uEMA.reset() self._dEMA.reset() def ud(candlePrice, prevCandlePrice, stddev): if prevCandlePrice is None: return [0, 0] elif candlePrice > prevCandlePrice: return [stddev, 0] elif candlePrice < prevCandlePrice: return [0, stddev] else: return [0, 0] def update(self, v): if self._prevInputValue is None: return self.v() self._stddev.update(v) stddev = self._stddev.v() if not isfinite(stddev): return self.v() [u, d] = RVI.ud(v, self._prevInputValue, stddev) self._uEMA.update(u) self._dEMA.update(d) uSum = self._uEMA.v() dSum = self._dEMA.v() if uSum == dSum: return super().update(0) else: return super().update(100 * (uSum / (uSum + dSum))) def add(self, v): if self._prevInputValue is None: self._prevInputValue = v return self.v() self._stddev.add(v) stddev = self._stddev.v() if not isfinite(stddev): return self.v() [u, d] = RVI.ud(v, self._prevInputValue, stddev) self._uEMA.add(u) self._dEMA.add(d) uSum = self._uEMA.v() dSum = self._dEMA.v() if uSum == dSum: super().add(0) else: super().add(100 * (uSum / (uSum + dSum))) self._prevInputValue = v return self.v()
class TSI(Indicator): def __init__(self, long, short, signal, cache_size=None): self._pcEMA = EMA(long, cache_size) self._pc2EMA = EMA(short, cache_size) self._apcEMA = EMA(long, cache_size) self._apc2EMA = EMA(short, cache_size) self._sEMA = EMA(signal, cache_size) self._lastPrice = None super().__init__({ 'args': [short, signal, cache_size], 'id': 'tsi', 'name': 'TSI(%f, %f, %f)' % (long, short, signal), 'seed_period': max([long, short, signal]), 'cache_size': cache_size }) def reset(self): super().reset() self._pcEMA.reset() self._pc2EMA.reset() self._apcEMA.reset() self._apc2EMA.reset() self._sEMA.reset() self._lastPrice = None def update(self, v): if self._lastPrice is None: return self.v() pc = v - self._lastPrice apc = abs(v - self._lastPrice) self._pcEMA.update(pc) self._apcEMA.update(apc) if self._pcEMA.ready(): self._pc2EMA.update(self._pcEMA.v()) else: return self.v() if self._apcEMA.ready(): self._apc2EMA.update(self._apcEMA.v()) else: return self.v() if not self._pc2EMA.ready() or not self._apc2EMA.ready(): return self.v() tsi = 100 * (self._pc2EMA.v() / self._apc2EMA.v()) self._sEMA.update(tsi) return super().update({'v': tsi, 'signal': self._sEMA.v()}) def add(self, v): if self._lastPrice is None: self._lastPrice = v return self.v() pc = v - self._lastPrice apc = abs(v - self._lastPrice) self._pcEMA.add(pc) self._apcEMA.add(apc) if self._pcEMA.ready(): self._pc2EMA.add(self._pcEMA.v()) else: return self.v() if self._apcEMA.ready(): self._apc2EMA.add(self._apcEMA.v()) else: return self.v() if not self._pc2EMA.ready() or not self._apc2EMA.ready(): return self.v() tsi = 100 * (self._pc2EMA.v() / self._apc2EMA.v()) self._sEMA.add(tsi) super().add({'v': tsi, 'signal': self._sEMA.v()}) self._lastPrice = v return self.v()