pine-scriptderivativezigzag

Compute slope/derivative values of zigzag line


I would like to compute the slope/derivative of each zigzag line, and show them above/below the zigzag line. How to do this?

Example of zigzag:

//@version=4
study("ZigZagSlope", overlay = true, max_bars_back = 500, max_lines_count = 300)
prd = input(defval = 3, title="ZigZag Period", minval = 2, maxval = 50)
showzigzag = input(defval = true, title = "Show Zig Zag")
upcol = input(defval = color.black, title = "Zigzag Up Color")
dncol = input(defval = color.black, title = "Zigzag Down Color")

float ph = highestbars(high, prd) == 0 ? high : na
float pl = lowestbars(low, prd) == 0 ? low : na
var dir = 0
dir := iff(ph and na(pl), 1, iff(pl and na(ph), -1, dir))
var max_array_size = 10
var zigzag = array.new_float(0)

add_to_zigzag(value, bindex)=>
    array.unshift(zigzag, bindex)
    array.unshift(zigzag, value)
    if array.size(zigzag) > max_array_size
        array.pop(zigzag)
        array.pop(zigzag)
    
update_zigzag(value, bindex)=>
    if array.size(zigzag) == 0
        add_to_zigzag(value, bindex)
    else
        if (dir == 1 and value > array.get(zigzag, 0)) or (dir == -1 and value < array.get(zigzag, 0))
            array.set(zigzag, 0, value)
            array.set(zigzag, 1, bindex)
        0.
Round_it(value)=> round(value / syminfo.mintick) * syminfo.mintick

dirchanged = change(dir)
if ph or pl
    if dirchanged
        add_to_zigzag(dir == 1 ? ph : pl, bar_index)
    else
        update_zigzag(dir == 1 ? ph : pl, bar_index)

if showzigzag and array.size(zigzag) >= 4
    var line zzline = na
    float val = array.get(zigzag, 0)
    int point = round(array.get(zigzag, 1))
    if change(val) or change(point)
        float val1 = array.get(zigzag, 2)
        int point1 = round(array.get(zigzag, 3))
        if change(val1) == 0 and change(point1) == 0
            line.delete(zzline)
        zzline := line.new(x1 = point, y1 = val, x2 = point1, y2 = val1, color = dir == 1 ? upcol : dncol, width = 2)

Example of computation of derivatives:

https://www.tradingview.com/script/1Ea3KEUq-MaxWarren-s-Pine-Acceleration-2nd-Derivative/


Solution

  • Slope is rise over run, in this case it is by (val - val1) / (point - point1). Which is the price difference over the the bar_index difference.

    You can add it to your script as follows, I've included the variable values in the label so you can confirm them manually.

    Comparing the current slope to the 2nd previous one of the same direction, we need to check first if it exists in the array by checking the array size again. Then we can retrieve the price and bar_index values from the array and do the same rise/run calculation and compare the existing zigzag's slope to the 2nd previous one.

    //@version=4
    study("ZigZagSlope", overlay = true, max_bars_back = 500, max_lines_count = 300)
    prd = input(defval = 3, title="ZigZag Period", minval = 2, maxval = 50)
    showzigzag = input(defval = true, title = "Show Zig Zag")
    upcol = input(defval = color.black, title = "Zigzag Up Color")
    dncol = input(defval = color.black, title = "Zigzag Down Color")
    
    float ph = highestbars(high, prd) == 0 ? high : na
    float pl = lowestbars(low, prd) == 0 ? low : na
    var dir = 0
    dir := iff(ph and na(pl), 1, iff(pl and na(ph), -1, dir))
    var max_array_size = 10
    var zigzag = array.new_float(0)
    
    add_to_zigzag(value, bindex)=>
        array.unshift(zigzag, bindex)
        array.unshift(zigzag, value)
        if array.size(zigzag) > max_array_size
            array.pop(zigzag)
            array.pop(zigzag)
        
    update_zigzag(value, bindex)=>
        if array.size(zigzag) == 0
            add_to_zigzag(value, bindex)
        else
            if (dir == 1 and value > array.get(zigzag, 0)) or (dir == -1 and value < array.get(zigzag, 0))
                array.set(zigzag, 0, value)
                array.set(zigzag, 1, bindex)
            0.
    Round_it(value)=> round(value / syminfo.mintick) * syminfo.mintick
    
    dirchanged = change(dir)
    if ph or pl
        if dirchanged
            add_to_zigzag(dir == 1 ? ph : pl, bar_index)
        else
            update_zigzag(dir == 1 ? ph : pl, bar_index)
    
    if showzigzag and array.size(zigzag) >= 4
        var line zzline = na
        var label slope_label = na
        float val = array.get(zigzag, 0)
        int point = round(array.get(zigzag, 1))
        if change(val) or change(point)
            float val1 = array.get(zigzag, 2)
            int point1 = round(array.get(zigzag, 3))
            if change(val1) == 0 and change(point1) == 0
                line.delete(zzline)
                label.delete(slope_label)
            zzline := line.new(x1 = point, y1 = val, x2 = point1, y2 = val1, color = dir == 1 ? upcol : dncol, width = 2)
            slope = (val - val1) / (point - point1)
            debug_vals_text = "\nval : " + tostring(val) + "\nval1 : " + tostring(val1) + "\npoint : " + tostring(point) + "\npoint1 : " + tostring(point1)
            slope_text = "slope : " + tostring(slope)
            string slope2_text = na
            float slope2 = na
            if array.size(zigzag) >= 8
                val2 = array.get(zigzag, 4)
                point2 = array.get(zigzag, 5)
                val3 = array.get(zigzag, 6)
                point3 = array.get(zigzag, 7)
                slope2 := (val2 - val3) / (point2 - point3)
                slope2_text := "\nval2 : " + tostring(val2) + "\nval3 : " + tostring(val3) + "\npoint2 : " + tostring(point2) + "\npoint3 : " + tostring(point3) + "\nprev slope : " + tostring(slope2)
            slope_diff_text = "\n\nslope diff : " + tostring(slope - slope2)
            slope_label := label.new(x = point, y = val, text = slope_text + "\n\n" + debug_vals_text + slope2_text + slope_diff_text, style = val > val1 ? label.style_label_down : label.style_label_up, size = size.small)