Skip to content

Commit 3dfa0c9

Browse files
committed
ENH: Add Backtest(..., exclusive_orders=) that closes prev trades on new orders
And thus approximates previous (0.1.x) behavior.
1 parent e03f55f commit 3dfa0c9

File tree

2 files changed

+27
-2
lines changed

2 files changed

+27
-2
lines changed

backtesting/backtesting.py

+15-2
Original file line numberDiff line numberDiff line change
@@ -643,7 +643,8 @@ def __set_contingent(self, type, price):
643643

644644

645645
class _Broker:
646-
def __init__(self, *, data, cash, commission, margin, trade_on_close, hedging, index):
646+
def __init__(self, *, data, cash, commission, margin,
647+
trade_on_close, hedging, exclusive_orders, index):
647648
assert 0 < cash, "cash shosuld be >0, is {}".format(cash)
648649
assert 0 <= commission < .1, "commission should be between 0-10%, is {}".format(commission)
649650
assert 0 < margin <= 1, "margin should be between 0 and 1, is {}".format(margin)
@@ -653,6 +654,7 @@ def __init__(self, *, data, cash, commission, margin, trade_on_close, hedging, i
653654
self._leverage = 1 / margin
654655
self._trade_on_close = trade_on_close
655656
self._hedging = hedging
657+
self._exclusive_orders = exclusive_orders
656658

657659
self._equity = np.tile(np.nan, len(index))
658660
self.orders = [] # type: List[Order]
@@ -699,7 +701,17 @@ def new_order(self,
699701
if trade:
700702
self.orders.insert(0, order)
701703
else:
704+
# If exclusive orders (each new order auto-closes previous orders/position),
705+
# cancel all non-contingent orders and close all open trades beforehand
706+
if self._exclusive_orders:
707+
for o in self.orders:
708+
if not o.is_contingent:
709+
o.cancel()
710+
for t in self.trades:
711+
t.close()
712+
702713
self.orders.append(order)
714+
703715
return order
704716

705717
@property
@@ -919,6 +931,7 @@ def __init__(self,
919931
margin: float = 1.,
920932
trade_on_close=False,
921933
hedging=False,
934+
exclusive_orders=False
922935
):
923936
"""
924937
Initialize a backtest. Requires data and a strategy to test.
@@ -1006,7 +1019,7 @@ def __init__(self,
10061019
self._broker = partial(
10071020
_Broker, cash=cash, commission=commission, margin=margin,
10081021
trade_on_close=trade_on_close, hedging=hedging,
1009-
index=data.index,
1022+
exclusive_orders=exclusive_orders, index=data.index,
10101023
)
10111024
self._strategy = strategy
10121025
self._results = None

backtesting/test/_test.py

+12
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,18 @@ def coroutine(self):
372372

373373
self._Backtest(coroutine, hedging=True).run()
374374

375+
def test_broker_exclusive_orders(self):
376+
def coroutine(self):
377+
yield self.buy(size=2)
378+
379+
assert len(self.trades) == 1
380+
yield self.sell(size=3)
381+
382+
assert len(self.trades) == 1
383+
assert self.trades[0].size == -3
384+
385+
self._Backtest(coroutine, exclusive_orders=True).run()
386+
375387

376388
class TestOptimize(TestCase):
377389
def test_optimize(self):

0 commit comments

Comments
 (0)