bt
bt copied to clipboard
Potentially infinite loop detected with 2 backtests
I have a relatively simple strategy which takes parameters (moving average period). Different parameter values result in a different strategy object below.
When I run separate backtests for the strategy, they run fine. However, when I attempt to run multiple backtests, they fail.
What could cause this? My commissions are 0.
#strat1, strat2 are constructed separately; same logic, just different moving average periods.
backtest1 = bt.Backtest(strat1, data, commissions=None, integer_positions=False)
backtest2 = bt.Backtest(strat2, data, commissions=None, integer_positions=False)
bt.run(backtest1)
#succeeds
bt.run(backtest2)
#succeeds
bt.run(backtest1, backtest2)
Exception: Potentially infinite loop detected. This occurred while trying to reduce the amount of shares purchased to respect the outlay <= amount rule. This is most likely due to a commission function that outputs a commission that is greater than the amount of cash a short sale can raise.
Interestingly, If I re-run that last line multiple times, it sometimes succeeds.
What could cause this?
Here's a video recording of the call succeeding after multiple attempts in Jupyter: https://www.loom.com/share/94db73797da5465ea55cd0b4a9270b26
After experimenting with it some more: it seems to always succeed on the 3rd try.
Personally what I've found as a fix is to add a tolerance to the np.isclose
check in the allocate
method of SecurityBase
.
TOL = 1e-12
while not np.isclose(full_outlay, amount, rtol=TOL) and q != 0:
dq_wout_considering_tx_costs = (full_outlay - amount) / (
self._price * self.multiplier
)
q = q - dq_wout_considering_tx_costs
if self.integer_positions:
q = math.floor(q)
full_outlay, _, _, _ = self.outlay(q)
TOL
can be an extremely small value. I've not checked how far I can push it.
@timkpaine Do you think this is an acceptable fix?