I am using plotly to plot. The dataframe contains OHLC data, which are plotted as candlesticks. Additionally, it has moving averages, which are plotted as scatter line types. From those MAs, I calculate zones using pandas. I would like to plot those zones on the chart as well. But I need the zones to be behind the candlesticks and MA lines.
Here is a sample data with a zone:
Date Time Open High Low Close ZoneBot ZoneTop
1/3/2021 22:01:00 1.77089 1.77126 1.77089 1.77126 1.772686 1.773486
1/3/2021 22:02:00 1.77141 1.77141 1.77126 1.77126 1.772704 1.773504
1/3/2021 22:03:00 1.77112 1.77146 1.77112 1.77136 1.772726 1.773526
1/3/2021 22:04:00 1.77121 1.77277 1.77114 1.77127 1.772747 1.773547
1/3/2021 22:05:00 1.7711 1.77132 1.77094 1.77094 1.772768 1.773568
1/3/2021 22:06:00 1.77117 1.77117 1.77052 1.77052 1.772784 1.773584
1/3/2021 22:07:00 1.77086 1.77086 1.7706 1.77083 1.772796 1.773596
1/3/2021 22:08:00 1.77088 1.77088 1.77086 1.77086 1.772811 1.773611
1/3/2021 22:09:00 1.77084 1.77084 1.77071 1.77071 1.772826 1.773626
1/3/2021 22:10:00 1.7707 1.77084 1.77064 1.77064 1.772839 1.773639
I have tried creating traces and filling between them. But fill is on top of everything else. The candles and MAs are not visible anymore.
I understand you cannot set the order of traces like in matplotlib or mplfinance; I saw the request already submitted for zorder on github.
So I was thinking I could try drawing a shape, because the shape you can set to go behind the traces.
Here is what I tried, but it doesn't plot anything:
# create a path shape that follows the curve of the line
path_commands = f'M{df.index[0],df[f"ZoneBot"][0]} '
for i in range(1, len(df.index)):
path_commands += f'L{df.index[i],df[f"ZoneBot"][i]} '
for i in range(len(df.index)-1, -1, -1):
path_commands += f'L{df.index[i],df[f"ZoneTop"][i]} '
path_commands += f'Z'
figure.add_shape(type='path',
path=path_commands,
fillcolor='black',
line=dict(color='black'),
opacity=0.5,
xref='x',
yref='y')
I also thought I could use rectangles for each data point. The problem with this is it took way to long to render. If there are 100 data points. That is 100 shapes per zone being rendered. Here is an example of that code:
for i in range(1,len(df.index)-1):
figure.add_shape(type="rect",
x0=df.index[i], x1=df.index[i+1], y0=df[f'ZoneBot'].iloc[i],
y1=df[f'ZoneTop'].iloc[i+1],fillcolor='black',
line=dict(color='black'),)
I request guidance as I am not able to find a solution by googling or figuring it out myself.
The answer is what @Derek O said plus to use color="rgba(255,0,0,0.1)"
The last float is the alpha channel (which is opacity). By doing this, it allows you to select your own fill color, set the correct opacity, and still see the candlesticks.