Skip to content

Commit 190b4f4

Browse files
committed
BUG: Fix computing commissions
Fixes #1273
1 parent 3e31891 commit 190b4f4

File tree

2 files changed

+23
-1
lines changed

2 files changed

+23
-1
lines changed

backtesting/backtesting.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -952,7 +952,8 @@ def _process_orders(self):
952952
# Adjust price to include commission (or bid-ask spread).
953953
# In long positions, the adjusted price is a fraction higher, and vice versa.
954954
adjusted_price = self._adjusted_price(order.size, price)
955-
adjusted_price_plus_commission = adjusted_price + self._commission(order.size, price)
955+
adjusted_price_plus_commission = \
956+
adjusted_price + self._commission(order.size, price) / abs(order.size)
956957

957958
# If order size was specified proportionally,
958959
# precompute true size in units, accounting for margin and spread/commissions

backtesting/test/_test.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,27 @@ def next(self):
260260
self.assertEqual(stats['_equity_curve']['Equity'].iloc[2:4].round(2).tolist(),
261261
[9781.28, 9846.04])
262262

263+
def test_commissions(self):
264+
class S(_S):
265+
def next(self):
266+
if len(self.data) == 2:
267+
self.buy(size=SIZE, tp=3)
268+
269+
FIXED_COMMISSION, COMMISSION = 10, .01
270+
CASH, SIZE, PRICE_ENTRY, PRICE_EXIT = 5000, 100, 1, 4
271+
arr = np.r_[1, PRICE_ENTRY, 1, 2, PRICE_EXIT, 1, 2]
272+
df = pd.DataFrame({'Open': arr, 'High': arr, 'Low': arr, 'Close': arr})
273+
with self.assertWarnsRegex(UserWarning, 'index is not datetime'):
274+
stats = Backtest(df, S, cash=CASH, commission=(FIXED_COMMISSION, COMMISSION)).run()
275+
EXPECTED_PAID_COMMISSION = (
276+
FIXED_COMMISSION + COMMISSION * SIZE * PRICE_ENTRY +
277+
FIXED_COMMISSION + COMMISSION * SIZE * PRICE_EXIT)
278+
self.assertEqual(stats['Commissions [$]'], EXPECTED_PAID_COMMISSION)
279+
self.assertEqual(stats._trades['Commission'][0], EXPECTED_PAID_COMMISSION)
280+
self.assertEqual(
281+
stats['Equity Final [$]'],
282+
CASH + (PRICE_EXIT - PRICE_ENTRY) * SIZE - EXPECTED_PAID_COMMISSION)
283+
263284
def test_dont_overwrite_data(self):
264285
df = EURUSD.copy()
265286
bt = Backtest(df, SmaCross)

0 commit comments

Comments
 (0)