//@version=5
indicator(title="Spectrometr", shorttitle="Spectrometr", overlay=false, format=format.price, precision=2)

// ——— Input Parameters
iPeriod     = input.int(240, title="Period")
iStartFrom  = input.int(1, title="Start From")
AddToObjName = input.string("1", title="Object Name Suffix")
HandlerColor = input.color(color.new(color.gray, 50), title="Handler Line Color")
TextColor    = input.color(color.new(color.gray, 50), title="Text Color")

// ——— Custom Variables
ObjNPref      = "Spectrometr_" + AddToObjName
LastLeftBar   = iStartFrom + iPeriod - 1
LastRightBar  = iStartFrom

// ——— Fourier Analysis Function
fFurie(arr) =>
    tN = array.size(arr)
    tM = int(tN / 2)
    aA = array.new<float>(tM, 0.0)
    aB = array.new<float>(tM, 0.0)
    aR = array.new<float>(tM, 0.0)

    for ti = 1 to tM - 1
        sumA = 0.0
        sumB = 0.0
        for tj = 0 to tN - 1
            val = array.get(arr, tj)
            sumA += val * math.sin(ti * 6.28 * tj / tN)
            sumB += val * math.cos(ti * 6.28 * tj / tN)
        array.set(aA, ti, 2 * sumA / tN)
        array.set(aB, ti, 2 * sumB / tN)
        array.set(aR, ti, math.sqrt(math.pow(array.get(aA, ti), 2) + math.pow(array.get(aB, ti), 2)))
    [aA, aB, aR]

// ——— Residuals and Fourier Component Calculation
residuals = array.new<float>()
fVals = array.new<float>(8, na)

if bar_index >= iPeriod
    // Collect price data
    prices = array.new<float>()
    for i = 0 to iPeriod - 1
        array.push(prices, close[i])

    // Estimate linear regression slope and intercept
    linreg_slope = ta.sma(ta.change(close), iPeriod)
    linreg_val   = ta.linreg(close, iPeriod, 0)

    // Compute residuals
    for i = 0 to iPeriod - 1
        lin_val = linreg_val + (iPeriod - 1 - i) * linreg_slope
        residual = close[i] - lin_val
        array.push(residuals, residual)

    // Apply Fourier transform
    [A, B, R] = fFurie(residuals)

    // Precompute 8 Fourier components
    for k = 1 to 8
        val = array.get(A, k) * math.sin(k * 6.28 * iPeriod / (iPeriod - 1)) +
              array.get(B, k) * math.cos(k * 6.28 * iPeriod / (iPeriod - 1))
        array.set(fVals, k - 1, val)

// ——— Plotting Fourier Components (Global Scope)
plot(array.get(fVals, 0), title="F_1", color=color.red, linewidth=2)
plot(array.get(fVals, 1), title="F_2", color=color.orange, linewidth=2)
plot(array.get(fVals, 2), title="F_3", color=color.yellow, linewidth=2)
plot(array.get(fVals, 3), title="F_4", color=color.lime, linewidth=2)
plot(array.get(fVals, 4), title="F_5", color=color.blue, linewidth=2)
plot(array.get(fVals, 5), title="F_6", color=color.new(color.blue, 50), linewidth=2)
plot(array.get(fVals, 6), title="F_7", color=color.new(color.purple, 50), linewidth=2)
plot(array.get(fVals, 7), title="F_8", color=color.gray, linewidth=2)

// ——— Drawing Line and Labels
if bar_index >= iPeriod
    line.new(x1=bar_index - LastLeftBar, y1=0, x2=bar_index - LastRightBar, y2=0,
             color=HandlerColor, style=line.style_dashed, width=3)

   // label.new(x=bar_index, y=0, text="Period: " + str.tostring(iPeriod),
     //         xloc=xloc.bar_index, yloc=yloc.price, style=label.style_label_left,
       //       color=color.white, textcolor=TextColor)

    //label.new(x=bar_index, y=0, text="StartFrom: " + str.tostring(iStartFrom),
      //        xloc=xloc.bar_index, yloc=yloc.price, style=label.style_label_right,
        //      color=color.white, textcolor=TextColor)

