I have currently achart where I display the price of an asset and add some moving average traces. Now I want to add other indicators to the chart ( OBV, MACD, RSI ). Every time the user calls one of these three I would like my current chart to be fractioned in subplots. Let say I add OBV, my display will have 2 subplots ( the price on row 1and OBV on row 2 ). Now if I want to add MACD, it should display the price on row 1, OBV on row 2 and MACD on row 3 . Now if the user decide to remove OBV it should display price on row 1 and MACD on row 2.
Currently I am only able to display each indicators for a specific row. How can I manage that ?
Here is my code for the moment :
def display(value, timeframes, indicators, start_date, end_date):
st.write(f"""
# {value}
Price chart""")
df = pd.read_csv(f’data/{timeframes}/{value}-{timeframes}-data.csv’, parse_dates=[‘timestamp’], index_col=‘timestamp’)
if start_date < end_date:
df = df[start_date : end_date]
else:
st.error('Error: End date must fall after start date.')
fig = make_subplots(rows = 5, cols = 1, shared_xaxes = True, vertical_spacing = 0.01, row_heights = [0.5, 0.1, 0.2, 0.2, 0.2])
trace_price = fig.add_trace(
go.Candlestick(
x = df.index,
open = df['open'],
high = df['high'],
low = df['low'],
close = df['close'],
name = 'Candlestick'),
#secondary_y = True,
row = 1, col = 1
)
colors = ['green' if row['open'] - row['close'] >= 0
else 'red' for index, row in df.iterrows()]
fig.add_trace(go.Bar(x=df.index,
y=df['volume'],
marker_color=colors), row=2, col=1)
for indi in indicators:
#FIRST SUBPLOT obj = indicators.indicators(df, range_indi, periods)
if indi.startswith('SMA'):
sma_trace = go.Scatter(
x=df.index, y=indicator.simple_moving_average(df,int(indi[3:])),
line=dict(color= np.random.choice(colors_sma, replace = False), width=1),
name = f'SMA{indi[3:]}'
)
fig.add_trace(sma_trace,
#secondary_y = True,
row = 1, col = 1)
if indi.startswith('WMA'):
wma_trace = go.Scatter(
x=df.index, y=indicator.weighted_moving_average(df,int(indi[3:])),
line=dict(color=np.random.choice(colors_wma, replace = False), width=1),
name = f'WMA{indi[3:]}'
)
fig.add_trace(wma_trace,
#secondary_y = True,
row = 1, col = 1)
if indi.startswith('EMA'):
ema_trace = go.Scatter(
x=df.index, y=indicator.exponential_moving_average(df,int(indi[3:])),
line=dict(color=np.random.choice(colors_ema, replace = False), width=1),
name = f'EMA{indi[3:]}'
)
fig.add_trace(ema_trace,
#secondary_y = True,
row = 1, col = 1)
# SECOND SUBPLOT
if indi.startswith('OBV'):
obv_trace = go.Scatter(
x=df.index, y= indicator.on_balance_volume(df, int(indi[3:])), line=dict(color='red', width=1),
name = f'OBV{indi[3:]}'
)
fig.add_trace(obv_trace, row = 3, col = 1)
# THIRD SUBPLOT
if indi.startswith('RSI'):
fig.add_trace(
go.Scatter(
x=df.index, y=indicator.relative_strength_index(df, periods = 14),
name='RSI', marker_color= 'blue'
), row=4, col=1,
)
fig.add_trace(
go.Scatter(
x=df.index, y=[70] * len(df.index),
name='Overbought', marker_color='#109618',
line = dict(dash='dot'), showlegend=False,
), row=4, col=1,
)
fig.add_trace(
go.Scatter(
x=df.index, y=[30] * len(df.index),
name='Oversold', marker_color='#109618',
line = dict(dash='dot'),showlegend=False,
),row=4, col=1,
)
# FOURTH SUBPLOT
if indi.startswith('MACD'):
macd, macd_s, macd_h = indicator.moving_average_convergence_divergence(df)
#fast signal
fig.add_trace(
go.Scatter(
x = df.index, y = macd,
line=dict(color='blue', width=1),
name = 'macd',
), row = 5, col = 1,
)
#slow signal
fig.add_trace(
go.Scatter(
x = df.index, y = macd_s,
line=dict(color='#000000', width=1),
name = 'macd',
), row = 5, col = 1,
)
# Colorize the histogram values
colors = np.where(macd_h < 0, 'red', 'green')
# Plot the histogram
fig.add_trace(
go.Bar(
x = df.index, y = macd_h,
name='histogram', marker_color=colors,
), row = 5, col = 1,
)
fig.update_layout(width= 800,height = 800 , xaxis_rangeslider_visible=False, showlegend= False)
fig.update_xaxes(gridcolor ='#7f7f7f')
# Set y-axes titles
fig.update_yaxes(title_text="Price", row = 1, col = 1)
fig.update_yaxes(title_text="Volume", row = 2, col = 1)
fig.update_yaxes(title_text="OBV", row = 3, col = 1)
fig.update_yaxes(title_text="RSI", row = 4, col = 1)
fig.update_yaxes(title_text="MACD", row = 5, col = 1)
fig.update_yaxes(gridcolor ='#7f7f7f')
price = st.plotly_chart(fig, width= 800,height = 800)
return price