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
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)
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
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
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
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
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