From 654ef5ea3287faf5beb6aac3a06a89b4dddce864 Mon Sep 17 00:00:00 2001 From: tomgwang Date: Thu, 26 Sep 2024 13:10:19 -0700 Subject: [PATCH] added caching --- indicators.py | 215 +++++--------------------------------------------- 1 file changed, 21 insertions(+), 194 deletions(-) diff --git a/indicators.py b/indicators.py index 0830299..9e7f4b7 100644 --- a/indicators.py +++ b/indicators.py @@ -517,99 +517,7 @@ def modified_bollinger_strategy(stk): return order_list - -# def test_get_orders(): -# sd = dt.datetime(2000,2,1) -# # ed = dt.datetime.today() -# ed = dt.datetime(2012,9,12) -# symbol = ['INTC', 'XOM', 'MSFT'] -# dates = dates = pd.date_range(sd, ed) -# prices = get_data(symbol, dates, addSPY=False) -# stk = security(prices) - -# # order_list = simple_bollinger_strategy(stk) -# order_list = modified_bollinger_strategy(stk) - -# # print(order_list) -# port_val = compute_portvals(order_list,100000,9.95,0.005) -# if isinstance(port_val, pd.DataFrame): -# port_val = port_val[port_val.columns[0]].to_frame() # just get the first column -# else: -# print("warning, code did not return a DataFrame") -# price_SPY = plot_against_sym(port_val) - -# rfr=0 -# sf=252 - -# cr, adr, sddr, sr = compute_portfolio_stats(port_val, [1.0], rfr, sf) -# crSP,adrSP,sddrSP,srSP = compute_portfolio_stats(price_SPY, [1.0], rfr, sf) -# # Compare portfolio against $SPX -# print("\nDate Range: {} to {}".format(sd.date(), ed.date())) -# print() -# print("Sharpe Ratio: {}, {}".format(sr, srSP)) -# print() -# print("Cumulative Return: {}, {}".format(cr, crSP)) -# print() -# print("Standard Deviation: {}, {}".format(sddr, sddrSP)) -# print() -# print("Average Daily Return: {}, {}".format(adr, adrSP)) -# print() -# print("Final Portfolio Value: {:.2f}".format(port_val['Portfolio'].iloc[-1])) - -def plot_basic(stk, axs): - data = stk.price.copy() - lower, upper = stk.bollinger(200) - data = data.join(lower, rsuffix = '_BOL200L') - data = data.join(upper, rsuffix = '_BOL200U') - data = data.join(stk.sma(200), rsuffix = '_SMA200') - data = data.join(stk.sma(50), rsuffix = '_SMA50') - data = data.join(stk.vwma(50), rsuffix = '_WVMA50') - plot_data(data, axs, ylabel='Price ($)') - -def plot_rsi(rsi, axs): - poscol = 'green' - negcol = 'red' - axs.plot(rsi.index.values, rsi.iloc[:,0]) - axs.axhline(70, color=negcol, ls='dotted') - axs.axhline(30, color=poscol, ls='dotted') - axs.fill_between(rsi.index.values, rsi.iloc[:,0], 70, - where=rsi.iloc[:,0]>=70, facecolor=negcol, edgecolor=negcol, alpha=0.5) - axs.fill_between(rsi.index.values, rsi.iloc[:,0], 30, - where=rsi.iloc[:,0]<=30, facecolor=poscol, edgecolor=poscol, alpha=0.5) - axs.set_yticks([30, 50, 70]) - axs.set_ylabel('RSI') - axs.grid() - -def plot_volume_rsi(rsi, axs): - poscol = 'green' - negcol = 'red' - axs.plot(rsi.index.values, rsi.iloc[:,0]) - axs.axhline(70, color=negcol, ls='dotted') - axs.axhline(30, color=poscol, ls='dotted') - axs.fill_between(rsi.index.values, rsi.iloc[:,0], 70, - where=rsi.iloc[:,0]>=70, facecolor=negcol, edgecolor=negcol, alpha=0.5) - axs.fill_between(rsi.index.values, rsi.iloc[:,0], 30, - where=rsi.iloc[:,0]<=30, facecolor=poscol, edgecolor=poscol, alpha=0.5) - axs.set_yticks([30, 50, 70]) - axs.set_ylabel('VoRSI') - axs.grid() - -def plot_macd(macd, macd_sig, macd_hist, axs): - poscol = 'green' - negcol = 'red' - axs.plot(macd.index.values, macd.iloc[:, 0], label='MACD') - axs.legend() - axs.plot(macd.index.values, macd_sig.iloc[:, 0]) - axs.plot(macd.index.values, macd_hist.iloc[:, 0]) - axs.fill_between(macd.index.values, macd_hist.iloc[:, 0], 0, - where=macd_hist.iloc[:, 0]>0, facecolor=poscol, edgecolor=poscol, alpha=0.5) - axs.fill_between(macd.index.values, macd_hist.iloc[:, 0], 0, - where=macd_hist.iloc[:, 0]<0, facecolor=negcol, edgecolor=negcol, alpha=0.5) - axs.set_ylabel('MACD') - axs.grid() - - -def intelligent_loop_plots(sym): +def intelligent_loop_plots(sym, tmp): # Only plot ones that are standing out meaning: # 1. outside of bollinger bands or recently crossed over (within 9 days) # 2. RSI above 70 or below 30 @@ -625,15 +533,6 @@ def intelligent_loop_plots(sym): # matplotlib.rcParams.update({'figure.max_open_warning': 0}) - lb_year = 3 # years of stock data to retrieve - plt_year = 2 # number of years data to plot - lb_trigger = 5 # days to lookback for triggering events - ed = dt.datetime.today() - sd = ed - dt.timedelta(days = 365 * lb_year) - plot_sd = ed - dt.timedelta(days = 365 * plt_year) - plot_ed = ed - - tmp = si.get_data(sym, start_date=sd)[["adjclose", "volume"]] price = tmp["adjclose"] vol = tmp["volume"] stk = security(sym, price, vol) @@ -726,18 +625,6 @@ def intelligent_loop_plots(sym): # plot_indicator =="[]" ): # continue # skipping plotting to save memory and time - # Plotting - - # fig, (axs0, axs1, axs2, axs3) = plt.subplots(4, sharex=True, - # gridspec_kw={'hspace': 0, 'height_ratios': [3, 1, 1, 1]}, - # figsize=(16, 12)) - # # fig.suptitle('{} - {} - {} - {}'.format(sym,\ - # # watchlist.loc[sym, 'Segment'], watchlist.loc[sym, 'Sub Segment'])) - # axs0.set_title('{} - {} - {} - {} - {}'.format(sym,\ - # watchlist.loc[sym, 'Segment'], watchlist.loc[sym, 'Sub Segment'],\ - # watchlist.loc[sym, 'Notes'], plot_indicator)) - # axs0.set_xlim([plot_sd, plot_ed]) - # plot basic price info data = price.copy().to_frame(sym) # to limit low bound when plotting in log scale @@ -759,6 +646,15 @@ def intelligent_loop_plots(sym): if __name__ == "__main__": + + lb_year = 3 # years of stock data to retrieve + plt_year = 2 # number of years data to plot + lb_trigger = 5 # days to lookback for triggering events + end_date = dt.datetime.today() + start_date = end_date - dt.timedelta(days = 365 * lb_year) + plot_sd = end_date - dt.timedelta(days = 365 * plt_year) + plot_ed = end_date + # test_sec_class() # test_smooth() # test_bollinger_sell() @@ -767,13 +663,17 @@ if __name__ == "__main__": # Initialize the app app = Dash() - # CACHE_CONFIG = {'CACHE_TYPE': 'SimpleCache'} - # cache = Cache() - # cache.init_app(app.server, config=CACHE_CONFIG) - watchlist = get_watchlist() symbols = watchlist.index.values.tolist() + CACHE_CONFIG = {'CACHE_TYPE': 'SimpleCache'} + cache = Cache() + cache.init_app(app.server, config=CACHE_CONFIG) + + @cache.memoize(timeout=14400) # cache timeout set to 4 hours + def fetch_stk_data(sym, sd): + return si.get_data(sym, start_date=sd)[["adjclose", "volume"]] + # App layout app.layout = [ # html.Button('Refresh Data', id='button', n_clicks=0), @@ -843,71 +743,6 @@ if __name__ == "__main__": else: return no_update - # @cache.memoize(timeout=14400) # cache timeout set to 4 hours - # def global_store(): - # j_obj = intelligent_loop_plots() - # return j_obj - - # retrieve data button callbacks - # @callback( - # Output("button", "disabled", allow_duplicate=True), - # Input("button", "n_clicks"), - # prevent_initial_call=True, - # ) - # def disable_btn(n): - # if n: - # return True - # return no_update - - # @callback( - # Output(component_id='signal', component_property='data'), - # # Output(component_id='button', component_property='disabled'), - # Input(component_id='button', component_property='n_clicks'), - # prevent_initial_call=True, - # ) - # def get_data_cb(clicks): - # # global all_plot_sym, all_plot_ind, all_data, all_vol, all_macd, all_rsi - # # if clicks == 0: - # # return # no update - # if not clicks or clicks == 0: - # raise PreventUpdate - - # print("get data") - # global_store() - # print("data retrieved") - # # unpacking - # # json_data = json.loads(j_obj) - # # all_plot_sym = json_data["all_plot_sym"] - # # all_plot_ind = json_data["all_plot_ind"] - # # all_data = pd.read_json(io.StringIO(json_data['all_data'])) - # # all_vol = pd.read_json(io.StringIO(json_data['all_vol'])) - # # all_macd = pd.read_json(io.StringIO(json_data['all_macd'])) - # # all_rsi = pd.read_json(io.StringIO(json_data['all_rsi'])) - # return clicks - - # Add controls to build the interaction - - # callback when data retrieve finishes triggered by signal - # @callback( - # Output(component_id='symbols_dropdown_list', component_property='options'), - # Output(component_id='button', component_property='disabled'), - # Output(component_id='start-button', component_property='disabled'), - # Input(component_id='signal', component_property='data'), - # ) - # def update_dropdown(in_data): - # if not in_data or in_data == 0: - # raise PreventUpdate - # # return no_update - # print(f"input: {in_data}") - # j_obj = global_store() - # # unpacking - # json_data = json.loads(j_obj) - # all_plot_sym = json_data["all_plot_sym"] - # print("dropdown menu options updated") - # # all_plot_sym = ["SPY", "AMZN"] - - # return sorted(all_plot_sym), False, False - # dropdown callback @callback( Output(component_id='controls-and-graph', component_property='figure'), @@ -922,19 +757,11 @@ if __name__ == "__main__": if not col_chosen: raise PreventUpdate # return no_update - # col_chosen = "SPY" - # j_obj = global_store() - # # unpacking - # json_data = json.loads(j_obj) - # # all_plot_sym = json_data["all_plot_sym"] - # all_plot_ind = json_data["all_plot_ind"] - # all_data = pd.read_json(io.StringIO(json_data['all_data'])) - # all_vol = pd.read_json(io.StringIO(json_data['all_vol'])) - # all_macd = pd.read_json(io.StringIO(json_data['all_macd'])) - # all_rsi = pd.read_json(io.StringIO(json_data['all_rsi'])) # get data - data, vol, macd, rsi, plot_ind = intelligent_loop_plots(col_chosen) + # tmp = si.get_data(sym, start_date=sd)[["adjclose", "volume"]] + tmp = fetch_stk_data(col_chosen, start_date) + data, vol, macd, rsi, plot_ind = intelligent_loop_plots(col_chosen, tmp) fig = make_subplots( rows=3,