Development of Custom Pine Script Trading Strategies
Pine Script is TradingView's scripting language for creating indicators and strategies right in browser. Looks simple, but writing strategy that doesn't give false signals on historical data and actually trades profitably—non-trivial task.
Pine Script Strategy Structure
//@version=5
strategy("EMA + RSI Strategy", overlay=true,
initial_capital=10000, commission_value=0.1,
default_qty_type=strategy.percent_of_equity, default_qty_value=10)
// Parameters (user-adjustable in TradingView interface)
emaFast = input.int(9, "Fast EMA", minval=1)
emaSlow = input.int(21, "Slow EMA", minval=1)
rsiPeriod = input.int(14, "RSI Period")
rsiOversold = input.float(30, "RSI Oversold")
rsiOverbought = input.float(70, "RSI Overbought")
// Calculate indicators
emaF = ta.ema(close, emaFast)
emaS = ta.ema(close, emaSlow)
rsi = ta.rsi(close, rsiPeriod)
// Entry conditions
longCondition = ta.crossover(emaF, emaS) and rsi < rsiOversold
shortCondition = ta.crossunder(emaF, emaS) and rsi > rsiOverbought
// Entry/exit
if longCondition
strategy.entry("Long", strategy.long)
if shortCondition
strategy.entry("Short", strategy.short)
// Exit with stop-loss and take-profit
strategy.exit("Long Exit", "Long",
stop=strategy.position_avg_price * 0.97, // -3% stop
limit=strategy.position_avg_price * 1.06) // +6% target
// Visualization
plot(emaF, "Fast EMA", color=color.blue)
plot(emaS, "Slow EMA", color=color.orange)
bgcolor(longCondition ? color.new(color.green, 90) : na)
Advanced Techniques
Market Regime Filter
// ADX filter: trade only when trend exists
[diPlus, diMinus, adx] = ta.dmi(14, 14)
trendFilter = adx > 25
// Volume filter: signal valid only with elevated volume
avgVolume = ta.sma(volume, 20)
volumeFilter = volume > avgVolume * 1.5
// Combine filters
longCondition := longCondition and trendFilter and volumeFilter
Position Sizing
// ATR-based stop: dynamic stop for volatility
atr = ta.atr(14)
stopDistance = atr * 2.0
// Size position to risk: risk max 2% of account per trade
riskAmount = strategy.equity * 0.02
positionSize = riskAmount / stopDistance
if longCondition
strategy.entry("Long", strategy.long, qty=positionSize)
strategy.exit("Long SL/TP", "Long",
stop=close - stopDistance,
limit=close + stopDistance * 2) // RR 1:2
Trading Sessions and Time Filters
// Trade only London and New York sessions
inLondon = not na(time(timeframe.period, "0800-1600", "Europe/London"))
inNewYork = not na(time(timeframe.period, "0930-1600", "America/New_York"))
tradingTime = inLondon or inNewYork
longCondition := longCondition and tradingTime
Backtesting in TradingView
Key metrics in Strategy Tester:
- Net Profit: absolute profit for period
- Percent Profitable: % of winning trades (60%+ good for trend-following)
- Profit Factor: sum of wins / sum of losses (> 1.5 acceptable)
- Max Drawdown: maximum loss from peak
- Sharpe Ratio: risk-adjusted return
Look-ahead bias—main Pine Script trap: if using security() without lookahead=barmerge.lookahead_off, strategy uses future data on backtest. Results unrealistically good.
// WRONG—look-ahead bias:
htf_close = request.security(syminfo.tickerid, "D", close)
// CORRECT—only closed bars:
htf_close = request.security(syminfo.tickerid, "D", close[1],
lookahead=barmerge.lookahead_off)
Alerts for Automation
Connect Pine Script strategy to trading bot via TradingView alerts + webhook:
// Create alerts
alertcondition(longCondition, "Long Signal",
"{{strategy.order.action}} {{ticker}} @ {{close}}")
alertcondition(shortCondition, "Short Signal",
"{{strategy.order.action}} {{ticker}} @ {{close}}")
Webhook URL receives JSON from TradingView and executes order through exchange API. Delay: usually 1–5 seconds from signal to order.
| Strategy Type | Complexity | Development Time |
|---|---|---|
| Simple indicator (RSI/EMA) | Low | 2–4 days |
| Multi-condition strategy | Medium | 1–2 weeks |
| Strategy with position sizing | Medium | 2–3 weeks |
| Complex multi-timeframe | High | 3–5 weeks |
Development includes writing strategy, parameter tuning, backtesting on multiple instruments, and configuring alerts for automated execution.







