def eval_impl(self): self.eval_note = START_PENDING_EVAL_NOTE period_length = 14 if len(self.data[ PriceIndexes.IND_PRICE_HIGH.value]) > period_length + 10: min_adx = 7.5 max_adx = 45 neutral_adx = 25 adx = tulipy.adx(self.data[PriceIndexes.IND_PRICE_HIGH.value], self.data[PriceIndexes.IND_PRICE_LOW.value], self.data[PriceIndexes.IND_PRICE_CLOSE.value], period_length) instant_ema = tulipy.ema( self.data[PriceIndexes.IND_PRICE_CLOSE.value], 2) slow_ema = tulipy.ema( self.data[PriceIndexes.IND_PRICE_CLOSE.value], 20) adx = DataUtil.drop_nan(adx) if len(adx): current_adx = adx[-1] current_slows_ema = slow_ema[-1] current_instant_ema = instant_ema[-1] multiplier = -1 if current_instant_ema < current_slows_ema else 1 # strong adx => strong trend if current_adx > neutral_adx: # if max adx already reached => when ADX forms a top and begins to turn down, you should look for a # retracement that causes the price to move toward its 20-day exponential moving average (EMA). adx_last_values = adx[-15:] adx_last_value = adx_last_values[-1] local_max_adx = adx_last_values.max() # max already reached => trend will slow down if adx_last_value < local_max_adx: self.eval_note = multiplier * ( current_adx - neutral_adx) / (local_max_adx - neutral_adx) # max not reached => trend will continue, return chances to be max now else: crossing_indexes = TrendAnalysis.get_threshold_change_indexes( adx, neutral_adx) chances_to_be_max = \ TrendAnalysis.get_estimation_of_move_state_relatively_to_previous_moves_length( crossing_indexes, adx) if len(crossing_indexes) > 2 \ else 0.75 proximity_to_max = min(1, current_adx / max_adx) self.eval_note = multiplier * proximity_to_max * chances_to_be_max # weak adx => change to come else: self.eval_note = multiplier * min(1, ( (neutral_adx - current_adx) / (neutral_adx - min_adx)))
async def evaluate(self, cryptocurrency, symbol, time_frame, close_candles, high_candles, low_candles, candle): self.eval_note = commons_constants.START_PENDING_EVAL_NOTE if len(close_candles) >= self.minimal_data: min_adx = 7.5 max_adx = 45 neutral_adx = 25 adx = tulipy.adx(high_candles, low_candles, close_candles, self.period_length) instant_ema = data_util.drop_nan(tulipy.ema(close_candles, 2)) slow_ema = data_util.drop_nan(tulipy.ema(close_candles, 20)) adx = data_util.drop_nan(adx) if len(adx): current_adx = adx[-1] current_slows_ema = slow_ema[-1] current_instant_ema = instant_ema[-1] multiplier = -1 if current_instant_ema < current_slows_ema else 1 # strong adx => strong trend if current_adx > neutral_adx: # if max adx already reached => when ADX forms a top and begins to turn down, you should look for a # retracement that causes the price to move toward its 20-day exponential moving average (EMA). adx_last_values = adx[-15:] adx_last_value = adx_last_values[-1] local_max_adx = adx_last_values.max() # max already reached => trend will slow down if adx_last_value < local_max_adx: self.eval_note = multiplier * ( current_adx - neutral_adx) / (local_max_adx - neutral_adx) # max not reached => trend will continue, return chances to be max now else: crossing_indexes = EvaluatorUtil.TrendAnalysis.get_threshold_change_indexes( adx, neutral_adx) chances_to_be_max = \ EvaluatorUtil.TrendAnalysis.get_estimation_of_move_state_relatively_to_previous_moves_length( crossing_indexes, adx) if len(crossing_indexes) > 2 else 0.75 proximity_to_max = min(1, current_adx / max_adx) self.eval_note = multiplier * proximity_to_max * chances_to_be_max # weak adx => change to come else: self.eval_note = multiplier * min(1, ( (neutral_adx - current_adx) / (neutral_adx - min_adx))) await self.evaluation_completed( cryptocurrency, symbol, time_frame, eval_time=evaluators_util.get_eval_time(full_candle=candle, time_frame=time_frame))
def test_adx(data): """Spot check against ti seems accurate, slight differences (1e-02) with Oanda display""" arr_high = data["high"].to_numpy().astype(float) arr_low = data["low"].to_numpy().astype(float) arr_close = data["close"].to_numpy().astype(float) ti_adx = np.append([np.nan for i in range(26)], ti.adx(arr_high, arr_low, arr_close, period=14)) adx = indicator.Indicate(data, exp=6)\ .average_directional_movement()['adx']\ .astype(float) assert np.allclose(ti_adx[-10:], adx[-10:], atol=1e-03, equal_nan=True)
def analyse(self): close = self.bars[:, 0].copy(order='C').astype('float64') high = self.bars[:, 3].copy(order='C').astype('float64') low = self.bars[:, 4].copy(order='C').astype('float64') if not (close.size + 2 - 2 * self.parameter > 0): raise RuntimeError my_result = ti.adx(high, low, close, self.parameter) median = np.median(my_result) if not np.isnan(median): self.calc = float(median) else: self.logger.warning("Data causes nan. {}".format(close)) return super(AdxFilter, self).analyse()
def calculate(self, candles): candles_len = len(candles) if candles_len < self.period + 20: #make sure 20 more candles are available to work with return 0 close_array = np.array( [float(x['ohlc'].close) for x in candles[-(self.period + 20):]]) high_array = np.array( [float(x['ohlc'].high) for x in candles[-(self.period + 20):]]) low_array = np.array( [float(x['ohlc'].low) for x in candles[-(self.period + 20):]]) #calculate adx = ti.adx(high_array, low_array, close_array, self.period) return adx[-1]
def get_ADX(high, low, close, signal): adx = np.zeros(len(high)) di = np.zeros([2,len(high)]) adx[signal*2-2:] = ti.adx(high, low, close, signal) di[:,signal-1:] = np.array(ti.di(high, low, close, signal)) return [adx, di[0], di[1]]
def add_adx(df, period=10): l = len(df.close.values) df[f'adx_{period}'] = pad_left(ti.adx( np.array(df.high), np.array(df.low), np.array(df.close), period), l)