import pandas as pd import pandas_datareader.data as web import numpy as np import math import matplotlib.pyplot as plt import datetime as dt import os # Stock Investors Financial Math # https://www.fmlabs.com/reference/default.htm?url=SimpleMA.htm # Alpha Vantage # https://www.alphavantage.co/documentation/ # Pandas # https://pandas.pydata.org/pandas-docs/stable/index.html # Knowledge # https://www.investopedia.com/articles/technical/02/050602.asp # https://ntguardian.wordpress.com/2016/09/19/introduction-stock-market-data-python-1 key = '0UO7Z2MVZ2YSQSVE' thresh_macd = 0.5 show_range_days = 20 show_title = 'KEYS' titles = [ 'AAPL', 'XLNX', 'QCOM', 'DPW.DE', 'CSCO', 'AIR', 'BA', 'NVDA', 'MSFT', 'DIS', 'NFLX', 'OHB.DE', 'ERCA.DE', 'VAR1.DE', 'HD', 'AMZN', 'GOOGL', 'ZIL2.DE', 'SIS.DE', 'GFT.DE', 'AMD.DE', 'PANW', 'RIB.DE', 'WAF.DE', 'EVT.DE', 'VOW.DE', 'KEYS', 'I'] def ema(data, key, alpha=0.5, ic=None): result = [] if ic is None: r = data[key][0] else: r = ic for v in data[key]: r = alpha*r + (1-alpha)*v result.append(r) return np.array(result) def sma(data, key, window_days, ic=None): mem = [0] * window_days result = [] k=0 cumsum = 0 for v in data[key]: cumsum += (v - mem[k]) mem[k] = v k += 1 if k >= window_days: k=0 result.append(cumsum/window_days) return result def sd(data, key, window_days, ic=None): mem = [0] * window_days result = [] k=0 cumsum = 0 data_mean = data[key] - sma(data, key, window_days, ic) for v in data_mean: v2 = v * v cumsum += (v2 - mem[k]) mem[k] = v2 k += 1 if k >= window_days: k=0 var = max(0, cumsum) / window_days result.append(math.sqrt(var)) return result def colsum(data, keys): result = np.zeros(data.shape[0]) for key in keys: result += data[key] return result def macd(data, key): ema_short = ema(data, key, alpha=0.85) ema_long = ema(data, key, alpha=0.925) return ema_short - ema_long def bollinger(data, window_days, f=2): tp_ser = colsum(data, keys=['high', 'low', 'close']) / 3 tp_df = tp_ser.to_frame(name='tp') stddev = np.array(sd(tp_df, 'tp', window_days)) mid = np.array(sma(tp_df, key='tp', window_days=window_days)) upper = mid + f * stddev lower = mid - f * stddev result = pd.DataFrame(upper, index=data.index, columns=['upper']) result['lower'] = lower result['mid'] = mid return result class Symbol(object): def __init__(self, name): self.name = name self.ax = None self.fig = None self.k_euro = 1/1.11 def fetch(self): filename = self.name.replace('.','_') + '.h5' fetch = False today = dt.date.today() try: hdf = pd.HDFStore(filename, 'r') except: fetch = True try: lastmodified = dt.datetime.fromtimestamp(os.stat(filename).st_mtime).date() if lastmodified != today: fetch = True except: fetch = True if fetch: print ("Fetching \"{}\"".format(self.name)) # Get stock price via data reader start = dt.datetime(today.year,1,1) end = dt.date.today() data = web.DataReader(self.name, "av-daily", start, end, api_key=key) hdf = pd.HDFStore(filename) hdf[self.name] = data self.data_full = hdf[self.name]*self.k_euro hdf.close() def __plot(self, d, keys): dates = d.index for key in keys: data = d[key] data.plot() def hover(event): if event.inaxes == self.ax: x_idx = int(event.xdata) self.ax.format_xdata = lambda x: dates[x_idx] self.ax.format_ydata = lambda y: '€{:.2f}'.format(data[x_idx]) self.fig.canvas.mpl_connect("motion_notify_event", hover) def analyze(self): self.data_full['ema'] = ema(self.data_full, key='close', alpha=0.75) self.data_full['macd'] = macd(self.data_full, key='close') self.data_full['sma'] = sma(self.data_full, key='close', window_days=30) self.boll_full = bollinger(self.data_full, window_days=30) _macd = self.data_full['macd'][len(self.data_full)-1] return {'macd' : _macd} def show(self, figNum=1): data = self.data_full[len(self.data_full)-1 - show_range_days:] boll = self.boll_full[len(self.boll_full)-1 - show_range_days:] self.fig = plt.figure(figNum) self.ax = plt.subplot(311) self.__plot(data, ['ema', 'close', 'sma']) plt.title(self.name) plt.legend() plt.grid() plt.subplot(312) boll['upper'].plot() boll['mid'].plot() boll['lower'].plot() plt.legend() plt.grid() plt.subplot(313) data['macd'].plot() plt.legend() plt.grid() figNum = 1 if '' != show_title: sym = Symbol(show_title) sym.fetch() sym.analyze() sym.show(figNum) else: for title in titles: sym = Symbol(title) sym.fetch() result = sym.analyze() if result['macd'] > thresh_macd: sym.show(figNum) figNum += 1 plt.show()