# Limits

> What each asset class and each indicator language can and cannot do, the bar ceilings on a run, and which timeframes your plan may use.

Source: https://docs.texttoquant.com/reference/limits

---

Everything here is enforced by the engine, so you meet these as a refusal before a run starts, not as
a wrong number afterwards. Three kinds of limit get mixed up constantly, and they behave differently:

| Kind | Example | What changes it |
| --- | --- | --- |
| **Capability** | The engine runs 16 timeframes | Nothing you can buy. It is what the code does. |
| **Entitlement** | Your plan may use 6 of them | Your [plan](/pricing). |
| **Data** | No stock has pre-market bars | Nothing. The data does not exist. |

## Timeframes

The engine runs sixteen, and so does the parser:

```text
1m  3m  5m  15m  30m  45m  1h  2h  4h  6h  8h  12h  1d  3d  1w  1M
```

`1M` is a **month**. `1m` is one minute. Case is the only thing that separates them.

Which of the sixteen you may run is a plan entitlement, and the pickers in the app show exactly your
list, so you cannot choose one you do not have. The [pricing page](/pricing) has the per-plan count.
Over the API or MCP, `get_usage` returns `allowedTimeframes`. Asking for one outside your list parses
cleanly and is then refused with `plan_timeframe_limit`.

<Callout variant="warning" title="Anything else is not a timeframe">
  `2d`, `2w`, `90m` and `3h` have no bar duration in the engine, on any plan. They are refused at
  parse with the runnable list attached, not silently rounded to something near them.
</Callout>

## How much history one run may ask for

Years and bars are separate limits and you meet whichever you hit first. "Unlimited history" on a
plan means unlimited **years**. The **bar** ceilings are the same for everyone:

| Run | Ceiling |
| --- | --- |
| Any single run | 2,000,000 bars |
| One asset, built-in indicators only | 4,000,000 bars |
| A portfolio, summed across every sleeve | 500,000 bars |
| Any run using a custom indicator | 350,000 bars |

A run over the ceiling is refused up front, naming a shorter range or a higher timeframe, rather than
being accepted and dying part-way through. Ten years of 1-minute data is about 5.2 million bars, so it
is over the limit on every plan; the same decade on 5m is not.

## Asset classes

| | Crypto | Equities | Forex | Metals |
| --- | --- | --- | --- | --- |
| **Name it** | `BTC`, `BTCUSDT` | `AAPL`, `NASDAQ:AAPL` | `EURUSD` | `XAUUSD`, `gold` |
| **Data** | Binance and other major venues | TradingView oracle | TradingView oracle | TradingView oracle |
| **Session** | 24/7 | US regular hours, 09:30 to 16:00 ET | Continuous 24x5 | Continuous 24x5 |
| **Trading year** | 365 days | 252 days | 260 days | 260 days |
| **Depth** | The pair's full listing history | See below | See below | See below |
| **Default cost** | 0.05% fee + 0.02% slippage | 0.01% fee + 0.02% slippage | 0.01% slippage, no commission | 0.015% slippage, no commission |
| **Funding, open interest, basis** | Yes | No | No | No |
| **Stops in pips** | No | No | **Yes** | No |
| **Overnight swap** | Not applicable | Not applicable | **Modelled** | Not modelled |

**What each "no" actually means.** Open interest and funding are read from Binance, so there is no
series to read on a stock or a currency pair. A pip is defined for a currency pair and nowhere else:
brokers quote gold in both 0.01 and 0.1 and call either one a pip, so a stop in pips on gold is
refused by name rather than guessed at. Metals accrue no swap because no lease-rate series exists to
compute one from, and treating it as zero would assert that gold has no carry, which is false.

Forex swap is modelled from central-bank and overnight-interbank rates for 15 currencies, charged per
rollover night with the usual Wednesday triple. **CNH, SGD and HKD trade but accrue no swap**, because
no overnight rate series is published for them; the run says so rather than charging zero quietly.

<Callout variant="info" title="Equities, forex and metals share one data path">
  All three are served by the TradingView oracle, which returns up to 50,000 bars per request. A
  longer range is fetched in slices, so **depth costs waiting, not bars**: your ceiling is the bar
  table above. The oracle's budget is shared across everyone using the platform, so a very deep
  intraday stock range can take a few minutes to assemble.
</Callout>

Pre-market and after-hours prints are not in the equities feed at all, so a strategy cannot trade
them. Egypt (EGX) is supported alongside US equities, with its own holiday tolerance.

## Writing your own indicator

Four ways, and they are not interchangeable. The gate is per plan; see the [pricing
page](/pricing) for which tier carries which.

| | Pine Script | JavaScript | Python | CSV upload |
| --- | --- | --- | --- | --- |
| **Runs where** | TradingView, via our oracle | Our sandbox | Our sandbox | Nowhere, the values are already computed |
| **Pinned to a symbol/timeframe** | **Yes**, recompiled per symbol | No | No | **Yes**, to the file's range |
| **Works on every asset class** | Yes | Yes | Yes | Yes |
| **Time budget** | Oracle round trip | 3 seconds | 3 seconds | Not applicable |
| **Memory** | Not applicable | 64 MB | 64 MB | Not applicable |
| **Size limit** | 100,000 characters | 128 KB | 128 KB | 5 MB, 100,000 rows |
| **Plots / inputs** | Pine's own | 12 / 24 | 12 / 24 | One column each |
| **Bars per run** | 350,000 | 350,000 | 350,000 | 350,000 |

**Pine goes through TradingView on every asset class, including crypto.** Crypto candles come from
Binance, but a Pine indicator in that run is still compiled by the oracle against the same symbol, so
it spends the shared request budget that crypto data itself never touches. A long crypto backtest with
a Pine indicator is slower than the same backtest with a built-in one for exactly that reason.

JavaScript and Python are the same capability with the same helpers and the same numbers. Neither is
pinned to anything: the saved indicator recomputes against whatever bars a run uses, so one indicator
works on every symbol and every timeframe. Neither can reach the network, read the clock, or use
randomness, so a backtest reproduces. See [JavaScript](/docs/reference/javascript-indicators) and
[Python](/docs/reference/python-indicators).

A CSV carries values you computed elsewhere. It is aligned onto the run's bars by timestamp, and it
covers only the dates in the file, so using it on another symbol or a later range means uploading
again.

## Portfolios

A book holds one asset class and one session calendar. A mixed book is refused, naming both sleeves,
because two session grids and two annualisation bases cannot share one equity curve. The v1 portfolio
path is spot crypto, up to 20 assets; see [Portfolios](/docs/reference/portfolio).

## What the engine will not do at all

- **No pre-market or after-hours equities data.** The feed carries regular-hours bars only.
- **No trading-calendar lookup.** Holidays are inferred from gaps in the data, tolerated up to 4.5
  days for US venues and 11 for Egypt.
- **No broker-specific spreads or swap rates.** Every cost applied when your query does not state one
  is a documented default, labelled `assumed` on the run.
- **No regime attribution below 5 trades or 60 bars.** The run says why instead of showing an empty
  panel.

Related: [Markets & data](/docs/reference/markets), [Costs & fees](/docs/concepts/costs),
[Plans & credits](/docs/concepts/plans-and-credits).
