import pandas as pd import datetime as dt import matplotlib.pyplot as plt from util import get_data def author(): return "felixm" def normalize(timeseries): return timeseries / timeseries.iloc[0] def bollinger_band(df, symbol, period=20, m=2): boll_sma = df[symbol].rolling(period).mean() std = df[symbol].rolling(period).std() boll_up = boll_sma + m * std boll_lo = boll_sma - m * std key_sma, key_up, key_lo = "boll_sma", "boll_up", "boll_lo" df[key_sma] = boll_sma df[key_up] = boll_up df[key_lo] = boll_lo return df[[key_sma, key_up, key_lo]] def sma(df, symbol, period): """Adds SMA for one or multiple periods to df and returns SMAs""" if type(period) is int: period = [period] keys = [] for p in period: key = f"sma_{p}" df[key] = df[symbol].rolling(p).mean() keys.append(key) return df[keys] def ema(df, symbol, period): """Adds EMA for one or multiple periods to df and returns EMAs""" if type(period) is int: period = [period] keys = [] for p in period: key = f"ema_{p}" df[key] = df[symbol].ewm(span=p).mean() keys.append(key) return df[keys] def price_sma(df, symbol, period): """Calculates SMA and adds new column price divided by SMA to the df.""" if type(period) is int: period = [period] keys = [] for p in period: key = f"price_sma_{p}" sma = df[symbol].rolling(p).mean() df[key] = df[symbol] / sma keys.append(key) return df[keys] def rsi(df, symbol, period=14): """Calculates relative strength index over given period.""" def rsi(x): pct = x.pct_change() avg_gain = pct[pct > 0].mean() avg_loss = pct[pct <= 0].abs().mean() rsi = 100 - (100 / (1 + ((avg_gain / period) / (avg_loss / period)))) return rsi key = "rsi" # Add one to get 'period' price changes (first change is nan). period += 1 df[key] = df[symbol].rolling(period).apply(rsi) return df[[key]] def macd(df, symbol): macd = df[symbol].ewm(span=12).mean() - df[symbol].ewm(span=26).mean() k1 = "macd" k2 = "macd_signal" k3 = "macd_diff" df[k1] = macd df[k2] = macd.rolling(9).mean() df[k3] = df[k1] - df[k2] return df[[k1, k2, k3]] def price_delta(df, symbol, period=1): """Calculate percentage change for period.""" k = f"pct_{period}" df[k] = df[symbol].pct_change(periods=period) df[k] = df[k].shift(-period) return df[k] def test_indicators(): symbol = "JPM" sd = dt.datetime(2008, 1, 1) ed = dt.datetime(2009, 12, 31) df = get_data([symbol], pd.date_range(sd, ed)) df.drop(columns=["SPY"], inplace=True) df_orig = df.copy() # df = normalize(df) sma(df, symbol, 21) ema(df, symbol, 21) df.plot(title="21 SMA and EMA") plt.savefig('figure_1.png') df = df_orig.copy() sma(df, symbol, 8) price_sma(df, symbol, 8) df.plot(title="SMA and price / SMA", subplots=True) plt.savefig('figure_2.png') df = df_orig.copy() bollinger_band(df, symbol) df.plot(title="Bollinger Band") plt.savefig('figure_3.png') df = df_orig.copy() rsi(df, symbol) fig, axes = plt.subplots(nrows=2, sharex=True) df[symbol].plot(ax=axes[0], title="JPM price action") df["JPM-rsi(14)"].plot(ax=axes[1], title="RSI") plt.savefig('figure_4.png') df = df_orig.copy() macd(df, symbol) fig, axes = plt.subplots(nrows=2, sharex=True) df[symbol].plot(ax=axes[0], title="JPM price action") df[["JPM-macd", "JPM-macd-signal"]].plot(ax=axes[1]) plt.savefig('figure_5.png')