1st working commit. TODO - fix SettingWithCopyWarning

This commit is contained in:
tomgwang 2024-09-25 18:19:19 -07:00
parent 37b6fdb145
commit 456bfc38d2

View File

@ -37,6 +37,7 @@ import json
import io import io
from flask_caching import Cache from flask_caching import Cache
from dash.exceptions import PreventUpdate from dash.exceptions import PreventUpdate
import yahoo_fin.stock_info as si
# def fill_missing_data(df): # def fill_missing_data(df):
# df.ffill(inplace=True) # df.ffill(inplace=True)
@ -95,7 +96,7 @@ class security:
This can be a list of stocks, bonds, or otherinvestment vehicles. This can be a list of stocks, bonds, or otherinvestment vehicles.
price - Pandas DataFrame with datetime as index sorted to chronical order 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 Parameters
---------- ----------
@ -111,9 +112,10 @@ class security:
days in a year. Monthly sampling frequency would be 12. And days in a year. Monthly sampling frequency would be 12. And
weekly sampling frequenc is 52. weekly sampling frequenc is 52.
""" """
self._symbol = sym
self._price = price self._price = price
self._volume = volume self._volume = volume
self._symbol = price.columns.values # self._symbol = price.columns.values
self._rfr = rfr self._rfr = rfr
self._sf = sf self._sf = sf
@ -607,7 +609,7 @@ def plot_macd(macd, macd_sig, macd_hist, axs):
axs.grid() axs.grid()
def intelligent_loop_plots(): def intelligent_loop_plots(sym):
# Only plot ones that are standing out meaning: # Only plot ones that are standing out meaning:
# 1. outside of bollinger bands or recently crossed over (within 9 days) # 1. outside of bollinger bands or recently crossed over (within 9 days)
# 2. RSI above 70 or below 30 # 2. RSI above 70 or below 30
@ -631,25 +633,10 @@ def intelligent_loop_plots():
plot_sd = ed - dt.timedelta(days = 365 * plt_year) plot_sd = ed - dt.timedelta(days = 365 * plt_year)
plot_ed = ed plot_ed = ed
watchlist = get_watchlist() tmp = si.get_data(sym, start_date=sd)[["adjclose", "volume"]]
symbols = watchlist.index.values.tolist() price = tmp["adjclose"]
vol = tmp["volume"]
prices, volumes = get_price_volume(symbols, pd.date_range(sd, ed), addSPY=True) stk = security(sym, price, vol)
# 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([])
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 = stk.rsi() rsi = stk.rsi()
vorsi = stk.volume_rsi() vorsi = stk.volume_rsi()
@ -665,19 +652,19 @@ def intelligent_loop_plots():
# RSI outside window (over bought / over sold) # RSI outside window (over bought / over sold)
rsi_tail = rsi.tail(lb_trigger) rsi_tail = rsi.tail(lb_trigger)
if (rsi_tail[sym] >= 70).any() or (rsi_tail[sym] <= 30).any(): if (rsi_tail >= 70).any() or (rsi_tail <= 30).any():
# print('--RSI', end = '') # print('--RSI', end = '')
plot_indicator += 'RSI, ' plot_indicator += 'RSI, '
# VoRSI outside window (over bought / over sold) # VoRSI outside window (over bought / over sold)
vorsi_tail = vorsi.tail(lb_trigger) vorsi_tail = vorsi.tail(lb_trigger)
if (vorsi_tail[sym] >= 70).any() or (vorsi_tail[sym] <= 30).any(): if (vorsi_tail >= 70).any() or (vorsi_tail <= 30).any():
# print('--VoRSI', end = '') # print('--VoRSI', end = '')
plot_indicator += 'VoRSI, ' plot_indicator += 'VoRSI, '
# Normalized MACD histogram out of 3% range # Normalized MACD histogram out of 3% range
norm_hist_tail = abs(norm_hist.tail(lb_trigger)) norm_hist_tail = abs(norm_hist.tail(lb_trigger))
if (abs(norm_hist_tail[sym]) >= 0.02).any(): if (abs(norm_hist_tail) >= 0.02).any():
# print('--MACD/R', end = '') # outside normal range # print('--MACD/R', end = '') # outside normal range
plot_indicator += 'MACD/R, ' plot_indicator += 'MACD/R, '
@ -685,7 +672,7 @@ def intelligent_loop_plots():
macd_hist_tail = macd_hist.tail(lb_trigger) macd_hist_tail = macd_hist.tail(lb_trigger)
macd_hist_sign = np.sign(macd_hist_tail) macd_hist_sign = np.sign(macd_hist_tail)
macd_hist_diff = macd_hist_sign.diff() macd_hist_diff = macd_hist_sign.diff()
if (abs(macd_hist_diff[sym]) > 1).any(): if (abs(macd_hist_diff) > 1).any():
# print('--MACD', end = '') # zero crossing # print('--MACD', end = '') # zero crossing
plot_indicator += 'MACD, ' plot_indicator += 'MACD, '
@ -693,7 +680,7 @@ def intelligent_loop_plots():
sma50_cross_tail = sma50.tail(lb_trigger) - price.tail(lb_trigger) sma50_cross_tail = sma50.tail(lb_trigger) - price.tail(lb_trigger)
sma50_cross_sign = np.sign(sma50_cross_tail) sma50_cross_sign = np.sign(sma50_cross_tail)
sma50_cross_diff = sma50_cross_sign.diff() sma50_cross_diff = sma50_cross_sign.diff()
if (abs(sma50_cross_diff[sym]) > 1).any(): if (abs(sma50_cross_diff) > 1).any():
# print('--SMA50', end = '') # print('--SMA50', end = '')
plot_indicator += 'SMA50, ' plot_indicator += 'SMA50, '
@ -701,7 +688,7 @@ def intelligent_loop_plots():
sma_cross_tail = sma50.tail(lb_trigger) - sma200.tail(lb_trigger).values sma_cross_tail = sma50.tail(lb_trigger) - sma200.tail(lb_trigger).values
sma_cross_sign = np.sign(sma_cross_tail) sma_cross_sign = np.sign(sma_cross_tail)
sma_cross_diff = sma_cross_sign.diff() sma_cross_diff = sma_cross_sign.diff()
if (abs(sma_cross_diff[sym]) > 1).any(): if (abs(sma_cross_diff) > 1).any():
# print('--Golden/Death', end = '') # print('--Golden/Death', end = '')
plot_indicator += 'Golden/Death, ' plot_indicator += 'Golden/Death, '
@ -711,7 +698,7 @@ def intelligent_loop_plots():
bol_up_tail = bol_up.tail(lb_trigger) bol_up_tail = bol_up.tail(lb_trigger)
price_high = price_tail - bol_up_tail.values price_high = price_tail - bol_up_tail.values
price_low = price_tail - bol_low_tail.values price_low = price_tail - bol_low_tail.values
if (price_high[sym] >= 0).any() or (price_low[sym] <= 0).any(): if (price_high >= 0).any() or (price_low <= 0).any():
# print('--Bollinger', end ='') # print('--Bollinger', end ='')
plot_indicator += 'Bollinger, ' plot_indicator += 'Bollinger, '
@ -720,7 +707,7 @@ def intelligent_loop_plots():
sma200_cross = price_tail - sma200_tail.values sma200_cross = price_tail - sma200_tail.values
sma200_cross_sign = np.sign(sma200_cross) sma200_cross_sign = np.sign(sma200_cross)
sma200_cross_diff = sma200_cross_sign.diff() sma200_cross_diff = sma200_cross_sign.diff()
if (abs(sma200_cross_diff[sym]) > 1).any(): if (abs(sma200_cross_diff) > 1).any():
# print('--SMA200', end = '') # print('--SMA200', end = '')
plot_indicator += 'SMA200, ' plot_indicator += 'SMA200, '
@ -728,22 +715,18 @@ def intelligent_loop_plots():
volume_tail = vol.tail(lb_trigger) volume_tail = vol.tail(lb_trigger)
vol_mean = vol.tail(50).mean() vol_mean = vol.tail(50).mean()
vol_std = vol.tail(50).std() vol_std = vol.tail(50).std()
if ((volume_tail[sym] - vol_mean[sym] - 2*vol_std[sym]) > 0).any(): if ((volume_tail[1] - vol_mean - 2*vol_std) > 0).any():
# print('--HiVol', end = '') # print('--HiVol', end = '')
plot_indicator += "HiVol, " plot_indicator += "HiVol, "
# print(f"-- {watchlist.loc[sym, 'Notes']}") # carriage return # print(f"-- {watchlist.loc[sym, 'Notes']}") # carriage return
plot_indicator += ']' plot_indicator += ']'
note_field = watchlist.loc[sym, 'Notes'].strip().lower() # note_field = watchlist.loc[sym, 'Notes'].strip().lower()
if note_field != "watch" and ( note_field == "skip" or \ # if note_field != "watch" and ( note_field == "skip" or \
plot_indicator =="[]" ): # plot_indicator =="[]" ):
continue # skipping plotting to save memory and time # continue # skipping plotting to save memory and time
# Plotting # 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
# fig, (axs0, axs1, axs2, axs3) = plt.subplots(4, sharex=True, # fig, (axs0, axs1, axs2, axs3) = plt.subplots(4, sharex=True,
# gridspec_kw={'hspace': 0, 'height_ratios': [3, 1, 1, 1]}, # gridspec_kw={'hspace': 0, 'height_ratios': [3, 1, 1, 1]},
@ -756,113 +739,62 @@ def intelligent_loop_plots():
# axs0.set_xlim([plot_sd, plot_ed]) # axs0.set_xlim([plot_sd, plot_ed])
# plot basic price info # plot basic price info
data = price.copy() data = price.copy().to_frame(sym)
# to limit low bound when plotting in log scale # to limit low bound when plotting in log scale
bol_low.loc[sma200[sym].divide(bol_low[sym]) >\ bol_low.loc[sma200.divide(bol_low) > bol_up.divide(sma200).mul(3)] = np.nan
bol_up[sym].divide(sma200[sym]).mul(3), sym] = np.nan data = data.join(bol_low.rename('_BOL200L'))
data = data.join(bol_low, rsuffix = '_BOL200L') data = data.join(bol_up.rename('_BOL200U'))
data = data.join(bol_up, rsuffix = '_BOL200U') data = data.join(sma200.rename('_SMA200'))
data = data.join(sma200, rsuffix = '_SMA200') data = data.join(sma50.rename('_SMA50'))
data = data.join(sma50, rsuffix = '_SMA50') data = data.join(vwma50.rename('_WVMA50'))
data = data.join(vwma50, rsuffix = '_WVMA50')
all_data = all_data.join(data, how='outer') 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)
macd = macd.join(macd_sig, rsuffix = '_SIG') rsi = rsi.to_frame('_RSI').join(vorsi.rename('_VoRSI'))
macd = macd.join(macd_hist, rsuffix = '_HIST') # rsi.rename(columns={sym: sym+'_RSI'}, inplace=True)
macd.rename(columns={sym: sym+'_MACD'}, inplace=True)
all_macd = all_macd.join(macd, how='outer')
rsi = rsi.join(vorsi, rsuffix = '_VoRSI') return data, vol.to_frame('_VOL'), macd, rsi, plot_indicator
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__": if __name__ == "__main__":
# test_sec_class() # test_sec_class()
# test_smooth() # test_smooth()
# test_bollinger_sell() # test_bollinger_sell()
# test_get_orders() # 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 # Initialize the app
app = Dash() app = Dash()
CACHE_CONFIG = {'CACHE_TYPE': 'SimpleCache'} # CACHE_CONFIG = {'CACHE_TYPE': 'SimpleCache'}
cache = Cache() # cache = Cache()
cache.init_app(app.server, config=CACHE_CONFIG) # cache.init_app(app.server, config=CACHE_CONFIG)
watchlist = get_watchlist()
symbols = watchlist.index.values.tolist()
# App layout # App layout
app.layout = [ app.layout = [
html.Button('Refresh Data', id='button', n_clicks=0), # html.Button('Refresh Data', id='button', n_clicks=0),
html.Button('Auto Play', id="start-button", n_clicks=0, disabled=True), html.Button('Auto Play', id="start-button", n_clicks=0),
# html.Div(children='Pick A Symbol from Dropdown List: '), # html.Div(children='Pick A Symbol from Dropdown List: '),
# html.Hr(), # html.Hr(),
# dcc.RadioItems(options=['pop', 'lifeExp', 'gdpPercap'], value='lifeExp', id='controls-and-radio-item'), # dcc.RadioItems(options=['pop', 'lifeExp', 'gdpPercap'], value='lifeExp', id='symbols_dropdown_list'),
# dcc.Dropdown(['pop', 'lifeExp', 'gdpPercap'], 'lifeExp', id='controls-and-radio-item'), # dcc.Dropdown(['pop', 'lifeExp', 'gdpPercap'], 'lifeExp', id='symbols_dropdown_list'),
dcc.Dropdown(id='controls-and-radio-item'), dcc.Dropdown(symbols, symbols[0], id='symbols_dropdown_list'),
# dash_table.DataTable(data=df.to_dict('records'), page_size=6), # dash_table.DataTable(data=df.to_dict('records'), page_size=6),
dcc.Graph( dcc.Graph(
figure={}, figure={},
id='controls-and-graph', id='controls-and-graph',
style={'height':'85vh'} style={'height':'85vh'}
), ),
dcc.Store(id="signal"), # dcc.Store(id="signal"),
# dcc.Store(id="dropdown-index"), dcc.Store(id="dropdown_index", data='0'),
dcc.Interval( dcc.Interval(
id='interval-component', id='interval-component',
interval=3*1000, # in milliseconds interval=3*1000, # in milliseconds
n_intervals=0, n_intervals=len(symbols),
disabled=True, disabled=True,
), ),
] ]
@ -886,7 +818,7 @@ if __name__ == "__main__":
# start / stop button callback # start / stop button callback
@callback(Output('interval-component', 'disabled'), @callback(Output('interval-component', 'disabled'),
Output("start-button", "children"), Output("start-button", "children"),
Output('controls-and-radio-item', 'disabled'), Output('symbols_dropdown_list', 'disabled'),
Input("start-button", "n_clicks"), Input("start-button", "n_clicks"),
State("start-button", "children"),) State("start-button", "children"),)
@ -900,9 +832,9 @@ if __name__ == "__main__":
return no_update return no_update
# interval callback # interval callback
@callback(Output('controls-and-radio-item', 'value'), @callback(Output('symbols_dropdown_list', 'value'),
Input("interval-component", "n_intervals"), Input("interval-component", "n_intervals"),
State('controls-and-radio-item', 'options'), State('symbols_dropdown_list', 'options'),
# State('dropdown-index', 'data'), # State('dropdown-index', 'data'),
) )
def cycle_syms(n, syms): def cycle_syms(n, syms):
@ -911,77 +843,77 @@ if __name__ == "__main__":
else: else:
return no_update return no_update
@cache.memoize(timeout=14400) # cache timeout set to 4 hours # @cache.memoize(timeout=14400) # cache timeout set to 4 hours
def global_store(): # def global_store():
j_obj = intelligent_loop_plots() # j_obj = intelligent_loop_plots()
return j_obj # return j_obj
# retrieve data button callbacks # retrieve data button callbacks
@callback( # @callback(
Output("button", "disabled", allow_duplicate=True), # Output("button", "disabled", allow_duplicate=True),
Input("button", "n_clicks"), # Input("button", "n_clicks"),
prevent_initial_call=True, # prevent_initial_call=True,
) # )
def disable_btn(n): # def disable_btn(n):
if n: # if n:
return True # return True
return no_update # return no_update
@callback( # @callback(
Output(component_id='signal', component_property='data'), # Output(component_id='signal', component_property='data'),
# Output(component_id='button', component_property='disabled'), # # Output(component_id='button', component_property='disabled'),
Input(component_id='button', component_property='n_clicks'), # Input(component_id='button', component_property='n_clicks'),
prevent_initial_call=True, # prevent_initial_call=True,
) # )
def get_data_cb(clicks): # def get_data_cb(clicks):
# global all_plot_sym, all_plot_ind, all_data, all_vol, all_macd, all_rsi # # global all_plot_sym, all_plot_ind, all_data, all_vol, all_macd, all_rsi
# if clicks == 0: # # if clicks == 0:
# return # no update # # return # no update
if not clicks or clicks == 0: # if not clicks or clicks == 0:
raise PreventUpdate # raise PreventUpdate
print("get data") # print("get data")
global_store() # global_store()
print("data retrieved") # print("data retrieved")
# unpacking # # unpacking
# json_data = json.loads(j_obj) # # json_data = json.loads(j_obj)
# all_plot_sym = json_data["all_plot_sym"] # # all_plot_sym = json_data["all_plot_sym"]
# all_plot_ind = json_data["all_plot_ind"] # # all_plot_ind = json_data["all_plot_ind"]
# all_data = pd.read_json(io.StringIO(json_data['all_data'])) # # all_data = pd.read_json(io.StringIO(json_data['all_data']))
# all_vol = pd.read_json(io.StringIO(json_data['all_vol'])) # # all_vol = pd.read_json(io.StringIO(json_data['all_vol']))
# all_macd = pd.read_json(io.StringIO(json_data['all_macd'])) # # all_macd = pd.read_json(io.StringIO(json_data['all_macd']))
# all_rsi = pd.read_json(io.StringIO(json_data['all_rsi'])) # # all_rsi = pd.read_json(io.StringIO(json_data['all_rsi']))
return clicks # return clicks
# Add controls to build the interaction # Add controls to build the interaction
# callback when data retrieve finishes triggered by signal # callback when data retrieve finishes triggered by signal
@callback( # @callback(
Output(component_id='controls-and-radio-item', component_property='options'), # Output(component_id='symbols_dropdown_list', component_property='options'),
Output(component_id='button', component_property='disabled'), # Output(component_id='button', component_property='disabled'),
Output(component_id='start-button', component_property='disabled'), # Output(component_id='start-button', component_property='disabled'),
Input(component_id='signal', component_property='data'), # Input(component_id='signal', component_property='data'),
) # )
def update_dropdown(in_data): # def update_dropdown(in_data):
if not in_data or in_data == 0: # if not in_data or in_data == 0:
raise PreventUpdate # raise PreventUpdate
# return no_update # # return no_update
print(f"input: {in_data}") # print(f"input: {in_data}")
j_obj = global_store() # j_obj = global_store()
# unpacking # # unpacking
json_data = json.loads(j_obj) # json_data = json.loads(j_obj)
all_plot_sym = json_data["all_plot_sym"] # all_plot_sym = json_data["all_plot_sym"]
print("dropdown menu options updated") # print("dropdown menu options updated")
# all_plot_sym = ["SPY", "AMZN"] # # all_plot_sym = ["SPY", "AMZN"]
return sorted(all_plot_sym), False, False # return sorted(all_plot_sym), False, False
# dropdown callback # dropdown callback
@callback( @callback(
Output(component_id='controls-and-graph', component_property='figure'), Output(component_id='controls-and-graph', component_property='figure'),
# Output("dropdown-index", "data"), # Output("dropdown-index", "data"),
Input(component_id='controls-and-radio-item', component_property='value'), Input(component_id='symbols_dropdown_list', component_property='value'),
# State('controls-and-radio-item', 'options') # State('symbols_dropdown_list', 'options')
# Input(component_id='signal', component_property='data'), # Input(component_id='signal', component_property='data'),
) )
@ -991,15 +923,18 @@ if __name__ == "__main__":
raise PreventUpdate raise PreventUpdate
# return no_update # return no_update
# col_chosen = "SPY" # col_chosen = "SPY"
j_obj = global_store() # j_obj = global_store()
# unpacking # # unpacking
json_data = json.loads(j_obj) # json_data = json.loads(j_obj)
# all_plot_sym = json_data["all_plot_sym"] # # all_plot_sym = json_data["all_plot_sym"]
all_plot_ind = json_data["all_plot_ind"] # all_plot_ind = json_data["all_plot_ind"]
all_data = pd.read_json(io.StringIO(json_data['all_data'])) # all_data = pd.read_json(io.StringIO(json_data['all_data']))
all_vol = pd.read_json(io.StringIO(json_data['all_vol'])) # all_vol = pd.read_json(io.StringIO(json_data['all_vol']))
all_macd = pd.read_json(io.StringIO(json_data['all_macd'])) # all_macd = pd.read_json(io.StringIO(json_data['all_macd']))
all_rsi = pd.read_json(io.StringIO(json_data['all_rsi'])) # 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( fig = make_subplots(
rows=3, rows=3,
@ -1011,48 +946,47 @@ if __name__ == "__main__":
) )
price_line = px.line( price_line = px.line(
all_data, data,
x=all_data.index, x=data.index,
y=[col_chosen, col_chosen+'_BOL200L', col_chosen+'_BOL200U', col_chosen+'_SMA200', col_chosen+'_SMA50', col_chosen+'_WVMA50'], y=data.columns.to_list(),
# y=[sym, sym+'_BOL200L', sym+'_BOL200U', sym+'_SMA200', sym+'_SMA50', sym+'_WVMA50'], # y=[sym, sym+'_BOL200L', sym+'_BOL200U', sym+'_SMA200', sym+'_SMA50', sym+'_WVMA50'],
) )
volume_line = px.bar( volume_line = px.bar(
all_vol, vol,
x=all_vol.index, x=vol.index,
# y=sym, y=vol.columns.to_list(),
y=col_chosen,
) )
macd_line = px.line( macd_line = px.line(
all_macd, macd,
x=all_macd.index, x=macd.index,
y=[col_chosen+'_MACD', col_chosen+'_SIG'], y=['_MACD', '_SIG'],
) )
macd_neg = all_macd.copy() macd_neg = macd.copy()
macd_pos = all_macd.copy() macd_pos = macd.copy()
macd_neg[macd_neg>0] = 0 macd_neg[macd_neg>0] = 0
macd_pos[macd_pos<0] = 0 macd_pos[macd_pos<0] = 0
macd_hist_pos = px.line( macd_hist_pos = px.line(
macd_pos, macd_pos,
x=macd_pos.index, 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_pos.update_traces(fill='tozeroy', line_color='rgba(0,100,0,0.5)', showlegend=False)
macd_hist_neg = px.line( macd_hist_neg = px.line(
macd_neg, macd_neg,
x=macd_neg.index, 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) macd_hist_neg.update_traces(fill='tozeroy', line_color='rgba(100,0,0,0.5)', showlegend=False)
rsi_line = px.line( rsi_line = px.line(
all_rsi, rsi,
x=all_rsi.index, x=rsi.index,
y=[col_chosen+'_RSI', col_chosen+'_VoRSI'], 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(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) 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.yaxis3.title="MACD"
fig.layout.yaxis4.title="RSI/VoRSI" 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(showlegend=False)
fig.update_layout(margin=dict(l=30, r=20, t=50, b=20)) fig.update_layout(margin=dict(l=30, r=20, t=50, b=20))