Pine Script Basics: Write Your First TradingView Indicator

Intermediate8 min read
Lines of colour-highlighted program code on a blurred screen
Image by Smile_Eh on Wikimedia Commons, CC0

How Do You Write Your First Pine Script Indicator?

Open the Pine Editor on a TradingView chart, start a new indicator and replace the template with a version line, an indicator() declaration, a calculation and a plot() call. Save it, press Add to chart, and the line appears. A first working indicator is about ten lines long, and you can write it in one sitting.

This guide builds one step by step: two moving averages and a marker when they cross. If you are new to the language, start with what Pine Script is. If you only want to paste someone else’s code, how to add a Pine Script to TradingView covers the copy-and-paste steps.

What Does the Top of a Pine Script Do?

Every script starts with two things. The first is the version line, //@version=6. It is a compiler annotation, a note that tells TradingView which version of the language you wrote. TradingView’s documentation says the annotation is not mandatory, but when it is left out, version 1 is assumed. Version 1 is far older than the code in this guide, so always write the line.

The second is the declaration statement, a call to indicator(), strategy() or library(). Each script needs exactly one. It sets the script’s type and its properties, such as its name. For an indicator, the first argument is the title that shows on the chart. The argument overlay = true asks for the drawing to sit on the price chart. The longer story is in Pine Script indicators, strategies and libraries.

How Do Variables and Comments Work?

A variable is a name that holds a value. You make one with a single equals sign: fastMa = ta.ema(close, 9) creates a variable called fastMa. Pine works out the type of value by itself. TradingView’s documentation adds that a variable’s type cannot change after it is first set, so a name that starts as a number cannot later hold text.

To change an existing variable, use := instead of =. You will not need it in this first script, but it is the fix when the editor complains that you are making a second variable with the same name.

A comment is a note for people that the computer ignores. It starts with two slashes (//) and can sit on its own line or after code. In the Pine Editor, Ctrl + / comments or uncomments the selected lines. Write comments for your future self, because you will forget what a line was for.

How Do You Calculate a Moving Average With ta.ema()?

A moving average is the average of the last few prices, recalculated on every bar, so it follows the market with a delay. Pine gives you ready-made functions in the ta namespace, a group of technical-analysis tools. ta.sma(close, 20) is the simple average of the last 20 closes. ta.ema(close, 9) is the exponential version, which weights recent bars more. Our guide to moving averages in forex explains the difference.

EUR/USD daily candlestick chart with a 9-period EMA in orange and a 21-period EMA in blue, with a green marker on the bar where the fast line crosses above the slow line
Real EUR/USD daily candles with the two lines the first script plots. The marker sits on 2026-07-30, the bar where the 9 EMA closed above the 21 EMA after being at or below it.

The names close, open, high and low are built in. Each is a series, a value that has one entry per bar. The number after the comma is the length. With a length of 9, the EMA looks at roughly the last nine bars.

How Do plot() and plotshape() Draw on the Chart?

plot() draws a line. It takes the value to draw, then optional arguments. Three matter most at the start:

  • title: the name that shows in the Data Window and in the Style tab of the settings. It must be fixed text, known before the script runs.
  • color: the line colour, such as color.orange. It can even be worked out bar by bar.
  • linewidth: the thickness. For a line, the unit is pixels.

plotshape() draws a small symbol on bars where a condition is true. In the script below it marks the crossover with a triangle: shape.triangleup is the style, location.belowbar puts it under the candle, and size.small keeps it tidy. The condition must be true or false, which is why we feed it the result of ta.crossover().

The Complete First Indicator

Here is the whole script. It is complete, so you can paste it as it is.

//@version=6
indicator("My First Indicator", overlay = true)

// Two moving averages of the closing price
fastMa = ta.ema(close, 9)
slowMa = ta.ema(close, 21)

// True only on the bar where the fast line crosses above the slow line
crossUp = ta.crossover(fastMa, slowMa)

plot(fastMa, "Fast EMA", color = color.orange, linewidth = 2)
plot(slowMa, "Slow EMA", color = color.blue, linewidth = 2)
plotshape(crossUp, "Cross up", shape.triangleup, location.belowbar, color.green, size = size.small)

Read it in order. Line 1 sets the version, line 2 declares an indicator, lines 5 and 6 build the two averages, and line 9 asks one question: did the fast average just cross above the slow one? ta.crossover(a, b) is true on the bar where a moves from below b to above it, and false on every other bar. The last three lines draw the results. Add it to a chart and you will see two coloured lines and green triangles under the bars where the fast line crossed up.

A word of caution. A crossover is a description of the past. The triangle shows that the averages crossed, not that price will keep going. Crossovers also lag, and in a sideways market they fire often and lose money. Use this script to learn the language, not as a trading rule.

The script runs once for every bar on the chart, from the oldest to the newest, which is why a single line of code produces a whole line on screen. How Pine Script runs covers what happens on the live bar.

Overlay or Own Pane: What Does overlay Change?

The overlay argument decides where the drawing goes. With overlay = true, the plots sit on the price chart, which suits moving averages because they share the price scale. Without it, TradingView puts the script in its own pane under the chart, which suits indicators with their own scale, such as RSI. According to the documentation, a plot normally displays in the same pane in which the script runs.

Try the other choice. This three-line script draws an RSI of 14 bars in a separate pane:

//@version=6
indicator("RSI test")
plot(ta.rsi(close, 14), "RSI", color = color.purple)

If you draw a moving average in a pane, it looks like a flat line at the bottom or top, because its numbers are in the thousands while the pane expects a scale like 0 to 100. If you draw an RSI on the price chart, it is squashed against the axis. Wrong overlay is the commonest beginner puzzle, and the fix is one word. The library marks each script as “On the chart” or “Own pane”, and you can browse moving-average scripts to see real examples of both.

What Mistakes Do Beginners Make First?

  • No version line: the script is read as version 1 and most modern code fails. Put //@version=6 on line 1.
  • Wrong overlay: a line that seems missing is often drawn in the wrong place. Check the pane and the overlay setting.
  • Misspelt names:ta.Ema is not ta.ema. Pine is case-sensitive, and the editor reports an undeclared identifier, meaning a name it does not know.
  • Type changes: if count = 1 is followed later by count := "high", the editor refuses, because a variable’s type cannot change.
  • Mixing up = and :=: use = to create and := to change.
  • Pasting under the template: two declarations in one script is an error. Replace the template.

When the editor shows an error, read the message, find the line it points to and fix that one thing first. Later errors are often caused by the first. Make small changes and add the script to the chart again after each.

What Should You Learn Next?

The lengths 9 and 21 are written into the code, so changing them means editing the script. Pine Script inputs shows how to put them in the settings window instead. To read other people’s code with confidence, use how to read a Pine Script. When something fails to compile, Pine Script errors and limits explains the messages.

You can also learn from real code. The Pine Script Library lists thousands of open-source scripts, and the indicator category is a good place to find short ones. Treat them as examples to study, since ForexR does not test or recommend any script.

An indicator you write yourself is still only a view of past prices. It cannot predict the market, and a pretty chart is not a tested strategy. Leveraged forex and CFD trading carries a high risk of losing money quickly, so only risk money you can afford to lose.

FAQ

Do I need to know how to code to write a Pine Script?

No. Pine Script was designed to be small and readable, and a first indicator is about ten lines. You do need patience with details such as spelling and punctuation, because the editor rejects anything it cannot read. Start by changing one line of a working script and watching what happens on the chart.

What is the difference between ta.sma and ta.ema in Pine Script?

Both average recent prices. ta.sma gives every bar in the window the same weight, so it moves more slowly. ta.ema gives newer bars more weight, so it reacts sooner and also gets more false turns in choppy markets. Neither is better; the choice depends on how much lag you accept.

Why does my indicator not show on the chart?

The common causes are that it was not added with the Add to chart button, it draws in its own pane lower down, overlay is set wrongly, or its colour matches the background. Check the pane under the price chart and the editor’s error messages first, then the script’s Visibility settings.

Can a Pine Script indicator place trades for me?

An indicator only draws. It cannot place orders, and a script on TradingView cannot send orders to a broker on its own. It can fire an alert when a condition is true, and some traders connect alerts to other software. That chain has its own risks and needs careful testing.

Related on ForexR

Next lesson Pine Script Inputs: How to Make Script Settings Adjustable Continue

More Intermediate Guides

Support and Resistance in Forex: How to Draw Key Levels How to Draw Trend Lines and Channels in Forex (Step by Step) Supply and Demand Zones in Forex: How to Find and Trade Them Forex Candlestick Patterns: Pin Bars, Engulfing, Doji & More Forex Chart Patterns: Reversal & Continuation Explained Forex Breakout Trading: How to Trade Breakouts & Spot Fakeouts Moving Averages in Forex: SMA vs EMA, Crossovers & Trends MACD Indicator Explained: Settings, Signals & Divergence RSI Indicator in Forex: Settings, Signals & Divergence Stochastic Oscillator Explained: Settings, Signals and Strategy Divergence Trading: How to Spot Regular and Hidden Divergence Bollinger Bands Explained: Squeeze, Band Walks & Signals Ichimoku Cloud Explained: A Simple Guide to All Five Lines Forex Pivot Points: Formula, Levels & How to Trade Fibonacci Retracement in Forex: Levels, Drawing & Examples ATR Indicator in Forex: How to Measure Volatility Most Volatile Currency Pairs (and the Calmest): How to Trade Them Best Forex Indicators for Beginners: The 7 Worth Learning Stop-Loss Strategies in Forex: Placement, Sizing & Trailing Take-Profit Strategies: When and Where to Exit a Winning Trade Risk-Reward Ratio Explained: What It Is and How to Use It Position Sizing in Forex: How to Calculate the Right Lot Size Forex Risk Management: Position Sizing & the 1-2% Rule How to Create a Forex Trading Plan (Simple Template Included) Forex Trading Styles: Scalping, Day, Swing & Position Forex Scalping for Beginners: How It Works, Costs and Rules Day Trading Forex: A Realistic Beginner’s Guide and Routine Swing Trading Forex: How to Catch Moves Over Days, Not Minutes Types of Forex Brokers: ECN vs STP vs Market Maker Explained How to Choose a Forex Rebate Provider: 9 Checks to Make First Total Trading Cost Explained: EUR/USD vs Gold After Rebates EA Settings Explained: Lot Size, Magic Number, Stop-Loss & More How to Backtest an EA in the MT4 and MT5 Strategy Tester How to Choose a Safe Forex EA: A 12-Point Checklist Pine Script Indicators vs Strategies vs Libraries Explained Pine Script Inputs: How to Make Script Settings Adjustable How to Read a Pine Script Before You Trust It: A Checklist How to Edit a Pine Script: Colours, Lengths and Filters Pine Script Alerts: alertcondition(), alert() and Webhooks Pine Script Sessions and Time: Shade London, New York, Asia Pine Script request.security(): Multi-Timeframe Done Safely Repainting in TradingView: How to Spot a Script That Repaints Build a Moving Average Crossover Strategy in Pine Script AI Trading Tools Explained: What Helps and What Sells AI Trading Signals: What They Are and When to Trust One AI Market Analysis: How Machines Read the Forex Market AI Sentiment Analysis in Trading: News Data Explained Fundamental Analysis in Forex: What Moves Currencies Safe-Haven Currencies: Risk-On and Risk-Off Explained Gold and the US Dollar: Why They Usually Move Apart Gold and Interest Rates: Why Real Yields Drive the Price Is Gold an Inflation Hedge? What 50 Years of Data Say Gold as a Safe Haven: When It Works and When It Fails Gold Trading Strategies: 5 Setups to Test on XAU/USD Gold Scalping: Costs, Timeframes and Rules for XAU/USD Gold Technical Analysis: Levels, ATR and Round Numbers How to Trade Gold During News: NFP, CPI and Fed Days Gold Correlations: Dollar, Yields, Silver, AUD and Bitcoin Gold-Silver Ratio Explained: How to Read and Trade It Gold vs Bitcoin: Which Is the Better Store of Value? How to Choose a Broker for Gold Trading: 9 Things to Check

Choose a Regulated Broker

Put what you’ve learned to work with a regulated broker. Compare costs, platforms and licences side by side.

Compare top brokers