← All articles

Build a trading strategy that remembers a setup and waits for confirmation

Model a three-hour confirmation window with no-code state rules, then inspect why a setup entered, expired, or exited in a real backtest.

Strategy methodsPublished By Stratifyre

Topics

Strategy RulesNo-Code TradingVisual Trade Analysis

You want to remember a bearish hourly candle, buy only if a later candle closes above its high within three hours, and discard the idea if confirmation arrives too late. After entry, use the remembered low as a protective stop and close any surviving position after three hours.

An indicator threshold cannot describe that whole sequence. The strategy needs a memory, a deadline, and a way to clear its memory after a decision. Those are the requirements to check when evaluating whether you can build a complex trading strategy without coding.

This example separates four decisions—remember, confirm, expire, and exit—into saved Stratifyre rules. The point is to inspect whether a sequence executes as specified; a short historical example does not establish a trading edge.

Write the sequence before choosing an indicator

Start with what must remain true after the original candle disappears from the newest chart position. Here, the setup candle is simply bearish: its close is below its open. We preserve that candle’s high, low, and evaluation timestamp while waiting for confirmation.

The setup is deliberately modest. It uses one instrument, one interval, fixed sizing, and no indicator warmup. The complexity comes from remembering an earlier event and enforcing its deadline.

“Later” excludes the setup candle itself. “Above” excludes equality. “Within three hours” includes confirmation exactly at the deadline, while expiration requires a timestamp strictly beyond it. These small choices determine which trades qualify.

This is an elapsed-time window, measured in milliseconds. On this continuous hourly dataset, three hours covers three later hourly evaluations. It is not a rule to count three exchange-session candles: missing data or an overnight market closure would require a separate decision about the intended clock.

Give memory a name and a reset rule

Stratifyre’s expression language is the formula surface inside its rule builder. A rule combines conditions with actions; setting a local variable records information for the instrument being evaluated. Local state uses vars.*; shared state uses globals.*. This example uses local state throughout. Rule scopes and variable actions.

Saved value Meaning When it changes
vars.armed A remembered setup is waiting Set to 1 on setup; set to 0 on entry or expiration
vars.armHigh Price confirmation must exceed Written when a fresh setup arms
vars.armLow Protective stop reference Written with the same setup
vars.armedAt Beginning of confirmation window Written with the setup
vars.enteredAt Entry-decision timestamp Written when confirmation submits the buy

An uninitialized local variable reads as zero in the inspected runtime. That lets vars.armed == 0 describe the initial state. More importantly, the arm rule does not replace a waiting setup with each new bearish candle: its unarmed guard preserves the original deadline and prices.

Inspect the saved memory rule
Actual saved rule requiring a flat, unarmed position and bearish candle, followed by four local-variable actions
Actual strategy editor: the arm rule stores high, low, evaluation time, and the armed flag. Open the image for full resolution.

Read the exact confirmation expression

The following is the saved condition expression for the entry rule, validated against the current Rust rule engine. Its result is compared with 1 in the condition editor because true comparisons evaluate numerically.

position.open_qty == 0
&& vars.armed == 1
&& time.current_ms > vars.armedAt
&& time.current_ms <= vars.armedAt + 10800000
&& close > vars.armHigh

10800000 is three hours: 3 × 60 × 60 × 1000. time.current_ms supplies the evaluation timestamp. The close must exceed the remembered high, rather than merely exceed the previous candle’s high. Expression reference.

An event operator such as crossing-up checks a transition between evaluations. A memory-based condition answers a different question: whether this close confirms the particular setup that is still armed. In this strategy, clearing armed after entry prevents that remembered setup from issuing another entry.

Each rule here uses “No limit”; the state and position guards enforce its sequence. A daily trigger limit would add a different policy. One setup does not mean one entry per day, and a three-hour deadline does not reset automatically at midnight.

All rule conditions in the inspected runtime evaluate before their triggered actions execute. A variable written by the arm rule is therefore read during a later evaluation. The explicit later-timestamp guard makes that requirement visible in the saved strategy instead of relying on rule names or a hoped-for same-bar handoff.

Inspect the saved entry and reset actions
Actual confirmation rule showing a 0.001 BTC market buy with vars.armLow stop, entry timestamp write, and armed flag reset
Actual saved entry actions. The editor clips the long condition horizontally; its complete validated expression appears above. Open the image for full resolution.

Keep signal timing separate from the fill model

The demonstration window is January 6–12, 2025, on Binance BTC/USDT spot, canonical instrument CRYPTO:BINANCE:BTCUSDT. The requested window contains 168 consecutive hourly bars, with no missing hourly timestamps in the returned data.

Setting Demonstration input
Starting capital $10,000
Entry Fixed 0.001 BTC; long only; no additions while long
Evaluation interval One hour; no indicator warmup
Execution and fill On-close; close fill mode
Protection Stored setup low; three-hour timed flatten
Costs Zero configured commission, slippage, and market impact
End of window Flatten remaining exposure
Actual backtest configuration showing January 6 through 12, 2025, hourly evaluation, on-close execution, close fill mode, and 10,000 starting capital
Actual settings for this retained run. The separate saved configuration confirms zero configured costs. Open the image for full resolution.

The observed entry uses the confirming candle’s close price, with its fill recorded at the following hourly timestamp. Decision records use the candle’s opening timestamp: a candle labeled 02:00 UTC covers 02:00–03:00, so its decision label does not mean its final close was available at 02:00. Read the recorded labels and prices together.

These close-price fills are a simplified mechanics check. They do not model whether a trader could observe a finalized hourly close and obtain that exact price. The stop also runs within the hourly execution model; this example does not inspect a one-second path through the candle or guarantee a sale exactly at the stop price.

Fixed 0.001 BTC is a quantity, not a fixed dollar risk. A wider distance between entry and remembered low exposes more money before costs. The zero-cost configuration isolates the sequence; it supplies no broker-fee estimate or after-cost profitability claim.

Audit the remembered candle, entry, and non-entry

The first setup shows why a wick above a level is different from a close above it. The January 6 candle labeled 00:00 UTC closed at 98,217.23, below its 98,363.61 open. Its remembered high was 98,773.48 and low 98,190.75.

January 6 UTC bar label Price or event Decision
00:00 Bearish close 98,217.23 Arm; store high 98,773.48 and low 98,190.75
01:00 High 98,816.28; close 98,759.43 No entry: wick exceeded the level, close did not
02:00 Close 98,815.39 Confirm two hours after setup; submit buy; clear armed flag
03:00 Recorded buy fill at 98,815.39 Position opens; original stop is 98,190.75
05:00 Close 99,600.00 Submit timed flatten, three hours after entry-decision label
06:00 Recorded sell fill at 99,600.00 Position closes
Actual hourly BTC backtest chart with filled buy near 98,815 and filled flatten sell near 99,600 for the audited first trade
Actual chart replay with native filled-order annotations; canceled-order labels are hidden. Its axis displays America/New_York time; the audit table uses UTC. Open the image for full resolution.

The trade record reports three hours held and a $0.78461 gain: (99,600.00 − 98,815.39) × 0.001 BTC. The timer was saved from the entry decision, not the fill timestamp; the recorded entry and exit fills each occur one hourly label after submission in this trade. Do not infer same-timestamp execution from the “on-close” setting alone.

Actual first-trade details showing entry 98,815.39, exit 99,600, initial stop 98,190.75, three hours held, and rounded profit 0.78 dollars
Actual completed trade: the remembered low appears as the original stop, while the timed flatten closes this position. Profit and dollar risk are rounded in the UI. Open the image for full resolution.

The next setup armed on the candle labeled 06:00 with a 99,763.99 high. The 07:00, 08:00, and 09:00 closes were 99,318.70, 99,043.49, and 98,999.99: all failed confirmation, including the final eligible evaluation. At 10:00, the first evaluation strictly after the deadline, the state snapshot showed armed = 0. That setup issued no buy.

Across the full seven days, the retained state history contains 28 armed setups, nine entries, and 19 expirations. Every entry was later than its setup, within three hours, and above the stored high. Six trades closed through timed flatten orders; three closed through the stop. Four trades won and five lost, for a net −$0.46025 and ending account value of $9,999.53975 before rounding.

Actual report summary showing a rounded 0.46 dollar loss, 44.44 percent win rate, and 0.85 profit factor
Actual run summary. Tiny fixed sizing makes percentage return and drawdown round toward zero; that does not mean the exact loss was zero. Nine trades do not establish profitability. Open the image for full resolution.

When replaying a decision, compare the previous state, saved expression, and order records. A condition badge rendered from the post-action state may show false after the entry has cleared armed; that badge alone is not a preserved trace of the original decision.

Decide what the test establishes

A saved condition proves what was configured; an accepted expression proves syntax and supported references. A completed trade plus its preceding state and price data establishes how this particular historical execution behaved. Inspect all three before treating the result as an implementation of your idea.

The same worksheet can expose requirements in other strategy families: a failed breakout needs a remembered level and failure deadline; a cooldown needs an exit event and restart clock; a portfolio rule needs an explicit choice between local and shared state. These are requirements to validate, not additional executions demonstrated here.

Persistent price areas require formation, boundaries, and invalidation rules; use the zone-definition documentation for that separate task. Higher-timeframe inputs require their own information cutoff. This example demonstrates neither zone detection nor a multi-timeframe filter, scanner, paper session, or broker behavior.

If your starting idea is still vague, first turn the words into explicit rules. If the sequence is already precise, create one strategy with a remembered value, a deadline, and a reset, then inspect a trade and a rejected setup before expanding the test.

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