Compute on Your Own Data
POST /api/indicators/compute lets you run the engine's 60+ indicator pipelines against klines you supply yourself — independent of the engine's in-memory cache, not bound to any venue or symbol.
Good for:
- Backtest: run indicators over OHLCV history pulled from your DB / CSV
- Custom data sources: counterparty exchange, aggregated contracts, your own tick resamples
- Offline analysis: validate indicator values for a specific window without being constrained by what the engine has cached
Not for:
- Live data — use
POST /api/indicatorsfor lower latency, it reads from in-memory store - Multi-timeframe (MTF) indicators like SMC's
fvg_timeframe— those need server-side prefetch of multiple timeframes; only the store-backed path supports them
30-second quickstart
curl -X POST 'https://api.mobiusquant.ai/api/indicators/compute' \
-H 'authorization: Bearer mq_xxx' \
-H 'content-type: application/json' \
-d '{
"klines": [
[1735689600000, 95000.0, 95500.0, 94800.0, 95200.0, 1234.5],
[1735693200000, 95200.0, 95800.0, 95100.0, 95650.0, 1500.2]
],
"interval": "1h",
"calc": [{"name": "rsi", "params": {"period": 14}}]
}'Returns:
{
"count": 2,
"interval": "1h",
"klines": [[1735689600000, 95000.0, ...], ...], // echoed
"indicators": {
"rsi:period=14": {
"columns": ["open_time", "rsi"],
"data": [[1735689600000, null], [1735693200000, null]],
"explain": { /* knowledge: summary_focus / signals / caveats */ }
}
}
}RSI returns
nullfor the first 14 bars — this is normal. All cumulative indicators need warmup. See Limits below.
Python example
import requests
import pandas as pd
# Load historical OHLCV from your own data source
df = pd.read_csv('btc_1h_history.csv') # columns: open_time(ms), open, high, low, close, volume
klines = df[['open_time', 'open', 'high', 'low', 'close', 'volume']].values.tolist()
resp = requests.post(
'https://api.mobiusquant.ai/api/indicators/compute',
headers={'Authorization': 'Bearer mq_xxx'},
json={
'klines': klines,
'interval': '1h',
'calc': [
{'name': 'ema', 'params': {'period': 20}, 'id': 'ema20'},
{'name': 'ema', 'params': {'period': 200}, 'id': 'ema200'},
{'name': 'rsi', 'params': {'period': 14}},
],
},
)
result = resp.json()
print(result['indicators']['ema20']['data'][-1]) # latest EMA20 value
print(result['indicators']['rsi:period=14']['data'][-1])SMC and other "composite" indicators work too
Indicators like SMC (Smart Money Concepts) that produce non-numeric output also return per-bar columns + an objects sidecar:
curl -X POST 'https://api.mobiusquant.ai/api/indicators/compute?explain=false' \
-H 'content-type: application/json' \
-d '{
"klines": [/* ≥500 historical bars */],
"calc": [{"id": "smc", "name": "smc",
"params": {"show_swing_points": true, "show_premium_discount_zones": true}}]
}'The response includes indicators.smc.objects with structured shapes — swing_structures, order_blocks_swing, fair_value_gaps, premium_zone, etc. Feed them straight into a chart renderer or an LLM. See SMC indicator page.
Request schema
| Field | Type | Required | Description |
|---|---|---|---|
klines | array | ✓ | OHLCV bars; each row auto-detected as either list or object (see below) |
calc | array | ✓ | Indicators to compute, each {name, params, id?} — same shape as /api/indicators |
interval | string | ✗ | Metadata only, echoed back; some MTF indicators ignore it |
echo_klines | bool | ✗ | Default true — echoes input klines; set false to shrink the response |
Two klines row formats (auto-detected):
// Compact (Binance nested-list style): [open_time_ms, open, high, low, close, volume, quote_volume?]
[1735689600000, 95000.0, 95500.0, 94800.0, 95200.0, 1234.5, 117526200.0]
// Object (more explicit)
{
"open_time": 1735689600000,
"open": 95000.0,
"high": 95500.0,
"low": 94800.0,
"close": 95200.0,
"volume": 1234.5,
"quote_volume": 117526200.0 // optional, used by some indicators (VWAP / CVD); defaults to 0
}Response schema
| Field | Type | Description |
|---|---|---|
count | int | Number of klines processed |
interval | string | Echoes request's interval (only when provided) |
klines | array | Echo of input klines (omitted when echo_klines=false) |
indicators | object | key = id or auto-generated name:p1=v1,..., value = single indicator's columns/data/objects/explain |
Each indicators.<key> has the same shape as in POST /api/indicators:
{
"columns": ["open_time", "rsi"],
"data": [[1735689600000, null], [1735693200000, 67.4], ...],
"objects": { /* present only for SMC and other non-numeric indicators */ },
"explain": { /* knowledge: only when ?explain=true */ }
}Limits
| Limit | Value | On violation |
|---|---|---|
| Kline count | ≤ 2000 | 413 |
open_time | strictly monotonically increasing in ms | 400 |
| OHLCV | must be finite (no NaN / inf) | 400 |
calc list | non-empty, all name in registry | 400 |
calc invalid params | Pydantic / signature mismatch | 422 |
Important: no warmup buffer
/api/indicators internally adds 1000 bars of warmup to feed accumulating indicators (EMA / RSI / ATR). /api/indicators/compute does not — it uses exactly the klines you supply.
So make sure you include enough history:
| Indicator / usage | Minimum bars |
|---|---|
| RSI(14) to stabilize | ≥ 50 |
| EMA(200) / ATR(200) to stabilize | ≥ 200 |
| Bollinger / Keltner / Donchian (default params) | ≥ 30 |
| SMC internal structure + FVG | ≥ 50 |
| SMC swing structure / OB / Strong-Weak / P/D zones | ≥ 100 (default swing_size=50, plus buffer) |
| SMC complete + EQH/EQL stable | ≥ 200 (ATR threshold converges) |
| Production-grade analysis | 500+ |
The first N bars returning null is normal — discard them and use the stable tail.
Auth & rate limits
Same as /api/indicators:
- No
Authorizationheader → anonymous IP bucket (low quota) - Valid
Bearer mq_xxx→ token bucket (higher quota) - Don't have a token yet? Apply for one — it's free.
Error codes
| Code | Meaning | What to do |
|---|---|---|
400 | Validation failed (non-monotonic, NaN, unknown indicator, too few columns) | Read detail, fix the request |
401 | Authorization header present but token invalid | Re-apply |
413 | klines exceeds 2000 | Batch, or shorten the window |
422 | Pydantic validation (missing field, wrong type, unknown field) | Check detail.loc |
429 | Rate limited | Honor Retry-After; token bucket has higher quota |
500 | Indicator computation crashed (indicator bug) | Report with the indicator name in detail |
Related
POST /api/indicators— Reads klines from engine cache and computes indicators (faster, but limited to subscribed venues/symbols)GET /api/indicators/registry— All 60+ indicators with parameter signatures- SMC indicator page — Details of the SMC
objectssidecar - AI Agent Manual — Engine integration guide for LLMs
- Skill Runtime Lookup — Endpoint decision tree for Skill integration