1
1
import matplotlib .dates as mdates
2
+ import matplotlib .colors as mcolors
2
3
import pandas as pd
3
4
import numpy as np
4
5
import datetime
@@ -52,7 +53,7 @@ def _check_and_prepare_data(data, config):
52
53
columns = ('Open' , 'High' , 'Low' , 'Close' , 'Volume' )
53
54
if all ([c .lower () in data for c in columns [0 :4 ]]):
54
55
columns = ('open' , 'high' , 'low' , 'close' , 'volume' )
55
-
56
+
56
57
o , h , l , c , v = columns
57
58
cols = [o , h , l , c ]
58
59
@@ -100,7 +101,7 @@ def _get_valid_plot_types(plottype=None):
100
101
return _alias_types [plottype ]
101
102
else :
102
103
return plottype
103
-
104
+
104
105
105
106
def _mav_validator (mav_value ):
106
107
'''
@@ -142,17 +143,6 @@ def _valid_mav(value, is_period=True):
142
143
return True
143
144
return False
144
145
145
- def _colors_validator (value ):
146
- if not isinstance (value , (list , tuple , np .ndarray )):
147
- return False
148
-
149
- for v in value :
150
- if v :
151
- if v is not None and not isinstance (v , (dict , str )):
152
- return False
153
-
154
- return True
155
-
156
146
157
147
def _hlines_validator (value ):
158
148
if isinstance (value ,dict ):
@@ -204,11 +194,11 @@ def _alines_validator(value, returnStandardizedValue=False):
204
194
A sequence of (line0, line1, line2), where:
205
195
206
196
linen = (x0, y0), (x1, y1), ... (xm, ym)
207
-
197
+
208
198
or the equivalent numpy array with two columns. Each line can be a different length.
209
199
210
200
The above is from the matplotlib LineCollection documentation.
211
- It basically says that the "segments" passed into the LineCollection constructor
201
+ It basically says that the "segments" passed into the LineCollection constructor
212
202
must be a Sequence of Sequences of 2 or more xy Pairs. However here in `mplfinance`
213
203
we want to allow that (seq of seq of xy pairs) _as well as_ just a sequence of pairs.
214
204
Therefore here in the validator we will allow both:
@@ -270,8 +260,8 @@ def _tlines_subvalidator(value):
270
260
def _bypass_kwarg_validation (value ):
271
261
''' For some kwargs, we either don't know enough, or
272
262
the validation is too complex to make it worth while,
273
- so we bypass kwarg validation. If the kwarg is
274
- invalid, then eventually an exception will be
263
+ so we bypass kwarg validation. If the kwarg is
264
+ invalid, then eventually an exception will be
275
265
raised at the time the kwarg value is actually used.
276
266
'''
277
267
return True
@@ -300,7 +290,7 @@ def _process_kwargs(kwargs, vkwargs):
300
290
Given a "valid kwargs table" and some kwargs, verify that each key-word
301
291
is valid per the kwargs table, and that the value of the kwarg is the
302
292
correct type. Fill a configuration dictionary with the default value
303
- for each kwarg, and then substitute in any values that were provided
293
+ for each kwarg, and then substitute in any values that were provided
304
294
as kwargs and return the configuration dictionary.
305
295
'''
306
296
# initialize configuration from valid_kwargs_table:
@@ -327,7 +317,7 @@ def _process_kwargs(kwargs, vkwargs):
327
317
328
318
# ---------------------------------------------------------------
329
319
# At this point in the loop, if we have not raised an exception,
330
- # then kwarg is valid as far as we can tell, therefore,
320
+ # then kwarg is valid as far as we can tell, therefore,
331
321
# go ahead and replace the appropriate value in config:
332
322
333
323
config [key ] = value
@@ -346,7 +336,7 @@ def _scale_padding_validator(value):
346
336
if key not in valid_keys :
347
337
raise ValueError ('Invalid key "' + str (key )+ '" found in `scale_padding` dict.' )
348
338
if not isinstance (value [key ],(int ,float )):
349
- raise ValueError ('`scale_padding` dict contains non-number at key "' + str (key )+ '"' )
339
+ raise ValueError ('`scale_padding` dict contains non-number at key "' + str (key )+ '"' )
350
340
return True
351
341
else :
352
342
raise ValueError ('`scale_padding` kwarg must be a number, or dict of (left,right,top,bottom) numbers.' )
@@ -370,11 +360,29 @@ def _yscale_validator(value):
370
360
return True
371
361
372
362
363
+ def _is_marketcolor_object (obj ):
364
+ if not isinstance (obj ,dict ): return False
365
+ market_colors_keys = ('candle' ,'edge' ,'wick' ,'ohlc' )
366
+ return all ([k in obj for k in market_colors_keys ])
367
+
368
+
369
+ def _mco_validator (value ): # marketcolor overrides validator
370
+ if isinstance (value ,dict ): # not yet supported, but maybe we will have other
371
+ if 'colors' not in value : # kwargs related to mktcolor overrides (ex: `mco_faceonly`)
372
+ raise ValueError ('`marketcolor_overrides` as dict must contain `colors` key.' )
373
+ colors = value ['colors' ]
374
+ else :
375
+ colors = value
376
+ if not isinstance (colors ,(list ,tuple ,np .ndarray )):
377
+ return False
378
+ return all ([(c is None or mcolors .is_color_like (c ) or _is_marketcolor_object (c )) for c in colors ])
379
+
380
+
373
381
def _check_for_external_axes (config ):
374
382
'''
375
- Check that all `fig` and `ax` kwargs are either ALL None,
383
+ Check that all `fig` and `ax` kwargs are either ALL None,
376
384
or ALL are valid instances of Figures/Axes:
377
-
385
+
378
386
An external Axes object can be passed in three places:
379
387
- mpf.plot() `ax=` kwarg
380
388
- mpf.plot() `volume=` kwarg
@@ -391,7 +399,7 @@ def _check_for_external_axes(config):
391
399
raise TypeError ('addplot must be `dict`, or `list of dict`, NOT ' + str (type (addplot )))
392
400
for apd in addplot :
393
401
ap_axlist .append (apd ['ax' ])
394
-
402
+
395
403
if len (ap_axlist ) > 0 :
396
404
if config ['ax' ] is None :
397
405
if not all ([ax is None for ax in ap_axlist ]):
@@ -416,6 +424,6 @@ def _check_for_external_axes(config):
416
424
raise ValueError ('`volume` must be of type `matplotlib.axis.Axes`' )
417
425
#if not isinstance(config['fig'],mpl.figure.Figure):
418
426
# raise ValueError('`fig` kwarg must be of type `matplotlib.figure.Figure`')
419
-
427
+
420
428
external_axes_mode = True if isinstance (config ['ax' ],mpl .axes .Axes ) else False
421
429
return external_axes_mode
0 commit comments