Grammar
Generated from the contract: research_query.v2 · feature_defs.v1 · 33 features. Also machine-readable at GET /api/v1/research/registry.
Document shape
{
"schema_version": "research_query.v2",
"normalization_version": "archive_normalization.v1",
"feature_version": "feature_defs.v1",
"target": "record_occurrences",
"where": { "all": [ [field, operator, value], ... ] },
"sequence": { "steps": [ { "all": [...] }, ... ], "within": "30m" }, // optional
"sort": ["times.anchor_time", "asc" | "desc"],
"page": { "limit": 1..50, "cursor": null | "opaque" }
}Clauses are conjunctive triples. Validation is fail-closed against closed registries: unknown fields, operators or values are named errors, never guesses. At least one times.anchor_time bound is required (the scan window).
Features (33)
| ID | DTYPE | RANGE / VALUES |
|---|---|---|
feature.vpin | number | 0 .. 1 |
feature.vpin_regime | enum | normal · elevated · high · critical |
feature.book_imbalance | number | -1 .. 1 |
feature.book_imbalance_pctrank | number | 0 .. 1 |
feature.spread_norm | number | 0 .. 1 |
feature.funding_rate | number | -0.05 .. 0.05 |
feature.funding_norm | number | 0 .. 1 |
feature.oi_velocity_pctrank | number | 0 .. 1 |
feature.liq_intensity_norm | number | 0 .. 1 |
feature.cascade_clustering_index | number | 0 .. 1 |
feature.liq_notional_usd_1h | number | 0 .. 1000000000000000 |
feature.top_trader_long_ratio | number | 0 .. 1 |
feature.global_long_ratio | number | 0 .. 1 |
feature.top_global_long_skew | number | -1 .. 1 |
feature.ret_15m | number | -1 .. 5 |
feature.ret_1h | number | -1 .. 5 |
feature.range_pct_1h | number | 0 .. 5 |
feature.realized_vol_1h | number | 0 .. 1 |
feature.realized_vol_pctrank | number | 0 .. 1 |
feature.vwap_dist | number | -1 .. 5 |
feature.taker_buy_ratio_15m | number | 0 .. 1 |
feature.large_trade_share_15m | number | 0 .. 1 |
feature.mins_to_funding | number | 0 .. 480 |
feature.candle_body_15m | number | -1 .. 1 |
feature.candle_upper_wick_15m | number | 0 .. 1 |
feature.candle_lower_wick_15m | number | 0 .. 1 |
feature.candle_compression_15m | number | 0 .. 10 |
feature.candle_engulfing_15m | enum | none · bullish · bearish |
feature.candle_sweep_reclaim_15m | enum | none · bullish · bearish |
feature.candle_containment_15m | enum | none · inside · outside |
feature.candle_body_1h | number | -1 .. 1 |
feature.candle_engulfing_1h | enum | none · bullish · bearish |
feature.candle_sweep_reclaim_1h | enum | none · bullish · bearish |
Operators
| FIELD KIND | OPERATORS |
|---|---|
| numeric features + windows | gte lte between |
| enum features | eq in |
| identity.symbol / identity.exchange | eq in |
| times.anchor_time | gte lte between |
Windows
Numeric features may be windowed: window.<feature>.<agg>_<duration>, e.g. window.book_imbalance.mean_15m. Closed lists:
| AGGREGATES | DURATIONS |
|---|---|
| min · max · mean · last · delta | 5m · 15m · 30m · 1h · 4h |
Sequences
2-4 steps, each 1-6 clauses over feature.* / window.* only, bound by within. Write the document form; the engine speaks the ISO form on the wire (translated for you):
| DOCUMENT FORM | WIRE FORM |
|---|---|
15m | PT15M |
30m | PT30M |
1h | PT1H |
4h | PT4H |
12h | PT12H |
24h | PT24H |
Limits
| LIMIT | VALUE |
|---|---|
| clauses (where + all steps) | 16 |
| values across all clauses | 50 |
| page limit | 50 |
Error codes
Validation failures answer 422 {"errors":[{code, message}]} with these codes, VERBATIM - the same set the app validator and the engine speak:
INVALID_SHAPE UNSUPPORTED_FIELD UNSUPPORTED_OPERATOR INVALID_VALUE QUERY_LIMIT UNSUPPORTED_TARGET TARGET_FIELD_MISMATCH UNSUPPORTED_FEATURE INVALID_SEQUENCE OUTCOME_IN_PREDICATE INVALID_CURSOR STALE_CURSOR PREVALENCE_SCOPE_UNSUPPORTED
Transport codes ride the {"error", "code"} envelope:
AUTH_REQUIRED KEY_INVALID KEY_REVOKED SCOPE_MISSING RATE_LIMITED INSUFFICIENT_CREDITS CREDITS_UNAVAILABLE SCAN_BUSY SCAN_TIMEOUT ENGINE_UNREACHABLE ENGINE_UNCONFIGURED TOKENS_UNCONFIGURED INTERPRETER_UNCONFIGURED FEATURE_DISABLED CURSOR_UNAVAILABLE
The honesty rule
Outcome fields (outcome.*) are computed forward from each anchor and can NEVER be filtered: asking answers OUTCOME_IN_PREDICATE. To study "setup then move", state the move as a sequence step (example 1) - the anchor becomes the completion, and rates come from outcomes_summary over ALL occurrences.