Indicator · Pine Script v5 · Own pane

Hurst Spectral Analysis Oscillator V2

by mikeyhu70

A Pine Script v5 indicator in a separate pane, the second revision of a Hurst spectral oscillator.

View on GitHub

Repaints

GitHub stars1on the repository
Pine versionv5runs as is
Lines of code621
Settings40inputs
LicenceNone statedfile: MPL-2.0
Last update6 months ago15 Apr 2026

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new indicator, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart, then adjust the settings with the gear icon next to its name.

Source Code

621 lines of Pine Script v5 from Hurst/Hurst Spectral Analysis Oscillator V2.txt, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

Hurst Spectral Analysis Oscillator V2.txt
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/

//@version=5
indicator('Hurst Spectral Analysis Oscillator', overlay=false, format=format.price, precision=3) 

//-------------------------------Inputs-------------------------------//
source = input(hl2, 'Source', group="Bandpass Settings")
bandWidth = input.float(0.000005, 'Bandwidth', minval=0.0, maxval=1.0, step=0.001, group="Bandpass Settings")
mode_sel = input.string(title='Cycle Selection Mode ?', defval='Auto', options=['Auto', 'Manual'])
mode_comp = input.string(title='Composite Line Multiplier Offset Mode ?', defval='Auto', options=['Auto', 'Manual'])
mode_comp_sel = input.string(title='Composite Selection Mode ?', defval='Auto', options=['Auto', 'Manual'])
mode_comp2 = input.string(title='Composite Cycle Multiplier Offset Mode ?', defval='Auto', options=['Auto', 'Manual'])
mode_offset = input.string(title='Cycle Offset Mode ?', defval='Auto', options=['Auto', 'Manual'])
//bandWidth = input.float(0.025, 'Bandwidth', minval=0.0, maxval=1.0, step=0.001, group="Bandpass Settings")
periodBandpass0 = input.float(1.1, '1 Day      ', minval=1, inline="1", group="Cycle Settings")
periodBandpass1 = input.float(2.2, '2 Day    ', minval=1, inline="2", group="Cycle Settings")
periodBandpassh = input.float(4.3, '5 Day      ', minval=2, inline="3", group="Cycle Settings")
periodBandpassf = input.float(8.5, '10 Day    ', minval=2, inline="4", group="Cycle Settings")
periodBandpass2 = input.float(17, '20 Day    ', minval=2, inline="5", group="Cycle Settings")
periodBandpass4 = input.float(34.1, '40 Day    ', minval=2, inline="6", group="Cycle Settings")
periodBandpass8 = input.float(68.2, '80 Day    ', minval=2, inline="7", group="Cycle Settings")
periodBandpass16 = input.float(136.4, '20 Week ', minval=2, inline="8", group="Cycle Settings")
periodBandpass32 = input.float(272.8, '40 Week ', minval=2, inline="9", group="Cycle Settings")
periodBandpass64 = input.float(545.6, '18 Month', minval=2, inline="10", group="Cycle Settings")
periodBandpass128 = input.float(1636.8, '54 Month', minval=2, inline="11", group="Cycle Settings")
periodBandpass256 = input.float(3273.6, '9 Year    ', minval=2, inline="12", group="Cycle Settings")
periodBandpass512 = input.float(6547.2, '18 Year  ', minval=2, inline="13", group="Cycle Settings")

// -- Functions

PriceFormat() =>
    syminfo.mintick <= 0.00001 ? '0' : syminfo.mintick <= 0.0001 ? '0' : syminfo.mintick <= 0.001 ? '0' : syminfo.mintick <= 0.01 ? '0' : syminfo.mintick <= 0.1 ? '0' : '0'

PriceFormat2() =>
    syminfo.mintick <= 0.00001 ? '0.0' : syminfo.mintick <= 0.0001 ? '0.0' : syminfo.mintick <= 0.001 ? '0.0' : syminfo.mintick <= 0.01 ? '0.0' : syminfo.mintick <= 0.1 ? '0.0' : '0.0'

f_resInMinutes() =>
    _resInMinutes = timeframe.multiplier * (timeframe.isseconds ? 1. / 60 : timeframe.isminutes ? 1. : timeframe.isdaily ? 60. * 24 : timeframe.isweekly ? 60. * 24 * 7 : timeframe.ismonthly ? 60. * 24 * 30.4375 : na)
    _resInMinutes

f_timeFrom(_from, _qty, _units) =>
    // _from  : starting time from where the offset is calculated: "bar" to start from the bar's starting time, "close" to start from the bar's closing time, "now" to start from the current time.
    // _qty   : the +/- qty of _units of offset required. A "series float" can be used but it will be cast to a "series int".
    // _units : string containing one of the seven allowed time units: "chart" (chart's resolution), "seconds", "minutes", "hours", "days", "months", "years".
    // Dependency: f_resInMinutes().
    int _timeFrom = na
    // Remove any "s" letter in the _units argument, so we don't need to compare singular and plural unit names.
    _unit = str.replace_all(_units, 's', '')
    // Determine if we will calculate offset from the bar's time or from current time.
    _t = _from == 'bar' ? time : _from == 'close' ? time_close : timenow
    // Calculate time at offset.
    if _units == 'chart'
        // Offset in chart res multiples.
        _timeFrom := int(_t + f_resInMinutes() * 60 * 1000 * _qty)
        _timeFrom
    else
        // Add the required _qty of time _units to the _from starting time.
        _year = year(_t) + (_unit == 'year' ? int(_qty) : 0)
        _month = month(_t) + (_unit == 'month' ? int(_qty) : 0)
        _day = dayofmonth(_t) + (_unit == 'day' ? int(_qty) : 0)
        _hour = hour(_t) + (_unit == 'hour' ? int(_qty) : 0)
        _minute = minute(_t) + (_unit == 'minute' ? int(_qty) : 0)
        _second = second(_t) + (_unit == 'econd' ? int(_qty) : 0)
        // Return the resulting time in ms Unix time format.
        _timeFrom := timestamp(_year, _month, _day, _hour, _minute, _second)
        _timeFrom

f_calc_bar_time(offset) =>
    ret = time + (time - time[1]) * offset
    ret

f_DaysBetween(t1, t2) =>
    math.ceil((t1 - t2) / 86400000) + 1

f_offsetTime(_userOffsetInput) =>

    // init our _return variable
    var int _return = na

    // get current time
    int _timeNow = time

    // get difference between current bar time and previous bar time
    int _timeSeg = time - time[1]

    // multiply the segment by the user input
    int _segMult = _timeSeg * _userOffsetInput

    // return time now + multiplied time segment for offset, giving us our
    // +1|2|3 etc. OR -1|2|3 location depending on user input.
    _return := _timeNow + _segMult
    _return


// Color Selection
fld18y = #5E0F0B
fld9y = #DB241A
fld54m = #D47A35
fld18m = #C4B727
fld40w = #62E322
fld20w = #3C8A15
fld80 = #67A5A8
fld40 = #161861
fld20 = #9658E1
fld10 = #D15C7B
fld5 = #E386C2
fld2 = #B80D18
fld1 = #FF7F50
fld5h = #FFB836
fld0 = color.gray

//colh = input.color(color.purple, " ", inline="1", group="Cycle Settings")
//colf = input.color(color.blue, " ", inline="2", group="Cycle Settings")
//col2 = input.color(color.aqua, " ", inline="3", group="Cycle Settings")
//col4 = input.color(color.green, " ", inline="4", group="Cycle Settings")
//col8 = input.color(color.yellow, " ", inline="5", group="Cycle Settings")
//col16 = input.color(color.orange, " ", inline="6", group="Cycle Settings")
//col32 = input.color(color.red, " ", inline="7", group="Cycle Settings")
//col64 = input.color(#856c44, " ", inline="8", group="Cycle Settings")
//col128 = input.color(color.black, " ", inline="9", group="Cycle Settings")
//col256 = input.color(color.gray, " ", inline="10", group="Cycle Settings")
//col512 = input.color(color.white, " ", inline="11", group="Cycle Settings")
//colcompu = input.color(color.new(#00ff0a, 70), "Composite Model Candle Colors", inline="12", group="Cycle Settings") 
//colcompd = input.color(color.new(#ff0000, 70), " ", inline="12", group="Cycle Settings") 

//color_col2= periodBandpass2 > 5500 ? fld18y : periodBandpass2 > 2500 ? fld9y : periodBandpass2 > 1000 ? fld54m : periodBandpass2 > 400 ? fld18m : periodBandpass2 > 200 ? fld40w : periodBandpass2 > 100 ? fld20w : periodBandpass2 > 55 ? fld80 : periodBandpass2 > 25 ? fld40 : periodBandpass2 > 12 ? fld20 : periodBandpass2 > 7 ? fld10 : periodBandpass2 > 3.2 ? fld5 : periodBandpass2 > 2 ? fld2 : periodBandpass2 > 1 ? fld1 : _auto_fld2 > 0.15 ? fld5h : fld0


col0 = input.color(fld1, " ", inline="1", group="Cycle Settings")
col1 = input.color(fld2, " ", inline="2", group="Cycle Settings")
colh = input.color(fld5, " ", inline="3", group="Cycle Settings")
colf = input.color(fld10, " ", inline="4", group="Cycle Settings")
col2 = input.color(fld20, " ", inline="5", group="Cycle Settings")
col4 = input.color(fld40, " ", inline="6", group="Cycle Settings")
col8 = input.color(fld80, " ", inline="7", group="Cycle Settings")
col16 = input.color(fld20w, " ", inline="8", group="Cycle Settings")
col32 = input.color(fld40w, " ", inline="9", group="Cycle Settings")
col64 = input.color(fld18m, " ", inline="10", group="Cycle Settings")
col128 = input.color(fld54m, " ", inline="11", group="Cycle Settings")
col256 = input.color(fld9y, " ", inline="12", group="Cycle Settings")
col512 = input.color(fld18y, " ", inline="13", group="Cycle Settings")

colcompu = input.color(color.new(#00ff0a, 70), "Composite Model Candle Colors", inline="14", group="Cycle Settings") 
colcompd = input.color(color.new(#ff0000, 70), " ", inline="14", group="Cycle Settings") 


// Composite Selection
comp0 = input.bool(false, "Composite", inline="1", group="Cycle Settings")
comp1 = input.bool(false, "Composite", inline="2", group="Cycle Settings")
comph = input.bool(true, "Composite", inline="3", group="Cycle Settings")
compf = input.bool(true, "Composite", inline="4", group="Cycle Settings")
comp2 = input.bool(true, "Composite", inline="5", group="Cycle Settings")
comp4 = input.bool(true, "Composite", inline="6", group="Cycle Settings")
comp8 = input.bool(false, "Composite", inline="7", group="Cycle Settings")
comp16 = input.bool(false, "Composite", inline="8", group="Cycle Settings")
comp32 = input.bool(false, "Composite", inline="9", group="Cycle Settings")
comp64 = input.bool(false, "Composite", inline="10", group="Cycle Settings")
comp128 = input.bool(false, "Composite", inline="11", group="Cycle Settings")
comp256 = input.bool(false, "Composite", inline="12", group="Cycle Settings")
comp512 = input.bool(false, "Composite", inline="13", group="Cycle Settings")
compdisplay = input.bool(true, "Composite Line", inline="14", group="Cycle Settings")
compcycle = input.bool(false, "Composite Cycle", inline="15", group="Cycle Settings")


// Offset Selection
_ocomp0 = input.int(4, "1 Day Offset Multiplier", inline="1", group="Cycle Settings 2")
_ocomp1 = input.int(4, "2 Day Offset Multiplier", inline="2", group="Cycle Settings 2")
_ocomph = input.int(4, "5 Day Offset Multiplier", inline="3", group="Cycle Settings 2")
_ocompf = input.int(4, "10 Day Offset Multiplier", inline="4", group="Cycle Settings 2")
_ocomp2 = input.int(2, "20 Day Offset Multiplier", inline="5", group="Cycle Settings 2")
_ocomp4 = input.int(2, "40 Day Offset Multiplier", inline="6", group="Cycle Settings 2")
_ocomp8 = input.int(2, "80 Day Offset Multiplier", inline="7", group="Cycle Settings 2")
_ocomp16 = input.int(1, "20 Week Offset Multiplier", inline="8", group="Cycle Settings 2")
_ocomp32 = input.int(1, "40 Week Offset Multiplier", inline="9", group="Cycle Settings 2")
_ocomp64 = input.int(1, "18 Month Offset Multiplier", inline="10", group="Cycle Settings 2")
_ocomp128 = input.int(1, "54 Month Offset Multiplier", inline="11", group="Cycle Settings 2")
_ocomp256 = input.int(1, "9 Year Offset Multiplier", inline="12", group="Cycle Settings 2")
_ocomp512 = input.int(1, "18 Year Offset Multiplier", inline="13", group="Cycle Settings 2")
_ocomps = input.float(1.0, "Composite Line Offset Multiplier", inline="14", group="Cycle Settings 2")
complinediv = input.int(2, "Composite Line Divider", inline="15", group="Cycle Settings 2")
_ocomps2 = input.float(2.0, "Composite Cycle Offset Multiplier", inline="16", group="Cycle Settings 2")
compcyclediv = input.int(2, "Composite Cycle Divider", inline="17", group="Cycle Settings 2")
cyclediv0 = input.int(1, "1 Day Cycle Divider", inline="18", group="Cycle Settings 2")
cyclediv1 = input.int(1, "2 Day Cycle Divider", inline="18", group="Cycle Settings 2")
cycledivh = input.int(1, "5 Day Cycle Divider", inline="18", group="Cycle Settings 2")
cycledivf = input.int(1, "10 Day Cycle Divider", inline="18", group="Cycle Settings 2")
cyclediv2 = input.int(1, "20 Day Cycle Divider", inline="18", group="Cycle Settings 2")
cyclediv4 = input.int(1, "40 Day Cycle Divider", inline="18", group="Cycle Settings 2")
cyclediv8 = input.int(1, "20 Day Cycle Divider", inline="18", group="Cycle Settings 2")
cyclediv16 = input.int(1, "20 Week Cycle Divider", inline="18", group="Cycle Settings 2")
cyclediv32 = input.int(1, "40 Week Cycle Divider", inline="18", group="Cycle Settings 2")
cyclediv64 = input.int(1, "18 Month Cycle Divider", inline="18", group="Cycle Settings 2")
cyclediv128 = input.int(1, "54 Month Cycle Divider", inline="18", group="Cycle Settings 2")
cyclediv256 = input.int(1, "9 Year Cycle Divider", inline="18", group="Cycle Settings 2")
cyclediv512 = input.int(1, "18 Year Cycle Divider", inline="18", group="Cycle Settings 2")
//__ocomps = timeframe.period == 'M' ? 0: timeframe.period == 'W' ? 0 : timeframe.period == 'D' ? 0 : timeframe.period == '240' ? 0 : timeframe.period == '120' ? 0 : timeframe.period == '60' ? 0 : timeframe.period == '30' ? 0 : timeframe.period == '15' ? 0 : timeframe.period == '10' ? 0 : timeframe.period == '5' ? 0 : 0
//__ocomps = timeframe.period == 'M' ? 4: timeframe.period == 'W' ? 2 : timeframe.period == 'D' ? 2 : timeframe.period == '240' ? 1 : timeframe.period == '120' ? 1 : timeframe.period == '60' ? 1 : timeframe.period == '30' ? 1 : timeframe.period == '15' ? 1 : timeframe.period == '10' ? 1 : timeframe.period == '5' ? 1 : 0
__ocomps = timeframe.period == 'M' ? 4: timeframe.period == 'W' ? 4 : timeframe.period == 'D' ? 4 : timeframe.period == '240' ? 2 : timeframe.period == '120' ? 2 : timeframe.period == '60' ? 2 : timeframe.period == '30' ? 2 : timeframe.period == '15' ? 2 : timeframe.period == '10' ? 2 : timeframe.period == '5' ? 2 : 0
ocomps  = mode_comp == 'Auto' ? __ocomps : _ocomps

__ocomps2 = timeframe.period == 'M' ? 4: timeframe.period == 'W' ? 8 : timeframe.period == 'D' ? 4 : timeframe.period == '240' ? 2 : timeframe.period == '120' ? 2 : timeframe.period == '60' ? 2 : timeframe.period == '30' ? 2 : timeframe.period == '15' ? 2 : timeframe.period == '10' ? 2 : timeframe.period == '5' ? 2 : 0
ocomps2  = mode_comp2 == 'Auto' ? __ocomps2 : _ocomps2

__ocomp0 = timeframe.period == 'M' ? 4: timeframe.period == 'W' ? 4 : timeframe.period == 'D' ? 8 : timeframe.period == '240' ? 32 : timeframe.period == '120' ? 32 : timeframe.period == '60' ? 32 : timeframe.period == '30' ? 32 : timeframe.period == '15' ? 32 : timeframe.period == '10' ? 32 : timeframe.period == '5' ? 32 : 0
__ocomp1 = timeframe.period == 'M' ? 4: timeframe.period == 'W' ? 4 : timeframe.period == 'D' ? 8 : timeframe.period == '240' ? 32 : timeframe.period == '120' ? 32 : timeframe.period == '60' ? 32 : timeframe.period == '30' ? 32 : timeframe.period == '15' ? 32 : timeframe.period == '10' ? 32 : timeframe.period == '5' ? 32 : 0
__ocomph = timeframe.period == 'M' ? 4: timeframe.period == 'W' ? 4 : timeframe.period == 'D' ? 4 : timeframe.period == '240' ? 32 : timeframe.period == '120' ? 32 : timeframe.period == '60' ? 32 : timeframe.period == '30' ? 32 : timeframe.period == '15' ? 32 : timeframe.period == '10' ? 32 : timeframe.period == '5' ? 32 : 0
__ocompf = timeframe.period == 'M' ? 4: timeframe.period == 'W' ? 4 : timeframe.period == 'D' ? 4 : timeframe.period == '240' ? 20 : timeframe.period == '120' ? 16 : timeframe.period == '60' ? 16 : timeframe.period == '30' ? 16 : timeframe.period == '15' ? 16 : timeframe.period == '10' ? 16 : timeframe.period == '5' ? 32 : 0
__ocomp2 = timeframe.period == 'M' ? 4: timeframe.period == 'W' ? 4 : timeframe.period == 'D' ? 4 : timeframe.period == '240' ? 8 : timeframe.period == '120' ? 8 : timeframe.period == '60' ? 8 : timeframe.period == '30' ? 8 : timeframe.period == '15' ? 8 : timeframe.period == '10' ? 8 : timeframe.period == '5' ? 8 : 0
__ocomp4 = timeframe.period == 'M' ? 4: timeframe.period == 'W' ? 4 : timeframe.period == 'D' ? 2 : timeframe.period == '240' ? 4 : timeframe.period == '120' ? 4 : timeframe.period == '60' ? 4 : timeframe.period == '30' ? 4 : timeframe.period == '15' ? 4 : timeframe.period == '10' ? 4 : timeframe.period == '5' ? 4 : 0
__ocomp8 = timeframe.period == 'M' ? 2: timeframe.period == 'W' ? 2 : timeframe.period == 'D' ? 2 : timeframe.period == '240' ? 2 : timeframe.period == '120' ? 2 : timeframe.period == '60' ? 4 : timeframe.period == '30' ? 4 : timeframe.period == '15' ? 4 : timeframe.period == '10' ? 4 : timeframe.period == '5' ? 4 : 0
__ocomp16 = timeframe.period == 'M' ? 2: timeframe.period == 'W' ? 2 : timeframe.period == 'D' ? 2 : timeframe.period == '240' ? 2 : timeframe.period == '120' ? 2 : timeframe.period == '60' ? 4 : timeframe.period == '30' ? 4 : timeframe.period == '15' ? 4 : timeframe.period == '10' ? 4 : timeframe.period == '5' ? 4 : 0
__ocomp32 = timeframe.period == 'M' ? 2: timeframe.period == 'W' ? 2 : timeframe.period == 'D' ? 2 : timeframe.period == '240' ? 2 : timeframe.period == '120' ? 2 : timeframe.period == '60' ? 2 : timeframe.period == '30' ? 2 : timeframe.period == '15' ? 2 : timeframe.period == '10' ? 2 : timeframe.period == '5' ? 2 : 0
__ocomp64 = timeframe.period == 'M' ? 2: timeframe.period == 'W' ? 2 : timeframe.period == 'D' ? 2 : timeframe.period == '240' ? 2 : timeframe.period == '120' ? 2 : timeframe.period == '60' ? 2 : timeframe.period == '30' ? 2 : timeframe.period == '15' ? 2 : timeframe.period == '10' ? 2 : timeframe.period == '5' ? 2 : 0
__ocomp128 = timeframe.period == 'M' ? 2: timeframe.period == 'W' ? 2 : timeframe.period == 'D' ? 2 : timeframe.period == '240' ? 2 : timeframe.period == '120' ? 2 : timeframe.period == '60' ? 2 : timeframe.period == '30' ? 2 : timeframe.period == '15' ? 2 : timeframe.period == '10' ? 2 : timeframe.period == '5' ? 2 : 0
__ocomp256 = timeframe.period == 'M' ? 2: timeframe.period == 'W' ? 2 : timeframe.period == 'D' ? 2 : timeframe.period == '240' ? 2 : timeframe.period == '120' ? 2 : timeframe.period == '60' ? 2 : timeframe.period == '30' ? 2 : timeframe.period == '15' ? 2 : timeframe.period == '10' ? 2 : timeframe.period == '5' ? 2 : 0
__ocomp512 = timeframe.period == 'M' ? 2: timeframe.period == 'W' ? 2 : timeframe.period == 'D' ? 2 : timeframe.period == '240' ? 2 : timeframe.period == '120' ? 2 : timeframe.period == '60' ? 2 : timeframe.period == '30' ? 2 : timeframe.period == '15' ? 2 : timeframe.period == '10' ? 2 : timeframe.period == '5' ? 2 : 0


ocomp0 = mode_offset == 'Auto' ? __ocomp0 : _ocomp0
ocomp1 = mode_offset == 'Auto' ? __ocomp1 : _ocomp1
ocomph = mode_offset == 'Auto' ? __ocomph : _ocomph
ocompf = mode_offset == 'Auto' ? __ocompf : _ocompf
ocomp2 = mode_offset == 'Auto' ? __ocomp2 : _ocomp2
ocomp4 = mode_offset == 'Auto' ? __ocomp4 : _ocomp4
ocomp8 = mode_offset == 'Auto' ? __ocomp8 : _ocomp8
ocomp16 = mode_offset == 'Auto' ? __ocomp16 : _ocomp16
ocomp32 = mode_offset == 'Auto' ? __ocomp32 : _ocomp32
ocomp64 = mode_offset == 'Auto' ? __ocomp64 : _ocomp64
ocomp128 = mode_offset == 'Auto' ? __ocomp128 : _ocomp128
ocomp256 = mode_offset == 'Auto' ? __ocomp256 : _ocomp256
ocomp512 = mode_offset == 'Auto' ? __ocomp512 : _ocomp512



// Force Cycle Display
dcomp0 = input.bool(false, "Non-Auto Selection", inline="1", group="Cycle Settings")
dcomp1 = input.bool(false, "Non-Auto Selection", inline="2", group="Cycle Settings")
dcomph = input.bool(false, "Non-Auto Selection", inline="3", group="Cycle Settings")
dcompf = input.bool(false, "Non-Auto Selection", inline="4", group="Cycle Settings")
dcomp2 = input.bool(false, "Non-Auto Selection", inline="5", group="Cycle Settings")
dcomp4 = input.bool(false, "Non-Auto Selection", inline="6", group="Cycle Settings")
dcomp8 = input.bool(false, "Non-Auto Selection", inline="7", group="Cycle Settings")
dcomp16 = input.bool(false, "Non-Auto Selection", inline="8", group="Cycle Settings")
dcomp32 = input.bool(false, "Non-Auto Selection", inline="9", group="Cycle Settings")
dcomp64 = input.bool(false, "Non-Auto Selection", inline="10", group="Cycle Settings")
dcomp128 = input.bool(false, "Non-Auto Selection", inline="11", group="Cycle Settings")
dcomp256 = input.bool(false, "Non-Auto Selection", inline="12", group="Cycle Settings")
dcomp512 = input.bool(false, "Non-Auto Selection", inline="13", group="Cycle Settings")

// Analysis Inputs
mode_sig_in = input.string(title='Bandpass Analysis Mode ?', defval='Auto', options=['Auto', 'Manual'])
_sig_in = input.string("20 Day", "Bandpass for Analysis", options=["5 Day", "10 Day", "20 Day", "40 Day", "80 Day", "20 Week", "40 Week", "18 Month", "54 Month", "9 Year", "18 Year", "None"], group="Analysis Settings")
decimals = input.int(2, 'Price Decimals', minval=0, maxval=10, group="Analysis Settings")
position = input.string(position.bottom_center, "Analysis Position", [position.top_center, position.top_right, position.middle_right, position.bottom_right, position.bottom_center, position.bottom_left, position.middle_left, position.top_left], group="Analysis Settings")
size = input.string(size.small, "Text Size", [size.tiny, size.small, size.normal, size.large, size.huge], group="Analysis Settings")
tableposy = input.string(defval='top', title='Chart Location', options=['bottom', 'middle', 'top'], inline='chartpos')
tableposx = input.string(defval='right', title='', options=['left', 'center', 'right'], inline='chartpos')
showtable = input.bool(defval = true, title = "Show Forecast Table")



//////
auto_sig_in = timeframe.period == 'M' ? "40 Week" : timeframe.period == 'W' ? "20 Week" : timeframe.period == 'D' ? "40 Day": timeframe.period == '240' ? "20 Day" : timeframe.period == '120' ? "10 Day" : timeframe.period == '60' ? "5 Day" : timeframe.period == '30' ? "5 Day" : timeframe.period == '15' ? "5 Day" : timeframe.period == '10' ? "2 Day": timeframe.period == '5' ? "2 Day" : "20 Day"
//////




sig_in  = mode_sig_in == 'Auto' ? auto_sig_in : _sig_in

//-------------------------------Functions & Calculations-------------------------------//
// @TMPascoe found & offered this bandpass by @HPotter found here https://www.tradingview.com/script/A1jhw5fG-Bandpass-Filter/
//      @BarefootJoey turned the code into a function and made it accept float Period
bpf(Series, float Period, Delta) =>
    float tmpbpf = na 
    var beta = math.cos(3.14 * (360 / Period) / 180)
    var gamma = 1 / math.cos(3.14 * (720 * Delta / Period) / 180)
    var alpha = gamma - math.sqrt(gamma * gamma - 1)
    tmpbpf := 0.5 * (1 - alpha) * (Series - Series[2]) + beta * (1 + alpha) * nz(tmpbpf[1]) - alpha * nz(tmpbpf[2])

//// Individual Bandpass Filters
//BPFh = bpf(source, periodBandpassh, bandWidth)
//BPFf = bpf(source, periodBandpassf, bandWidth)
//BPF2 = bpf(source, periodBandpass2, bandWidth)
//BPF4 = bpf(source, periodBandpass4, bandWidth)
//BPF8 = bpf(source, periodBandpass8, bandWidth)
//BPF16 = bpf(source, periodBandpass16, bandWidth)
//BPF32 = bpf(source, periodBandpass32, bandWidth)
//BPF64 = bpf(source, periodBandpass64, bandWidth)
//BPF128 = bpf(source, periodBandpass128, bandWidth)
//BPF256 = bpf(source, periodBandpass256, bandWidth)


mode_multiplier2 = input.string(title='Auto Multiplier?', defval='Auto', options=['Auto', 'Manual'])
Multiplier2 = input(title='Bars in TF Period', defval=1)
instrument_type = syminfo.type
auto_multiplier_stock = timeframe.period == 'M' ? 0.04 : timeframe.period == 'W' ? 0.20 : timeframe.period == 'D' ? 1 : 6.5 / (timeframe.multiplier / 60)
auto_multiplier_stock_extended = timeframe.period == 'M' ? 0.04 : timeframe.period == 'W' ? 0.20 : timeframe.period == 'D' ? 1 : 16 / (timeframe.multiplier / 60) - 1
auto_multiplier_others = timeframe.period == 'M' ? 0.04 : timeframe.period == 'W' ? 0.20 : timeframe.period == 'D' ? 1 : 22 / (timeframe.multiplier / 60)
_auto_multiplier2 = mode_multiplier2 == 'Manual' ? Multiplier2 : (instrument_type != 'futures' or instrument_type != 'forex' or instrument_type != 'crypto') and mode_multiplier2 == 'Auto' and syminfo.session == session.regular ? auto_multiplier_stock : (instrument_type != 'futures' or instrument_type != 'forex' or instrument_type != 'crypto') and mode_multiplier2 == 'Auto' and syminfo.session == session.extended ? auto_multiplier_stock_extended : auto_multiplier_others

// Individual Bandpass Filters
BPF0 = bpf(source, periodBandpass0*_auto_multiplier2, bandWidth)
BPF1 = bpf(source, periodBandpass1*_auto_multiplier2, bandWidth)
BPFh = bpf(source, periodBandpassh*_auto_multiplier2, bandWidth)
BPFf = bpf(source, periodBandpassf*_auto_multiplier2, bandWidth)
BPF2 = bpf(source, periodBandpass2*_auto_multiplier2, bandWidth)
BPF4 = bpf(source, periodBandpass4*_auto_multiplier2, bandWidth)
BPF8 = bpf(source, periodBandpass8*_auto_multiplier2, bandWidth)
BPF16 = bpf(source, periodBandpass16*_auto_multiplier2, bandWidth)
BPF32 = bpf(source, periodBandpass32*_auto_multiplier2, bandWidth)
BPF64 = bpf(source, periodBandpass64*_auto_multiplier2, bandWidth)
BPF128 = bpf(source, periodBandpass128*_auto_multiplier2, bandWidth)
BPF256 = bpf(source, periodBandpass256*_auto_multiplier2, bandWidth)
BPF512 = bpf(source, periodBandpass512*_auto_multiplier2, bandWidth)

BPF0_2 = bpf(source, int(periodBandpass0*_auto_multiplier2/complinediv), bandWidth)
BPF1_2 = bpf(source, int(periodBandpass1*_auto_multiplier2/complinediv), bandWidth)
BPFh_2 = bpf(source, int(periodBandpassh*_auto_multiplier2/complinediv), bandWidth)
BPFf_2 = bpf(source, int(periodBandpassf*_auto_multiplier2/complinediv), bandWidth)
BPF2_2 = bpf(source, int(periodBandpass2*_auto_multiplier2/complinediv), bandWidth)
BPF4_2 = bpf(source, int(periodBandpass4*_auto_multiplier2/complinediv), bandWidth)
BPF8_2 = bpf(source, int(periodBandpass8*_auto_multiplier2/complinediv), bandWidth)
BPF16_2 = bpf(source, int(periodBandpass16*_auto_multiplier2/complinediv), bandWidth)
BPF32_2 = bpf(source, int(periodBandpass32*_auto_multiplier2/complinediv), bandWidth)
BPF64_2 = bpf(source, int(periodBandpass64*_auto_multiplier2/complinediv), bandWidth)
BPF128_2 = bpf(source, int(periodBandpass128*_auto_multiplier2/complinediv), bandWidth)
BPF256_2 = bpf(source, int(periodBandpass256*_auto_multiplier2/complinediv), bandWidth)
BPF512_2 = bpf(source, int(periodBandpass512*_auto_multiplier2/complinediv), bandWidth)

_comp_sel_BPF0 = timeframe.period == 'M' ? 0 : timeframe.period == 'W' ? 0 : timeframe.period == 'D' ? 0 : timeframe.period == '240' ? 0 : timeframe.period == '120' ? 0 : timeframe.period == '60' ? 0 : timeframe.period == '30' ? 0 : timeframe.period == '15' ? 0 : timeframe.period == '10' ? 0 : timeframe.period == '5' ? 1 : 0
_comp_sel_BPF1 = timeframe.period == 'M' ? 0 : timeframe.period == 'W' ? 0 : timeframe.period == 'D' ? 0 : timeframe.period == '240' ? 0 : timeframe.period == '120' ? 0 : timeframe.period == '60' ? 0 : timeframe.period == '30' ? 1 : timeframe.period == '15' ? 1: timeframe.period == '10' ? 1 : timeframe.period == '5' ? 1 : 0
_comp_sel_BPFh = timeframe.period == 'M' ? 0 : timeframe.period == 'W' ? 0 : timeframe.period == 'D' ? 0 : timeframe.period == '240' ? 0 : timeframe.period == '120' ? 1 : timeframe.period == '60' ? 1 : timeframe.period == '30' ? 1 : timeframe.period == '15' ? 1 : timeframe.period == '10' ? 1 : timeframe.period == '5' ? 1 : 0
_comp_sel_BPFf = timeframe.period == 'M' ? 0 : timeframe.period == 'W' ? 0 : timeframe.period == 'D' ? 0 : timeframe.period == '240' ? 1 : timeframe.period == '120' ? 1 : timeframe.period == '60' ? 1 : timeframe.period == '30' ? 1 : timeframe.period == '15' ? 1 : timeframe.period == '10' ? 1 : timeframe.period == '5' ? 1 : 0
_comp_sel_BPF2 = timeframe.period == 'M' ? 0 : timeframe.period == 'W' ? 0 : timeframe.period == 'D' ? 1 : timeframe.period == '240' ? 1 : timeframe.period == '120' ? 1 : timeframe.period == '60' ? 1 : timeframe.period == '30' ? 1 : timeframe.period == '15' ? 1 : timeframe.period == '10' ? 1 : timeframe.period == '5' ? 0 : 0
_comp_sel_BPF4 = timeframe.period == 'M' ? 1 : timeframe.period == 'W' ? 1 : timeframe.period == 'D' ? 1 : timeframe.period == '240' ? 1 : timeframe.period == '120' ? 1 : timeframe.period == '60' ? 1 : timeframe.period == '30' ? 0 : timeframe.period == '15' ? 0 : timeframe.period == '10' ? 0 : timeframe.period == '5' ? 0 : 0
_comp_sel_BPF8 = timeframe.period == 'M' ? 1 : timeframe.period == 'W' ? 1 : timeframe.period == 'D' ? 1 : timeframe.period == '240' ? 1 : timeframe.period == '120' ? 0 : timeframe.period == '60' ? 0 : timeframe.period == '30' ? 0 : timeframe.period == '15' ? 0 : timeframe.period == '10' ? 0 : timeframe.period == '5' ? 0 : 0
_comp_sel_BPF16 = timeframe.period == 'M' ? 1 : timeframe.period == 'W' ? 1 : timeframe.period == 'D' ? 1 : timeframe.period == '240' ? 0 : timeframe.period == '120' ? 0 : timeframe.period == '60' ? 0 : timeframe.period == '30' ? 0 : timeframe.period == '15' ? 0 : timeframe.period == '10' ? 0 : timeframe.period == '5' ? 0 : 0
_comp_sel_BPF32 = timeframe.period == 'M' ? 1 : timeframe.period == 'W' ? 1 : timeframe.period == 'D' ? 0 : timeframe.period == '240' ? 0 : timeframe.period == '120' ? 0 : timeframe.period == '60' ? 0 : timeframe.period == '30' ? 0 : timeframe.period == '15' ? 0 : timeframe.period == '10' ? 0 : timeframe.period == '5' ? 0 : 0
_comp_sel_BPF64 = timeframe.period == 'M' ? 0 : timeframe.period == 'W' ? 0 : timeframe.period == 'D' ? 0 : timeframe.period == '240' ? 0 : timeframe.period == '120' ? 0 : timeframe.period == '60' ? 0 : timeframe.period == '30' ? 0 : timeframe.period == '15' ? 0 : timeframe.period == '10' ? 0 : timeframe.period == '5' ? 0 : 0
_comp_sel_BPF128 = timeframe.period == 'M' ? 0 : timeframe.period == 'W' ? 0 : timeframe.period == 'D' ? 0 : timeframe.period == '240' ? 0 : timeframe.period == '120' ? 0 : timeframe.period == '60' ? 0 : timeframe.period == '30' ? 0 : timeframe.period == '15' ? 0 : timeframe.period == '10' ? 0 : timeframe.period == '5' ? 0 : 0
_comp_sel_BPF256 = timeframe.period == 'M' ? 0 : timeframe.period == 'W' ? 0 : timeframe.period == 'D' ? 0 : timeframe.period == '240' ? 0 : timeframe.period == '120' ? 0 : timeframe.period == '60' ? 0 : timeframe.period == '30' ? 0 : timeframe.period == '15' ? 0 : timeframe.period == '10' ? 0 : timeframe.period == '5' ? 0 : 0
_comp_sel_BPF512 = timeframe.period == 'M' ? 0 : timeframe.period == 'W' ? 0 : timeframe.period == 'D' ? 0 : timeframe.period == '240' ? 0 : timeframe.period == '120' ? 0 : timeframe.period == '60' ? 0 : timeframe.period == '30' ? 0 : timeframe.period == '15' ? 0 : timeframe.period == '10' ? 0 : timeframe.period == '5' ? 0 : 0

scomp0  = (mode_comp_sel == 'Auto' and _comp_sel_BPF0) ? 1 : mode_comp_sel == 'Manual' ? comp0 : 0
scomp1  = (mode_comp_sel == 'Auto' and _comp_sel_BPF1) ? 1 : mode_comp_sel == 'Manual' ? comp1: 0
scomph  = (mode_comp_sel == 'Auto' and _comp_sel_BPFh) ? 1 : mode_comp_sel == 'Manual' ? comph : 0
scompf  = (mode_comp_sel == 'Auto' and _comp_sel_BPFf) ? 1 : mode_comp_sel == 'Manual' ? compf : 0
scomp2  = (mode_comp_sel == 'Auto' and _comp_sel_BPF2) ? 1 : mode_comp_sel == 'Manual' ? comp2 : 0
scomp4  = (mode_comp_sel == 'Auto' and _comp_sel_BPF4) ? 1 : mode_comp_sel == 'Manual' ? comp4 : 0
scomp8  = (mode_comp_sel == 'Auto' and _comp_sel_BPF8) ? 1 : mode_comp_sel == 'Manual' ? comp8 : 0
scomp16  = (mode_comp_sel == 'Auto' and _comp_sel_BPF16) ? 1 : mode_comp_sel == 'Manual' ? comp16 : 0
scomp32  = (mode_comp_sel == 'Auto' and _comp_sel_BPF32) ? 1 : mode_comp_sel == 'Manual' ? comp32 : 0
scomp64  = (mode_comp_sel == 'Auto' and _comp_sel_BPF64) ? 1 : mode_comp_sel == 'Manual' ? comp64 : 0
scomp128  = (mode_comp_sel == 'Auto' and _comp_sel_BPF128) ? 1 : mode_comp_sel == 'Manual' ? comp128 : 0
scomp256  = (mode_comp_sel == 'Auto' and _comp_sel_BPF256) ? 1 : mode_comp_sel == 'Manual' ? comp256 : 0
scomp512  = (mode_comp_sel == 'Auto' and _comp_sel_BPF512) ? 1 : mode_comp_sel == 'Manual' ? comp512 : 0

comp_t = 0.0
comp_n = 0

if scomp0
    comp_t := comp_t + periodBandpass0*_auto_multiplier2
    comp_n := comp_n + 1

if scomp1
    comp_t := comp_t + periodBandpass1*_auto_multiplier2
    comp_n := comp_n + 1

if scomph
    comp_t := comp_t + periodBandpassh*_auto_multiplier2
    comp_n := comp_n + 1

if scompf
    comp_t := comp_t + periodBandpassf*_auto_multiplier2
    comp_n := comp_n + 1

if scomp2
    comp_t := comp_t + periodBandpass2*_auto_multiplier2
    comp_n := comp_n + 1

if scomp4
    comp_t := comp_t + periodBandpass4*_auto_multiplier2
    comp_n := comp_n + 1

if scomp8
    comp_t := comp_t + periodBandpass8*_auto_multiplier2
    comp_n := comp_n + 1

if scomp16
    comp_t := comp_t + periodBandpass16*_auto_multiplier2
    comp_n := comp_n + 1

if scomp32
    comp_t := comp_t + periodBandpass32*_auto_multiplier2
    comp_n := comp_n + 1

if scomp64
    comp_t := comp_t + periodBandpass64*_auto_multiplier2
    comp_n := comp_n + 1

if scomp128
    comp_t := comp_t + periodBandpass128*_auto_multiplier2
    comp_n := comp_n + 1

if scomp256
    comp_t := comp_t + periodBandpass256*_auto_multiplier2
    comp_n := comp_n + 1

if scomp512
    comp_t := comp_t + periodBandpass512*_auto_multiplier2
    comp_n := comp_n + 1

offset_composite = int(ocomps * comp_t /comp_n)

// Composite Line
//compBPF = (scomp0?BPF0:0) + (scomp1?BPF1:0) + (scomph?BPFh:0) + (scompf?BPFf:0) + (scomp2?BPF2:0) + (scomp4?BPF4:0) + (scomp8?BPF8:0) + (scomp16?BPF16:0) + (scomp32?BPF32:0) + (scomp64?BPF64:0) + (scomp128?BPF128:0) + (scomp256?BPF256:0) + (scomp512?BPF512:0)
compBPF = (scomp0?BPF0_2:0) + (scomp1?BPF1_2:0) + (scomph?BPFh_2:0) + (scompf?BPFf_2:0) + (scomp2?BPF2_2:0) + (scomp4?BPF4_2:0) + (scomp8?BPF8_2:0) + (scomp16?BPF16_2:0) + (scomp32?BPF32_2:0) + (scomp64?BPF64_2:0) + (scomp128?BPF128_2:0) + (scomp256?BPF256_2:0) + (scomp512?BPF512_2:0)

col = ta.change(compBPF) > 0 ? colcompu : colcompd


//Composite Cycle
BPFcomp2= bpf(source, int(comp_t/comp_n)/compcyclediv, bandWidth)
//plot(offset_composite, title="Offset Composite")

// Cycle Analysis
// Truncate Decimals
truncate(number, pricedecimals) =>
    factor = math.pow(10, pricedecimals)
    int(number * factor) / factor

// Switch output/plot for analytics
sig_out = sig_in == "1 Day" ? BPF0 :sig_in == "2 Day" ? BPF1 : sig_in == "5 Day" ? BPFh : sig_in == "10 Day" ? BPFf : sig_in == "20 Day" ? BPF2 : sig_in == "40 Day" ? BPF4 : sig_in == "80 Day" ? BPF8 : sig_in == "20 Week" ? BPF16 : sig_in == "40 Week" ? BPF32 : sig_in == "18 Month" ? BPF64 : sig_in == "54 Month" ? BPF128 : sig_in == "9 Year" ? BPF256 : sig_in == "18 Year" ? BPF512 : na

period_out = sig_in == "1 Day" ? periodBandpass0 : sig_in == "2 Day" ? periodBandpass1 : sig_in == "5 Day" ? periodBandpassh : sig_in == "10 Day" ? periodBandpassf : sig_in == "20 Day" ? periodBandpass2 : sig_in == "40 Day" ? periodBandpass4 : sig_in == "80 Day" ? periodBandpass8 : sig_in == "20 Week" ? periodBandpass16 : sig_in == "40 Week" ? periodBandpass32 : sig_in == "18 Month" ? periodBandpass64 : sig_in == "54 Month" ? periodBandpass128 : sig_in == "9 Year" ? periodBandpass256 : sig_in == "18 Year" ? periodBandpass512 : 1 // :na 

col_out = sig_in == "1 Day" ? col0 : sig_in == "1 Day" ? col1 : sig_in == "5 Day" ? colh : sig_in == "10 Day" ? colf : sig_in == "20 Day" ? col2 : sig_in == "40 Day" ? col4 : sig_in == "80 Day" ? col8 : sig_in == "20 Week" ? col16 : sig_in == "40 Week" ? col32 : sig_in == "18 Month" ? col64 : sig_in == "54 Month" ? col128 : sig_in == "9 Year" ? col256 : sig_in == "18 Year" ? col512 : color.gray

// Highs/Lows
hi = sig_out[2]<sig_out[1] and sig_out[1]>sig_out
lo = sig_out[2]>sig_out[1] and sig_out[1]<sig_out

// Define Crosses
midcross = ta.cross(sig_out, 0)
midcrossbars = ta.barssince(midcross)
midcrossbars2 = ta.barssince(midcross)[1]
last_wavelength = ta.barssince(midcross) - ta.barssince(midcross)

// Bars Since Last Amp Hi & Lo
xhi = ta.barssince(hi)
xlo = ta.barssince(lo)

// Wavelength   
wavelength = math.round(math.abs(xhi-xlo)*2)

// Last Amp Hi & Lo
bpfphi = ta.highest(sig_out,math.round(period_out))
bpfamphi = ta.valuewhen(bpfphi, sig_out, 0)
bpfplo = ta.lowest(sig_out,math.round(period_out))
bpfamplo = ta.valuewhen(bpfplo, sig_out, 0)
tot_amp = bpfphi - bpfplo

// Estimates/Forecasts
next_peak = -math.abs(xhi-wavelength)
next_trough = -math.abs(xlo-wavelength)
next_node = math.abs(xhi-xlo)-midcrossbars

// Highlight background of next peak/node/trough
next_peak_col = color.new(color.red,hi?75:100)
next_node_col = color.new(color.gray, midcross?75:100)
next_trough_col = color.new(color.green, lo?75:100)

// Sentiment 
amp_sent = bpfphi>math.abs(bpfplo)?"🟢":bpfphi<math.abs(bpfplo)?"🔴":"⚪"
bbwavelen = wavelength>period_out?"🟢":wavelength<period_out?"🔴":"⚪"
bbpt = -next_peak<-next_trough?"Bullish🟢":-next_peak>-next_trough?"Bearish🔴":"Neutral⚪"

// Analytics Tooltip 📏🧮⏳🎰🤖🎭🔮📈📉🔁🌊🔴🟢⚪
labeltt= "🔄 Cycle: " + str.tostring(sig_in) + "/" + str.tostring(period_out) + " bars" +
 "\n📏 Period (⊺): ~" + str.tostring(math.abs(xhi-xlo)) + " bars" +
 "\n🌊 Wavelength (λ): ~" + str.tostring(wavelength) + " bars " + bbwavelen +
 "\n⚖ Delta (∆) Amplitude (ª): " + str.tostring(truncate(tot_amp, decimals)) + " " + amp_sent +
 "\n📈 Peak (ª): " + str.tostring(truncate(bpfphi, decimals)) + ", " + str.tostring(xhi) + " bars ago" + 
 "\n🔀 Node: " + str.tostring(midcrossbars) + " bars ago" +
 "\n📉 Trough (ª): " + str.tostring(truncate(bpfplo, decimals)) + ", " + str.tostring(xlo) + " bars ago" + 
 "\n\n🔮 Estimates: " + bbpt +
 "\n📈 Next Peak: " + str.tostring(-next_peak) + "ish bars " +
 "\n🔀 Next Node: " + str.tostring(next_node) + "ish bars" + 
 "\n📉 Next Trough: " + str.tostring(-next_trough) + "ish bars " 

labeltt2= "🔄 Cycle: " + str.tostring(sig_in) + "/" + str.tostring(period_out) + " bars" +
 "\n📏 Period (⊺): ~" + str.tostring(math.abs(xhi-xlo)) + " bars" +
 "\n🌊 Wavelength (λ): ~" + str.tostring(wavelength) + " bars " + bbwavelen +
 "\n\n🔮 Estimates: " + bbpt +
 "\n📈 Next Peak: " + str.tostring(-next_peak) + "ish bars " +
 "\n🔀 Next Node: " + str.tostring(next_node) + "ish bars" + 
 "\n📉 Next Trough: " + str.tostring(-next_trough) + "ish bars " 


// ------------------------------- Plots, Displays, Outputs -------------------------------//
plot(0, "Midline", color.new(color.gray,30), style=plot.style_histogram, display=display.none)
//plot(BPFh, '5 Day', color=color.new(colh, 0), linewidth=sig_in == "5 Day" ? 3 : 1, display=display.none)
//plot(BPFf, '10 Day', color=color.new(colf, 0), linewidth=sig_in == "10 Day" ? 3 : 1, display=display.none)
//plot(BPF2, '20 Day', color=color.new(col2, 0), linewidth=sig_in == "20 Day" ? 3 : 1, display=display.all)
//plot(BPF4, '40 Day', color=color.new(col4, 0), linewidth=sig_in == "40 Day" ? 3 : 1, display=display.none)
//plot(BPF8, '80 Day', color=color.new(col8, 0), linewidth=sig_in == "80 Day" ? 3 : 1, display=display.none)
//plot(BPF16, '20 Week', color=color.new(col16, 0), linewidth=sig_in == "20 Week" ? 3 : 1, display=display.none)
//plot(BPF32, '40 Week', color=color.new(col32, 0), linewidth=sig_in == "40 Week" ? 3 : 1, display=display.none)
//plot(BPF64, '18 Month', color=color.new(col64, 0), linewidth=sig_in == "18 Month" ? 3 : 1, display=display.none)
//plot(BPF128, '54 Month', color=color.new(col128, 0), linewidth=sig_in == "54 Month" ? 3 : 1, display=display.none)
//plot(BPF256, '9 Year', color=color.new(col256, 0), linewidth=sig_in == "9 Year" ? 3 : 1, display=display.none)
//plot(BPF512, '18 Year', color=color.new(col512, 0), linewidth=sig_in == "18 Year" ? 3 : 1, display=display.none)

_display_BPF0 = timeframe.period == 'M' ? 0 : timeframe.period == 'W' ? 0 : timeframe.period == 'D' ? 0 : timeframe.period == '240' ? 0 : timeframe.period == '120' ? 0 : timeframe.period == '60' ? 0 : timeframe.period == '30' ? 0 : timeframe.period == '15' ? 0 : timeframe.period == '10' ? 1 : timeframe.period == '5' ? 1 : 0
_display_BPF1 = timeframe.period == 'M' ? 0 : timeframe.period == 'W' ? 0 : timeframe.period == 'D' ? 0 : timeframe.period == '240' ? 0 : timeframe.period == '120' ? 0 : timeframe.period == '60' ? 0 : timeframe.period == '30' ? 1 : timeframe.period == '15' ? 1 : timeframe.period == '10' ? 1 : timeframe.period == '5' ? 1 : 0
_display_BPFh = timeframe.period == 'M' ? 0 : timeframe.period == 'W' ? 0 : timeframe.period == 'D' ? 0 : timeframe.period == '240' ? 0 : timeframe.period == '120' ? 1 : timeframe.period == '60' ? 1 : timeframe.period == '30' ? 1 : timeframe.period == '15' ? 1 : timeframe.period == '10' ? 1 : timeframe.period == '5' ? 1 : 0
_display_BPFf = timeframe.period == 'M' ? 0 : timeframe.period == 'W' ? 0 : timeframe.period == 'D' ? 0 : timeframe.period == '240' ? 1 : timeframe.period == '120' ? 1 : timeframe.period == '60' ? 1 : timeframe.period == '30' ? 1 : timeframe.period == '15' ? 1 : timeframe.period == '10' ? 0 : timeframe.period == '5' ? 0 : 0
_display_BPF2 = timeframe.period == 'M' ? 0 : timeframe.period == 'W' ? 0 : timeframe.period == 'D' ? 1 : timeframe.period == '240' ? 1 : timeframe.period == '120' ? 1 : timeframe.period == '60' ? 1 : timeframe.period == '30' ? 0 : timeframe.period == '15' ? 0 : timeframe.period == '10' ? 0 : timeframe.period == '5' ? 0 : 0
_display_BPF4 = timeframe.period == 'M' ? 0 : timeframe.period == 'W' ? 1 : timeframe.period == 'D' ? 1 : timeframe.period == '240' ? 1 : timeframe.period == '120' ? 0 : timeframe.period == '60' ? 0 : timeframe.period == '30' ? 0 : timeframe.period == '15' ? 0 : timeframe.period == '10' ? 0 : timeframe.period == '5' ? 0 : 0
_display_BPF8 = timeframe.period == 'M' ? 1 : timeframe.period == 'W' ? 1 : timeframe.period == 'D' ? 1 : timeframe.period == '240' ? 0 : timeframe.period == '120' ? 0 : timeframe.period == '60' ? 0 : timeframe.period == '30' ? 0 : timeframe.period == '15' ? 0 : timeframe.period == '10' ? 0 : timeframe.period == '5' ? 0 : 0
_display_BPF16 = timeframe.period == 'M' ? 1 : timeframe.period == 'W' ? 1 : timeframe.period == 'D' ? 0 : timeframe.period == '240' ? 0 : timeframe.period == '120' ? 0 : timeframe.period == '60' ? 0 : timeframe.period == '30' ? 0 : timeframe.period == '15' ? 0 : timeframe.period == '10' ? 0 : timeframe.period == '5' ? 0 : 0
_display_BPF32 = timeframe.period == 'M' ? 1 : timeframe.period == 'W' ? 0 : timeframe.period == 'D' ? 0 : timeframe.period == '240' ? 0 : timeframe.period == '120' ? 0 : timeframe.period == '60' ? 0 : timeframe.period == '30' ? 0 : timeframe.period == '15' ? 0 : timeframe.period == '10' ? 0 : timeframe.period == '5' ? 0 : 0
_display_BPF64 = timeframe.period == 'M' ? 0 : timeframe.period == 'W' ? 0 : timeframe.period == 'D' ? 0 : timeframe.period == '240' ? 0 : timeframe.period == '120' ? 0 : timeframe.period == '60' ? 0 : timeframe.period == '30' ? 0 : timeframe.period == '15' ? 0 : timeframe.period == '10' ? 0 : timeframe.period == '5' ? 0 : 0
_display_BPF128 = timeframe.period == 'M' ? 0 : timeframe.period == 'W' ? 0 : timeframe.period == 'D' ? 0 : timeframe.period == '240' ? 0 : timeframe.period == '120' ? 0 : timeframe.period == '60' ? 0 : timeframe.period == '30' ? 0 : timeframe.period == '15' ? 0 : timeframe.period == '10' ? 0 : timeframe.period == '5' ? 0 : 0
_display_BPF256 = timeframe.period == 'M' ? 0 : timeframe.period == 'W' ? 0 : timeframe.period == 'D' ? 0 : timeframe.period == '240' ? 0 : timeframe.period == '120' ? 0 : timeframe.period == '60' ? 0 : timeframe.period == '30' ? 0 : timeframe.period == '15' ? 0 : timeframe.period == '10' ? 0 : timeframe.period == '5' ? 0 : 0
_display_BPF512 = timeframe.period == 'M' ? 0 : timeframe.period == 'W' ? 0 : timeframe.period == 'D' ? 0 : timeframe.period == '240' ? 0 : timeframe.period == '120' ? 0 : timeframe.period == '60' ? 0 : timeframe.period == '30' ? 0 : timeframe.period == '15' ? 0 : timeframe.period == '10' ? 0 : timeframe.period == '5' ? 0 : 0


display_BPF0 = mode_sel == 'Auto' ? _display_BPF0 : dcomp0
display_BPF1 = mode_sel == 'Auto' ? _display_BPF1 : dcomp1
display_BPFh = mode_sel == 'Auto' ? _display_BPFh : dcomph
display_BPFf = mode_sel == 'Auto' ? _display_BPFf : dcompf
display_BPF2 = mode_sel == 'Auto' ? _display_BPF2 : dcomp2
display_BPF4 = mode_sel == 'Auto' ? _display_BPF4 : dcomp4
display_BPF8 = mode_sel == 'Auto' ? _display_BPF8 : dcomp8
display_BPF16 = mode_sel == 'Auto' ? _display_BPF16 : dcomp16
display_BPF32 = mode_sel == 'Auto' ? _display_BPF32 : dcomp32
display_BPF64 = mode_sel == 'Auto' ? _display_BPF64 : dcomp64
display_BPF128 = mode_sel == 'Auto' ? _display_BPF128 : dcomp128
display_BPF256 = mode_sel == 'Auto' ? _display_BPF256 : dcomp256
display_BPF512 = mode_sel == 'Auto' ? _display_BPF512 : dcomp512

plot(display_BPF0 ? BPF0 : na, '1 Day', color=color.new(col0, 0), linewidth=1, offset=ocomp0*int(periodBandpassh/cyclediv0), display=display.all)
plot(display_BPF1 ? BPF1: na, '2 Day', color=color.new(col1, 0), linewidth=1, offset=ocomp1*int(periodBandpassf/cyclediv1), display=display.all)
plot(display_BPFh ? BPFh : na, '5 Day', color=color.new(colh, 0), linewidth=1, offset=ocomph*int(periodBandpassh/cycledivh), display=display.all)
plot(display_BPFf ? BPFf: na, '10 Day', color=color.new(colf, 0), linewidth=2, offset=ocompf*int(periodBandpassf/cycledivf), display=display.all)
plot(display_BPF2  ? BPF2: na, '20 Day', color=color.new(col2, 0), linewidth=2, offset=ocomp2*int(periodBandpass2/cyclediv2), display=display.all)
plot(display_BPF4  ? BPF4: na, '40 Day', color=color.new(col4, 0), linewidth=2, offset=ocomp4*int(periodBandpass4/cyclediv4), display=display.all)
plot(display_BPF8  ? BPF8: na, '80 Day', color=color.new(col8, 0), linewidth=2, offset=ocomp8*int(periodBandpass8/cyclediv8), display=display.all)
plot(display_BPF16 ? BPF16: na, '20 Week', color=color.new(col16, 0), linewidth=3, offset=ocomp16*int(periodBandpass16/cyclediv16), display=display.all)
plot(display_BPF32  ? BPF32: na, '40 Week', color=color.new(col32, 0), linewidth=3, offset=ocomp32*int(periodBandpass32/cyclediv32), display=display.all)
plot(display_BPF64  ? BPF64: na, '18 Month', color=color.new(col64, 0), linewidth=3, offset=ocomp64*int(periodBandpass64/cyclediv64), display=display.all)
plot(display_BPF128  ? BPF128: na, '54 Month', color=color.new(col128, 0), linewidth=4, offset=ocomp128*int(periodBandpass128/cyclediv128), display=display.all)
plot(display_BPF256  ? BPF256: na, '9 Year', color=color.new(col256, 0), linewidth=4, offset=ocomp256*int(periodBandpass256/cyclediv256), display=display.all)
plot(display_BPF512  ? BPF512: na, '18 Year', color=color.new(col512, 0), linewidth=4, offset=ocomp512*int(periodBandpass512/cyclediv512), display=display.all)

//plot (compBPF, linewidth=2, title="Composite Line", color=color.new(color.silver, 40), style=plot.style_steplinebr, offset=offset_composite)

//plot (compdisplay ? compBPF : na,linewidth=2, title="Composite Line", color=color.new(color.silver, 40), style=plot.style_circles, offset=offset_composite)

// get highs, lows and timestamps from D1 and W1 timeframes
day_start = request.security(syminfo.tickerid, 'D', time, lookahead=barmerge.lookahead_on)
day_high = request.security(syminfo.tickerid, 'D', high, lookahead=barmerge.lookahead_on)
day_low = request.security(syminfo.tickerid, 'D', low, lookahead=barmerge.lookahead_on)
week_start = request.security(syminfo.tickerid, 'W', time, lookahead=barmerge.lookahead_on)
week_high = request.security(syminfo.tickerid, 'W', high, lookahead=barmerge.lookahead_on)
week_low = request.security(syminfo.tickerid, 'W', low, lookahead=barmerge.lookahead_on)

var second_ms = 1000
var minute_ms = second_ms * 60
var hour_ms = minute_ms * 60
var day_ms = hour_ms * 24
var week_ms = day_ms * 7

get_ms_from_today_start() =>
    hour_ms * hour(timenow) + minute_ms * minute(timenow) + second_ms * second(timenow)
get_ms_from_week_start() =>
    day_ms * (dayofweek(timenow) == dayofweek.sunday ? 6 : dayofweek(timenow) - 2) + get_ms_from_today_start()

// calculate ranges in ms for time calculations
from_day_start_to_now_range = get_ms_from_today_start()
from_week_start_to_now_range = get_ms_from_week_start()  // dayofweek returns 1 for sunday and 2 for monday
from_candle_to_now_range = timenow - time

//limit_left = from_candle_to_now_range < day_ms * (int(ocomps*comp_t/comp_n) * nhist) + from_day_start_to_now_range + second_ms

////plot (limit_left ? compdisplay ? compBPF : na : na,linewidth=1, title="Composite Line", color=color.new(color.silver, 30), style=plot.style_circles, offset=int(ocomps*comp_t/comp_n))
//plot (limit_left ? compdisplay ? compBPF : na : na,linewidth=1, title="Composite Line", color=color.new(color.silver, 30), style=plot.style_linebr, offset=int(ocomps*comp_t/comp_n))

plot (compdisplay ? compBPF : na ,linewidth=1, title="Composite Line", color=color.new(color.silver, 30), style=plot.style_circles, offset=int(ocomps*comp_t/comp_n))
plot (compdisplay ? compBPF : na ,linewidth=1, title="Composite Line", color=color.new(color.silver, 30), style=plot.style_linebr, offset=int(ocomps*comp_t/comp_n))


plot (compcycle ? BPFcomp2 : na ,linewidth=1, title="Composite Cycle", color=color.new(color.gray, 40), style=plot.style_cross, offset=int(ocomps2*comp_t/comp_n))
plot (compcycle ? BPFcomp2 : na ,linewidth=1, title="Composite Cycle", color=color.new(color.gray, 40), style=plot.style_linebr, offset=int(ocomps2*comp_t/comp_n))

plotcandle(compBPF[1], ta.lowest(compBPF,1), math.min(compBPF,compBPF[1]), compBPF, color=col, wickcolor=color.new(col,100), bordercolor=col, title='Composite Candles', display=display.none)

bgcolor(color=next_peak_col, title="Peak Estimate", offset=wavelength)
bgcolor(color=next_node_col, title="Node Estimate", offset=wavelength)
bgcolor(color=next_trough_col, title="Trough Estimate", offset=wavelength)

plotshape(hi, "Actual Peak", shape.triangledown, location.top, color.rgb(236, 174, 92, 18), size=size.tiny, display=display.all) 
plotshape(lo, "Actual Trough", shape.triangleup, location.bottom, color.rgb(69, 225, 220, 14), size=size.tiny, display=display.all) 

var table Ticker = na
table.delete(Ticker)
Ticker := table.new(position, 1, 1)
if barstate.islast
    table.cell(Ticker, 0, 0, 
      text = "🔄 Cycle Analysis", 
      text_size = size, 
      text_color = color.new(col_out,0),
      tooltip = sig_in!="None"?labeltt:"No Bandpass selected. Double click to open & change Settings.")


var srtable = table.new(position = tableposy + '_' + tableposx, columns = 5, rows= 11, frame_width = 0, frame_color = color.gray, border_width = 1, border_color = color.gray)
if showtable
    table.cell(srtable, 0, 0, text = labeltt2, text_color = color.white, bgcolor = color.new(color.gray,100), text_size = size.tiny)
    table.merge_cells(srtable, 0, 0, 3, 0)

Overview

Hurst Spectral Analysis Oscillator V2 passes the hl2 price through bandpass filters for cycles from 1 day upward and draws the cycle waves with a composite line. A single bandwidth value applies to all filters, and auto or manual modes control cycle selection, composite multiplier offsets and cycle offsets. The code uses higher-timeframe data with lookahead, so history may look cleaner than live bars.

Details

Published by

mikeyhu70 on GitHub

Type

Indicator, Pine Script v5

Draws

Separate pane below the chart

Category

Oscillators & momentum

Markets

Any symbol

Timeframes

Any timeframe

Risk Notes

  • Reads higher-timeframe data with lookahead on, so the history can show signals that were not there in real time

Settings

The inputs you can change from the gear icon on the chart. Defaults are the author's.

SettingTypeDefaultVariable
Sourcesourcehl2source
Bandwidthfloat0.000005bandWidth
Cycle Selection Mode ?stringAutomode_sel
Composite Line Multiplier Offset Mode ?stringAutomode_comp
Composite Selection Mode ?stringAutomode_comp_sel
Composite Cycle Multiplier Offset Mode ?stringAutomode_comp2
Cycle Offset Mode ?stringAutomode_offset
1 Day float1.1periodBandpass0
2 Day float2.2periodBandpass1
5 Day float4.3periodBandpassh
10 Day float8.5periodBandpassf
20 Day float17periodBandpass2
Show all 40 settings
SettingTypeDefaultVariable
40 Day float34.1periodBandpass4
80 Day float68.2periodBandpass8
20 Week float136.4periodBandpass16
40 Week float272.8periodBandpass32
18 Monthfloat545.6periodBandpass64
54 Monthfloat1636.8periodBandpass128
9 Year float3273.6periodBandpass256
18 Year float6547.2periodBandpass512
colorfld1col0
colorfld2col1
colorfld5colh
colorfld10colf
colorfld20col2
colorfld40col4
colorfld80col8
colorfld20wcol16
colorfld40wcol32
colorfld18mcol64
colorfld54mcol128
colorfld9ycol256
colorfld18ycol512
Composite Model Candle Colorscolorcolor.new(#00ff0a, 70)colcompu
colorcolor.new(#ff0000, 70)colcompd
Compositeboolfalsecomp0
Compositeboolfalsecomp1
Compositebooltruecomph
Compositebooltruecompf
Compositebooltruecomp2
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

Asymmetrical RSI

by everget
948 stars

Asymmetrical RSI is an indicator that computes a custom relative strength index from the rate of change of a user-selected source. It plots the resulting ARSI line in a separate pane with color coding that turns green above the overbought level and red below t

Indicator v4 Oscillators & momentum
Updated 11 days ago · GPL-3.0 GitHub repository of Asymmetrical RSI

This indicator calculates momentum setups based on the Relative Strength Index (RSI) and plots in a separate pane. It offers multiple scanning modes such as Continuous Break, Continuous Retracement, Flip Break, Flip Retracement, and both regular and hidden div

Indicator v6 Oscillators & momentumDivergence Repaints
Updated 1 year ago · MPL-2.0 GitHub repository of Momentum Setup - RSI Directional Momentum Indicator

Beep Boop

by magic8bot
409 stars

This indicator calculates a modified MACD oscillator and signal line alongside a trend EMA filter, plotting the output as a stylized column histogram in a separate pane. Instead of plotting true MACD distance, it quantifies positive and negative histogram mome

Indicator v4 Oscillators & momentumTrend
Updated 3 years ago · MIT GitHub repository of Beep Boop
261 stars

This indicator demonstrates an experimental graph-style scatter visualization within a separate pane using Pine Script arrays. It tracks two features across recent bars: the single-bar price change and a scaled 14-period Relative Strength Index. Values are loa

Indicator v4 Oscillators & momentum
Updated 4 years ago · None stated GitHub repository of Example: Graph Style - 4th Dimension RSI

KD指標

by TaichiS
219 stars

This script calculates and plots a Stochastic Oscillator (KD indicator) in a separate chart pane. It determines the fast stochastic value over a 9-period lookback, then applies a 3-period Simple Moving Average (SMA) to create the %K line, and a second 3-period

Indicator v4 Oscillators & momentum
Updated 5 years ago · None stated GitHub repository of KD指標

More indicators

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers