← Blog
Backtesting

Does Your Backtest Survive the Adverse Same-Bar Fill? A 48.8 Million-Pair Stress Test.

2026.07.29·6 min read·Rulyfi

Key Takeaways

  • An OHLC bar can show that take-profit and stop-loss prices were both touched. It cannot show which came first. Run the same search under both TP-first and SL-first before promoting a candidate.
  • We evaluated 48,825,000 identical configurations twice, forming 97,650,000 backtest runs. Total return changed in 37,168,124 pairs, or 76.13%.
  • Among the changed pairs, the median SL-first result moved 13.50 percentage points lower in total return, 1.94 points lower in win rate, and 5.80 points deeper in maximum drawdown.
  • Of 8,025,529 TP-first profitable configurations with at least 30 trades in both modes, 6,624,631, or 82.54%, became non-positive under SL-first. For a common row-level gate, use three buckets: advance candidates that pass both assumptions, send TP-first-only candidates to finer-data validation, and reject candidates that fail both.

An hourly candle has a high above a take-profit price and a low below a stop-loss price. Both levels are inside the candle. Which order filled first?

The candle does not say.

A backtest engine still has to choose. It can award the take-profit first, apply the stop-loss first, or infer a path through the bar. Each rule produces a definite equity curve from evidence that did not contain a definite sequence.

The adverse direction is predetermined whenever it replaces a profitable exit with a losing one. The open question is whether the candidate still survives that choice.

We tested that question across 48.825 million matched configurations.

1. One bar contains four prices, not a path

An OHLC bar records the open, high, low, and close for an interval. It does not record the order of every price between them.

Other engines face the same missing sequence. TradingView documents that its broker emulator infers one of two intrabar paths from OHLC data, then offers Bar Magnifier to use lower-timeframe data for more granular fills.1 Other backtesting systems also make fill behavior depend on whether tick, quote-bar, or trade-bar data is available.2

Rulyfi exposes two same-bar choices:

  • TP-first, Conservative Fill off: if the bar contains both exit prices, fill the take-profit.
  • SL-first, Conservative Fill on: if the bar contains both exit prices, fill the stop-loss.

Both modes close the trade on the same candle. The exit price changes, but the later signal calendar stays aligned. In our paired exports, trade count changed in zero configurations. Funding contribution also changed in zero.

These modes define two modeled paths. SL-first is the adverse stress assumption inside this hourly OHLC model. The live intrabar path remains unknown.

2. The paired stress test

We held the candles, strategy grid, direction, fees, slippage, funding, walk-forward settings, TP, SL, and time-to-live constant. The only experiment switch was the same-bar fill rule. The full scan setup was:

MarketsBinance USDT perpetuals: BTC, ETH, BNB, XRP, and SOL
DirectionsLong and short, run separately
BarsOne hour; 50,000-hour analysis window from November 13, 2020 at 17:00 UTC through July 29, 2026 at 01:00 UTC
Indicator grid20 indicators × 14 periods = 280 variations
Entry combinationsC(280,2) = 39,060; each candidate requires the conditions of two different indicator-period variations
Exits125 per pair: TP {0.5, 1, 2, 3, 4}% × SL {0.5, 1, 2, 3, 4}% × TTL {6, 12, 24, 48, 96} bars
Total4,882,500 configurations per market and direction
Costs0.04% taker fee and 0.01% slippage; bar-aligned funding included in trade PnL
ValidationFour forward folds
Result settingsMinimum trade count 0; top 100 leaderboard rows; save all results; force a fresh scan

“280 indicator variations” deserves specifics. The campaign payload varied only the 14 period values below for every indicator. There was no separate hidden parameter grid for individual indicators.

IndicatorParameter sweepVariations
SMA, EMA, HMA, ADX, Aroon, Vortex Indicator, RSI, CCI, Williams %R, ROC, CMO, Percentile Rank, Donchian Channel, Choppiness Index, Z-Score, R-Squared, MFI, CMF, EFI, Volume Ratioperiod {5, 6, 8, 10, 12, 16, 20, 24, 32, 40, 48, 64, 80, 96}14 each, 280 total

The TP and SL grids were deliberately symmetric. Both used the same five percentages because the goal was not to optimize one preferred reward-to-risk ratio. It was to compare all 25 exit shapes on equal footing, including tight, wide, and asymmetric TP/SL combinations, so fill sensitivity could be observed by exit geometry rather than inferred from one favored ratio. TTL varied separately across five values to test whether time in trade changed the affected share.

This produced 4,882,500 configurations for each market and direction.

We ran each configuration once under TP-first and once under SL-first:

UnitCount
Matched configurations48,825,000
Backtest runs97,650,000
Parquet result files20

Treat the 48.825 million rows as a dense, repeated parameter grid rather than independent trading ideas or statistical samples.

Every TP-first row joined one-to-one with its SL-first twin by market, direction, indicator pair, TP, SL, and TTL. There were no missing keys and no strategy-label mismatches.

BTC, ETH, BNB, and XRP contained the complete requested warmup. SOL contained the full analysis interval but had 1,050 fewer warmup candles than requested. We therefore keep SOL separately labeled in any warmup-sensitive reading.

3. How far the results moved

Total return changed in 37,168,124 of 48,825,000 matched configurations, or 76.13%.

The direction is built into the stress. When the same bar touches both exits, replacing TP with SL cannot improve that trade. The important findings are the prevalence and magnitude of the dependence.

How three performance measures changed under the adverse same-bar fillThree separate percentile strips show SL-first minus TP-first changes among 37,168,124 configurations whose total return changed. Median total return moved down 13.50 percentage points, win rate 1.94 points, and maximum drawdown 5.80 points deeper.Total returnSL-first minus TP-first-120 pp-60 pp0 ppp10 -113.9 ppmedian -13.50 ppp90 -1.4 ppWin rateSL-first minus TP-first-14 pp-7 pp0 ppp10 -12.3 ppmedian -1.94 ppp90 -0.3 ppMaximum drawdownSL-first minus TP-first-40 pp-20 pp0 ppp10 -35.0 ppmedian -5.80 ppp90 -0.5 ppMore negative MDD change means a deeper drawdownThe 10th percentile, median, and 90th percentile of three paired performance changes among the 37,168,124 configurations whose total return changed. Each row has its own scale. Trade count and funding contribution changed in zero pairs. Source: 97.65 million backtest runs, 2026-07-29.

Among configurations whose total return changed, the median changes were:

  • total return: -13.50 percentage points;
  • win rate: -1.94 percentage points;
  • maximum drawdown: -5.80 percentage points, meaning a deeper drawdown because MDD is stored as a negative number.

The distribution was not a cloud of rounding dust. At the 90th percentile, the total-return change was still -1.43 percentage points. At the 10th percentile it was -113.86 points, reflecting a long compounding tail.

We do not use the mean return change as the typical result. A small number of extreme compounded TP-first rows distort it.

4. Use three decisions, not one verdict

Apply the same row-level pass rule to each matched pair. In the example below, a row passes with positive total return and at least 30 trades in both modes. The paired result becomes a research decision:

  1. Passes both assumptions: advance the candidate to the next validation stage.
  2. Passes TP-first only: do not promote or discard it yet. Acquire lower-timeframe or tick evidence.
  3. Fails both assumptions: reject it under the current specification.

This screen tests one specific ambiguity: which modeled exit wins when both prices appear inside the same OHLC bar.

RMP and DSR are recalculated across each job population rather than from one row alone. Compare those classifications separately instead of forcing a disagreement into the three row-level buckets.

OutcomeConfigurations
Profitable under TP-first8,025,529
Profitable under both1,400,898
TP-first profitable, SL-first non-positive6,624,631
Non-positive under TP-first, profitable under SL-first0

Only 17.46% of the TP-first profitable group remained profitable under SL-first. The other 82.54% belong in the second bucket. Hourly OHLC alone cannot tell us whether to promote them.

5. Start finer-data validation where exposure repeats

Intrabar data is expensive to store, process, and replay across a large search. The paired stress test helps decide where it matters first.

Fill-order sensitivity rises with trade count while profitable retention fallsTwo aligned bar panels by trade-count bucket. The affected share rises from 25.7 percent at 1 to 29 trades to 99.94 percent at 3,000 or more. The share of TP-first profitable configurations remaining profitable under SL-first falls from 72.4 percent to nearly zero.Configurations with changed total return0%50%100%0.0%25.7%54.9%73.8%91.7%99.01%99.94%TP-first profitable configurations still profitable under SL-first0%50%100%n/a72.4%48.9%34.2%18.9%6.2%<0.01%0trades1-29trades30-99trades100-299trades300-999trades1000-2999trades3000+tradesWarning signal, not causal proofSensitivity by realized trade count. The upper panel shows how often total return changed; the lower panel shows how many TP-first profitable configurations stayed profitable under SL-first. At 3,000 or more trades, 99.94% changed and only 61 of 1,324,931 TP-first profitable configurations remained profitable. Frequency is a validation-priority signal, not proof of the cause. Source: all 48.825 million matched configurations.

The affected share rose with realized trade count:

  • 25.70% at 1 to 29 trades;
  • 54.85% at 30 to 99;
  • 73.77% at 100 to 299;
  • 91.72% at 300 to 999;
  • 99.01% at 1,000 to 2,999;
  • 99.94% at 3,000 or more.

In the 3,000-plus bucket, only 61 of 1,324,931 TP-first profitable configurations remained profitable under SL-first.

Repeated exposure to ambiguous bars is consistent with the rising affected share. High-frequency indicator families and tight exit settings overlap, so trade frequency is a warning signal for validation priority rather than an identified cause.

6. Tight exits are vulnerable, but wide exits are not immune

The effect was not confined to one take-profit or stop-loss corner.

Every take-profit and stop-loss cell was sensitive to same-bar fill orderA five by five heatmap of the share of matched configurations whose total return changed. Values range from 62.1 percent at four percent take-profit and stop-loss to 83.2 percent at one percent take-profit and stop-loss.take-profitstop-loss0.5%1%2%3%4%0.5%1%2%3%4%75.5%80.2%82.2%80.5%77.6%79.8%83.2%81.7%78.5%75.2%81.0%81.2%77.6%74.7%70.9%79.3%78.0%74.0%70.9%67.4%77.1%75.3%71.2%67.9%62.1%Highest affected share83.2%TP 1% / SL 1%Widest exits62.1%TP 4% / SL 4%TTL sensitivity75.3% to 76.5%6 to 96 barscell value = share with changed total returnThe share of matched configurations whose total return changed in each TP and SL cell. All 25 exit shapes were affected, from 62.1% with 4% exits to 83.2% at TP 1% and SL 1%. TTL changed the affected share much less, from 75.3% to 76.5% across 6 to 96 bars. Source: all 48.825 million matched configurations.

In every one of the 25 TP and SL cells, total return changed for at least 62.1% of configurations.

  • TP 1% with SL 1% had the highest affected share at 83.2%.
  • TP 0.5% with SL 0.5% changed in 75.5% of configurations. Its profitable n30 count fell from 658,800 to 838.
  • Even TP 4% with SL 4% changed in 62.1%. Its profitable n30 count fell from 267,920 to 154,418.

Changing TTL from 6 to 96 bars moved the affected share only from 75.3% to 76.5%. In this grid, exit geometry and repeated exposure were more useful warning signals than TTL.

Use that pattern as a prioritization signal within these five perpetual markets, one-hour bars, and this fixed exit grid.

7. Run the test on your own candidate set

The procedure is simple, but the controls matter:

  1. Freeze the candles, date range, costs, funding, strategy grid, and exit grid.
  2. Enable Save all results before starting the scan.
  3. Run the TP-first search with Conservative Fill off.
  4. Repeat the same search under SL-first with Conservative Fill on.
  5. Compare the two Parquet exports offline.
  6. Pair rows by an immutable configuration key, not row position or rank.
  7. Compare total return, win rate, maximum drawdown, and candidate survival.
  8. Keep row-local performance changes separate from job-level RMP and DSR recalibration.
  9. Flag any SL-first-only or RMP/DSR classification disagreement for a screen-calibration audit.
  10. Send TP-first-only candidates to lower-timeframe or tick replay.

A cached result may lack a full export and require a fresh run. Builder opens results displayed in the leaderboard, while arbitrary Parquet rows remain an offline workflow. Pairing the exports and assigning the three decision buckets are also offline research steps.

Comparing two exported rows is easy. Producing two auditable search populations that differ in only one execution rule is the real experiment.

Ranking is a poor substitute for pairing. Top lists can change because many rows tie at a metric ceiling, and RMP or DSR can move when the surrounding trial population changes. The immutable strategy and exit key is the comparison unit.

The paired scans give you two auditable populations. Use them to promote robust candidates and direct intrabar data toward the unresolved set.

8. What surviving the adverse fill proves

Passing both modes shows robustness to this modeled same-bar ambiguity and earns the candidate its next test. A TP-first-only pass leaves the hourly evidence unresolved and tells you which candidate needs intrabar evidence next.

Lower-timeframe data narrows the unknown sequence but inherits its own bar resolution. Live fills also depend on gaps, spread, liquidity, queue position, partial fills, latency, and market impact. QuantConnect's documentation, for example, notes that built-in backtest fill models assume complete fills unless a custom partial-fill model is supplied.2

The method replaces one fragile point estimate with a decision: advance, investigate, or reject. At search scale, that decision turns limited intrabar data into a resource you can allocate deliberately.

This article is for education and research, not financial advice. Trading can result in loss of principal. Backtest results do not guarantee future performance, and past performance does not predict future results.

Frequently asked questions

Is SL-first the realistic fill?

No. It is the adverse assumption in this two-rule model. The actual sequence is absent from the hourly bar.

Should I discard every candidate that fails SL-first?

If it passes TP-first but fails SL-first, treat it as unresolved and replay it with finer intrabar data. If it fails the common row-level gate under both modes, reject it under the current strategy specification.

Does lower-timeframe data solve the problem?

It reduces the ambiguity by revealing more of the path. It does not reproduce order-book priority, partial fills, or every live execution constraint.

Footnotes

  1. TradingView, Strategies: broker emulator and Bar Magnifier.

  2. QuantConnect, Trade fills: key concepts and supported equity fill models. 2

crypto-backtestingexecution-modelstop-losstake-profitstrategy-validation