Feature Definition Query
GET /api/indicators/signals returns feature definitions grouped by indicator: available features, judgment rules, meanings and validity requirements. It does not return current observations for a symbol or trading recommendations.
Base URL: https://api.mobiusquant.ai. The usual optional Bearer token and API rate limits apply. An administrator account is not required.
Requests
# All indicators, including those without independent features and their reasons
curl 'https://api.mobiusquant.ai/api/indicators/signals'
# All MACD features
curl 'https://api.mobiusquant.ai/api/indicators/signals?indicator=macd'
# MACD events, excluding ongoing states
curl 'https://api.mobiusquant.ai/api/indicators/signals?indicator=macd&kind=event'
# One feature definition
curl 'https://api.mobiusquant.ai/api/indicators/signals?id=macd.cross_up'| Parameter | Type | Required | Meaning |
|---|---|---|---|
indicator | string | No | Exact indicator name, as in calc[].name, e.g. macd; omit for all indicators |
kind | event / state | No | Filter by events or states; omit for both |
id | string | No | Full feature ID, e.g. macd.cross_up |
Names and IDs are case-sensitive, with no fuzzy matching. Filters combine with AND. When both indicator and id are supplied, the ID must belong to that indicator.
- Without
kindorid, indicators without features remain present with a reason andsignals: []. - With
kindorid, only groups containing matching features are returned. - A valid query with no matches returns
200with{"count":0,"signal_count":0,"indicators":{}}, for exampleindicator=cvd&kind=state. - An empty string is not an omitted parameter; empty values return
422.
Response
For ?id=macd.cross_up:
{
"count": 1,
"signal_count": 1,
"indicators": {
"macd": {
"has_signals": true,
"signal_status": "supported",
"signal_reason": "",
"signals": [
{
"id": "macd.cross_up",
"label": "MACD 金叉",
"kind": "event",
"description": "前根 MACD <= Signal,本根 MACD > Signal。",
"meaning": "MACD 相对信号线或零轴的动量关系;事件只在交叉根出现,状态可持续,不是买卖指令。",
"required_history": "max(fast, slow) + signal 根连续有效输入",
"version": 1,
"details": [],
"supports_forming": true
}
]
}
}
}Group fields
| Field | Meaning |
|---|---|
count | Number of indicator groups returned after filtering |
signal_count | Number of feature definitions returned after filtering |
indicators | Object keyed by indicator name; read by key, not position |
has_signals | Whether the indicator provides feature output, not whether current data is ready |
signal_status | supported: features available; none: no independent features; unreviewed: no feature decision yet |
signal_reason | Reason for no feature output; empty string for supported indicators |
signals | Matching definitions, not calculated values; empty array when no features exist |
Do not equate none with unreviewed, or interpret an empty type-filtered result as evidence that an indicator has no features of any kind.
Feature fields
| Field | Type | Meaning |
|---|---|---|
id | string | Stable feature ID; matches calculated column names and chart marker signal_ids |
label | string | Display name |
kind | string | event: occurs on one bar; state: evaluated per bar and may persist |
description | string | Judgment rule using the actual calculation request's parameters |
meaning | string | Interpretation of the feature |
required_history | string | History and validity requirements; may contain parameter formulas, not a fixed integer |
version | integer | Version of this feature definition |
details | string[] | Additional boundaries or confirmation requirements; empty when none |
supports_forming | boolean | Supports include_forming: true final-sample trials; not a data-readiness guarantee |
Names and explanatory text are currently Chinese; IDs and enums are language-independent. Get calculation parameters, defaults and indicator interval constraints from GET /api/indicators/registry. GET /api/indicators/registry?include_signals=true remains available for compact definitions.
Using definitions with calculation and charts
- Query this endpoint to select features by
indicatorandid. - Send a calculation request to
/api/indicatorsor/api/indicators/computewith top-level"signals": true. - Locate the definition's
idinindicators[response_key].signals.columnsand read that column indata.
For charts, send "signals": true to /api/chart. Feature tables are in indicator_signals[response_key]. Event markers expose signal_ids that join to this directory for names, rules and meanings. States do not generate per-bar event markers. When using multiple parameter sets for the same indicator, identify instances by response key / indicator_key; feature IDs do not change with parameters. The directory's query parameter id is a feature ID, not the caller-defined calculation calc[].id.
Definition availability does not imply that data can be evaluated:
| Calculated value | Meaning |
|---|---|
true | Event occurred or state holds on a closed candle |
false | Valid evaluation, but event did not occur or state does not hold |
null | Unknown: forming candle, insufficient history, invalid dependencies or input gaps |
Live features support the connected Binance, Bybit, OKX and Hyperliquid feeds, including Binance stock perpetuals, but not stock spot venues. BYO requires an explicit interval and continuous, fixed-duration candles, subject to each selected indicator's constraints. Set last_bar_closed: false for a forming last candle. After an interval gap or invalid OHLCV, subsequent features in that input are null. Feature open_time and confirmed_at_ms use milliseconds; chart marker time uses seconds. A confirmation time does not imply that an event occurred. Indicators without feature capability return the entire signals: null in calculation results, unlike the directory's signals: [].
See native feature calculation and feature charting for examples.
Forming-candle trials
Set top-level signals: true and include_forming: true on /api/indicators, /api/indicators/compute or /api/chart. include_forming defaults to false and accepts only a JSON boolean. Using it without signals: true returns 422.
curl -X POST 'https://api.mobiusquant.ai/api/indicators?explain=false' \
-H 'Content-Type: application/json' \
-d '{"exchange":"binance","market":"perp","symbol":"BTCUSDT","interval":"5m","limit":2,"signals":true,"include_forming":true,"calc":[{"name":"macd","id":"m"}]}'The engine treats the current actual OHLCV of the final forming candle as a complete sample for this calculation. It does not predict the final close or invent future candles. History, continuity, native thresholds, structural windows and model confirmation requirements are unchanged. Crossings compare adjacent candles, not consecutive requests. Repeating a request does not increase confirmation counts or deduplicate features.
There is one result: indicators[key].signals for calculation and indicator_signals[key] for charting. The table appends bar_status after the existing feature columns; always read columns by name:
| bar_status | Meaning | confirmed_at_ms |
|---|---|---|
closed | Closed-bar calculation | Existing interval-based close timestamp |
forming | Current snapshot trial of the final forming bar | Always null |
true means the condition currently holds and can support an intrabar warning; false means it does not hold; null still means dependencies are insufficient or invalid. A trial may disappear on the next update or at close. It is not a confirmed event. Values, features, reasons and native objects come from the same calculation. For example, confirmed in a CVD feature ID is not proof of closure: read bar_status and the object's status. Trial CVD results use objects.schema_version=2, with status=forming and confirmed_at_ms=null for provisional divergences.
BYO callers must still supply last_bar_closed: false and interval. Historical intrabar snapshots are allowed; all preceding bars must be closed. Fully closed input returns only closed rows. Live latest requests without the current forming candle return 503 with Retry-After. Explicit historical windows never relabel a previous candle as forming. The option does not provide intrabar snapshot replay or an additional source-finality guarantee; calculation.as_of_ms is not the upstream observation time.
Chart event markers carry the same bar_status, with null confirmation times for trials; no new color rules or special drawing primitives are added. Existing include options still work. Trial calculation metadata adds include_forming=true and signal_evaluation_version=1. Data-free definitions expose limits.live_features.supports_forming, consistent with the feature directory. Unsupported forming features are null, with forming_not_supported when reasons are requested. Indicators without native features still return signals: null.
Omitting or disabling include_forming preserves the original numeric/object/feature/chart behavior and omits the bar_status column. Alert storage, intrabar-to-close correlation, notifications, deduplication and cooldown remain consumer responsibilities.
Optional calculation information
Calculation and chart requests accept an optional top-level include array:
{
"exchange": "binance",
"market": "perp",
"symbol": "BTCUSDT",
"interval": "5m",
"limit": 100,
"calc": [{"name": "macd"}, {"name": "cvd"}, {"name": "hmm_regime"}],
"signals": true,
"include": ["signal_reasons", "signal_details", "calculation", "definition"]
}Use this body with /api/indicators?explain=false or /api/chart. BYO accepts the same options. Omitting include, or passing [], preserves the existing response. Unknown or duplicate options return 422. signal_reasons and signal_details require signals: true; calculation and definition work independently. Indicators without features still return signals: null.
| Option | Calculation response | Chart response |
|---|---|---|
signal_reasons | indicators[key].signals.invalid_reasons | indicator_signals[key].invalid_reasons |
signal_details | indicators[key].signals.details | indicator_signals[key].details |
calculation | indicators[key].calculation | indicator_calculations[key] |
definition | indicators[key].definition | indicator_definitions[key] |
Reasons for unknown features
invalid_reasons uses {columns, data}. The first column is open_time in milliseconds; the remaining columns are feature IDs. Only rows containing at least one unknown feature are included. Unknown cells contain arrays of reason codes; valid cells contain null, meaning no invalidity reason. Read the actual three-state result from signals.data, not from this explanation table. When all features are valid, the explanation table has an empty data array.
| Code | Meaning |
|---|---|
bar_not_closed | A required bar has not closed |
insufficient_history | More history or a previous valid observation is required |
input_gap | A gap in this calculation's input affects the observation |
invalid_input | Invalid OHLCV in this input affects the observation |
invalid_dependency | Required values, volume conditions or native objects are unavailable |
state_unavailable | No required valid direction or state exists |
not_applicable | A native prerequisite is not met, such as testing support restoration across different HMM directions |
Reasons are per feature and per bar. Multiple reasons may apply, including problems with the previous bar for crossing events. Existing booleans and nulls do not change. BYO NaN/inf inputs are still rejected; enabling explanations does not relax input validation.
Native value and object links
details.bindings is keyed by feature ID:
values[]: afieldandoffset(0for the feature bar,-1for the previous input bar).objects:collection,match,id_field,fieldsand responsecontainer. Charts also supply the actualobject_key; do not assume it equals the indicator name.context:{columns, data}, supplying only necessary native value rows not otherwise available in this response. Timestamps remain milliseconds.
Explicit bindings currently cover MACD, RSI, CVD and HMM. Other indicators return empty bindings and context when no property links are declared; this does not change their feature support.
CVD matches the same instance's objects.divergences by confirmation_bar_time_ms = feature open_time and direction. Read the existing object ID, strength, endpoints and confirmation time. Charts use indicator_objects[object_key].divergences. Strength is not duplicated. An object ID is a result link, not a notification deduplication guarantee.
HMM transitions link previous/current hmm_state or hmm_context_state; support events also link hmm_supported. Raw responses reuse returned rows and add a clipped previous row to context when needed. Charts lack a complete numeric table, so context supplies fields needed for true events/states. These values come from the same calculation, not a second request.
Calculation metadata
Each indicator instance returns:
algorithm_version: indicator algorithm version, not deployment version.effective_params: supplied parameters plus applied defaults.resolved: effective automatic choices, such as HMM normalizationd1orlegacy.signal_versions: feature ID to definition version; empty for indicators without features.inputandoutput: actual calculation history and returned window, each withstart_open_time_ms,end_open_time_msandbars. Endpoints are bar open times in milliseconds; empty ranges have null endpoints and zero bars.interval_ms,as_of_ms,last_bar_closed: input duration, live evaluation cutoff and input last-bar closure. BYO normally has a null cutoff and uses the caller's closure assertion.
An input range does not guarantee continuity, sufficient warmup or immutable market data. Parameters, versions and ranges alone cannot guarantee reproducibility after historical revisions. Version storage, change detection and migration belong to the consumer.
Structured indicator definitions
GET /api/indicators/registry?include_schema=trueEach indicator gains a definition with parameters, output fields, restrictions, algorithm/feature versions, effective defaults, resolved choices and native value bindings. No candles are read. For parameter-dependent fields, use:
POST /api/indicators/registry/resolve
Content-Type: application/json{
"interval": "4h",
"calc": [
{"name": "ema", "params": {"period": 50}, "id": "ema50"},
{"name": "hmm_regime", "id": "hmm"}
]
}The response is {count, indicators}, keyed by calculation instance keys. EMA resolves to ema_50; HMM resolves to Legacy normalization. No candles are required. interval is optional; omitting it leaves interval-dependent choices unresolved. calc supports up to 100 entries.
parameters: declared type, default, required/nullable flags and explicitconstraints.validation=nativepreserves original indicator validation.parameter_constraints_complete=false: constraints are not exhaustive. Empty constraints do not mean arbitrary values are accepted. Successful resolution does not guarantee arbitrary candle inputs can be calculated successfully.outputs[]: resolvedname/type/nullable/unit, optional bounds, descriptions and enum meanings. Do not hard-code default parameter-dependent column names.- Units:
pricefollows input prices,input_volumefollows input volume,unix_msis milliseconds,categoryis an enum, andmodel_weightis not a calibrated probability. limits: intervals, live intervals, asset classes, volume requirements, unsupported venues and live-feature markets. Null interval/asset lists add no indicator-specific restriction; still check actual venue availability through/api/marketsand/api/intervals.signal_value_bindings: data-free native links. Actual chart object keys are in the current response'ssignals.details.
These options do not define monitoring rules, polling progress, notifications or trade recommendations.
Errors
| HTTP status | Cause | Action |
|---|---|---|
400 | Unknown indicator/feature ID, or indicator and ID ownership mismatch | Read detail and correct the query |
422 | Invalid kind, empty parameter or excessive length | Maximum lengths: 128 for indicator, 200 for id; use documented enum values |
401 | Invalid, expired or revoked supplied token | Correct the token; do not silently retry anonymously |
429 | API rate limit exceeded | Respect Retry-After; do not reload definitions for every candle |
405 | POST, PUT, PATCH or DELETE | Use GET; this endpoint is read-only |
Field types and query parameters are also available through OpenAPI.