Professional traders need comprehensive performance metrics to evaluate their strategies effectively. This tutorial demonstrates how to build a reusable PNL (Profit and Loss) tracking module that integrates seamlessly with any Pine Script strategy. The module provides real-time performance analytics directly on your TradingView charts.

Overview
The PnL tracker module consists of three main components:
- Tracking Variables: Store trade statistics and performance metrics
- Calculation Logic: Process trades and update metrics automatically
- Dashboard Display: Visual representation of performance data
Complete Code Implementation
// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// Modular PnL Tracking System - Can be attached to any strategy
//@version=6
strategy("Strategy with Modular PnL Tracker [Example: Supertrend]", overlay=true, initial_capital=10000, default_qty_type=strategy.percent_of_equity, default_qty_value=100)
// ========================================
// MODULE: PNL TRACKER INPUTS
// ========================================
showPnLDashboard = input.bool(true, "Show PnL Dashboard", group="PnL Tracker Settings")
dashboardLocation = input.string("Top Right", "Dashboard Location", options=["Top Right", "Top Left", "Bottom Right", "Bottom Left"], group="PnL Tracker Settings")
dashboardTextSize = input.string("Normal", "Text Size", options=["Small", "Normal", "Large"], group="PnL Tracker Settings")
bgTransparency = input.int(90, "Background Transparency", minval=0, maxval=100, group="PnL Tracker Settings")
showExtendedMetrics = input.bool(true, "Show Extended Metrics", group="PnL Tracker Settings")
showStreakInfo = input.bool(true, "Show Streak Information", group="PnL Tracker Settings")
// Color Settings
profitTextColor = input.color(color.lime, "Profit Text Color", group="PnL Tracker Colors")
lossTextColor = input.color(color.red, "Loss Text Color", group="PnL Tracker Colors")
neutralTextColor = input.color(color.gray, "Neutral Text Color", group="PnL Tracker Colors")
headerBgColor = input.color(color.navy, "Header Background", group="PnL Tracker Colors")
// ========================================
// MODULE: PNL TRACKING VARIABLES
// ========================================
// Core PnL Variables
var float pnl_entryPrice = na
var int pnl_totalTrades = 0
var int pnl_winningTrades = 0
var int pnl_losingTrades = 0
var float pnl_totalPnL = 0.0
var float pnl_totalWinPnL = 0.0
var float pnl_totalLossPnL = 0.0
var float pnl_maxWin = 0.0
var float pnl_maxLoss = 0.0
var float pnl_lastPnL = 0.0
// Equity and Drawdown
var float pnl_equity = strategy.initial_capital
var float pnl_peakEquity = strategy.initial_capital
var float pnl_maxDrawdown = 0.0
var float pnl_currentDrawdown = 0.0
// Streak Tracking
var int pnl_currentStreak = 0
var int pnl_maxWinStreak = 0
var int pnl_maxLossStreak = 0
var bool pnl_inWinStreak = true
// Extended Metrics
var float pnl_avgWin = 0.0
var float pnl_avgLoss = 0.0
var float pnl_profitFactor = 0.0
var float pnl_winRate = 0.0
var float pnl_expectancy = 0.0
var float pnl_payoffRatio = 0.0
// Performance Arrays
var float[] pnl_tradeReturns = array.new_float(0)
var int pnl_lastClosedTrades = 0
// ========================================
// MODULE: PNL TRACKING LOGIC
// ========================================
// Update PnL metrics when a trade closes
if (strategy.closedtrades > pnl_lastClosedTrades)
// Get last trade info
lastProfit = strategy.closedtrades.profit(strategy.closedtrades - 1)
// Update trade counter
pnl_totalTrades := strategy.closedtrades
pnl_lastClosedTrades := strategy.closedtrades
// Update PnL
pnl_totalPnL := pnl_totalPnL + lastProfit
pnl_lastPnL := lastProfit
// Track trade returns for statistics
array.push(pnl_tradeReturns, lastProfit)
if (array.size(pnl_tradeReturns) > 100)
array.shift(pnl_tradeReturns)
// Update win/loss stats
if (lastProfit > 0)
pnl_winningTrades := pnl_winningTrades + 1
pnl_totalWinPnL := pnl_totalWinPnL + lastProfit
pnl_maxWin := math.max(pnl_maxWin, lastProfit)
// Update win streak
if (pnl_inWinStreak)
pnl_currentStreak := pnl_currentStreak + 1
else
pnl_inWinStreak := true
pnl_currentStreak := 1
pnl_maxWinStreak := math.max(pnl_maxWinStreak, pnl_currentStreak)
else
pnl_losingTrades := pnl_losingTrades + 1
pnl_totalLossPnL := pnl_totalLossPnL + lastProfit
pnl_maxLoss := math.min(pnl_maxLoss, lastProfit)
// Update loss streak
if (not pnl_inWinStreak)
pnl_currentStreak := pnl_currentStreak + 1
else
pnl_inWinStreak := false
pnl_currentStreak := 1
pnl_maxLossStreak := math.max(pnl_maxLossStreak, pnl_currentStreak)
// Calculate extended metrics
if (pnl_totalTrades > 0)
pnl_winRate := (pnl_winningTrades / pnl_totalTrades) * 100
pnl_avgWin := pnl_winningTrades > 0 ? pnl_totalWinPnL / pnl_winningTrades : 0
pnl_avgLoss := pnl_losingTrades > 0 ? math.abs(pnl_totalLossPnL / pnl_losingTrades) : 0
pnl_profitFactor := pnl_totalLossPnL != 0 ? math.abs(pnl_totalWinPnL / pnl_totalLossPnL) : pnl_totalWinPnL > 0 ? 999 : 0
pnl_expectancy := (pnl_winRate / 100 * pnl_avgWin) - ((100 - pnl_winRate) / 100 * pnl_avgLoss)
pnl_payoffRatio := pnl_avgLoss != 0 ? pnl_avgWin / pnl_avgLoss : 0
// Update equity and drawdown
pnl_equity := strategy.initial_capital + strategy.netprofit
pnl_peakEquity := math.max(pnl_peakEquity, pnl_equity)
pnl_currentDrawdown := ((pnl_peakEquity - pnl_equity) / pnl_peakEquity) * 100
pnl_maxDrawdown := math.max(pnl_maxDrawdown, pnl_currentDrawdown)
// Helper function for color (moved outside of displayPnLDashboard)
getMetricColor(val) =>
val > 0 ? profitTextColor : val < 0 ? lossTextColor : neutralTextColor
// ========================================
// MODULE: DASHBOARD DISPLAY FUNCTION
// ========================================
displayPnLDashboard() =>
if (showPnLDashboard)
// Determine position
tablePos = dashboardLocation == "Top Right" ? position.top_right : dashboardLocation == "Top Left" ? position.top_left : dashboardLocation == "Bottom Right" ? position.bottom_right : position.bottom_left
// Determine text size
textSz = dashboardTextSize == "Small" ? size.small : dashboardTextSize == "Large" ? size.large : size.normal
// Create table with sufficient rows (30 to be safe)
var table pnlTable = table.new(tablePos, 2, 30, bgcolor=color.new(color.black, bgTransparency), frame_color=color.gray, frame_width=1, border_color=color.gray, border_width=1)
row = 0
// HEADER
table.cell(pnlTable, 0, row, "PNL TRACKER", text_color=color.white, text_size=textSz, bgcolor=headerBgColor, text_halign=text.align_center)
table.merge_cells(pnlTable, 0, row, 1, row)
row += 1
// SEPARATOR
table.cell(pnlTable, 0, row, "────────────────", text_color=color.gray, text_size=textSz)
table.merge_cells(pnlTable, 0, row, 1, row)
row += 1
// ACCOUNT METRICS
table.cell(pnlTable, 0, row, "Equity:", text_color=color.white, text_size=textSz, text_halign=text.align_left)
table.cell(pnlTable, 1, row, str.tostring(pnl_equity, "#,##0.00"), text_color=getMetricColor(pnl_equity - strategy.initial_capital), text_size=textSz, text_halign=text.align_right)
row += 1
table.cell(pnlTable, 0, row, "Total PnL:", text_color=color.white, text_size=textSz, text_halign=text.align_left)
table.cell(pnlTable, 1, row, str.tostring(pnl_totalPnL, "#,##0.00"), text_color=getMetricColor(pnl_totalPnL), text_size=textSz, text_halign=text.align_right)
row += 1
table.cell(pnlTable, 0, row, "PnL %:", text_color=color.white, text_size=textSz, text_halign=text.align_left)
table.cell(pnlTable, 1, row, str.tostring((pnl_totalPnL/strategy.initial_capital)*100, "#0.00") + "%", text_color=getMetricColor(pnl_totalPnL), text_size=textSz, text_halign=text.align_right)
row += 1
table.cell(pnlTable, 0, row, "Last Trade:", text_color=color.white, text_size=textSz, text_halign=text.align_left)
table.cell(pnlTable, 1, row, str.tostring(pnl_lastPnL, "#,##0.00"), text_color=getMetricColor(pnl_lastPnL), text_size=textSz, text_halign=text.align_right)
row += 1
// SEPARATOR
table.cell(pnlTable, 0, row, "────────────────", text_color=color.gray, text_size=textSz)
table.merge_cells(pnlTable, 0, row, 1, row)
row += 1
// TRADE STATISTICS
table.cell(pnlTable, 0, row, "Total Trades:", text_color=color.white, text_size=textSz, text_halign=text.align_left)
table.cell(pnlTable, 1, row, str.tostring(pnl_totalTrades), text_color=neutralTextColor, text_size=textSz, text_halign=text.align_right)
row += 1
table.cell(pnlTable, 0, row, "Winning:", text_color=color.white, text_size=textSz, text_halign=text.align_left)
table.cell(pnlTable, 1, row, str.tostring(pnl_winningTrades), text_color=profitTextColor, text_size=textSz, text_halign=text.align_right)
row += 1
table.cell(pnlTable, 0, row, "Losing:", text_color=color.white, text_size=textSz, text_halign=text.align_left)
table.cell(pnlTable, 1, row, str.tostring(pnl_losingTrades), text_color=lossTextColor, text_size=textSz, text_halign=text.align_right)
row += 1
table.cell(pnlTable, 0, row, "Win Rate:", text_color=color.white, text_size=textSz, text_halign=text.align_left)
table.cell(pnlTable, 1, row, str.tostring(pnl_winRate, "#0.00") + "%", text_color=pnl_winRate >= 50 ? profitTextColor : lossTextColor, text_size=textSz, text_halign=text.align_right)
row += 1
// EXTENDED METRICS
if (showExtendedMetrics and row < 29)
table.cell(pnlTable, 0, row, "────────────────", text_color=color.gray, text_size=textSz)
table.merge_cells(pnlTable, 0, row, 1, row)
row += 1
if row < 29
table.cell(pnlTable, 0, row, "Avg Win:", text_color=color.white, text_size=textSz, text_halign=text.align_left)
table.cell(pnlTable, 1, row, str.tostring(pnl_avgWin, "#0.00"), text_color=profitTextColor, text_size=textSz, text_halign=text.align_right)
row += 1
if row < 29
table.cell(pnlTable, 0, row, "Avg Loss:", text_color=color.white, text_size=textSz, text_halign=text.align_left)
table.cell(pnlTable, 1, row, str.tostring(pnl_avgLoss, "#0.00"), text_color=lossTextColor, text_size=textSz, text_halign=text.align_right)
row += 1
if row < 29
table.cell(pnlTable, 0, row, "Max Win:", text_color=color.white, text_size=textSz, text_halign=text.align_left)
table.cell(pnlTable, 1, row, str.tostring(pnl_maxWin, "#0.00"), text_color=profitTextColor, text_size=textSz, text_halign=text.align_right)
row += 1
if row < 29
table.cell(pnlTable, 0, row, "Max Loss:", text_color=color.white, text_size=textSz, text_halign=text.align_left)
table.cell(pnlTable, 1, row, str.tostring(math.abs(pnl_maxLoss), "#0.00"), text_color=lossTextColor, text_size=textSz, text_halign=text.align_right)
row += 1
if row < 29
table.cell(pnlTable, 0, row, "Profit Factor:", text_color=color.white, text_size=textSz, text_halign=text.align_left)
pfStr = pnl_profitFactor > 100 ? ">100" : str.tostring(pnl_profitFactor, "#0.00")
table.cell(pnlTable, 1, row, pfStr, text_color=pnl_profitFactor >= 1 ? profitTextColor : lossTextColor, text_size=textSz, text_halign=text.align_right)
row += 1
if row < 29
table.cell(pnlTable, 0, row, "Expectancy:", text_color=color.white, text_size=textSz, text_halign=text.align_left)
table.cell(pnlTable, 1, row, str.tostring(pnl_expectancy, "#0.00"), text_color=getMetricColor(pnl_expectancy), text_size=textSz, text_halign=text.align_right)
row += 1
if row < 29
table.cell(pnlTable, 0, row, "Payoff Ratio:", text_color=color.white, text_size=textSz, text_halign=text.align_left)
table.cell(pnlTable, 1, row, str.tostring(pnl_payoffRatio, "#0.00"), text_color=pnl_payoffRatio >= 1 ? profitTextColor : lossTextColor, text_size=textSz, text_halign=text.align_right)
row += 1
// RISK METRICS
if row < 29
table.cell(pnlTable, 0, row, "────────────────", text_color=color.gray, text_size=textSz)
table.merge_cells(pnlTable, 0, row, 1, row)
row += 1
if row < 29
table.cell(pnlTable, 0, row, "Current DD:", text_color=color.white, text_size=textSz, text_halign=text.align_left)
table.cell(pnlTable, 1, row, str.tostring(pnl_currentDrawdown, "#0.00") + "%", text_color=pnl_currentDrawdown > 5 ? lossTextColor : neutralTextColor, text_size=textSz, text_halign=text.align_right)
row += 1
if row < 29
table.cell(pnlTable, 0, row, "Max DD:", text_color=color.white, text_size=textSz, text_halign=text.align_left)
table.cell(pnlTable, 1, row, str.tostring(pnl_maxDrawdown, "#0.00") + "%", text_color=lossTextColor, text_size=textSz, text_halign=text.align_right)
row += 1
// STREAK INFO
if (showStreakInfo and row < 29)
table.cell(pnlTable, 0, row, "────────────────", text_color=color.gray, text_size=textSz)
table.merge_cells(pnlTable, 0, row, 1, row)
row += 1
if row < 29
streakStr = pnl_inWinStreak ? "W" + str.tostring(pnl_currentStreak) : "L" + str.tostring(pnl_currentStreak)
streakColor = pnl_inWinStreak ? profitTextColor : lossTextColor
table.cell(pnlTable, 0, row, "Current Streak:", text_color=color.white, text_size=textSz, text_halign=text.align_left)
table.cell(pnlTable, 1, row, streakStr, text_color=streakColor, text_size=textSz, text_halign=text.align_right)
row += 1
if row < 29
table.cell(pnlTable, 0, row, "Max Win Streak:", text_color=color.white, text_size=textSz, text_halign=text.align_left)
table.cell(pnlTable, 1, row, str.tostring(pnl_maxWinStreak), text_color=profitTextColor, text_size=textSz, text_halign=text.align_right)
row += 1
if row < 29
table.cell(pnlTable, 0, row, "Max Loss Streak:", text_color=color.white, text_size=textSz, text_halign=text.align_left)
table.cell(pnlTable, 1, row, str.tostring(pnl_maxLossStreak), text_color=lossTextColor, text_size=textSz, text_halign=text.align_right)
// ========================================
// EXAMPLE STRATEGY: SUPERTREND
// ========================================
// This section contains your actual strategy logic
// Replace this with ANY strategy you want
// Strategy Parameters
factor = input.float(3.0, "Supertrend Multiplier", minval=1.0, maxval=10.0, step=0.1, group="Strategy Settings")
length = input.int(10, "ATR Length", minval=1, maxval=100, step=1, group="Strategy Settings")
// Calculate Supertrend
[supertrend, direction] = ta.supertrend(factor, length)
// Plot Supertrend
plot(supertrend, "Supertrend", color=direction == -1 ? color.green : color.red, linewidth=2)
// Trading Signals
buy = direction == -1 and direction[1] == 1
sell = direction == 1 and direction[1] == -1
// Track entry price for the module
if (buy or sell)
pnl_entryPrice := close
// Execute Trades
if (buy)
strategy.entry("BUY", direction=strategy.long)
if (sell)
strategy.entry("SHORT", direction=strategy.short)
// ========================================
// MODULE: CALL PNL TRACKER
// ========================================
// The PnL tracking logic now runs inline (not in functions)
// This avoids the "cannot modify global variable" error
// Display the dashboard
displayPnLDashboard()
// ========================================
// OPTIONAL: VISUAL ENHANCEMENTS
// ========================================
// Background coloring based on position (subtle)
bgcolor(strategy.position_size > 0 ? color.new(color.green, 95) : strategy.position_size < 0 ? color.new(color.red, 95) : na)
Strategy Settings
//@version=6
strategy("Strategy with Modular PnL Tracker [Example: Supertrend]", overlay=true, initial_capital=10000, default_qty_type=strategy.percent_of_equity, default_qty_value=100)
// ========================================
// MODULE: PNL TRACKER INPUTS
// ========================================
showPnLDashboard = input.bool(true, "Show PnL Dashboard", group="PnL Tracker Settings")
dashboardLocation = input.string("Top Right", "Dashboard Location", options=["Top Right", "Top Left", "Bottom Right", "Bottom Left"], group="PnL Tracker Settings")
dashboardTextSize = input.string("Normal", "Text Size", options=["Small", "Normal", "Large"], group="PnL Tracker Settings")
bgTransparency = input.int(90, "Background Transparency", minval=0, maxval=100, group="PnL Tracker Settings")
showExtendedMetrics = input.bool(true, "Show Extended Metrics", group="PnL Tracker Settings")
showStreakInfo = input.bool(true, "Show Streak Information", group="PnL Tracker Settings")
// Color Settings
profitTextColor = input.color(color.lime, "Profit Text Color", group="PnL Tracker Colors")
lossTextColor = input.color(color.red, "Loss Text Color", group="PnL Tracker Colors")
neutralTextColor = input.color(color.gray, "Neutral Text Color", group="PnL Tracker Colors")
headerBgColor = input.color(color.navy, "Header Background", group="PnL Tracker Colors")
Core Tracking Variables
The module uses prefixed variables (pnl_) to avoid naming conflicts with existing strategy code:
// Core PnL Variables
var float pnl_entryPrice = na
var int pnl_totalTrades = 0
var int pnl_winningTrades = 0
var int pnl_losingTrades = 0
var float pnl_totalPnL = 0.0
var float pnl_totalWinPnL = 0.0
var float pnl_totalLossPnL = 0.0
var float pnl_maxWin = 0.0
var float pnl_maxLoss = 0.0
var float pnl_lastPnL = 0.0
// Equity and Drawdown
var float pnl_equity = strategy.initial_capital
var float pnl_peakEquity = strategy.initial_capital
var float pnl_maxDrawdown = 0.0
var float pnl_currentDrawdown = 0.0
// Streak Tracking
var int pnl_currentStreak = 0
var int pnl_maxWinStreak = 0
var int pnl_maxLossStreak = 0
var bool pnl_inWinStreak = true
Trade Processing Logic
The module automatically detects closed trades and updates all metrics:
// Update PnL metrics when a trade closes
if (strategy.closedtrades > pnl_lastClosedTrades)
// Get last trade info
lastProfit = strategy.closedtrades.profit(strategy.closedtrades - 1)
// Update trade counter
pnl_totalTrades := strategy.closedtrades
pnl_lastClosedTrades := strategy.closedtrades
// Update PnL
pnl_totalPnL := pnl_totalPnL + lastProfit
pnl_lastPnL := lastProfit
// Update win/loss stats
if (lastProfit > 0)
pnl_winningTrades := pnl_winningTrades + 1
pnl_totalWinPnL := pnl_totalWinPnL + lastProfit
pnl_maxWin := math.max(pnl_maxWin, lastProfit)
else
pnl_losingTrades := pnl_losingTrades + 1
pnl_totalLossPnL := pnl_totalLossPnL + lastProfit
pnl_maxLoss := math.min(pnl_maxLoss, lastProfit)
Performance Metrics Calculation
Advanced metrics provide deeper insights into strategy performance:
// Calculate extended metrics
if (pnl_totalTrades > 0)
pnl_winRate := (pnl_winningTrades / pnl_totalTrades) * 100
pnl_avgWin := pnl_winningTrades > 0 ? pnl_totalWinPnL / pnl_winningTrades : 0
pnl_avgLoss := pnl_losingTrades > 0 ? math.abs(pnl_totalLossPnL / pnl_losingTrades) : 0
pnl_profitFactor := pnl_totalLossPnL != 0 ? math.abs(pnl_totalWinPnL / pnl_totalLossPnL) : pnl_totalWinPnL > 0 ? 999 : 0
pnl_expectancy := (pnl_winRate / 100 * pnl_avgWin) - ((100 - pnl_winRate) / 100 * pnl_avgLoss)
pnl_payoffRatio := pnl_avgLoss != 0 ? pnl_avgWin / pnl_avgLoss : 0
Dashboard Display Function
The visual dashboard presents all metrics in an organized table format:
displayPnLDashboard() =>
if (showPnLDashboard)
// Determine position
tablePos = dashboardLocation == "Top Right" ? position.top_right : dashboardLocation == "Top Left" ? position.top_left : dashboardLocation == "Bottom Right" ? position.bottom_right : position.bottom_left
// Create table
var table pnlTable = table.new(tablePos, 2, 30, bgcolor=color.new(color.black, bgTransparency), frame_color=color.gray, frame_width=1, border_color=color.gray, border_width=1)
// Populate table with metrics
row = 0
table.cell(pnlTable, 0, row, "PNL TRACKER", text_color=color.white, bgcolor=headerBgColor)
// ... additional rows for each metric
Integration Steps
Step 1: Add the Module
Copy the complete PnL tracker code (inputs, variables, and logic) to the beginning of your strategy script.
Step 2: Track Entry Prices
Add entry price tracking when your strategy generates signals:
// Your existing buy/sell conditions
if (buy or sell)
pnl_entryPrice := close
Step 3: Activate the Dashboard
Add this single line at the end of your script:
displayPnLDashboard()
Example Integration: Supertrend Strategy
Here’s how the module integrates with a simple Supertrend strategy:
// Strategy Parameters
factor = input.float(3.0, "Supertrend Multiplier", minval=1.0, maxval=10.0, step=0.1)
length = input.int(10, "ATR Length", minval=1, maxval=100, step=1)
// Calculate Supertrend
[supertrend, direction] = ta.supertrend(factor, length)
// Trading Signals
buy = direction == -1 and direction[1] == 1
sell = direction == 1 and direction[1] == -1
// Track entry price for PnL module
if (buy or sell)
pnl_entryPrice := close
// Execute Trades
if (buy)
strategy.entry("BUY", direction=strategy.long)
if (sell)
strategy.entry("SHORT", direction=strategy.short)
// Display PnL Dashboard
displayPnLDashboard()
Metrics Explained
Basic Metrics
- Equity: Current account balance including unrealized P&L
- Total PnL: Cumulative profit/loss from all closed trades
- Win Rate: Percentage of profitable trades
- Total Trades: Number of completed trades
Advanced Metrics
- Profit Factor: Ratio of gross profit to gross loss (values > 1.0 indicate profitability)
- Expectancy: Average expected profit per trade
- Payoff Ratio: Average win divided by average loss
- Maximum Drawdown: Largest peak-to-trough decline in equity
Streak Analysis
- Current Streak: Consecutive wins or losses
- Max Win/Loss Streak: Historical maximum consecutive wins/losses
Customization Options
Visual Settings
- Dashboard position (four corner options)
- Text size (Small/Normal/Large)
- Background transparency (0-100%)
- Custom colors for profit/loss/neutral states
Display Options
- Toggle extended metrics on/off
- Show/hide streak information
- Enable/disable entire dashboard
Performance Considerations
- Variable Naming: All module variables use
pnl_prefix to prevent conflicts - Table Management: Fixed 30-row table prevents runtime errors
- Calculation Efficiency: Metrics update only when trades close
- Memory Usage: Stores last 100 trades for statistical analysis
Common Implementation Patterns
Pattern 1: Minimal Integration
For basic PnL tracking without modifications:
// Add module code at script start
// Add entry price tracking in strategy logic
// Call displayPnLDashboard() at script end
Pattern 2: Selective Metrics
Display only essential metrics:
showExtendedMetrics = false
showStreakInfo = false
Pattern 3: Custom Positioning
Adapt dashboard location based on chart layout:
dashboardLocation = "Bottom Right" // Avoids overlap with price action
Troubleshooting Guide
Issue: Dashboard Not Appearing
- Verify
showPnLDashboard = true - Check dashboard position isn’t off-screen
- Ensure
displayPnLDashboard()is called
Issue: Metrics Not Updating
- Confirm trades are actually closing
- Verify entry price tracking is implemented
- Check strategy has sufficient historical data
Issue: Visual Conflicts
- Adjust transparency settings
- Change dashboard position
- Modify text size for better readability
Best Practices
- Test First: Run the module on historical data before live trading
- Monitor Performance: Review metrics regularly to identify strategy issues
- Adjust Position Sizing: Use metrics to optimize position sizes
- Document Changes: Keep notes when modifying metric calculations
- Version Control: Save different versions when experimenting with modifications
Conclusion
This modular PnL tracker transforms any Pine Script strategy into a professional trading system with comprehensive performance analytics. The plug-and-play design ensures compatibility with existing strategies while providing flexibility through extensive customization options. Implement this module to gain deeper insights into strategy performance and make data-driven trading decisions.
Thank you. I have integrated it into my strategy and it works without any issues.
Thank you for the script. I have integrated into my strategy and it works well. It would be good to have details in loss or profit on both sides like short or long. Currently it shows max loss or max win or avg loss or avg win but with shorts or longs is missing. Same with winning or losing trades. If this can be incorporated it would be good or more beneficial.
Thanks lot sir, as always you was the best and you are the best