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.
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
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.armHigh10800000 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
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 |
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 |
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.
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.
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

