# Backtest Finder API

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](https://orats.com/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](https://orats.com/data-api#tools-apis) of the Data API page.

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

---

## Catalog

`GET https://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.

**cURL**

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

**Response**

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

---

## Performance

`POST https://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

- `ticker` (string): The underlying symbol to search. Ex: SPY
- `strategy` (string): The strategy to search, from the precomputed list above. Ex: IronCondor
- `rank` (string): 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

- `rankDir` (string): Orders the rank positions: asc returns the best-ranked rows first, desc returns the worst first. Defaults to asc.
- `filters` (object): 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.
- `screen` (boolean): 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.
- `currentEnvironment` (object): 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.

**cURL**

```bash
curl -L "https://api.orats.io/backtest-finder/performance?token=my-token" \
  -H "Content-Type: application/json" \
  -d '{
    "ticker": "SPY",
    "strategy": "IronCondor",
    "currentEnvironment": null,
    "filters": {},
    "rank": "bestReturnOnRisk",
    "rankDir": "asc"
  }'
```

**Response**

```json
[
  {
    "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

`GET https://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

- `id` (string): The id from a Performance row. Ex: 988c00ada5d823a1821576ec0da4d2a5

**cURL**

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

**Response**

```json
[
  {
    "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

`POST https://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

- `body` (array): A JSON array of strategy names from the precomputed list. Ex: ["IronCondor","IronButterfly"]

**cURL**

```bash
curl -L "https://api.orats.io/backtest-finder/performance/environment?token=my-token" \
  -H "Content-Type: application/json" \
  -d '["IronCondor"]'
```

**Response**

```json
[
  {
    "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

`GET https://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

- `id` (string): The rootBaseId from a Performance row. Ex: 0d2284dc0eeef69b2042b14a04859a72

**cURL**

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

**Response**

```json
{
  "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

`GET https://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

- `id` (string): The id from a Performance row. Ex: 988c00ada5d823a1821576ec0da4d2a5

**cURL**

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

**Response**

```json
{
  "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

`GET https://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

- `id` (string): The id from a Performance row. Ex: 988c00ada5d823a1821576ec0da4d2a5

**cURL**

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

**Response**

```json
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

`GET https://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

- `id` (string): The id from a Performance row. Ex: 988c00ada5d823a1821576ec0da4d2a5

**cURL**

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

**Response**

```json
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
```
