Skip to content
Finance
Skill

/pine-backtester

Implements comprehensive backtesting and performance metrics. Use when adding trade analysis, equity curves, or statistical validation.

BOOST
From plugin
pinescript
21412 skills3 agents3 commands2 hooks
+1
Install
$ npx -y skills add traderspost/pinescript-agents --skill pine-backtester --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/pine-backtester

Context preview

The summary Claude sees to decide when to auto-load this skill.

Implements comprehensive backtesting and performance metrics. Use when adding trade analysis, equity curves, or statistical validation.

SKILL.md

pine-backtester.SKILL.md
name: pine-backtester
description: Implements comprehensive backtesting and performance metrics. Use when adding trade analysis, equity curves, or statistical validation.
allowed-tools: Read, Edit, Grep, Glob

Pine Script Backtester

Specialized in adding comprehensive testing and validation capabilities to Pine Script indicators and strategies.

Core Responsibilities

Strategy Performance Metrics

  • Win rate and profit factor
  • Maximum drawdown analysis
  • Sharpe and Sortino ratios
  • Risk-adjusted returns
  • Trade distribution analysis

Indicator Accuracy Testing

  • Signal accuracy measurements
  • False positive/negative rates
  • Lag analysis
  • Divergence detection accuracy
  • Multi-timeframe validation

Statistical Analysis

  • Monte Carlo simulations
  • Walk-forward analysis
  • Confidence intervals
  • Statistical significance tests
  • Correlation analysis

Pine Script v6 2025 Backtesting Features

Enhanced Reporting (August 2025: 40,960 char strings)

Now possible: comprehensive multi-section reports:

// Build detailed performance report (up to 40K chars!)
var string fullReport = ""
fullReport := "═══════════════════════════════════════════\n"
fullReport += "           COMPREHENSIVE BACKTEST REPORT    \n"
fullReport += "═══════════════════════════════════════════\n\n"
fullReport += "PERFORMANCE SUMMARY\n"
fullReport += "───────────────────\n"
fullReport += "Win Rate: " + str.tostring(winRate, "#.##") + "%\n"
fullReport += "Profit Factor: " + str.tostring(pf, "#.##") + "\n"
fullReport += "Sharpe Ratio: " + str.tostring(sharpe, "#.##") + "\n\n"
fullReport += "TRADE DISTRIBUTION\n"
fullReport += "───────────────────\n"
// ... Can include much more detailed analysis

Use `for...in` for Trade Arrays (March 2025)

The preferred way to iterate over trade data arrays:

// ✅ BEST: Use for...in for arrays (safe, clean)
for tradeReturn in tradeReturns
    // Process each return directly

// ✅ BEST: With index when needed
for [i, tradeReturn] in tradeReturns
    // Have both index and value

// ❌ AVOID: Traditional for with dynamic boundary
for i = 0 to array.size(tradeReturns) - 1
    array.push(newArray, processedValue)  // Can infinite loop!

// ✅ FALLBACK: If traditional for needed, cache boundary
arrSize = array.size(tradeReturns)
for i = 0 to arrSize - 1
    // Safe processing

Conditional Backtest Settings (July 2025)

Use `active` parameter to show relevant settings:

showAdvancedMetrics = input.bool(false, "Show Advanced Metrics", group="Backtest")
sharpeRiskFreeRate = input.float(0.02, "Risk-Free Rate",
    group="Backtest",
    active=showAdvancedMetrics,  // Only show when advanced enabled
    tooltip="Annual risk-free rate for Sharpe calculation")

Visual Line Styles (September 2025)

Differentiate backtest visualization with line styles:

// Primary metrics: solid
plot(strategy.equity, "Equity", color.blue, linestyle=plot.linestyle_solid)
// Benchmarks: dashed
plot(benchmarkEquity, "Benchmark", color.gray, linestyle=plot.linestyle_dashed)
// Projections: dotted
plot(projectedEquity, "Projected", color.yellow, linestyle=plot.linestyle_dotted)

⚠️ UDT-First Trade Tracking

**For comprehensive trade analysis, use UDTs to track individual trades.**

Trade UDT Pattern

// Define Trade UDT for detailed tracking
type Trade
    // Time coordinates (for historical analysis)
    int entryTime
    int exitTime
    int entryBar
    int exitBar

    // Trade data
    float entryPrice
    float exitPrice
    float positionSize
    bool isLong
    string exitReason

    // Calculated metrics
    float pnl = 0.0
    float pnlPercent = 0.0
    int duration = 0

    // Visualization (optional)
    line tradeLine = na
    label entryLabel = na
    label exitLabel = na

// Methods for trade analysis
method calculate(Trade this) =>
    this.duration := this.exitBar - this.entryBar
    if this.isLong
        this.pnl := (this.exitPrice - this.entryPrice) * this.positionSize
        this.pnlPercent := ((this.exitPrice - this.entryPrice) / this.entryPrice) * 100
    else
        this.pnl := (this.entryPrice - this.exitPrice) * this.positionSize
        this.pnlPercent := ((this.entryPrice - this.exitPrice) / this.entryPrice) * 100

method draw(Trade this, color winColor, color loseColor) =>
    tradeColor = this.pnl >= 0 ? winColor : loseColor
    // Use xloc.bar_time for unlimited lookback!
    this.tradeLine := line.new(this.entryTime, this.entryPrice,
         this.exitTime, this.exitPrice,
         xloc=xloc.bar_time, color=tradeColor, width=2)

// Storage
var array<Trade> completedTrades = array.new<Trade>()
var Trade currentTrade = na

Trade Analysis with for...in

// Analyze all trades using for...in
if barstate.islastconfirmedhistory
    totalPnl = 0.0
    wins = 0
    losses = 0
    totalDuration = 0

    for trade in completedTrades
        totalPnl += trade.pnl
        if trade.pnl >= 0
            wins += 1
        else
            losses += 1
        totalDuration += trade.duration

    winRate = array.size(completedTrades) > 0 ? (wins / array.size(completedTrades)) * 100 : 0
    avgDuration = array.size(completedTrades) > 0 ? totalDuration / array.size(completedTrades) : 0

Trade Distribution with UDT Arrays

// Categorize trades by exit reason
var array<Trade> stopLossTrades = array.new<Trade>()
var array<Trade> takeProfitTrades = array.new<Trade>()
var array<Trade> timeoutTrades = array.new<Trade>()

// When trade closes, categorize it
if tradeJustClosed
    if currentTrade.exitReason == "SL"
        array.push(stopLossTrades, currentTrade)
    else if currentTrade.exitReason == "TP"
        array.push(takeProfitTrades, currentTrade)
    else
        array.push(timeoutTrades, currentTrade)

// Analyze by category
if barstate.islast
    slCount = array.size(stopLossTrades)
    tpCount = array.size(takeProfitTrades)
    // ... di
Read more
Ships withpinescript

A comprehensive Pine Script development environment powered by Claude Code's Skills system. This tool helps you create professional TradingView indicators and strategies with AI assistance. Just type start to begin!

Get the whole plugin

Other skills on pinescript.