class DEMA(Indicator): """ Double Exponential Moving Average Output: a list of floats """ def __init__(self, period: int, input_values: List[float] = None, input_indicator: Indicator = None): super().__init__() self.period = period self.ema = EMA(period) self.add_sub_indicator(self.ema) self.ema_ema = EMA(period) self.add_managed_sequence(self.ema_ema) self.initialize(input_values, input_indicator) def _calculate_new_value(self) -> Any: if not self.ema.has_output_value(): return None self.ema_ema.add_input_value(self.ema[-1]) if not self.ema_ema.has_output_value(): return None return 2.0 * self.ema[-1] - self.ema_ema[-1]
class MassIndex(Indicator): """ Mass Index Output: a list of floats """ def __init__(self, ema_period: int, ema_ema_period: int, ema_ratio_period: int, input_values: List[OHLCV] = None): super().__init__() self.ema_ratio_period = ema_ratio_period self.ema = EMA(ema_period) self.ema_ema = EMA(ema_ema_period) self.ema_ratio = [] self.add_managed_sequence(self.ema) self.add_managed_sequence(self.ema_ema) self.add_managed_sequence(self.ema_ratio) self.initialize(input_values) def _calculate_new_value(self) -> Any: value = self.input_values[-1] self.ema.add_input_value(value.high - value.low) if not self.ema.has_output_value(): return None self.ema_ema.add_input_value(self.ema[-1]) if not self.ema_ema.has_output_value(): return None self.ema_ratio.append(self.ema[-1] / float(self.ema_ema[-1])) if len(self.ema_ratio) < self.ema_ratio_period: return None return sum(self.ema_ratio[-self.ema_ratio_period:])
class ChaikinOsc(Indicator): """ Chaikin Oscillator Output: a list of floats """ def __init__(self, period_fast: int, period_slow: int, input_values: List[OHLCV] = None): super().__init__() self.period_fast = period_fast self.period_slow = period_slow self.accu_dist = AccuDist() self.add_sub_indicator(self.accu_dist) self.ema_fast = EMA(period_fast) self.add_managed_sequence(self.ema_fast) self.ema_slow = EMA(period_slow) self.add_managed_sequence(self.ema_slow) self.initialize(input_values) def _calculate_new_value(self) -> Any: if not self.accu_dist.has_output_value(): return None self.ema_fast.add_input_value(self.accu_dist[-1]) self.ema_slow.add_input_value(self.accu_dist[-1]) if not self.ema_fast.has_output_value( ) or not self.ema_slow.has_output_value(): return None return self.ema_fast[-1] - self.ema_slow[-1]