示例#1
0
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
示例#2
0
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])
示例#3
0
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
示例#5
0
 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)
示例#6
0
 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)