Skip to content

Commit e138c3a

Browse files
committed
Allow removal of data from plotting and data on data plotting
1 parent cd44a25 commit e138c3a

1 file changed

Lines changed: 56 additions & 17 deletions

File tree

backtrader/plot/plot.py

Lines changed: 56 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -285,10 +285,21 @@ def calcrows(self, strategy):
285285
rowsminor = self.pinf.sch.rowsminor
286286
nrows = 0
287287

288+
datasnoplot = 0
289+
for data in strategy.datas:
290+
if not data.plotinfo.plot:
291+
datasnoplot += 1
292+
self.dplotsup.pop(data, None)
293+
self.dplotsdown.pop(data, None)
294+
self.dplotsover.pop(data, None)
295+
296+
elif data.plotinfo.plotmaster is not None:
297+
datasnoplot += 1
298+
288299
# Datas and volumes
289-
nrows += len(strategy.datas) * rowsmajor
300+
nrows += (len(strategy.datas) - datasnoplot) * rowsmajor
290301
if self.pinf.sch.volume and not self.pinf.sch.voloverlay:
291-
nrows += len(strategy.datas) * rowsminor
302+
nrows += (len(strategy.datas) - datasnoplot) * rowsminor
292303

293304
# top indicators/observers
294305
nrows += len(self.dplotstop) * rowsminor
@@ -537,15 +548,24 @@ def plotdata(self, data, indicators):
537548
volumes = data.volume.plotrange(self.pinf.xstart, self.pinf.xend)
538549

539550
vollabel = 'Volume'
540-
if self.pinf.sch.volume and self.pinf.sch.voloverlay:
551+
voloverlay = (self.pinf.sch.voloverlay and
552+
data.plotinfo.plotmaster is not None)
553+
# if self.pinf.sch.volume and self.pinf.sch.voloverlay:
554+
if self.pinf.sch.volume and voloverlay:
541555
volplot = self.plotvolume(
542556
data, opens, highs, lows, closes, volumes, vollabel)
543557
axvol = self.pinf.daxis[data.volume]
544558
ax = axvol.twinx()
545559
self.pinf.daxis[data] = ax
546560
self.pinf.vaxis.append(ax)
547561
else:
548-
ax = self.newaxis(data, rowspan=self.pinf.sch.rowsmajor)
562+
if data.plotinfo.plotmaster is None:
563+
ax = self.newaxis(data, rowspan=self.pinf.sch.rowsmajor)
564+
axdatamaster = None
565+
else:
566+
axdatamaster = self.pinf.daxis[data.plotinfo.plotmaster]
567+
ax = axdatamaster.twinx()
568+
self.pinf.vaxis.append(ax)
549569

550570
datalabel = ''
551571
dataname = ''
@@ -561,9 +581,15 @@ def plotdata(self, data, indicators):
561581
(opens[-1], highs[-1], lows[-1], closes[-1])
562582

563583
if self.pinf.sch.style.startswith('line'):
584+
if axdatamaster is None:
585+
color = self.pinf.sch.loc
586+
else:
587+
self.pinf.nextcolor(axdatamaster)
588+
color = self.pinf.color(axdatamaster)
589+
564590
plotted = plot_lineonclose(
565591
ax, self.pinf.xdata, closes,
566-
color=self.pinf.sch.loc, label=datalabel)
592+
color=color, label=datalabel)
567593
else:
568594
if self.pinf.sch.style.startswith('candle'):
569595
plotted = plot_candlestick(
@@ -593,7 +619,8 @@ def plotdata(self, data, indicators):
593619
ax.set_ylim(ax.get_ylim())
594620

595621
if self.pinf.sch.volume:
596-
if not self.pinf.sch.voloverlay:
622+
# if not self.pinf.sch.voloverlay:
623+
if not vololverlay:
597624
self.plotvolume(
598625
data, opens, highs, lows, closes, volumes, vollabel)
599626
else:
@@ -608,6 +635,10 @@ def plotdata(self, data, indicators):
608635
self.plotind(data, ind, subinds=self.dplotsover[ind], masterax=ax)
609636

610637
handles, labels = ax.get_legend_handles_labels()
638+
if axdatamaster is not None:
639+
h2, l2 = axdatamaster.get_legend_handles_labels()
640+
else:
641+
h2, l2 = None, None
611642
if handles:
612643
# put data and volume legend entries in the 1st positions
613644
# because they are "collections" they are considered after Line2D
@@ -618,19 +649,27 @@ def plotdata(self, data, indicators):
618649
labels.insert(0, vollabel)
619650
handles.insert(0, volplot)
620651

621-
didx = labels.index(datalabel)
622-
labels.insert(0, labels.pop(didx))
623-
handles.insert(0, handles.pop(didx))
652+
if h2 is None:
653+
didx = labels.index(datalabel)
654+
labels.insert(0, labels.pop(didx))
655+
handles.insert(0, handles.pop(didx))
656+
else:
657+
didx = labels.index(datalabel)
658+
l2.append(labels.pop(didx))
659+
# h2.insert(0, plotted[0])
660+
h2.append(handles.pop(didx))
624661

625662
# feed handles/labels to legend to get right order
626-
legend = ax.legend(handles, labels,
627-
loc='upper left', frameon=False, shadow=False,
628-
fancybox=False,
629-
prop=self.pinf.prop, numpoints=1, ncol=1)
630-
631-
# hack: if title is set. legend has a Vbox for the labels
632-
# which has a default "center" set
633-
legend._legend_box.align = 'left'
663+
if h2 is not None:
664+
legend = ax.legend(h2 or handles, l2 or labels,
665+
loc='upper left',
666+
frameon=False, shadow=False,
667+
fancybox=False, prop=self.pinf.prop,
668+
numpoints=1, ncol=1)
669+
670+
# hack: if title is set. legend has a Vbox for the labels
671+
# which has a default "center" set
672+
legend._legend_box.align = 'left'
634673

635674
for ind in indicators:
636675
downinds = self.dplotsdown[ind]

0 commit comments

Comments
 (0)