Docs / Rule language
Rule language
Bring your own bars
Rules, value questions and formulas normally run on a symbol's daily history from Ora's market data. Send state.bars instead and they run on your bars: a private instrument, a backtest slice, a custom index, intraday data, anything with a close.
state.bars: an array of{"date", "open", "high", "low", "close", "volume"}(alsoo h l c v), oldest first, or{"columns": [...], "rows": [[...], ...]}.- Only
closeis required: open, high and low default to it, volume to 0. Up to 5,000 bars a request. - Dates are optional for daily bars (calendar functions and reading another symbol need them) and must strictly increase.
- Intraday bars: add
"interval": "5m"(1m, 5m, 15m, 30m, 1h) and a date with a time on every bar, such as"2026-10-30T09:35:00". Thenvwap(),opening_range_high(),minutes_since_open()andtime_of_day()work. - No symbol is needed. Earnings, dividend and split facts are not available on your bars; another symbol is:
beta(60, 'SPY')lines SPY's daily bars up with yours by date.
Daily bars, no symbol
Request (state.bars shortened here: the request sent 60 bars (2 oldest and the newest shown).)
{
"model": "ora-fin-0.1.1",
"state": {
"bars": [
{
"date": "2026-08-07",
"open": 311.18,
"high": 314.54,
"low": 310.47,
"close": 313.06,
"volume": 34437191
},
{
"date": "2026-08-10",
"open": 306.83,
"high": 308.26,
"low": 304.63,
"close": 308.26,
"volume": 43391681
},
{
"date": "2026-10-30",
"open": 346.72,
"high": 349.19,
"low": 334.35,
"close": 344.63,
"volume": 67362573
}
]
},
"questions": {
"above20": {
"type": "yes_no",
"ask": "C > sma(C, 20)"
},
"rsi": {
"type": "value",
"ask": "rsi(C, 14)"
},
"stretch": {
"type": "value",
"ask": "zscore(C, 20)"
},
"monday": {
"type": "value",
"ask": "dayofweek()"
},
"beta": {
"type": "value",
"ask": "beta(40, 'SPY')"
}
}
}Response (HTTP 200, session 2026-10-30)
{
"model": "ora-fin-0.1.1",
"answers": {
"above20": {
"type": "yes_no",
"yes_no": 0.7481,
"rule": "C > sma(C, 20)",
"basis": "rule"
},
"rsi": {
"type": "value",
"value": 55.348664518,
"rule": "rsi(C, 14)",
"as_of": "2026-10-30"
},
"stretch": {
"type": "value",
"value": 0.5785420081,
"rule": "zscore(C, 20)",
"as_of": "2026-10-30"
},
"monday": {
"type": "value",
"value": 5,
"rule": "dayofweek()",
"as_of": "2026-10-30"
},
"beta": {
"type": "value",
"value": 0.2569830887,
"rule": "beta(40, 'SPY')",
"as_of": "2026-10-30"
}
},
"usage": {
"input_tokens": 3681,
"output_tokens": 20
},
"version": "ora-text-0.2.0"
}
Columns and rows
The compact form: one array of column names and one array per bar.
Request (rows shortened here: the request sent 30 rows.)
{
"model": "ora-fin-0.1.1",
"state": {
"bars": {
"columns": [
"date",
"close"
],
"rows": [
[
"2026-09-21",
338.98
],
[
"2026-09-22",
339.75
],
[
"2026-10-30",
344.63
]
]
}
},
"questions": {
"ema10": {
"type": "value",
"ask": "ema(C, 10)"
},
"up5": {
"type": "yes_no",
"ask": "C > C[-5]"
}
}
}Response (HTTP 200, session 2026-10-30)
{
"model": "ora-fin-0.1.1",
"answers": {
"ema10": {
"type": "value",
"value": 344.8874451231,
"rule": "ema(C, 10)",
"as_of": "2026-10-30"
},
"up5": {
"type": "yes_no",
"yes_no": 0.2268,
"rule": "C > C[-5]",
"basis": "rule"
}
},
"usage": {
"input_tokens": 780,
"output_tokens": 8
},
"version": "ora-text-0.2.0"
}
Intraday bars
Session functions reset on each new date in the timestamps; the clock is the timestamps' own time zone.
Request (state.bars shortened here: the request sent 78 bars (2 oldest and the newest shown).)
{
"model": "ora-fin-0.1.1",
"state": {
"bars": [
{
"date": "2026-10-30T09:30:00",
"open": 250,
"high": 250.2,
"low": 249.85,
"close": 250.05,
"volume": 20000
},
{
"date": "2026-10-30T09:35:00",
"open": 250.05,
"high": 250.35,
"low": 249.9,
"close": 250.2,
"volume": 20300
},
{
"date": "2026-10-30T15:55:00",
"open": 253.83,
"high": 254.19,
"low": 253.68,
"close": 254.04,
"volume": 20000
}
],
"interval": "5m"
},
"questions": {
"above_vwap": {
"type": "yes_no",
"ask": "C > vwap()"
},
"vwap": {
"type": "value",
"ask": "vwap()"
},
"orh": {
"type": "value",
"ask": "opening_range_high(30)"
},
"broke_orh": {
"type": "yes_no",
"ask": "C > opening_range_high(30) and minutes_since_open() >= 30"
},
"clock": {
"type": "value",
"ask": "time_of_day()"
}
}
}Response (HTTP 200, session 2026-10-30)
{
"model": "ora-fin-0.1.1",
"answers": {
"above_vwap": {
"type": "yes_no",
"yes_no": 0.2421,
"rule": "C > vwap()",
"basis": "rule"
},
"vwap": {
"type": "value",
"value": 255.4062546288,
"rule": "vwap()",
"as_of": "2026-10-30"
},
"orh": {
"type": "value",
"value": 251.85,
"rule": "opening_range_high(30)",
"as_of": "2026-10-30"
},
"broke_orh": {
"type": "yes_no",
"yes_no": 0.8345,
"rule": "C > opening_range_high(30) and minutes_since_open() >= 30",
"basis": "rule"
},
"clock": {
"type": "value",
"value": 1555,
"rule": "time_of_day()",
"as_of": "2026-10-30"
}
},
"usage": {
"input_tokens": 5089,
"output_tokens": 20
},
"version": "ora-text-0.2.0"
}
Validation
Bars are checked before anything runs; a problem is a 422 on state.bars naming the bar.
Request
{
"model": "ora-fin-0.1.1",
"state": {
"bars": [
{
"date": "2026-10-29",
"close": 101.2
},
{
"date": "2026-10-28",
"close": 100.4
}
]
},
"questions": {
"v": {
"type": "value",
"ask": "C"
}
}
}Response (HTTP 422)
{
"detail": [
{
"loc": [
"body",
"state",
"bars"
],
"type": "value_error",
"msg": "bars[1]: dates must be strictly increasing (oldest first, no duplicates)"
}
]
}
The bars are taken out of the state before the model reads it (the rules have already used them). Like everything else in a request, they count toward its input tokens.
Information, not investment advice. Beliefs and probabilities on this page are real responses for the session shown and change with every session.