Skip to content

Commit

Permalink
ENH: Show paid 'Commissions [$]' in stats
Browse files Browse the repository at this point in the history
  • Loading branch information
kernc committed Dec 13, 2022
1 parent 4e22454 commit cd5ae83
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 2 deletions.
4 changes: 4 additions & 0 deletions backtesting/_stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ def compute_stats(

if isinstance(trades, pd.DataFrame):
trades_df: pd.DataFrame = trades
commissions = None # Not shown
else:
# Came straight from Backtest.run()
trades_df = pd.DataFrame({
Expand All @@ -68,6 +69,7 @@ def compute_stats(
'Tag': [t.tag for t in trades],
})
trades_df['Duration'] = trades_df['ExitTime'] - trades_df['EntryTime']
commissions = sum(t._commissions for t in trades)
del trades

pl = trades_df['PnL']
Expand All @@ -92,6 +94,8 @@ def _round_timedelta(value, _period=_data_period(index)):
s.loc['Exposure Time [%]'] = have_position.mean() * 100 # In "n bars" time, not index time
s.loc['Equity Final [$]'] = equity[-1]
s.loc['Equity Peak [$]'] = equity.max()
if commissions:
s.loc['Commissions [$]'] = commissions
s.loc['Return [%]'] = (equity[-1] - equity[0]) / equity[0] * 100
c = ohlc_data.Close.values
s.loc['Buy & Hold Return [%]'] = (c[-1] - c[0]) / c[0] * 100 # long-only return
Expand Down
12 changes: 10 additions & 2 deletions backtesting/backtesting.py
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,7 @@ def __init__(self, broker: '_Broker', size: int, entry_price: float, entry_bar,
self.__sl_order: Optional[Order] = None
self.__tp_order: Optional[Order] = None
self.__tag = tag
self._commissions = 0

def __repr__(self):
return f'<Trade size={self.__size} time={self.__entry_bar}-{self.__exit_bar or ""} ' \
Expand Down Expand Up @@ -1011,9 +1012,16 @@ def _close_trade(self, trade: Trade, price: float, time_index: int):
if trade._tp_order:
self.orders.remove(trade._tp_order)

self.closed_trades.append(trade._replace(exit_price=price, exit_bar=time_index))
closed_trade = trade._replace(exit_price=price, exit_bar=time_index)
self.closed_trades.append(closed_trade)
# Apply commission one more time at trade exit
self._cash += trade.pl - self._commission(trade.size, price)
commission = self._commission(trade.size, price)
self._cash += trade.pl - commission
# Save commissions on Trade instance for stats
trade_open_commission = self._commission(closed_trade.size, closed_trade.entry_price)
# applied here instead of on Trade open because size could have changed
# by way of _reduce_trade()
closed_trade._commissions = commission + trade_open_commission

def _open_trade(self, price: float, size: int,
sl: Optional[float], tp: Optional[float], time_index: int, tag):
Expand Down

0 comments on commit cd5ae83

Please sign in to comment.