Reference

Phrasing families

Ways of saying a condition beyond a plain comparison: range position, streaks, recency, relative volume and volatility-scaled moves.

Most conditions are a plain comparison: a value against a number or another series. But a lot of real trading ideas are not shaped like that. They talk about a window, where price sits in its yearly range, how long ago something happened, whether a state held for five bars, how big a move is relative to current volatility.

Each of those is a phrasing family: a way of saying a condition that gets compiled into exact maths on your bars. They are not a special mode or a separate syntax, write them in an ordinary strategy sentence and combine them freely with everything else (AND/OR, direction, sessions, higher-timeframe gates, stops and targets).

Copy the phrasing, change the numbers

Each example below is a working phrase. The wording in bold is what the parser keys on, keep it and swap the asset, the numbers and the window. Every family has a ready-to-run card in the templates gallery under Windows & streaks.

Where a value sits in a window#

Say thisWhat the engine checks
price is in the bottom 20% of its 52-week rangeclose ≤ lowest(low, N) + 0.20 × (highest(high, N) − lowest(low, N))
price trades in the top 10% of the 20-day rangethe same band, measured from the top
price is in the lower quartile of its 100-bar rangequartile / third / half / decile all work
price is 20% below its all-time highclose ≤ 0.80 × all-time high
price is within 5% of the 52-week highproximity to one extreme

The window is read on your timeframe: a 52-week range on the 1d is 364 bars; a 6-month range on the 4h is 1080.

Range position is not distance from the high

"20% below the high" anchors on one extreme. "The bottom 20% of the range" anchors on the whole range: high and low. In an asymmetric range these are different conditions, and the parser keeps them apart. Say the one you mean.

Where the bar closed inside itself#

A close-strength (close-location) filter, for when a bar closing on its high means something different from a bar closing on its low.

Say thisWhat the engine checks
the candle closes in the top 25% of its rangeclose ≥ low + 0.75 × (high − low)
price closes in the lower third of the barclose ≤ low + 0.333 × (high − low)
the bar closes near its highthe top quarter of the bar (the documented convention)

The deciding difference from the family above is the window: a bar/candle range (or no window at all) is this one; an N-day / N-week / N-bar range is range position.

How long ago something happened#

Say thisWhat the engine checks
at least 10 bars since RSI was above 70bars since (RSI > 70) ≥ 10
fewer than 5 bars since the MACD crossed its signalbars since (cross) < 5
more than 20 bars since price closed above the 200 EMAbars since (close > EMA200) > 20
This is the opposite of a live filter

"10 bars since RSI was above 70" does not mean RSI is above 70 now, it means it isn't, and hasn't been for a while. Use at least / more than for a cooldown and fewer than / within for freshness.

A state or a direction that has to persist#

Say thisWhat the engine checks
RSI has been above 50 for 5 consecutive barsthe comparison holds on every one of the last 5 bars
price has stayed above the 20 EMA for 3 bars in a rowsame, against a series
the 50 EMA has been rising for 5 consecutive barsthe EMA is higher than the bar before on each of those 5 steps
RSI has been falling for 3 barsthe mirror

Compare with the proportion form, which is a different question: 60% of the last 20 bars closed above the 50 EMA counts bars in a state; for 5 consecutive bars requires all of them.

Level vs slope

"the 10-bar ROC is positive" is a level (ROC > 0). "the 10-bar ROC is rising" is a direction. Adding "for 3 bars" to either one makes it persist; it does not turn one into the other.

Volume, normalised#

Raw volume thresholds don't travel between assets or across years. These do.

Say thisWhat the engine checks
relative volume is above 2 (or RVOL > 2)volume ≥ 2 × mean(volume, 20), twice normal participation
relative volume above 1.5 over the last 50 barsthe same, averaged over 50 bars
dollar volume is above $10 millionclose × volume ≥ 10,000,000
turnover above $5Msame as dollar volume
volume is twice its 20-bar averagevolume ≥ 2 × mean(volume, 20)
RVOL is a multiple, never a unit count

"relative volume above 2" means twice the average, not two units, which would be true on every bar. If you want an absolute floor, say volume is above 1,000,000.

A series at its own extreme#

For any non-price series (RSI, ADX, ATR, volume, MACD) this adapts instead of waiting for a fixed level a strong asset may never reach.

Say thisWhat the engine checks
RSI is at its lowest in 50 barsRSI ≤ lowest(RSI, 50)
volume is the highest of the last 20 barsvolume ≥ highest(volume, 20)
ADX is at a 100-bar highADX ≥ highest(ADX, 100)

For price extremes, use the breakout wording instead: price makes a new 20-day high, price breaks above the 20-bar high, which routes to the breakout/Donchian logic.

Moves measured in volatility#

The same percentage means something different in a calm month and a violent one. Measuring in ATR keeps the rule honest across regimes.

Say thisWhat the engine checks
price has fallen more than 2 ATR in the last 5 barsclose − close[5] ≤ −2 × ATR(14)
price has risen more than 1.5 ATR(20) over the last 10 barswith an explicit ATR period
price has moved more than 3 ATR over the last 10 barsundirected, both tails fire
price closes more than 2 ATR above the previous closethe single-bar form
price is 2 ATR below the 20 EMAan overextension band around an indicator

Intraday anchors: the opening range and today's levels#

These read the CURRENT day, and reset at each new day.

Say thisWhat the engine checks
price breaks above the high of the first 30 minutesthe first-N-bars range of the day, broken
price breaks below the low of the first 4 barsthe same range, downside
price is above today's openclose > day_open
price hits the day's high / the low of the daythe running extreme so far today
price is down more than 3% on the dayclose ≤ 0.97 × day_open
Today is not yesterday, and the day is not a session

"Today's high" is the running extreme so far today; "yesterday's high" is a completed previous-day level. They are different conditions, and the parser keeps them apart. And if you name a session, "the New York session opening range", that anchors to the session open instead of the day open, which is a separate (also supported) level.

The opening range only exists once it is complete

Until the first N bars of the day have printed, the range is undefined and the condition is false. That is deliberate: a breakout judged against a range still being built would be reading bars the strategy has not traded through.

Gaps, coils and bar shape#

Say thisWhat the engine checks
price fills yesterday's gap / the gap closesprice trades back through the previous day's close
the last 10 bars have a range under 3%highest(high,10) − lowest(low,10) ≤ 0.03 × close
the 20-bar range is tighter than 5%the same, wider window
the candle range is more than 1.5 ATR(high − low) ≥ 1.5 × ATR(14)
the body is bigger than 1 ATR(20)|close − open| ≥ 1 × ATR(20)
price is within 0.1% of a round 1000 leveldistance to the nearest multiple of 1000
Gap fill is direction-agnostic on purpose

"Fills the gap" says nothing about which way the gap went, so the condition fires when price touches the previous close from either side. Say "gaps down 2%" separately if you want to detect the gap itself as well.

Round levels: state the increment, and keep the tolerance tight

"A round number" could mean 100, 1000 or 10000, the parser will ask rather than guess, so say which ("a round 1000 level", "multiples of 500"). And because the tolerance is a percent of price, it must be tighter than half the increment: at BTC prices, "within 1% of a round 1000 level" is wider than the gap between levels, so every bar qualifies.

Ranking a series against its own history#

Say thisWhat the engine checks
RSI is in the bottom 10% of its last 100 readingspercent rank of RSI over 100 bars ≤ 10
ATR is in the top 5% of the last 200 barspercent rank ≥ 95
volatility is in its bottom quartilethe regime filter (no explicit window needed)

The explicit "of its last N readings" form works in exits too, and composes inside larger expressions, the shorter regime phrasing is an entry filter.

How this asset moves against another one#

These are relationships, not filters. "Only while BTC is above its 200 EMA" asks about BTC; these ask how the two assets move together.

Say thisWhat the engine checks
the 30-day correlation between ETH and BTC drops below 0.5correlation of the two return series over 30 bars
the correlation to BTC is above 0.8the same, against the asset you are trading
ETH has outperformed BTC over the last 30 daysETH's 30-bar growth ≥ BTC's 30-bar growth
it is underperforming SPY over 60 barsthe mirror
ETH outperforms BTC by more than 5% over 20 dayswith an excess-return margin
the ETH/BTC ratio is at a 50-bar highthe pair ratio at its own rolling extreme
the 60-day beta to SPY is above 1.5the OLS slope of this asset's returns on the benchmark's
Correlation and beta are measured on returns

Two assets that both trend up have a price correlation near 1 no matter how differently they behave, so a price-based answer would be meaningless. These conditions compare the return series, which is what the words mean to a trader.

Name the other asset

"Beats the market" and "correlated with everything" have no series behind them, so the parser will not invent one. Say the symbol: outperformed BTC, beta to SPY, correlation between ETH and BTC.

Exits that depend on the trade, not on a price#

Most exits are a level, a stop, a target, an indicator crossing. These four depend on how the trade itself has behaved, which no price condition can express.

Say thisWhat the engine does
exit if the trade isn't profitable after 10 barsat bar 10 onward, close on the first bar that is not in profit
give it 20 candles to work then cut itthe same, in the other phrasing
exit if it gives back half of the open profitclose once the open profit falls to half its peak
close it if it retraces 30% of the gainthe same, at 30%
exit on the first profitable closeclose on the first bar strictly beyond your entry
hold for a maximum of 5 daysa hard time cap, converted to bars for your timeframe
exit when price closes below the lowest low of the last 5 barsa structure trail
A time box is not a time exit

"Exit after 10 bars" closes the trade no matter what, winners included. "Exit if it isn't profitable after 10 bars" spares the winner and cuts only the trade that failed to work. Both are supported; they are different strategies, so say the one you mean.

Give-back is not a trailing stop

A trailing stop follows price by a fixed distance. A give-back is a fraction of the profit the trade has already shown, so it tightens automatically as the winner grows. It also arms only once the trade has genuinely been green, the peak is measured on closes, so a wick through your entry cannot turn it into a second stop-loss.

Say the time unit for a holding cap

The engine's clock is bars. "A maximum of 5 days" on a 4-hour chart becomes 30 bars, but only because you said days. If you write "5 bars", you get 5 bars.

This week, this month, this year#

The day anchors have week, month and year siblings. These are the current period's running values, and they reset at each boundary.

Say thisWhat the engine checks
price breaks above this week's highthe running high of the current week
price hits the low of this monththe running low of the current month
BTC is down more than 5% this weekclose ≤ 0.95 × the week's open
it is up 20% year to dateclose ≥ 1.20 × the year's open
price makes a new weekly highthis bar takes out the week's high so far
price is in the bottom 20% of this week's rangewhere in the week's range it is trading
This week is not last week

"This week's high" is the running high of the week you are in; "last week's high" is a completed level from a different week. Both work, they are different conditions, and the parser keeps them apart on exactly that wording.

Period-to-date resets; a rolling window does not

"Down 5% this week" is measured from the week's open and starts again every Monday. "Down 5% over the last 10 bars" slides forward every bar and never resets. Pick the one that matches how you think about the trade.

Two timeframes in one condition#

Saying "the daily RSI is above 50" moves that whole condition to the daily chart, which is usually exactly right. These three are the cases where the two sides of the comparison live on different timeframes, which a single higher-timeframe filter cannot express.

Say thisWhat the engine checks
the 1h RSI is above the daily RSIthis chart's RSI vs the daily RSI, in one condition
price is more than 3% below the daily 200 EMAthe current price against a daily level
price is 2 ATR above the weekly VWAPthe same, measured in volatility
price is above where it closed 3 daily bars agothis chart's price vs a daily close from three days back
A filter moves the whole condition; a distance does not

"Price is above the 200 EMA on the daily" asks whether the daily bar is above its daily EMA, a trend filter, and the right reading. "Price is 3% below the daily 200 EMA" asks how far the price is right now from that level. Adding the distance is what tells the parser you mean the second one.

Three daily bars ago is a value, not a period

"Where it closed 3 daily bars ago" is an earlier value of the same series. RSI(3) is a different indicator entirely. The parser keeps them apart, but the wording matters.

Who is actually doing the buying#

Say thisWhat the engine checks
the cumulative volume delta over the last 20 bars is positiveeach bar's volume signed by whether it closed up or down, summed
CVD turns negative over 50 barsthe same, other side
up volume is more than twice down volume over the last 20 barsthe two sides summed separately and compared
dollar volume is in the top 10% of the last 100 barsparticipation ranked against its own history
the bar range is in the top 5% of the last 200 barsthe same, on range
bullish OBV divergence, bearish volume divergencedivergence measured on that series
Divergence is not RSI-only

Divergence works on obv, volume, cci, mfi, roc, williams %r and stochastic as well as rsi and macd. If you were told otherwise before, that guidance was out of date.

Bar-level CVD is a proxy

True cumulative volume delta needs tick data to know which side each trade hit. On bars, the standard approximation is each bar's volume signed by whether it closed up or down which is what these conditions use. It is a good proxy, not the real thing.

Volatility and regime#

These describe how the asset is behaving right now, rather than where its price is. They are unit-free, so the same number means the same thing on every asset and in every year.

Say thisWhat the engine checks
20-day realized volatility is below 40%the standard deviation of returns, annualised, as a percentage
historical volatility is above 80%the same (window defaults to 20)
the 20-bar efficiency ratio is above 0.6how much of the distance travelled actually went somewhere
a 3 standard deviation down movethe size of the return against the asset's own recent spread
the move is more than 3 sigmathe same, either direction
the 20-day autocorrelation is negativewhether yesterday's move tends to be given back
returns are positively autocorrelated over 30 daysthe same, other side
Realized volatility is a percentage, ATR is a price

"Volatility below 40%" and "ATR below 40" are different conditions. ATR is measured in the asset's own currency, so 40 means something different for every asset and every year. Realized volatility is the annualised percentage every options desk quotes, write the % and you get the comparable one.

Efficiency ratio vs ADX

Both answer "is this trending or chopping". The efficiency ratio is bounded between 0 and 1 1.0 is a straight line, 0 is noise that ends where it started, so a threshold you pick on one asset transfers to another. ADX does not have that property.

Sigma near a band

"2 standard deviations below VWAP" is a band around VWAP, not the size of a move, the sigma points at a reference series. "a 2 standard deviation down move" is the size of the return. Both work; naming the reference series is what tells them apart.

Candle geometry#

Named candlestick patterns already work: hammer, doji, engulfing, morning star, marubozu, shooting star and around sixty more. Name one and you get it. These phrasings are for when you'd rather describe the shape than name the pattern.

Say thisWhat the engine checks
a long lower wick, a long tailthe lower shadow is at least twice the body
the upper wick is at least 60% of the rangethat shadow against the whole bar
the lower wick is more than twice the bodythe multiple you state
the body is more than 70% of the rangehow much of the bar the body fills
a wide-bodied candlethe same, at 70%
the body is the largest of the last 10 barsagainst the ten bars before this one
an inside bar, an outside bar, an outside reversalthis bar's range against the previous bar's
gaps up more than 2%, opens 1% above the previous closethe open against the previous close
Describing a shape is not the same as naming a pattern

"A long lower wick" and "a hammer" select different bars. A hammer additionally requires a prior downtrend and a small upper wick, so naming the pattern narrows the strategy. Say whichever one you actually mean, both work.

Outside bar vs engulfing

An outside bar takes out both extremes of the previous bar, it compares full ranges. A bullish engulfing compares bodies. Different conditions, both supported; say the one you want.

Gaps need a market that closes

A gap is the open against the previous close, so it only exists where trading stops overnight, stocks. On 24/7 crypto the tape is continuous and every bar opens where the last one closed, so there is nothing to measure. Ask for a gap on a crypto pair and the phrase is read the way a crypto trader means it: the bar closed that far above the previous close.

Volatility, persistence and shape#

Say thisWhat the engine checks
ATR is above 3% of price, ATR% below 1.5ATR divided by price, as a percentage
RSI has been above 50 for the last 3 daysevery bar in those three days
price stayed above the 200 EMA for two weeksthe same, in weeks
three consecutive narrowing bars, a coileach bar's range against the one before it
the range has expanded two bars in a rowthe mirror
the 50 and 200 EMA are converging, pulling apartthe gap against its own value a few bars ago
Write the % on an ATR filter

"ATR above 3" and "ATR above 3% of price" are different conditions. ATR is quoted in the asset's own currency, so a bare number is a price: on a $60,000 asset, "ATR above 3" is three dollars: true on every bar. It also drifts as price moves, so a threshold tuned at one price stops working at another. Say the percentage and the filter travels.

Durations in days and weeks

A persistence filter can be written in calendar time: "for the last 3 days", "for two weeks", and the timeframe is accounted for: three days is eighteen bars on a 4h chart and three on a daily one. You don't need to do the conversion.

Converging is not the same as close together

Two averages can be far apart and closing fast, or nearly touching and drifting apart opposite trades. "Converging" asks whether the gap is shrinking; ask for the spread if you want how far apart they are right now.

Everyday conditions#

Say thisWhat the engine checks
the third touch of the 200 EMA, the second retest of VWAPthe level falls inside the bar, counted
only when the daily candle is greenthe last completed daily close against its open
while the 4h candle is redthe same, other side
price is within 1 ATR of the 50 EMAthe gap measured in ATR, not percent
stop 1 ATR below entry, take profit at 3 ATRa stop sized to the asset's own volatility
Say ATR and you get ATR

"Stop 1 ATR below entry" and "1% stop" are very different orders. Write the word ATR and the stop is sized to volatility; write % and it is a fixed percentage. You can mix them in one strategy, "3 ATR target and a 2% stop" keeps each one as written.

Ordinals count

"The third touch" is not the same request as "a touch", it fires on different bars and far less often. A touch means the level fell inside the bar's range, so a bar that merely closed nearby does not count.

Higher-timeframe candles use the last completed bar

"Only when the daily candle is green" on a 1h chart reads the last finished daily candle. The day still forming is not used, because its colour is not knowable at the time the trade would be taken.

The rest of the family list#

These work the same way and are documented alongside the operators:

Say thisWhat it means
price is within 2% of the 200 EMAproximity to a level
the bar's range is twice the average rangerange expansion
the z-score is below −2standardised distance from the mean
the 50 EMA is more than 5% above the 200 EMApercent spread between two indicators
RSI rose 20 points over the last 5 barschange of a series over a window
RSI is 2 standard deviations below its 20-bar meana statistical band on any series
volatility is in its bottom quartilepercentile rank of a series vs its history

If a phrase doesn't work#

Two things help more than rewording blindly:

  1. Check the parse. The terminal shows the parsed conditions before you run, if a clause is missing or reads differently from what you meant, that's the signal.
  2. Use the wording above verbatim, then change the numbers. The examples are the exact phrasings the parser is trained and tested on.

See also operators & conditions for the comparison vocabulary, and query syntax for the anatomy of a full strategy sentence.