Skip to main content

Backtesting Trading Strategies 📊

Introduction to Backtesting

Backtesting is the process of testing a trading strategy on historical data to evaluate its performance. Pine Script provides powerful tools for implementing and testing trading strategies.

Basic Strategy Structure

//@version=5
strategy("My First Strategy", overlay=true)

// Define strategy parameters
longPeriod = input(20, "Long MA Period")
shortPeriod = input(10, "Short MA Period")

// Calculate indicators
fastMA = ta.sma(close, shortPeriod)
slowMA = ta.sma(close, longPeriod)

// Define entry conditions
longCondition = ta.crossover(fastMA, slowMA)
shortCondition = ta.crossunder(fastMA, slowMA)

// Execute trades
if (longCondition)
strategy.entry("Long", strategy.long)

if (shortCondition)
strategy.entry("Short", strategy.short)

Position Sizing

Fixed Position Size

//@version=5
strategy("Fixed Size Example")

// Fixed position size
fixedSize = input.float(1.0, "Position Size")

if (longCondition)
strategy.entry("Long", strategy.long, qty=fixedSize)

Dynamic Position Sizing

//@version=5
strategy("Dynamic Sizing")

// Risk-based position sizing
riskPercent = input.float(1.0, "Risk %", minval=0.1, maxval=100)
atrPeriod = input.int(14, "ATR Period")
atr = ta.atr(atrPeriod)

// Calculate position size based on ATR
riskAmount = strategy.equity * (riskPercent / 100)
positionSize = riskAmount / atr

if (longCondition)
strategy.entry("Long", strategy.long, qty=positionSize)

Stop Loss and Take Profit

//@version=5
strategy("SL and TP Example", overlay=true)

// Define stop loss and take profit levels
stopLoss = input.float(2.0, "Stop Loss %", minval=0.1)
takeProfit = input.float(4.0, "Take Profit %", minval=0.1)

if (longCondition)
entryPrice = close
strategy.entry("Long", strategy.long)
strategy.exit("Exit", "Long",
stop=entryPrice * (1 - stopLoss/100),
limit=entryPrice * (1 + takeProfit/100))

Strategy Properties

//@version=5
strategy("Strategy Properties Example",
initial_capital=10000,
default_qty_type=strategy.percent_of_equity,
default_qty_value=100,
commission_type=strategy.commission.percent,
commission_value=0.1)

Performance Analysis

Basic Metrics

//@version=5
strategy("Performance Metrics")

// Plot equity curve
plot(strategy.equity, "Equity", color=color.blue)

// Create performance table
var table perfTable = table.new(position.top_right, 3, 4)

if barstate.islast
table.cell(perfTable, 0, 0, "Metric", bgcolor=color.blue, text_color=color.white)
table.cell(perfTable, 1, 0, "Value", bgcolor=color.blue, text_color=color.white)

table.cell(perfTable, 0, 1, "Net Profit")
table.cell(perfTable, 1, 1, str.tostring(strategy.netprofit))

table.cell(perfTable, 0, 2, "Win Rate")
table.cell(perfTable, 1, 2, str.tostring(strategy.wintrades/strategy.closedtrades * 100) + "%")

Advanced Backtesting Features

Time-Based Filters

//@version=5
strategy("Time Filtered Strategy")

// Trading session
sessionInput = input.session("0930-1600", "Trading Session")
inSession = session.ismarket(sessionInput)

// Only trade during session
if longCondition and inSession
strategy.entry("Long", strategy.long)

Risk Management

//@version=5
strategy("Risk Management")

// Maximum drawdown protection
maxDrawdown = input.float(10, "Max Drawdown %")

// Check drawdown before entry
currentDrawdown = (strategy.equity - strategy.equity_high) / strategy.equity_high * 100

if longCondition and currentDrawdown > -maxDrawdown
strategy.entry("Long", strategy.long)
Pro Tips
  • Always backtest across different market conditions
  • Consider transaction costs and slippage
  • Use realistic position sizing
  • Test your strategy parameters
Common Pitfalls

❌ Overfitting to historical data ❌ Ignoring transaction costs ❌ Not accounting for market liquidity ❌ Using unrealistic position sizes

Next Steps

Ready to learn about strategy optimization? Move on to the next chapter! 🚀