@@ -474,7 +474,50 @@ def plot( data, **kwargs ):
474
474
raise TypeError ('addplot must be `dict`, or `list of dict`, NOT ' + str (type (addplot )))
475
475
476
476
for apdict in addplot :
477
+
478
+ panid = apdict ['panel' ]
479
+ if panid == 'main' : panid = 0 # for backwards compatibility
480
+ elif panid == 'lower' : panid = 1 # for backwards compatibility
481
+
482
+ #--------------------------------------------------------------#
483
+ # Note: _auto_secondary_y() sets the 'magnitude' column in the
484
+ # `panels` dataframe, which is needed for automatically
485
+ # determining if secondary_y is needed. Therefore we call
486
+ # _auto_secondary_y() for *all* addplots, even those that
487
+ # are set to True or False (not 'auto') for secondary_y
488
+ # because their magnitudes may be needed if *any* apdicts
489
+ # contain secondary_y='auto'.
490
+ # In theory we could first loop through all apdicts to see
491
+ # if any have secondary_y='auto', but since that is the
492
+ # default value, we will just assume we have at least one.
493
+
477
494
apdata = apdict ['data' ]
495
+ aptype = apdict ['type' ]
496
+
497
+ if aptype == 'ohlc' or aptype == 'candle' :
498
+ #import pdb; pdb.set_trace()
499
+ if not isinstance (apdata ,pd .DataFrame ):
500
+ raise TypeError ('addplot type "' + aptype + '" MUST be accompanied by addplot data of type `pd.DataFrame`' )
501
+ d ,o ,h ,l ,c ,v = _check_and_prepare_data (apdata ,config )
502
+ collections = _construct_mpf_collections (aptype ,d ,xdates ,o ,h ,l ,c ,v ,config ,style )
503
+ lo = math .log (max (math .fabs (np .nanmin (l )),1e-7 ),10 ) - 0.5
504
+ hi = math .log (max (math .fabs (np .nanmax (h )),1e-7 ),10 ) + 0.5
505
+ secondary_y = _auto_secondary_y ( panels , panid , lo , hi )
506
+ if 'auto' != apdict ['secondary_y' ]:
507
+ secondary_y = apdict ['secondary_y' ]
508
+ if secondary_y :
509
+ ax = panels .at [panid ,'axes' ][1 ]
510
+ panels .at [panid ,'used2nd' ] = True
511
+ else :
512
+ ax = panels .at [panid ,'axes' ][0 ]
513
+ for coll in collections :
514
+ ax .add_collection (coll )
515
+ datalim = (minx , min (l )), (maxx , max (h ))
516
+ #ax.update_datalim(datalim)
517
+ ax .autoscale_view () # Is this really necessary??
518
+ #ax.set_ylim(min(l),max(h))
519
+ continue
520
+
478
521
if isinstance (apdata ,list ) and not isinstance (apdata [0 ],(float ,int )):
479
522
raise TypeError ('apdata is list but NOT of float or int' )
480
523
if isinstance (apdata ,pd .DataFrame ):
@@ -488,26 +531,12 @@ def plot( data, **kwargs ):
488
531
ydata = apdata .loc [:,column ]
489
532
else :
490
533
ydata = column
491
- yd = [y for y in ydata if not math .isnan (y )]
492
- ymhi = math .log (max (math .fabs (np .nanmax (yd )),1e-7 ),10 )
493
- ymlo = math .log (max (math .fabs (np .nanmin (yd )),1e-7 ),10 )
494
534
secondary_y = False
495
- panid = apdict ['panel' ]
496
- if panid == 'main' : panid = 0 # for backwards compatibility
497
- elif panid == 'lower' : panid = 1 # for backwards compatibility
498
535
if apdict ['secondary_y' ] == 'auto' :
499
- # If mag(nitude) for this panel is not yet set, then set it
500
- # here, as this is the first ydata to be plotted on this panel:
501
- # i.e. consider this to be the 'primary' axis for this panel.
502
- p = panid ,'mag'
503
- if panels .at [p ] is None :
504
- panels .at [p ] = {'lo' :ymlo ,'hi' :ymhi }
505
- elif ymlo < panels .at [p ]['lo' ] or ymhi > panels .at [p ]['hi' ]:
506
- secondary_y = True
507
- #if secondary_y:
508
- # print('auto says USE secondary_y ... for panel',panid)
509
- #else:
510
- # print('auto says do NOT use secondary_y ... for panel',panid)
536
+ yd = [y for y in ydata if not math .isnan (y )]
537
+ ymhi = math .log (max (math .fabs (np .nanmax (yd )),1e-7 ),10 )
538
+ ymlo = math .log (max (math .fabs (np .nanmin (yd )),1e-7 ),10 )
539
+ secondary_y = _auto_secondary_y ( panels , panid , ymlo , ymhi )
511
540
else :
512
541
secondary_y = apdict ['secondary_y' ]
513
542
#print("apdict['secondary_y'] says secondary_y is",secondary_y)
@@ -540,13 +569,6 @@ def plot( data, **kwargs ):
540
569
ls = apdict ['linestyle' ]
541
570
color = apdict ['color' ]
542
571
ax .plot (xdates , ydata , linestyle = ls , color = color )
543
- #elif aptype == 'ohlc' or aptype == 'candle':
544
- # This won't work as is, because here we are looping through one column at a time
545
- # and mpf_collections needs ohlc columns:
546
- # collections =_construct_mpf_collections(aptype,dates,xdates,opens,highs,lows,closes,volumes,config,style)
547
- # if len(collections) == 1: collections = [collections]
548
- # for collection in collections:
549
- # ax.add_collection(collection)
550
572
else :
551
573
raise ValueError ('addplot type "' + str (aptype )+ '" NOT yet supported.' )
552
574
@@ -604,6 +626,12 @@ def plot( data, **kwargs ):
604
626
#fig.autofmt_xdate()
605
627
606
628
axA1 .autoscale_view () # Is this really necessary??
629
+ # It appears to me, based on experience coding types 'ohlc' and 'candle'
630
+ # for `addplot`, that this IS necessary when the only thing done to the
631
+ # the axes is .add_collection(). (However, if ax.plot() .scatter() or
632
+ # .bar() was called, then possibly this is not necessary; not entirely
633
+ # sure, but it definitely was necessary to get 'ohlc' and 'candle'
634
+ # working in `addplot`).
607
635
608
636
axA1 .set_ylabel (config ['ylabel' ])
609
637
@@ -674,12 +702,27 @@ def plot( data, **kwargs ):
674
702
# print('rcpdfhead(3)=',rcpdf.head(3))
675
703
# return # rcpdf
676
704
705
+ def _auto_secondary_y ( panels , panid , ylo , yhi ):
706
+ # If mag(nitude) for this panel is not yet set, then set it
707
+ # here, as this is the first ydata to be plotted on this panel:
708
+ # i.e. consider this to be the 'primary' axis for this panel.
709
+ secondary_y = False
710
+ p = panid ,'mag'
711
+ if panels .at [p ] is None :
712
+ panels .at [p ] = {'lo' :ylo ,'hi' :yhi }
713
+ elif ylo < panels .at [p ]['lo' ] or yhi > panels .at [p ]['hi' ]:
714
+ secondary_y = True
715
+ #if secondary_y:
716
+ # print('auto says USE secondary_y ... for panel',panid)
717
+ #else:
718
+ # print('auto says do NOT use secondary_y ... for panel',panid)
719
+ return secondary_y
677
720
678
721
def _valid_addplot_kwargs ():
679
722
680
723
valid_linestyles = ('-' ,'solid' ,'--' ,'dashed' ,'-.' ,'dashdot' ,'.' ,'dotted' ,None ,' ' ,'' )
681
724
#valid_types = ('line','scatter','bar','ohlc','candle')
682
- valid_types = ('line' ,'scatter' ,'bar' )
725
+ valid_types = ('line' ,'scatter' ,'bar' , 'ohlc' , 'candle' )
683
726
684
727
vkwargs = {
685
728
'scatter' : { 'Default' : False ,
0 commit comments