math
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © facejungle

//@version=5

// @description TODO: add library description here
library("math", true)

export pine_ema(float src, int length) =>
    alpha = 2 / (length + 1)
    sum = 0.0
    sum := na(sum[1]) ? src : alpha * src + (1 - alpha) * nz(sum[1])

export pine_dema(float src, int length) =>
    ema = pine_ema(src, length)
    2 * ema - pine_ema(ema, length)

export pine_tema(float src, int length) =>
    ema = pine_ema(src, length)
    3 * (ema - pine_ema(ema, length)) + pine_ema(pine_ema(ema, length), length)

export pine_sma(float src, int length) =>
    sum = 0.0
    for i = 0 to length - 1
        sum := sum + src[i] / length
    sum

export pine_smma(float src, int length) =>
    sum = 0.0
    sma = pine_sma(src, length)
    na(sum[1]) ? sma : (sum[1] * (length - 1) + src) / length

export pine_ssma(float src, int length) =>
    a1 = math.exp(-1.414*3.14159 / length)
    b1 = 2*a1*math.cos(1.414*3.14159 / length)
    c2 = b1
    c3 = (-a1)*a1
    c1 = 1 - c2 - c3
    sum = 0.0
    sum := c1*(src + nz(src[1])) / 2 + c2*nz(sum[1]) + c3*nz(sum[2])

export pine_rma(float src, int length) =>
    alpha = 1/length
    sum = 0.0
    sma = pine_sma(src, length)
    sum := na(sum[1]) ? sma : alpha * src + (1 - alpha) * nz(sum[1])

export pine_wma(float x, int y) =>
    norm = 0.0
    sum = 0.0
    for i = 0 to y - 1
        weight = (y - i) * y
        norm := norm + weight
        sum := sum + x[i] * weight
    sum / norm

export pine_hma(float src, int length) => 
    pine_wma(2 * pine_wma(src, length / 2) - pine_wma(src, length), math.round(math.sqrt(length)))

export pine_vwma(float x, int y) =>
    pine_sma(x * volume, y) / ta.sma(volume, y)

export pine_swma(float x) =>
    x[3] * 1 / 6 + x[2] * 2 / 6 + x[1] * 2 / 6 + x[0] * 1 / 6

export pine_alma(float src, int length, float offset, float sigma) =>
    m = math.floor(offset * (length - 1))
    s = length / sigma
    norm = 0.0
    sum = 0.0
    for i = 0 to length - 1
        weight = math.exp(-1 * math.pow(i - m, 2) / (2 * math.pow(s, 2)))
        norm := norm + weight
        sum := sum + src[length - i - 1] * weight
    sum / norm
