def money_flow_index(close_data, high_data, low_data, volume, period): """ Money Flow Index. Formula: MFI = 100 - (100 / (1 + PMF / NMF)) """ catch_errors.check_for_input_len_diff( close_data, high_data, low_data, volume ) catch_errors.check_for_period_error(close_data, period) mf = money_flow(close_data, high_data, low_data, volume) tp = typical_price(close_data, high_data, low_data) flow = [tp[idx] > tp[idx-1] for idx in range(1, len(tp))] pf = [mf[idx] if flow[idx] else 0 for idx in range(0, len(flow))] nf = [mf[idx] if not flow[idx] else 0 for idx in range(0, len(flow))] pmf = [sum(pf[idx+1-period:idx+1]) for idx in range(period-1, len(pf))] nmf = [sum(nf[idx+1-period:idx+1]) for idx in range(period-1, len(nf))] # Dividing by 0 is not an issue, it turns the value into NaN which we would # want in that case with warnings.catch_warnings(): warnings.simplefilter("ignore", category=RuntimeWarning) money_ratio = np.array(pmf) / np.array(nmf) mfi = 100 - (100 / (1 + money_ratio)) mfi = fill_for_noncomputable_vals(close_data, mfi) return mfi
def true_strength_index(close_data): """ True Strength Index. Double Smoothed PC ------------------ PC = Current Price minus Prior Price First Smoothing = 25-period EMA of PC Second Smoothing = 13-period EMA of 25-period EMA of PC Double Smoothed Absolute PC --------------------------- Absolute Price Change |PC| = Absolute Value of Current Price minus Prior Price First Smoothing = 25-period EMA of |PC| Second Smoothing = 13-period EMA of 25-period EMA of |PC| TSI = 100 x (Double Smoothed PC / Double Smoothed Absolute PC) """ if len(close_data) < 40: raise RuntimeError("Data must have at least 40 items") pc = np.diff(close_data, 1) apc = np.abs(pc) num = ema(pc, 25) num = ema(num, 13) den = ema(apc, 25) den = ema(den, 13) tsi = 100 * num / den tsi = fill_for_noncomputable_vals(close_data, tsi) return tsi
def chaikin_money_flow(close_data, high_data, low_data, volume, period): """ Chaikin Money Flow. Formula: CMF = SUM[(((Cn - Ln) - (Hn - Cn)) / (Hn - Ln)) * V] / SUM(Vn) """ catch_errors.check_for_input_len_diff(close_data, high_data, low_data, volume) catch_errors.check_for_period_error(close_data, period) close_data = np.array(close_data) high_data = np.array(high_data) low_data = np.array(low_data) volume = np.array(volume) cmf = [ sum((((close_data[idx + 1 - period:idx + 1] - low_data[idx + 1 - period:idx + 1]) - (high_data[idx + 1 - period:idx + 1] - close_data[idx + 1 - period:idx + 1])) / (high_data[idx + 1 - period:idx + 1] - low_data[idx + 1 - period:idx + 1])) * volume[idx + 1 - period:idx + 1]) / sum(volume[idx + 1 - period:idx + 1]) for idx in range(period - 1, len(close_data)) ] cmf = fill_for_noncomputable_vals(close_data, cmf) return cmf
def relative_ema(data, short, long): ema_short = exponential_moving_average(data, period=short) ema_long = exponential_moving_average(data, period=long) with warnings.catch_warnings(): warnings.simplefilter("ignore", category=RuntimeWarning) emadiff = ema_short - ema_long rema = np.divide(emadiff, ema_long) return fill_for_noncomputable_vals(data, rema)
def relative_sma(data, short, long): sma_short = simple_moving_average(data, period=short) sma_long = simple_moving_average(data, period=long) with warnings.catch_warnings(): warnings.simplefilter("ignore", category=RuntimeWarning) smadiff = sma_short - sma_long rsma = np.divide(smadiff, sma_long) return fill_for_noncomputable_vals(data, rsma)
def relative_strength_index(self, data, period): """ Relative Strength Index. Formula: RSI = 100 - (100 / 1 + (prevGain/prevLoss)) """ catch_errors.check_for_period_error(data, period) period = int(period) self.changes = [ data_tup[1] - data_tup[0] for data_tup in zip(data[::1], data[1::1]) ] filtered_gain = [val < 0 for val in self.changes] self.gains = [ 0 if filtered_gain[idx] is True else self.changes[idx] for idx in range(0, len(filtered_gain)) ] filtered_loss = [val > 0 for val in self.changes] self.losses = [ 0 if filtered_loss[idx] is True else abs(self.changes[idx]) for idx in range(0, len(filtered_loss)) ] self.avg_gain = np.mean(self.gains[:period]) self.avg_loss = np.mean(self.losses[:period]) # first value rsi = [] if self.avg_loss == 0: rsi.append(100) else: rs = self.avg_gain / self.avg_loss rsi.append(100 - (100 / (1 + rs))) # others for idx in range(1, len(data) - period): avg_gain = ((self.avg_gain * (period - 1) + self.gains[idx + (period - 1)]) / period) avg_loss = ((self.avg_loss * (period - 1) + self.losses[idx + (period - 1)]) / period) if avg_loss == 0: rsi.append(100) else: rs = avg_gain / avg_loss rsi.append(100 - (100 / (1 + rs))) rsi = fill_for_noncomputable_vals(data, rsi) self.rsi = rsi return rsi
def conversion_base_line_helper(data, period): """ The only real difference between TenkanSen and KijunSen is the period value """ catch_errors.check_for_period_error(data, period) cblh = [(np.max(data[idx+1-period:idx+1]) + np.min(data[idx+1-period:idx+1])) / 2 for idx in range(period-1, len(data))] cblh = fill_for_noncomputable_vals(data, cblh) return cblh
def avg_helper(close_data, low_data, period): catch_errors.check_for_input_len_diff(close_data, low_data) catch_errors.check_for_period_error(close_data, period) bp = buying_pressure(close_data, low_data) tr = true_range(close_data, period) avg = map( lambda idx: sum(bp[idx + 1 - period:idx + 1]) / sum(tr[ idx + 1 - period:idx + 1]), range(period - 1, len(close_data))) avg = fill_for_noncomputable_vals(close_data, avg) return avg
def stochrsi(data, period): """ StochRSI. Formula: SRSI = ((RSIt - RSI LOW) / (RSI HIGH - LOW RSI)) * 100 """ rsi = relative_strength_index(data, period)[period:] stochrsi = map(lambda idx: 100 * ((rsi[idx] - np.min(rsi[idx+1-period:idx+1])) / (np.max(rsi[idx+1-period:idx+1]) - np.min(rsi[idx+1-period:idx+1]))), range(period-1, len(rsi))) stochrsi = fill_for_noncomputable_vals(data, stochrsi) return stochrsi
def detrended_price_oscillator(data, period): """ Detrended Price Oscillator. Formula: DPO = DATA[i] - Avg(DATA[period/2 + 1]) """ catch_errors.check_for_period_error(data, period) period = int(period) dop = [data[idx] - np.mean(data[idx+1-(int(period/2)+1):idx+1]) for idx in range(period-1, len(data))] dop = fill_for_noncomputable_vals(data, dop) return dop
def momentum(data, period): """ Momentum. Formula: DATA[i] - DATA[i - period] """ catch_errors.check_for_period_error(data, period) momentum = [data[idx] - data[idx+1-period] for idx in range(period-1, len(data))] momentum = fill_for_noncomputable_vals(data, momentum) return momentum
def rate_of_change(data, period): """ Rate of Change. Formula: (Close - Close n periods ago) / (Close n periods ago) * 100 """ catch_errors.check_for_period_error(data, period) rocs = [((data[idx] - data[idx - (period - 1)]) / data[idx - (period - 1)]) * 100 for idx in range(period - 1, len(data))] rocs = fill_for_noncomputable_vals(data, rocs) return rocs
def standard_variance(data, period): """ Standard Variance. Formula: (Ct - AVGt)^2 / N """ catch_errors.check_for_period_error(data, period) sv = map(lambda idx: np.var(data[idx + 1 - period:idx + 1], ddof=1), range(period - 1, len(data))) sv = fill_for_noncomputable_vals(data, sv) return sv
def buying_pressure(close_data, low_data): """ Buying Pressure. Formula: BP = current close - min() """ catch_errors.check_for_input_len_diff(close_data, low_data) bp = map( lambda idx: close_data[idx] - np.min( [low_data[idx], close_data[idx - 1]]), range(1, len(close_data))) bp = fill_for_noncomputable_vals(close_data, bp) return bp
def percent_k(data, period): """ %K. Formula: %k = data(t) - low(n) / (high(n) - low(n)) """ percent_k = [ ((data['Close'][idx] - np.min(data['Low'][idx + 1 - period:idx + 1])) / (np.max(data['High'][idx + 1 - period:idx + 1]) - np.min(data['Low'][idx + 1 - period:idx + 1]))) for idx in range(period - 1, len(data['Close'])) ] percent_k = fill_for_noncomputable_vals(data['Close'], percent_k) return percent_k
def standard_deviation(data, period): """ Standard Deviation. Formula: std = sqrt(avg(abs(x - avg(x))^2)) """ catch_errors.check_for_period_error(data, period) stds = map(lambda idx: np.std(data[idx + 1 - period:idx + 1], ddof=1), range(period - 1, len(data))) stds = fill_for_noncomputable_vals(data, stds) return stds
def smoothed_moving_average(data, period): """ Smoothed Moving Average. Formula: smma = avg(data(n)) - avg(data(n)/n) + data(t)/n """ catch_errors.check_for_period_error(data, period) smma = map( lambda idx: ((np.mean(data[idx - (period - 1):idx + 1]) - (np.mean( data[idx - (period - 1):idx + 1]) / period) + data[idx]) / period), range(0, len(data))) smma = fill_for_noncomputable_vals(data, smma) return smma
def aroon_down(data, period): """ Aroon Down. Formula: AROONDWN = (((PERIOD) - (PERIODS SINCE PERIOD LOW)) / (PERIOD)) * 100 """ catch_errors.check_for_period_error(data, period) period = int(period) a_down = [((period - data[idx + 1 - period:idx + 1].index( np.min(data[idx + 1 - period:idx + 1]))) / float(period)) * 100 for idx in range(period - 1, len(data))] a_down = fill_for_noncomputable_vals(data, a_down) return a_down
def percent_k(data, period): """ %K. Formula: %k = data(t) - low(n) / (high(n) - low(n)) """ catch_errors.check_for_period_error(data, period) percent_k = [((data[idx] - np.min(data[idx + 1 - period:idx + 1])) / (np.max(data[idx + 1 - period:idx + 1]) - np.min(data[idx + 1 - period:idx + 1]))) for idx in range(period - 1, len(data))] percent_k = fill_for_noncomputable_vals(data, percent_k) return percent_k
def aroon_up(data, period): """ Aroon Up. Formula: AROONUP = (((PERIOD) - (PERIODS since PERIOD high)) / (PERIOD)) * 100 """ catch_errors.check_for_period_error(data, period) period = int(period) a_up = [((period - data[idx + 1 - period:idx + 1].index( np.max(data[idx + 1 - period:idx + 1]))) / float(period)) * 100 for idx in range(period - 1, len(data))] a_up = fill_for_noncomputable_vals(data, a_up) return a_up
def simple_moving_average(data, period): """ Simple Moving Average. Formula: SUM(data / N) """ catch_errors.check_for_period_error(data, period) # Mean of Empty Slice RuntimeWarning doesn't affect output so it is # supressed with warnings.catch_warnings(): warnings.simplefilter("ignore", category=RuntimeWarning) sma = map(lambda idx: np.mean(data[idx - (period - 1):idx + 1]), range(0, len(data))) sma = fill_for_noncomputable_vals(data, sma) return sma
def volume_adjusted_moving_average(close, volume, n): try: avg_vol = np.mean(volume) vol_incr = avg_vol * 0.67 vol_ratio = [val / vol_incr for val in volume] close_vol = np.array(close) * vol_ratio vama = [ sum(close_vol[idx + 1 - n:idx + 1]) / n for idx in range(n - 1, len(close)) ] vama = fill_for_noncomputable_vals(close, vama) df = pd.DataFrame() df['value_adjusted_mavg'] = vama return df return df except Exception as e: raise (e)
def exponential_moving_average(data, period): """ Exponential Moving Average. Formula: p0 + (1 - w) * p1 + (1 - w)^2 * p2 + (1 + w)^3 * p3 +... / 1 + (1 - w) + (1 - w)^2 + (1 - w)^3 +... where: w = 2 / (N + 1) """ catch_errors.check_for_period_error(data, period) emas = map( lambda idx: exponential_moving_average_helper( data[idx - period + 1:idx + 1], period), range(period - 1, len(data))) emas = fill_for_noncomputable_vals(data, emas) return emas
def volume_adjusted_moving_average(close_data, volume, period): """ Volume Adjusted Moving Average. Formula: VAMA = SUM(CLOSE * VolumeRatio) / period """ catch_errors.check_for_input_len_diff(close_data, volume) catch_errors.check_for_period_error(close_data, period) avg_vol = np.mean(volume) vol_incr = avg_vol * 0.67 vol_ratio = [val / vol_incr for val in volume] close_vol = np.array(close_data) * vol_ratio vama = [sum(close_vol[idx+1-period:idx+1]) / period for idx in range(period-1, len(close_data))] vama = fill_for_noncomputable_vals(close_data, vama) return vama
def linear_weighted_moving_average(data, period): """ Linear Weighted Moving Average. Formula: LWMA = SUM(DATA[i]) * i / SUM(i) """ catch_errors.check_for_period_error(data, period) idx_period = list(range(1, period + 1)) lwma = [(sum([ i * idx_period[data[idx - (period - 1):idx + 1].index(i)] for i in data[idx - (period - 1):idx + 1] ])) / sum(range(1, len(data[idx + 1 - period:idx + 1]) + 1)) for idx in range(period - 1, len(data))] lwma = fill_for_noncomputable_vals(data, lwma) return lwma
def relative_strength_index(data, period): """ Relative Strength Index. Formula: RSI = 100 - (100 / 1 + (prevGain/prevLoss)) """ catch_errors.check_for_period_error(data, period) period = int(period) changes = [ data_tup[1] - data_tup[0] for data_tup in zip(data[::1], data[1::1]) ] gains = [0 if val < 0 else val for val in changes] losses = [0 if val > 0 else abs(val) for val in changes] avg_gain = np.mean(gains[:period]) avg_loss = np.mean(losses[:period]) rsi = [] if avg_loss == 0: rsi.append(100) else: rs = avg_gain / avg_loss rsi.append(100 - (100 / (1 + rs))) for idx in range(1, len(data) - period): avg_gain = ((avg_gain * (period - 1) + gains[idx + (period - 1)]) / period) avg_loss = ((avg_loss * (period - 1) + losses[idx + (period - 1)]) / period) if avg_loss == 0: rsi.append(100) else: rs = avg_gain / avg_loss rsi.append(100 - (100 / (1 + rs))) rsi = fill_for_noncomputable_vals(data, rsi) return rsi
def weighted_moving_average(data, period): """ Weighted Moving Average. Formula: (P1 + 2 P2 + 3 P3 + ... + n Pn) / K where K = (1+2+...+n) = n(n+1)/2 and Pn is the most recent price """ catch_errors.check_for_period_error(data, period) k = (period * (period + 1)) / 2.0 wmas = [] for idx in range(0, len(data)-period+1): product = [data[idx + period_idx] * (period_idx + 1) for period_idx in range(0, period)] wma = sum(product) / k wmas.append(wma) wmas = fill_for_noncomputable_vals(data, wmas) return wmas
def upper_bollinger_band(data, period, std_mult=2.0): """ Upper Bollinger Band. Formula: u_bb = SMA(t) + STD(SMA(t-n:t)) * std_mult """ catch_errors.check_for_period_error(data, period) period = int(period) simple_ma = sma(data, period)[period - 1:] upper_bb = [] for idx in range(len(data) - period + 1): std_dev = np.std(data[idx:idx + period]) upper_bb.append(simple_ma[idx] + std_dev * std_mult) upper_bb = fill_for_noncomputable_vals(data, upper_bb) return np.array(upper_bb)
def percent_k_pr(high_data, low_data, close_data, period): """ %K. Formula: %k = data(t) - low(n) / (high(n) - low(n)) """ # print (len(high_data)) # print (period) catch_errors.check_for_period_error(high_data, period) catch_errors.check_for_period_error(low_data, period) catch_errors.check_for_period_error(close_data, period) percent_k = [ ((close_data[idx] - np.min(low_data[idx + 1 - period:idx + 1])) / (np.max(high_data[idx + 1 - period:idx + 1]) - np.min(low_data[idx + 1 - period:idx + 1]))) for idx in range(period - 1, len(close_data)) ] percent_k = fill_for_noncomputable_vals(close_data, percent_k) return percent_k
def vertical_horizontal_filter(data, period): """ Vertical Horizontal Filter. Formula: ABS(pHIGH - pLOW) / SUM(ABS(Pi - Pi-1)) """ catch_errors.check_for_period_error(data, period) vhf = [ abs( np.max(data[idx + 1 - period:idx + 1]) - np.min(data[idx + 1 - period:idx + 1])) / sum([ abs(data[idx + 1 - period:idx + 1][i] - data[idx + 1 - period:idx + 1][i - 1]) for i in range(0, len(data[idx + 1 - period:idx + 1])) ]) for idx in range(period - 1, len(data)) ] vhf = fill_for_noncomputable_vals(data, vhf) return vhf