def preProcessCalculation(df, limit): df = df.reset_index() adx = np.array( average_directional_index(df['close'], df['high'], df['low'], limit)) mfi = np.array( money_flow_index(df['close'], df['high'], df['low'], df['volume'], limit - 1)) atr = np.array(average_true_range(df['close'], limit)) obv = np.array(on_balance_volume(df['close'], df['volume'])) rocr = np.array(rate_of_change(df['close'], limit)) mom = np.array(momentum(df['close'], limit)) return adx, mfi, atr, obv, rocr, mom
def double_top_double_bottom(key, price_action, time_frame): #To determine up/down trend and the strength pdi = np.array( positive_directional_index(price_action[id.close], price_action[id.high], price_action[id.low], id.window_size)) ndi = np.array( negative_directional_index(price_action[id.close], price_action[id.high], price_action[id.low], id.window_size)) adx = np.array( average_directional_index(price_action[id.close], price_action[id.high], price_action[id.low], id.window_size)) obv = np.array( on_balance_volume(price_action[id.close], price_action[id.volume])) #Calculate the local maxima and minima in the window frame local_minima, local_maxima, indices_minima, indices_maxima = get_local_min_max( np.array(price_action[id.high])) notifier = {values.double_top: False, values.double_bottom: False} if pdi[len(pdi) - 1] > ndi[len(ndi) - 1] and adx[len(adx) - 1] >= 25: notifier[values.double_top] = check_double_top(price_action, indices_maxima, obv) if pdi[len(pdi) - 1] < ndi[len(ndi) - 1] and adx[len(adx) - 1] >= 25: notifier[values.double_bottom] = check_double_bottom( price_action, indices_minima, obv) if notifier[values.double_top]: db.insert_strategy(key, time_frame, values.double_top, price_action.iloc[-1][id.time]) if notifier[values.double_bottom]: db.insert_strategy(key, time_frame, values.double_bottom, price_action.iloc[-1][id.time])
def update_indicator(csv_filename, periods, timeframe, datetimeformat_string): """ Update the given csv_file with new column values for corr rows """ df_csv = pd.read_csv(csv_filename, index_col=None, dayfirst=True) df_csv.drop_duplicates(subset=['coin', 'exchange', 'unix_timestamp'], inplace=True) for indicator in indicator_list: if indicator not in df_csv.columns and indicator not in df_csv.index: df_csv[indicator] = np.nan df_csv = df_csv.set_index(['coin', 'exchange', 'unix_timestamp']) data = list(df_csv.index.get_level_values(0).unique()) i = 0 j = 0 for coin_name in data: coin_df = df_csv[df_csv.index.get_level_values(0) == coin_name] coin_df = coin_df.reset_index() coin_df = coin_df.sort_values( by=['exchange', 'unix_timestamp']).set_index( ['coin', 'exchange', 'unix_timestamp']) df_by_exchange = coin_df.groupby(['exchange'], group_keys=False) for key, item in df_by_exchange: req_data = df_by_exchange.get_group(key) req_data2 = req_data.iloc[-periods:] start_date = req_data2.index.get_level_values(2)[0] end_date = req_data2.index.get_level_values(2)[req_data2.shape[0] - 1] req_data2 = req_data[ (req_data.index.get_level_values(2) >= start_date) & (req_data.index.get_level_values(2) <= end_date)] np_volumeto = np.array(req_data2.volumeto.values, dtype='f8') if len(np_volumeto) < 20: j = j + 1 print(coin_name, j, " Not Updated") continue req_data2[ 'BBANDS_BANDWIDTH_PERCENT'] = pyti.bollinger_bands.percent_b( req_data2.close.values, 20) req_data2['MONEY_FLOW_INDEX'] = money_flow_index.money_flow_index( req_data2.close.values, req_data2.high.values, req_data2.low.values, np_volumeto, 14) req_data2[ 'STOCH_PERCENT_K_MONEY_FLOW_INDEX'] = pyti.stochastic.percent_k( req_data2.MONEY_FLOW_INDEX.values, 14) * 100 req_data2[ 'STOCH_PERCENT_D_MONEY_FLOW_INDEX'] = pyti.simple_moving_average.simple_moving_average( req_data2.STOCH_PERCENT_K_MONEY_FLOW_INDEX.values, 3) req_data2['RSI'] = talib.func.RSI(req_data2.close.values, timeperiod=configParser.getint( 'technical_settings', 'rsi_period')) req_data2['RSI_OVER_BOUGHT'] = np.where( (req_data2.RSI >= configParser.getint('technical_settings', 'rsi_over_bought')) & (req_data2.RSI <= req_data2.RSI.shift(1)), 1, 0) req_data2['RSI_OVER_SOLD'] = np.where( (req_data2.RSI <= configParser.getint('technical_settings', 'rsi_over_sold')) & (req_data2.RSI >= req_data2.RSI.shift(1)), 1, 0) req_data2['STOCHRSI_K'] = pyti.stochrsi.stochrsi( req_data2.close.values, 14) req_data2[ 'STOCHRSI_D'] = pyti.simple_moving_average.simple_moving_average( req_data2.STOCHRSI_K.values, 3) req_data2['STOCH_PERCENT_K'] = pyti.stochastic.percent_k( req_data2.high.values, 14) * 100 req_data2[ 'STOCH_PERCENT_D'] = pyti.simple_moving_average.simple_moving_average( req_data2.STOCH_PERCENT_K.values, 3) req_data2['STOCH_OVER_BOUGHT'] = np.where( (req_data2.STOCH_PERCENT_K >= configParser.getint( 'technical_settings', 'stoch_over_bought')) & (req_data2.STOCH_PERCENT_K <= req_data2.STOCH_PERCENT_K.shift(1)), 1, 0) req_data2['STOCH_OVER_SOLD'] = np.where( (req_data2.STOCH_PERCENT_K <= configParser.getint( 'technical_settings', 'stoch_over_sold')) & (req_data2.STOCH_PERCENT_K >= req_data2.STOCH_PERCENT_K.shift(1)), 1, 0) req_data2['SMA_FAST'] = talib.func.SMA(req_data2.close.values, 7) req_data2['SMA_SLOW'] = talib.func.SMA(req_data2.close.values, 21) req_data2['SMA_TEST'] = np.where( req_data2.SMA_FAST > req_data2.SMA_SLOW, 1, 0) req_data2[ 'ON_BALANCE_VOLUME'] = on_balance_volume.on_balance_volume( req_data2.close.values, np_volumeto) req_data2['ON_BALANCE_VOLUME_TEST'] = np.where( req_data2.ON_BALANCE_VOLUME > req_data2.ON_BALANCE_VOLUME.shift(1), 1, 0) req_data2['MACD'], req_data2[ 'MACD_SIGNAL'], MACD_HISTOGRAM = talib.func.MACD( req_data2.close.values, fastperiod=configParser.getint('technical_settings', 'macd_fast'), slowperiod=configParser.getint('technical_settings', 'macd_slow'), signalperiod=configParser.getint('technical_settings', 'macd_signal')) req_data2['MACD_TEST'] = np.where( req_data2.MACD > req_data2.MACD_SIGNAL, 1, 0) df_csv.update(req_data2) i = i + 1 df_csv.to_csv(csv_filename, date_format=datetimeStringformat_to_csv) df_csv = pd.read_csv(csv_filename) dbClient.save_to_db(df_csv, 'technical data')
def _get_ta_features(high, low, close, volume, desc): """ Returns a dict containing the technical analysis indicators calculated on the given high, low, close and volumes. """ ta = {} # Set numpy to ignore division error and invalid values (since not all features are complete) old_settings = np.seterr(divide='ignore', invalid='ignore') record_count = len(close) # Determine relative moving averages for _short, _long in desc['rsma']: if record_count < _short or record_count < _long: logging.error( "get_ta_features: not enough records for rsma (short={}, long={}, records={})" .format(_short, _long, record_count)) continue ta['rsma_{}_{}'.format(_short, _long)] = relative_sma(close, _short, _long) for _short, _long in desc['rema']: if record_count < _short or record_count < _long: logging.error( "get_ta_features: not enough records for rema (short={}, long={}, records={})" .format(_short, _long, record_count)) continue ta['rema_{}_{}'.format(_short, _long)] = relative_ema(close, _short, _long) # MACD Indicator if 'macd' in desc: for _short, _long in desc['macd']: if record_count < _short or record_count < _long: logging.error( "get_ta_features: not enough records for rema (short={}, long={}, records={})" .format(_short, _long, record_count)) continue ta['macd_{}_{}'.format( _short, _long)] = moving_average_convergence_divergence( close, _short, _long) # Aroon Indicator if 'ao' in desc: for _period in desc['ao']: if record_count < _period: logging.error( "get_ta_features: not enough records for ao (period={}, records={})" .format(_period, record_count)) continue ta['ao_{}'.format(_period)] = aroon_oscillator(close, _period) # Average Directional Movement Index (ADX) if 'adx' in desc: for _period in desc['adx']: if record_count < _period: logging.error( "get_ta_features: not enough records for adx (period={}, records={})" .format(_period, record_count)) continue ta['adx_{}'.format(_period)] = average_directional_index( close, high, low, _period) # Difference between Positive Directional Index(DI+) and Negative Directional Index(DI-) if 'wd' in desc: for _period in desc['wd']: if record_count < _period: logging.error( "get_ta_features: not enough records for wd (period={}, records={})" .format(_period, record_count)) continue ta['wd_{}'.format(_period)] = \ positive_directional_index(close, high, low, _period) \ - negative_directional_index(close, high, low, _period) # Percentage Price Oscillator if 'ppo' in desc: for _short, _long in desc['ppo']: if record_count < _short or record_count < _long: logging.error( "get_ta_features: not enough records for ppo (short={}, long={}, records={})" .format(_short, _long, record_count)) continue ta['ppo_{}_{}'.format(_short, _long)] = price_oscillator( close, _short, _long) # Relative Strength Index if 'rsi' in desc: for _period in desc['rsi']: if record_count < _period: logging.error( "get_ta_features: not enough records for rsi (period={}, records={})" .format(_period, record_count)) continue ta['rsi_{}'.format(_period)] = relative_strength_index( close, _period) # Money Flow Index if 'mfi' in desc: for _period in desc['mfi']: if record_count < _period: logging.error( "get_ta_features: not enough records for mfi (period={}, records={})" .format(_period, record_count)) continue ta['mfi_{}'.format(_period)] = money_flow_index( close, high, low, volume, _period) # True Strength Index if 'tsi' in desc and len(close) >= 40: if record_count < 40: logging.error( "get_ta_features: not enough records for tsi (period={}, records={})" .format(40, record_count)) else: ta['tsi'] = true_strength_index(close) if 'boll' in desc: for _period in desc['stoch']: if record_count < _period: logging.error( "get_ta_features: not enough records for boll (period={}, records={})" .format(_period, record_count)) continue ta['boll_{}'.format(_period)] = percent_b(close, _period) # Stochastic Oscillator if 'stoch' in desc: for _period in desc['stoch']: if record_count < _period: logging.error( "get_ta_features: not enough records for stoch (period={}, records={})" .format(_period, record_count)) continue ta['stoch_{}'.format(_period)] = percent_k(close, _period) # ta.py['stoch'] = percent_k(high, low, close, 14) # Chande Momentum Oscillator ## Not available in ta.py if 'cmo' in desc: for _period in desc['cmo']: if record_count < _period: logging.error( "get_ta_features: not enough records for cmo (period={}, records={})" .format(_period, record_count)) continue ta['cmo_{}'.format(_period)] = chande_momentum_oscillator( close, _period) # Average True Range Percentage if 'atrp' in desc: for _period in desc['atrp']: if record_count < _period: logging.error( "get_ta_features: not enough records for atrp (period={}, records={})" .format(_period, record_count)) continue ta['atrp_{}'.format(_period)] = average_true_range_percent( close, _period) # Percentage Volume Oscillator if 'pvo' in desc: for _short, _long in desc['pvo']: if record_count < _short or record_count < _long: logging.error( "get_ta_features: not enough records for pvo (short={}, long={}, records={})" .format(_short, _long, record_count)) continue ta['pvo_{}_{}'.format(_short, _long)] = volume_oscillator( volume, _short, _long) # Force Index if 'fi' in desc: fi = force_index(close, volume) for _period in desc['fi']: if record_count < _period: logging.error( "get_ta_features: not enough records for atrp (period={}, records={})" .format(_period, record_count)) continue ta['fi_{}'.format(_period)] = exponential_moving_average( fi, _period) # Accumulation Distribution Line if 'adi' in desc: ta['adi'] = accumulation_distribution(close, high, low, volume) # On Balance Volume if 'obv' in desc: ta['obv'] = on_balance_volume(close, volume) # Restore numpy error settings np.seterr(**old_settings) return ta
def test_obv_invalid_data(self): self.close_data.append(0) with self.assertRaises(Exception) as cm: on_balance_volume.on_balance_volume(self.close_data, self.volume) expected = "Error: mismatched data lengths, check to ensure that all input data is the same length and valid" self.assertEqual(str(cm.exception), expected)
def test_obv(self): obv = on_balance_volume.on_balance_volume(self.close_data, self.volume) np.testing.assert_array_equal(obv, self.obv_expected)