New
The Tools APIs are now live: option scanning, backtest search, intraday backtesting, and time & sales over REST

Backtest Finder API

View as Markdown

Search hundreds of millions of precomputed option strategy backtests by ticker and strategy, then pull the full results for any one of them: summary stats, monthly returns, trade logs, and daily returns. The Options Backtester in the ORATS dashboard runs on this same service.

Authenticate with the token query parameter. Do not send an Authorization header: the Results Stats endpoint redirects to a presigned S3 URL, and clients that forward headers across redirects will break on it.

Fifteen strategies are precomputed across roughly 146 tickers: IronButterfly, IronCondor, LongCall, LongCallCalendar, LongCallSpread, LongPut, LongPutCalendar, LongPutSpread, LongStraddle, ShortCall, ShortCallSpread, ShortPut, ShortPutSpread, ShortStraddle, and ShortStrangle. Not every ticker has every strategy, and asking for a combination that was never precomputed returns a 500, so call the Catalog endpoint below to see what exists.

Validation errors return a 400 with a message field in the body; an unknown ticker and strategy combination, or an unknown id on the Results and Backtest Input endpoints, returns a 404 with a message.

Each endpoint is rate limited to 10 requests per minute per token. Beyond that, requests return a 429 with a message saying when the minute window resets.

Overview and pricing for this and the other Tools APIs are in the Tools APIs section of the Data API page.

Base URL:https://api.orats.io/backtest-finder

Catalog

GEThttps://api.orats.io/backtest-finder/catalog

Retrieves the universe of precomputed backtests: every ticker, the strategies precomputed for it, and the number of stored backtests per ticker and strategy combination. Use it to populate ticker and strategy pickers and to avoid the 500 error a never-precomputed combination returns from the Performance endpoint.

The response is an object keyed by ticker; each value is an array of strategy entries.

Required attributes

No attributes beyond the token.

GET/backtest-finder/catalog
curl -L "https://api.orats.io/backtest-finder/catalog?token=my-token"

Response

{
  "SPY": [
    {
      "strategy": "IronButterfly",
      "count": 1080
    },
    {
      "strategy": "IronCondor",
      "count": 5701
    }
  ],
  "AAPL": [
    {
      "strategy": "ShortPutSpread",
      "count": 4662
    }
  ]
}

Performance

POSThttps://api.orats.io/backtest-finder/performance

Retrieves ranked backtest performance rows for a ticker and strategy. The response is an array of up to limit rows (1 to 100, default 100), each holding the ranked performance metrics, the leg targets, the entry and exit triggers, and the full input configuration.

Each row's id can be passed to the Performance by Id and Results endpoints below, and its rootBaseId can be passed to the Backtest Input endpoint.

Row metrics are a precomputed snapshot over the window given by the row's startDate and endDate (currently through early January 2026, see the v field). The Results endpoints are refreshed more often and can include later trades, so a row's totStratTrades, annualReturn, and stratWinRate can differ slightly from the summary in Results Stats for the same id.

Units: return-style metrics (annualReturn, annualMarginReturn, bestYearRtn, worstYearRtn, bestMonthRtn, worstMonthRtn, volatility, maxDrawDown, totStratPLPct, bestTradePct, plPerTradeAvgPct, plPerDayAvgPct) are percent of the 100-share stock notional at entry, so annualReturn 2.04 is 2.04 percent per year; stratWinRate and pctOfTimeInMarket are percent; sharpe, sortino, riskRewardAvg, and bestReturnOnRisk are plain ratios; PL fields are dollars. Unscreened rows can carry extreme values (a bestReturnOnRisk in the tens of thousands on a four-trade row); earlier datasets clamped bestReturnOnRisk at 99.99999999 and totStratPL at plus or minus 999,999.99 on performance rows, and Results Stats always carries the unclamped values.

Required attributes

  • Name
    ticker
    Type
    string
    Description

    The underlying symbol to search. Ex: SPY

  • Name
    strategy
    Type
    string
    Description

    The strategy to search, from the precomputed list above. Ex: IronCondor

  • Name
    rank
    Type
    string
    Description

    The ranking to order results by: a composite (bestReturnOnRisk, bestOverallPerformance, bestConservativeWinner) or a metric id such as annualReturn, sharpe, sortino, or maxDrawDown. All three composites are scored for every ticker in the catalog. Only the ranking columns are accepted: any annualReturn variant, sharpe, sortino, volatility, maxDrawDown, drawDownDays, daysInTradeAvg, the best and worst month, year, and trade metrics, the plPer averages, stratWinRate, totStratTrades, pctOfTimeInMarket, totStratPL, and totStratPLPct; other columns, a missing rank, or a differently cased spelling (Sharpe) return a 400 with a message of unknown rank, with a casing hint when only the case differs. Rank ids are case-sensitive. Rankings apply the default quality screen described under screen below, which keeps low-sample backtests (a single trade across the whole history, with an annualized return in the thousands of percent) out of the top rows; still check totStratTrades on a row before trusting it.

Optional attributes

  • Name
    rankDir
    Type
    string
    Description

    Orders the rank positions: asc returns the best-ranked rows first, desc returns the worst first. Defaults to asc.

  • Name
    filters
    Type
    object
    Description

    Metric bands that narrow candidates before ranking. Each key is a metric id with a min and/or max, for example pctOfTimeInMarket with min 40, marginToStockPct with max 40, riskRewardAvg with min 0.07. The value must be an object (a string or an array returns a 400) and its keys must be performance-row columns; an unknown column, a non-numeric or empty min or max, an array, an object without min or max, or a range on a text column returns a 400 naming the field. Two value shapes are applied: an object with numeric min and/or max, or a bare string for an equality match (for example an entry trigger level). A limit field in the body caps the response (1 to 100, default 100; the GET form below accepts up to 10,000); zero, negative, or non-numeric limits return a 400 and fractions round down. A ticker in any case or with surrounding spaces is normalized; a strategy that is not in the precomputed list, including a lowercase or underscored spelling, returns a 404 with a casing hint, and a request whose body is empty or not a JSON object returns a 400. A filter on one of the three screened columns replaces that column's default threshold (see screen). Defaults to no filters beyond the screen.

  • Name
    screen
    Type
    boolean
    Description

    Whether to apply the default quality screen: pctOfTimeInMarket at least 40, marginToStockPct at most 20, and riskRewardAvg at least 0.07, the same three thresholds the dashboard finder applies. Defaults to true. Set to false (the boolean, not the string) to rank the raw, unscreened rows. A filters entry on a screened column overrides only that gate. Tickers with short histories (a few hundred stored backtests in the Catalog) can have no rows that pass the screen and return an empty array; rank them with screen false or a lower pctOfTimeInMarket filter.

  • Name
    currentEnvironment
    Type
    object
    Description

    Set to null (the default) to search all backtests regardless of the current market environment. Pass an object of the five entry-trigger levels to keep only backtests whose entry triggers match it: each of entryVix, entrySma, entryRsi, entryIvPct, and entrySlopePct on a row must be none or equal one of the supplied values (entrySma accepts an array, e.g. ["below50d","above200d"]). Levels are lowercase and case-sensitive: low, moderate, high, or none for entryVix, entryIvPct, and entrySlopePct; oversold, moderate, overbought, or none for entryRsi; above50d, below50d, above200d, below200d, or none for entrySma. A value outside those sets matches only rows whose trigger is none. Level values come from the current-environment endpoint of the Data API for the same ticker. Results are ranked by the same rank and rankDir as an unfiltered search.

POST/backtest-finder/performance
{
  "ticker": "SPY",
  "strategy": "IronCondor",
  "currentEnvironment": null,
  "filters": {},
  "rank": "bestReturnOnRisk",
  "rankDir": "asc"
}

Response

[
  {
    "rank": 1,
    "id": "988c00ada5d823a1821576ec0da4d2a5",
    "ticker": "SPY",
    "strategy": "IronCondor",
    "dte1Target": 8,
    "dte2Target": 8,
    "dte3Target": 8,
    "dte4Target": 8,
    "delta1Target": 0.1,
    "delta2Target": 0.35,
    "delta3Target": 0.35,
    "delta4Target": 0.1,
    "lrDteLeg1Leg2Min": 0,
    "lrDteLeg1Leg2Max": 0,
    "lrDteLeg2Leg3Min": 0,
    "lrDteLeg2Leg3Max": 0,
    "lrDteLeg3Leg4Min": 0,
    "lrDteLeg3Leg4Max": 0,
    "lrSwLeg1Leg2Min": 1,
    "lrSwLeg1Leg2Max": null,
    "lrSwLeg2Leg3Min": 1,
    "lrSwLeg2Leg3Max": null,
    "lrSwLeg3Leg4Min": 1,
    "lrSwLeg3Leg4Max": null,
    "spreadYieldLevel": "high",
    "spreadYieldTarget": -0.0304462,
    "spreadYieldMin": -0.0518128,
    "spreadYieldMax": -0.0090796,
    "strikeDiffPctLevel": "none",
    "strikeDiffPctTarget": null,
    "strikeDiffPctMin": null,
    "strikeDiffPctMax": null,
    "entryVix": "none",
    "entrySma": "above50d",
    "entryRsi": "none",
    "entryIvPct": "low",
    "entrySlopePct": "none",
    "exitStopLoss": "-50",
    "exitProfit": "50",
    "annualReturn": 2.04,
    "annualMarginReturn": 67.45,
    "annualReturnBull": 3.23,
    "annualReturnBear": 0.69,
    "annualReturn1Yr": 1.71,
    "annualReturn5Yr": 1.89,
    "sharpe": 0.68,
    "sortino": 1.16,
    "volatility": 2.99,
    "maxDrawDown": -2.72,
    "drawDownDays": 135,
    "bestMonthRtn": 2.45,
    "worstMonthRtn": -2.36,
    "bestYearRtn": 5.86,
    "worstYearRtn": -1,
    "bestTradePL": 619,
    "worstTradePL": -1521,
    "bestTradePct": 1.44,
    "worstTradePct": -2.5,
    "plPerTradeAvg": 21.02,
    "plPerDayAvg": 12.87,
    "plPerTradeAvgPct": 0.03529,
    "plPerDayAvgPct": 0.0187,
    "stratWinRate": 61.4,
    "daysInTradeAvg": 8,
    "totStratTrades": 1020,
    "totStratPL": 21445,
    "totStratPLPct": 0,
    "creditReceivedPerTradeAvg": 310.15,
    "marginPerTradeAvg": 1006.44,
    "mostMarginUsed": 3285,
    "leastMarginUsed": 221,
    "bestTradePctMargin": 52.25,
    "worstTradePctMargin": -84.62,
    "marginToStockPct": 3.08,
    "riskRewardAvg": 0.406324,
    "pctOfTimeInMarket": 40.35,
    "bestReturnOnRisk": 0.009208,
    "startDate": "2007-01-03",
    "endDate": "2026-01-06",
    "baseId": "2c5fa0a71a3cf39aacd069b06bd2e67c",
    "executionTime": 0.17,
    "createdDate": "2026-01-22 00:50:48.0",
    "updatedAt": "2026-01-22 00:50:48.0",
    "v": "2026-Q2-prod",
    "rootBaseId": "0d2284dc0eeef69b2042b14a04859a72",
    "bestOverallPerformance": 2.363432431503667,
    "bestConservativeWinner": 6.5010034758594095,
    "input": {
      "legs": [
        {
          "deltaMax": 0.2,
          "deltaMin": 0.05,
          "deltaTarget": 0.1,
          "dteMax": 16,
          "dteMin": 4,
          "dteTarget": 8,
          "ratio": 1,
          "type": "call"
        },
        {
          "deltaMax": 0.45,
          "deltaMin": 0.3,
          "deltaTarget": 0.35,
          "dteMax": 16,
          "dteMin": 4,
          "dteTarget": 8,
          "ratio": -1,
          "type": "call"
        },
        {
          "deltaMax": 0.45,
          "deltaMin": 0.3,
          "deltaTarget": 0.35,
          "dteMax": 16,
          "dteMin": 4,
          "dteTarget": 8,
          "ratio": -1,
          "type": "put"
        },
        {
          "deltaMax": 0.2,
          "deltaMin": 0.05,
          "deltaTarget": 0.1,
          "dteMax": 16,
          "dteMin": 4,
          "dteTarget": 8,
          "ratio": 1,
          "type": "put"
        }
      ],
      "lrDte": [
        {
          "max": 0,
          "min": 0,
          "name": "leg1Leg2"
        },
        {
          "max": 0,
          "min": 0,
          "name": "leg2Leg3"
        },
        {
          "max": 0,
          "min": 0,
          "name": "leg3Leg4"
        }
      ],
      "lrSw": [
        {
          "max": null,
          "min": 1,
          "name": "leg1Leg2"
        },
        {
          "max": null,
          "min": 1,
          "name": "leg2Leg3"
        },
        {
          "max": null,
          "min": 1,
          "name": "leg3Leg4"
        }
      ],
      "spreadYield": {
        "level": "high",
        "target": -0.0304462,
        "min": -0.0518128,
        "max": -0.0090796
      },
      "strategy": "IronCondor",
      "ticker": "SPY",
      "entryVix": "none",
      "entryRsi": "none",
      "entrySma": "above50d",
      "entryIvPct": "low",
      "entrySlopePct": "none",
      "exitStopLoss": "-50",
      "exitProfit": "50"
    }
  }
]

Performance by Id

GEThttps://api.orats.io/backtest-finder/performance

Retrieves a single backtest performance row by its id, from any ticker and strategy, with no other attributes required. The row has the same shape as the Performance endpoint's rows minus the rank field, including the full input configuration, so one call recovers everything about a stored backtest from its id alone.

The response is an array holding the one matching row. Unknown ids return an empty array with a 200 status, never a 404.

Required attributes

  • Name
    id
    Type
    string
    Description

    The id from a Performance row. Ex: 988c00ada5d823a1821576ec0da4d2a5

GET/backtest-finder/performance
curl -L "https://api.orats.io/backtest-finder/performance?token=my-token&id=988c00ada5d823a1821576ec0da4d2a5"

Response

[
  {
    "id": "988c00ada5d823a1821576ec0da4d2a5",
    "ticker": "SPY",
    "strategy": "IronCondor",
    "dte1Target": 8,
    "dte2Target": 8,
    "dte3Target": 8,
    "dte4Target": 8,
    "delta1Target": 0.1,
    "delta2Target": 0.35,
    "delta3Target": 0.35,
    "delta4Target": 0.1,
    "lrDteLeg1Leg2Min": 0,
    "lrDteLeg1Leg2Max": 0,
    "lrDteLeg2Leg3Min": 0,
    "lrDteLeg2Leg3Max": 0,
    "lrDteLeg3Leg4Min": 0,
    "lrDteLeg3Leg4Max": 0,
    "lrSwLeg1Leg2Min": 1,
    "lrSwLeg1Leg2Max": null,
    "lrSwLeg2Leg3Min": 1,
    "lrSwLeg2Leg3Max": null,
    "lrSwLeg3Leg4Min": 1,
    "lrSwLeg3Leg4Max": null,
    "spreadYieldLevel": "high",
    "spreadYieldTarget": -0.0304462,
    "spreadYieldMin": -0.0518128,
    "spreadYieldMax": -0.0090796,
    "strikeDiffPctLevel": "none",
    "strikeDiffPctTarget": null,
    "strikeDiffPctMin": null,
    "strikeDiffPctMax": null,
    "entryVix": "none",
    "entrySma": "above50d",
    "entryRsi": "none",
    "entryIvPct": "low",
    "entrySlopePct": "none",
    "exitStopLoss": "-50",
    "exitProfit": "50",
    "annualReturn": 2.04,
    "annualMarginReturn": 67.45,
    "annualReturnBull": 3.23,
    "annualReturnBear": 0.69,
    "annualReturn1Yr": 1.71,
    "annualReturn5Yr": 1.89,
    "sharpe": 0.68,
    "sortino": 1.16,
    "volatility": 2.99,
    "maxDrawDown": -2.72,
    "drawDownDays": 135,
    "bestMonthRtn": 2.45,
    "worstMonthRtn": -2.36,
    "bestYearRtn": 5.86,
    "worstYearRtn": -1,
    "bestTradePL": 619,
    "worstTradePL": -1521,
    "bestTradePct": 1.44,
    "worstTradePct": -2.5,
    "plPerTradeAvg": 21.02,
    "plPerDayAvg": 12.87,
    "plPerTradeAvgPct": 0.03529,
    "plPerDayAvgPct": 0.0187,
    "stratWinRate": 61.4,
    "daysInTradeAvg": 8,
    "totStratTrades": 1020,
    "totStratPL": 21445,
    "totStratPLPct": 0,
    "creditReceivedPerTradeAvg": 310.15,
    "marginPerTradeAvg": 1006.44,
    "mostMarginUsed": 3285,
    "leastMarginUsed": 221,
    "bestTradePctMargin": 52.25,
    "worstTradePctMargin": -84.62,
    "marginToStockPct": 3.08,
    "riskRewardAvg": 0.406324,
    "pctOfTimeInMarket": 40.35,
    "bestReturnOnRisk": 0.009208,
    "startDate": "2007-01-03",
    "endDate": "2026-01-06",
    "baseId": "2c5fa0a71a3cf39aacd069b06bd2e67c",
    "executionTime": 0.17,
    "createdDate": "2026-01-22 00:50:48.0",
    "updatedAt": "2026-01-22 00:50:48.0",
    "v": "2026-Q2-prod",
    "rootBaseId": "0d2284dc0eeef69b2042b14a04859a72",
    "bestOverallPerformance": 2.363432431503667,
    "bestConservativeWinner": 6.5010034758594095,
    "input": {
      "legs": [
        {
          "deltaMax": 0.2,
          "deltaMin": 0.05,
          "deltaTarget": 0.1,
          "dteMax": 16,
          "dteMin": 4,
          "dteTarget": 8,
          "ratio": 1,
          "type": "call"
        },
        {
          "deltaMax": 0.45,
          "deltaMin": 0.3,
          "deltaTarget": 0.35,
          "dteMax": 16,
          "dteMin": 4,
          "dteTarget": 8,
          "ratio": -1,
          "type": "call"
        },
        {
          "deltaMax": 0.45,
          "deltaMin": 0.3,
          "deltaTarget": 0.35,
          "dteMax": 16,
          "dteMin": 4,
          "dteTarget": 8,
          "ratio": -1,
          "type": "put"
        },
        {
          "deltaMax": 0.2,
          "deltaMin": 0.05,
          "deltaTarget": 0.1,
          "dteMax": 16,
          "dteMin": 4,
          "dteTarget": 8,
          "ratio": 1,
          "type": "put"
        }
      ],
      "lrDte": [
        {
          "max": 0,
          "min": 0,
          "name": "leg1Leg2"
        },
        {
          "max": 0,
          "min": 0,
          "name": "leg2Leg3"
        },
        {
          "max": 0,
          "min": 0,
          "name": "leg3Leg4"
        }
      ],
      "lrSw": [
        {
          "max": null,
          "min": 1,
          "name": "leg1Leg2"
        },
        {
          "max": null,
          "min": 1,
          "name": "leg2Leg3"
        },
        {
          "max": null,
          "min": 1,
          "name": "leg3Leg4"
        }
      ],
      "spreadYield": {
        "level": "high",
        "target": -0.0304462,
        "min": -0.0518128,
        "max": -0.0090796
      },
      "strategy": "IronCondor",
      "ticker": "SPY",
      "entryVix": "none",
      "entryRsi": "none",
      "entrySma": "above50d",
      "entryIvPct": "low",
      "entrySlopePct": "none",
      "exitStopLoss": "-50",
      "exitProfit": "50"
    }
  }
]

Current Environment

POSThttps://api.orats.io/backtest-finder/performance/environment

Retrieves ranked backtest performance rows whose entry triggers match the current market environment, across the precomputed environment universe of ETFs: DIA, EEM, GLD, HYG, IWM, QQQ, SMH, SPY, TLT, XLE, XLK, and XLY. Rows are pre-screened with the same quality thresholds as the Performance endpoint's default screen, and at most ten candidates per ticker and strategy enter the global ranking. A strategy name that is not in the precomputed list returns a 400 naming it, with a casing hint when only the case differs (ironcondor to IronCondor). Environment rows carry a sequential rank and leave spreadYieldLevel, strikeDiffPctLevel, and exitStopLoss null; fetch the same id from Performance by Id for those values.

The request body is a JSON array of strategy names, not an object. Rows are ranked globally across every ticker and strategy combination, capped at 100, and have the same shape as the Performance endpoint minus a few metadata fields: bestOverallPerformance, bestConservativeWinner, createdDate, updatedAt, and the duplicated rootBaseId columns. An empty array, an object, a bare string, or an empty body returns a 400 with a message that the body must be a non-empty array of strategy names.

Required attributes

  • Name
    body
    Type
    array
    Description

    A JSON array of strategy names from the precomputed list. Ex: ["IronCondor","IronButterfly"]

POST/backtest-finder/performance/environment
[
  "IronCondor"
]

Response

[
  {
    "rank": 59,
    "id": "988c00ada5d823a1821576ec0da4d2a5",
    "ticker": "SPY",
    "strategy": "IronCondor",
    "dte1Target": 8,
    "dte2Target": 8,
    "dte3Target": 8,
    "dte4Target": 8,
    "delta1Target": 0.1,
    "delta2Target": 0.35,
    "delta3Target": 0.35,
    "delta4Target": 0.1,
    "lrDteLeg1Leg2Min": 0,
    "lrDteLeg1Leg2Max": 0,
    "lrDteLeg2Leg3Min": 0,
    "lrDteLeg2Leg3Max": 0,
    "lrDteLeg3Leg4Min": 0,
    "lrDteLeg3Leg4Max": 0,
    "lrSwLeg1Leg2Min": 1,
    "lrSwLeg1Leg2Max": null,
    "lrSwLeg2Leg3Min": 1,
    "lrSwLeg2Leg3Max": null,
    "lrSwLeg3Leg4Min": 1,
    "lrSwLeg3Leg4Max": null,
    "spreadYieldLevel": null,
    "spreadYieldTarget": -0.0304462,
    "spreadYieldMin": -0.0518128,
    "spreadYieldMax": -0.0090796,
    "strikeDiffPctLevel": null,
    "strikeDiffPctTarget": null,
    "strikeDiffPctMin": null,
    "strikeDiffPctMax": null,
    "entryVix": "none",
    "entrySma": "above50d",
    "entryRsi": "none",
    "entryIvPct": "low",
    "entrySlopePct": "none",
    "exitStopLoss": -50,
    "exitProfit": 50,
    "annualReturn": 2.04,
    "annualMarginReturn": 67.45,
    "annualReturnBull": 3.23,
    "annualReturnBear": 0.69,
    "annualReturn1Yr": 1.71,
    "annualReturn5Yr": 1.89,
    "sharpe": 0.68,
    "sortino": 1.16,
    "volatility": 2.99,
    "maxDrawDown": -2.72,
    "drawDownDays": 135,
    "bestMonthRtn": 2.45,
    "worstMonthRtn": -2.36,
    "bestYearRtn": 5.86,
    "worstYearRtn": -1,
    "bestTradePL": 619,
    "worstTradePL": -1521,
    "bestTradePct": 1.44,
    "worstTradePct": -2.5,
    "plPerTradeAvg": 21.02,
    "plPerDayAvg": 12.87,
    "plPerTradeAvgPct": 0.03529,
    "plPerDayAvgPct": 0.0187,
    "stratWinRate": 61.4,
    "daysInTradeAvg": 8,
    "totStratTrades": 1020,
    "totStratPL": 21445,
    "totStratPLPct": 0,
    "creditReceivedPerTradeAvg": 310.15,
    "marginPerTradeAvg": 1006.44,
    "mostMarginUsed": 3285,
    "leastMarginUsed": 221,
    "bestTradePctMargin": 52.25,
    "worstTradePctMargin": -84.62,
    "marginToStockPct": 3.08,
    "riskRewardAvg": 0.406324,
    "pctOfTimeInMarket": 40.35,
    "bestReturnOnRisk": 0.009208,
    "startDate": "2007-01-03",
    "endDate": "2026-01-06",
    "baseId": "2c5fa0a71a3cf39aacd069b06bd2e67c",
    "executionTime": "0.17",
    "v": "2026-Q2-prod",
    "rootBaseId": "0d2284dc0eeef69b2042b14a04859a72",
    "input": {
      "legs": [
        {
          "deltaMax": 0.2,
          "deltaMin": 0.05,
          "deltaTarget": 0.1,
          "dteMax": 16,
          "dteMin": 4,
          "dteTarget": 8,
          "ratio": 1,
          "type": "call"
        },
        {
          "deltaMax": 0.45,
          "deltaMin": 0.3,
          "deltaTarget": 0.35,
          "dteMax": 16,
          "dteMin": 4,
          "dteTarget": 8,
          "ratio": -1,
          "type": "call"
        },
        {
          "deltaMax": 0.45,
          "deltaMin": 0.3,
          "deltaTarget": 0.35,
          "dteMax": 16,
          "dteMin": 4,
          "dteTarget": 8,
          "ratio": -1,
          "type": "put"
        },
        {
          "deltaMax": 0.2,
          "deltaMin": 0.05,
          "deltaTarget": 0.1,
          "dteMax": 16,
          "dteMin": 4,
          "dteTarget": 8,
          "ratio": 1,
          "type": "put"
        }
      ]
    }
  }
]

Backtest Input

GEThttps://api.orats.io/backtest-finder/input

Retrieves the base input configuration for a backtest: the leg definitions with delta and DTE bands, the leg relationships, and the spread yield band.

Pass the rootBaseId from a Performance row, not the row id. An unknown id, a missing or non-hex id, or a performance row id returns a 404 with a message; uppercase hex ids are folded to lowercase.

Note that this is the BASE configuration shared by a family of stored variants, so its bands and criteria can differ from any one variant's (in the example below, the base has no spread yield criterion while the variant row above has a high band). To replicate a specific backtest exactly, read the input object embedded on its Performance row instead.

Required attributes

  • Name
    id
    Type
    string
    Description

    The rootBaseId from a Performance row. Ex: 0d2284dc0eeef69b2042b14a04859a72

GET/backtest-finder/input
curl -L "https://api.orats.io/backtest-finder/input?token=my-token&id=0d2284dc0eeef69b2042b14a04859a72"

Response

{
  "id": "0d2284dc0eeef69b2042b14a04859a72",
  "legs": [
    {
      "deltaMax": 0.2,
      "deltaMin": 0.05,
      "deltaTarget": 0.1,
      "dteMax": 16,
      "dteMin": 4,
      "dteTarget": 8,
      "ratio": 1,
      "type": "call"
    },
    {
      "deltaMax": 0.45,
      "deltaMin": 0.3,
      "deltaTarget": 0.35,
      "dteMax": 16,
      "dteMin": 4,
      "dteTarget": 8,
      "ratio": -1,
      "type": "call"
    },
    {
      "deltaMax": 0.45,
      "deltaMin": 0.3,
      "deltaTarget": 0.35,
      "dteMax": 16,
      "dteMin": 4,
      "dteTarget": 8,
      "ratio": -1,
      "type": "put"
    },
    {
      "deltaMax": 0.2,
      "deltaMin": 0.05,
      "deltaTarget": 0.1,
      "dteMax": 16,
      "dteMin": 4,
      "dteTarget": 8,
      "ratio": 1,
      "type": "put"
    }
  ],
  "lrDte": [
    {
      "max": 0,
      "min": 0,
      "name": "leg1Leg2"
    },
    {
      "max": 0,
      "min": 0,
      "name": "leg2Leg3"
    },
    {
      "max": 0,
      "min": 0,
      "name": "leg3Leg4"
    }
  ],
  "lrSw": [
    {
      "max": null,
      "min": 1,
      "name": "leg1Leg2"
    },
    {
      "max": null,
      "min": 1,
      "name": "leg2Leg3"
    },
    {
      "max": null,
      "min": 1,
      "name": "leg3Leg4"
    }
  ],
  "spreadYield": {
    "level": "none",
    "max": null,
    "min": null,
    "target": null
  },
  "strategy": "IronCondor",
  "ticker": "SPY"
}

Results Stats

GEThttps://api.orats.io/backtest-finder/results/stats

Retrieves the full results blob for a backtest: summary statistics, monthly returns by year, the per-leg trade log, and daily returns for in-trade days.

The endpoint responds with a 302 redirect to a presigned S3 URL that expires in 300 seconds. Follow the redirect (for example with the -L flag in cURL) and do not send an Authorization header, which S3 rejects. The S3 object is gzip encoded; most HTTP clients decompress it automatically.

Required attributes

  • Name
    id
    Type
    string
    Description

    The id from a Performance row. Ex: 988c00ada5d823a1821576ec0da4d2a5

GET/backtest-finder/results/stats
curl -L --compressed "https://api.orats.io/backtest-finder/results/stats?token=my-token&id=988c00ada5d823a1821576ec0da4d2a5"

Response

{
  "summary": {
    "AnnReturn": 1.87,
    "AnnMarginReturn": 62.03,
    "AnnReturn1Yr": -1.08,
    "AnnReturn5Yrs": 1.14,
    "annReturnBull": 3.23,
    "annReturnBear": 0.69,
    "AnnSharpe": 0.63,
    "AnnSortino": 1.08,
    "AnnVolatility": 2.98,
    "MaxDrawDown": -2.72,
    "DrawDownDays": 135,
    "BestMonthRtn": 2.45,
    "WorstMonthRtn": -2.36,
    "BestYearRtn": 5.86,
    "WorstYearRtn": -1,
    "BestTradePL": 622,
    "WorstTradePL": -1521,
    "BestTradePct": 1.44,
    "WorstTradePct": -2.5,
    "PLPerTradeAvg": 18.81,
    "PLPerDayAvg": 11.69,
    "PLPerTradeAvgPct": 0.03267,
    "PLPerDayAvgPct": 0.0173,
    "StratWinRate": 61,
    "DaysInTradeAvg": 8,
    "TotStratTrades": 1042,
    "TotStratPL": 19597,
    "TotStratPLPct": 0,
    "CreditReceivedPerTradeAvg": 317.19,
    "marginPerTradeAvg": 1026.36,
    "mostMarginUsed": 3088,
    "leastMarginUsed": 221,
    "bestTradePctMargin": 52.25,
    "worstTradePctMargin": -84.62,
    "marginToStockPct": 3.07,
    "riskRewardAvg": 0.4061687,
    "PctOfTimeInMarket": 40.04,
    "BestReturnOnRisk": 0.0085223
  },
  "monthly": [
    {
      "year": 2008,
      "Jan": 0,
      "Feb": 0,
      "Mar": 0,
      "Apr": 0,
      "May": 0.45,
      "Jun": 1.02,
      "Jul": 0,
      "Aug": 0.82,
      "Sep": 0,
      "Oct": 0,
      "Nov": 0,
      "Dec": 0,
      "annReturn": 2.29,
      "annSharpe": 2.78,
      "annSortino": 65.99,
      "annVolatility": 0.82
    },
    {
      "year": 2026,
      "Jan": -0.04,
      "Feb": 0.53,
      "Mar": 0,
      "Apr": 0,
      "May": 0,
      "Jun": -0.59,
      "Jul": -0.76,
      "Aug": 0,
      "Sep": 0,
      "Oct": 0,
      "Nov": 0,
      "Dec": 0,
      "annReturn": -0.86,
      "annSharpe": -0.49,
      "annSortino": -0.8,
      "annVolatility": 1.76
    }
  ],
  "trades": [
    {
      "date": "2008-05-02",
      "ticker": "SPY",
      "leg": 1,
      "ratio": 1,
      "weight": 1,
      "optionType": "call",
      "year": 2008,
      "month": 5,
      "strike": 147,
      "dte": 16,
      "tradeOptPx": 0.14,
      "delta": 0.08,
      "entryStockPx": 141.51,
      "ivPctile": 29.37,
      "exitDate": "2008-05-12",
      "exitStockPx": 140.46,
      "exitOptionPx": 0.01,
      "expirDate": "2008-05-16",
      "expirPx": 142.66,
      "profit": -15,
      "tradeType": "opening",
      "iVolMid": 0.127739,
      "startingConstIv": 0.16066,
      "tradeIv": 0.128
    },
    {
      "date": "2008-05-02",
      "ticker": "SPY",
      "leg": 2,
      "ratio": -1,
      "weight": 1,
      "optionType": "call",
      "year": 2008,
      "month": 5,
      "strike": 143,
      "dte": 16,
      "tradeOptPx": 1.07,
      "delta": 0.38,
      "entryStockPx": 141.51,
      "ivPctile": 29.37,
      "exitDate": "2008-05-12",
      "exitStockPx": 140.46,
      "exitOptionPx": 0.17,
      "expirDate": "2008-05-16",
      "expirPx": 142.66,
      "profit": 88,
      "tradeType": "opening",
      "iVolMid": 0.143535,
      "startingConstIv": 0.16066,
      "tradeIv": 0.1422
    }
  ],
  "returns": [
    {
      "date": "2008-05-02",
      "return": -0.00028267,
      "marginReturn": -0.00952381,
      "profit": -4,
      "count": 1,
      "openingCount": 1
    },
    {
      "date": "2008-05-05",
      "return": -1.36e-06,
      "marginReturn": 0.00013414,
      "profit": 0,
      "count": 2,
      "openingCount": 1
    }
  ]
}

Results Trades

GEThttps://api.orats.io/backtest-finder/results/trades

Retrieves the per-leg trade log for a backtest as CSV. Each row is one leg of one trade. The year and month columns are the year and month of the leg's expiration date; month is zero-padded on some backtests and a bare number on others.

Required attributes

  • Name
    id
    Type
    string
    Description

    The id from a Performance row. Ex: 988c00ada5d823a1821576ec0da4d2a5

GET/backtest-finder/results/trades
curl -L "https://api.orats.io/backtest-finder/results/trades?token=my-token&id=988c00ada5d823a1821576ec0da4d2a5"

Response

date,ticker,leg,ratio,weight,optionType,year,month,strike,dte,tradeOptPx,delta,entryStockPx,ivPctile,exitDate,exitStockPx,exitOptionPx,expirDate,expirPx,profit,tradeType,iVolMid,startingConstIv,tradeIv
2008-05-02,SPY,1,1,1,call,2008,5,147,16,0.14,0.08,141.51,29.37,2008-05-12,140.46,0.01,2008-05-16,142.66,-15,opening,0.127739,0.16066,0.128
2008-05-02,SPY,2,-1,1,call,2008,5,143,16,1.07,0.38,141.51,29.37,2008-05-12,140.46,0.17,2008-05-16,142.66,88,opening,0.143535,0.16066,0.1422

Results Returns

GEThttps://api.orats.io/backtest-finder/results/returns

Retrieves daily returns for a backtest as CSV, covering in-trade days only. The returns and marginReturns columns are fractions of the stock notional and the margin; profit is the day's mark-to-market of the open positions (it does not sum to the trade log's realized profit), and profit, trades, and openingTrades are empty on backtests whose stored returns carry only the two return columns.

Required attributes

  • Name
    id
    Type
    string
    Description

    The id from a Performance row. Ex: 988c00ada5d823a1821576ec0da4d2a5

GET/backtest-finder/results/returns
curl -L "https://api.orats.io/backtest-finder/results/returns?token=my-token&id=988c00ada5d823a1821576ec0da4d2a5"

Response

date,returns,marginReturns,profit,trades,openingTrades
2008-05-02,-0.00028267,-0.00952381,-4,1,1
2008-05-05,-0.00000136,0.00013414,0,2,1
Contact Us
Questions about the API requirements? Want to become an affiliate? Curious about the backtester? Leave us a message and we'll get back to you shortly.
Your email
Your message
Submit
ORATS University
ORATS University
Master the art of options
Research
Implementation
Risk
Review
The opinions and ideas presented herein are for informational and educational purposes only and should not be construed to represent trading or investment advice tailored to your investment objectives. You should not rely solely on any content herein and we strongly encourage you to discuss any trades or investments with your broker or investment adviser, prior to execution. None of the information contained herein constitutes a recommendation that any particular security, portfolio, transaction, or investment strategy is suitable for any specific person. Option trading and investing involves risk and is not suitable for all investors. For more information please see our disclaimer.
Interactive Brokers is not affiliated with Option Research & Technology Services, LLC and does not endorse or recommend any information or advice provided by Option Research & Technology Services, LLC.