@@ -119,7 +119,17 @@ def _valid_plot_kwargs():
119
119
'mav' : { 'Default' : None ,
120
120
'Description' : 'Moving Average window size(s); (int or tuple of ints)' ,
121
121
'Validator' : _mav_validator },
122
+
123
+ 'ema' : { 'Default' : None ,
124
+ 'Description' : 'Exponential Moving Average window size(s); (int or tuple of ints)' ,
125
+ 'Validator' : _mav_validator },
122
126
127
+ 'mavcolors' : { 'Default' : None ,
128
+ 'Description' : 'color cycle for moving averages (list or tuple of colors)' +
129
+ '(overrides mpf style mavcolors).' ,
130
+ 'Validator' : lambda value : isinstance (value ,(list ,tuple )) and
131
+ all ([mcolors .is_color_like (v ) for v in value ]) },
132
+
123
133
'renko_params' : { 'Default' : dict (),
124
134
'Description' : 'dict of renko parameters; call `mpf.kwarg_help("renko_params")`' ,
125
135
'Validator' : lambda value : isinstance (value ,dict ) },
@@ -454,6 +464,13 @@ def plot( data, **kwargs ):
454
464
else :
455
465
raise TypeError ('style should be a `dict`; why is it not?' )
456
466
467
+ if config ['mavcolors' ] is not None :
468
+ config ['_ma_color_cycle' ] = cycle (config ['mavcolors' ])
469
+ elif style ['mavcolors' ] is not None :
470
+ config ['_ma_color_cycle' ] = cycle (style ['mavcolors' ])
471
+ else :
472
+ config ['_ma_color_cycle' ] = None
473
+
457
474
if not external_axes_mode :
458
475
fig = plt .figure ()
459
476
_adjust_figsize (fig ,config )
@@ -532,8 +549,10 @@ def plot( data, **kwargs ):
532
549
533
550
if ptype in VALID_PMOVE_TYPES :
534
551
mavprices = _plot_mav (axA1 ,config ,xdates ,pmove_avgvals )
552
+ emaprices = _plot_ema (axA1 , config , xdates , pmove_avgvals )
535
553
else :
536
554
mavprices = _plot_mav (axA1 ,config ,xdates ,closes )
555
+ emaprices = _plot_ema (axA1 , config , xdates , closes )
537
556
538
557
avg_dist_between_points = (xdates [- 1 ] - xdates [0 ]) / float (len (xdates ))
539
558
if not config ['tight_layout' ]:
@@ -599,6 +618,13 @@ def plot( data, **kwargs ):
599
618
else :
600
619
for jj in range (0 ,len (mav )):
601
620
retdict ['mav' + str (mav [jj ])] = mavprices [jj ]
621
+ if config ['ema' ] is not None :
622
+ ema = config ['ema' ]
623
+ if len (ema ) != len (emaprices ):
624
+ warnings .warn ('len(ema)=' + str (len (ema ))+ ' BUT len(emaprices)=' + str (len (emaprices )))
625
+ else :
626
+ for jj in range (0 , len (ema )):
627
+ retdict ['ema' + str (ema [jj ])] = emaprices [jj ]
602
628
retdict ['minx' ] = minx
603
629
retdict ['maxx' ] = maxx
604
630
retdict ['miny' ] = miny
@@ -1140,10 +1166,7 @@ def _plot_mav(ax,config,xdates,prices,apmav=None,apwidth=None):
1140
1166
if len (mavgs ) > 7 :
1141
1167
mavgs = mavgs [0 :7 ] # take at most 7
1142
1168
1143
- if style ['mavcolors' ] is not None :
1144
- mavc = cycle (style ['mavcolors' ])
1145
- else :
1146
- mavc = None
1169
+ mavc = config ['_ma_color_cycle' ]
1147
1170
1148
1171
for idx ,mav in enumerate (mavgs ):
1149
1172
mean = pd .Series (prices ).rolling (mav ).mean ()
@@ -1158,6 +1181,42 @@ def _plot_mav(ax,config,xdates,prices,apmav=None,apwidth=None):
1158
1181
mavp_list .append (mavprices )
1159
1182
return mavp_list
1160
1183
1184
+
1185
+ def _plot_ema (ax ,config ,xdates ,prices ,apmav = None ,apwidth = None ):
1186
+ '''ema: exponential moving average'''
1187
+ style = config ['style' ]
1188
+ if apmav is not None :
1189
+ mavgs = apmav
1190
+ else :
1191
+ mavgs = config ['ema' ]
1192
+ mavp_list = []
1193
+ if mavgs is not None :
1194
+ shift = None
1195
+ if isinstance (mavgs ,dict ):
1196
+ shift = mavgs ['shift' ]
1197
+ mavgs = mavgs ['period' ]
1198
+ if isinstance (mavgs ,int ):
1199
+ mavgs = mavgs , # convert to tuple
1200
+ if len (mavgs ) > 7 :
1201
+ mavgs = mavgs [0 :7 ] # take at most 7
1202
+
1203
+ mavc = config ['_ma_color_cycle' ]
1204
+
1205
+ for idx ,mav in enumerate (mavgs ):
1206
+ # mean = pd.Series(prices).rolling(mav).mean()
1207
+ mean = pd .Series (prices ).ewm (span = mav ,adjust = False ).mean ()
1208
+ if shift is not None :
1209
+ mean = mean .shift (periods = shift [idx ])
1210
+ emaprices = mean .values
1211
+ lw = config ['_width_config' ]['line_width' ]
1212
+ if mavc :
1213
+ ax .plot (xdates , emaprices , linewidth = lw , color = next (mavc ))
1214
+ else :
1215
+ ax .plot (xdates , emaprices , linewidth = lw )
1216
+ mavp_list .append (emaprices )
1217
+ return mavp_list
1218
+
1219
+
1161
1220
def _auto_secondary_y ( panels , panid , ylo , yhi ):
1162
1221
# If mag(nitude) for this panel is not yet set, then set it
1163
1222
# here, as this is the first ydata to be plotted on this panel:
0 commit comments