Market Time Cycle (Expo)
// This work is licensed under a Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0) https://creativecommons.org/licenses/by-nc-sa/4.0/
// © Zeiierman

//@version=5
indicator("Market Time Cycle (Expo)",max_lines_count=500, precision=0)
//~~~~~~~~~~~~~~~~~~~~~~~}
// Inputs {
marketcycle    = input.bool(true, title="Market Cycle", group="Market Cycle",inline="Market Cycle",tooltip="")
NumbOfBars     = input.float(200.0,minval=1,title="",step=10, group="Market Cycle",inline="Market Cycle",tooltip="Set the Nbr bars for the Market Cycle.")/2 
overlap        = input.bool(false,title="Overlap Cycles", group="Market Cycle",inline="c",tooltip="")
bg             = input.bool(true, title="Cycle divider", group="Market Cycle",inline="c",tooltip="The overlap variable lets traders choose whether they want overlapping cycles or not. If the overlap option is selected, the next cycle starts right after the previous one, otherwise, it starts after the period equal to the Market Cycle Period")
sine           = input.bool(true, title="Sine Wave Cycle", group="Sine Wave Cycle",inline="Sine Wave Cycle",tooltip="")
sineWavePeriod = input.int(20, minval=1,title="", group="Sine Wave Cycle",inline="Sine Wave Cycle",tooltip="Set the sine wave period.")
//~~~~~~~~~~~~~~~~~~~~~~~}

// Initialize Variables {
b   = bar_index
Dec = (NumbOfBars-0.0)/NumbOfBars
//~~~~~~~~~~~~~~~~~~~~~~~}

// Code {
// Compute cycle period and counter
var c = 0 
c := c+1 
var a1 = NumbOfBars 
a1 := a1 - Dec

// If period is out of bounds, reset cycle period and counter
if a1+(overlap?0:NumbOfBars)<=0.0 
    a1 := NumbOfBars
    c := 0 

cycle() =>
    if c == 0 
        float prev_y = na
        int prev_x = na
        var float max_height = na
        var int max_height_index = na
        for j = -90 to 90 by 10
            x = (NumbOfBars) * math.sin(math.toradians(j)) 
            y = (NumbOfBars) * math.cos(math.toradians(j)) 
            var color lineColor = na
            if j < -60
                lineColor := color.red
            else if j < -30
                lineColor := color.orange
            else if j < 0
                lineColor := color.yellow
            else if j < 30
                lineColor := color.green
            else if j < 60
                lineColor := color.blue
            else
                lineColor := color.purple
            line.new(prev_x, prev_y, bar_index + math.round(x), y, color = marketcycle?lineColor:na, width = 2)
            prev_y := y
            prev_x := bar_index + math.round(x)
            if na(max_height) or y > max_height
                max_height := y
        max_height
max_height   = cycle()
height_scale = math.round((fixnan(ta.valuewhen(fixnan(max_height)==fixnan(max_height[1]),fixnan(max_height),1))),1)

// Function to generate a sine wave
generateSineWave(height, duration) =>
    pi        = 3.14159265359
    waveSpeed = 2 * pi / duration
    sineWave  = height * math.sin(waveSpeed * bar_index)
    sineWave
sineWave = generateSineWave(100, math.atan(sineWavePeriod))

// Function to generate cycle signals
generateSignal(sineWave, signalThreshold, entryLimit, direction) =>
    signal = 0.
    entry  = 0.
    if (direction and sineWave > signalThreshold) or (not direction and sineWave < signalThreshold)
        signal := height_scale/2
    for i = 0 to 5
        if (direction and signal[i] and sineWave > entryLimit) or (not direction and signal[i] and sineWave < entryLimit)
            entry := height_scale/2
    entry
//~~~~~~~~~~~~~~~~~~~~~~~}

// Plot cycle
cycle_1 = sine?generateSignal(sineWave, 99.6, 80, true):na
cycle_2 = sine?generateSignal(sineWave, -99.6, -80, false):na
plot(cycle_1, style=plot.style_area, color=color.new(color.green, 0), title='Sine Wave Cycle 1')
plot(cycle_2, style=plot.style_area, color=color.new(#ffcb7e, 0), title='Sine Wave Cycle 2')

// Plot cycle divider {
bgcolor(color=bg and c==NumbOfBars?color.navy:na, title="BG Divider Market Cycle 1")
bgcolor(color=overlap and bg and c==0?color.navy:na, title="BG Divider Market Cycle 2")
//~~~~~~~~~~~~~~~~~~~~~~~~~}