Complete Suite: all 12 tools. 6 Premium desks inside.All 12 tools $606.98 one by one

$606.98 one by one $97 once Save $509.98Get the SuiteGet it

thinkScript to Pine Script converter

Paste a thinkorswim study or strategy: the Pine Script v6 appears beside it, each line tagged with the thinkScript line it came from.

Updated 25 October 2026. Runs in your browser; nothing you type is uploaded.

Sample studyPine Script v6, ready to paste

Pine Script v6numbers: its thinkScript line

// Converted from thinkScript with ProEA's thinkScript to Pine converter.
// TradingView's compiler is the final word: paste it into the Pine Editor and add it to a chart.
//@version=6
indicator("EMA cross with arrows and a label", overlay = true)
// EMA cross with arrows and a label
fastLength = input.int(9, "fastLength")
slowLength = input.int(21, "slowLength")
price = input.source(close, "price")
fastAvg = ta.ema(price, fastLength)
slowAvg = ta.ema(price, slowLength)
Fast = fastAvg
Slow = slowAvg
BuySignal = ta.crossover(fastAvg, slowAvg)
SellSignal = ta.crossunder(fastAvg, slowAvg)
alertcondition(BuySignal, "EMA cross up", "EMA cross up")
p_Fast = plot(Fast, "Fast", color = #00FFFF)
p_Slow = plot(Slow, "Slow", color = #FFC800, linewidth = 2)
plotshape(BuySignal, "BuySignal", shape.arrowup, location.belowbar, color = #00FF00, size = size.small)
plotshape(SellSignal, "SellSignal", shape.arrowdown, location.abovebar, color = #FF0000, size = size.small)
fill(p_Fast, p_Slow, color = Fast > Slow ? color.new(#00FF00, 70) : color.new(#FF0000, 70))
var table _labels = table.new(position.top_left, 1, 1)
table.cell(_labels, 0, 0, fastAvg > slowAvg ? "Trend: up" : "Trend: down", bgcolor = fastAvg > slowAvg ? #00FF00 : #FF0000, text_color = color.black, text_size = size.small)

An indicator

All 19 statements converted to Pine v6

Our Pine checker finds nothing to fix. TradingView's compiler is the final word.

  • Notepick this condition in TradingView's alert dialog; the sound is chosen there too

Share this calculator

Post on XPost to Reddit
Embed or cite it on your site

Free on any site, blog, Notion page or Substack: paste this code to show the live calculator. The credit line is optional; keep it, edit it, add rel="nofollow" or remove it.

<iframe src="https://proea.app/embed/tools/thinkscript-to-pine-converter" title="thinkScript to Pine Script converter" loading="lazy" referrerpolicy="strict-origin-when-cross-origin" style="display:block;width:100%;height:1420px;border:0;border-radius:12px"></iframe>
<p style="font-size:12px">thinkScript to Pine Script converter by <a href="https://proea.app/en/tools/thinkscript-to-pine-converter?utm_source=embed&utm_medium=referral&utm_campaign=thinkscript-to-pine-converter">ProEA</a></p>

Writing about it instead? Cite the method and link the page:

The math: Average(close, 20) → ta.sma(close, 20) · a crosses above b → ta.crossover(a, b) · close(period = AggregationPeriod.DAY) → request.security(syminfo.tickerid, "D", close)

thinkScript functions in Pine Script

Each row is what the converter writes for it.

thinkScriptPine Script v6
def x = Average(close, 20);x = ta.sma(close, 20)
def x = ExpAverage(close, 20);x = ta.ema(close, 20)
def x = WildersAverage(close, 14);x = ta.rma(close, 14)
def x = MovingAverage(AverageType.HULL, close, 20);x = ta.hma(close, 20)
def x = Highest(high, 20);x = ta.highest(high, 20)
def x = Sum(volume, 10);x = math.sum(volume, 10)
def x = StDev(close, 20);x = ta.stdev(close, 20)
def x = TrueRange(high, close, low);x = ta.tr(true)
def x = ATR(14);x = ta.atr(14)
def x = RSI(14);x = ta.rsi(close, 14)
def x = MACD().Diff;[_macdValue1, _macdAvg1, _macdDiff1] = ta.macd(close, 12, 26, 9) x = _macdDiff1
def x = BollingerBands().UpperBand;x = ta.sma(close, 20) + 2.0 * ta.stdev(close, 20)
def x = close crosses above Average(close, 50);x = ta.crossover(close, ta.sma(close, 50))
def x = if close > open then 1 else -1;x = close > open ? 1 : -1
def x = IsNaN(close[1]);x = na(close[1])
def x = AbsValue(close - open);x = math.abs(close - open)
def x = BarNumber();x = bar_index + 1
def x = GetValue(close, 5);x = close[5]

Other timeframes and symbols

thinkScript reads them inside any expression; Pine asks request.security().

thinkScriptPine Script v6
def x = close(period = AggregationPeriod.DAY);x = request.security(syminfo.tickerid, "D", close)
def x = high(period = AggregationPeriod.DAY)[1];x = request.security(syminfo.tickerid, "D", high[1], lookahead = barmerge.lookahead_on)
def x = Average(close(period = AggregationPeriod.WEEK), 20);x = request.security(syminfo.tickerid, "W", ta.sma(close, 20))
def x = close(symbol = "SPX");x = request.security("SP:SPX", timeframe.period, close)
Why yesterday's high uses lookahead

On an intraday chart, high(period = AggregationPeriod.DAY) is today's high so far, and it changes until the day closes: Pine's request.security() without lookahead behaves the same way. Offset by a day first ([1]) and the value is finished, so asking for it with lookahead_on is safe and doesn't repaint: every bar sees yesterday's high as it was. A whole expression on another timeframe, such as a 20-week average, goes into one request, so the average is taken over weeks, as thinkorswim takes it.

Plots, bubbles, colours and orders

A plot's styles, set on later lines, fold into one plot() call.

thinkScriptPine Script v6
plot Avg = Average(close, 20); Avg.SetDefaultColor(Color.CYAN); Avg.SetLineWeight(2);Avg = ta.sma(close, 20) plot(Avg, "Avg", color = #00FFFF, linewidth = 2)
plot Hist = close - open; Hist.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);Hist = close - open plot(Hist, "Hist", style = plot.style_histogram)
plot Up = close crosses above open[1]; Up.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);Up = ta.crossover(close, open[1]) plotshape(Up, "Up", shape.arrowup, location.belowbar, size = size.small)
plot Line = close; Line.AssignValueColor(if close > open then Color.GREEN else Color.RED);Line = close plot(Line, "Line", color = close > open ? #00FF00 : #FF0000)
AddChartBubble(close > high[1], high, "Break", Color.GREEN, yes);if close > high[1] label.new(bar_index, high, "Break", color = #00FF00, textcolor = color.black, style = label.style_label_down, size = size.small)
AssignPriceColor(if close > open then Color.GREEN else Color.CURRENT);barcolor(close > open ? #00FF00 : na)
def go = close crosses above Average(close, 20); AddOrder(OrderType.BUY_AUTO, go);go = ta.crossover(close, ta.sma(close, 20)) if go strategy.entry("Long", strategy.long)

What doesn't convert

Marked TODO in the code and listed with its line; the rest still compiles.

Future bars, thinkorswim data, thinkorswim-only studies
  • A negative offset such as close[-1] reads a bar that hasn't happened yet. Pine can't, so the value becomes na and the line is marked.
  • imp_volatility and open_interest are thinkorswim data a Pine script isn't given.
  • TTM_Squeeze, ZigZagHighLow and other thinkorswim-only studies have no Pine source to call: rebuild them from their formula.
  • HighestAll() and LowestAll() read the whole chart, later bars too; ta.max() and ta.min() give the highest and lowest so far.
  • thinkScript's vwap price is each bar's own volume-weighted price, which TradingView doesn't give a script: hlc3 stands in. reference VWAP() converts to the session VWAP.
  • SetHiding() and the alert sound have no Pine setting; the sound is picked in TradingView's alert dialog.

For the lines left to finish, Pine Fixer gives your AI the Pine v6 rules and the compiler's own error texts, and the Pine Script checker reads the result for repaint risks.

Method and privacy

Method: The converter reads thinkScript the way thinkorswim does (case-insensitive names, numbers as booleans, plots styled by later statements) and writes Pine Script v6: averages and studies as their ta.* functions, crosses as ta.crossover and ta.crossunder, other timeframes through request.security(), labels as a table, bubbles as labels, clouds as fill(), AddOrder as strategy orders. A line it can't prove (a future bar, data TradingView doesn't give scripts, a thinkorswim-only study) keeps a typed placeholder and a TODO. The result is checked by this site's Pine checker; TradingView's compiler is the final word. Nothing leaves your browser.

Calculations run entirely in your browser — nothing you type is uploaded. Your last numbers stay in this browser so you can pick up where you left off; Forget them clears them. A link with your numbers carries them after the # sign, which browsers do not send to servers, and the page takes them out of the address before any analytics loads. Copy and download actions save your calculation locally. The site may record coarse tool actions under its privacy policy, without inputs, results, file contents or filenames.

Common questions

Can you convert thinkScript to Pine Script?

Most of a study, line for line: inputs, defs, plots and their colours, averages and built-in studies, crosses, labels, chart bubbles, clouds, other timeframes and AddOrder strategies. What has no Pine equivalent is marked TODO with its line: offsets into future bars such as close[-1], thinkorswim-only data such as imp_volatility, and proprietary studies such as TTM_Squeeze.

What is ExpAverage in Pine Script?

ExpAverage(close, 20) is ta.ema(close, 20). Average is ta.sma, WildersAverage is ta.rma, WMA is ta.wma, and MovingAverage(AverageType.HULL, close, 20) is ta.hma(close, 20). When the average type is an input, the converter adds a small _ma() function that picks the right one.

How do I get the previous day's high in Pine Script from thinkScript?

high(period = AggregationPeriod.DAY)[1] becomes request.security(syminfo.tickerid, "D", high[1], lookahead = barmerge.lookahead_on). Offsetting by one day before asking with lookahead is the pattern that doesn't repaint: each bar sees yesterday's finished high.

How do thinkScript plots and labels convert?

A thinkScript plot is a value plus styles set by later lines; Pine draws it with one plot() call, so SetDefaultColor becomes color, SetLineWeight linewidth and PaintingStrategy.HISTOGRAM style = plot.style_histogram. Boolean arrows become plotshape(), AddLabel a cell in a table at the top left, AddChartBubble label.new() and AddCloud fill().

Why are some lines marked TODO?

thinkScript can read bars that haven't happened yet with a negative offset, and it has studies and data TradingView doesn't give a Pine script. The converter won't guess at those: it leaves a typed placeholder (na, false or empty text) so the rest compiles, marks the line, and lists it with its thinkScript line number.

Is my thinkScript sent anywhere?

No. The converter runs in your browser: the script isn't uploaded, stored or put in the page's link. Paste the Pine it writes into TradingView's Pine Editor, whose compiler is the final word.

Fix, build or get finished Pine v6

  • Pine Fixer An AI skill pack for 45 compiler-verified Pine v6 failure classes, with a repaint clinic. $9.99 once.
  • Pine Starter Stack Prompt Vault, Builder Lite and Pine Fixer in one zip. $19.99 once.
  • Pine Pro Library 19 TradingView desks with their full Pine v6 source and every update. $49 once.

Goes deeper

Limits and trading risk

These tools calculate from your inputs, supported historical records or explicitly labelled teaching examples. They do not verify a live account, predict future returns or confirm that a broker or prop-firm rule has been met. Missing costs, floating losses and changed market conditions can materially change outcomes. Trading can lose the capital committed to it; check the stated method and your account specifications.

Read the risk disclosure