Every condition has an evaluate field. The default is on_close:
the engine waits for the strategy's timeframe bar to close, then
checks the condition against that bar's values. The alternative is
on_tick: the engine checks the condition every minute against the
live 1-minute close.
On-close (default)
Use this for any condition that reads an indicator value: RSI, ADX, MACD, EMA, Bollinger Bands, Williams %R, anything else. Indicator values are only meaningful once the bar that produced them closes. On-close also matches backtest semantics exactly, so the live behavior mirrors what you measured.
On-tick
Use this for price-anchored conditions that need to fire intra-bar:
- "Live price entered the demand zone"
- "Price crossed the breakout level"
- "Price is in a specific range" (limit-order-like)
The engine swaps the condition's price columns (open/high/low/close) for the latest 1-minute close. Indicator values stay at their last-closed-bar reading.
Strategies with at least one on-tick condition are re-evaluated every minute instead of once per timeframe bar. For a single 4h strategy this is irrelevant. At scale (1000+ live strategies) it's measurable. Add on-tick deliberately, not by default.
What you give up
Faster reaction is rarely free. In our internal data, identical strategies switched from on-close to on-tick caught roughly 2x the entries but the win rate dropped from 56% to 40%. The extra entries were the noisy intra-bar wicks that would have been gone by the next close.
Reach for on-tick when the strategy is fundamentally about price touching a level - not as a generic "more signals" knob.
Backtest fidelity
When the engine sees an on-tick condition, the backtest walks each bar as four synthetic sub-bars (open -> low -> high -> close) and probes the entry rules at each step. The first sub-bar that satisfies all conditions fires the entry, and the entry price equals that sub-bar's price.
This gives backtest fills that match the live runtime's intra-bar behavior. The approximation is faithful for zone-touch and level-break strategies. It's less precise for momentum strategies with tight intra-bar stops where the exact path within the bar matters - the engine doesn't know whether price went up-then-down or down-then-up within a bar, it just visits both extremes.
Mixing both modes
Conditions inside the same rule can use different modes. Common pattern: indicator filter on-close, price-touch trigger on-tick.
{
"long": {
"logic": "AND",
"conditions": [
{ "type": "comparison", "indicator": "rsi", "operator": "<", "value": 30 },
{ "type": "price_in_supply_demand_zone", "zone": "demand", "evaluate": "on_tick" }
]
}
}The RSI check runs once per closed bar; the zone-touch runs every minute. The entry fires the minute both are true.
