def build_strategy_data(self, strategy: bt.Strategy, start: Optional[datetime.datetime] = None, end: Optional[datetime.datetime] = None, num_back: Optional[int] = None, startidx: int = 0): """startidx: index number to write into the dataframe for the index column""" strategydf = pd.DataFrame() start, end = Bokeh._get_start_end(strategy, start, end) strat_clk: array[float] = strategy.lines.datetime.plotrange(start, end) # if patches occured then we see duplicate entries in the strategie clock -> clean them strat_clk = np.unique(strat_clk) if num_back is None: num_back = len(strat_clk) strat_clk = strat_clk[-num_back:] # we use timezone of first data. we might see duplicated timestamps here dtline = [bt.num2date(x, strategy.datas[0]._tz) for x in strat_clk] # add an index line to use as x-axis (instead of datetime axis) to avoid datetime gaps (e.g. weekends) indices = list(range(startidx, startidx + len(dtline))) strategydf['index'] = indices strategydf['datetime'] = dtline for data in strategy.datas: source_id = FigureEnvelope._source_id(data) df_data = convert_to_pandas(strat_clk, data, start, end, source_id) strategydf = strategydf.join(df_data) df_colors = FigureEnvelope.build_color_lines( df_data, self.p.scheme, col_open=source_id + 'open', col_close=source_id + 'close', col_prefix=source_id) strategydf = strategydf.join(df_colors) for obj in itertools.chain(strategy.getindicators(), strategy.getobservers()): for lineidx in range(obj.size()): line = obj.lines[lineidx] source_id = FigureEnvelope._source_id(line) dataline = line.plotrange(start, end) line_clk = get_clock_line(obj).plotrange(start, end) dataline = convert_by_line_clock(dataline, line_clk, strat_clk) strategydf[source_id] = dataline # apply a proper index (should be identical to 'index' column) if strategydf.shape[0] > 0: strategydf.index = indices return strategydf
def _build_graph(self, datas, inds, obs, tradingdomain=None) -> Tuple[Dict, List]: data_graph = {} volume_graph = [] for d in datas: if not d.plotinfo.plot or not FigureEnvelope.should_filter_by_tradingdomain( d, tradingdomain): continue pmaster = Bokeh._resolve_plotmaster(d.plotinfo.plotmaster) if pmaster is None: data_graph[d] = [] else: if pmaster not in data_graph: data_graph[pmaster] = [] data_graph[pmaster].append(d) if self.p.scheme.volume and self.p.scheme.voloverlay is False: volume_graph.append(d) for obj in itertools.chain(inds, obs): if not hasattr(obj, 'plotinfo'): # no plotting support - so far LineSingle derived classes continue # should this indicator be plotted? if not obj.plotinfo.plot or obj.plotinfo.plotskip or not FigureEnvelope.should_filter_by_tradingdomain( obj, tradingdomain): continue # subplot = create a new figure for this indicator subplot: bool = obj.plotinfo.subplot plotmaster: str = obj.plotinfo.plotmaster if subplot and plotmaster is None: data_graph[obj] = [] else: plotmaster = plotmaster if plotmaster is not None else get_indicator_data( obj) if plotmaster not in data_graph: data_graph[plotmaster] = [] data_graph[plotmaster].append(obj) return data_graph, volume_graph
def list_tradingdomains(self, strategy: bt.Strategy): data_graph, volume_graph = self._build_graph(strategy.datas, strategy.getindicators(), strategy.getobservers()) lgs = list() for master in itertools.chain(data_graph.keys(), volume_graph): lg = FigureEnvelope._resolve_tradingdomain(master) if isinstance(lg, str) and lg not in lgs: lgs.append(lg) return lgs
def _blueprint_strategy(self, strategy: bt.Strategy, start=None, end=None, tradingdomain=None, **kwargs) -> None: if not strategy.datas: return self._cur_figurepage.analyzers += [ a for _, a in strategy.analyzers.getitems() ] data_graph, volume_graph = self._build_graph(strategy.datas, strategy.getindicators(), strategy.getobservers(), tradingdomain) start, end = Bokeh._get_start_end(strategy, start, end) # reset hover container to not mix hovers with other strategies hoverc = HoverContainer( hover_tooltip_config=self.p.scheme.hover_tooltip_config, is_multidata=len(strategy.datas) > 1) strat_figures = [] for master, slaves in data_graph.items(): plotorder = getattr(master.plotinfo, 'plotorder', 0) figure = FigureEnvelope(strategy, self._cur_figurepage.cds, hoverc, start, end, self.p.scheme, master, plotorder, len(strategy.datas) > 1) figure.plot(master, None) for s in slaves: figure.plot(s, master) strat_figures.append(figure) for f in strat_figures: f.figure.legend.click_policy = self.p.scheme.legend_click f.figure.legend.location = self.p.scheme.legend_location f.figure.legend.background_fill_color = self.p.scheme.legend_background_color f.figure.legend.label_text_color = self.p.scheme.legend_text_color f.figure.legend.orientation = self.p.scheme.legend_orientation # link axis for i in range(1, len(strat_figures)): strat_figures[i].figure.x_range = strat_figures[0].figure.x_range # configure xaxis visibility if self.p.scheme.xaxis_pos == "bottom": for i, f in enumerate(strat_figures): f.figure.xaxis.visible = False if i <= len( strat_figures) else True hoverc.apply_hovertips(strat_figures) self._cur_figurepage.figure_envs += strat_figures # volume graphs for v in volume_graph: plotorder = getattr(v.plotinfo, 'plotorder', 0) figure = FigureEnvelope(strategy, self._cur_figurepage.cds, hoverc, start, end, self.p.scheme, v, plotorder, is_multidata=len(strategy.datas) > 1) figure.plot_volume(v) self._cur_figurepage.figure_envs.append(figure)