Docs / Rule language
Rule language
Function reference
Every price, function and pattern the rule language accepts on Ora (81 entries), each with its signature, what it means, an example rule and that rule's real belief on SPY, NVDA, TSLA, XLE for the session of 2026-10-30.
Belief colours: 0.6 and up between 0.4 and under. Try it opens the example on SPY in the Playground.
Prices
O H L C VOpen, high, low, close and volume of the bar being evaluated: the latest completed daily session. Prices are split- and dividend-adjusted.
C > OA green day. Every rule is about the latest bar unless you look back with an offset.C[-n] H[-n] L[-n] O[-n] V[-n]The same value n bars back. C[-1] is yesterday's close, H[-2] the high two sessions ago. Offsets work on the five price letters only; for anything else use ref().
C > C[-5]Higher than a week (five sessions) ago. A positive offset such as C[1] looks forward: there is no next bar, so it reads as "not known" (0.50).hl2()The middle of the bar: (H + L) / 2.
C > hl2()Closed in the upper half of the day's range.hlc3()The typical price: (H + L + C) / 3.
hlc3() > sma(hlc3(), 20)Typical price above its own 20-day average.ohlc4()The average of the four prices: (O + H + L + C) / 4.
ohlc4() > sma(C, 10)The day's average price is above the 10-day average close.tr()True range: the bar's high minus low, extended to include a gap from the previous close.
tr() > 1.5 * ref(atr(14), -1)Today's true range is half again yesterday's ATR: a wide day.Windows
sma(x, n)Simple moving average of the last n bars, including the current one.
C > sma(C, 50)Above the 50-day average.avg(x, n)Another name for sma(). Same result.
V > avg(V, 20)Volume above its 20-day average.mean(x, n)A third name for sma().
C > mean(C, 100)Above the 100-day average.sum(x, n)Rolling sum of the last n bars. Summing a comparison counts the bars where it held.
sum(C > C[-1], 10) >= 6Up on at least six of the last ten sessions.min(x, n)Lowest value of the last n bars, INCLUDING the current one.
C < 1.02 * min(L, 20)Closed within 2% of the 20-day low. (L <= min(L, 20) would be a poor rule: min includes today, so the two sides are at best equal, and a tie answers 0.50.)max(x, n)Highest value of the last n bars, INCLUDING the current one. So C > max(C, n) can never be true.
C >= 0.98 * max(H, 20)Closed within 2% of the 20-day high.highest(x, n)Highest value of the n bars BEFORE the current one. This is the breakout form.
C > highest(C, 20)Closed above every close of the previous 20 sessions.lowest(x, n)Lowest value of the n bars before the current one.
C < lowest(C, 20)Closed below every close of the previous 20 sessions.std(x, n)Standard deviation over the window (population form, like most charting tools).
std(C, 10) < 0.5 * std(C, 50)Recent swings are less than half their longer-run size: compression.zscore(x, n)How many standard deviations the current value sits from its window mean. A flat window scores 0.
zscore(C, 20) < -2More than two deviations under the 20-day mean.median(x, n)Middle value of the window. Less pulled by one wild day than an average.
V > 2 * median(V, 20)Volume more than twice its typical (median) day.percentrank(x, n)Where the current value ranks among the n − 1 bars before it, 0 to 100.
percentrank(V, 50) > 90Volume in the top tenth of the last 50 sessions.wma(x, n)Linearly weighted moving average: recent bars count more.
wma(C, 10) > wma(C, 30)Fast weighted average above the slow one.ema(x, n)Exponential moving average, smoothing 2 / (n + 1).
C > ema(C, 21)Above the 21-day EMA.rma(x, n)Wilder's smoothing, 1 / n: what RSI and ATR are built from.
C > rma(C, 14)Above a Wilder-smoothed 14-day average.linreg(x, n)The least-squares line through the window, read at the current bar: a smoothed level, not the slope.
linreg(C, 20) > ref(linreg(C, 20), -5)The 20-day regression level is higher than a week ago: rising.roc(x, n)Percent change over n bars: roc(C, 20) = 5 means up 5% in 20 sessions.
roc(C, 20) > 5Up more than 5% over the last 20 sessions.cum(x)Running total from the first bar loaded.
cum(C > C[-1]) > cum(C < C[-1])More up days than down days across all the history loaded (about 1,500 sessions).highestbars(x, n)How many bars ago the window's high was set, 0 to n − 1 (0 = this bar). The window includes the current bar.
highestbars(H, 20) <= 3The 20-day high was set in the last four sessions.lowestbars(x, n)How many bars ago the window's low was set (0 = this bar).
lowestbars(L, 20) >= 15The 20-day low is at least 15 sessions old.Indicators
rsi(x, n)Relative strength index, 0 to 100 (Wilder). rsi(C, 14) is the usual one.
rsi(C, 14) > 50Momentum on the up side.atr(n)Average true range over n bars, in price.
H - L > 2 * atr(14)Today's range is more than twice the average.atr_pct(n)ATR as a percent of the close: 3 means 3%. Comparable across symbols.
atr_pct(14) > 3A typical day moves more than 3%.macd(x [, fast, slow, signal])MACD line: ema(fast) − ema(slow). Defaults 12, 26, 9.
macd(C) > 0The 12-day EMA is above the 26-day.macdsignal(x [, fast, slow, signal])The MACD signal line: an EMA of the MACD line.
macd(C) > macdsignal(C)MACD above its signal line.macdhist(x [, fast, slow, signal])MACD histogram: line minus signal.
macdhist(C) > ref(macdhist(C), -1)The histogram is rising.bbupper(x, n [, up, dn])Upper Bollinger band: sma + up × std. Default 2.
C > bbupper(C, 20, 2)A close above the upper band.bbmid(x, n)Middle band: the simple average.
C > bbmid(C, 20)Above the middle band (the 20-day average).bblower(x, n [, up, dn])Lower Bollinger band: sma − dn × std (dn defaults to up).
C < bblower(C, 20, 2)A close under the lower band.adx(n)Trend strength, 0 to 100, with no direction. Above 25 is usually called trending.
adx(14) > 25A trending market, up or down.diplus(n)+DI: the upward directional movement ADX is built from.
diplus(14) > diminus(14)Up moves have been stronger than down moves.diminus(n)−DI: the downward directional movement.
diminus(14) > 25Strong downward movement.stochk(n [, d, slow])Stochastic %K, 0 to 100: where the close sits in the n-bar range, smoothed over slow (default 3).
stochk(14) < 20Near the bottom of its 14-day range.stochd(n [, d, slow])Stochastic %D: the d-bar average of %K (default 3).
stochk(14) > stochd(14)%K above %D.cci(n)Commodity channel index: typical price against its average, in units of mean deviation.
cci(20) > 100Strong upward deviation.willr(n)Williams %R, −100 to 0: 0 is the top of the n-bar range.
willr(14) > -20In the top fifth of the 14-day range.obv()On-balance volume: adds the day's volume on an up close, subtracts it on a down close.
obv() > sma(obv(), 20)Volume flow above its 20-day average.Signals
crossup(a, b)1 on the bar where a crosses above b (it was at or below b on the bar before), 0 otherwise. As a whole rule it answers 0.95 or 0.05.
crossup(C, sma(C, 50))Crossed above the 50-day today.crossdown(a, b)1 on the bar where a crosses below b.
crossdown(sma(C, 20), sma(C, 50))The 20-day crossed under the 50-day today.barssince(cond)Bars since a condition was last true (0 = true on this bar). Not known until it has been true once.
barssince(C > highest(C, 20)) > 30More than 30 sessions since the last 20-day closing breakout.Maths
abs(x)Absolute value.
abs(C / C[-1] - 1) > 0.02Moved more than 2% either way today.sqrt(x)Square root (negative input is not a number).
std(log(C / C[-1]), 20) * sqrt(252) > 0.4Annualized 20-day volatility above 40%.log(x)Natural logarithm (zero or negative input is not a number).
log(C / C[-20]) > 0.05A 20-session log return above 5%.sign(x)−1, 0 or 1.
sum(sign(C - C[-1]), 10) > 2More up days than down days over ten sessions, by at least three.iif(cond, a, b)a where the condition holds, b otherwise. Use it to switch a threshold by regime.
rsi(C, 14) < iif(C > sma(C, 200), 40, 30)Oversold, with a looser line (40) in an uptrend and a stricter one (30) below the 200-day.ref(x, -n)Any series n bars back: the offset for things that are not a price letter.
sma(C, 50) > ref(sma(C, 50), -10)The 50-day average is higher than ten sessions ago: rising.between(x, a, b)1 when x is inside [a, b] (inclusive, either order), else 0.
between(rsi(C, 14), 40, 60)RSI in the neutral band. As a whole rule it answers 0.95 or 0.05.least(a, b)The smaller of two series, bar by bar.
least(O, C) - L > 2 * abs(C - O)A long lower wick: twice the body.greatest(a, b)The larger of two series, bar by bar.
H - greatest(O, C) > 2 * abs(C - O)A long upper wick: twice the body.Recursion
rec(seed, step)A series built from its own previous value: inside step, self is the previous bar's result (seed before the first bar). Only arithmetic, comparisons and abs/sqrt/log/sign/iif/least/greatest/between may touch self.
C > rec(C, self + 0.1 * (C - self))Above a home-made exponential average (smoothing 0.1).Patterns
doji()Body at most 10% of the day's range.
Expands to
(H > L) and (abs(C - O) <= 0.1 * (H - L))
dragonfly_doji()Doji with a long lower wick (60%+ of the range) and almost no upper wick.
Expands to
((H > L) and (abs(C - O) <= 0.1 * (H - L))) and ((H - greatest(O, C)) <= 0.1 * (H - L)) and ((least(O, C) - L) >= 0.6 * (H - L))
gravestone_doji()Doji with a long upper wick and almost no lower wick.
Expands to
((H > L) and (abs(C - O) <= 0.1 * (H - L))) and ((least(O, C) - L) <= 0.1 * (H - L)) and ((H - greatest(O, C)) >= 0.6 * (H - L))
spinning_top()Small body (10–30% of range) with wicks of at least a quarter of the range on both sides.
Expands to
(H > L) and (abs(C - O) <= 0.3 * (H - L)) and (abs(C - O) > 0.1 * (H - L)) and ((H - greatest(O, C)) >= 0.25 * (H - L)) and ((least(O, C) - L) >= 0.25 * (H - L))
marubozu()Body at least 90% of the range: almost no wicks.
Expands to
(H > L) and (abs(C - O) >= 0.9 * (H - L))
hammer()Lower wick at least twice the body, upper wick at most 10% of the range, closing below the close five bars back.
Expands to
((H > L) and (abs(C - O) > 0) and ((least(O, C) - L) >= 2 * abs(C - O)) and ((H - greatest(O, C)) <= 0.1 * (H - L))) and (C < C[-5])
hanging_man()Hammer shape, closing above the close five bars back.
Expands to
((H > L) and (abs(C - O) > 0) and ((least(O, C) - L) >= 2 * abs(C - O)) and ((H - greatest(O, C)) <= 0.1 * (H - L))) and (C > C[-5])
shooting_star()Upper wick at least twice the body, lower wick at most 10% of the range, after a five-bar rise.
Expands to
((H > L) and (abs(C - O) > 0) and ((H - greatest(O, C)) >= 2 * abs(C - O)) and ((least(O, C) - L) <= 0.1 * (H - L))) and (C > C[-5])
inverted_hammer()Shooting-star shape after a five-bar decline.
Expands to
((H > L) and (abs(C - O) > 0) and ((H - greatest(O, C)) >= 2 * abs(C - O)) and ((least(O, C) - L) <= 0.1 * (H - L))) and (C < C[-5])
engulfing_bull()A green body that engulfs yesterday's red body.
Expands to
(C[-1] < O[-1]) and (C > O) and (O <= C[-1]) and (C >= O[-1]) and (abs(C - O) > abs(C[-1] - O[-1]))
engulfing_bear()A red body that engulfs yesterday's green body.
Expands to
(C[-1] > O[-1]) and (C < O) and (O >= C[-1]) and (C <= O[-1]) and (abs(C - O) > abs(C[-1] - O[-1]))
harami_bull()A small green body inside yesterday's red body.
Expands to
(C[-1] < O[-1]) and (C > O) and (abs(C - O) < abs(C[-1] - O[-1])) and (O >= C[-1]) and (C <= O[-1])
harami_bear()A small red body inside yesterday's green body.
Expands to
(C[-1] > O[-1]) and (C < O) and (abs(C - O) < abs(C[-1] - O[-1])) and (O <= C[-1]) and (C >= O[-1])
piercing_line()After a red day, opens below its close and closes above the middle of its body (but under its open).
Expands to
(C[-1] < O[-1]) and (C > O) and (O < C[-1]) and (C > (O[-1] + C[-1]) / 2) and (C < O[-1])
dark_cloud()After a green day, opens above its close and closes below the middle of its body (but above its open).
Expands to
(C[-1] > O[-1]) and (C < O) and (O > C[-1]) and (C < (O[-1] + C[-1]) / 2) and (C > O[-1])
morning_star()A red bar, a small bar (half its body or less) that stays under its close, then a green bar closing above the middle of the first.
Expands to
(C[-2] < O[-2]) and (abs(C[-1] - O[-1]) <= 0.5 * abs(C[-2] - O[-2])) and (greatest(O[-1], C[-1]) <= C[-2]) and (C > O) and (C > (O[-2] + C[-2]) / 2)
evening_star()A green bar, a small bar that stays above its close, then a red bar closing below the middle of the first.
Expands to
(C[-2] > O[-2]) and (abs(C[-1] - O[-1]) <= 0.5 * abs(C[-2] - O[-2])) and (least(O[-1], C[-1]) >= C[-2]) and (C < O) and (C < (O[-2] + C[-2]) / 2)
three_white_soldiers()Three green bars, each closing higher and opening inside the previous body.
Expands to
(C > O) and (C[-1] > O[-1]) and (C[-2] > O[-2]) and (C > C[-1]) and (C[-1] > C[-2]) and (O >= O[-1]) and (O <= C[-1]) and (O[-1] >= O[-2]) and (O[-1] <= C[-2])
three_black_crows()Three red bars, each closing lower and opening inside the previous body.
Expands to
(C < O) and (C[-1] < O[-1]) and (C[-2] < O[-2]) and (C < C[-1]) and (C[-1] < C[-2]) and (O <= O[-1]) and (O >= C[-1]) and (O[-1] <= O[-2]) and (O[-1] >= C[-2])
tweezer_bottom()Red then green, with lows within 0.1% of each other.
Expands to
(C[-1] < O[-1]) and (C > O) and (abs(L - L[-1]) <= 0.001 * C[-1])
tweezer_top()Green then red, with highs within 0.1%.
Expands to
(C[-1] > O[-1]) and (C < O) and (abs(H - H[-1]) <= 0.001 * C[-1])
inside_bar()Today's high and low are inside yesterday's (equal counts).
Expands to
(H <= H[-1]) and (L >= L[-1])
outside_bar()Today's high above yesterday's and low below it.
Expands to
(H > H[-1]) and (L < L[-1])
gap_up()Today's whole range is above yesterday's high: an unfilled gap up.
Expands to
L > H[-1]
gap_down()Today's whole range is below yesterday's low.
Expands to
H < L[-1]
Not available on Ora: intraday
The grammar knows these names, but Ora runs rules on daily bars, so they return a 422 (see Error messages).
| Name | Meaning |
|---|---|
vwap() | Volume-weighted average price |
opening_range_high([m]) opening_range_low([m]) | High / low of the first m minutes |
minutes_since_open() time_of_day() | Clock time inside the session |
rvol(n) | Relative volume against the previous n bars |
gap() | Percent gap from the previous close |
C@5m, sma(C@1h, 20) … | Another timeframe after @ |
Information, not investment advice. Beliefs and probabilities on this page are real responses for the session shown and change with every session.