openapi: 3.1.0
info:
  title: Backtesting
  version: 1.0.0
  description: tastytrade options backtester
  contact:
    name: tastytrade API support
    email: api.support@tastytrade.com
    url: https://developer.tastytrade.com
servers:
  - url: https://backtester.vast.tastyworks.com
    description: Backtester API
paths:
  /backtests:
    get:
      summary: List Your Backtests
      description: Returns the IDs of every backtest the authenticated user has
        submitted. Use an ID with `GET /backtests/{id}` to poll status or read
        results.
      operationId: getUsersBacktests
      responses:
        "200":
          description: An array of backtest IDs belonging to the current user.
          content:
            application/json:
              schema:
                type: array
                items:
                  type: string
        "401":
          description: Unauthorized.
        "429":
          description: Request rate exceeded reasonable thresholds. Back off exponentially
            before retrying.
      tags:
        - backtesting
      x-tt-class: read
      x-money-moving: false
      x-idempotent: true
      x-rate-limit-bucket: read
    post:
      summary: Create A Backtest
      description: 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}`.
      operationId: postBacktests
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/BacktestPost"
      responses:
        "200":
          description: Backtest completed and ready to read. The body is a fully populated
            backtest object.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BacktestGet"
        "201":
          description: Backtest accepted and still running. Poll `GET /backtests/{id}` and
            watch `status` until it reaches `completed`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BacktestGet"
        "400":
          $ref: "#/components/responses/400"
          description: The request body was malformed or did not match the backtest schema
            (for example a missing required leg field or an invalid
            `strikeSelection` value).
        "401":
          description: Unauthorized.
        "404":
          $ref: "#/components/responses/404"
          description: Backtest not found.
        "429":
          description: Request rate exceeded reasonable thresholds. Back off exponentially
            before retrying.
        "500":
          $ref: "#/components/responses/500"
      tags:
        - backtesting
      x-tt-class: mutating
      x-money-moving: false
      x-idempotent: false
      x-rate-limit-bucket: write
  /backtests/{id}:
    get:
      summary: Get Backtest By ID
      description: Fetches a single backtest by its ID. Poll this endpoint to watch
        `status` move through `pending`, `running`, and `completed`; while it
        runs the object reports `progress` and an `ETA` you can use to space out
        polls. Once `completed`, read `statistics`, `trials`, `snapshots`, and
        `notices`.
      operationId: getBacktests
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: The backtest object, including its current status and (once
            completed) results.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BacktestGet"
        "400":
          $ref: "#/components/responses/400"
          description: The supplied backtest ID was malformed.
        "401":
          description: Unauthorized.
        "404":
          $ref: "#/components/responses/404"
          description: No backtest exists with the supplied ID for this user.
        "429":
          description: Request rate exceeded reasonable thresholds. Poll on an interval
            rather than tightly looping, and back off on 429.
        "500":
          $ref: "#/components/responses/500"
      tags:
        - backtesting
      x-tt-class: read
      x-money-moving: false
      x-idempotent: true
      x-rate-limit-bucket: read
  /backtests/{id}/logs:
    get:
      summary: Get Backtest Logs
      description: Returns the step-by-step execution logs for the specified backtest,
        useful for understanding how trials were opened and closed during the
        run.
      operationId: getBacktestsLogs
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: The execution log for the backtest.
        "400":
          $ref: "#/components/responses/400"
          description: The supplied backtest ID was malformed.
        "401":
          description: Unauthorized.
        "404":
          $ref: "#/components/responses/404"
          description: No backtest exists with the supplied ID for this user.
        "429":
          description: Request rate exceeded reasonable thresholds. Back off exponentially
            before retrying.
      tags:
        - backtesting
      x-tt-class: read
      x-money-moving: false
      x-idempotent: true
      x-rate-limit-bucket: read
  /backtests/{id}/cancel:
    post:
      summary: Cancel A Running Backtest
      description: Stops a `pending` or `running` backtest early. Returns `204 No
        Content` on success. Useful for aborting a long run you no longer need.
      operationId: cancelBacktests
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      responses:
        "204":
          description: The backtest was cancelled. No response body is returned.
        "400":
          $ref: "#/components/responses/400"
          description: The supplied backtest ID was malformed.
        "401":
          description: Unauthorized.
        "404":
          $ref: "#/components/responses/404"
          description: No backtest exists with the supplied ID for this user.
        "429":
          description: Request rate exceeded reasonable thresholds. Back off exponentially
            before retrying.
      tags:
        - backtesting
      x-tt-class: mutating
      x-money-moving: false
      x-idempotent: false
      x-rate-limit-bucket: write
  /available-dates:
    get:
      summary: List Available Date Ranges
      description: Returns each symbol with historical backtest data alongside the
        `startDate` and `endDate` of its available coverage. Call this before
        creating a backtest to confirm a symbol has history for your requested
        window.
      operationId: getAvailableDates
      responses:
        "200":
          description: An array of symbols, each with the inclusive range of dates that
            have backtest history.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/AvailableSymbolDates"
        "400":
          $ref: "#/components/responses/400"
          description: The request was malformed.
        "401":
          description: Unauthorized.
        "429":
          description: Request rate exceeded reasonable thresholds. Back off exponentially
            before retrying.
        "500":
          $ref: "#/components/responses/500"
      tags:
        - backtesting
      x-tt-class: read
      x-money-moving: false
      x-idempotent: true
      x-rate-limit-bucket: read
  /simulate-trade:
    post:
      summary: Simulate A Single Trade
      description: Returns historical pricing for one trade without defining a full
        backtest. Supply an `underlying` and one or more `legs` (each leg uses
        tastytrade/OCC symbology), optionally bounded by `startTime`/`endTime`.
        The response is a time series of price points with the trade `effect`
        (debit or credit), `underlyingPrice`, and `delta`.
      operationId: simulateTrade
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                underlying:
                  type: string
                  description: Underlying symbol of the trade
                startTime:
                  type: string
                  format: date-time
                  description: Optionally, start time of the trade in ISO 8601 format.
                endTime:
                  type: string
                  format: date-time
                  description: Optionally, end time of the trade in ISO 8601 format.
                legs:
                  type: array
                  items:
                    type: object
                    properties:
                      symbol:
                        type: string
                        description: The leg symbol uses the tastytrade / OCC symbology convention -
                          https://developer.tastytrade.com/api-overview/#tastytrade-symbology
                      direction:
                        type: string
                        enum:
                          - long
                          - short
                      quantity:
                        type: integer
            examples:
              coveredCall:
                summary: Covered call
                value:
                  underlying: SPY
                  legs:
                    - symbol: SPY   190227C00275000
                      direction: short
                      quantity: 1
                    - symbol: SPY
                      direction: long
                      quantity: 100
              putRatioSpread:
                summary: Put ratio spread
                value:
                  underlying: SPY
                  legs:
                    - symbol: SPY   190227P00265000
                      direction: long
                      quantity: 3
                    - symbol: SPY   190227P00275000
                      direction: short
                      quantity: 1
              longCallButterfly:
                summary: Long call butterfly
                value:
                  underlying: SPY
                  legs:
                    - symbol: SPY   190227C00270000
                      direction: long
                      quantity: 2
                    - symbol: SPY   190227C00275000
                      direction: short
                      quantity: 1
                    - symbol: SPY   190227C00265000
                      direction: short
                      quantity: 1
      responses:
        "200":
          description: A time-ordered series of price points for the simulated trade.
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    dateTime:
                      type: string
                      format: date-time
                    price:
                      type: string
                    effect:
                      type: string
                      enum:
                        - debit
                        - credit
                    underlyingPrice:
                      type: string
                    delta:
                      type: string
        "400":
          description: The request body was malformed, for example an invalid leg `symbol`
            or `direction`.
        "401":
          description: Unauthorized.
        "404":
          description: No history is available for the requested underlying or time range.
        "429":
          description: Request rate exceeded reasonable thresholds. Back off exponentially
            before retrying.
      tags:
        - backtesting
      x-tt-class: mutating
      x-money-moving: false
      x-idempotent: false
      x-rate-limit-bucket: write
components:
  schemas:
    BacktestPost:
      type: object
      properties:
        symbol:
          type: string
          description: Underlying symbol the strategy trades. Confirm history exists for
            your date range via `GET /available-dates`.
          example: SPY
        startDate:
          type: string
          format: date
          description: First date of the historical window to backtest, in ISO 8601
            `YYYY-MM-DD` format.
          example: 2022-01-01
        endDate:
          type: string
          format: date
          description: Last date of the historical window to backtest, in ISO 8601
            `YYYY-MM-DD` format.
          example: 2022-12-31
        legs:
          type: array
          items:
            type: object
            allOf:
              - $ref: "#/components/schemas/Leg"
        entryConditions:
          allOf:
            - $ref: "#/components/schemas/EntryConditions"
        exitConditions:
          allOf:
            - $ref: "#/components/schemas/ExitConditions"
      description: "The definition of a backtest to run: an underlying `symbol`, a
        historical `startDate`/`endDate` window, one or more strategy `legs`,
        and optional `entryConditions`/`exitConditions` controlling when trials
        open and close."
    BacktestGet:
      type: object
      properties:
        id:
          type: string
          description: Unique identifier for this backtest. Use it with `GET
            /backtests/{id}` to poll status and read results.
          example: b1f8c2a4-9e7d-4a31-8c6f-2d5e1a0b3c7e
        symbol:
          type: string
          description: Underlying symbol the strategy trades.
          example: SPY
        startDate:
          type: string
          format: date
          description: First date of the backtested historical window, in ISO 8601
            `YYYY-MM-DD` format.
          example: 2022-01-01
        endDate:
          type: string
          format: date
          description: Last date of the backtested historical window, in ISO 8601
            `YYYY-MM-DD` format.
          example: 2022-12-31
        legs:
          type: array
          items:
            type: object
            allOf:
              - $ref: "#/components/schemas/Leg"
        entryConditions:
          allOf:
            - $ref: "#/components/schemas/EntryConditions"
        exitConditions:
          allOf:
            - $ref: "#/components/schemas/ExitConditions"
        ETA:
          type: number
          description: Estimated time remaining until the run completes. Use it to space
            out polls while the backtest is still running.
        progress:
          type: number
          description: Completion progress of the run.
        status:
          type: string
          enum:
            - pending
            - running
            - completed
          description: Current run state. Moves through `pending`, `running`, and
            `completed`; read results once it is `completed`.
          example: completed
        statistics:
          type: array
          items:
            type: object
          description: Aggregate performance metrics for the run, populated once the
            backtest completes.
        trials:
          type: array
          items:
            allOf:
              - $ref: "#/components/schemas/Trial"
        snapshots:
          type: array
          items:
            allOf:
              - $ref: "#/components/schemas/Snapshot"
        notices:
          description: Conditional annotations appearing if specific conditions are met
            (for example overlapping ranges due to a stock split).
          type: array
          items:
            type: string
          example: []
      description: A backtest object returned when creating or polling a backtest.
        Includes the original definition plus run state (`status`, `progress`,
        `ETA`) and, once completed, the results in `statistics`, `trials`,
        `snapshots`, and `notices`.
    Snapshot:
      type: object
      properties:
        dateTime:
          type: string
          description: Timestamp of this snapshot in ISO 8601 format.
          example: 2022-01-03T14:30:00Z
        profitLoss:
          type: number
          description: Cumulative strategy profit or loss at this point in the run.
          example: 128.5
        underlyingPrice:
          type: number
          description: Price of the underlying symbol at this point in the run.
          example: 477.71
      description: A single point in the backtest's time series, capturing strategy
        profit/loss and the underlying price at a given moment.
    Trial:
      type: object
      properties:
        openDateTime:
          type: string
          description: Timestamp the trial opened, in ISO 8601 format.
          example: 2022-01-03T14:30:00Z
        closeDateTime:
          type: string
          description: Timestamp the trial closed, in ISO 8601 format.
          example: 2022-01-20T20:00:00Z
        profitLoss:
          type: number
          description: Realized profit or loss for this trial.
          example: 128.5
      description: A single simulated trade within the backtest, with its open and
        close times and realized profit/loss.
    Leg:
      type: object
      required:
        - type
        - direction
        - quantity
        - strikeSelection
        - daysUntilExpiration
      properties:
        type:
          type: string
          enum:
            - equity
            - equity-option
          description: "The instrument type for this leg: `equity` for shares or
            `equity-option` for an option contract."
          example: equity-option
        direction:
          type: string
          enum:
            - long
            - short
          description: "The position direction: `long` to buy, `short` to sell."
          example: short
        side:
          type: string
          enum:
            - call
            - put
          description: The option side, `call` or `put`. Only applicable when `type` is
            `equity-option`.
          example: put
        quantity:
          type: integer
          minimum: 1
          maximum: 100
          description: Number of contracts or shares (1-10 for options, 1-100 for stocks).
          example: 1
        strikeSelection:
          type: string
          enum:
            - delta
            - percentageOTM
            - percentageOTMRelative
            - currentPriceOffset
            - currentPriceOffsetRelative
            - currentPriceExactOffsetRelative
            - premium
          description: "How the strike is chosen for this leg. The accompanying value
            field depends on this: for example `delta` reads `delta`, `premium`
            reads `premium`."
          example: delta
        strikeRelativeLeg:
          type: integer
          description: Index of the leg to use as reference when strike selection is
            relative to another leg.
          example: 0
        delta:
          type: number
          minimum: 1
          maximum: 100
          description: Delta value used when `strikeSelection` is `delta`, expressed as an
            integer from 1 to 100.
          example: 16
        percentageOTM:
          type: number
          description: Percentage out-of-the-money when `strikeSelection` is
            `percentageOTM` or `percentageOTMRelative` (for example 0.1 for 10%
            OTM, -0.1 for 10% ITM).
          example: 0.1
        currentPriceOffset:
          type: number
          maximum: 50000
          description: Offset from current price when `strikeSelection` is a
            currentPriceOffset variant (max 50000).
          example: 5
        premium:
          type: number
          maximum: 50000
          description: Target premium when `strikeSelection` is `premium` (max 50000).
          example: 2.5
        daysUntilExpiration:
          type: integer
          description: Number of days until expiration to target for this leg.
          example: 45
      description: One position in the strategy. The required fields are `type`,
        `direction`, `quantity`, `strikeSelection`, and `daysUntilExpiration`;
        `side` applies only to `equity-option` legs. The strike-related field
        you supply depends on `strikeSelection`.
    EntryConditions:
      type: object
      properties:
        frequency:
          type:
            - string
            - "null"
          enum:
            - every day
            - on specific days of the week
            - on exact days to expiration match
          description: "How often to open new trials: `every day`, `on specific days of
            the week`, or `on exact days to expiration match`."
          example: every day
        specificDays:
          type:
            - array
            - "null"
          items:
            type: integer
          description: Days of the week on which to enter, used when `frequency` is `on
            specific days of the week`.
        maximumActiveTrials:
          type:
            - integer
            - "null"
          description: Maximum number of trials allowed open simultaneously.
          example: 5
        maximumActiveTrialsBehavior:
          type:
            - string
            - "null"
          enum:
            - don't enter
            - close oldest
          description: "What to do when the active-trial limit is reached: `don't enter`
            to skip the entry, or `close oldest` to free a slot."
          example: don't enter
        minimumVIX:
          type:
            - integer
            - "null"
          description: Only open trials when the VIX is at or above this value.
          example: 15
        maximumVIX:
          type:
            - integer
            - "null"
          description: Only open trials when the VIX is at or below this value.
          example: 30
      description: Optional rules controlling when new trials are opened during the
        backtest, such as entry frequency, concurrency limits, and VIX bounds.
    ExitConditions:
      type: object
      properties:
        takeProfitPercentage:
          type:
            - integer
            - "null"
          description: Profit threshold for closing a trial, expressed as a percentage.
          example: 50
        stopLossPercentage:
          type:
            - integer
            - "null"
          description: Loss threshold for closing a trial, expressed as a percentage.
          example: 100
        afterDaysInTrade:
          type:
            - integer
            - "null"
          description: Close a trial after it has been open this many days.
          example: 21
        atDaysToExpiration:
          type:
            - integer
            - "null"
          description: Close a trial when this many days to expiration remain.
          example: 7
        minimumVIX:
          type:
            - integer
            - "null"
          description: VIX threshold used as an exit condition for closing trials.
          example: 12
      description: Optional rules controlling when trials are closed during the
        backtest, such as profit/loss targets, time in trade, and days to
        expiration.
    AvailableSymbolDates:
      type: object
      properties:
        symbol:
          type: string
          description: The symbol with available history.
          example: SPY
        startDate:
          type: string
          description: Earliest date with available backtest history for this symbol.
          example: 2012-01-03
        endDate:
          type: string
          description: Latest date with available backtest history for this symbol.
          example: 2024-12-31
      description: The inclusive range of historical dates available for backtesting a
        single symbol.
  responses:
    "400":
      description: Request included malformed input
    "404":
      description: Backtest not found
    "500":
      description: Failed to process request
x-tastytrade-service:
  serviceName: backtesting-api
  group: backtesting
  title: Backtesting
tags:
  - name: backtesting
