← All articles

Backtest an Order-Block Retest With Rules You Can Inspect

Define an order block’s formation, bounds, and invalidation, then inspect a real hourly Bitcoin retest, its confirmation timing, and a failed trade.

Strategy methodsPublished By Stratifyre

Topics

Order BlocksPrice ActionBacktesting

An order-block backtest starts with a definition that another trader could reproduce. Which candle creates the area? Do its wicks or body set the boundaries? When does the area become available, and what makes it fail?

This example saves one bullish definition, runs it on hourly Binance BTC/USDT data, and follows both a winning retest and a losing trade. The purpose is to inspect the rules. A price pattern does not reveal institutional orders, and this short, zero-cost simulation does not establish a trading edge.

Define the area before defining the entry

For this test, a bullish order block means a bearish origin candle followed by a bullish confirmation candle whose close clears the origin’s high. The saved definition requires all three conditions:

bar.close[1] < bar.open[1]
bar.close > bar.open
bar.close > bar.high[1] + (bar.high[1] - bar.low[1]) * 0.015

Here [1] means the preceding candle. The extra clearance is 1.5% of the origin candle’s high-to-low range, not 1.5% of Bitcoin’s price. The zone uses that candle’s entire range:

Decision Saved choice
Upper boundary Origin candle high: bar.high[1]
Lower boundary Origin candle low: bar.low[1]
Invalidation A later close strictly below the lower boundary: price < zone.lower
Detection interval Explicitly 1h
History and retention 168-bar lookback; maximum 20 retained active zones

A wick below the lower boundary does not satisfy this close-based invalidation. An attached trading stop can still trigger on that wick. The area’s lifecycle and the position’s exit are separate decisions.

To reproduce the definition, start from Bullish Order Block Zones in the strategy editor’s Add Zone Definition menu, then set the hourly interval, lookback, and ID shown below. Check the expressions after saving; the preset’s daily default would describe a different test.

Saved hourly bullish order-block formation, origin-candle bounds, and close-based invalidation
Actual saved definition used by this run, including its hourly interval and three formation conditions. Open the full-size definition.

Stratifyre’s zone-definition documentation describes these separate formation, boundary, and invalidation controls. A “Demand” label classifies the area; it does not supply those conditions.

Turn the retest into an entry

The entry references the definition’s ID, blog-bullish-ob. It requires an available zone and a flat position before testing the newest retained area:

ZONE_ACTIVE_COUNT(ZONES({id: 'blog-bullish-ob'})) > 0
position.open_qty = 0
bars['1h'].low <= ZONES({id: 'blog-bullish-ob'})[0].upper
bars['1h'].close > ZONES({id: 'blog-bullish-ob'})[0].upper
bars['1h'].close > bars['1h'].open
ZONES({id: 'blog-bullish-ob'})[0].touchCount = 1

All conditions connect with AND. The candle must trade into the area and finish bullish above its upper edge. Touch counting uses range overlap: consecutive overlapping candles belong to one touch episode, so the rejection can occur after the first overlapping candle.

The action buys 0.01 BTC, places a stop at the selected zone’s low, and sets a target two times the signal-close-to-stop distance above the signal close. A Once per 1D limit restricts repeated entries; it is a time restriction rather than “one trade per zone.”

Saved retest conditions check a retained zone, flat position, overlap, bullish rejection, and first touch
Actual saved entry conditions. Open the full-size rule.
Saved fixed Bitcoin quantity, zone-low stop, target expression, and daily trigger limit
Actual action and repeat-entry controls; no broker order was submitted. Open the full-size action.

The retained set is limited by lookback and proximity to price; [0] selects the newest member of that set. It is not a permanent reference to every historical block.

Check confirmation time against the recorded trade

A rectangle drawn over an earlier candle can make a pattern look available too soon. TradingView’s repainting discussion explains why unconfirmed values and plotting into the past deserve scrutiny. That general warning is not proof of another platform’s timing; inspect the actual sequence.

For the first trade, the origin candle’s high was $94,952.29 and its low $94,542.00. Its range was $410.29, making the clearance $6.15435. The next candle closed at $95,128.59, above the required $94,958.44435.

  1. Origin: January 1, 23:00 UTCThe bearish candle supplies the two boundaries.
  2. Confirmation: January 2, 00:00 UTCThe bullish candle clears the origin high plus the specified range allowance.
  3. First zone event: 01:00 UTCThe retained event identifies the confirmed area and one touch. Confirmation and first observation are different timestamps.
  4. Rejection and order: 02:00 UTCLow $94,803.03 overlaps the zone; bullish close $95,234.36 clears its upper edge.
  5. Recorded fill: 03:00 UTCThe returned trade uses the prior signal candle’s $95,234.36 close.

These are recorded candle-opening and event labels, not intrahour execution times. The confirmation candle’s closing value exists only after that hour finishes. The detector excludes its newest candle from formation replay; this run’s first zone event occurs on the next update, rather than at the origin candle.

Actual hourly chart shows the retained order-block areas and the first buy and target fills
Actual replay after the first trade, at January 2, 10:00 UTC. The UI displays America/New_York time; the matching area is $94,542–$94,952.29. Its buy filled at $95,234.36 and its target at $96,619.08. Open the full-size replay.

The position’s initial risk was (95,234.36 − 94,542.00) × 0.01 = $6.9236. Its target gain was $13.8472. That reconciles the returned prices and quantity; it does not establish that a real market order could obtain the simulated close.

Keep the interaction that failed

The third trade bought at $98,227.48 with a $97,909.85 stop. The returned stop exit lost $3.1763 on 0.01 BTC.

The zone’s invalidation timestamp was January 5, 08:00 UTC. That hourly candle closed at $97,861.04, below the saved lower boundary. Its later drawing-update event was timestamped 10:00 UTC: the chart update and recorded invalidation are separate observations.

Actual replay includes the losing buy, stop fill, and failed order-block area
Actual replay at January 5, 12:00 UTC, displaying America/New_York time. The $98,227.48 buy and $97,909.85 stop are retained alongside earlier trades and zones. Open the full-size failed interaction.

A failed zone does not automatically become a profitable opposite-direction setup. The useful observation is narrower: these entry conditions can trigger before an area later fails.

Read the report as a rule audit

The single prespecified run used Binance spot BTC/USDT, January 1–7, 2025, hourly bars, $10,000 starting capital, fixed 0.01 BTC sizing, on-close execution, close-price fills, enforced volume limits, and final flattening. Commissions, slippage, and market impact were deliberately set to zero.

Returned trade P&L before modeled costs
First target exit +$13.8472
Second target exit +$13.1514
Stop exit −$3.1763
Third target exit +$15.6645
Final boundary close $0.0000
Total +$39.4868
Completed report displays the recorded return and profit before modeled costs
Actual completed summary: $39.49 P&L and 60% displayed win rate. Five trades and zero modeled costs do not support the displayed “Excellent” label as evidence of future performance. Open the full-size report.

Ending equity was $10,039.4868. The records contain three positive trades, one negative trade, and one flat trade; the report counts that flat trade within its two “losing trades.” The final flat entry and flattening share a January 8, 00:00 UTC timestamp, beyond the 168 hourly bars checked for January 1–7, and its price matches that additional boundary candle’s close. Keep that boundary artifact visible rather than counting it as a normal losing retest.

This run answers a rule-inspection question. It does not establish after-cost profitability, reliable risk estimates from five trades, intrabar price ordering, or live fill quality. Test realistic costs and later periods separately using the slippage stress-test workflow.

Give swing levels and breakers their own definitions

The same worksheet helps distinguish three ideas without treating their names as detection logic:

Idea What must be explicit
Order block Origin candle, displacement confirmation, bounds, and close-versus-wick invalidation; executed above
Confirmed swing level Middle candle compared with both neighbors, confirmation after the right neighbor, and zone width
Breaker hypothesis Which original block failed, which bounds survive, and a separately confirmed opposite-side retest

The current swing-low preset compares the middle candle’s low with both neighbors, uses a band extending upward by 1% of that middle candle’s range, and invalidates on a later wick below its low. The swing-high preset mirrors that structure. These are source-checked definitions, not additional executions in this article; set their interval explicitly before testing them.

This run did not execute a breaker strategy. There is no dedicated breaker preset in the inspected catalogue, and changing a zone’s label does not add failed-block tracking or automatic role reversal. A custom breaker needs its own saved conditions and an observed failure-to-retest sequence before making that claim.

Choose one area, write its formation and invalidation rules, then use Stratifyre’s backtesting workflow to inspect when it became available, why the trade fired, and what happened when it failed.

Put your strategy rules to the test

Build your strategy, inspect historical trades, and review the assumptions behind your results.

Build and test your strategy