
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.
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.
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.
Discover more
Related skills
View allquant-analysis
Quantitative Analysis Skill provides an end-to-end toolkit for quantitative finance research and production analysis. It automates data ingestion, interactive analysis in Jupyter (jupyter_execute,…
bankr
Bankr enables executing crypto trading and DeFi operations via natural-language commands. It offers two integration options: a batteries-included Bankr CLI and a REST API at https://api.bankr.bot,…
zyfai
Zyfai turns any Ethereum EOA into a yield-generating account by deploying a deterministic Safe smart-wallet subaccount that is owned and withdrawable only by the user's EOA.