Reputation: 141
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
Reputation: 141
I think I found a simple solution by just adding the following line after fig, ax = plt.subplots():
ax.margins(0)
Upvotes: 1