diff --git a/indicators.py b/indicators.py index 0911a66..0830299 100644 --- a/indicators.py +++ b/indicators.py @@ -37,6 +37,7 @@ import json import io from flask_caching import Cache from dash.exceptions import PreventUpdate +import yahoo_fin.stock_info as si # def fill_missing_data(df): # df.ffill(inplace=True) @@ -95,7 +96,7 @@ class security: This can be a list of stocks, bonds, or otherinvestment vehicles. price - Pandas DataFrame with datetime as index sorted to chronical order """ - def __init__(self, price, volume=None, rfr: float = 0.01, sf: float = 252.0): + def __init__(self, sym, price, volume=None, rfr: float = 0.01, sf: float = 252.0): """ Parameters ---------- @@ -111,9 +112,10 @@ class security: days in a year. Monthly sampling frequency would be 12. And weekly sampling frequenc is 52. """ + self._symbol = sym self._price = price self._volume = volume - self._symbol = price.columns.values + # self._symbol = price.columns.values self._rfr = rfr self._sf = sf @@ -607,7 +609,7 @@ def plot_macd(macd, macd_sig, macd_hist, axs): axs.grid() -def intelligent_loop_plots(): +def intelligent_loop_plots(sym): # 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 @@ -631,238 +633,168 @@ def intelligent_loop_plots(): plot_sd = ed - dt.timedelta(days = 365 * plt_year) plot_ed = ed - watchlist = get_watchlist() - symbols = watchlist.index.values.tolist() + tmp = si.get_data(sym, start_date=sd)[["adjclose", "volume"]] + price = tmp["adjclose"] + vol = tmp["volume"] + stk = security(sym, price, vol) - prices, volumes = get_price_volume(symbols, pd.date_range(sd, ed), addSPY=True) + rsi = stk.rsi() + vorsi = stk.volume_rsi() + macd, macd_sig, macd_hist, norm_hist = stk.macd() + sma50 = stk.sma(50) + vwma50 = stk.vwma(50) + sma200 = stk.sma(200) + bol_low, bol_up = stk.bollinger(200) - # plt.ion() - num_of_plots = 2 - all_plot_sym = [] - all_plot_ind = {} - all_data = pd.DataFrame([]) - all_vol = pd.DataFrame([]) - all_macd = pd.DataFrame([]) - all_rsi = pd.DataFrame([]) + # init + plot_indicator = "[" + # print('{:5}: '.format(sym), end = '') - for sym in symbols: - price = prices[sym].to_frame() - vol = volumes[sym].to_frame() - all_vol = all_vol.join(vol, how='outer') - stk = security(price, vol) + # RSI outside window (over bought / over sold) + rsi_tail = rsi.tail(lb_trigger) + if (rsi_tail >= 70).any() or (rsi_tail <= 30).any(): + # print('--RSI', end = '') + plot_indicator += 'RSI, ' - rsi = stk.rsi() - vorsi = stk.volume_rsi() - macd, macd_sig, macd_hist, norm_hist = stk.macd() - sma50 = stk.sma(50) - vwma50 = stk.vwma(50) - sma200 = stk.sma(200) - bol_low, bol_up = stk.bollinger(200) + # VoRSI outside window (over bought / over sold) + vorsi_tail = vorsi.tail(lb_trigger) + if (vorsi_tail >= 70).any() or (vorsi_tail <= 30).any(): + # print('--VoRSI', end = '') + plot_indicator += 'VoRSI, ' - # init - plot_indicator = "[" - # print('{:5}: '.format(sym), end = '') + # Normalized MACD histogram out of 3% range + norm_hist_tail = abs(norm_hist.tail(lb_trigger)) + if (abs(norm_hist_tail) >= 0.02).any(): + # print('--MACD/R', end = '') # outside normal range + plot_indicator += 'MACD/R, ' - # RSI outside window (over bought / over sold) - rsi_tail = rsi.tail(lb_trigger) - if (rsi_tail[sym] >= 70).any() or (rsi_tail[sym] <= 30).any(): - # print('--RSI', end = '') - plot_indicator += 'RSI, ' + # MACD histogram zero crossing + macd_hist_tail = macd_hist.tail(lb_trigger) + macd_hist_sign = np.sign(macd_hist_tail) + macd_hist_diff = macd_hist_sign.diff() + if (abs(macd_hist_diff) > 1).any(): + # print('--MACD', end = '') # zero crossing + plot_indicator += 'MACD, ' - # VoRSI outside window (over bought / over sold) - vorsi_tail = vorsi.tail(lb_trigger) - if (vorsi_tail[sym] >= 70).any() or (vorsi_tail[sym] <= 30).any(): - # print('--VoRSI', end = '') - plot_indicator += 'VoRSI, ' + # Stock price crosses SMA50 + sma50_cross_tail = sma50.tail(lb_trigger) - price.tail(lb_trigger) + sma50_cross_sign = np.sign(sma50_cross_tail) + sma50_cross_diff = sma50_cross_sign.diff() + if (abs(sma50_cross_diff) > 1).any(): + # print('--SMA50', end = '') + plot_indicator += 'SMA50, ' - # Normalized MACD histogram out of 3% range - norm_hist_tail = abs(norm_hist.tail(lb_trigger)) - if (abs(norm_hist_tail[sym]) >= 0.02).any(): - # print('--MACD/R', end = '') # outside normal range - plot_indicator += 'MACD/R, ' + # Death cross or golden cross - SMA50 vs SMA200 + sma_cross_tail = sma50.tail(lb_trigger) - sma200.tail(lb_trigger).values + sma_cross_sign = np.sign(sma_cross_tail) + sma_cross_diff = sma_cross_sign.diff() + if (abs(sma_cross_diff) > 1).any(): + # print('--Golden/Death', end = '') + plot_indicator += 'Golden/Death, ' - # MACD histogram zero crossing - macd_hist_tail = macd_hist.tail(lb_trigger) - macd_hist_sign = np.sign(macd_hist_tail) - macd_hist_diff = macd_hist_sign.diff() - if (abs(macd_hist_diff[sym]) > 1).any(): - # print('--MACD', end = '') # zero crossing - plot_indicator += 'MACD, ' + # Price outside bollinger band or crossing + price_tail = price.tail(lb_trigger) + bol_low_tail = bol_low.tail(lb_trigger) + bol_up_tail = bol_up.tail(lb_trigger) + price_high = price_tail - bol_up_tail.values + price_low = price_tail - bol_low_tail.values + if (price_high >= 0).any() or (price_low <= 0).any(): + # print('--Bollinger', end ='') + plot_indicator += 'Bollinger, ' - # Stock price crosses SMA50 - sma50_cross_tail = sma50.tail(lb_trigger) - price.tail(lb_trigger) - sma50_cross_sign = np.sign(sma50_cross_tail) - sma50_cross_diff = sma50_cross_sign.diff() - if (abs(sma50_cross_diff[sym]) > 1).any(): - # print('--SMA50', end = '') - plot_indicator += 'SMA50, ' + # Price cross 200 day moving average + sma200_tail = sma200.tail(lb_trigger) + sma200_cross = price_tail - sma200_tail.values + sma200_cross_sign = np.sign(sma200_cross) + sma200_cross_diff = sma200_cross_sign.diff() + if (abs(sma200_cross_diff) > 1).any(): + # print('--SMA200', end = '') + plot_indicator += 'SMA200, ' - # Death cross or golden cross - SMA50 vs SMA200 - sma_cross_tail = sma50.tail(lb_trigger) - sma200.tail(lb_trigger).values - sma_cross_sign = np.sign(sma_cross_tail) - sma_cross_diff = sma_cross_sign.diff() - if (abs(sma_cross_diff[sym]) > 1).any(): - # print('--Golden/Death', end = '') - plot_indicator += 'Golden/Death, ' + # Large trading volume trigger + volume_tail = vol.tail(lb_trigger) + vol_mean = vol.tail(50).mean() + vol_std = vol.tail(50).std() + if ((volume_tail[1] - vol_mean - 2*vol_std) > 0).any(): + # print('--HiVol', end = '') + plot_indicator += "HiVol, " - # Price outside bollinger band or crossing - price_tail = price.tail(lb_trigger) - bol_low_tail = bol_low.tail(lb_trigger) - bol_up_tail = bol_up.tail(lb_trigger) - price_high = price_tail - bol_up_tail.values - price_low = price_tail - bol_low_tail.values - if (price_high[sym] >= 0).any() or (price_low[sym] <= 0).any(): - # print('--Bollinger', end ='') - plot_indicator += 'Bollinger, ' + # print(f"-- {watchlist.loc[sym, 'Notes']}") # carriage return + plot_indicator += ']' + # note_field = watchlist.loc[sym, 'Notes'].strip().lower() + # if note_field != "watch" and ( note_field == "skip" or \ + # plot_indicator =="[]" ): + # continue # skipping plotting to save memory and time - # Price cross 200 day moving average - sma200_tail = sma200.tail(lb_trigger) - sma200_cross = price_tail - sma200_tail.values - sma200_cross_sign = np.sign(sma200_cross) - sma200_cross_diff = sma200_cross_sign.diff() - if (abs(sma200_cross_diff[sym]) > 1).any(): - # print('--SMA200', end = '') - plot_indicator += 'SMA200, ' + # Plotting - # Large trading volume trigger - volume_tail = vol.tail(lb_trigger) - vol_mean = vol.tail(50).mean() - vol_std = vol.tail(50).std() - if ((volume_tail[sym] - vol_mean[sym] - 2*vol_std[sym]) > 0).any(): - # print('--HiVol', end = '') - plot_indicator += "HiVol, " + # 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]) - # print(f"-- {watchlist.loc[sym, 'Notes']}") # carriage return - plot_indicator += ']' - note_field = watchlist.loc[sym, 'Notes'].strip().lower() - if note_field != "watch" and ( note_field == "skip" or \ - plot_indicator =="[]" ): - continue # skipping plotting to save memory and time + # plot basic price info + data = price.copy().to_frame(sym) + # to limit low bound when plotting in log scale + bol_low.loc[sma200.divide(bol_low) > bol_up.divide(sma200).mul(3)] = np.nan + data = data.join(bol_low.rename('_BOL200L')) + data = data.join(bol_up.rename('_BOL200U')) + data = data.join(sma200.rename('_SMA200')) + data = data.join(sma50.rename('_SMA50')) + data = data.join(vwma50.rename('_WVMA50')) - # Plotting - all_plot_sym.append(sym) - all_plot_ind[sym] = sym + ' - ' + watchlist.loc[sym, 'Segment'] + ' - ' +\ - watchlist.loc[sym, 'Sub Segment'] +\ - ' - ' + watchlist.loc[sym, 'Notes'] + ' - ' + plot_indicator + macd = macd.to_frame('_MACD').join(macd_sig.rename('_SIG')) + macd = macd.join(macd_hist.rename('_HIST')) + # macd.rename(columns={sym: sym+'_MACD'}, inplace=True) - # 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]) + rsi = rsi.to_frame('_RSI').join(vorsi.rename('_VoRSI')) + # rsi.rename(columns={sym: sym+'_RSI'}, inplace=True) - # plot basic price info - data = price.copy() - # to limit low bound when plotting in log scale - bol_low.loc[sma200[sym].divide(bol_low[sym]) >\ - bol_up[sym].divide(sma200[sym]).mul(3), sym] = np.nan - data = data.join(bol_low, rsuffix = '_BOL200L') - data = data.join(bol_up, rsuffix = '_BOL200U') - data = data.join(sma200, rsuffix = '_SMA200') - data = data.join(sma50, rsuffix = '_SMA50') - data = data.join(vwma50, rsuffix = '_WVMA50') + return data, vol.to_frame('_VOL'), macd, rsi, plot_indicator - all_data = all_data.join(data, how='outer') - - macd = macd.join(macd_sig, rsuffix = '_SIG') - macd = macd.join(macd_hist, rsuffix = '_HIST') - macd.rename(columns={sym: sym+'_MACD'}, inplace=True) - all_macd = all_macd.join(macd, how='outer') - - rsi = rsi.join(vorsi, rsuffix = '_VoRSI') - rsi.rename(columns={sym: sym+'_RSI'}, inplace=True) - all_rsi = all_rsi.join(rsi, how='outer') - - # # plot stk price in log scale - # axs0.set_yscale('log') - # plot_data(data, axs0, ylabel='Price ($)') - # axs0.plot(data.index[-1], data.iloc[-1][sym], marker=5, color='C0',\ - # markersize=10) - - # # plot volume - # axs0t = axs0.twinx() - # vol.plot(kind='area', ax=axs0t, color='red', alpha=0.1, legend=False) - # axs0t.plot(vol.index[-1], vol.iloc[-1][sym], marker=5, color='red',\ - # markersize=10) - - # # plot RSI - # plot_rsi(rsi, axs1) - # # plot Volume RSI - # plot_volume_rsi(vorsi, axs2) - # # plot MCAD - # plot_macd(macd, macd_sig, macd_hist, axs3) - - # for debug only - # num_of_plots -= 1 - # if num_of_plots < 0: - # break - - all_data = all_data[all_data.index >= plot_sd] - all_vol = all_vol[all_vol.index >= plot_sd] - all_macd = all_macd[all_macd.index >= plot_sd] - all_rsi = all_rsi[all_rsi.index >= plot_sd] - - # pack into one json obj - j_dict = {"all_plot_sym": all_plot_sym, "all_plot_ind": all_plot_ind, - "all_data": all_data.to_json(orient='columns', index=True), - "all_vol": all_vol.to_json(orient='columns', index=True), - "all_macd": all_macd.to_json(orient='columns', index=True), - "all_rsi": all_rsi.to_json(orient='columns', index=True)} - - j_obj = json.dumps(j_dict) - - # return all_plot_sym, all_plot_ind, all_data, all_vol, all_macd, all_rsi - return j_obj if __name__ == "__main__": # test_sec_class() # test_smooth() # test_bollinger_sell() # test_get_orders() - # all_plot_sym, all_plot_ind, all_data, all_vol, all_macd, all_rsi = intelligent_loop_plots() - - # j_obj = intelligent_loop_plots() - # # 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'])) # Initialize the app app = Dash() - CACHE_CONFIG = {'CACHE_TYPE': 'SimpleCache'} - cache = Cache() - cache.init_app(app.server, config=CACHE_CONFIG) + # CACHE_CONFIG = {'CACHE_TYPE': 'SimpleCache'} + # cache = Cache() + # cache.init_app(app.server, config=CACHE_CONFIG) + + watchlist = get_watchlist() + symbols = watchlist.index.values.tolist() # App layout app.layout = [ - html.Button('Refresh Data', id='button', n_clicks=0), - html.Button('Auto Play', id="start-button", n_clicks=0, disabled=True), + # html.Button('Refresh Data', id='button', n_clicks=0), + html.Button('Auto Play', id="start-button", n_clicks=0), # html.Div(children='Pick A Symbol from Dropdown List: '), # html.Hr(), - # dcc.RadioItems(options=['pop', 'lifeExp', 'gdpPercap'], value='lifeExp', id='controls-and-radio-item'), - # dcc.Dropdown(['pop', 'lifeExp', 'gdpPercap'], 'lifeExp', id='controls-and-radio-item'), - dcc.Dropdown(id='controls-and-radio-item'), + # dcc.RadioItems(options=['pop', 'lifeExp', 'gdpPercap'], value='lifeExp', id='symbols_dropdown_list'), + # dcc.Dropdown(['pop', 'lifeExp', 'gdpPercap'], 'lifeExp', id='symbols_dropdown_list'), + dcc.Dropdown(symbols, symbols[0], id='symbols_dropdown_list'), # dash_table.DataTable(data=df.to_dict('records'), page_size=6), dcc.Graph( figure={}, id='controls-and-graph', style={'height':'85vh'} ), - dcc.Store(id="signal"), - # dcc.Store(id="dropdown-index"), + # dcc.Store(id="signal"), + dcc.Store(id="dropdown_index", data='0'), dcc.Interval( id='interval-component', interval=3*1000, # in milliseconds - n_intervals=0, + n_intervals=len(symbols), disabled=True, ), ] @@ -886,7 +818,7 @@ if __name__ == "__main__": # start / stop button callback @callback(Output('interval-component', 'disabled'), Output("start-button", "children"), - Output('controls-and-radio-item', 'disabled'), + Output('symbols_dropdown_list', 'disabled'), Input("start-button", "n_clicks"), State("start-button", "children"),) @@ -900,9 +832,9 @@ if __name__ == "__main__": return no_update # interval callback - @callback(Output('controls-and-radio-item', 'value'), + @callback(Output('symbols_dropdown_list', 'value'), Input("interval-component", "n_intervals"), - State('controls-and-radio-item', 'options'), + State('symbols_dropdown_list', 'options'), # State('dropdown-index', 'data'), ) def cycle_syms(n, syms): @@ -911,77 +843,77 @@ 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 + # @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("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 + # @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 + # 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='controls-and-radio-item', 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"] + # @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 + # return sorted(all_plot_sym), False, False # dropdown callback @callback( Output(component_id='controls-and-graph', component_property='figure'), # Output("dropdown-index", "data"), - Input(component_id='controls-and-radio-item', component_property='value'), - # State('controls-and-radio-item', 'options') + Input(component_id='symbols_dropdown_list', component_property='value'), + # State('symbols_dropdown_list', 'options') # Input(component_id='signal', component_property='data'), ) @@ -991,15 +923,18 @@ if __name__ == "__main__": 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'])) + # 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) fig = make_subplots( rows=3, @@ -1011,48 +946,47 @@ if __name__ == "__main__": ) price_line = px.line( - all_data, - x=all_data.index, - y=[col_chosen, col_chosen+'_BOL200L', col_chosen+'_BOL200U', col_chosen+'_SMA200', col_chosen+'_SMA50', col_chosen+'_WVMA50'], + data, + x=data.index, + y=data.columns.to_list(), # y=[sym, sym+'_BOL200L', sym+'_BOL200U', sym+'_SMA200', sym+'_SMA50', sym+'_WVMA50'], ) volume_line = px.bar( - all_vol, - x=all_vol.index, - # y=sym, - y=col_chosen, + vol, + x=vol.index, + y=vol.columns.to_list(), ) macd_line = px.line( - all_macd, - x=all_macd.index, - y=[col_chosen+'_MACD', col_chosen+'_SIG'], + macd, + x=macd.index, + y=['_MACD', '_SIG'], ) - macd_neg = all_macd.copy() - macd_pos = all_macd.copy() + macd_neg = macd.copy() + macd_pos = macd.copy() macd_neg[macd_neg>0] = 0 macd_pos[macd_pos<0] = 0 macd_hist_pos = px.line( macd_pos, x=macd_pos.index, - y=[col_chosen+'_HIST'], + y=['_HIST'], ) macd_hist_pos.update_traces(fill='tozeroy', line_color='rgba(0,100,0,0.5)', showlegend=False) macd_hist_neg = px.line( macd_neg, x=macd_neg.index, - y=[col_chosen+'_HIST'], + y=['_HIST'], ) macd_hist_neg.update_traces(fill='tozeroy', line_color='rgba(100,0,0,0.5)', showlegend=False) rsi_line = px.line( - all_rsi, - x=all_rsi.index, - y=[col_chosen+'_RSI', col_chosen+'_VoRSI'], + rsi, + x=rsi.index, + y=['_RSI', '_VoRSI'], ) fig.add_traces(price_line.data + volume_line.data, rows=1, cols=1, secondary_ys=[False, False, False, False, False, False, True]) fig.add_traces(macd_line.data + macd_hist_pos.data + macd_hist_neg.data, rows=2, cols=1) @@ -1072,7 +1006,7 @@ if __name__ == "__main__": fig.layout.yaxis3.title="MACD" fig.layout.yaxis4.title="RSI/VoRSI" - fig.update_layout(title_text=all_plot_ind[col_chosen]) + fig.update_layout(title_text=plot_ind) # fig.update_layout(showlegend=False) fig.update_layout(margin=dict(l=30, r=20, t=50, b=20))