def plot(self, figsize: Tuple[int, int] = (15, 8), date_range: Optional[Union[Tuple[str, str], Tuple[np.datetime64, np.datetime64]]] = None, sampling_frequency: str = None, title: str = 'Price / Volume') -> None: ''' Plot a candlestick or line plot depending on whether we have ohlc data or just close prices Args: figsize: Size of the figure (default (15,8)) date_range: A tuple of strings or numpy datetimes for plotting a smaller sample of the data, e.g. ("2018-01-01", "2018-01-06") sampling_frequency: Downsample before plotting. See pandas frequency strings for possible values. title: Title of the graph, default "Price / Volume" ''' if date_range and isinstance(date_range[0], str): date_range = strtup2date(date_range) data: Union[TradeBarSeries, TimeSeries] if self.has_ohlc(): data = TradeBarSeries('price', self.timestamps, self.o, self.h, self.l, self.c, self.v, self.vwap) else: data = TimeSeries('price', self.timestamps, self.c) subplot = Subplot(data) plot = Plot([subplot], figsize=figsize, date_range=date_range, sampling_frequency=sampling_frequency, title=title) plot.draw()
def __init__(self, subplot_list: Sequence[Subplot], title: str = None, figsize: Tuple[float, float] = (15, 8), date_range: Union[Tuple[str, str], Tuple[Optional[np.datetime64], Optional[np.datetime64]]] = None, date_format: str = None, sampling_frequency: str = None, show_grid: bool = True, show_date_gaps: bool = True, hspace: Optional[float] = 0.15) -> None: ''' Args: subplot_list: List of Subplot objects to draw title: Title for this plot. Default None figsize: Figure size. Default (15, 8) date_range: Tuple of strings or numpy datetime64 limiting timestamps to draw. e.g. ("2018-01-01 14:00", "2018-01-05"). Default None date_format: Date format to use for x-axis sampling_frequency: Set this to downsample subplots that have a datetime x axis. For example, if you have minute bar data, you might want to subsample to hours if the plot is too crowded. See pandas time frequency strings for possible values. Default None show_grid: If set to True, show a grid on the subplots. Default True show_date_gaps: If set to True, then when there is a gap between timestamps will draw a dashed vertical line. For example, you may have minute bars and a gap between end of trading day and beginning of next day. Even if set to True, this will turn itself off if there are too many gaps to avoid clutter. Default True hspace: Height (vertical) space between subplots. Default 0.15 ''' if isinstance(subplot_list, Subplot): subplot_list = [subplot_list] assert (len(subplot_list)) self.subplot_list = subplot_list self.title = title self.figsize = figsize self.date_range = strtup2date(date_range) self.date_format = date_format self.sampling_frequency = sampling_frequency self.show_date_gaps = show_date_gaps self.show_grid = show_grid self.hspace = hspace
def plot(self, contract_groups: Sequence[ContractGroup] = None, primary_indicators: Sequence[str] = None, primary_indicators_dual_axis: Sequence[str] = None, secondary_indicators: Sequence[str] = None, secondary_indicators_dual_axis: Sequence[str] = None, indicator_properties: PlotPropertiesType = None, signals: Sequence[str] = None, signal_properties: PlotPropertiesType = None, pnl_columns: Sequence[str] = None, title: str = None, figsize: Tuple[int, int] = (20, 15), _date_range: DateRangeType = None, date_format: str = None, sampling_frequency: str = None, trade_marker_properties: PlotPropertiesType = None, hspace: float = 0.15) -> None: ''' Plot indicators, signals, trades, position, pnl Args: contract_groups: Contract groups to plot or None (default) for all contract groups. primary indicators: List of indicators to plot in the main indicator section. Default None (plot everything) primary indicators: List of indicators to plot in the secondary indicator section. Default None (don't plot anything) indicator_properties: If set, we use the line color, line type indicated for the given indicators signals: Signals to plot. Default None (plot everything). plot_equity: If set, we plot the equity curve. Default is True title: Title of plot. Default None figsize: Figure size. Default (20, 15) date_range: Used to restrict the date range of the graph. Default None date_format: Date format for tick labels on x axis. If set to None (default), will be selected based on date range. See matplotlib date format strings sampling_frequency: Downsampling frequency. The graph may get too busy if you have too many bars of data, so you may want to downsample before plotting. See pandas frequency strings for possible values. Default None. trade_marker_properties: A dictionary of order reason code -> marker shape, marker size, marker color for plotting trades with different reason codes. By default we use the dictionary from the :obj:`ReasonCode` class hspace: Height (vertical) space between subplots. Default is 0.15 ''' date_range = strtup2date(_date_range) if contract_groups is None: contract_groups = self.contract_groups if isinstance(contract_groups, ContractGroup): contract_groups = [contract_groups] if pnl_columns is None: pnl_columns = ['equity'] for contract_group in contract_groups: primary_indicator_names = [ind_name for ind_name in self.indicator_values[contract_group].__dict__ if hasattr(self.indicator_values[contract_group], ind_name)] if primary_indicators: primary_indicator_names = list(set(primary_indicator_names).intersection(primary_indicators)) secondary_indicator_names: List[str] = [] if secondary_indicators: secondary_indicator_names = list(secondary_indicators) signal_names = [sig_name for sig_name in self.signals.keys() if hasattr(self.signal_values[contract_group], sig_name)] if signals: signal_names = list(set(signal_names).intersection(signals)) primary_indicator_list = _get_time_series_list(self.timestamps, primary_indicator_names, self.indicator_values[contract_group], indicator_properties) secondary_indicator_list = _get_time_series_list(self.timestamps, secondary_indicator_names, self.indicator_values[contract_group], indicator_properties) signal_list = _get_time_series_list(self.timestamps, signal_names, self.signal_values[contract_group], signal_properties) df_pnl_ = self.df_pnl(contract_group) pnl_list = [TimeSeries(pnl_column, timestamps=df_pnl_.timestamp.values, values=df_pnl_[pnl_column].values) for pnl_column in pnl_columns] trades = [trade for trade in self._trades if trade.order.contract.contract_group == contract_group] if trade_marker_properties: trade_sets = trade_sets_by_reason_code(trades, trade_marker_properties, remove_missing_properties=True) else: trade_sets = trade_sets_by_reason_code(trades) primary_indicator_subplot = Subplot( primary_indicator_list + trade_sets, # type: ignore # mypy does not allow adding heterogeneous lists secondary_y=primary_indicators_dual_axis, height_ratio=0.5, ylabel='Primary Indicators') if len(secondary_indicator_list): secondary_indicator_subplot = Subplot(secondary_indicator_list, secondary_y=secondary_indicators_dual_axis, height_ratio=0.5, ylabel='Secondary Indicators') signal_subplot = Subplot(signal_list, ylabel='Signals', height_ratio=0.167) pnl_subplot = Subplot(pnl_list, ylabel='Equity', height_ratio=0.167, log_y=True, y_tick_format='${x:,.0f}') position = df_pnl_.position.values disp_attribs = FilledLinePlotAttributes() pos_subplot = Subplot( [TimeSeries('position', timestamps=df_pnl_.timestamp, values=position, display_attributes=disp_attribs)], ylabel='Position', height_ratio=0.167) title_full = title if len(contract_groups) > 1: if title is None: title = '' title_full = f'{title} {contract_group.name}' plot_list = [] if len(primary_indicator_list): plot_list.append(primary_indicator_subplot) if len(secondary_indicator_list): plot_list.append(secondary_indicator_subplot) if len(signal_list): plot_list.append(signal_subplot) if len(position): plot_list.append(pos_subplot) if len(pnl_list): plot_list.append(pnl_subplot) if not len(plot_list): return plot = Plot(plot_list, figsize=figsize, date_range=date_range, date_format=date_format, sampling_frequency=sampling_frequency, title=title_full, hspace=hspace) plot.draw()