Simulation API
The /v1/simulation surface is a live, key-gated historical fill and
backtest contract. Without a key it returns 401, not 404 — the endpoints
exist and are serving. FEATURE_SIMULATION_API_ENABLED defaults to true; it
is a kill switch an operator can throw, not an activation step you must wait for.
Live does not mean unlimited. Access is gated on your plan’s
analytics.backtesting entitlement and metered in simulated market-hours, so
a call can still be refused on entitlement or quota rather than on auth. The
volume caps below are plan-matrix numbers. This page does not claim a Telonex
or vendor-validated SKU.
First successful call
simulateFill is the hook: one condition, one timestamp, one memorable
VWAP. Do not start with a backtest.
All money and share fields are decimal strings. Parse with
Decimal, never float.
Nine paths
GET /v1/simulation/book resolves a bounded hour record from Redis or
an adjacent v4 sidecar. It never walks an unbound hours list.
Token identity
Fill and book responses echo the resolved token_id and
comp_token_id. Backtest create accepts an optional token_ids map
(condition_id → token_id). The job stores the resolved map so clients
can verify the exact books that were walked. Exact asset_id matching
is preserved: primary / yes / no never match a real token.
Errors
Every simulation error is a structured /v1 envelope. Branch on
X-Polysim-Code, not the body text. Declared codes include:
INVALID_REQUEST, INVALID_WINDOW, INVALID_CURSOR
UPGRADE_REQUIRED, INSUFFICIENT_PERMISSION, NOT_FOUND
IDEMPOTENCY_KEY_REUSE, IDEMPOTENCY_CONFLICT_PENDING
UNIVERSE_EXCLUDED
BACKTEST_MONTHLY_CAP, BACKTEST_MARKET_CAP, BACKTEST_WINDOW_CAP
SIMULATION_HOURS_EXCEEDED
METERING_UNAVAILABLE, JOB_STORE_UNAVAILABLE (503)
CONDITION_HOUR_NOT_COVERED, ARCHIVE_UNAVAILABLE, ARCHIVE_NOT_FOUND
OpenAPI advertises 503 plus those codes. A missing sidecar next to a
v4 capture object is fail-closed (quarantined), not a fabricated
valid hour.
Volume caps (matrix, not activation)
FEATURE_MATRIX gates volume, not the fill/coverage features:
analytics.backtesting remains false for free/pro. depth_walk_depletion
and signed exports still require dataset.historical_full. Do not treat
these numbers as a live commercial SKU.
A tier’s monthly budget always exceeds one maximum-size backtest
(max_days x 24 x max_markets) by at least 3x — otherwise the plan would
advertise a run it then refuses to meter. backend/tests/test_backtest_ budget_invariant.py asserts that for every tier. unlimited is a real
absence of a limit, not a large number.
SDK
wait() polls get_backtest until completed / failed / cancelled.
It does not enable the flag and does not talk to Telonex.