Exemplo n.º 1
0
 def records_readable(self):
     """Records in readable format."""
     records_df = self.records
     out = pd.DataFrame()
     _id_str = 'Trade Id' if self.trade_type == TradeType.Trade else 'Position Id'
     out[_id_str] = records_df['id']
     out['Column'] = records_df['col'].map(
         lambda x: self.wrapper.columns[x])
     out['Size'] = records_df['size']
     out['Entry Date'] = records_df['entry_idx'].map(
         lambda x: self.wrapper.index[x])
     out['Avg. Entry Price'] = records_df['entry_price']
     out['Entry Fees'] = records_df['entry_fees']
     out['Exit Date'] = records_df['exit_idx'].map(
         lambda x: self.wrapper.index[x])
     out['Avg. Exit Price'] = records_df['exit_price']
     out['Exit Fees'] = records_df['exit_fees']
     out['PnL'] = records_df['pnl']
     out['Return'] = records_df['return']
     out['Direction'] = records_df['direction'].map(
         to_value_map(TradeDirection))
     out['Status'] = records_df['status'].map(to_value_map(TradeStatus))
     if self.trade_type == TradeType.Trade:
         out['Position Id'] = records_df['position_id']
     return out
Exemplo n.º 2
0
    def __init__(self,
                 wrapper,
                 mapped_arr,
                 col_arr,
                 id_arr=None,
                 idx_arr=None,
                 value_map=None,
                 **kwargs):
        Wrapping.__init__(self,
                          wrapper,
                          mapped_arr=mapped_arr,
                          col_arr=col_arr,
                          id_arr=id_arr,
                          idx_arr=idx_arr,
                          value_map=value_map,
                          **kwargs)
        mapped_arr = np.asarray(mapped_arr)
        col_arr = np.asarray(col_arr)
        checks.assert_shape_equal(mapped_arr, col_arr, axis=0)
        if id_arr is None:
            id_arr = np.arange(len(mapped_arr))
        if idx_arr is not None:
            idx_arr = np.asarray(idx_arr)
            checks.assert_shape_equal(mapped_arr, idx_arr, axis=0)
        if value_map is not None:
            if checks.is_namedtuple(value_map):
                value_map = to_value_map(value_map)

        self._mapped_arr = mapped_arr
        self._id_arr = id_arr
        self._col_arr = col_arr
        self._idx_arr = idx_arr
        self._value_map = value_map
        self._col_mapper = ColumnMapper(wrapper, col_arr)
Exemplo n.º 3
0
 def records_readable(self):
     """Records in readable format."""
     records_df = self.records
     out = pd.DataFrame()
     out['Drawdown Id'] = records_df['id']
     out['Column'] = records_df['col'].map(lambda x: self.wrapper.columns[x])
     out['Start Date'] = records_df['start_idx'].map(lambda x: self.wrapper.index[x])
     out['Valley Date'] = records_df['valley_idx'].map(lambda x: self.wrapper.index[x])
     out['End Date'] = records_df['end_idx'].map(lambda x: self.wrapper.index[x])
     out['Status'] = records_df['status'].map(to_value_map(DrawdownStatus))
     return out
Exemplo n.º 4
0
 def records_readable(self):
     """Records in readable format."""
     records_df = self.records
     out = pd.DataFrame()
     out['Order Id'] = records_df['id']
     out['Date'] = records_df['idx'].map(lambda x: self.wrapper.index[x])
     out['Column'] = records_df['col'].map(lambda x: self.wrapper.columns[x])
     out['Size'] = records_df['size']
     out['Price'] = records_df['price']
     out['Fees'] = records_df['fees']
     out['Side'] = records_df['side'].map(to_value_map(OrderSide))
     return out
Exemplo n.º 5
0
 def value_counts(self, group_by=None, value_map=None, wrap_kwargs=None):
     """Return a pandas object containing counts of unique values."""
     mapped_codes, mapped_uniques = pd.factorize(self.values)
     col_map = self.col_mapper.get_col_map(group_by=group_by)
     value_counts = nb.mapped_value_counts_nb(mapped_codes, col_map)
     value_counts_df = self.wrapper.wrap(value_counts,
                                         index=mapped_uniques,
                                         group_by=group_by,
                                         **merge_dicts({}, wrap_kwargs))
     if value_map is None:
         value_map = self.value_map
     if value_map is not None:
         if checks.is_namedtuple(value_map):
             value_map = to_value_map(value_map)
         value_counts_df.index = value_counts_df.index.map(value_map)
     return value_counts_df
Exemplo n.º 6
0
 def value_counts(self,
                  group_by: tp.GroupByLike = None,
                  value_map: tp.Optional[tp.ValueMapLike] = None,
                  wrap_kwargs: tp.KwargsLike = None) -> tp.SeriesFrame:
     """Return a pandas object containing counts of unique values."""
     mapped_codes, mapped_uniques = pd.factorize(self.values)
     col_map = self.col_mapper.get_col_map(group_by=group_by)
     value_counts = nb.mapped_value_counts_nb(mapped_codes, col_map)
     value_counts_df = self.wrapper.wrap(value_counts,
                                         index=mapped_uniques,
                                         group_by=group_by,
                                         **merge_dicts({}, wrap_kwargs))
     if value_map is None:
         value_map = self.value_map
     if value_map is not None:
         if checks.is_namedtuple(value_map):
             value_map = to_value_map(value_map)
         value_counts_df.index = value_counts_df.index.map(value_map)
     return value_counts_df
Exemplo n.º 7
0
    def plot(self,
             column=None,
             plot_close=True,
             plot_zones=True,
             close_trace_kwargs=None,
             entry_trace_kwargs=None,
             exit_trace_kwargs=None,
             exit_profit_trace_kwargs=None,
             exit_loss_trace_kwargs=None,
             active_trace_kwargs=None,
             profit_shape_kwargs=None,
             loss_shape_kwargs=None,
             row=None, col=None,
             xref='x', yref='y',
             fig=None,
             **layout_kwargs):  # pragma: no cover
        """Plot orders.

        Args:
            column (str): Name of the column to plot.
            plot_close (bool): Whether to plot `Trades.close`.
            plot_zones (bool): Whether to plot zones.

                Set to False if there are many trades within one position.
            close_trace_kwargs (dict): Keyword arguments passed to `plotly.graph_objects.Scatter` for `Trades.close`.
            entry_trace_kwargs (dict): Keyword arguments passed to `plotly.graph_objects.Scatter` for "Entry" markers.
            exit_trace_kwargs (dict): Keyword arguments passed to `plotly.graph_objects.Scatter` for "Exit" markers.
            exit_profit_trace_kwargs (dict): Keyword arguments passed to `plotly.graph_objects.Scatter` for "Exit - Profit" markers.
            exit_loss_trace_kwargs (dict): Keyword arguments passed to `plotly.graph_objects.Scatter` for "Exit - Loss" markers.
            active_trace_kwargs (dict): Keyword arguments passed to `plotly.graph_objects.Scatter` for "Active" markers.
            profit_shape_kwargs (dict): Keyword arguments passed to `plotly.graph_objects.Figure.add_shape` for profit zones.
            loss_shape_kwargs (dict): Keyword arguments passed to `plotly.graph_objects.Figure.add_shape` for loss zones.
            row (int): Row position.
            col (int): Column position.
            xref (str): X coordinate axis.
            yref (str): Y coordinate axis.
            fig (plotly.graph_objects.Figure): Figure to add traces to.
            **layout_kwargs: Keyword arguments for layout.

        ## Example

        ```python-repl
        >>> trades.plot()
        ```

        ![](/vectorbt/docs/img/trades_plot.png)"""
        from vectorbt.settings import color_schema, contrast_color_schema

        self_col = self.select_series(column=column, group_by=False)

        if close_trace_kwargs is None:
            close_trace_kwargs = {}
        close_trace_kwargs = merge_dicts(dict(
            line_color=color_schema['blue'],
            name='Close' if self_col.wrapper.name is None else self_col.wrapper.name
        ), close_trace_kwargs)
        if entry_trace_kwargs is None:
            entry_trace_kwargs = {}
        if exit_trace_kwargs is None:
            exit_trace_kwargs = {}
        if exit_profit_trace_kwargs is None:
            exit_profit_trace_kwargs = {}
        if exit_loss_trace_kwargs is None:
            exit_loss_trace_kwargs = {}
        if active_trace_kwargs is None:
            active_trace_kwargs = {}
        if profit_shape_kwargs is None:
            profit_shape_kwargs = {}
        if loss_shape_kwargs is None:
            loss_shape_kwargs = {}

        if fig is None:
            fig = CustomFigureWidget()
        fig.update_layout(**layout_kwargs)

        # Plot close
        if plot_close:
            fig = self_col.close.vbt.plot(trace_kwargs=close_trace_kwargs, row=row, col=col, fig=fig)

        if len(self_col.values) > 0:
            # Extract information
            _id = self_col.values['id']
            _id_str = 'Trade Id' if self.trade_type == TradeType.Trade else 'Position Id'
            size = self_col.values['size']
            entry_idx = self_col.values['entry_idx']
            entry_price = self_col.values['entry_price']
            entry_fees = self_col.values['entry_fees']
            exit_idx = self_col.values['exit_idx']
            exit_price = self_col.values['exit_price']
            exit_fees = self_col.values['exit_fees']
            pnl = self_col.values['pnl']
            ret = self_col.values['return']
            direction_value_map = to_value_map(TradeDirection)
            direction = self_col.values['direction']
            direction = np.vectorize(lambda x: str(direction_value_map[x]))(direction)
            status = self_col.values['status']

            def get_duration_str(from_idx, to_idx):
                if isinstance(self_col.wrapper.index, DatetimeTypes):
                    duration = self_col.wrapper.index[to_idx] - self_col.wrapper.index[from_idx]
                elif self_col.wrapper.freq is not None:
                    duration = self_col.wrapper.to_time_units(to_idx - from_idx)
                else:
                    duration = to_idx - from_idx
                return np.vectorize(str)(duration)

            duration = get_duration_str(entry_idx, exit_idx)

            if len(entry_idx) > 0:
                # Plot Entry markers
                entry_customdata = np.stack((
                    _id,
                    size,
                    entry_fees,
                    direction,
                    *((self_col.values['position_id'],)
                      if self.trade_type == TradeType.Trade else ())
                ), axis=1)
                entry_scatter = go.Scatter(
                    x=self_col.wrapper.index[entry_idx],
                    y=entry_price,
                    mode='markers',
                    marker=dict(
                        symbol='square',
                        color=contrast_color_schema['blue'],
                        size=7,
                        line=dict(
                            width=1,
                            color=adjust_lightness(contrast_color_schema['blue'])
                        )
                    ),
                    name='Entry',
                    customdata=entry_customdata,
                    hovertemplate=_id_str + ": %{customdata[0]}"
                                            "<br>Date: %{x}"
                                            "<br>Avg. Price: %{y}"
                                            "<br>Size: %{customdata[1]:.6f}"
                                            "<br>Fees: %{customdata[2]:.6f}"
                                            "<br>Direction: %{customdata[3]}"
                                  + ("<br>Position Id: %{customdata[4]}"
                                     if self.trade_type == TradeType.Trade else '')
                )
                entry_scatter.update(**entry_trace_kwargs)
                fig.add_trace(entry_scatter, row=row, col=col)

            # Plot end markers
            def _plot_end_markers(mask, name, color, kwargs):
                if np.any(mask):
                    customdata = np.stack((
                        _id[mask],
                        duration[mask],
                        size[mask],
                        exit_fees[mask],
                        pnl[mask],
                        ret[mask],
                        direction[mask],
                        *((self_col.values['position_id'][mask],)
                          if self.trade_type == TradeType.Trade else ())
                    ), axis=1)
                    scatter = go.Scatter(
                        x=self_col.wrapper.index[exit_idx[mask]],
                        y=exit_price[mask],
                        mode='markers',
                        marker=dict(
                            symbol='square',
                            color=color,
                            size=7,
                            line=dict(
                                width=1,
                                color=adjust_lightness(color)
                            )
                        ),
                        name=name,
                        customdata=customdata,
                        hovertemplate=_id_str + ": %{customdata[0]}"
                                                "<br>Date: %{x}"
                                                "<br>Duration: %{customdata[1]}"
                                                "<br>Avg. Price: %{y}"
                                                "<br>Size: %{customdata[2]:.6f}"
                                                "<br>Fees: %{customdata[3]:.6f}"
                                                "<br>PnL: %{customdata[4]:.6f}"
                                                "<br>Return: %{customdata[5]:.2%}"
                                                "<br>Direction: %{customdata[6]}"
                                      + ("<br>Position Id: %{customdata[7]}"
                                         if self.trade_type == TradeType.Trade else '')
                    )
                    scatter.update(**kwargs)
                    fig.add_trace(scatter, row=row, col=col)

            # Plot Exit markers
            _plot_end_markers(
                (status == TradeStatus.Closed) & (pnl == 0.),
                'Exit',
                contrast_color_schema['gray'],
                exit_trace_kwargs
            )

            # Plot Exit - Profit markers
            _plot_end_markers(
                (status == TradeStatus.Closed) & (pnl > 0.),
                'Exit - Profit',
                contrast_color_schema['green'],
                exit_profit_trace_kwargs
            )

            # Plot Exit - Loss markers
            _plot_end_markers(
                (status == TradeStatus.Closed) & (pnl < 0.),
                'Exit - Loss',
                contrast_color_schema['red'],
                exit_loss_trace_kwargs
            )

            # Plot Active markers
            _plot_end_markers(
                status == TradeStatus.Open,
                'Active',
                contrast_color_schema['orange'],
                active_trace_kwargs
            )

            if plot_zones:
                profit_mask = pnl > 0.
                if np.any(profit_mask):
                    # Plot profit zones
                    for i in np.flatnonzero(profit_mask):
                        fig.add_shape(**merge_dicts(dict(
                            type="rect",
                            xref=xref,
                            yref=yref,
                            x0=self_col.wrapper.index[entry_idx[i]],
                            y0=entry_price[i],
                            x1=self_col.wrapper.index[exit_idx[i]],
                            y1=exit_price[i],
                            fillcolor='green',
                            opacity=0.2,
                            layer="below",
                            line_width=0,
                        ), profit_shape_kwargs))

                loss_mask = pnl < 0.
                if np.any(loss_mask):
                    # Plot loss zones
                    for i in np.flatnonzero(loss_mask):
                        fig.add_shape(**merge_dicts(dict(
                            type="rect",
                            xref=xref,
                            yref=yref,
                            x0=self_col.wrapper.index[entry_idx[i]],
                            y0=entry_price[i],
                            x1=self_col.wrapper.index[exit_idx[i]],
                            y1=exit_price[i],
                            fillcolor='red',
                            opacity=0.2,
                            layer="below",
                            line_width=0,
                        ), loss_shape_kwargs))

        return fig