plotly,python, plot histogram over other subplot?
The data is time series, and I imagine several subplots with some overlaying the others in attempt to consolidate my favorite technical indicators. In regards to the histogram, I would like to achieve something like this:
How can I achieve this properly?
have tried:
- googling: "plotly overlay histogram","plotly overlay barchart","plotly overlay multiple sublots"
- adding specs with secondary_y=True when creating the subplots.
- adding barmode='stack' in different places, which doesn't seem to work by itself.
fig = make_subplots(
rows=3,
cols=1,
shared_xaxes=False,
vertical_spacing=0,
#subplot_titles=('candles','volume','atr')
row_width=[.3,.5,1],
specs=[
[{'secondary_y':False}],
[{'secondary_y':False}],
[{'secondary_y':True}]
]
)
candle = go.Candlestick(
x=df.date,
open=df.open,
high=df.high,
low=df.low,
close=df.close,
name='Candles',
increasing_line_color='#0ebc6e',
decreasing_line_color='#e8482c',
#increasing_line_color='green',
#decreasing_line_color='gray',
line={'width': 1},
hoverlabel={
'font':{
'color':'white',
'family':'Open Sans',
'size':15
}
},
)
vol_hist = go.Histogram(
x=df.volume,
y=df.close,
orientation='h',
name='vol hist',
nbinsx=len(df.volume),
nbinsy=len(df.close),
hovertemplate=[],
marker={
'color':'steelblue'
},
)
bb_hi = go.Scatter(
x=df.date,
y=df.bb_high,
name='bollinger_high',
line={'color':'orange','width':1},
hovertemplate=[],
)
bb_low = go.Scatter(
x=df.date,
y=df.bb_low,
name='bollinger_low',
line={'color':'orange','width':1},
hovertemplate=[],
)
vol = go.Bar(
x=df.date,
y=df.volume,
name='Volume',
marker_color='steelblue',
)
atr = go.Scatter(
x=df.date,
y=df.atr,
name='ATR',
line={'color':'steelblue','width':1}
)
fig.add_trace(candle,row=1,col=1)
fig.add_trace(vol_hist,row=1,col=1)
#fig.add_trace(bb_hi,row=1,col=1)
#fig.add_trace(bb_low,row=1,col=1)
fig.add_trace(atr,row=3,col=1)
fig.add_trace(vol,row=2,col=1)
#fig.add_trace(anime)
Solution 1:
I first overlaid the histogram of the candlestick, volume, and closing price using two axes of the x-axis, since it cannot be done in layers. This could be achieved by referring to this example. Secondly, I added a bar chart of volume, then Bollinger Bands, and finally EMA. This is the result of outputting fig.data
one step at a time, checking the contents, and making modifications. The remaining task is to display the x-axis of volume and EMA. This is as far as I can go.
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import pandas as pd
import numpy as np
import yfinance as yf
df = yf.download("AAPL", start="2021-01-01", end="2021-12-01")
df.reset_index(inplace=True)
df.columns = ['date', 'open', 'high', 'low', 'close', 'adj close', 'volume']
df['ma'] = df['close'].rolling(25).mean()
df['sigma'] = df['close'].rolling(25).std()
df['bb_high'] = df['ma'] + df['sigma'] * 2
df['bb_low'] = df['ma'] - df['sigma'] * 2
fig = make_subplots(rows=3, cols=1,
vertical_spacing=0.025,
row_heights=[0.6,0.20,0.20],
shared_xaxes=False,
specs=[[{"secondary_y": True}],[{"secondary_y": False}],[{"secondary_y": False}]])
fig.add_trace(
go.Histogram(
x=df.volume,
y=df.close,
orientation='h',
name='vol hist',
nbinsx=len(df.volume),
nbinsy=len(df.close),
hovertemplate=[],
opacity=0.4,
marker={
'color':'steelblue'
},
), secondary_y=True)
fig.add_trace(
go.Candlestick(
x=df.date,
open=df.open,
high=df.high,
low=df.low,
close=df.close,
name='Candles',
increasing_line_color='#0ebc6e',
decreasing_line_color='#e8482c',
line={'width': 1},
hoverlabel={
'font':{
'color':'white',
'family':'Open Sans',
'size':15
}
},
), secondary_y=True)
fig.add_trace(
go.Scatter(
x=df.date,
y=df.bb_high,
name='bollinger_high',
line={'color':'orange','width':1},
hovertemplate=[],
), secondary_y=False)
fig.add_trace(
go.Scatter(
x=df.date,
y=df.bb_low,
name='bollinger_low',
line={'color':'orange','width':1},
hovertemplate=[],
), secondary_y=False)
fig.add_trace(
go.Bar(
x=df.date,
y=df.volume,
name='Volume',
marker_color='steelblue',
), secondary_y=False, row=2, col=1)
fig.add_trace(
go.Scatter(
x=df.date,
y=df.close.ewm(26).mean(),
name='EMA',
line={'color':'steelblue','width':2}
), secondary_y=False, row=3, col=1)
fig.update_layout(xaxis2={'anchor': 'y', 'overlaying': 'x', 'side': 'top', 'autorange':'reversed'})
fig.data[0].update(xaxis='x2')
fig.update_layout(yaxis={'tickvals': np.arange(120,170,10)})
fig.data[4].update(xaxis='x')
fig.data[5].update(xaxis='x')
fig.update_xaxes(rangeslider_visible=False, showticklabels=True, row=1, col=1)
fig.update_layout(autosize=False, width=1000, height=800)
fig.show()