import unittest import pandas as pd from backtestingfx import Backtest, Strategy class IntrabarExecutionTest(unittest.TestCase): def test_new_entries_are_checked_from_the_following_bar(self): for is_long in (True, False): for count in (1, 2): with self.subTest(is_long=is_long, count=count): seen = [] class EnterOnce(Strategy): def next(self): seen.append(len(self.positions)) if self.index == 0: if is_long: self.buy(1.0, stop_loss=1.09, take_profit=1.11) else: self.sell(1.0, stop_loss=1.11, take_profit=1.09) index = pd.date_range("2026-01-01", periods=count, freq="h", tz="UTC") data = pd.DataFrame( {"open": [1.1] * count, "high": [1.12] * count, "low": [1.08] * count, "close": [1.1] * count}, index=index, ) stats = Backtest(data, EnterOnce, commission=0, spread=0).run() self.assertEqual(stats.num_trades, 1) trade = stats.trades[0] self.assertEqual(trade.entry_timestamp, int(index[0].timestamp())) self.assertEqual(trade.exit_timestamp, int(index[-1].timestamp())) if count == 1: # Final liquidation at close: the entry bar's range is not replayed. self.assertAlmostEqual(trade.exit_price, 1.1) self.assertAlmostEqual(trade.pnl, 0.0) self.assertEqual(seen, [0]) else: # Both levels touched on the next bar: stop is processed before next(). self.assertAlmostEqual(trade.exit_price, 1.09 if is_long else 1.11) self.assertAlmostEqual(trade.pnl, -1000.0) self.assertEqual(seen, [0, 0]) if __name__ == "__main__": unittest.main()