Create A Backtest
postBacktests/backtestsBase URL: https://backtester.vast.tastyworks.com (Backtester API)
Submits a backtest definition (underlying `symbol`, a `startDate`/`endDate` window, and one or more `legs`) and starts the run. A `201` means the backtest is pending and still running; a `200` means it is already completed. Either way the body includes an `id` to poll with `GET /backtests/{id}`.
Code samples
curl -X POST 'https://backtester.vast.tastyworks.com/backtests' \
-H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
-H 'User-Agent: tastytrade-docs-example/1.0' \
-H 'Content-Type: application/json' \
-d '{
"symbol": "SPY",
"startDate": "2022-01-01",
"endDate": "2022-12-31",
"legs": [
{
"type": "equity-option",
"direction": "short",
"side": "put",
"quantity": 1,
"strikeSelection": "delta",
"strikeRelativeLeg": 0,
"delta": 16,
"percentageOTM": 0.1,
"currentPriceOffset": 5,
"premium": 2.5,
"daysUntilExpiration": 45
}
],
"entryConditions": {
"frequency": "every day",
"specificDays": [
0
],
"maximumActiveTrials": 5,
"maximumActiveTrialsBehavior": "don'\''t enter",
"minimumVIX": 15,
"maximumVIX": 30
},
"exitConditions": {
"takeProfitPercentage": 50,
"stopLossPercentage": 100,
"afterDaysInTrade": 21,
"atDaysToExpiration": 7,
"minimumVIX": 12
}
}'import requests
import json
url = "https://backtester.vast.tastyworks.com/backtests"
headers = {
"Authorization": "Bearer YOUR_ACCESS_TOKEN",
"User-Agent": "tastytrade-docs-example/1.0",
}
payload = json.loads("""
{
"symbol": "SPY",
"startDate": "2022-01-01",
"endDate": "2022-12-31",
"legs": [
{
"type": "equity-option",
"direction": "short",
"side": "put",
"quantity": 1,
"strikeSelection": "delta",
"strikeRelativeLeg": 0,
"delta": 16,
"percentageOTM": 0.1,
"currentPriceOffset": 5,
"premium": 2.5,
"daysUntilExpiration": 45
}
],
"entryConditions": {
"frequency": "every day",
"specificDays": [
0
],
"maximumActiveTrials": 5,
"maximumActiveTrialsBehavior": "don't enter",
"minimumVIX": 15,
"maximumVIX": 30
},
"exitConditions": {
"takeProfitPercentage": 50,
"stopLossPercentage": 100,
"afterDaysInTrade": 21,
"atDaysToExpiration": 7,
"minimumVIX": 12
}
}
""")
resp = requests.post(url, headers=headers, json=payload)
print(resp.status_code, resp.json())const resp = await fetch("https://backtester.vast.tastyworks.com/backtests", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_ACCESS_TOKEN",
"User-Agent": "tastytrade-docs-example/1.0",
"Content-Type": "application/json",
},
body: JSON.stringify({
"symbol": "SPY",
"startDate": "2022-01-01",
"endDate": "2022-12-31",
"legs": [
{
"type": "equity-option",
"direction": "short",
"side": "put",
"quantity": 1,
"strikeSelection": "delta",
"strikeRelativeLeg": 0,
"delta": 16,
"percentageOTM": 0.1,
"currentPriceOffset": 5,
"premium": 2.5,
"daysUntilExpiration": 45
}
],
"entryConditions": {
"frequency": "every day",
"specificDays": [
0
],
"maximumActiveTrials": 5,
"maximumActiveTrialsBehavior": "don't enter",
"minimumVIX": 15,
"maximumVIX": 30
},
"exitConditions": {
"takeProfitPercentage": 50,
"stopLossPercentage": 100,
"afterDaysInTrade": 21,
"atDaysToExpiration": 7,
"minimumVIX": 12
}
}),
})
const data = await resp.json()
console.log(resp.status, data)package main
import (
"net/http"
"io"
"fmt"
"strings"
)
func main() {
body := strings.NewReader(`{
"symbol": "SPY",
"startDate": "2022-01-01",
"endDate": "2022-12-31",
"legs": [
{
"type": "equity-option",
"direction": "short",
"side": "put",
"quantity": 1,
"strikeSelection": "delta",
"strikeRelativeLeg": 0,
"delta": 16,
"percentageOTM": 0.1,
"currentPriceOffset": 5,
"premium": 2.5,
"daysUntilExpiration": 45
}
],
"entryConditions": {
"frequency": "every day",
"specificDays": [
0
],
"maximumActiveTrials": 5,
"maximumActiveTrialsBehavior": "don't enter",
"minimumVIX": 15,
"maximumVIX": 30
},
"exitConditions": {
"takeProfitPercentage": 50,
"stopLossPercentage": 100,
"afterDaysInTrade": 21,
"atDaysToExpiration": 7,
"minimumVIX": 12
}
}`)
req, _ := http.NewRequest("POST", "https://backtester.vast.tastyworks.com/backtests", body)
req.Header.Set("Authorization", "Bearer YOUR_ACCESS_TOKEN")
req.Header.Set("User-Agent", "tastytrade-docs-example/1.0")
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
out, _ := io.ReadAll(resp.Body)
fmt.Println(resp.Status, string(out))
}import java.net.URI;
import java.net.http.*;
HttpClient client = HttpClient.newHttpClient();
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://backtester.vast.tastyworks.com/backtests"))
.header("Authorization", "Bearer YOUR_ACCESS_TOKEN")
.header("User-Agent", "tastytrade-docs-example/1.0")
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString("""
{
"symbol": "SPY",
"startDate": "2022-01-01",
"endDate": "2022-12-31",
"legs": [
{
"type": "equity-option",
"direction": "short",
"side": "put",
"quantity": 1,
"strikeSelection": "delta",
"strikeRelativeLeg": 0,
"delta": 16,
"percentageOTM": 0.1,
"currentPriceOffset": 5,
"premium": 2.5,
"daysUntilExpiration": 45
}
],
"entryConditions": {
"frequency": "every day",
"specificDays": [
0
],
"maximumActiveTrials": 5,
"maximumActiveTrialsBehavior": "don't enter",
"minimumVIX": 15,
"maximumVIX": 30
},
"exitConditions": {
"takeProfitPercentage": 50,
"stopLossPercentage": 100,
"afterDaysInTrade": 21,
"atDaysToExpiration": 7,
"minimumVIX": 12
}
}
"""))
.build();
HttpResponse<String> resp = client.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.statusCode() + " " + resp.body());Parameters
No parameters.
Request bodyapplication/json
Example
{
"symbol": "SPY",
"startDate": "2022-01-01",
"endDate": "2022-12-31",
"legs": [
{
"type": "equity-option",
"direction": "short",
"side": "put",
"quantity": 1,
"strikeSelection": "delta",
"strikeRelativeLeg": 0,
"delta": 16,
"percentageOTM": 0.1,
"currentPriceOffset": 5,
"premium": 2.5,
"daysUntilExpiration": 45
}
],
"entryConditions": {
"frequency": "every day",
"specificDays": [
0
],
"maximumActiveTrials": 5,
"maximumActiveTrialsBehavior": "don't enter",
"minimumVIX": 15,
"maximumVIX": 30
},
"exitConditions": {
"takeProfitPercentage": 50,
"stopLossPercentage": 100,
"afterDaysInTrade": 21,
"atDaysToExpiration": 7,
"minimumVIX": 12
}
}Schema
symbolstringUnderlying symbol the strategy trades. Confirm history exists for your date range via `GET /available-dates`.
example:
"SPY"startDatestring <date>First date of the historical window to backtest, in ISO 8601 `YYYY-MM-DD` format.
example:
"2022-01-01"endDatestring <date>Last date of the historical window to backtest, in ISO 8601 `YYYY-MM-DD` format.
example:
"2022-12-31"legsarray<object>typerequiredstringThe instrument type for this leg: `equity` for shares or `equity-option` for an option contract.
enum: equity, equity-option
example:
"equity-option"directionrequiredstringThe position direction: `long` to buy, `short` to sell.
enum: long, short
example:
"short"sidestringThe option side, `call` or `put`. Only applicable when `type` is `equity-option`.
enum: call, put
example:
"put"quantityrequiredintegerNumber of contracts or shares (1-10 for options, 1-100 for stocks).
example:
1strikeSelectionrequiredstringHow the strike is chosen for this leg. The accompanying value field depends on this: for example `delta` reads `delta`, `premium` reads `premium`.
enum: delta, percentageOTM, percentageOTMRelative, currentPriceOffset, currentPriceOffsetRelative, currentPriceExactOffsetRelative, premium
example:
"delta"strikeRelativeLegintegerIndex of the leg to use as reference when strike selection is relative to another leg.
example:
0deltanumberDelta value used when `strikeSelection` is `delta`, expressed as an integer from 1 to 100.
example:
16percentageOTMnumberPercentage out-of-the-money when `strikeSelection` is `percentageOTM` or `percentageOTMRelative` (for example 0.1 for 10% OTM, -0.1 for 10% ITM).
example:
0.1currentPriceOffsetnumberOffset from current price when `strikeSelection` is a currentPriceOffset variant (max 50000).
example:
5premiumnumberTarget premium when `strikeSelection` is `premium` (max 50000).
example:
2.5daysUntilExpirationrequiredintegerNumber of days until expiration to target for this leg.
example:
45
entryConditionsobject (EntryConditions)Optional rules controlling when new trials are opened during the backtest, such as entry frequency, concurrency limits, and VIX bounds.
frequencystring | nullHow often to open new trials: `every day`, `on specific days of the week`, or `on exact days to expiration match`.
enum: every day, on specific days of the week, on exact days to expiration match
example:
"every day"specificDaysarray<integer>Days of the week on which to enter, used when `frequency` is `on specific days of the week`.
maximumActiveTrialsinteger | nullMaximum number of trials allowed open simultaneously.
example:
5maximumActiveTrialsBehaviorstring | nullWhat to do when the active-trial limit is reached: `don't enter` to skip the entry, or `close oldest` to free a slot.
enum: don't enter, close oldest
example:
"don't enter"minimumVIXinteger | nullOnly open trials when the VIX is at or above this value.
example:
15maximumVIXinteger | nullOnly open trials when the VIX is at or below this value.
example:
30
exitConditionsobject (ExitConditions)Optional rules controlling when trials are closed during the backtest, such as profit/loss targets, time in trade, and days to expiration.
takeProfitPercentageinteger | nullProfit threshold for closing a trial, expressed as a percentage.
example:
50stopLossPercentageinteger | nullLoss threshold for closing a trial, expressed as a percentage.
example:
100afterDaysInTradeinteger | nullClose a trial after it has been open this many days.
example:
21atDaysToExpirationinteger | nullClose a trial when this many days to expiration remain.
example:
7minimumVIXinteger | nullVIX threshold used as an exit condition for closing trials.
example:
12
Responses
Example response
{
"id": "b1f8c2a4-9e7d-4a31-8c6f-2d5e1a0b3c7e",
"symbol": "SPY",
"startDate": "2022-01-01",
"endDate": "2022-12-31",
"legs": [
{
"type": "equity-option",
"direction": "short",
"side": "put",
"quantity": 1,
"strikeSelection": "delta",
"strikeRelativeLeg": 0,
"delta": 16,
"percentageOTM": 0.1,
"currentPriceOffset": 5,
"premium": 2.5,
"daysUntilExpiration": 45
}
],
"entryConditions": {
"frequency": "every day",
"specificDays": [
0
],
"maximumActiveTrials": 5,
"maximumActiveTrialsBehavior": "don't enter",
"minimumVIX": 15,
"maximumVIX": 30
},
"exitConditions": {
"takeProfitPercentage": 50,
"stopLossPercentage": 100,
"afterDaysInTrade": 21,
"atDaysToExpiration": 7,
"minimumVIX": 12
},
"ETA": 0,
"progress": 0,
"status": "completed",
"statistics": [
{}
],
"trials": [
{
"openDateTime": "2022-01-03T14:30:00Z",
"closeDateTime": "2022-01-20T20:00:00Z",
"profitLoss": 128.5
}
],
"snapshots": [
{
"dateTime": "2022-01-03T14:30:00Z",
"profitLoss": 128.5,
"underlyingPrice": 477.71
}
],
"notices": []
}Schema
idstringUnique identifier for this backtest. Use it with `GET /backtests/{id}` to poll status and read results.
example:
"b1f8c2a4-9e7d-4a31-8c6f-2d5e1a0b3c7e"symbolstringUnderlying symbol the strategy trades.
example:
"SPY"startDatestring <date>First date of the backtested historical window, in ISO 8601 `YYYY-MM-DD` format.
example:
"2022-01-01"endDatestring <date>Last date of the backtested historical window, in ISO 8601 `YYYY-MM-DD` format.
example:
"2022-12-31"legsarray<object>typerequiredstringThe instrument type for this leg: `equity` for shares or `equity-option` for an option contract.
enum: equity, equity-option
example:
"equity-option"directionrequiredstringThe position direction: `long` to buy, `short` to sell.
enum: long, short
example:
"short"sidestringThe option side, `call` or `put`. Only applicable when `type` is `equity-option`.
enum: call, put
example:
"put"quantityrequiredintegerNumber of contracts or shares (1-10 for options, 1-100 for stocks).
example:
1strikeSelectionrequiredstringHow the strike is chosen for this leg. The accompanying value field depends on this: for example `delta` reads `delta`, `premium` reads `premium`.
enum: delta, percentageOTM, percentageOTMRelative, currentPriceOffset, currentPriceOffsetRelative, currentPriceExactOffsetRelative, premium
example:
"delta"strikeRelativeLegintegerIndex of the leg to use as reference when strike selection is relative to another leg.
example:
0deltanumberDelta value used when `strikeSelection` is `delta`, expressed as an integer from 1 to 100.
example:
16percentageOTMnumberPercentage out-of-the-money when `strikeSelection` is `percentageOTM` or `percentageOTMRelative` (for example 0.1 for 10% OTM, -0.1 for 10% ITM).
example:
0.1currentPriceOffsetnumberOffset from current price when `strikeSelection` is a currentPriceOffset variant (max 50000).
example:
5premiumnumberTarget premium when `strikeSelection` is `premium` (max 50000).
example:
2.5daysUntilExpirationrequiredintegerNumber of days until expiration to target for this leg.
example:
45
entryConditionsobject (EntryConditions)Optional rules controlling when new trials are opened during the backtest, such as entry frequency, concurrency limits, and VIX bounds.
frequencystring | nullHow often to open new trials: `every day`, `on specific days of the week`, or `on exact days to expiration match`.
enum: every day, on specific days of the week, on exact days to expiration match
example:
"every day"specificDaysarray<integer>Days of the week on which to enter, used when `frequency` is `on specific days of the week`.
maximumActiveTrialsinteger | nullMaximum number of trials allowed open simultaneously.
example:
5maximumActiveTrialsBehaviorstring | nullWhat to do when the active-trial limit is reached: `don't enter` to skip the entry, or `close oldest` to free a slot.
enum: don't enter, close oldest
example:
"don't enter"minimumVIXinteger | nullOnly open trials when the VIX is at or above this value.
example:
15maximumVIXinteger | nullOnly open trials when the VIX is at or below this value.
example:
30
exitConditionsobject (ExitConditions)Optional rules controlling when trials are closed during the backtest, such as profit/loss targets, time in trade, and days to expiration.
takeProfitPercentageinteger | nullProfit threshold for closing a trial, expressed as a percentage.
example:
50stopLossPercentageinteger | nullLoss threshold for closing a trial, expressed as a percentage.
example:
100afterDaysInTradeinteger | nullClose a trial after it has been open this many days.
example:
21atDaysToExpirationinteger | nullClose a trial when this many days to expiration remain.
example:
7minimumVIXinteger | nullVIX threshold used as an exit condition for closing trials.
example:
12
ETAnumberEstimated time remaining until the run completes. Use it to space out polls while the backtest is still running.
progressnumberCompletion progress of the run.
statusstringCurrent run state. Moves through `pending`, `running`, and `completed`; read results once it is `completed`.
enum: pending, running, completed
example:
"completed"statisticsarray<object>Aggregate performance metrics for the run, populated once the backtest completes.
trialsarray<object>openDateTimestringTimestamp the trial opened, in ISO 8601 format.
example:
"2022-01-03T14:30:00Z"closeDateTimestringTimestamp the trial closed, in ISO 8601 format.
example:
"2022-01-20T20:00:00Z"profitLossnumberRealized profit or loss for this trial.
example:
128.5
snapshotsarray<object>dateTimestringTimestamp of this snapshot in ISO 8601 format.
example:
"2022-01-03T14:30:00Z"profitLossnumberCumulative strategy profit or loss at this point in the run.
example:
128.5underlyingPricenumberPrice of the underlying symbol at this point in the run.
example:
477.71
noticesarray<string>Conditional annotations appearing if specific conditions are met (for example overlapping ranges due to a stock split).
example:
[]
Example response
{
"id": "b1f8c2a4-9e7d-4a31-8c6f-2d5e1a0b3c7e",
"symbol": "SPY",
"startDate": "2022-01-01",
"endDate": "2022-12-31",
"legs": [
{
"type": "equity-option",
"direction": "short",
"side": "put",
"quantity": 1,
"strikeSelection": "delta",
"strikeRelativeLeg": 0,
"delta": 16,
"percentageOTM": 0.1,
"currentPriceOffset": 5,
"premium": 2.5,
"daysUntilExpiration": 45
}
],
"entryConditions": {
"frequency": "every day",
"specificDays": [
0
],
"maximumActiveTrials": 5,
"maximumActiveTrialsBehavior": "don't enter",
"minimumVIX": 15,
"maximumVIX": 30
},
"exitConditions": {
"takeProfitPercentage": 50,
"stopLossPercentage": 100,
"afterDaysInTrade": 21,
"atDaysToExpiration": 7,
"minimumVIX": 12
},
"ETA": 0,
"progress": 0,
"status": "completed",
"statistics": [
{}
],
"trials": [
{
"openDateTime": "2022-01-03T14:30:00Z",
"closeDateTime": "2022-01-20T20:00:00Z",
"profitLoss": 128.5
}
],
"snapshots": [
{
"dateTime": "2022-01-03T14:30:00Z",
"profitLoss": 128.5,
"underlyingPrice": 477.71
}
],
"notices": []
}Schema
idstringUnique identifier for this backtest. Use it with `GET /backtests/{id}` to poll status and read results.
example:
"b1f8c2a4-9e7d-4a31-8c6f-2d5e1a0b3c7e"symbolstringUnderlying symbol the strategy trades.
example:
"SPY"startDatestring <date>First date of the backtested historical window, in ISO 8601 `YYYY-MM-DD` format.
example:
"2022-01-01"endDatestring <date>Last date of the backtested historical window, in ISO 8601 `YYYY-MM-DD` format.
example:
"2022-12-31"legsarray<object>typerequiredstringThe instrument type for this leg: `equity` for shares or `equity-option` for an option contract.
enum: equity, equity-option
example:
"equity-option"directionrequiredstringThe position direction: `long` to buy, `short` to sell.
enum: long, short
example:
"short"sidestringThe option side, `call` or `put`. Only applicable when `type` is `equity-option`.
enum: call, put
example:
"put"quantityrequiredintegerNumber of contracts or shares (1-10 for options, 1-100 for stocks).
example:
1strikeSelectionrequiredstringHow the strike is chosen for this leg. The accompanying value field depends on this: for example `delta` reads `delta`, `premium` reads `premium`.
enum: delta, percentageOTM, percentageOTMRelative, currentPriceOffset, currentPriceOffsetRelative, currentPriceExactOffsetRelative, premium
example:
"delta"strikeRelativeLegintegerIndex of the leg to use as reference when strike selection is relative to another leg.
example:
0deltanumberDelta value used when `strikeSelection` is `delta`, expressed as an integer from 1 to 100.
example:
16percentageOTMnumberPercentage out-of-the-money when `strikeSelection` is `percentageOTM` or `percentageOTMRelative` (for example 0.1 for 10% OTM, -0.1 for 10% ITM).
example:
0.1currentPriceOffsetnumberOffset from current price when `strikeSelection` is a currentPriceOffset variant (max 50000).
example:
5premiumnumberTarget premium when `strikeSelection` is `premium` (max 50000).
example:
2.5daysUntilExpirationrequiredintegerNumber of days until expiration to target for this leg.
example:
45
entryConditionsobject (EntryConditions)Optional rules controlling when new trials are opened during the backtest, such as entry frequency, concurrency limits, and VIX bounds.
frequencystring | nullHow often to open new trials: `every day`, `on specific days of the week`, or `on exact days to expiration match`.
enum: every day, on specific days of the week, on exact days to expiration match
example:
"every day"specificDaysarray<integer>Days of the week on which to enter, used when `frequency` is `on specific days of the week`.
maximumActiveTrialsinteger | nullMaximum number of trials allowed open simultaneously.
example:
5maximumActiveTrialsBehaviorstring | nullWhat to do when the active-trial limit is reached: `don't enter` to skip the entry, or `close oldest` to free a slot.
enum: don't enter, close oldest
example:
"don't enter"minimumVIXinteger | nullOnly open trials when the VIX is at or above this value.
example:
15maximumVIXinteger | nullOnly open trials when the VIX is at or below this value.
example:
30
exitConditionsobject (ExitConditions)Optional rules controlling when trials are closed during the backtest, such as profit/loss targets, time in trade, and days to expiration.
takeProfitPercentageinteger | nullProfit threshold for closing a trial, expressed as a percentage.
example:
50stopLossPercentageinteger | nullLoss threshold for closing a trial, expressed as a percentage.
example:
100afterDaysInTradeinteger | nullClose a trial after it has been open this many days.
example:
21atDaysToExpirationinteger | nullClose a trial when this many days to expiration remain.
example:
7minimumVIXinteger | nullVIX threshold used as an exit condition for closing trials.
example:
12
ETAnumberEstimated time remaining until the run completes. Use it to space out polls while the backtest is still running.
progressnumberCompletion progress of the run.
statusstringCurrent run state. Moves through `pending`, `running`, and `completed`; read results once it is `completed`.
enum: pending, running, completed
example:
"completed"statisticsarray<object>Aggregate performance metrics for the run, populated once the backtest completes.
trialsarray<object>openDateTimestringTimestamp the trial opened, in ISO 8601 format.
example:
"2022-01-03T14:30:00Z"closeDateTimestringTimestamp the trial closed, in ISO 8601 format.
example:
"2022-01-20T20:00:00Z"profitLossnumberRealized profit or loss for this trial.
example:
128.5
snapshotsarray<object>dateTimestringTimestamp of this snapshot in ISO 8601 format.
example:
"2022-01-03T14:30:00Z"profitLossnumberCumulative strategy profit or loss at this point in the run.
example:
128.5underlyingPricenumberPrice of the underlying symbol at this point in the run.
example:
477.71
noticesarray<string>Conditional annotations appearing if specific conditions are met (for example overlapping ranges due to a stock split).
example:
[]
Related
- Rate-limit class:
write· not idempotent — Rate limits & backoff - Error reference — codes, causes, and fixes
Agents: this page is also Markdown (with the embedded OpenAPI definition) — append .md or send Accept: text/markdown. Index at /llms.txt.