Useful Pine Script v5 code snippets

Just copy & paste the ones you like and enjoy. Happy Trading!

Cutting-edge code, all day long.

Accurately calculate Peak-to-Trough cycles (Run-up and Drawdown)


Did you know that TradingView strategies calculate the drawdown for each trade but not for multiple trades together? That has a big impact.

TradingView’s strategy metrics might show you a max drawdown of 8.9%, representing the largest loss for any individual trade in the strategy. However, strategy’s drawdown from a relative peak to trough over multiple trades might be much larger. This insight is so critical, yet many traders are unaware that TradingView’s backtest results for drawdown can be misleading (albeit unintentionally). For that reason we are offering this free code to identify the peak-to-trough drawdown in your strategy. You can also use to automatically stop your strategy in case the drawdown exceeds your limit.

accurate strategy max drawdown peak to trough for tradingview by
accurate strategy max drawdown peak to trough for tradingview by
  • Accurately calculates peaks and troughs / drawdowns.
  • Let's you pause your strategy when the drawdown exceeds a level you specify.
  • Rows automatically switch color based on the year of when the trough occured.
  • Change the minimum trough percentage to see more or fewer cycles.
Max Drawdown (Peak-to-Trough)

showTable = input(true, title="Show Peak/Trough Table?")
min_trough = input.float(defval=20.0, title="Minimum Trough Percentage (0.1-100)")
maxdraw  = input.float(20.0, title = "Max Loss from Peak Startegy Equity at which Strategy will stop executing trades.")

// Initialize variables
var float equityPeak = na
var float equityTrough = na
var int cycleCount = 0
var bool inDrawdown = false
var float initialCapital = capital
var float prevTrough = initialCapital
var float prevRunUp = na
var bool useLighterGray = true // rows with same year get the same row color
var int lastYear = na

// Variable to indicate whether the strategy should end
var bool end_strategy = false

// Table to display data
var table resultTable =, 5, 30, bgcolor=#ffffff00, frame_color=#4f4040, frame_width=1)

// Function to convert float to percentage string
f_to_percent(value) =>
    str.tostring(value, "#.##") + "%"

// Function to get month/year string without commas
get_month_year_string() =>
    str.tostring(year) + "/" + str.tostring(month)

// Update the table headers
if (bar_index == 0 and showTable)
    table.cell(resultTable, 0, 0, "Show Min Trough: " + f_to_percent(min_trough), bgcolor=#a8a8a88f, text_size=size.tiny)
    table.cell(resultTable, 1, 0, "Cycle Count", bgcolor=#a8a8a88f, text_size=size.tiny)
    table.cell(resultTable, 2, 0, "Prev.RunUp(%)", bgcolor=#a8a8a88f, text_size=size.tiny)
    table.cell(resultTable, 3, 0, "Drawdown(%)", bgcolor=#a8a8a88f, text_size=size.tiny)
    table.cell(resultTable, 4, 0, "Year/Month", bgcolor=#a8a8a88f, text_size=size.tiny)

// Track peaks and troughs in equity
if (na(equityPeak) or strategy.equity > equityPeak)
    if (inDrawdown and strategy.equity > equityPeak and not na(equityTrough)) // Confirm end of drawdown cycle
        drawdownPercentage = (equityPeak - equityTrough) / equityPeak * 100
        if drawdownPercentage > min_trough
            cycleCount += 1
            prevRunUp := (equityPeak - prevTrough) / prevTrough * 100
            if cycleCount <= 20 and showTable
                currentYear = year
                if na(lastYear) or currentYear != lastYear
                    useLighterGray := not useLighterGray
                    lastYear := currentYear
                rowColor = useLighterGray ?, 80) :, 50)
                table.cell(resultTable, 1, cycleCount, str.tostring(cycleCount), bgcolor=rowColor, text_size=size.tiny)
                table.cell(resultTable, 2, cycleCount, f_to_percent(prevRunUp), bgcolor=rowColor, text_size=size.tiny)
                table.cell(resultTable, 3, cycleCount, f_to_percent(drawdownPercentage), bgcolor=rowColor, text_size=size.tiny)
                table.cell(resultTable, 4, cycleCount, get_month_year_string(), bgcolor=rowColor, text_size=size.tiny)
            prevTrough := equityTrough
    equityPeak := strategy.equity
    equityTrough := na
    inDrawdown := false
else if (strategy.equity < equityPeak)
    equityTrough := na(equityTrough) ? strategy.equity : math.min(equityTrough, strategy.equity)
    inDrawdown := true
// Calculate if the strategy should end
if not na(equityPeak) and not na(equityTrough)
    drawdownPercentage = (equityPeak - equityTrough) / equityPeak * 100
    if drawdownPercentage >= maxdraw
        end_strategy := true
Scroll to Top

We're going live soon. Join our waitlist!

    For questions, write us to

    Upgrade to Annual and SAVE

    Pay 294/yr instead of 588 = 6 months free


    Proceed with Monthly Plan