Skip to content

Commit 6bfc0be

Browse files
fill_between now accepts list of dict for multiple fill_betweens
1 parent 8501f81 commit 6bfc0be

File tree

4 files changed

+75
-17
lines changed

4 files changed

+75
-17
lines changed

examples/macd.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import pandas as pd
2+
import mplfinance as mpf
3+
4+
import matplotlib.dates as mdates
5+
6+
idf = pd.read_csv('data/SPY_20110701_20120630_Bollinger.csv',index_col=0,parse_dates=True)
7+
df = idf.loc['2011-07-01':'2011-12-30',:]
8+
9+
10+
# =======
11+
# MACD:
12+
13+
# df = df.iloc[0:30]
14+
15+
exp12 = df['Close'].ewm(span=12, adjust=False).mean()
16+
exp26 = df['Close'].ewm(span=26, adjust=False).mean()
17+
macd = exp12 - exp26
18+
signal = macd.ewm(span=9, adjust=False).mean()
19+
histogram = macd - signal
20+
21+
fb_green = dict(y1=macd.values,y2=signal.values,where=signal<macd,color="#93c47d",alpha=0.6,interpolate=True)
22+
fb_red = dict(y1=macd.values,y2=signal.values,where=signal>macd,color="#e06666",alpha=0.6,interpolate=True)
23+
fb_green['panel'] = 1
24+
fb_red['panel'] = 1
25+
fb = [fb_green,fb_red]
26+
27+
apds = [mpf.make_addplot(exp12,color='lime'),
28+
mpf.make_addplot(exp26,color='c'),
29+
mpf.make_addplot(histogram,type='bar',width=0.7,panel=1,
30+
color='dimgray',alpha=1,secondary_y=True),
31+
mpf.make_addplot(macd,panel=1,color='fuchsia',secondary_y=False),
32+
mpf.make_addplot(signal,panel=1,color='b',secondary_y=False)#,fill_between=fb),
33+
]
34+
35+
s = mpf.make_mpf_style(base_mpf_style='classic',rc={'figure.facecolor':'lightgray'})
36+
37+
mpf.plot(df,type='candle',addplot=apds,figscale=1.6,figratio=(6,5),title='\n\nMACD',
38+
style=s,volume=True,volume_panel=2,panel_ratios=(3,4,1),fill_between=fb)#,show_nontrading=True)
39+

src/mplfinance/_arg_validators.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import numpy as np
44
import datetime
55
from mplfinance._helpers import _list_of_dict, _mpf_is_color_like
6+
from mplfinance._helpers import _num_or_seq_of_num
67
import matplotlib as mpl
78
import warnings
89

@@ -434,3 +435,15 @@ def _check_for_external_axes(config):
434435

435436
external_axes_mode = True if isinstance(config['ax'],mpl.axes.Axes) else False
436437
return external_axes_mode
438+
439+
def _valid_fb_dict(value):
440+
return (isinstance(value,dict) and
441+
'y1' in value and
442+
_num_or_seq_of_num(value['y1']))
443+
444+
def _fill_between_validator(value):
445+
if _num_or_seq_of_num(value): return True
446+
if _valid_fb_dict(value): return True
447+
if _list_of_dict(value):
448+
return all([_valid_fb_dict(v) for v in value])
449+
return False

src/mplfinance/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
version_info = (0, 12, 8, 'beta', 9)
2+
version_info = (0, 12, 9, 'beta', 0)
33

44
_specifier_ = {'alpha': 'a','beta': 'b','candidate': 'rc','final': ''}
55

src/mplfinance/plotting.py

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
from mplfinance import _styles
3333

3434
from mplfinance._arg_validators import _check_and_prepare_data, _mav_validator
35-
from mplfinance._arg_validators import _get_valid_plot_types
35+
from mplfinance._arg_validators import _get_valid_plot_types, _fill_between_validator
3636
from mplfinance._arg_validators import _process_kwargs, _validate_vkwargs_dict
3737
from mplfinance._arg_validators import _kwarg_not_implemented, _bypass_kwarg_validation
3838
from mplfinance._arg_validators import _hlines_validator, _vlines_validator
@@ -304,9 +304,7 @@ def _valid_plot_kwargs():
304304
'Description' : 'fill between specification as y-value, or sequence of'+
305305
' y-values, or dict containing key "y1" plus any additional'+
306306
' kwargs for `fill_between()`',
307-
'Validator' : lambda value: _num_or_seq_of_num(value) or
308-
(isinstance(value,dict) and 'y1' in value and
309-
_num_or_seq_of_num(value['y1'])) },
307+
'Validator' : _fill_between_validator },
310308

311309
'tight_layout' : { 'Default' : False,
312310
'Description' : 'True|False implement tight layout (minimal padding around Figure)'+
@@ -705,19 +703,23 @@ def plot( data, **kwargs ):
705703
# fill_between is NOT supported for external_axes_mode
706704
# (caller can easily call ax.fill_between() themselves).
707705
if config['fill_between'] is not None and not external_axes_mode:
708-
fb = config['fill_between']
709-
panid = config['main_panel']
710-
if isinstance(fb,dict):
706+
fblist = config['fill_between']
707+
panid = config['main_panel']
708+
if _num_or_seq_of_num(fblist):
709+
fblist = [dict(y1=fblist),]
710+
elif isinstance(fblist,dict):
711+
fblist = [fblist,]
712+
if not _list_of_dict(fblist):
713+
raise TypeError('Bad type for `fill_between` specifier.')
714+
for fb in fblist:
711715
if 'x' in fb:
712716
raise ValueError('fill_between dict may not contain `x`')
713717
if 'panel' in fb:
714718
panid = fb['panel']
715719
del fb['panel']
716-
else:
717-
fb = dict(y1=fb)
718-
fb['x'] = xdates
719-
ax = panels.at[panid,'axes'][0]
720-
ax.fill_between(**fb)
720+
fb['x'] = xdates
721+
ax = panels.at[panid,'axes'][0]
722+
ax.fill_between(**fb)
721723

722724
# put the primary axis on one side,
723725
# and the twinx() on the "other" side:
@@ -1061,9 +1063,13 @@ def _addplot_apply_supplements(ax,apdict,xdates):
10611063
ax.set_yscale(ysd)
10621064
# added by Wen
10631065
if "fill_between" in apdict and apdict['fill_between'] is not None:
1064-
fb = apdict['fill_between']
1065-
fb['x'] = xdates
1066-
ax.fill_between(**fb)
1066+
fblist = apdict['fill_between']
1067+
if isinstance(fblist,dict):
1068+
fblist = [fblist,]
1069+
if _list_of_dict(fblist):
1070+
for fb in fblist:
1071+
fb['x'] = xdates
1072+
ax.fill_between(**fb)
10671073

10681074
def _set_ylabels_side(ax_pri,ax_sec,primary_on_right):
10691075
# put the primary axis on one side,
@@ -1241,7 +1247,7 @@ def _valid_addplot_kwargs():
12411247
'Validator' : lambda value: _is_marketcolor_object(value) },
12421248
'fill_between': { 'Default' : None, # added by Wen
12431249
'Description' : " fill region",
1244-
'Validator' : lambda value: isinstance(value,dict) },
1250+
'Validator' : _fill_between_validator },
12451251

12461252
}
12471253

0 commit comments

Comments
 (0)