PineScript Tutorial: Complete Beginner's Guide to TradingView Strategies
Learn PineScript from scratch. Build your first TradingView strategy step-by-step with entry logic, stop losses, and backtesting.
PineScript is TradingView's built-in programming language for creating custom indicators and automated trading strategies. This tutorial walks you through PineScript from zero — no prior coding experience needed.
What is PineScript?
PineScript is a domain-specific language designed exclusively for TradingView. It lets you:
- Create custom indicators and overlays
- Build backtestable trading strategies
- Set automated alerts based on conditions
- Share strategies with the TradingView community
Current version: PineScript v6 (recommended for all new scripts)
Getting Started: The Pine Editor
- Open TradingView and log in
- Click the Pine Editor tab at the bottom of any chart
- You'll see a blank editor — this is where you write PineScript code
- Click Add to Chart to run your script
Script Structure
Every PineScript script starts with a version declaration and a function call that defines the script type:
//@version=5
indicator("My Indicator", overlay=true)
// or
strategy("My Strategy", overlay=true)indicator()— Creates a visual indicator (no backtesting)strategy()— Creates a backtestable strategy with entries and exits
Your First Indicator: A Simple Moving Average
Let's start with the basics — plotting a moving average on your chart:
//@version=5
indicator("Simple SMA", overlay=true)
// Define an input so users can change the period
length = input(20, "SMA Length")
// Calculate the SMA
smaValue = ta.sma(close, length)
// Plot it on the chart
plot(smaValue, "SMA", color=color.blue, linewidth=2)What each line does:
input()— Creates a settings field users can adjustta.sma()— Calculates the Simple Moving Averageplot()— Draws the line on the chartclose— The closing price of each bar
Variables and Data Types
PineScript has a few core data types:
//@version=5
indicator("Data Types Demo")
// Integer
myLength = 14
// Float
myMultiplier = 2.5
// Boolean
isUptrend = close > open
// String
myLabel = "Buy Signal"
// Color
myColor = close > open ? color.green : color.redBuilt-in Variables
PineScript provides price data automatically:
| Variable | Description |
|---|---|
open | Opening price |
high | Highest price |
low | Lowest price |
close | Closing price |
volume | Bar volume |
time | Bar timestamp |
bar_index | Current bar number |
Common Indicators (ta. library)
// Moving Averages
ta.sma(close, 20) // Simple Moving Average
ta.ema(close, 20) // Exponential Moving Average
ta.hma(close, 20) // Hull Moving Average
// Oscillators
ta.rsi(close, 14) // Relative Strength Index
ta.cci(close, 20) // Commodity Channel Index
ta.stoch(close, high, low, 14) // Stochastic
// MACD (returns a tuple)
[macdLine, signalLine, histogram] = ta.macd(close, 12, 26, 9)
// Bollinger Bands (returns a tuple)
[middle, upper, lower] = ta.bb(close, 20, 2)
// Volatility
ta.atr(14) // Average True Range
// Trend
ta.adx(high, low, close, 14) // Average Directional IndexConditions and Crossovers
Detecting crossovers is essential for strategy building:
//@version=5
indicator("Crossover Demo", overlay=true)
fastEMA = ta.ema(close, 9)
slowEMA = ta.ema(close, 21)
// Detect crossovers
bullishCross = ta.crossover(fastEMA, slowEMA) // fast crosses ABOVE slow
bearishCross = ta.crossunder(fastEMA, slowEMA) // fast crosses BELOW slow
// Visual markers on chart
plotshape(bullishCross, "Buy", shape.triangleup, location.belowbar, color.green, size=size.small)
plotshape(bearishCross, "Sell", shape.triangledown, location.abovebar, color.red, size=size.small)
plot(fastEMA, "Fast", color=color.green)
plot(slowEMA, "Slow", color=color.red)Building Your First Strategy
Now let's build a complete backtestable strategy. We'll use an RSI strategy with a stop loss:
//@version=5
strategy("My First Strategy", overlay=true, default_qty_type=strategy.percent_of_equity, default_qty_value=10)
// --- Inputs ---
rsiLength = input(14, "RSI Length")
oversold = input(30, "Oversold Level")
overbought = input(70, "Overbought Level")
stopLossPercent = input.float(2.0, "Stop Loss %") / 100
// --- Calculate RSI ---
rsiValue = ta.rsi(close, rsiLength)
// --- Entry Conditions ---
longCondition = ta.crossover(rsiValue, oversold)
// --- Execute Trades ---
if (longCondition)
strategy.entry("Long", strategy.long)
stopPrice = close * (1 - stopLossPercent)
strategy.exit("Stop Loss", "Long", stop=stopPrice)
// --- Exit Conditions ---
if (rsiValue > overbought)
strategy.close("Long")Key strategy functions:
| Function | Purpose |
|---|---|
strategy.entry() | Open a new position |
strategy.close() | Close a position by name |
strategy.exit() | Set stop loss and/or take profit |
strategy.position_size | Check current position size |
Adding a Take Profit
Extend the strategy with both stop loss and take profit:
//@version=5
strategy("RSI with SL/TP", overlay=true)
rsiLength = input(14, "RSI Length")
slPercent = input.float(2.0, "Stop Loss %") / 100
tpPercent = input.float(4.0, "Take Profit %") / 100
rsiValue = ta.rsi(close, rsiLength)
if (ta.crossover(rsiValue, 30))
strategy.entry("Long", strategy.long)
strategy.exit("SL/TP", "Long",
stop=close * (1 - slPercent),
limit=close * (1 + tpPercent))
if (rsiValue > 70)
strategy.close("Long")Running a Backtest
After adding your strategy to a chart:
- Click the Strategy Tester tab at the bottom
- View the Overview for key metrics (net profit, win rate, drawdown)
- Check List of Trades for individual trade details
- Use Performance Summary for detailed statistics
- Adjust inputs and re-run to optimize
Important backtest settings:
- Set realistic commission (0.1% for crypto, $1 per trade for stocks)
- Use appropriate slippage (1-3 ticks)
- Test on sufficient historical data (at least 100 trades)
Common PineScript Mistakes
- Using
strategy()when you wantindicator()— Strategies have overhead; use indicators for visual-only tools - Not handling
navalues — Early bars may not have enough data for indicators - Repainting — Using
closeon the current bar can repaint; useclose[1]for confirmed signals - Over-complicated conditions — Keep entry logic simple and readable
- No risk management — Always include stop losses in strategies
PineScript vs Other Languages
| Feature | PineScript | MQL5 | NinjaScript | Python |
|---|---|---|---|---|
| Platform | TradingView | MetaTrader 5 | NinjaTrader | Any |
| Difficulty | Easy | Hard | Medium | Medium |
| Backtesting | Built-in | Built-in | Built-in | Libraries needed |
| Live trading | Via broker | Direct | Direct | Via API |
| Community | Huge | Large | Medium | Huge |
Skip the Learning Curve with SpendDock
Learning PineScript takes time. What if you could describe your strategy in plain English instead?
"Buy when RSI drops below 30 and price is above the 200 EMA. Set a 2% stop loss and 4% take profit. Only trade during New York session."
SpendDock generates production-ready PineScript code from natural language descriptions — plus exports to MQL5, NinjaScript, and Python. No coding required.
SpendDock advantages:
- Describe strategies in plain English
- Get clean, optimized PineScript instantly
- Export to any platform (TradingView, MetaTrader, NinjaTrader, Python)
- Built-in risk management and position sizing
- Skip weeks of learning PineScript syntax
Conclusion
PineScript is the easiest way to start building trading strategies. Key takeaways:
- Start with simple indicators before building strategies
- Use
ta.crossover()andta.crossunder()for signal detection - Always include stop losses with
strategy.exit() - Backtest with realistic commission and slippage settings
- Use
close[1]instead ofcloseto avoid repainting
Ready to build strategies faster? Try SpendDock and generate PineScript code from plain English descriptions.
Skip the Coding — Generate Your Strategy
Describe your trading strategy in plain English and get production-ready code for TradingView, MetaTrader, NinjaTrader, or Python.
Try SpendDock Free