Docs / Questions & answers
Many symbols in one request
Send state.positions instead of state.symbol. Every question is answered once per position, and each position's other fields can be read by name in its rules.
{
"model": "ora-fin",
"state": {
"positions": [
{
"symbol": "AAPL",
"shares": 100,
"entry": 200
},
{
"symbol": "msft",
"shares": 50,
"entry": 300
},
{
"symbol": "NVDA",
"shares": 10,
"entry": 100
}
]
},
"questions": {
"pnl": "=(C - entry) * shares",
"above_entry": {
"type": "bool",
"ask": "=C > entry"
}
},
"aggregate": [
"pnl"
]
}
A real response (other fields left out):
{
"answers_by_symbol": {
"AAPL": {
"pnl": {
"type": "value",
"value": 13832,
"rule": "(C - entry) * shares",
"as_of": "2026-11-02",
"facts": {
"entry": 200,
"shares": 100
}
},
"above_entry": {
"type": "bool",
"bool": true,
"rule": "C > entry",
"basis": "rule",
"as_of": "2026-11-02",
"facts": {
"entry": 200
}
}
},
"MSFT": {
"pnl": {
"type": "value",
"value": 10356,
"rule": "(C - entry) * shares",
"as_of": "2026-11-02",
"facts": {
"entry": 300,
"shares": 50
}
},
"above_entry": {
"type": "bool",
"bool": true,
"rule": "C > entry",
"basis": "rule",
"as_of": "2026-11-02",
"facts": {
"entry": 300
}
}
},
"NVDA": {
"pnl": {
"type": "value",
"value": 1020.6,
"rule": "(C - entry) * shares",
"as_of": "2026-11-02",
"facts": {
"entry": 100,
"shares": 10
}
},
"above_entry": {
"type": "bool",
"bool": true,
"rule": "C > entry",
"basis": "rule",
"as_of": "2026-11-02",
"facts": {
"entry": 100
}
}
}
},
"aggregate": {
"pnl": {
"sum": 25208.6,
"count": 3,
"missing": []
}
},
"usage": {
"input_tokens": 4300,
"output_tokens": 54,
"data_tokens": 3000
}
}
How it works
- Fields. Other fields in
stateare shared by all positions. A position's own field wins over a shared one. - One bad symbol. It goes in
errors_by_symboland the others still answer. When none can answer, the request is a422naming each one. - Other results.
context_by_symbolgives each session. Anoutputtemplate fills in once per position, underoutput_by_symbol. Actions run once per position, underactions_by_symbol. - Totals.
"aggregate": ["pnl"]adds up a number question.missingnames the positions with no number, which are not counted as 0.
{
"errors_by_symbol": {
"ZZZNOPE": {
"status": 422,
"detail": [
{
"loc": [
"body",
"state",
"symbol"
],
"type": "value_error",
"msg": "No daily prices for `ZZZNOPE`. Use a symbol as Ora lists it (AAPL, BRK-B, 7203.T, BTCUSD, EURUSD), or send `state.context` or `state.bars` yourself."
}
]
}
},
"aggregate": {
"v": {
"sum": 2366.8,
"count": 2,
"missing": [
"ZZZNOPE",
"$P123",
"$S77"
]
}
}
}
Limits and cost
At most 50 positions in one request, and positions times questions at most 500. Answers are keyed by symbol, so a symbol can be listed once. A position can't carry its own bars or context.
Each position is metered and rate limited as its own call, with its own market data tokens, and is listed as its own line in your usage. It costs what the same calls would cost one at a time. usage adds them up.
{
"detail": [
{
"loc": [
"body",
"state",
"positions"
],
"msg": "At most 50 positions per request, got 51. Split it into several requests.",
"type": "too_long"
}
]
}
It needs at least one rule in the request, and a state with no symbol, bars or context. Otherwise positions is an ordinary field, as it always was.