def data_to_indicators(data, o, h, l, c, v, window) -> pd.DataFrame: """ Given a DataFrame of stock prices, return the data along with the corresponding indicators :param data: Data in C-OHLV format :param window: default value of window for indicators (only for indicators that support this) :param o: name of column containing 'OPEN' values :param h: name of column containing 'HIGH' values :param l: name of column containing 'LOW' values :param c: name of column containing 'CLOSE' values :param v: name of column containing 'VOLUME' values :return: DataFrame with all indicators """ df = data.reset_index(drop=True) # Momentum # TODO PMO df['macd_' + str(window)] = macd(df[c], n_fast=int(window / 2), n_slow=window) df['rsi_' + str(window)] = rsi(df[c], n=window) df['wr_' + str(window)] = wr(df[h], df[l], df[c], lbp=window) df['mfi_' + str(window)] = money_flow_index(df[h], df[l], df[c], df[v], n=window) df['stochk_' + str(window)] = stoch(df[h], df[l], df[c], n=window) df['stochd_' + str(window)] = stoch_signal(df[h], df[l], df[c], n=window, d_n=3) # ROC df['roc_' + str(window)] = [(df[c][i] - df[c][i - window]) / df[c][i - window] if i >= window else np.nan for i in range(0, df[c].size)] # Smoothing df['sma_' + str(window)] = simple_moving_average.simple_moving_average(df[c], period=window) df['wma_' + str(window)] = weighted_moving_average.weighted_moving_average(df[c], period=window) df['ema_' + str(window)] = exponential_moving_average.exponential_moving_average(np.array(df[c]), period=window) df['hma_' + str(window)] = hull_moving_average.hull_moving_average(np.array(df[c]), period=window) # df['cma_' + str(window)] = [df[c][i - int(window / 2): i + int(window / 2)].mean() # if (i >= int(window / 2) and (i + int(window / 2)) < df[c].size) else np.nan # for i in range(0, df[c].size)] # Overbought/Oversold Signals df['cci_' + str(window)] = cci(df[h], df[l], df[c], n=window, c=0.015) # Volume df['adl'] = acc_dist_index(df[h], df[l], df[c], df[v]) df['cmf_' + str(window)] = chaikin_money_flow(df[h], df[l], df[c], df[v], n=window) df['obv'] = on_balance_volume(df[c], df[v]) df['emv_' + str(window)] = ease_of_movement(df[h], df[l], df[c], df[v], n=window) # Volatility df['atr_' + str(window)] = average_true_range(df[h], df[l], df[c], n=window) df['mass_ind_' + str(window)] = mass_index(df[h], df[l], n=window / 2, n2=window) # Trends # How will model know b/w Ichmoku A and B? df['ichimoku_a'] = ichimoku_a(df[h], df[l], n1=9, n2=26) df['ichimoku_b'] = ichimoku_b(df[h], df[l], n2=26, n3=52) series_aroon_up = aroon_up(df[c], n=window) series_aroon_down = aroon_down(df[c], n=window) df['aroon_ind_' + str(window)] = series_aroon_up - series_aroon_down df['adx_' + str(window)] = adx(df[h], df[l], df[c], n=window) return df
def test_hma_period_10(self): period = 10 hma = hull_moving_average.hull_moving_average(self.data, period) np.testing.assert_array_equal(hma, self.hma_period_10_expected)
def test_hull_moving_average_invalid_period(self): period = 128 with self.assertRaises(Exception) as cm: hull_moving_average.hull_moving_average(self.data, period) expected = "Error: data_len < period" self.assertEqual(str(cm.exception), expected)
def analyze(signal): """ Analyze data """ def calc_rsi(prices, n=14): deltas = np.diff(prices) seed = deltas[:n + 1] up = seed[seed >= 0].sum() / n down = -seed[seed < 0].sum() / n rs = up / down rsi = np.zeros_like(prices) rsi[:n] = 100. - 100. / (1. + rs) for i in range(n, len(prices)): delta = deltas[i - 1] # cause the diff is 1 shorter if delta > 0: upval = delta downval = 0. else: upval = 0. downval = -delta up = (up * (n - 1) + upval) / n down = (down * (n - 1) + downval) / n rs = up / down rsi[i] = 100. - 100. / (1. + rs) return rsi def get_last_peak(data): np_data = np.array(data) peaks = (np_data >= np.roll(np_data, 1)) & (np_data > np.roll( np_data, -1)) peaks = list(peaks[1:len(peaks) - 1]) idx = len(peaks) - peaks[::-1].index(True) return DictMap({'index': idx, 'value': data[idx]}) def get_last_trough(data): np_data = np.array(data) troughs = (np_data <= np.roll(np_data, 1)) & (np_data < np.roll( np_data, -1)) troughs = list(troughs[1:len(troughs) - 1]) idx = len(troughs) - troughs[::-1].index(True) return DictMap({'index': idx, 'value': data[idx]}) data = list(signal) ema = exponential_moving_average(data[-EMA_PERIOD:], EMA_PERIOD)[-1] if Trader.selling_analyzed_data: hull_data = hull_moving_average(data[-(HULL_PERIOD + 30):], HULL_PERIOD) else: hull_data = hull_moving_average(data, HULL_PERIOD) # @TODO: clean up the code sell_now = False if not Trader.selling_analyzed_data: # first time hd = [x for x in hull_data if x >= 0] last_peak = get_last_peak(hd) last_trough = get_last_trough(hd) if last_peak.index > last_trough.index: Trader.selling_analyzed_data.last_is_trough = False else: Trader.selling_analyzed_data.last_is_trough = True Trader.selling_analyzed_data.peak = last_peak.value Trader.selling_analyzed_data.trough = last_trough.value Trader.selling_analyzed_data.previous_peak = None Trader.selling_analyzed_data.previous_trough = None Trader.selling_analyzed_data.last = hull_data[-1] else: last = hull_data[-1] height = Trader.selling_analyzed_data.peak - Trader.selling_analyzed_data.trough if Trader.selling_analyzed_data.last_is_trough: retrace_height = last - Trader.selling_analyzed_data.trough else: retrace_height = Trader.selling_analyzed_data.peak - last retrace_perc = retrace_height / height * 100.0 if Trader.selling_analyzed_data.last_is_trough: if retrace_perc < 0: Trader.selling_analyzed_data.last_is_trough = False if Trader.selling_analyzed_data.previous_trough: Trader.selling_analyzed_data.trough = Trader.selling_analyzed_data.previous_trough if last < Trader.selling_analyzed_data.last: if retrace_perc > IGNORE_SMALL_PEAK_PERCENTAGE: Trader.selling_analyzed_data.last_is_trough = False Trader.selling_analyzed_data.previous_peak = Trader.selling_analyzed_data.peak Trader.selling_analyzed_data.peak = Trader.selling_analyzed_data.last else: if retrace_perc < 0: Trader.selling_analyzed_data.last_is_trough = True if Trader.selling_analyzed_data.previous_peak: Trader.selling_analyzed_data.peak = Trader.selling_analyzed_data.previous_peak if last > Trader.selling_analyzed_data.last: # got a new reversal if retrace_perc > IGNORE_SMALL_PEAK_PERCENTAGE: Trader.selling_analyzed_data.last_is_trough = True Trader.selling_analyzed_data.previous_trough = Trader.selling_analyzed_data.trough Trader.selling_analyzed_data.trough = Trader.selling_analyzed_data.last if retrace_perc >= SELL_MAX_RETRACEMENT_PERCENTAGE: sell_now = True Trader.selling_analyzed_data.last = last Trader.logger.debug("selling analyze data: %s" % str(Trader.selling_analyzed_data)) rsi = calc_rsi(data[-(RSI_PERIOD + 1):], RSI_PERIOD)[-1] ma_spread = 100 * (ema / hull_data[-1] - 1) Trader.logger.debug("ema - rsi - ma_spread: %s - %s - %s" % (str(ema), str(rsi), str(ma_spread))) buy_now = False if rsi < RSI_OVERSOLD_PERCENTAGE and ma_spread > MIN_MA_SPREAD and hull_data[ -1] <= hull_data[-2]: Trader.buy_now_tracking = True else: if Trader.buy_now_tracking and hull_data[-1] > hull_data[ -2] and Trader.selling_analyzed_data.last_is_trough: height = Trader.selling_analyzed_data.peak - Trader.selling_analyzed_data.trough retrace_height = last - Trader.selling_analyzed_data.trough retrace_perc = retrace_height / height * 100.0 if retrace_perc >= BUY_MAX_RETRACEMENT_PERCENTAGE: buy_now = True Trader.buy_now_tracking = False return DictMap({ 'buy_now': buy_now, 'sell_now': sell_now, 'ema': ema, 'hull': hull_data[-1], 'close': data[-1] })