PropHub / Automate / Pine Script Basics
🛠️ Beginner Tutorial — No Coding Experience Needed

Pine Script Basics —
Build Your First Indicator

Learn enough Pine Script to build your own TradingView indicators with alert conditions. Goes from zero to a working automated signal in one guide.

What You'll Build

By the End of This Guide You'll Have...

Step 1
Understand Pine Script syntax
Step 2
Write variables & conditions
Step 3
Plot on chart
Step 4
Add alert conditions
Result
Working indicator with alerts

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.

The Basics

Pine Script Fundamentals

1. The Version Declaration

Every Pine Script file starts with a version declaration. Always use version 5 (the current version):

Pine Script
//@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).

2. Variables

Variables store values. Pine Script calculates them on every bar automatically:

Pine Script
// 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

3. Historical Referencing with [n]

Add [1] to refer to the previous bar's value. [2] = two bars ago, etc.:

Pine Script
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]

4. Conditions (true/false)

Conditions evaluate to true or false on each bar. These become your signal triggers:

Pine Script
// 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))

5. Plotting on the Chart

Pine Script
// 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)

6. Alert Conditions — The Key to Automation

This is what connects your indicator to Traders Post. Every alertcondition() creates a selectable option in the TradingView alert dialog:

Pine Script
// 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)
Your First Indicator

Build a Complete EMA Crossover — Start to Finish

Here's a complete, working indicator using everything above. Paste this into Pine Script Editor and add it to your chart:

Pine Script v5 — Complete Indicator
// ═══════════════════════════════════════════════
// 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.
How to Add This to TradingView
Copy the code → open TradingView → click Pine Script Editor at the bottom → delete existing code → paste yours → click Add to chart. Your indicator appears immediately. To set up automation: create a TradingView alert using the "EMA Cross — LONG" or "SHORT" condition with your Traders Post webhook URL.
Common Built-in Functions

Quick Reference — Most Used Functions

Pine Script — Function Reference
// 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