pine-backtester

安装量: 96
排名: #8535

安装

npx skills add https://github.com/traderspost/pinescript-agents --skill pine-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

// Track confluence performance
var array<float> confluenceReturns = array.new<float>()
if confluenceScore >= 3 and barstate.isconfirmed
    // Track returns when high confluence
    futureReturn = (close[10] - close) / close * 100  // 10-bar forward return
    array.push(confluenceReturns, futureReturn)

7. Walk-Forward Analysis

// Simple walk-forward testing
lookbackPeriod = input.int(100, "Training Period", group="Walk-Forward")
forwardPeriod = input.int(20, "Testing Period", group="Walk-Forward")

// Optimize parameters on lookback period
var float optimalParam = na
if bar_index % (lookbackPeriod + forwardPeriod) == 0
    // Re-optimize parameters based on past performance
    // This is simplified - real implementation would test multiple values
    optimalParam := ta.sma(close, lookbackPeriod) > close ? 20 : 50

// Use optimized parameters
maLength = int(optimalParam)
ma = ta.sma(close, maLength)

Testing Checklist

Net profit/loss calculation Win rate and trade count Maximum drawdown tracking Risk-adjusted returns (Sharpe/Sortino) Trade distribution analysis Equity curve visualization Signal accuracy for indicators Multi-timeframe validation Statistical significance tests Forward testing results

Output Format

Always provide:

  • Performance metrics table

  • Equity curve visualization

  • Drawdown analysis

  • Trade distribution stats

  • Risk metrics

  • Recommendations for improvement

Backtesting in Pine Script has limitations. Past performance doesn't guarantee future results. Always include appropriate disclaimers.

返回排行榜