---
title: Execution Model
description: >-
  Understanding how kScript v2 processes your code through its three-phase
  lifecycle for optimal performance and predictable behavior.
---


Every indicator follows a simple recipe: **Setup once → Calculate per candle → Display per candle.**

{% stepper %}
{% step %}
**Setup Phase**

Runs once when your indicator first loads. Prepare everything your indicator needs before processing any candles.

| Task | Description |
|------|-------------|
| Call `define(...)` | Required — tells kScript about your indicator |
| Create settings with `input(...)` | Optional — let users adjust period, colors, etc. |
| Get data with `ohlcv(...)` | Create all `timeseries` here |

{% endstep %}

{% step %}
**Calculate Phase**

Runs for each candle on the chart. Process indicator calculations. This repeats for every candle, computing values based on your defined logic.

| Task | Description |
|------|-------------|
| Calculate indicators | `rsi(...)`, `ema(...)`, `sma(...)` |
| Store temporary values in `var` | For comparisons, colors, or per-candle logic |
| Make decisions | Use `if/else` to compare values |

{% hint style="warning" %}
Don't create `timeseries` in the Calculate phase — use the ones from Setup.
{% endhint %}
{% endstep %}

{% step %}
**Display Phase**

Runs for each candle, after calculations. Draw your indicator on the chart using the calculated values.

| Function | Use Case |
|----------|----------|
| `plotLine(...)` | Lines for RSI, moving averages, etc. |
| `plotBar(...)` | Vertical bars for volume, histograms |
| `plotShape(...)` | Markers, arrows, labels for signals |

{% hint style="success" %}
You can use multiple plot functions in one indicator.
{% endhint %}
{% endstep %}
{% endstepper %}


## Understanding the Flow

```text
Phase 1 (Setup runs once)
    ↓
Phase 2 (Calculate for candle 1) → Phase 3 (Display candle 1)
    ↓
Phase 2 (Calculate for candle 2) → Phase 3 (Display candle 2)
    ↓
...and so on for every candle
```


## Key Characteristics

<table data-view="cards"><tbody>
<tr><td>Deterministic Results</td><td>Given the same input data, a script will always produce identical output. Essential for reliable backtesting and strategy validation.</td><td></td></tr>
<tr><td>Immutable Historical Data</td><td>`timeseries` objects provide read-only access to historical values. Past data cannot be modified, ensuring data integrity.</td><td></td></tr>
<tr><td>Efficient Memory Usage</td><td>Only current bar calculations are held in memory. Historical data is managed by the runtime with optimized caching.</td><td></td></tr>
<tr><td>Real-time Compatibility</td><td>The same script logic handles both historical analysis and live data processing without special handling.</td><td></td></tr>
</tbody></table>


## Limitations and Constraints

{% hint style="warning" %}
Keep these constraints in mind when writing your indicators.
{% endhint %}

- **No Future Data Access** — Scripts cannot access data from future bars (e.g., `ts[-1]` is invalid). This prevents look-ahead bias in analysis.
- **Global Scope `timeseries` Only** — `timeseries` declarations must be in global scope. They cannot be declared inside functions, loops, or conditional blocks.
- **Execution Time Limits** — scripts must complete execution within 500ms (excluding data fetch). This ensures responsive chart rendering and prevents infinite loops.
- **No Cross-Bar Variable Persistence** — `var` variables cannot maintain state between bars. Use `timeseries` for values that need historical access, or `static` for persistent values.


## Example: Complete Indicator Structure

```javascript
//@version=2

// ====== PHASE 1: SETUP ======
define(title="RSI Indicator", position="offchart", axis=true);

// User inputs
var period = input(name="period", type="number", defaultValue=14, label="RSI Period");
var overbought = input(name="overbought", type="number", defaultValue=70, label="Overbought Level");
var oversold = input(name="oversold", type="number", defaultValue=30, label="Oversold Level");

// Data source (timeseries created here)
timeseries ohlcvData = ohlcv(symbol=currentSymbol, exchange=currentExchange);

// ====== PHASE 2: CALCULATE ======
// Calculate RSI
var rsiValue = rsi(source=ohlcvData.close, period=period);

// Determine color based on value
var colorIndex = rsiValue > overbought ? 0 : (rsiValue < oversold ? 1 : 2);

// ====== PHASE 3: DISPLAY ======
plotLine(value=rsiValue, width=2, colors=["red", "green", "blue"], colorIndex=colorIndex, label=["RSI"], desc=["Relative Strength Index"]);

// Draw horizontal reference lines
hline(overbought, "red", 1);
hline(oversold, "green", 1);
```
