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 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 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 typical_price(close_data, high_data, low_data): """ Typical Price. Formula: TPt = (HIGHt + LOWt + CLOSEt) / 3 """ catch_errors.check_for_input_len_diff(close_data, high_data, low_data) tp = [(high_data[idx] + low_data[idx] + close_data[idx]) / 3 for idx in range(0, len(close_data))] return np.array(tp)
def money_flow(close_data, high_data, low_data, volume): """ Money Flow. Formula: MF = VOLUME * TYPICAL PRICE """ catch_errors.check_for_input_len_diff(close_data, high_data, low_data, volume) mf = volume * tp(close_data, high_data, low_data) return mf
def band_width(high_data, low_data, period): """ Bandwidth. Formula: BW = SMA(H - L) """ catch_errors.check_for_input_len_diff(high_data, low_data) diff = np.array(high_data) - np.array(low_data) bw = sma(diff, period) return bw
def positive_directional_index(close_data, high_data, low_data, period): """ Positive Directional Index (+DI). Formula: +DI = 100 * SMMA(+DM) / ATR """ catch_errors.check_for_input_len_diff(close_data, high_data, low_data) pdi = (100 * smma(positive_directional_movement(high_data, low_data), period) / atr(close_data, period)) return pdi
def negative_directional_index(close_data, high_data, low_data, period): """ Negative Directional Index (-DI). Formula: -DI = 100 * SMMA(-DM) / ATR """ catch_errors.check_for_input_len_diff(close_data, high_data, low_data) ndi = (100 * smma(negative_directional_movement(high_data, low_data), period) / atr(close_data, period)) return ndi
def commodity_channel_index(close_data, high_data, low_data, period): """ Commodity Channel Index. Formula: CCI = (TP - SMA(TP)) / (0.015 * Mean Deviation) """ catch_errors.check_for_input_len_diff(close_data, high_data, low_data) catch_errors.check_for_period_error(close_data, period) tp = typical_price(close_data, high_data, low_data) cci = ((tp - sma(tp, period)) / (0.015 * np.mean(np.absolute(tp - np.mean(tp))))) return cci
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 force_index(close_data, volume): """ Force Index. Formula: """ catch_errors.check_for_input_len_diff( close_data, volume ) pc = np.diff(close_data, 1) fi = pc * volume[1:] fi = np.append(np.nan, fi) return fi
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 accumulation_distribution(close_data, high_data, low_data, volume): """ Accumulation/Distribution. Formula: A/D = (Ct - Lt) - (Ht - Ct) / (Ht - Lt) * Vt + A/Dt-1 """ catch_errors.check_for_input_len_diff(close_data, high_data, low_data, volume) ad = np.zeros(len(close_data)) for idx in range(1, len(close_data)): ad[idx] = ((((close_data[idx] - low_data[idx]) - (high_data[idx] - close_data[idx])) / (high_data[idx] - low_data[idx]) * volume[idx]) + ad[idx - 1]) return ad
def positive_directional_movement(high_data, low_data): """ Positive Directional Movement (+DM). Formula: +DM: if UPMOVE > DWNMOVE and UPMOVE > 0 then +DM = UPMOVE else +DM = 0 """ catch_errors.check_for_input_len_diff(high_data, low_data) up_moves = calculate_up_moves(high_data) down_moves = calculate_down_moves(low_data) pdm = [] for idx in range(0, len(up_moves)): if up_moves[idx] > down_moves[idx] and up_moves[idx] > 0: pdm.append(up_moves[idx]) else: pdm.append(0) return pdm
def negative_directional_movement(high_data, low_data): """ Negative Directional Movement (-DM). -DM: if DWNMOVE > UPMOVE and DWNMOVE > 0 then -DM = DWNMOVE else -Dm = 0 """ catch_errors.check_for_input_len_diff(high_data, low_data) up_moves = calculate_up_moves(high_data) down_moves = calculate_down_moves(low_data) ndm = [] for idx in range(0, len(down_moves)): if down_moves[idx] > up_moves[idx] and down_moves[idx] > 0: ndm.append(down_moves[idx]) else: ndm.append(0) return ndm
def positive_volume_index(close_data, volume): """ Positive Volume Index (PVI). Formula: PVI0 = 1 IF Vt > Vt-1 PVIt = PVIt-1 + (CLOSEt - CLOSEt-1 / CLOSEt-1 * PVIt-1) ELSE: PVIt = PVIt-1 """ catch_errors.check_for_input_len_diff(close_data, volume) pvi = np.zeros(len(volume)) pvi[0] = 1 for idx in range(1, len(volume)): if volume[idx] > volume[idx - 1]: pvi[idx] = volume_index_helper(pvi, idx, close_data) else: pvi[idx] = pvi[idx - 1] return pvi
def negative_volume_index(close_data, volume): """ Negative Volume Index (NVI). Formula: NVI0 = 1 IF Vt < Vt-1 NVIt = NVIt-1 + (CLOSEt - CLOSEt-1 / CLOSEt-1 * NVIt-1) ELSE: NVIt = NVIt-1 """ catch_errors.check_for_input_len_diff(close_data, volume) nvi = np.zeros(len(volume)) nvi[0] = 1 for idx in range(1, len(volume)): if volume[idx] < volume[idx - 1]: nvi[idx] = volume_index_helper(nvi, idx, close_data) else: nvi[idx] = nvi[idx - 1] return nvi
def accumulation_distribution(close_data, high_data, low_data, volume): """ Accumulation/Distribution. Formula: A/D = (Ct - Lt) - (Ht - Ct) / (Ht - Lt) * Vt + A/Dt-1 """ catch_errors.check_for_input_len_diff(close_data, high_data, low_data, volume) ad = np.zeros(len(close_data)) for idx in range(1, len(close_data)): candle = high_data[idx] - low_data[idx] if candle == 0: if high_data[idx] != close_data[idx]: raise RuntimeError("High and low are equals but close is not.") else: ad[idx] = ad[idx - 1] else: ad[idx] = ((((close_data[idx] - low_data[idx]) - (high_data[idx] - close_data[idx])) / (high_data[idx] - low_data[idx]) * volume[idx]) + ad[idx - 1]) return ad
def on_balance_volume(close_data, volume): """ On Balance Volume. Formula: start = 1 if CLOSEt > CLOSEt-1 obv = obvt-1 + volumet elif CLOSEt < CLOSEt-1 obv = obvt-1 - volumet elif CLOSEt == CLOSTt-1 obv = obvt-1 """ catch_errors.check_for_input_len_diff(close_data, volume) obv = np.zeros(len(volume)) obv[0] = 1 for idx in range(1, len(obv)): if close_data[idx] > close_data[idx-1]: obv[idx] = obv[idx-1] + volume[idx] elif close_data[idx] < close_data[idx-1]: obv[idx] = obv[idx-1] - volume[idx] elif close_data[idx] == close_data[idx-1]: obv[idx] = obv[idx-1] return obv