Back to Skill Marketplace

Trading Automation

pine-backtester

pine-backtester provides comprehensive backtesting for Pine Script indicators and strategies. Use it to append performance metrics, analyze trades, generate equity curves, compute win rates, track drawdowns, and perform statistical validation.

Updated today<1 min setup

Overview

pine-backtester provides comprehensive backtesting for Pine Script indicators and strategies.

pine-backtester provides comprehensive backtesting for Pine Script indicators and strategies. Use it to append performance metrics, analyze trades, generate equity curves, compute win rates, track drawdowns, and perform statistical validation. It ingests Pine Script strategy output (or indicator with applied entry/exit rules) to produce per-trade logs, summary statistics (CAGR, annualized return, volatility, Sharpe, Sortino, profit factor, expectancy), max drawdown and drawdown duration, trade distribution, and rolling metrics. Supports parameter sweeps, multi-timeframe testing, risk sizing variations, and Monte Carlo/resampling for robustness checks. Outputs visual equity curves, heatmaps, and CSV reports for further analysis. Trigger when requesting "backtest", "performance", "metrics", "win rate", "drawdown", or testing assistance to validate strategy edge and improve risk-adjusted returns.

Skill.md

How this skill works

pine-backtester provides comprehensive backtesting for Pine Script indicators and strategies. Use it to append performance metrics, analyze trades, generate equity curves, compute win rates, track drawdowns, and perform statistical validation.

SKILL.mdALPHIO / VERIFIED

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

Backtesting Components

1. Comprehensive Strategy Metrics Table

// Strategy Performance Metrics
var table metricsTable = table.new(position.bottom_right, 2, 15, bgcolor=color.new(color.black, 90))

if barstate.islastconfirmedhistory
    wins = strategy.wintrades
    losses = strategy.losstrades
    totalTrades = wins + losses
    winRate = totalTrades > 0 ? (wins / totalTrades) * 100 : 0

    avgWin = strategy.grossprofit / math.max(wins, 1)
    avgLoss = math.abs(strategy.grossloss) / math.max(losses, 1)
    profitFactor = avgLoss > 0 ? avgWin / avgLoss : 0

    // Drawdown calculation
    var float maxEquity = strategy.initial_capital
    var float maxDrawdown = 0.0
    currentEquity = strategy.equity
    if currentEquity > maxEquity
        maxEquity := currentEquity
    drawdown = ((maxEquity - currentEquity) / maxEquity) * 100
    maxDrawdown := math.max(maxDrawdown, drawdown)

    // Populate table
    table.cell(metricsTable, 0, 0, "METRIC", bgcolor=color.gray, text_color=color.white)
    table.cell(metricsTable, 1, 0, "VALUE", bgcolor=color.gray, text_color=color.white)

    table.cell(metricsTable, 0, 1, "Total Trades", text_color=color.white)
    table.cell(metricsTable, 1, 1, str.tostring(totalTrades), text_color=color.yellow)

    table.cell(metricsTable, 0, 2, "Win Rate", text_color=color.white)
    table.cell(metricsTable, 1, 2, str.tostring(winRate, "#.##") + "%", text_color=winRate > 50 ? color.green : color.red)

    table.cell(metricsTable, 0, 3, "Profit Factor", text_color=color.white)
    table.cell(metricsTable, 1, 3, str.tostring(profitFactor, "#.##"), text_color=profitFactor > 1 ? color.green : color.red)

    table.cell(metricsTable, 0, 4, "Max Drawdown", text_color=color.white)
    table.cell(metricsTable, 1, 4, str.tostring(maxDrawdown, "#.##") + "%", text_color=maxDrawdown < 20 ? color.green : color.red)

    table.cell(metricsTable, 0, 5, "Net Profit", text_color=color.white)
    netProfit = strategy.netprofit
    table.cell(metricsTable, 1, 5, str.tostring(netProfit, "#,###.##"), text_color=netProfit > 0 ? color.green : color.red)

2. Trade Distribution Analysis

// Trade distribution tracking
var array<float> tradeReturns = array.new<float>()
var array<int> tradeDurations = array.new<int>()
var int tradeStartBar = 0

if strategy.position_size != strategy.position_size[1]
    if strategy.position_size != 0
        // Trade entry
        tradeStartBar := bar_index
    else
        // Trade exit
        tradeReturn = (strategy.equity - strategy.equity[bar_index - tradeStartBar]) / strategy.equity[bar_index - tradeStartBar] * 100
        array.push(tradeReturns, tradeReturn)
        array.push(tradeDurations, bar_index - tradeStartBar)

// Calculate distribution stats
if barstate.islastconfirmedhistory and array.size(tradeReturns) > 0
    avgReturn = array.avg(tradeReturns)
    stdReturn = array.stdev(tradeReturns)
    medianReturn = array.median(tradeReturns)
    maxReturn = array.max(tradeReturns)
    minReturn = array.min(tradeReturns)

    // Display distribution
    table.cell(metricsTable, 0, 6, "Avg Return", text_color=color.white)
    table.cell(metricsTable, 1, 6, str.tostring(avgReturn, "#.##") + "%", text_color=avgReturn > 0 ? color.green : color.red)

    table.cell(metricsTable, 0, 7, "Std Dev", text_color=color.white)
    table.cell(metricsTable, 1, 7, str.tostring(stdReturn, "#.##") + "%", text_color=color.yellow)

3. Sharpe Ratio Calculation

// Sharpe Ratio calculation
var array<float> returns = array.new<float>()
var float previousEquity = strategy.initial_capital

if bar_index > 0
    currentReturn = (strategy.equity - previousEquity) / previousEquity
    array.push(returns, currentReturn)
    if array.size(returns) > 252  // Keep 1 year of daily returns
        array.shift(returns)
    previousEquity := strategy.equity

if barstate.islastconfirmedhistory and array.size(returns) > 30
    avgReturn = array.avg(returns) * 252  // Annualized
    stdReturn = array.stdev(returns) * math.sqrt(252)  // Annualized
    riskFreeRate = 0.02  // 2% risk-free rate
    sharpeRatio = stdReturn > 0 ? (avgReturn - riskFreeRate) / stdReturn : 0

    table.cell(metricsTable, 0, 8, "Sharpe Ratio", text_color=color.white)
    table.cell(metricsTable, 1, 8, str.tostring(sharpeRatio, "#.##"), text_color=sharpeRatio > 1 ? color.green : sharpeRatio > 0 ? color.yellow : color.red)

4. Indicator Accuracy Testing

// For indicators: Track signal accuracy
var int truePositives = 0
var int falsePositives = 0
var int trueNegatives = 0
var int falseNegatives = 0

// Define what constitutes a successful signal (example: price moves 1% in signal direction)
targetMove = input.float(1.0, "Target Move %", group="Backtest Settings")
lookforward = input.int(10, "Bars to Confirm", group="Backtest Settings")

if barstate.isconfirmed and bar_index > lookforward
    // Check if past signal was correct
    if buySignal[lookforward]
        priceChange = (close - close[lookforward]) / close[lookforward] * 100
        if priceChange >= targetMove
            truePositives += 1
        else
            falsePositives += 1
    else if sellSignal[lookforward]
        priceChange = (close[lookforward] - close) / close[lookforward] * 100
        if priceChange >= targetMove
            trueNegatives += 1
        else
            falseNegatives += 1

// Display accuracy metrics
if barstate.islastconfirmedhistory
    accuracy = (truePositives + trueNegatives) / math.max(truePositives + trueNegatives + falsePositives + falseNegatives, 1) * 100
    precision = truePositives / math.max(truePositives + falsePositives, 1) * 100
    recall = truePositives / math.max(truePositives + falseNegatives, 1) * 100

    table.cell(metricsTable, 0, 9, "Signal Accuracy", text_color=color.white)
    table.cell(metricsTable, 1, 9, str.tostring(accuracy, "#.##") + "%", text_color=accuracy > 60 ? color.green : color.red)

5. Equity Curve Visualization

// Plot equity curve (for strategies)
plot(strategy.equity, "Equity Curve", color=color.blue, linewidth=2)

// Add drawdown visualization
equityMA = ta.sma(strategy.equity, 20)
plot(equityMA, "Equity MA", color=color.orange, linewidth=1)

// Underwater equity (drawdown visualization)
var float peakEquity = strategy.initial_capital
peakEquity := math.max(peakEquity, strategy.equity)
drawdownValue = (peakEquity - strategy.equity) / peakEquity * 100

// Plot drawdown as histogram
plot(drawdownValue, "Drawdown %", color=color.red, style=plot.style_histogram, histbase=0)

6. Multi-Timeframe Validation

// Test indicator on multiple timeframes
htf1_signal = request.security(syminfo.tickerid, "60", buySignal)
htf2_signal = request.security(syminfo.tickerid, "240", buySignal)
htf3_signal = request.security(syminfo.tickerid, "D", buySignal)

// Confluence scoring
confluenceScore = 0
confluenceScore += buySignal ? 1 : 0
confluenceScore += htf1_signal ? 1 : 0
confluenceScore += htf2_signal ? 1 : 0
confluenceScore += htf3_signal ? 1 : 0

Best used for

When to use it

pine-backtester provides comprehensive backtesting for Pine Script indicators and strategies. Use it to append performance metrics, analyze trades, generate equity curves, compute win rates, track drawdowns, and perform statistical validation.

01 · PRE-MEETING

Prepare a decision brief

Turn scattered evidence into a structured case before an investment committee meeting.

02 · TEAM WORKFLOW

Standardize handoffs

Create consistent research outputs across analysts, portfolio managers, and agents.

03 · LIVE UPDATE

Refresh the thesis

Update scenarios after a new catalyst, KPI release, or earnings result.

Community notes

Built to improve with use.

Feedback will appear here as this skill is used and reviewed.

Leave feedback

Discover more

Related skills

View all
無料で始める