> ## Documentation Index
> Fetch the complete documentation index at: https://docs.stratalerts.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Bundle Format

> Complete reference for the StratAlerts NDJSON market bundle: every field, refresh cadence, how to fetch it with your API key, and Python parsing examples.

## Fields and Fetch Reference

The StratAlerts market bundle is a structured snapshot of every tracked symbol delivered as an NDJSON file — one JSON object per line, one line per symbol. It refreshes every 300 seconds (5 minutes), so the data your LLM receives always reflects current market conditions. This page covers the exact bundle format, every available field, how to fetch the bundle, and how to parse it in code.

## File format

The bundle is **NDJSON** (Newline-Delimited JSON). Each line is a valid, self-contained JSON object representing one symbol. This format is intentional: it streams efficiently, parses line by line without loading the entire file into memory, and works cleanly as LLM context input.

```text bundle-0001.ndjson theme={null}
{"Symbol":"SPY","Sector":"ETF","LastPrice":561.40,...}
{"Symbol":"QQQ","Sector":"ETF","LastPrice":477.83,...}
{"Symbol":"AAPL","Sector":"Technology","LastPrice":213.57,...}
```

**Refresh cadence:** Every 300 seconds. The bundle URL does not change — the same URL always returns the latest snapshot.

## Fields

### Identity and price

| Field                | Type              | Description                                                     |
| -------------------- | ----------------- | --------------------------------------------------------------- |
| `Symbol`             | string            | Ticker symbol (e.g., `SPY`, `NQ=F`, `BTC-USD`)                  |
| `Sector`             | string            | Sector classification (e.g., `Technology`, `Financials`, `ETF`) |
| `LastPrice`          | number            | Most recent trade price                                         |
| `LastTradeTimestamp` | string (ISO 8601) | Timestamp of the last trade                                     |
| `LastPriceSource`    | string            | Data source for the last price                                  |

### TFC state

Timeframe continuity (TFC) state is provided for five higher timeframes. Each value is one of `green`, `red`, or `na`.

| Field   | Timeframe | Values               |
| ------- | --------- | -------------------- |
| `TFC_D` | Daily     | `green`, `red`, `na` |
| `TFC_W` | Weekly    | `green`, `red`, `na` |
| `TFC_M` | Monthly   | `green`, `red`, `na` |
| `TFC_Q` | Quarterly | `green`, `red`, `na` |
| `TFC_Y` | Yearly    | `green`, `red`, `na` |

### Candles (OHLCV)

OHLCV bars are included for nine timeframes. Each timeframe block contains: `Time`, `Open`, `High`, `Low`, `Close`, `Volume`.

| Timeframe key | Timeframe |
| ------------- | --------- |
| `Candle_15`   | 15-minute |
| `Candle_30`   | 30-minute |
| `Candle_60`   | 60-minute |
| `Candle_4H`   | 4-hour    |
| `Candle_D`    | Daily     |
| `Candle_W`    | Weekly    |
| `Candle_M`    | Monthly   |
| `Candle_Q`    | Quarterly |
| `Candle_Y`    | Yearly    |

Each candle object looks like:

```json candle object theme={null}
{
  "Time": "2026-04-10T09:30:00Z",
  "Open": 558.20,
  "High": 563.80,
  "Low": 557.40,
  "Close": 561.40,
  "Volume": 42871200
}
```

### Setup fields

Setup fields reflect the current Strat setup state on the daily timeframe by default.

| Field          | Type           | Description                                                            |
| -------------- | -------------- | ---------------------------------------------------------------------- |
| `C2`           | string         | Candle 2 scenario — the prior candle type (e.g., `1`, `2U`, `2D`, `3`) |
| `C1`           | string         | Candle 1 scenario — the current candle type                            |
| `CC`           | string         | Current candle scenario                                                |
| `SetupTarget`  | string         | The identified setup target (price level or label)                     |
| `TriggerGreen` | number \| null | Price level that triggers the bullish side of the setup                |
| `TriggerRed`   | number \| null | Price level that triggers the bearish side of the setup                |
| `Continuation` | boolean        | Whether the setup is a continuation setup                              |
| `InForce`      | boolean        | Whether the setup is currently in-force (trigger has been breached)    |
| `P3`           | boolean        | Whether the setup is a P3 (potential 3)                                |
| `PMG`          | boolean        | Whether a PMG (potential major gap) flag is set                        |

## Sample bundle row

This shows a complete single-symbol row from the bundle:

```json sample row (SPY) theme={null}
{
  "Symbol": "SPY",
  "Sector": "ETF",
  "LastPrice": 561.40,
  "LastTradeTimestamp": "2026-04-10T14:35:22Z",
  "LastPriceSource": "consolidated",
  "TFC_D": "green",
  "TFC_W": "green",
  "TFC_M": "red",
  "TFC_Q": "red",
  "TFC_Y": "green",
  "Candle_D": {
    "Time": "2026-04-10T09:30:00Z",
    "Open": 558.20,
    "High": 563.80,
    "Low": 557.40,
    "Close": 561.40,
    "Volume": 42871200
  },
  "Candle_W": {
    "Time": "2026-04-07T09:30:00Z",
    "Open": 549.10,
    "High": 564.90,
    "Low": 546.30,
    "Close": 561.40,
    "Volume": 198450000
  },
  "C2": "1",
  "C1": "2U",
  "CC": "2U",
  "SetupTarget": "564.90",
  "TriggerGreen": 563.80,
  "TriggerRed": 557.40,
  "Continuation": false,
  "InForce": false,
  "P3": false,
  "PMG": false
}
```

## Fetching the bundle

Send an HTTP GET to your bundle URL with your API key in the `X-API-Key` header:

<CodeGroup>
  ```bash cURL theme={null}
  curl -H "X-API-Key: YOUR_API_KEY" \
    https://app.stratalerts.com/api/v1/bundles/latest.ndjson
  ```

  ```python Python theme={null}
  import requests

  response = requests.get(
      "https://app.stratalerts.com/api/v1/bundles/latest.ndjson",
      headers={"X-API-Key": "YOUR_API_KEY"},
  )
  response.raise_for_status()
  bundle_text = response.text
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    "https://app.stratalerts.com/api/v1/bundles/latest.ndjson",
    {
      headers: { "X-API-Key": "YOUR_API_KEY" },
    }
  );
  const bundleText = await response.text();
  ```
</CodeGroup>

Your bundle URL and API key are available in **Account → AI Tools** after subscribing.

## Parsing the bundle in Python

This example fetches the bundle, parses every row, and filters for symbols that are in-force on the daily:

```python parse and filter bundle theme={null}
import json
import requests

def fetch_bundle(api_key: str) -> list[dict]:
    url = "https://app.stratalerts.com/api/v1/bundles/latest.ndjson"
    response = requests.get(url, headers={"X-API-Key": api_key})
    response.raise_for_status()
    rows = []
    for line in response.text.splitlines():
        line = line.strip()
        if line:
            rows.append(json.loads(line))
    return rows

def in_force_daily(rows: list[dict]) -> list[dict]:
    return [r for r in rows if r.get("InForce") is True]

rows = fetch_bundle("YOUR_API_KEY")
active = in_force_daily(rows)

for symbol in active:
    print(f"{symbol['Symbol']} — {symbol['CC']} — in force at {symbol['TriggerGreen'] or symbol['TriggerRed']}")
```

<Tip>
  Parse the bundle line by line rather than loading the entire file into memory at once. For large universes, streaming line-by-line reduces memory overhead significantly.
</Tip>

## Related

<CardGroup cols={2}>
  <Card title="AI Tools overview" icon="brain" href="/ai-tools/overview">
    How AI Tools works, compatible models, and pricing.
  </Card>

  <Card title="AI Search" icon="magnifying-glass" href="/ai-tools/ai-search">
    Run natural language queries directly inside the StratAlerts setups table — no API key or code required.
  </Card>
</CardGroup>
