Skip to content

Commit

Permalink
ENH: Add Backtest(..., exclusive_orders=) that closes prev trades o…
Browse files Browse the repository at this point in the history
…n new orders

And thus approximates previous (0.1.x) behavior.
  • Loading branch information
kernc committed Jul 13, 2020
1 parent e03f55f commit b123fba
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 2 deletions.
17 changes: 15 additions & 2 deletions backtesting/backtesting.py
Original file line number Diff line number Diff line change
Expand Up @@ -643,7 +643,8 @@ def __set_contingent(self, type, price):


class _Broker:
def __init__(self, *, data, cash, commission, margin, trade_on_close, hedging, index):
def __init__(self, *, data, cash, commission, margin,
trade_on_close, hedging, exclusive_orders, index):
assert 0 < cash, "cash shosuld be >0, is {}".format(cash)
assert 0 <= commission < .1, "commission should be between 0-10%, is {}".format(commission)
assert 0 < margin <= 1, "margin should be between 0 and 1, is {}".format(margin)
Expand All @@ -653,6 +654,7 @@ def __init__(self, *, data, cash, commission, margin, trade_on_close, hedging, i
self._leverage = 1 / margin
self._trade_on_close = trade_on_close
self._hedging = hedging
self._exclusive_orders = exclusive_orders

self._equity = np.tile(np.nan, len(index))
self.orders = [] # type: List[Order]
Expand Down Expand Up @@ -699,7 +701,17 @@ def new_order(self,
if trade:
self.orders.insert(0, order)
else:
# If exclusive orders (each new order auto-closes previous orders/position),
# cancel all non-contingent orders and close all open trades beforehand
if self._exclusive_orders:
for o in self.orders:
if not o.is_contingent:
o.cancel()
for t in self.trades:
t.close()

self.orders.append(order)

return order

@property
Expand Down Expand Up @@ -919,6 +931,7 @@ def __init__(self,
margin: float = 1.,
trade_on_close=False,
hedging=False,
exclusive_orders=False,
):
"""
Initialize a backtest. Requires data and a strategy to test.
Expand Down Expand Up @@ -1006,7 +1019,7 @@ def __init__(self,
self._broker = partial(
_Broker, cash=cash, commission=commission, margin=margin,
trade_on_close=trade_on_close, hedging=hedging,
index=data.index,
exclusive_orders=exclusive_orders, index=data.index,
)
self._strategy = strategy
self._results = None
Expand Down
12 changes: 12 additions & 0 deletions backtesting/test/_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,18 @@ def coroutine(self):

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

def test_broker_exclusive_orders(self):
def coroutine(self):
yield self.buy(size=2)

assert len(self.trades) == 1
yield self.sell(size=3)

assert len(self.trades) == 1
assert self.trades[0].size == -3

self._Backtest(coroutine, exclusive_orders=True).run()


class TestOptimize(TestCase):
def test_optimize(self):
Expand Down

0 comments on commit b123fba

Please sign in to comment.