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 tradingwhale.io
accurate strategy max drawdown peak to trough for tradingview by tradingwhale.io
  • 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.")

//  Peak-Trough Cycles with Date
// 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
var int lastYear = na
var float highestDrawdown = na
var string dateOfHighestDrawdown = na

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

// Collect Drawdown(%) values during the cycle tracking
var float[] drawdownValues = array.new_float()

// Table to display data
var table resultTable = table.new(position.top_right, 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)

// Track peaks and troughs in equity based on closed trades
float currentEquity = initialCapital + strategy.netprofit

if (na(equityPeak) or currentEquity > equityPeak)
    if (inDrawdown and not na(equityTrough))  // Confirm end of drawdown cycle
        float drawdownPercentage = (equityPeak - equityTrough) / equityPeak * 100
        if na(highestDrawdown) or drawdownPercentage > highestDrawdown  // Check if this is the highest drawdown
            highestDrawdown := drawdownPercentage  // Update the highest drawdown
            dateOfHighestDrawdown = timenow  // Record the date of the highest drawdown

        if drawdownPercentage > min_trough  // Minimum drawdown threshold
            cycleCount += 1
            prevRunUp := (equityPeak - prevTrough) / prevTrough * 100
            if cycleCount <= max_dd_rows and showTable
                table.cell(resultTable, 0, 0, "Show MinDraw: " + f_to_percent(min_trough), bgcolor=#a8a8a88f, text_size=size.tiny)
                table.cell(resultTable, 1, 0, "Cycle Count", bgcolor=#a8a8a88f, text_size=size.tiny)
                if plot_runups
                    table.cell(resultTable, 2, 0, "Prev.RunUp(%)", bgcolor=#a8a8a88f, text_size=size.tiny)
                table.cell(resultTable, 3, 0, "MaxDraw(%)", bgcolor=#a8a8a88f, text_size=size.tiny)
                table.cell(resultTable, 4, 0, "Year/Month", bgcolor=#a8a8a88f, text_size=size.tiny)
                int currentYear = year(timenow)
                if na(lastYear) or currentYear != lastYear
                    useLighterGray := not useLighterGray
                    lastYear := currentYear
                color rowColor = useLighterGray ? color.new(color.gray, 80) : color.new(color.gray, 50)
                table.cell(resultTable, 1, cycleCount, str.tostring(cycleCount), bgcolor=rowColor, text_size=size.tiny)
                if plot_runups
                    table.cell(resultTable, 2, cycleCount, f_to_percent(prevRunUp), bgcolor=rowColor, text_size=size.tiny)
                table.cell(resultTable, 3, cycleCount, f_to_percent(highestDrawdown), bgcolor=rowColor, text_size=size.tiny)
                table.cell(resultTable, 4, cycleCount, get_month_year_string(), bgcolor=rowColor, text_size=size.tiny)
            array.push(drawdownValues, highestDrawdown)
            prevTrough := equityTrough
            highestDrawdown := na  // Reset the highest drawdown after recording
            dateOfHighestDrawdown := na  // Reset the date of the highest drawdown after recording

    equityPeak := currentEquity
    equityTrough := na
    inDrawdown := false
else if (currentEquity < equityPeak)
    equityTrough := na(equityTrough) ? currentEquity : math.min(equityTrough, currentEquity)
    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 sales@tradingwhale.io

    Upgrade to Annual and SAVE

    Pay 294/yr instead of 588 = 6 months free

    or

    Proceed with Monthly Plan