Skip to content

Pine Script to CodeLab Migration

Side-by-side guide for converting TradingView Pine Script indicators to ChartLabs CodeLab.

Key Differences

AspectPine ScriptCodeLab
LanguagePine ScriptTypeScript
StructureTop-level functionsClass-based (extends Script)
Entry pointindicator() / strategy()class extends Script/Strategy
LifecycleImplicitcalculate() method
Statevar keywordthis.setState() / this.getState()
Functionsta.sma()this.sma()
Inputsinput.int()input.number()
Plottingplot()plot() (similar syntax)
Colorscolor.greencolor.green (same!)

Function Mapping

Moving Averages

Pine ScriptCodeLab
ta.sma(close, 14)this.sma('close', 14)
ta.ema(close, 14)this.ema('close', 14)
ta.wma(close, 14)this.wma('close', 14)
ta.rma(close, 14)this.rma('close', 14)
ta.dema(close, 14)this.dema('close', 14)
ta.tema(close, 14)this.tema('close', 14)
ta.hma(close, 14)this.hma('close', 14)
ta.vwma(close, 14)this.vwma('close', 14)
ta.linreg(close, 14, 0)this.linreg('close', 14)

Indicators

Pine ScriptCodeLab
ta.rsi(close, 14)this.rsi('close', 14)
ta.atr(14)this.atr(14)
ta.cci(close, 20)this.cci('close', 20)
ta.mfi(close, 14)this.mfi(14)
ta.obvthis.obv()
ta.stdev(close, 14)this.stdev('close', 14)
ta.bb(close, 20, 2)this.bbands('close', 20, 2)
ta.macd(close, 12, 26, 9)this.macd('close', 12, 26, 9)
ta.stoch(close, high, low, 14)this.stoch(14, 3, 3)
ta.supertrend(3, 10)this.supertrend(10, 3)
ta.dmi(14)this.adx(14)

Range & Utility

Pine ScriptCodeLab
ta.highest(high, 14)this.highest('high', 14)
ta.lowest(low, 14)this.lowest('low', 14)
math.sum(close, 14)this.sum('close', 14)
ta.trthis.trueRange()
ta.change(close)this.change('close')
ta.roc(close, 14)this.roc('close', 14)
ta.percentrank(close, 14)this.percentRank('close', 14)
ta.barssince(cond)this.barsSince(cond)
ta.valuewhen(cond, close, 0)this.valuewhen(cond, 'close')
ta.rising(close, 3)this.rising('close', 3)
ta.falling(close, 3)this.falling('close', 3)

Crossovers

Pine ScriptCodeLab
ta.crossover(fast, slow)this.crossOver(fast, slow, prevFast, prevSlow)
ta.crossunder(fast, slow)this.crossUnder(fast, slow, prevFast, prevSlow)

WARNING

CodeLab crossover functions need 4 arguments (current + previous for both series). Use this.getPlot() to get previous values.

Inputs

Pine ScriptCodeLab
input.int("Period", 14)input.number('Period', 14)
input.float("Mult", 2.0)input.number('Mult', 2.0, { step: 0.1 })
input.source(close)input.source('Source', 'close')
input.bool("Show", true)input.boolean('Show', true)
input.color(color.blue)input.color('Color', '#3b82f6')
input.string("fast", options=...)input.string('Mode', 'fast', { options: [...] })

Plotting

Pine ScriptCodeLab
plot(val, "Name", color.blue)plot('Name', val, { color: color.blue })
hline(70)hline('Level', 70, { color: color.red })
plotshape(cond, ...)plotShape('Name', cond, { ... })
bgcolor(color.new(...))bgcolor('#rrggbbaa')
barcolor(c)barcolor(c)

State (Variables)

Pine ScriptCodeLab
var float x = nathis.setState('x', 0) on first bar
x := newValuethis.setState('x', newValue)
Read: xthis.getState('x')

Full Conversion Example

Pine Script (Original)

//@version=5
indicator("RSI with MA", overlay=false)

length = input.int(14, "RSI Period", minval=2)
maLength = input.int(9, "MA Period", minval=1)
src = input.source(close, "Source")

rsiVal = ta.rsi(src, length)
rsiMA = ta.sma(rsiVal, maLength)

plot(rsiVal, "RSI", color.purple, 2)
plot(rsiMA, "RSI MA", color.orange, 1)
hline(70, "OB", color.red)
hline(30, "OS", color.green)

CodeLab (Converted)

typescript
import { Script, input, plot, hline, color } from '@chartlabs/script-sdk';

export default class RSIWithMA extends Script {
  length = input.number('RSI Period', 14, { min: 2, max: 200 });
  maLength = input.number('MA Period', 9, { min: 1, max: 100 });
  source = input.source('Source', 'close');

  calculate() {
    const rsiVal = this.rsi(this.source, this.length);
    plot('RSI', rsiVal, { color: color.purple, width: 2 });

    // SMA of RSI — pass the numeric RSI value as source
    const rsiMA = this.sma(rsiVal, this.maLength);
    plot('RSI MA', rsiMA, { color: color.orange, width: 1 });

    hline('OB', 70, { color: color.red, style: 'dashed' });
    hline('OS', 30, { color: color.green, style: 'dashed' });
  }
}

Key Migration Notes

  1. Class-based: Wrap everything in a class extending Script
  2. this. prefix: All SDK functions need this. (this.sma, this.ema, etc.)
  3. String sources: Pass series names as strings ('close' not close)
  4. Explicit imports: Import only what you use from @chartlabs/script-sdk
  5. Plot order: Name comes first in CodeLab: plot('Name', value, opts) vs Pine's plot(value, "Name", ...)
  6. crossOver needs 4 args: Biggest gotcha — you must provide previous bar values too
  7. No na value: Use 0, NaN, or conditional logic for uninitialized state
  8. State management: Replace Pine's var with setState/getState

ChartLabs Documentation