Learn enough Pine Script to build your own TradingView indicators with alert conditions. Goes from zero to a working automated signal in one guide.
We'll build a complete EMA crossover indicator from scratch — the same type of logic used in our free PropHub indicators. Once you understand the pattern, you can modify any indicator to suit your own strategy.
Every Pine Script file starts with a version declaration. Always use version 5 (the current version):
//@version=5 indicator("My First Indicator", overlay=true)
overlay=true means your indicator draws on the main price chart. Use overlay=false for a separate panel below (like RSI).
Variables store values. Pine Script calculates them on every bar automatically:
// Built-in price variables — always available close // closing price of current bar open // opening price high // bar high low // bar low volume // bar volume // Your own variables my_ema = ta.ema(close, 20) // 20-period EMA of close price my_rsi = ta.rsi(close, 14) // 14-period RSI my_atr = ta.atr(14) // 14-period ATR
Add [1] to refer to the previous bar's value. [2] = two bars ago, etc.:
close // current bar close close[1] // previous bar close close[2] // two bars ago close // Example: did price go up this bar vs last bar? price_rose = close > close[1]
Conditions evaluate to true or false on each bar. These become your signal triggers:
// Basic comparisons above_ema = close > ta.ema(close, 20) // true if price is above 20 EMA rsi_overbought = ta.rsi(close, 14) > 70 // true if RSI above 70 // Combine conditions with 'and' / 'or' buy_signal = above_ema and not rsi_overbought sell_signal = not above_ema or rsi_overbought // Crossover functions (fires only on the bar of the cross) cross_up = ta.crossover(ta.ema(close, 20), ta.ema(close, 50)) cross_down = ta.crossunder(ta.ema(close, 20), ta.ema(close, 50))
// Plot a line (for indicators like EMA) plot(ta.ema(close, 20), "20 EMA", color=color.aqua, linewidth=2) // Plot signal arrows on the chart plotshape(buy_signal, "Buy", shape.labelup, location.belowbar, color.green) plotshape(sell_signal, "Sell", shape.labeldown, location.abovebar, color.red) // Background colour (highlight certain bars) bgcolor(above_ema ? color.new(color.green, 95) : na)
This is what connects your indicator to Traders Post. Every alertcondition() creates a selectable option in the TradingView alert dialog:
// alertcondition(condition, title, message) alertcondition(buy_signal, "My Indicator — LONG", "Signal fired: LONG on " + syminfo.ticker) alertcondition(sell_signal, "My Indicator — SHORT", "Signal fired: SHORT on " + syminfo.ticker) // The title appears in TradingView's alert condition dropdown // The message is the default text (overridden by your JSON in the alert dialog)
Here's a complete, working indicator using everything above. Paste this into Pine Script Editor and add it to your chart:
// ═══════════════════════════════════════════════ // My First PropHub Indicator — EMA Crossover // Built following the Pine Script Basics guide // ═══════════════════════════════════════════════ //@version=5 indicator("My EMA Crossover", overlay=true) // ── Step 1: Create inputs so you can adjust from the chart ── fast_len = input.int(20, "Fast EMA", minval=1) slow_len = input.int(50, "Slow EMA", minval=1) // ── Step 2: Calculate the EMAs ────────────────── fast_ema = ta.ema(close, fast_len) slow_ema = ta.ema(close, slow_len) // ── Step 3: Define your signal conditions ─────── // crossover: fast EMA crosses ABOVE slow EMA → bullish // crossunder: fast EMA crosses BELOW slow EMA → bearish bull_cross = ta.crossover(fast_ema, slow_ema) bear_cross = ta.crossunder(fast_ema, slow_ema) // ── Step 4: Plot the EMAs on the chart ────────── plot(fast_ema, "Fast EMA", color=color.new(color.aqua, 0), linewidth=1) plot(slow_ema, "Slow EMA", color=color.new(color.orange, 0), linewidth=1) // ── Step 5: Add signal arrows ─────────────────── plotshape(bull_cross, "Buy Signal", shape.labelup, location.belowbar, color.new(color.green, 0), text="▲", textcolor=color.white, size=size.small) plotshape(bear_cross, "Sell Signal", shape.labeldown, location.abovebar, color.new(color.red, 0), text="▼", textcolor=color.white, size=size.small) // ── Step 6: Add alert conditions for automation ─ alertcondition(bull_cross, "EMA Cross — LONG", "EMA Crossover LONG signal on " + syminfo.ticker) alertcondition(bear_cross, "EMA Cross — SHORT", "EMA Crossover SHORT signal on " + syminfo.ticker) // Done! Now add alerts in TradingView using these conditions // and connect to Traders Post via webhook.
// Moving Averages ta.ema(source, length) // Exponential Moving Average ta.sma(source, length) // Simple Moving Average ta.wma(source, length) // Weighted Moving Average ta.vwap(source) // Volume Weighted Average Price // Oscillators ta.rsi(source, length) // Relative Strength Index ta.macd(source, f, s, sig) // MACD ta.stoch(c, h, l, len) // Stochastic // Volatility ta.atr(length) // Average True Range ta.bbands(source, len, m) // Bollinger Bands // Price stats ta.highest(source, length) // Highest value over N bars ta.lowest(source, length) // Lowest value over N bars // Crossover detection ta.crossover(a, b) // True when a crosses above b ta.crossunder(a, b) // True when a crosses below b // Math math.abs(value) // Absolute value math.max(a, b) // Maximum of two values math.min(a, b) // Minimum of two values math.sqrt(value) // Square root