Run a backtest
This how-to walks you through the tastytrade options backtester: submit a backtest definition, poll the backtest by id until it finishes, then read the resulting statistics, trials, and snapshots.
This guide assumes you already have an access token. If not, see Get started. The backtester is its own service on its own host: all examples use https://backtester.vast.tastyworks.com — the server published in its OpenAPI spec — not the main api.tastyworks.com gateway, and there is no separate cert/sandbox instance. Authentication works the same way as the rest of the API: send your token in the Authorization header (the backtester validates it against tastytrade's auth service). Unlike the core API, responses are plain JSON objects with camelCase keys (for example startDate) — there is no data/context envelope. For the complete operation, parameter, and schema reference, see /reference/backtesting.
Before you start
- A 15-minute OAuth access token from
POST /oauth/token. - A
User-Agent: product/versionheader — required across the tastytrade API, so send it here too. - A backtest definition: an underlying
symbol, astartDate/endDaterange, and one or morelegs.
To confirm a symbol has history for your date range, call GET /available-dates, which returns each available symbol with its startDate and endDate.
1. Build the backtest request
A backtest defines a strategy over a historical window. Each entry in legs describes one position. The required leg fields are type, direction, quantity, strikeSelection, and daysUntilExpiration. For an equity-option leg also set side (call or put).
strikeSelection decides which strike is chosen, and the value you supply depends on it. For example, with "strikeSelection": "delta" you provide a numeric delta (the 16-delta short put in the example below). Other modes include percentageOTM, currentPriceOffset, and premium. Optional entryConditions and exitConditions control when trials open and close.
Here is a short-put strategy on SPY, selling the 16-delta put 45 days out, entered every day, with a 50% take-profit:
{
"symbol": "SPY",
"startDate": "2022-01-01",
"endDate": "2022-12-31",
"legs": [
{
"type": "equity-option",
"direction": "short",
"side": "put",
"quantity": 1,
"strikeSelection": "delta",
"delta": 16,
"daysUntilExpiration": 45
}
],
"entryConditions": {
"frequency": "every day"
},
"exitConditions": {
"takeProfitPercentage": 50
}
}
2. Submit the backtest
POST the definition to /backtests.
curl -X POST "https://backtester.vast.tastyworks.com/backtests" \
-H "Authorization: Bearer <access-token>" \
-H "User-Agent: my-app/1.0.0" \
-H "Content-Type: application/json" \
-d @backtest.json
The response is a backtest object. A 201 means the backtest is pending and still running; a 200 means it is already ready. Either way the body includes an id you use to poll. A malformed body returns 400; see /reference/errors.
3. Poll for completion
Fetch the backtest by id and watch its status, which moves through pending, running, and completed:
curl "https://backtester.vast.tastyworks.com/backtests/{id}" \
-H "Authorization: Bearer <access-token>" \
-H "User-Agent: my-app/1.0.0"
While it runs, the object reports progress and an ETA you can use to space out polls. An unknown id returns 404. Poll on an interval rather than tightly looping, and on 429 back off per Rate limits & backoff.
4. Read the results
Once status is completed, read these fields from the backtest object:
| Field | What it contains |
|---|---|
statistics | Aggregate performance metrics for the run. |
trials | Each simulated trade, with openDateTime, closeDateTime, and profitLoss. |
snapshots | Time series of profitLoss and underlyingPrice at each dateTime. |
notices | Conditional annotations (for example, overlapping ranges due to a stock split). |
For step-by-step execution detail, fetch GET /backtests/{id}/logs. To stop a long run early, POST /backtests/{id}/cancel (returns 204). To list your existing backtests, GET /backtests returns an array of ids.
Try a single trade first
To check historical pricing for one trade without defining a full backtest, POST /simulate-trade with an underlying and legs (each leg uses tastytrade/OCC symbology). It returns a series of dateTime, price, effect (debit/credit), underlyingPrice, and delta points.
Next steps
- Browse every operation and schema at /reference/backtesting.
- Explore all endpoints in the API reference.
- Handle failures with Idempotency & retries and Rate limits & backoff.