Use cases · Builders
Algo / bot developer: 20 ways to use Ora
Bots that read a signal, check risk and post an order, a message or nothing. Each example is a complete, runnable request with the real answers it returned (38 requests, captured 2026-10-31), what they mean and, where it fits, the action it would send.
ora-fin-0.1.1. Another model changes the request JSON and the Playground link; run it there to see its answers.Rule functions and facts used by this player (50)
sma 8offset 5atr 4rsi 3highest 3lowest 3roc 3avg 2crossup 2stochk 2abs 2max 2ref 2adx 2min 2std 2zscore 2crossdown 1willr 1swinglow 1engulfing_bull 1morning_star 1bblower 1bbmid 1bbupper 1linreg 1ema 1macd 1macdsignal 1stochd 1days_to_ex_div 1div_yield_ttm 1days_to_earnings 1last_earnings_gap 1last_earnings_move 1cci 1diminus 1diplus 1log 1sqrt 1obv 1doji 1percentrank 1cum 1mean 1sign 1sum 1outside_bar 1tweezer_bottom 1tweezer_top 1
Examples 1–10 of 20 · page 1 of 2
Algo / bot developer · example 1
An RSI(2) mean-reversion bot on SPY: signal, risk check, order
A daily bot buys short-term oversold dips in an uptrend and posts the order to the broker API only when the risk checks pass.
- ScheduleMon–Fri at 16:15 ET
- StateSPY
- Questions4 asked
- Answersreal, captured
- Actions2 rules · dry run
State
{"symbol":"SPY"} The server fills in the latest completed session.
Questions
rsi2 | rule | rsi(C, 2) < 10Two-day RSI under 10 |
trend | English → rule | Is the stock above its 200-day moving average? |
liquid | rule | avg(C * V, 20) > 100000000Trades more than $100 million a day |
drop5 | forecast | Will it drop at least 5% at some point in the next month? A 5% drawdown within a month |
Answers
| Question | Answer | Reading |
|---|---|---|
rsi2Two-day RSI under 10 | 0.5164 | on the line (true) |
trendIs the stock above its 200-day moving average compiled to C > sma(C, 200) | 0.9451 | true |
liquidTrades more than $100 million a day | 0.9463 | true |
drop5A 5% drawdown within a month | 0.203 | 20% · unlikely |
Actions
Rules on the answers decide what to send.
rsi2 >= 0.6 and trend >= 0.6 and drop5 < 0.5→Webhookbroker-apielse→Slackbot-log{
"text": "SPY (2026-10-30): no RSI(2) entry. Oversold 52%, uptrend 95%, 5% drawdown odds 20%."
}What it means
For SPY on the session of 2026-10-30: True now: Is the stock above its 200-day moving average; Trades more than $100 million a day. On the line: Two-day RSI under 10. Forecasts: A 5% drawdown within a month 20%. Fired: log (Slack → bot-log).
Either an order goes to the broker or a log line goes to Slack, so every session leaves a trace of what the bot decided and why.
As a scheduled workflow (Mon–Fri at 16:15 ET)
Create it under Workflows in the console: it runs these questions for every symbol on the schedule and fires the actions per symbol. The answers above are what one run returned.
{
"name": "An RSI(2) mean-reversion bot on SPY: signal, risk check, order",
"symbols": "SPY",
"days": [
1,
2,
3,
4,
5
],
"at_time": "16:15",
"model": "ora-fin-0.1.1",
"questions": {
"rsi2": {
"type": "yes_no",
"ask": "rsi(C, 2) < 10"
},
"trend": {
"type": "yes_no",
"instructions": "Is the stock above its 200-day moving average?"
},
"liquid": {
"type": "yes_no",
"ask": "avg(C * V, 20) > 100000000"
},
"drop5": {
"type": "yes_no",
"instructions": "Will it drop at least 5% at some point in the next month?"
}
},
"actions": [
{
"id": "buy",
"when": "rsi2 >= 0.6 and trend >= 0.6 and drop5 < 0.5",
"do": "webhook",
"connection": "broker-api",
"body": {
"symbol": "{{symbol}}",
"side": "buy",
"order_type": "market_on_open",
"strategy": "rsi2_dip",
"p_rsi2": "{{rsi2}}",
"p_trend": "{{trend}}",
"p_drop5": "{{drop5}}",
"as_of": "{{as_of}}"
}
},
{
"id": "log",
"when": "else",
"do": "slack",
"connection": "bot-log",
"message": "{{symbol}} ({{as_of}}): no RSI(2) entry. Oversold {{rsi2|pct}}, uptrend {{trend|pct}}, 5% drawdown odds {{drop5|pct}}."
}
]
}Request JSON
{
"model": "ora-fin-0.1.1",
"state": {
"symbol": "SPY"
},
"questions": {
"rsi2": {
"type": "yes_no",
"ask": "rsi(C, 2) < 10"
},
"trend": {
"type": "yes_no",
"instructions": "Is the stock above its 200-day moving average?"
},
"liquid": {
"type": "yes_no",
"ask": "avg(C * V, 20) > 100000000"
},
"drop5": {
"type": "yes_no",
"instructions": "Will it drop at least 5% at some point in the next month?"
}
},
"actions": [
{
"id": "buy",
"when": "rsi2 >= 0.6 and trend >= 0.6 and drop5 < 0.5",
"do": "webhook",
"connection": "broker-api",
"body": {
"symbol": "{{symbol}}",
"side": "buy",
"order_type": "market_on_open",
"strategy": "rsi2_dip",
"p_rsi2": "{{rsi2}}",
"p_trend": "{{trend}}",
"p_drop5": "{{drop5}}",
"as_of": "{{as_of}}"
}
},
{
"id": "log",
"when": "else",
"do": "slack",
"connection": "bot-log",
"message": "{{symbol}} ({{as_of}}): no RSI(2) entry. Oversold {{rsi2|pct}}, uptrend {{trend|pct}}, 5% drawdown odds {{drop5|pct}}."
}
],
"dry_run": true
}Response JSON (SPY, real)
{
"model": "ora-fin-0.1.1",
"answers": {
"rsi2": {
"yes_no": 0.5164,
"rule": "rsi(C, 2) < 10",
"basis": "rule"
},
"trend": {
"yes_no": 0.9451,
"rule": "C > sma(C, 200)",
"basis": "comparison"
},
"liquid": {
"yes_no": 0.9463,
"rule": "avg(C * V, 20) > 100000000",
"basis": "rule"
},
"drop5": {
"yes_no": 0.203
}
},
"context": {
"symbol": "SPY",
"as_of": "2026-10-30"
},
"actions": [
{
"id": "buy",
"fired": false,
"status": "skipped"
},
{
"id": "log",
"fired": true,
"status": "dry_run",
"do": "slack",
"connection": "bot-log",
"preview": {
"text": "SPY (2026-10-30): no RSI(2) entry. Oversold 52%, uptrend 95%, 5% drawdown odds 20%."
}
}
]
}Algo / bot developer · example 2
Golden-cross trend bot on QQQ with an exit branch
Enter when the 50-day crosses above the 200-day, exit when it crosses back below, do nothing otherwise.
- StateQQQ
- Questions4 asked
- Answersreal, captured
- Actions2 rules · dry run
State
{"symbol":"QQQ"} The server fills in the latest completed session.
Questions
cross_up | rule | crossup(sma(C, 50), sma(C, 200))50-day crossed above the 200-day today |
cross_dn | rule | crossdown(sma(C, 50), sma(C, 200))50-day crossed below the 200-day today |
setup | rule | sma(C, 50) > sma(C, 200)50-day above the 200-day |
up_week | forecast | Will the stock be higher in a week? Higher in a week |
Answers
| Question | Answer | Reading |
|---|---|---|
cross_up50-day crossed above the 200-day today | 0.05 | false |
cross_dn50-day crossed below the 200-day today | 0.05 | false |
setup50-day above the 200-day | 0.9463 | true |
up_weekHigher in a week | 0.561 | 56% · close to even |
Actions
Rules on the answers decide what to send.
cross_up >= 0.6→Webhookbroker-apicross_dn >= 0.6→Webhookbroker-apiWhat it means
For QQQ on the session of 2026-10-30: True now: 50-day above the 200-day. Not true: 50-day crossed above the 200-day today; 50-day crossed below the 200-day today. Forecasts: Higher in a week 56%. No action fired: every rule was false.
Crosses are rare one-day events, so on almost every run neither branch fires; the setup state says which side the bot should already be on.
Request JSON
{
"model": "ora-fin-0.1.1",
"state": {
"symbol": "QQQ"
},
"questions": {
"cross_up": {
"type": "yes_no",
"ask": "crossup(sma(C, 50), sma(C, 200))"
},
"cross_dn": {
"type": "yes_no",
"ask": "crossdown(sma(C, 50), sma(C, 200))"
},
"setup": {
"type": "yes_no",
"ask": "sma(C, 50) > sma(C, 200)"
},
"up_week": {
"type": "yes_no",
"instructions": "Will the stock be higher in a week?"
}
},
"actions": [
{
"id": "enter",
"when": "cross_up >= 0.6",
"do": "webhook",
"connection": "broker-api",
"body": {
"symbol": "{{symbol}}",
"side": "buy",
"strategy": "golden_cross",
"as_of": "{{as_of}}"
}
},
{
"id": "exit",
"when": "cross_dn >= 0.6",
"do": "webhook",
"connection": "broker-api",
"body": {
"symbol": "{{symbol}}",
"side": "sell",
"strategy": "golden_cross",
"as_of": "{{as_of}}"
}
}
],
"dry_run": true
}Response JSON (QQQ, real)
{
"model": "ora-fin-0.1.1",
"answers": {
"cross_up": {
"yes_no": 0.05,
"rule": "crossup(sma(C, 50), sma(C, 200))",
"basis": "rule"
},
"cross_dn": {
"yes_no": 0.05,
"rule": "crossdown(sma(C, 50), sma(C, 200))",
"basis": "rule"
},
"setup": {
"yes_no": 0.9463,
"rule": "sma(C, 50) > sma(C, 200)",
"basis": "rule"
},
"up_week": {
"yes_no": 0.561
}
},
"context": {
"symbol": "QQQ",
"as_of": "2026-10-30"
},
"actions": [
{
"id": "enter",
"fired": false,
"status": "skipped"
},
{
"id": "exit",
"fired": false,
"status": "skipped"
}
]
}Algo / bot developer · example 3
A Discord signal bot for oversold large caps
Post oversold-in-uptrend setups for a few large caps to a Discord channel through its incoming webhook.
- State4 symbols
- Questions4 asked
- Answersreal, captured
- Actions1 rule · dry run
State
{"symbol":"AAPL"} then MSFT, AMZN, NVDA, one request each. The server fills in the latest completed session.
Questions
setup | rule | C > sma(C, 200) and rsi(C, 14) < 40Pullback in an uptrend: above the 200-day, RSI under 40 |
stoch | rule | stochk(14) < 20Stochastic %K under 20 |
willr | rule | willr(14) < -80Williams %R below -80: near the bottom of the 14-day range |
up_week | forecast | Will the stock be higher in a week? Higher in a week |
Answers
| Symbol | setuprule | stochrule | willrrule | up_weekforecast | Fired |
|---|---|---|---|---|---|
AAPL | 0.0634 | 0.0683 | 0.0893 | 0.59 | none |
MSFT | 0.1064 | 0.2022 | 0.4842 | 0.574 | none |
AMZN | 0.3073 | 0.31 | 0.2923 | 0.493 | none |
NVDA | 0.5455 | 0.5475 | 0.6293 | 0.527 | none |
true false not known for rules; forecasts are odds. Hover a column for its question.
Actions
Rules on the answers decide what to send. Each symbol runs its own request, so each one can fire.
setup >= 0.6→Webhookdiscord-signalsWhat it means
Session of 2026-10-30, 4 symbols: Pullback in an uptrend: above the 200-day, RSI under 40: true for none of 4. Stochastic %K under 20: true for none of 4. Williams %R below -80: near the bottom of the 14-day range: true for NVDA of 4. Highest odds for “Higher in a week”: AAPL at 59%. discord fired for none.
Discord expects a JSON body with a content field; the bot posts only when the setup rule is true for a symbol.
Request JSON (AAPL; the others differ only in the symbol)
{
"model": "ora-fin-0.1.1",
"state": {
"symbol": "AAPL"
},
"questions": {
"setup": {
"type": "yes_no",
"ask": "C > sma(C, 200) and rsi(C, 14) < 40"
},
"stoch": {
"type": "yes_no",
"ask": "stochk(14) < 20"
},
"willr": {
"type": "yes_no",
"ask": "willr(14) < -80"
},
"up_week": {
"type": "yes_no",
"instructions": "Will the stock be higher in a week?"
}
},
"actions": [
{
"id": "discord",
"when": "setup >= 0.6",
"do": "webhook",
"connection": "discord-signals",
"body": {
"content": "{{symbol}} ({{as_of}}): pullback in an uptrend. Stochastic oversold {{stoch|pct}}, Williams %R oversold {{willr|pct}}, higher in a week {{up_week|pct}}. Not advice."
}
}
],
"dry_run": true
}Response JSON (AAPL, real)
{
"model": "ora-fin-0.1.1",
"answers": {
"setup": {
"yes_no": 0.0634,
"rule": "C > sma(C, 200) and rsi(C, 14) < 40",
"basis": "rule"
},
"stoch": {
"yes_no": 0.0683,
"rule": "stochk(14) < 20",
"basis": "rule"
},
"willr": {
"yes_no": 0.0893,
"rule": "willr(14) < -80",
"basis": "rule"
},
"up_week": {
"yes_no": 0.59
}
},
"context": {
"symbol": "AAPL",
"as_of": "2026-10-30"
},
"actions": [
{
"id": "discord",
"fired": false,
"status": "skipped"
}
]
}Algo / bot developer · example 4
Telegram breakout bot for semiconductors
Send a Telegram message when a chip stock breaks a 55-day high (a Donchian breakout) with volume.
- State5 symbols
- Questions4 asked
- Answersreal, captured
- Actions1 rule · dry run
State
{"symbol":"NVDA"} then AMD, MU, SMH, TSM, one request each. The server fills in the latest completed session.
Questions
donchian | rule | C > highest(C, 55)55-day closing breakout |
vol | rule | C > C[-1] and V > 1.5 * ref(avg(V, 20), -1)Up on heavy volume |
near | English → rule | Is the stock within 5% of its 52-week high? |
rally5 | forecast | Will it rally at least 5% at some point in the next month? A 5% rally within a month |
Answers
| Symbol | donchianrule | volrule | nearrule | rally5forecast | Fired |
|---|---|---|---|---|---|
NVDA | 0.0537 | 0.0732 | 0.0537 | 0.616 | none |
AMD | 0.0537 | 0.0537 | 0.0576 | 0.836 | none |
MU | 0.0685 | 0.0909 | 0.0537 | 0.855 | none |
SMH | 0.0567 | 0.0537 | 0.0537 | 0.728 | none |
TSM | 0.0537 | 0.0539 | 0.0537 | 0.683 | none |
true false not known for rules; forecasts are odds. Hover a column for its question.
Actions
Rules on the answers decide what to send. Each symbol runs its own request, so each one can fire.
donchian >= 0.6 and vol >= 0.6→Webhooktelegram-botWhat it means
Session of 2026-10-30, 5 symbols: 55-day closing breakout: true for none of 5. Up on heavy volume: true for none of 5. Is the stock within 5% of its 52-week high: true for none of 5. Highest odds for “A 5% rally within a month”: MU at 86%. tg fired for none.
The Telegram body is shaped as the bot API expects; signals need both the breakout and the volume rule to be true.
Request JSON (NVDA; the others differ only in the symbol)
{
"model": "ora-fin-0.1.1",
"state": {
"symbol": "NVDA"
},
"questions": {
"donchian": {
"type": "yes_no",
"ask": "C > highest(C, 55)"
},
"vol": {
"type": "yes_no",
"ask": "C > C[-1] and V > 1.5 * ref(avg(V, 20), -1)"
},
"near": {
"type": "yes_no",
"instructions": "Is the stock within 5% of its 52-week high?"
},
"rally5": {
"type": "yes_no",
"instructions": "Will it rally at least 5% at some point in the next month?"
}
},
"actions": [
{
"id": "tg",
"when": "donchian >= 0.6 and vol >= 0.6",
"do": "webhook",
"connection": "telegram-bot",
"body": {
"chat_id": "@chip_breakouts",
"text": "{{symbol}} ({{as_of}}) broke its 55-day high on volume. 5% rally odds: {{rally5|pct}}."
}
}
],
"dry_run": true
}Response JSON (NVDA, real)
{
"model": "ora-fin-0.1.1",
"answers": {
"donchian": {
"yes_no": 0.0537,
"rule": "C > highest(C, 55)",
"basis": "rule"
},
"vol": {
"yes_no": 0.0732,
"rule": "C > C[-1] and V > 1.5 * ref(avg(V, 20), -1)",
"basis": "rule"
},
"near": {
"yes_no": 0.0537,
"rule": "abs(C / max(H, 252) - 1) <= 0.05",
"basis": "comparison"
},
"rally5": {
"yes_no": 0.616
}
},
"context": {
"symbol": "NVDA",
"as_of": "2026-10-30"
},
"actions": [
{
"id": "tg",
"fired": false,
"status": "skipped"
}
]
}Algo / bot developer · example 5
Range check before starting a grid bot on GLD
Grid bots work in ranges and lose in trends; check range and trend strength before switching one on.
- StateGLD
- Questions4 asked
- Answersreal, captured
- Actions2 rules · dry run
State
{"symbol":"GLD"} The server fills in the latest completed session.
Questions
tight | English → rule | Has the stock traded in a range of less than 5% over the last 10 sessions? |
adx_low | rule | adx(14) < 20ADX under 20: no strong trend |
range_top | English → rule | Is the stock in the top 10% of its 20-day range? |
big_move | forecast | Will there be a big move in either direction in the next 5 days? A big move either way in 5 days |
Answers
| Question | Answer | Reading |
|---|---|---|
tightHas the stock traded in a range of less than 5% over the last 10 sessions compiled to max(H, 10) / min(L, 10) - 1 < 0.05 | 0.1103 | false |
adx_lowADX under 20: no strong trend | 0.2829 | false |
range_topIs the stock in the top 10% of its 20-day range compiled to (C - min(L, 20)) / (max(H, 20) - min(L, 20)) >= 0.9 | 0.0575 | false |
big_moveA big move either way in 5 days | 0.427 | 43% · close to even |
Actions
Rules on the answers decide what to send.
adx_low >= 0.6 and big_move < 0.5→Webhookgrid-botelse→Webhookgrid-bot{
"symbol": "GLD",
"command": "stay_off",
"as_of": "2026-10-30"
}What it means
For GLD on the session of 2026-10-30: Not true: Has the stock traded in a range of less than 5% over the last 10 sessions; ADX under 20: no strong trend; Is the stock in the top 10% of its 20-day range. Forecasts: A big move either way in 5 days 43%. Fired: stay_off (Webhook → grid-bot).
The grid starts only without a strong trend and with low odds of a big move; otherwise the bot is told explicitly to stay off.
Request JSON
{
"model": "ora-fin-0.1.1",
"state": {
"symbol": "GLD"
},
"questions": {
"tight": {
"type": "yes_no",
"instructions": "Has the stock traded in a range of less than 5% over the last 10 sessions?"
},
"adx_low": {
"type": "yes_no",
"ask": "adx(14) < 20"
},
"range_top": {
"type": "yes_no",
"instructions": "Is the stock in the top 10% of its 20-day range?"
},
"big_move": {
"type": "yes_no",
"instructions": "Will there be a big move in either direction in the next 5 days?"
}
},
"actions": [
{
"id": "start_grid",
"when": "adx_low >= 0.6 and big_move < 0.5",
"do": "webhook",
"connection": "grid-bot",
"body": {
"symbol": "{{symbol}}",
"command": "start",
"p_no_trend": "{{adx_low}}",
"p_big_move": "{{big_move}}",
"as_of": "{{as_of}}"
}
},
{
"id": "stay_off",
"when": "else",
"do": "webhook",
"connection": "grid-bot",
"body": {
"symbol": "{{symbol}}",
"command": "stay_off",
"as_of": "{{as_of}}"
}
}
],
"dry_run": true
}Response JSON (GLD, real)
{
"model": "ora-fin-0.1.1",
"answers": {
"tight": {
"yes_no": 0.1103,
"rule": "max(H, 10) / min(L, 10) - 1 < 0.05",
"basis": "pattern"
},
"adx_low": {
"yes_no": 0.2829,
"rule": "adx(14) < 20",
"basis": "rule"
},
"range_top": {
"yes_no": 0.0575,
"rule": "(C - min(L, 20)) / (max(H, 20) - min(L, 20)) >= 0.9",
"basis": "pattern"
},
"big_move": {
"yes_no": 0.427
}
},
"context": {
"symbol": "GLD",
"as_of": "2026-10-30"
},
"actions": [
{
"id": "start_grid",
"fired": false,
"status": "skipped"
},
{
"id": "stay_off",
"fired": true,
"status": "dry_run",
"do": "webhook",
"connection": "grid-bot",
"preview": {
"body": {
"symbol": "GLD",
"command": "stay_off",
"as_of": "2026-10-30"
}
}
}
]
}Algo / bot developer · example 6
Trailing-stop exit for a TSLA swing bot
Exit an open long when the chandelier stop or a swing-low break is hit; warn when only the forecast looks weak.
- StateTSLA
- Questions3 asked
- Answersreal, captured
- Actions2 rules · dry run
State
{"symbol":"TSLA"} The server fills in the latest completed session.
Questions
chandelier | rule | C < highest(H, 22) - 3 * atr(22)Chandelier exit: 3 ATR under the 22-day high |
swing_break | rule | C < swinglow(5, 1)closed below the last confirmed swing low |
drop10 | forecast | Will it drop at least 10% at some point in the next month? A 10% drawdown within a month |
Answers
| Question | Answer | Reading |
|---|---|---|
chandelierChandelier exit: 3 ATR under the 22-day high | 0.0986 | false |
swing_breakclosed below the last confirmed swing low | 0.0602 | false |
drop10A 10% drawdown within a month | 0.638 | 64% · likely |
Actions
Rules on the answers decide what to send.
chandelier >= 0.6 or swing_break >= 0.6→Webhookbroker-apidrop10 >= 0.4→Slackbot-log{
"text": "TSLA (2026-10-30): stop not hit, but 10% drawdown odds are 64%."
}What it means
For TSLA on the session of 2026-10-30: Not true: Chandelier exit: 3 ATR under the 22-day high; closed below the last confirmed swing low. Forecasts: A 10% drawdown within a month 64%. Fired: warn (Slack → bot-log).
Stops are exact rules on the close; the forecast only warns, so the bot's exits stay reproducible.
Request JSON
{
"model": "ora-fin-0.1.1",
"state": {
"symbol": "TSLA"
},
"questions": {
"chandelier": {
"type": "yes_no",
"ask": "C < highest(H, 22) - 3 * atr(22)"
},
"swing_break": {
"type": "yes_no",
"ask": "C < swinglow(5, 1)"
},
"drop10": {
"type": "yes_no",
"instructions": "Will it drop at least 10% at some point in the next month?"
}
},
"actions": [
{
"id": "exit",
"when": "chandelier >= 0.6 or swing_break >= 0.6",
"do": "webhook",
"connection": "broker-api",
"body": {
"symbol": "{{symbol}}",
"side": "sell",
"reason": "trailing_stop",
"p_chandelier": "{{chandelier}}",
"p_swing_break": "{{swing_break}}",
"as_of": "{{as_of}}"
}
},
{
"id": "warn",
"when": "drop10 >= 0.4",
"do": "slack",
"connection": "bot-log",
"message": "{{symbol}} ({{as_of}}): stop not hit, but 10% drawdown odds are {{drop10|pct}}."
}
],
"dry_run": true
}Response JSON (TSLA, real)
{
"model": "ora-fin-0.1.1",
"answers": {
"chandelier": {
"yes_no": 0.0986,
"rule": "C < highest(H, 22) - 3 * atr(22)",
"basis": "rule"
},
"swing_break": {
"yes_no": 0.0602,
"rule": "C < swinglow(5, 1)",
"basis": "rule"
},
"drop10": {
"yes_no": 0.638
}
},
"context": {
"symbol": "TSLA",
"as_of": "2026-10-30"
},
"actions": [
{
"id": "exit",
"fired": false,
"status": "skipped"
},
{
"id": "warn",
"fired": true,
"status": "dry_run",
"do": "slack",
"connection": "bot-log",
"preview": {
"text": "TSLA (2026-10-30): stop not hit, but 10% drawdown odds are 64%."
}
}
]
}Algo / bot developer · example 7
Candlestick reversal bot on IWM: morning star or engulfing
Buy small caps on a bullish reversal candle at a 20-day low, with a trend filter.
- StateIWM
- Questions4 asked
- Answersreal, captured
- Actions1 rule · dry run
State
{"symbol":"IWM"} The server fills in the latest completed session.
Questions
star | rule | morning_star() or engulfing_bull()Morning star or bullish engulfing |
at_low | rule | L <= 1.02 * lowest(L, 20)low within 2% of the prior 20-day low |
trend | English → rule | Is the stock above its 200-day moving average? |
up_week | forecast | Will the stock be higher in a week? Higher in a week |
Answers
| Question | Answer | Reading |
|---|---|---|
starMorning star or bullish engulfing | 0.0926 | false |
at_lowlow within 2% of the prior 20-day low | 0.3213 | false |
trendIs the stock above its 200-day moving average compiled to C > sma(C, 200) | 0.5564 | on the line (true) |
up_weekHigher in a week | 0.526 | 53% · close to even |
Actions
Rules on the answers decide what to send.
star >= 0.6 and at_low >= 0.6→Webhookbroker-apiWhat it means
For IWM on the session of 2026-10-30: Not true: Morning star or bullish engulfing; low within 2% of the prior 20-day low. On the line: Is the stock above its 200-day moving average. Forecasts: Higher in a week 53%. No action fired: every rule was false.
The candle must print at a low to count; the trend flag is passed along so the bot can size smaller against the trend.
Request JSON
{
"model": "ora-fin-0.1.1",
"state": {
"symbol": "IWM"
},
"questions": {
"star": {
"type": "yes_no",
"ask": "morning_star() or engulfing_bull()"
},
"at_low": {
"type": "yes_no",
"ask": "L <= 1.02 * lowest(L, 20)"
},
"trend": {
"type": "yes_no",
"instructions": "Is the stock above its 200-day moving average?"
},
"up_week": {
"type": "yes_no",
"instructions": "Will the stock be higher in a week?"
}
},
"actions": [
{
"id": "buy",
"when": "star >= 0.6 and at_low >= 0.6",
"do": "webhook",
"connection": "broker-api",
"body": {
"symbol": "{{symbol}}",
"side": "buy",
"strategy": "reversal_candle",
"with_trend": "{{trend}}",
"as_of": "{{as_of}}"
}
}
],
"dry_run": true
}Response JSON (IWM, real)
{
"model": "ora-fin-0.1.1",
"answers": {
"star": {
"yes_no": 0.0926,
"rule": "morning_star() or engulfing_bull()",
"basis": "rule"
},
"at_low": {
"yes_no": 0.3213,
"rule": "L <= 1.02 * lowest(L, 20)",
"basis": "rule"
},
"trend": {
"yes_no": 0.5564,
"rule": "C > sma(C, 200)",
"basis": "comparison"
},
"up_week": {
"yes_no": 0.526
}
},
"context": {
"symbol": "IWM",
"as_of": "2026-10-30"
},
"actions": [
{
"id": "buy",
"fired": false,
"status": "skipped"
}
]
}Algo / bot developer · example 8
Volatility squeeze breakout bot for XLE
Trade breakouts that come out of a low-volatility squeeze, a classic bot setup.
- StateXLE
- Questions4 asked
- Answersreal, captured
- Actions1 rule · dry run
State
{"symbol":"XLE"} The server fills in the latest completed session.
Questions
squeeze | rule | std(C, 20) < 0.7 * std(C, 100) and C > highest(C, 20)Squeeze, then a breakout |
bbw | English → rule | Is Bollinger Band width at its lowest in 120 sessions? |
linreg | rule | linreg(C, 20) > ref(linreg(C, 20), -5)20-day regression line rising over a week |
vol_rise | forecast | Will volatility rise over the next 5 days? Volatility rising over 5 days |
Answers
| Question | Answer | Reading |
|---|---|---|
squeezeSqueeze, then a breakout | 0.6462 | true |
bbwIs Bollinger Band width at its lowest in 120 sessions compiled to ((bbupper(C, 20) - bblower(C, 20)) / bbmid(C, 20)) <= ref(min(((bbupper(C, 20) - bblower(C, 20)) / bbmid(C, 20)), 119), -1) | 0.0774 | false |
linreg20-day regression line rising over a week | 0.7215 | true |
vol_riseVolatility rising over 5 days | 0.46 | 46% · close to even |
Actions
Rules on the answers decide what to send.
squeeze >= 0.6→Webhookbroker-api{
"symbol": "XLE",
"side": "buy",
"strategy": "squeeze_breakout",
"p_slope_up": 0.7215,
"as_of": "2026-10-30"
}What it means
For XLE on the session of 2026-10-30: True now: Squeeze, then a breakout; 20-day regression line rising over a week. Not true: Is Bollinger Band width at its lowest in 120 sessions. Forecasts: Volatility rising over 5 days 46%. Fired: long (Webhook → broker-api).
Squeeze breakouts are rare; most days the bot simply does nothing, which is what a disciplined breakout bot should do.
Request JSON
{
"model": "ora-fin-0.1.1",
"state": {
"symbol": "XLE"
},
"questions": {
"squeeze": {
"type": "yes_no",
"ask": "std(C, 20) < 0.7 * std(C, 100) and C > highest(C, 20)"
},
"bbw": {
"type": "yes_no",
"instructions": "Is Bollinger Band width at its lowest in 120 sessions?"
},
"linreg": {
"type": "yes_no",
"ask": "linreg(C, 20) > ref(linreg(C, 20), -5)"
},
"vol_rise": {
"type": "yes_no",
"instructions": "Will volatility rise over the next 5 days?"
}
},
"actions": [
{
"id": "long",
"when": "squeeze >= 0.6",
"do": "webhook",
"connection": "broker-api",
"body": {
"symbol": "{{symbol}}",
"side": "buy",
"strategy": "squeeze_breakout",
"p_slope_up": "{{linreg}}",
"as_of": "{{as_of}}"
}
}
],
"dry_run": true
}Response JSON (XLE, real)
{
"model": "ora-fin-0.1.1",
"answers": {
"squeeze": {
"yes_no": 0.6462,
"rule": "std(C, 20) < 0.7 * std(C, 100) and C > highest(C, 20)",
"basis": "rule"
},
"bbw": {
"yes_no": 0.0774,
"rule": "((bbupper(C, 20) - bblower(C, 20)) / bbmid(C, 20)) <= ref(min(((bbupper(C, 20) - bblower(C, 20)) / bbmid(C, 20)), 119), -1)",
"basis": "pattern"
},
"linreg": {
"yes_no": 0.7215,
"rule": "linreg(C, 20) > ref(linreg(C, 20), -5)",
"basis": "rule"
},
"vol_rise": {
"yes_no": 0.46
}
},
"context": {
"symbol": "XLE",
"as_of": "2026-10-30"
},
"actions": [
{
"id": "long",
"fired": true,
"status": "dry_run",
"do": "webhook",
"connection": "broker-api",
"preview": {
"body": {
"symbol": "XLE",
"side": "buy",
"strategy": "squeeze_breakout",
"p_slope_up": 0.7215,
"as_of": "2026-10-30"
}
}
}
]
}Algo / bot developer · example 9
A voting bot: five momentum signals on NFLX
Combine five independent momentum rules into a vote, and only act when most agree.
- StateNFLX
- Questions5 asked
- Answersreal, captured
- Actions2 rules · dry run
State
{"symbol":"NFLX"} The server fills in the latest completed session.
Questions
macd | rule | macd(C) > macdsignal(C)MACD above its signal line |
rsi | rule | rsi(C, 14) > 50RSI above 50 |
roc | rule | roc(C, 20) > 5Up more than 5% in 20 sessions |
ema | rule | C > ema(C, 21)close above the 21-day EMA |
kd | English → rule | Is stochastic %K above %D? |
Answers
| Question | Answer | Reading |
|---|---|---|
macdMACD above its signal line | 0.1584 | false |
rsiRSI above 50 | 0.0783 | false |
rocUp more than 5% in 20 sessions | 0.1119 | false |
emaclose above the 21-day EMA | 0.0972 | false |
kdIs stochastic %K above %D compiled to stochk(14, 3, 3) > stochd(14, 3, 3) | 0.5569 | on the line (true) |
Actions
Rules on the answers decide what to send.
macd >= 0.6 and rsi >= 0.6 and roc >= 0.6 and ema >= 0.6→Webhookbroker-apielse→Slackbot-log{
"text": "NFLX (2026-10-30) vote: MACD 16%, RSI 8%, ROC 11%, EMA 10%, stochastic 56%. No trade."
}What it means
For NFLX on the session of 2026-10-30: Not true: MACD above its signal line; RSI above 50; Up more than 5% in 20 sessions; close above the 21-day EMA. On the line: Is stochastic %K above %D. Fired: report (Slack → bot-log).
Requiring several rules to agree trades fewer, cleaner signals; the log line shows exactly which votes were missing.
Request JSON
{
"model": "ora-fin-0.1.1",
"state": {
"symbol": "NFLX"
},
"questions": {
"macd": {
"type": "yes_no",
"ask": "macd(C) > macdsignal(C)"
},
"rsi": {
"type": "yes_no",
"ask": "rsi(C, 14) > 50"
},
"roc": {
"type": "yes_no",
"ask": "roc(C, 20) > 5"
},
"ema": {
"type": "yes_no",
"ask": "C > ema(C, 21)"
},
"kd": {
"type": "yes_no",
"instructions": "Is stochastic %K above %D?"
}
},
"actions": [
{
"id": "strong",
"when": "macd >= 0.6 and rsi >= 0.6 and roc >= 0.6 and ema >= 0.6",
"do": "webhook",
"connection": "broker-api",
"body": {
"symbol": "{{symbol}}",
"side": "buy",
"strategy": "momentum_vote",
"as_of": "{{as_of}}"
}
},
{
"id": "report",
"when": "else",
"do": "slack",
"connection": "bot-log",
"message": "{{symbol}} ({{as_of}}) vote: MACD {{macd|pct}}, RSI {{rsi|pct}}, ROC {{roc|pct}}, EMA {{ema|pct}}, stochastic {{kd|pct}}. No trade."
}
],
"dry_run": true
}Response JSON (NFLX, real)
{
"model": "ora-fin-0.1.1",
"answers": {
"macd": {
"yes_no": 0.1584,
"rule": "macd(C) > macdsignal(C)",
"basis": "rule"
},
"rsi": {
"yes_no": 0.0783,
"rule": "rsi(C, 14) > 50",
"basis": "rule"
},
"roc": {
"yes_no": 0.1119,
"rule": "roc(C, 20) > 5",
"basis": "rule"
},
"ema": {
"yes_no": 0.0972,
"rule": "C > ema(C, 21)",
"basis": "rule"
},
"kd": {
"yes_no": 0.5569,
"rule": "stochk(14, 3, 3) > stochd(14, 3, 3)",
"basis": "comparison"
}
},
"context": {
"symbol": "NFLX",
"as_of": "2026-10-30"
},
"actions": [
{
"id": "strong",
"fired": false,
"status": "skipped"
},
{
"id": "report",
"fired": true,
"status": "dry_run",
"do": "slack",
"connection": "bot-log",
"preview": {
"text": "NFLX (2026-10-30) vote: MACD 16%, RSI 8%, ROC 11%, EMA 10%, stochastic 56%. No trade."
}
}
]
}Algo / bot developer · example 10
Pairs bot: check both legs before trading XOM vs CVX
Check momentum and stretch for both energy majors before a relative-value bot opens a pair.
- State2 symbols
- Questions4 asked
- Answersreal, captured
- Actionsnone
State
{"symbol":"XOM"} then CVX, one request each. The server fills in the latest completed session.
Questions
zs | rule | zscore(C, 20) > 1.5close more than 1.5 standard deviations above its 20-day mean |
zs_low | rule | zscore(C, 20) < -1.5close more than 1.5 standard deviations below its 20-day mean |
roc | rule | roc(C, 10) > 010-day rate of change positive |
beat_spy | forecast | Will it beat SPY over the next month? Beating SPY over a month |
Answers
| Symbol | zsrule | zs_lowrule | rocrule | beat_spyforecast |
|---|---|---|---|---|
XOM | 0.6012 | 0.0537 | 0.8825 | 0.554 |
CVX | 0.5012 | 0.0555 | 0.8706 | 0.564 |
true false not known for rules; forecasts are odds. Hover a column for its question.
What it means
Session of 2026-10-30, 2 symbols: close more than 1.5 standard deviations above its 20-day mean: true for XOM of 2. close more than 1.5 standard deviations below its 20-day mean: true for none of 2. 10-day rate of change positive: true for XOM, CVX of 2. Highest odds for “Beating SPY over a month”: CVX at 56%.
A pair needs one leg stretched up and the other stretched down; the bot compares the two answer sets before sending any order.
Request JSON (XOM; the others differ only in the symbol)
{
"model": "ora-fin-0.1.1",
"state": {
"symbol": "XOM"
},
"questions": {
"zs": {
"type": "yes_no",
"ask": "zscore(C, 20) > 1.5"
},
"zs_low": {
"type": "yes_no",
"ask": "zscore(C, 20) < -1.5"
},
"roc": {
"type": "yes_no",
"ask": "roc(C, 10) > 0"
},
"beat_spy": {
"type": "yes_no",
"instructions": "Will it beat SPY over the next month?"
}
}
}Response JSON (XOM, real)
{
"model": "ora-fin-0.1.1",
"answers": {
"zs": {
"yes_no": 0.6012,
"rule": "zscore(C, 20) > 1.5",
"basis": "rule"
},
"zs_low": {
"yes_no": 0.0537,
"rule": "zscore(C, 20) < -1.5",
"basis": "rule"
},
"roc": {
"yes_no": 0.8825,
"rule": "roc(C, 10) > 0",
"basis": "rule"
},
"beat_spy": {
"yes_no": 0.554
}
},
"context": {
"symbol": "XOM",
"as_of": "2026-10-30"
}
}Information, not investment advice. Rules answer from the latest completed daily session; forecasts are probabilities. Actions ran as dry runs: nothing was sent. More in Builders: Quant developer, Fintech app builder, Robo-advisor, Broker app, Data vendor / platform, Trading educator / newsletter.