import pandas as pd import pandas_datareader.data as web from pandas_datareader._utils import RemoteDataError from scipy.interpolate import UnivariateSpline import datetime as dt import os import time import agent from functions import * import matplotlib.pyplot as plt import matplotlib as mpl mpl.rc('figure', max_open_warning = 0) key = '0UO7Z2MVZ2YSQSVE' class Stock(object): def __init__(self, params, symbol, symbol_params): self.symbol_params = symbol_params self.symbol = symbol self.params = params try: self.name = symbol_params['name'] except: self.name = symbol self.ax = None self.fig = None self.currency = symbol_params['currency'] self.currency_corr = 1 if '$' in self.currency: self.currency_corr = self.params['k_euro'] self.data = {} self.boll = {} self.indicators = {} def fetch(self): filename = 'stocks/' + self.symbol.replace('.', '_') + '.h5' fetch = False today = dt.date.today() start = dt.date(today.year-1, today.month, today.day) end = today try: hdf = pd.HDFStore(filename, 'r') hdf.close() except: fetch = True try: lastmodified = dt.datetime.fromtimestamp(os.stat(filename).st_mtime).date() if lastmodified != today: fetch = self.params['fetch_on_outdated'] except: fetch = True if fetch: # Get stock price via data reader while(True): try: print("Fetching \"{}\"".format(self.symbol)) data = web.DataReader(self.symbol, "av-daily", start, end, api_key=key) break except RemoteDataError: for timeout in reversed(range(0, 60)): print ("Try again in {} s".format(timeout)) time.sleep(1) hdf = pd.HDFStore(filename) hdf[self.symbol] = data else: hdf = pd.HDFStore(filename, 'r') data = hdf[self.symbol] * self.currency_corr start_pos = 0 end_pos = 0 for index in data.index: end_pos += 1 if str(end) in index: break self.data['index'] = np.array(data.index[start_pos:end_pos]) self.data['close'] = np.array(data['close'][start_pos:end_pos]) self.data['high'] = np.array(data['high'][start_pos:end_pos]) self.data['low'] = np.array(data['low'][start_pos:end_pos]) hdf.close() def get_latest(self, key): N = len(self.data['index']) return self.data[key][N-1] def statistics(self): N = len(self.data['index']) self.data['ema'] = exponential_moving_average(self.data['close'], alpha=self.params['ema_alpha']) self.data['sma'] = moving_average(self.data['close'], window_days=self.params['sma_days']) self.data['close_n'] = normalize(self.data['close']) self.data['macd'] = macd(self.data['close_n']) self.data['min'] = moving_min(self.data['close_n'], window_days=self.params['q_days']) self.data['max'] = moving_max(self.data['close_n'], window_days=self.params['q_days']) self.data['Qmin'] = self.data['close_n'] - self.data['min'] self.data['Qmax'] = self.data['close_n'] - self.data['max'] self.boll = bollinger(self.data, window_days=30) y_r = np.append(self.data['macd'], self.data['macd'][N-1]) x_r = np.linspace(1, N, N+1) spl = UnivariateSpline(x=x_r, y=y_r, k=5) spl.set_smoothing_factor(0.25) spl_d = spl.derivative() spl_dd = spl.derivative().derivative() yf = spl(x_r) yf_d = spl_d(x_r) x_r2 = np.linspace(1, N, N+1) yf_dd = spl_dd(x_r2) self.data['macd_f'] = np.transpose(yf) self.data['macd_fd'] = np.transpose(yf_d) self.data['macd_fdd'] = np.transpose(yf_dd) def analyze(self, buy_callback, range_days): return agent.buy_BTFD(self.symbol, self.data, params=self.params['btfd'], marker_key='close_n', range_days=range_days, buy_callback=buy_callback) @staticmethod def has_candidate(data, key): result = np.count_nonzero(data[key] != None) return result > 0 @staticmethod def slice(data, start, stop): result = {} for key in iter(data): result[key] = data[key][start:stop] return result def __plot(self, id, data, keys): ax = plt.subplot(id) N = len(data['index']) start = max(0, N - self.params['show_range_days']) stop = N xr = list(range(start, stop)) sliced = Stock.slice(data, start, stop) for key in keys: plt.plot(xr, sliced[key], label=key) def hover(event): if event.inaxes == ax: x_idx = min(N-1, int(event.xdata)) ax.format_xdata = lambda x: self.data['index'][x_idx] self.fig.canvas.mpl_connect("motion_notify_event", hover) def __ind(self, data, keys): N = len(data['index']) start = max(0, N - self.params['show_range_days']) stop = N xr = list(range(start, stop)) sliced = Stock.slice(data, start, stop) for key in keys: plt.plot(xr, sliced[key], 'go', label=key) def show(self, indicators, figNum=1): num_subplots = 4 subplot_id = 100*num_subplots + 10 + 1 self.fig = plt.figure(figNum) self.__plot(subplot_id, self.data, ['min', 'max', 'close_n']) self.__ind(indicators, ['BTFD']) plt.title('{} ({})'.format(self.name, self.symbol)) plt.legend() plt.grid() subplot_id += 1 # self.__plot(self.boll, ['lower', 'mid', 'upper']) self.__plot(subplot_id, self.data, ['Qmin', 'Qmax']) plt.legend() plt.grid() subplot_id += 1 self.__plot(subplot_id, self.data, ['macd', 'macd_f']) plt.legend() plt.grid() subplot_id += 1 self.__plot(subplot_id, self.data, ['macd_fd', 'macd_fdd']) plt.legend() plt.grid()