RazzleDazzle
RazzleDazzle

Reputation: 141

Conditionally changing background color in matplotlib plot

I am plotting stock prices and a moving average in Python / Matplotlib. Now I would like to change the backgroundcolor to red if the close is less than -5% below the moving average, and to green when the close is more than 5% above the moving average. To make things easier, the dataframe already contains a column "above_below": =1 if price is >5% above the MA, -1 if price < -5% below MA. How could I implement a conditional background based on this column?

Here is what I have so far:

from yahoo_fin import stock_info as si
import talib
import numpy as np
import matplotlib.pyplot as plt

sym = 'SBUX'
data = si.get_data(sym, start_date='01/01/2022')
data['ma10'] = talib.EMA(data['close'], 10)
conditions = [(data['close'] / data['ma10'] -1 > 0.05), (data['close'] / data['ma10'] -1 <-0.05)]
values = [1,-1]

data['above_below'] = np.select(conditions, values, default = np.nan)
fig, ax = plt.subplots()
ax.plot(data.close)
ax.plot(data.ma10)
ax.pcolorfast(ax.get_xlim(), ax.get_ylim(), data['above_below'].values[np.newaxis], cmap='RdYlGn', alpha=0.3)
plt.show()

However the result doesn't seem to be right. The dataframe looks good:

                  open        high         low       close    adjclose    volume ticker        ma10  above_below
2022-01-03  116.470001  117.800003  114.779999  116.680000  114.626328   5475700   SBUX         NaN          NaN
2022-01-04  116.900002  117.050003  114.169998  114.239998  112.229271   8367600   SBUX         NaN          NaN
2022-01-05  114.400002  114.959999  110.400002  110.440002  108.496162   8662300   SBUX         NaN          NaN
2022-01-06  110.000000  111.879997  109.989998  111.139999  109.183838   6099900   SBUX         NaN          NaN
2022-01-07  108.220001  109.709999  107.480003  107.570000  105.676674  11266400   SBUX         NaN          NaN
2022-01-10  106.620003  107.010002  104.419998  106.029999  104.163773   8499400   SBUX         NaN          NaN
2022-01-11  106.040001  106.169998  103.709999  104.040001  102.208801  13073200   SBUX         NaN          NaN
2022-01-12  104.440002  105.320000  103.680000  103.870003  102.041801  11810500   SBUX         NaN          NaN
2022-01-13  104.150002  104.669998  102.089996  102.400002  100.597672   9818500   SBUX         NaN          NaN
2022-01-14  101.910004  101.910004   99.089996  100.120003   98.357796  13703200   SBUX  107.653001         -1.0
2022-01-18   99.169998   99.360001   97.510002   97.730003   96.009865  11396000   SBUX  105.848819         -1.0
2022-01-19   97.940002   98.389999   96.779999   96.870003   95.165001  10856800   SBUX  104.216307         -1.0
2022-01-20   97.489998   98.940002   95.589996   95.720001   94.035240  20311500   SBUX  102.671524         -1.0
2022-01-21   95.900002   98.410004   95.470001   96.309998   94.614853  13438300   SBUX  101.514883         -1.0
2022-01-24   94.750000   98.349998   94.410004   98.099998   96.373344  17201400   SBUX  100.893995          NaN
2022-01-25   96.669998   98.089996   95.129997   97.010002   95.302536  12368500   SBUX  100.187814          NaN
2022-01-26   97.699997   98.639999   94.900002   95.580002   93.897705  11863000   SBUX   99.350030          NaN

The MA requires at least 10 days of data to be calculated and that seems fine. So I would expect that the red / green background will start with the moving average. However in the chart, the background colors seem off by some offset. There is a red background in the first few datapoints that don't even have a moving average yet. And also at the end, it is colored green, when the price is below the MA.

When I checked it with other ticker symbols, it also is kind of off...

What could be the reason for this issue?

Upvotes: 1

Views: 535

Answers (1)

RazzleDazzle
RazzleDazzle

Reputation: 141

I think I found a simple solution by just adding the following line after fig, ax = plt.subplots(): ax.margins(0) enter image description here

Upvotes: 1

Related Questions