Ora
All use cases All industries

Individuals

Retail investorActive day traderSwing traderOptions traderDividend investorLong-term passive investorCrypto traderFX traderCommodities traderSocial trading communityStudents and universities

Buy side

Financial advisor / RIAWealth managerFamily officeHedge fund PMQuant researcherPortfolio manager (long-only)Risk managerPrivate equityVC / growth investorFund-of-funds allocator

Sell side

Equity research analystSell-side sales traderExecution trader / deskMarket makerProp trading firmCompliance officer

Corporates

Investor relations teamCorporate treasuryCFO officeBank credit analystFinancial journalist / media

Builders

Quant developerFintech app builderRobo-advisorBroker appAlgo / bot developerData vendor / platformTrading educator / newsletter

Institutions

ETF issuerIndex providerInsurance investment officePension fundEndowmentSovereign wealth fund

Use cases · Builders

Quant developer: 20 ways to use Ora

Wires exact rules and forecasts into pipelines, tests and order systems. Each example is a complete, runnable request with the real answers it returned (32 requests, captured 2026-10-31), what they mean and, where it fits, the action it would send.

Answers were captured on 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 (64)

sma 8ref 7offset 6avg 5ema 3abs 3atr 3crossup 2wma 2adx 2highest 2log 2sqrt 2std 2zscore 2rsi 2sum 2mean 2crossdown 1diminus 1diplus 1linreg 1median 1gap_down 1gap_up 1inside_bar 1marubozu 1outside_bar 1spinning_top 1cum 1rec 1rma 1macd 1macdsignal 1cci 1stochd 1stochk 1willr 1days_since_earnings 1days_to_earnings 1last_earnings_move 1next_report_amc 1barssince 1highestbars 1lowestbars 1bblower 1between 1iif 1sign 1greatest 1hammer 1hanging_man 1inverted_hammer 1least 1hl2 1hlc3 1ohlc4 1tr 1swinghigh 1swinglow 1lowest 1max 1obv 1percentrank 1

Examples 1–10 of 20 · page 1 of 2

Quant developer · example 1

Unit-test a moving-average signal on SPY against the rule engine

Before shipping a crossover signal in a pipeline, compare the in-house computation with Ora's exact rules for the same session.

ora-fin-0.1.1SPY4 questions1 action
  1. StateSPY
  2. Questions4 asked
  3. Answersreal, captured
  4. Actions1 rule · dry run

State

{"symbol":"SPY"} The server fills in the latest completed session.

Questions

cross_50rulecrossup(C, sma(C, 50))
Crossed above the 50-day today
ema_wmarulewma(C, 10) > ema(C, 30)
10-day weighted average above the 30-day EMA
sma50_uprulesma(C, 50) > ref(sma(C, 50), -10)
The 50-day average is rising
dn_crossrulecrossdown(sma(C, 20), sma(C, 50))
20-day average crossed under the 50-day today

Answers

QuestionAnswerReading
cross_50
Crossed above the 50-day today
0.05false
ema_wma
10-day weighted average above the 30-day EMA
0.3059false
sma50_up
The 50-day average is rising
0.2481false
dn_cross
20-day average crossed under the 50-day today
0.05false

Actions

Rules on the answers decide what to send.

cross_50 >= 0→Webhookci-results
What each action would send 1 of 1 fired · dry run, nothing sent
test_resultwould send (dry run)Webhook → ci-results
{
  "suite": "signal_parity",
  "symbol": "SPY",
  "as_of": "2026-10-30",
  "cross_50d": 0.05,
  "wma_over_ema": 0.3059,
  "sma50_rising": 0.2481,
  "cross_20_50_down": 0.05
}

What it means

For SPY on the session of 2026-10-30: Not true: Crossed above the 50-day today; 10-day weighted average above the 30-day EMA; The 50-day average is rising; 20-day average crossed under the 50-day today. Fired: test_result (Webhook → ci-results).

Each answer carries the rule that was evaluated, so a test can assert the in-house flag matches the rule's yes or no for the same as_of date.

Request JSON
{
  "model": "ora-fin-0.1.1",
  "state": {
    "symbol": "SPY"
  },
  "questions": {
    "cross_50": {
      "type": "yes_no",
      "ask": "crossup(C, sma(C, 50))"
    },
    "ema_wma": {
      "type": "yes_no",
      "ask": "wma(C, 10) > ema(C, 30)"
    },
    "sma50_up": {
      "type": "yes_no",
      "ask": "sma(C, 50) > ref(sma(C, 50), -10)"
    },
    "dn_cross": {
      "type": "yes_no",
      "ask": "crossdown(sma(C, 20), sma(C, 50))"
    }
  },
  "actions": [
    {
      "id": "test_result",
      "when": "cross_50 >= 0",
      "do": "webhook",
      "connection": "ci-results",
      "body": {
        "suite": "signal_parity",
        "symbol": "{{symbol}}",
        "as_of": "{{as_of}}",
        "cross_50d": "{{cross_50}}",
        "wma_over_ema": "{{ema_wma}}",
        "sma50_rising": "{{sma50_up}}",
        "cross_20_50_down": "{{dn_cross}}"
      }
    }
  ],
  "dry_run": true
}
Response JSON (SPY, real)
{
  "model": "ora-fin-0.1.1",
  "answers": {
    "cross_50": {
      "yes_no": 0.05,
      "rule": "crossup(C, sma(C, 50))",
      "basis": "rule"
    },
    "ema_wma": {
      "yes_no": 0.3059,
      "rule": "wma(C, 10) > ema(C, 30)",
      "basis": "rule"
    },
    "sma50_up": {
      "yes_no": 0.2481,
      "rule": "sma(C, 50) > ref(sma(C, 50), -10)",
      "basis": "rule"
    },
    "dn_cross": {
      "yes_no": 0.05,
      "rule": "crossdown(sma(C, 20), sma(C, 50))",
      "basis": "rule"
    }
  },
  "context": {
    "symbol": "SPY",
    "as_of": "2026-10-30"
  },
  "actions": [
    {
      "id": "test_result",
      "fired": true,
      "status": "dry_run",
      "do": "webhook",
      "connection": "ci-results",
      "preview": {
        "body": {
          "suite": "signal_parity",
          "symbol": "SPY",
          "as_of": "2026-10-30",
          "cross_50d": 0.05,
          "wma_over_ema": 0.3059,
          "sma50_rising": 0.2481,
          "cross_20_50_down": 0.05
        }
      }
    }
  ]
}

crossdown crossup ema ref sma wma

Quant developer · example 2

Send a QQQ breakout signal to the order service as typed JSON

A breakout rule plus a volume rule plus the one-week forecast decide whether a signed webhook carries an entry signal to the order management service.

ora-fin-0.1.1QQQ4 questions2 actions
  1. StateQQQ
  2. Questions4 asked
  3. Answersreal, captured
  4. Actions2 rules · dry run

State

{"symbol":"QQQ"} The server fills in the latest completed session.

Questions

breakoutruleC > highest(C, 20)
20-day closing breakout
volumeruleV > 2 * ref(avg(V, 20), -1)
Volume more than twice the previous 20-day average
adxruleadx(14) > 25
Trending (ADX above 25)
up_weekforecastWill the stock be higher in a week?
Higher in a week

Answers

QuestionAnswerReading
breakout
20-day closing breakout
0.0537false
volume
Volume more than twice the previous 20-day average
0.766true
adx
Trending (ADX above 25)
0.6956true
up_week
Higher in a week
0.56156% · close to even

Actions

Rules on the answers decide what to send.

breakout >= 0.6 and volume >= 0.6 and up_week >= 0.55→Webhookoms-signals
else→Webhookoms-signals
What each action would send 1 of 2 fired · dry run, nothing sent
entryrule false: skipped
no_signalwould send (dry run)Webhook → oms-signals
{
  "symbol": "QQQ",
  "signal": "none",
  "p_breakout": 0.0537,
  "as_of": "2026-10-30"
}

What it means

For QQQ on the session of 2026-10-30: True now: Volume more than twice the previous 20-day average; Trending (ADX above 25). Not true: 20-day closing breakout. Forecasts: Higher in a week 56%. Fired: no_signal (Webhook → oms-signals).

The order service receives exactly one body per run, either an entry or an explicit none, so downstream code never has to infer silence.

Request JSON
{
  "model": "ora-fin-0.1.1",
  "state": {
    "symbol": "QQQ"
  },
  "questions": {
    "breakout": {
      "type": "yes_no",
      "ask": "C > highest(C, 20)"
    },
    "volume": {
      "type": "yes_no",
      "ask": "V > 2 * ref(avg(V, 20), -1)"
    },
    "adx": {
      "type": "yes_no",
      "ask": "adx(14) > 25"
    },
    "up_week": {
      "type": "yes_no",
      "instructions": "Will the stock be higher in a week?"
    }
  },
  "actions": [
    {
      "id": "entry",
      "when": "breakout >= 0.6 and volume >= 0.6 and up_week >= 0.55",
      "do": "webhook",
      "connection": "oms-signals",
      "body": {
        "symbol": "{{symbol}}",
        "signal": "breakout_long",
        "p_breakout": "{{breakout}}",
        "p_volume": "{{volume}}",
        "p_trend": "{{adx}}",
        "p_up_week": "{{up_week}}",
        "as_of": "{{as_of}}"
      }
    },
    {
      "id": "no_signal",
      "when": "else",
      "do": "webhook",
      "connection": "oms-signals",
      "body": {
        "symbol": "{{symbol}}",
        "signal": "none",
        "p_breakout": "{{breakout}}",
        "as_of": "{{as_of}}"
      }
    }
  ],
  "dry_run": true
}
Response JSON (QQQ, real)
{
  "model": "ora-fin-0.1.1",
  "answers": {
    "breakout": {
      "yes_no": 0.0537,
      "rule": "C > highest(C, 20)",
      "basis": "rule"
    },
    "volume": {
      "yes_no": 0.766,
      "rule": "V > 2 * ref(avg(V, 20), -1)",
      "basis": "rule"
    },
    "adx": {
      "yes_no": 0.6956,
      "rule": "adx(14) > 25",
      "basis": "rule"
    },
    "up_week": {
      "yes_no": 0.561
    }
  },
  "context": {
    "symbol": "QQQ",
    "as_of": "2026-10-30"
  },
  "actions": [
    {
      "id": "entry",
      "fired": false,
      "status": "skipped"
    },
    {
      "id": "no_signal",
      "fired": true,
      "status": "dry_run",
      "do": "webhook",
      "connection": "oms-signals",
      "preview": {
        "body": {
          "symbol": "QQQ",
          "signal": "none",
          "p_breakout": 0.0537,
          "as_of": "2026-10-30"
        }
      }
    }
  ]
}

adx avg highest ref

Quant developer · example 3

Build a regime feature vector for AAPL from exact rules

Turn trend, volatility and momentum states into binary features for a model, each computed by the rule engine rather than reimplemented.

ora-fin-0.1.1AAPL6 questions1 action
  1. StateAAPL
  2. Questions6 asked
  3. Answersreal, captured
  4. Actions1 rule · dry run

State

{"symbol":"AAPL"} The server fills in the latest completed session.

Questions

trendruleadx(14) > 20 and diplus(14) > diminus(14)
Trending up (ADX over 20 and +DI over −DI)
linreg_uprulelinreg(C, 20) > ref(linreg(C, 20), -5)
20-day regression line higher than a week ago
vol_regimerulestd(log(C / C[-1]), 20) * sqrt(252) > 0.4
Annualized 20-day volatility above 40%
zsrulezscore(C, 50) > 1
close more than 1 standard deviation above its 50-day mean
median_volruleV > 2 * median(V, 20)
volume over twice its 20-day median
drop5forecastWill it drop at least 5% at some point in the next month?
A 5% drawdown within a month

Answers

QuestionAnswerReading
trend
Trending up (ADX over 20 and +DI over −DI)
0.2895false
linreg_up
20-day regression line higher than a week ago
0.6301true
vol_regime
Annualized 20-day volatility above 40%
0.0537false
zs
close more than 1 standard deviation above its 50-day mean
0.5609on the line (true)
median_vol
volume over twice its 20-day median
0.2151false
drop5
A 5% drawdown within a month
0.36537% · unlikely

Actions

Rules on the answers decide what to send.

trend >= 0→Webhookfeature-store
What each action would send 1 of 1 fired · dry run, nothing sent
featureswould send (dry run)Webhook → feature-store
{
  "entity": "AAPL",
  "as_of": "2026-10-30",
  "adx_uptrend": 0.2895,
  "linreg_up": 0.6301,
  "hv_over_40": 0.0537,
  "zscore_over_1": 0.5609,
  "volume_over_2x_median": 0.2151,
  "p_drop5": 0.365
}

What it means

For AAPL on the session of 2026-10-30: True now: 20-day regression line higher than a week ago. Not true: Trending up (ADX over 20 and +DI over −DI); Annualized 20-day volatility above 40%; volume over twice its 20-day median. On the line: close more than 1 standard deviation above its 50-day mean. Forecasts: A 5% drawdown within a month 37%. Fired: features (Webhook → feature-store).

Rule answers near one or zero become clean binary features; the forecast column stays a probability and is stored as such.

Request JSON
{
  "model": "ora-fin-0.1.1",
  "state": {
    "symbol": "AAPL"
  },
  "questions": {
    "trend": {
      "type": "yes_no",
      "ask": "adx(14) > 20 and diplus(14) > diminus(14)"
    },
    "linreg_up": {
      "type": "yes_no",
      "ask": "linreg(C, 20) > ref(linreg(C, 20), -5)"
    },
    "vol_regime": {
      "type": "yes_no",
      "ask": "std(log(C / C[-1]), 20) * sqrt(252) > 0.4"
    },
    "zs": {
      "type": "yes_no",
      "ask": "zscore(C, 50) > 1"
    },
    "median_vol": {
      "type": "yes_no",
      "ask": "V > 2 * median(V, 20)"
    },
    "drop5": {
      "type": "yes_no",
      "instructions": "Will it drop at least 5% at some point in the next month?"
    }
  },
  "actions": [
    {
      "id": "features",
      "when": "trend >= 0",
      "do": "webhook",
      "connection": "feature-store",
      "body": {
        "entity": "{{symbol}}",
        "as_of": "{{as_of}}",
        "adx_uptrend": "{{trend}}",
        "linreg_up": "{{linreg_up}}",
        "hv_over_40": "{{vol_regime}}",
        "zscore_over_1": "{{zs}}",
        "volume_over_2x_median": "{{median_vol}}",
        "p_drop5": "{{drop5}}"
      }
    }
  ],
  "dry_run": true
}
Response JSON (AAPL, real)
{
  "model": "ora-fin-0.1.1",
  "answers": {
    "trend": {
      "yes_no": 0.2895,
      "rule": "adx(14) > 20 and diplus(14) > diminus(14)",
      "basis": "rule"
    },
    "linreg_up": {
      "yes_no": 0.6301,
      "rule": "linreg(C, 20) > ref(linreg(C, 20), -5)",
      "basis": "rule"
    },
    "vol_regime": {
      "yes_no": 0.0537,
      "rule": "std(log(C / C[-1]), 20) * sqrt(252) > 0.4",
      "basis": "rule"
    },
    "zs": {
      "yes_no": 0.5609,
      "rule": "zscore(C, 50) > 1",
      "basis": "rule"
    },
    "median_vol": {
      "yes_no": 0.2151,
      "rule": "V > 2 * median(V, 20)",
      "basis": "rule"
    },
    "drop5": {
      "yes_no": 0.365
    }
  },
  "context": {
    "symbol": "AAPL",
    "as_of": "2026-10-30"
  },
  "actions": [
    {
      "id": "features",
      "fired": true,
      "status": "dry_run",
      "do": "webhook",
      "connection": "feature-store",
      "preview": {
        "body": {
          "entity": "AAPL",
          "as_of": "2026-10-30",
          "adx_uptrend": 0.2895,
          "linreg_up": 0.6301,
          "hv_over_40": 0.0537,
          "zscore_over_1": 0.5609,
          "volume_over_2x_median": 0.2151,
          "p_drop5": 0.365
        }
      }
    }
  ]
}

adx diminus diplus linreg log median offset ref sqrt std zscore

Quant developer · example 4

Scan a five-name tech universe for oversold-in-uptrend setups

Run the same rule set over a small universe in parallel and rank by the drawdown forecast.

ora-fin-0.1.15 symbols, one request each4 questions1 action
  1. State5 symbols
  2. Questions4 asked
  3. Answersreal, captured
  4. Actions1 rule · dry run

State

{"symbol":"AAPL"} then MSFT, NVDA, AMD, ORCL, one request each. The server fills in the latest completed session.

Questions

setuprule(C > sma(C, 200) and rsi(C, 14) < 40) or (C < sma(C, 200) and rsi(C, 14) < 25)
Oversold, with the line set by the trend
rsi2rulersi(C, 2) < 10
Two-day RSI under 10
above_200ruleC > sma(C, 200) * 1.10
More than 10% above the 200-day
drop5forecastWill it drop at least 5% at some point in the next month?
A 5% drawdown within a month

Answers

Symbolsetuprulersi2ruleabove_200ruledrop5forecastFired
AAPL0.06340.14640.9340.365none
MSFT0.10640.58120.94310.422none
NVDA0.54550.5910.060.523none
AMD0.52170.45180.87010.763none
ORCL0.05370.23880.05370.653none

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 and drop5 < 0.5→Slackquant-dev
AAPL 0 of 1 fired · dry run, nothing sent
MSFT 0 of 1 fired · dry run, nothing sent
NVDA 0 of 1 fired · dry run, nothing sent
AMD 0 of 1 fired · dry run, nothing sent
ORCL 0 of 1 fired · dry run, nothing sent

What it means

Session of 2026-10-30, 5 symbols: Oversold, with the line set by the trend: true for none of 5. Two-day RSI under 10: true for none of 5. More than 10% above the 200-day: true for AAPL, MSFT, AMD of 5. Highest odds for “A 5% drawdown within a month”: AMD at 76%. candidate fired for none.

One request per symbol with identical keys makes the results a table; filter on the setup rule and sort by the drawdown odds.

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) or (C < sma(C, 200) and rsi(C, 14) < 25)"
    },
    "rsi2": {
      "type": "yes_no",
      "ask": "rsi(C, 2) < 10"
    },
    "above_200": {
      "type": "yes_no",
      "ask": "C > sma(C, 200) * 1.10"
    },
    "drop5": {
      "type": "yes_no",
      "instructions": "Will it drop at least 5% at some point in the next month?"
    }
  },
  "actions": [
    {
      "id": "candidate",
      "when": "setup >= 0.6 and drop5 < 0.5",
      "do": "slack",
      "connection": "quant-dev",
      "message": "{{symbol}} ({{as_of}}): oversold-in-regime setup ({{setup|pct}}), RSI(2) {{rsi2|pct}}, 5% drawdown odds {{drop5|pct}}."
    }
  ],
  "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) or (C < sma(C, 200) and rsi(C, 14) < 25)",
      "basis": "rule"
    },
    "rsi2": {
      "yes_no": 0.1464,
      "rule": "rsi(C, 2) < 10",
      "basis": "rule"
    },
    "above_200": {
      "yes_no": 0.934,
      "rule": "C > sma(C, 200) * 1.10",
      "basis": "rule"
    },
    "drop5": {
      "yes_no": 0.365
    }
  },
  "context": {
    "symbol": "AAPL",
    "as_of": "2026-10-30"
  },
  "actions": [
    {
      "id": "candidate",
      "fired": false,
      "status": "skipped"
    }
  ]
}

rsi sma

Quant developer · example 5

Regression-test candlestick detectors on TSLA

Check that a home-grown candlestick detector agrees with Ora's pattern functions on the latest bar.

ora-fin-0.1.1TSLA6 questions
  1. StateTSLA
  2. Questions6 asked
  3. Answersreal, captured
  4. Actionsnone

State

{"symbol":"TSLA"} The server fills in the latest completed session.

Questions

marubozurulemarubozu()
marubozu candle: Body at least 90% of the range: almost no wicks.
spinningrulespinning_top()
spinning top candle: Small body (10–30% of range) with wicks of at least a quarter of the range on both sides.
outsideruleoutside_bar()
outside bar candle: Today's high above yesterday's and low below it.
insideruleinside_bar()
inside bar candle: Today's high and low are inside yesterday's (equal counts).
gap_uprulegap_up()
gap up candle: Today's whole range is above yesterday's high: an unfilled gap up.
gap_downrulegap_down()
gap down candle: Today's whole range is below yesterday's low.

Answers

QuestionAnswerReading
marubozu
marubozu candle: Body at least 90% of the range: almost no wicks.
0.0551false
spinning
spinning top candle: Small body (10–30% of range) with wicks of at least a quarter of the range on both sides.
0.2832false
outside
outside bar candle: Today's high above yesterday's and low below it.
0.3172false
inside
inside bar candle: Today's high and low are inside yesterday's (equal counts).
0.0795false
gap_up
gap up candle: Today's whole range is above yesterday's high: an unfilled gap up.
0.0577false
gap_down
gap down candle: Today's whole range is below yesterday's low.
0.2768false

What it means

For TSLA on the session of 2026-10-30: Not true: marubozu candle: Body at least 90% of the range: almost no wicks.; spinning top candle: Small body (10–30% of range) with wicks of at least a quarter of the range on both sides.; outside bar candle: Today's high above yesterday's and low below it.; inside bar candle: Today's high and low are inside yesterday's (equal counts).; gap up candle: Today's whole range is above yesterday's high: an unfilled gap up.; gap down candle: Today's whole range is below yesterday's low..

A pattern answer is an exact rule on one bar; disagreement with the in-house detector points at a definition difference worth documenting.

Request JSON
{
  "model": "ora-fin-0.1.1",
  "state": {
    "symbol": "TSLA"
  },
  "questions": {
    "marubozu": {
      "type": "yes_no",
      "ask": "marubozu()"
    },
    "spinning": {
      "type": "yes_no",
      "ask": "spinning_top()"
    },
    "outside": {
      "type": "yes_no",
      "ask": "outside_bar()"
    },
    "inside": {
      "type": "yes_no",
      "ask": "inside_bar()"
    },
    "gap_up": {
      "type": "yes_no",
      "ask": "gap_up()"
    },
    "gap_down": {
      "type": "yes_no",
      "ask": "gap_down()"
    }
  }
}
Response JSON (TSLA, real)
{
  "model": "ora-fin-0.1.1",
  "answers": {
    "marubozu": {
      "yes_no": 0.0551,
      "rule": "marubozu()",
      "basis": "rule"
    },
    "spinning": {
      "yes_no": 0.2832,
      "rule": "spinning_top()",
      "basis": "rule"
    },
    "outside": {
      "yes_no": 0.3172,
      "rule": "outside_bar()",
      "basis": "rule"
    },
    "inside": {
      "yes_no": 0.0795,
      "rule": "inside_bar()",
      "basis": "rule"
    },
    "gap_up": {
      "yes_no": 0.0577,
      "rule": "gap_up()",
      "basis": "rule"
    },
    "gap_down": {
      "yes_no": 0.2768,
      "rule": "gap_down()",
      "basis": "rule"
    }
  },
  "context": {
    "symbol": "TSLA",
    "as_of": "2026-10-30"
  }
}

gap_down gap_up inside_bar marubozu outside_bar spinning_top

Quant developer · example 6

Compare a custom recursive smoother with built-in averages on MSFT

Prototype an exponential smoother with rec() and check it against ema and rma before porting it to production code.

ora-fin-0.1.1MSFT4 questions
  1. StateMSFT
  2. Questions4 asked
  3. Answersreal, captured
  4. Actionsnone

State

{"symbol":"MSFT"} The server fills in the latest completed session.

Questions

rec_aboveruleC > rec(C, self + 0.1 * (C - self))
close above a recursive smoother with alpha one tenth
ema_aboveruleC > ema(C, 19)
close above the 19-day EMA
rma_aboveruleC > rma(C, 10)
close above the 10-day Wilder average
cum_uprulecum(C > C[-1]) > cum(C < C[-1])
more up days than down days in the whole history

Answers

QuestionAnswerReading
rec_above
close above a recursive smoother with alpha one tenth
0.3041false
ema_above
close above the 19-day EMA
0.3041false
rma_above
close above the 10-day Wilder average
0.3041false
cum_up
more up days than down days in the whole history
0.9463true

What it means

For MSFT on the session of 2026-10-30: True now: more up days than down days in the whole history. Not true: close above a recursive smoother with alpha one tenth; close above the 19-day EMA; close above the 10-day Wilder average.

A smoother with alpha one tenth should agree with the 19-day EMA most days; a disagreement on this session is a test case to keep.

Request JSON
{
  "model": "ora-fin-0.1.1",
  "state": {
    "symbol": "MSFT"
  },
  "questions": {
    "rec_above": {
      "type": "yes_no",
      "ask": "C > rec(C, self + 0.1 * (C - self))"
    },
    "ema_above": {
      "type": "yes_no",
      "ask": "C > ema(C, 19)"
    },
    "rma_above": {
      "type": "yes_no",
      "ask": "C > rma(C, 10)"
    },
    "cum_up": {
      "type": "yes_no",
      "ask": "cum(C > C[-1]) > cum(C < C[-1])"
    }
  }
}
Response JSON (MSFT, real)
{
  "model": "ora-fin-0.1.1",
  "answers": {
    "rec_above": {
      "yes_no": 0.3041,
      "rule": "C > rec(C, self + 0.1 * (C - self))",
      "basis": "rule"
    },
    "ema_above": {
      "yes_no": 0.3041,
      "rule": "C > ema(C, 19)",
      "basis": "rule"
    },
    "rma_above": {
      "yes_no": 0.3041,
      "rule": "C > rma(C, 10)",
      "basis": "rule"
    },
    "cum_up": {
      "yes_no": 0.9463,
      "rule": "cum(C > C[-1]) > cum(C < C[-1])",
      "basis": "rule"
    }
  },
  "context": {
    "symbol": "MSFT",
    "as_of": "2026-10-30"
  }
}

cum ema offset rec rma

Quant developer · example 7

Nightly signal snapshot for the index ETFs, posted to a data lake hook

After every close, compute the same four signals for the index ETFs and post each row to an ingestion webhook.

ora-fin-0.1.14 symbols, one request each4 questions1 actionworkflow · Mon–Fri at 16:45 ET
  1. ScheduleMon–Fri at 16:45 ET
  2. State4 symbols
  3. Questions4 asked
  4. Answersreal, captured
  5. Actions1 rule · dry run

State

{"symbol":"SPY"} then QQQ, IWM, DIA, one request each. The server fills in the latest completed session.

Questions

trendruleC > sma(C, 50)
Above the 50-day average
momentumrulemacd(C) > macdsignal(C)
MACD above its signal line
breadth_proxyrulesum(C > C[-1], 10) >= 6
Up on at least six of the last ten days
up_weekforecastWill the stock be higher in a week?
Higher in a week

Answers

Symboltrendrulemomentumrulebreadth_proxyruleup_weekforecastFired
SPY0.11280.16580.550.598row
QQQ0.06530.12380.20180.561row
IWM0.21760.92470.91740.526row
DIA0.28490.61820.550.567row

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.

trend >= 0→Webhooklake-ingest
SPY 1 of 1 fired · dry run, nothing sent
rowwould send (dry run)Webhook → lake-ingest
{
  "table": "ora_signals",
  "symbol": "SPY",
  "as_of": "2026-10-30",
  "trend": 0.1128,
  "momentum": 0.1658,
  "mostly_up": 0.55,
  "p_up_week": 0.598
}
QQQ 1 of 1 fired · dry run, nothing sent
rowwould send (dry run)Webhook → lake-ingest
{
  "table": "ora_signals",
  "symbol": "QQQ",
  "as_of": "2026-10-30",
  "trend": 0.0653,
  "momentum": 0.1238,
  "mostly_up": 0.2018,
  "p_up_week": 0.561
}
IWM 1 of 1 fired · dry run, nothing sent
rowwould send (dry run)Webhook → lake-ingest
{
  "table": "ora_signals",
  "symbol": "IWM",
  "as_of": "2026-10-30",
  "trend": 0.2176,
  "momentum": 0.9247,
  "mostly_up": 0.9174,
  "p_up_week": 0.526
}
DIA 1 of 1 fired · dry run, nothing sent
rowwould send (dry run)Webhook → lake-ingest
{
  "table": "ora_signals",
  "symbol": "DIA",
  "as_of": "2026-10-30",
  "trend": 0.2849,
  "momentum": 0.6182,
  "mostly_up": 0.55,
  "p_up_week": 0.567
}

What it means

Session of 2026-10-30, 4 symbols: Above the 50-day average: true for none of 4. MACD above its signal line: true for IWM, DIA of 4. Up on at least six of the last ten days: true for IWM of 4. Highest odds for “Higher in a week”: SPY at 60%. row fired for SPY, QQQ, IWM, DIA.

The always-true condition makes every symbol post a row, so the table has one record per symbol per session for later research.

As a scheduled workflow (Mon–Fri at 16:45 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": "Nightly signal snapshot for the index ETFs, posted to a data lake hook",
  "symbols": "SPY QQQ IWM DIA",
  "days": [
    1,
    2,
    3,
    4,
    5
  ],
  "at_time": "16:45",
  "model": "ora-fin-0.1.1",
  "questions": {
    "trend": {
      "type": "yes_no",
      "ask": "C > sma(C, 50)"
    },
    "momentum": {
      "type": "yes_no",
      "ask": "macd(C) > macdsignal(C)"
    },
    "breadth_proxy": {
      "type": "yes_no",
      "ask": "sum(C > C[-1], 10) >= 6"
    },
    "up_week": {
      "type": "yes_no",
      "instructions": "Will the stock be higher in a week?"
    }
  },
  "actions": [
    {
      "id": "row",
      "when": "trend >= 0",
      "do": "webhook",
      "connection": "lake-ingest",
      "body": {
        "table": "ora_signals",
        "symbol": "{{symbol}}",
        "as_of": "{{as_of}}",
        "trend": "{{trend}}",
        "momentum": "{{momentum}}",
        "mostly_up": "{{breadth_proxy}}",
        "p_up_week": "{{up_week}}"
      }
    }
  ]
}
Request JSON (SPY; the others differ only in the symbol)
{
  "model": "ora-fin-0.1.1",
  "state": {
    "symbol": "SPY"
  },
  "questions": {
    "trend": {
      "type": "yes_no",
      "ask": "C > sma(C, 50)"
    },
    "momentum": {
      "type": "yes_no",
      "ask": "macd(C) > macdsignal(C)"
    },
    "breadth_proxy": {
      "type": "yes_no",
      "ask": "sum(C > C[-1], 10) >= 6"
    },
    "up_week": {
      "type": "yes_no",
      "instructions": "Will the stock be higher in a week?"
    }
  },
  "actions": [
    {
      "id": "row",
      "when": "trend >= 0",
      "do": "webhook",
      "connection": "lake-ingest",
      "body": {
        "table": "ora_signals",
        "symbol": "{{symbol}}",
        "as_of": "{{as_of}}",
        "trend": "{{trend}}",
        "momentum": "{{momentum}}",
        "mostly_up": "{{breadth_proxy}}",
        "p_up_week": "{{up_week}}"
      }
    }
  ],
  "dry_run": true
}
Response JSON (SPY, real)
{
  "model": "ora-fin-0.1.1",
  "answers": {
    "trend": {
      "yes_no": 0.1128,
      "rule": "C > sma(C, 50)",
      "basis": "rule"
    },
    "momentum": {
      "yes_no": 0.1658,
      "rule": "macd(C) > macdsignal(C)",
      "basis": "rule"
    },
    "breadth_proxy": {
      "yes_no": 0.55,
      "rule": "sum(C > C[-1], 10) >= 6",
      "basis": "rule"
    },
    "up_week": {
      "yes_no": 0.598
    }
  },
  "context": {
    "symbol": "SPY",
    "as_of": "2026-10-30"
  },
  "actions": [
    {
      "id": "row",
      "fired": true,
      "status": "dry_run",
      "do": "webhook",
      "connection": "lake-ingest",
      "preview": {
        "body": {
          "table": "ora_signals",
          "symbol": "SPY",
          "as_of": "2026-10-30",
          "trend": 0.1128,
          "momentum": 0.1658,
          "mostly_up": 0.55,
          "p_up_week": 0.598
        }
      }
    }
  ]
}

macd macdsignal offset sma sum

Quant developer · example 8

Stochastic %K and %D states for AMD as model inputs

Feed oscillator states into a classifier without writing an oscillator library.

ora-fin-0.1.1AMD5 questions
  1. StateAMD
  2. Questions5 asked
  3. Answersreal, captured
  4. Actionsnone

State

{"symbol":"AMD"} The server fills in the latest completed session.

Questions

k_over_drulestochk(14) > stochd(14)
stochastic %K above %D
k_lowrulestochk(14) < 20
Stochastic %K under 20
willrrulewillr(14) > -20
Williams %R above −20
ccirulecci(20) > 100
CCI above 100
up_tomorrowforecastWill the stock be up tomorrow?
Up tomorrow

Answers

QuestionAnswerReading
k_over_d
stochastic %K above %D
0.3746false
k_low
Stochastic %K under 20
0.1754false
willr
Williams %R above −20
0.0666false
cci
CCI above 100
0.0724false
up_tomorrow
Up tomorrow
0.52853% · close to even

What it means

For AMD on the session of 2026-10-30: Not true: stochastic %K above %D; Stochastic %K under 20; Williams %R above −20; CCI above 100. Forecasts: Up tomorrow 53%.

Oscillator states come back as exact rules; the next-day forecast is the label the classifier is compared with.

Request JSON
{
  "model": "ora-fin-0.1.1",
  "state": {
    "symbol": "AMD"
  },
  "questions": {
    "k_over_d": {
      "type": "yes_no",
      "ask": "stochk(14) > stochd(14)"
    },
    "k_low": {
      "type": "yes_no",
      "ask": "stochk(14) < 20"
    },
    "willr": {
      "type": "yes_no",
      "ask": "willr(14) > -20"
    },
    "cci": {
      "type": "yes_no",
      "ask": "cci(20) > 100"
    },
    "up_tomorrow": {
      "type": "yes_no",
      "instructions": "Will the stock be up tomorrow?"
    }
  }
}
Response JSON (AMD, real)
{
  "model": "ora-fin-0.1.1",
  "answers": {
    "k_over_d": {
      "yes_no": 0.3746,
      "rule": "stochk(14) > stochd(14)",
      "basis": "rule"
    },
    "k_low": {
      "yes_no": 0.1754,
      "rule": "stochk(14) < 20",
      "basis": "rule"
    },
    "willr": {
      "yes_no": 0.0666,
      "rule": "willr(14) > -20",
      "basis": "rule"
    },
    "cci": {
      "yes_no": 0.0724,
      "rule": "cci(20) > 100",
      "basis": "rule"
    },
    "up_tomorrow": {
      "yes_no": 0.528
    }
  },
  "context": {
    "symbol": "AMD",
    "as_of": "2026-10-30"
  }
}

cci stochd stochk willr

Quant developer · example 9

Earnings blackout flag for NVDA in a trading pipeline

Block new entries when a report is close, using the earnings calendar facts instead of a separate data feed.

ora-fin-0.1.1NVDA4 questions2 actions
  1. StateNVDA
  2. Questions4 asked
  3. Answersreal, captured
  4. Actions2 rules · dry run

State

{"symbol":"NVDA"} The server fills in the latest completed session.

Questions

earn_soonruledays_to_earnings <= 7
earnings within 7 days
just_reportedruledays_since_earnings <= 5
Reported in the last 5 days
amcEnglish → ruleDoes the stock report after the close next time?
big_moverruleabs(last_earnings_move) > 5
Last earnings move bigger than 5%

Answers

QuestionAnswerReading
earn_soon
earnings within 7 days
0.0537false
just_reported
Reported in the last 5 days
0.0537false
amc
Does the stock report after the close next time
compiled to next_report_amc > 0.5
0.8591true
big_mover
Last earnings move bigger than 5%
0.9463true

Actions

Rules on the answers decide what to send.

earn_soon >= 0.6→Webhookrisk-gate
else→Webhookrisk-gate
What each action would send 1 of 2 fired · dry run, nothing sent
blackoutrule false: skipped
clearwould send (dry run)Webhook → risk-gate
{
  "symbol": "NVDA",
  "gate": "clear",
  "as_of": "2026-10-30"
}

What it means

For NVDA on the session of 2026-10-30: True now: Does the stock report after the close next time; Last earnings move bigger than 5%. Not true: earnings within 7 days; Reported in the last 5 days. Fired: clear (Webhook → risk-gate).

The gate service gets a blackout or a clear for each symbol; strategies read the gate rather than the calendar.

Request JSON
{
  "model": "ora-fin-0.1.1",
  "state": {
    "symbol": "NVDA"
  },
  "questions": {
    "earn_soon": {
      "type": "yes_no",
      "ask": "days_to_earnings <= 7"
    },
    "just_reported": {
      "type": "yes_no",
      "ask": "days_since_earnings <= 5"
    },
    "amc": {
      "type": "yes_no",
      "instructions": "Does the stock report after the close next time?"
    },
    "big_mover": {
      "type": "yes_no",
      "ask": "abs(last_earnings_move) > 5"
    }
  },
  "actions": [
    {
      "id": "blackout",
      "when": "earn_soon >= 0.6",
      "do": "webhook",
      "connection": "risk-gate",
      "body": {
        "symbol": "{{symbol}}",
        "gate": "earnings_blackout",
        "p_earn_soon": "{{earn_soon}}",
        "p_big_mover": "{{big_mover}}",
        "as_of": "{{as_of}}"
      }
    },
    {
      "id": "clear",
      "when": "else",
      "do": "webhook",
      "connection": "risk-gate",
      "body": {
        "symbol": "{{symbol}}",
        "gate": "clear",
        "as_of": "{{as_of}}"
      }
    }
  ],
  "dry_run": true
}
Response JSON (NVDA, real)
{
  "model": "ora-fin-0.1.1",
  "answers": {
    "earn_soon": {
      "yes_no": 0.0537,
      "rule": "days_to_earnings <= 7",
      "basis": "rule"
    },
    "just_reported": {
      "yes_no": 0.0537,
      "rule": "days_since_earnings <= 5",
      "basis": "rule"
    },
    "amc": {
      "yes_no": 0.8591,
      "rule": "next_report_amc > 0.5",
      "basis": "pattern"
    },
    "big_mover": {
      "yes_no": 0.9463,
      "rule": "abs(last_earnings_move) > 5",
      "basis": "rule"
    }
  },
  "context": {
    "symbol": "NVDA",
    "as_of": "2026-10-30"
  },
  "actions": [
    {
      "id": "blackout",
      "fired": false,
      "status": "skipped"
    },
    {
      "id": "clear",
      "fired": true,
      "status": "dry_run",
      "do": "webhook",
      "connection": "risk-gate",
      "preview": {
        "body": {
          "symbol": "NVDA",
          "gate": "clear",
          "as_of": "2026-10-30"
        }
      }
    }
  ]
}

abs days_since_earnings days_to_earnings last_earnings_move next_report_amc

Quant developer · example 10

How long since GE last broke out? Timing features with barssince

Measure time-since-event features (breakout, 52-week high, volume spike) for a holding-period model.

ora-fin-0.1.1GE4 questions
  1. StateGE
  2. Questions4 asked
  3. Answersreal, captured
  4. Actionsnone

State

{"symbol":"GE"} The server fills in the latest completed session.

Questions

quietrulebarssince(C > highest(C, 20)) > 30
No 20-day breakout for 30 sessions
recent_highrulehighestbars(H, 50) <= 5
the 50-day high was set in the last 5 sessions
old_lowrulelowestbars(L, 50) >= 30
the 50-day low is at least 30 sessions old
since_spikerulebarssince(V > 2 * avg(V, 20)) < 10
a volume spike within the last 10 sessions

Answers

QuestionAnswerReading
quiet
No 20-day breakout for 30 sessions
0.9237true
recent_high
the 50-day high was set in the last 5 sessions
0.0563false
old_low
the 50-day low is at least 30 sessions old
0.1019false
since_spike
a volume spike within the last 10 sessions
0.534on the line (true)

What it means

For GE on the session of 2026-10-30: True now: No 20-day breakout for 30 sessions. Not true: the 50-day high was set in the last 5 sessions; the 50-day low is at least 30 sessions old. On the line: a volume spike within the last 10 sessions.

Bar-count rules turn event timing into features; a recent high with an old low describes a stock trending away from its base.

Request JSON
{
  "model": "ora-fin-0.1.1",
  "state": {
    "symbol": "GE"
  },
  "questions": {
    "quiet": {
      "type": "yes_no",
      "ask": "barssince(C > highest(C, 20)) > 30"
    },
    "recent_high": {
      "type": "yes_no",
      "ask": "highestbars(H, 50) <= 5"
    },
    "old_low": {
      "type": "yes_no",
      "ask": "lowestbars(L, 50) >= 30"
    },
    "since_spike": {
      "type": "yes_no",
      "ask": "barssince(V > 2 * avg(V, 20)) < 10"
    }
  }
}
Response JSON (GE, real)
{
  "model": "ora-fin-0.1.1",
  "answers": {
    "quiet": {
      "yes_no": 0.9237,
      "rule": "barssince(C > highest(C, 20)) > 30",
      "basis": "rule"
    },
    "recent_high": {
      "yes_no": 0.0563,
      "rule": "highestbars(H, 50) <= 5",
      "basis": "rule"
    },
    "old_low": {
      "yes_no": 0.1019,
      "rule": "lowestbars(L, 50) >= 30",
      "basis": "rule"
    },
    "since_spike": {
      "yes_no": 0.534,
      "rule": "barssince(V > 2 * avg(V, 20)) < 10",
      "basis": "rule"
    }
  },
  "context": {
    "symbol": "GE",
    "as_of": "2026-10-30"
  }
}

avg barssince highest highestbars lowestbars

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: Fintech app builder, Robo-advisor, Broker app, Algo / bot developer, Data vendor / platform, Trading educator / newsletter.

Create an account Open the Playground Everything here also lives in the console, next to your keys and usage.