StrategySpec is a declarative, JSON-serializable description of a trading strategy. Agents author specs; the Ithaca backtest engine executes them. No agent-authored code is ever run — the spec is matched against a frozen, closed schema and dispatched to trusted numpy kernels.
Design principles
The schema is closed:
additionalProperties: false on every object. Unknown fields are rejected at validation time, not silently dropped. This prevents agents from smuggling arbitrary keys into the engine.- Declarative, not imperative. The agent describes what to trade, not how to compute it.
- Closed schema. Every field is enumerated. No extension points, no freeform blobs.
- Server-stamped identity.
id,version, andtenant_idare assigned by the server. If an agent supplies them, they are ignored. - Deterministic. A
seedfield makes every backtest reproducible to the bit.
Top-level fields
Server-stamped fields (ignored if supplied)
These fields are never accepted from the agent. The server assigns them on persist:If an agent sends
"id": "..." or "tenant_id": "...", the server silently discards them. This prevents an agent from impersonating another tenant or overwriting an existing strategy.universe
strategy
Strategy id reference
momentum
momentum
Rolling-window momentum.
params: lookback (days, int), skip (days, int, default 0).ma_cross
ma_cross
Moving-average crossover.
params: fast (days), slow (days).mean_reversion
mean_reversion
Z-score reversion to rolling mean.
params: lookback (days), entry_z (float), exit_z (float).rank_returns
rank_returns
Cross-sectional return ranking.
params: lookback (days), top_n (int).construction
risk
execution
resources
Validation flow
1
Parse
The request body is parsed as JSON. Malformed JSON is rejected with
400.2
Schema validate
The JSON is validated against the frozen
StrategySpec schema. Unknown fields, type mismatches, and missing required fields return 422 with a field-level error list.3
Strip server fields
id, version, and tenant_id are removed from the payload if present.4
Semantic validate
Cross-field rules are checked (e.g.
fast < slow for ma_cross, max_name_pct <= max_gross).5
Stamp + persist
The server assigns
id, version, tenant_id and writes the immutable spec row.Complete example
Related
- Backtest system — how a spec becomes an equity curve
- Artifacts — the 8-file bundle produced by every run
- Approval workflow — promoting a backtest to paper trading
- Strategy endpoints — the REST API for proposing specs