TradingCharts

Compute Budget Exceeded

A computation ran past its wall-clock budget (2 s per live tick, 10 s for a full recompute). What the budgets are, how pacing avoids the error, and the usual causes.

What the budgets are

Computation Budget When it runs
Full compute (computeFull) 10 s On start, on every bar close for cumulative scripts, and after a history reload — the whole loaded history (up to 5,000 bars) in one pass.
Live tick (computeTick) 2 s Every price update on the forming bar.
Loop guard 100,000 iterations per loop Compiled into every for / while: the loop exits when its counter passes the guard, the script continues.
Backtest 60 s (+1 s per 2,500 bars) A Strategy Tester run; stopped and reported as failed beyond it.

A slow script is not killed on the first slow tick. Live ticks are paced: a tick that takes longer than 150 ms moves the script to a slower tier that recomputes at most every 5 s, then 30 s, then 60 s (always on the latest price; bar closes are never skipped). The legend shows a ⏱ chip with "Updating every 30s" while this is happening. Only a single computation that runs past the hard budget above produces this error.

Common causes

1. while with no shrinking guard

i = 0
while condition
    i := i + 1          // but `condition` doesn't shrink → spins until the loop guard trips

Add an explicit upper bound:

i = 0
while condition and i < 10_000
    i := i + 1

2. Nested loop over bar_index

for i = 0 to bar_index          // ⚠ grows with history: 5,000 × 100 iterations per bar
    for j = 0 to 100
        …

The outer bound keeps growing. Replace with a fixed lookback or a dedicated array of recent values.

3. Recomputing history on every tick

A script whose result depends on the whole history (ta.cum, ta.obv, running totals in var arrays, request.security on many symbols) is recomputed from the first bar on every live tick. Prefer the streaming ta.* functions, keep per-bar state in var variables, and read Profiling and optimization.

4. request.security with a target that varies per bar

Each unique (symbol, timeframe) pair is fetched once per computation, up to 512 pairs. A symbol string built from per-bar data creates a new pair every bar:

sym = str.tostring(bar_index)       // ⚠ unique per bar
x = request.security(sym, "D", close)

See also