Limits and plans
Quotas, what happens at the edge of one, and the error shape every failure uses.
Plans#
| Free | Pro | Team | |
|---|---|---|---|
| Price | $0 | $49/mo | $399/mo |
| Trials per month | 200 | 5,000 | 50,000 |
| Max sweep points per call | 100 | 1,000 | 5,000 |
| Max universe size | 10 | 50 | 200 |
| Holdout evaluations per month | 1 | 10 | 100 |
| Concurrent jobs | 1 | 4 | 16 |
Read the live values rather than this table — the table is generated from the same seed but your account is the authority:
plans()
account_status()
account_status returns trials_used, trials_limit, trials_remaining,
holdouts_limit, max_sweep_points, max_universe_size and
concurrent_jobs for your principal.
Why trials are the metered unit#
A trial is the scarce thing on this server. Every trial permanently raises the bar your own future results must clear — that is what an append-only ledger means. Metering the thing that carries the statistical cost puts the price on the same side as the discipline: a sweep of 2,000 configurations is expensive here because it is expensive to your statistics.
Compute is not the constraint being priced. Overfitting is.
What consumes a trial#
| Call | Trials consumed |
|---|---|
backtest_submit |
1 |
backtest_cross_section |
1, regardless of universe size |
sweep_submit |
one per configuration |
| A spec already evaluated | 0 — deduplicated by hash |
execution_replay_submit |
0 — a replay adds nothing to the ledger |
holdout_evaluate |
0 trials, but consumes the one-shot |
| Every read tool | 0 |
gate_check, experiment_ledger, server_status, account_status,
plans, data_catalog, universe_catalog, library_search, library_get,
case_studies, backtest_result and job_status consume nothing.
At the edge of a quota#
The quota is checked before the work runs, not after. A quota that only bit once trials were already in the ledger would leave the ledger holding trials the caller was told they could not make.
Replays are checked before the quota rather than against it, because a replay adds no trials and must not be billed as though it did.
Error shape#
Every failure a caller could plausibly fix is raised as a structured error, never a stack trace:
{
"error": "quota_exceeded",
"reason": "a sweep of 400 points would exceed the Free monthly trial quota; 187 of 200 used",
"remediation": "reduce max_points to 13 or fewer, or upgrade the plan"
}
error and reason are always present. remediation is present whenever
there is a concrete next action.
error |
Meaning |
|---|---|
not_authenticated |
No bearer token, or one the server does not recognise |
quota_exceeded |
The call would exceed a plan limit; nothing was recorded |
bad_request |
An argument cannot be used; reason says which |
not_found |
No such run, strategy, split, family or universe |
insufficient_data |
The range holds too few bars for this computation |
immutable |
Attempt to modify something registered as fixed, such as split ranges |
holdout_locked |
The holdout is not readable; the strategy is not frozen |
holdout_spent |
This strategy's one holdout evaluation is already used |
strategy_frozen |
Attempt to modify a frozen spec |
not_frozen |
holdout_evaluate called before strategy_freeze |
upstream_error |
A venue API failed; the cost model or candles are unavailable |
quant_error |
Base class; a failure with no more specific code |
Asynchronous work#
backtest_submit, backtest_cross_section, sweep_submit, data_ingest,
data_ingest_universe and execution_replay_submit return a job_id
immediately. Poll job_status.
Nothing returns bulk data. Return series are resources, addressed as
quant://runs/{run_id}/returns, not tool output.
Quota reset#
Trial and holdout quotas are counted per calendar month.
The ledger does not reset. N is monotonic for the life of a family regardless of billing period — a new month buys you more trials, not a lower multiple-testing hurdle. Those are deliberately different things.
Read this page as Markdown:
/docs/limits.md