Core Concepts

Execution Model

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.

  1. 1

    Setup Phase

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

    TaskDescription
    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
  2. 2

    Calculate Phase

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

    TaskDescription
    Calculate indicatorsrsi(...), ema(...), sma(...)
    Store temporary values in varFor comparisons, colors, or per-candle logic
    Make decisionsUse if/else to compare values
  3. 3

    Display Phase

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

    FunctionUse Case
    plotLine(...)Lines for RSI, moving averages, etc.
    plotBar(...)Vertical bars for volume, histograms
    plotShape(...)Markers, arrows, labels for signals

Understanding the Flow

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

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

Limitations and Constraints

  • 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 Onlytimeseries 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 Persistencevar variables cannot maintain state between bars. Use timeseries for values that need historical access, or static for persistent values.

Example: Complete Indicator Structure

//@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);