Prime, E & PI Superiority Cycles
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Eliza123123 & david4342

//@version=5
indicator("Prime, E & PI Superiority Cycles", overlay = true, max_lines_count = 200)

// Inputs
Prime = input.bool(true, "On/Off", "", inline = "Colour", group = "Prime Frame")
PrimeCol = input.color(color.new(color.olive,0), "", inline = "Colour", group = "Prime Frame")
Euler = input.bool(true, "On/Off", "", inline = "Colour", group = "E Frame")
EulerCol = input.color(color.new(color.green,0), "", inline = "Colour", group = "E frame")
Pi = input.bool(true, "On/Off", "", inline = "Colour", group = "Pi Frame")
PiCol = input.color(color.new(color.maroon,0), "", inline = "Colour", group = "Pi Frame")

//---------------------FRAME CREATION CODE-------------------//

// Define constants
pi = 3.14159
e = 2.71828

// Initialises and assigns values to the Prime Frame, E frame and Pi Frame.
float[] primes = array.from(2.0,3.0,5.0,7.0,11.0,13.0,17.0,19.0,23.0,27.0,29.0,31.0,37.0,41.0,43.0,47.0,53.0,59.0,61.0,67.0,71.0,73.0,79.0,83.0,89.0,97.0)
float[] eLevels = array.from(2.71828, 5.43656, 8.15484, 10.87312, 13.5914, 16.30968, 19.02796, 21.74624, 24.46452, 27.1828, 29.90108, 32.61936, 35.33764, 
 38.05592, 40.7742, 43.49248, 46.21076, 48.92904, 51.64732, 54.3656, 57.08388, 59.80216, 62.52044, 65.23872, 67.957, 70.67528, 73.39356000000001, 76.11184, 
 78.83012, 81.5484, 84.26668000000001, 86.98496, 89.70324, 92.42152, 95.13980000000001, 97.85808)
float[] piLevels = array.from(3.14159, 6.28318, 9.424769999999999, 12.56636, 15.70795, 18.849539999999998, 21.99113, 25.13272, 28.27431, 31.4159, 34.55749, 
 37.699079999999995, 40.840669999999996, 43.98226, 47.12385, 50.26544, 53.40703, 56.54862, 59.69021, 62.8318, 65.97339, 69.11498, 72.25657, 75.39815999999999, 
 78.53975, 81.68133999999999, 84.82293, 87.96452, 91.10611, 94.2477, 97.38929)

// Function gets scaling for the asset. This is important as the elements from primes, eLevels and piLevels array need to mutiplied by scale to ensure indicator works on all assets
get_scale_func() =>
    get_scale = 0.0
    if (close >= 10 and close < 100)
        get_scale := 1
    if (close >= 100 and close < 1000)
        get_scale := 10
    if (close >= 1000 and close < 10000)
        get_scale := 100
    if (close >= 1 and close < 10)
        get_scale := 0.1
    if (close >= 0.1 and close < 1)
        get_scale := 0.01
    if (close >= 0.01 and close < 0.1)
        get_scale := 0.001
    if (close >= 0.001 and close < 0.01)
        get_scale := 0.0001
    if (close >= 0.0001 and close < 0.001)
        get_scale := 0.00001
    if (close >= 0.00001 and close < 0.0001)
        get_scale := 0.000001
    if (close > 10000)
        get_scale := 1000
    get_scale

// Calls and assings cale from get_scale_func() 
scale = get_scale_func()

// Color switch for on/off switches
if Pi
    PiCol 
else
    PiCol := na
if Euler
    EulerCol
else
    EulerCol := na
if Prime
    PrimeCol
else
    PrimeCol := na

// Function to create frames defined by  a constant to be iterated up the chart
create_frame_func(fFrame, showLines, frameCol) => 
    a = 1
    lw = a % 10 == 0 ? 4 : 1
    while a <= (100.0 / (fFrame / scale))
        if barstate.islast and showLines
            line.new(bar_index[4999], fFrame * a, bar_index, fFrame * a, color = frameCol, width = lw, extend = extend.both)
        a += 1
    
// Generates e and pi frame
closest_pi_percent = create_frame_func(3.14159 * scale, true, PiCol) // Pi
closest_e_percent = create_frame_func(2.71828 * scale, true, EulerCol) // Euler's Constant

// Generates prime frame
i = 0
while i < array.size(primes)
    a = array.get(primes, i)
    v = a * scale
    line = line.new (bar_index[1], v, bar_index, v, color = PrimeCol, width = 1, extend = extend.both)
    i += 1

//---------------------END OF FRAME CREATION CODE-------------------//

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//---------------------SUPERIORITY CYCLE CODE-------------------//

// Initialise high and low arrays
float [] highsArray = array.new_float(0)
float [] lowsArray = array.new_float(0)

// Add last 11 highs/lows to arrays
for j = 0 to 10
    array.push(highsArray, high[j])
    array.push(lowsArray, low[j])

// Boolean condition to ensure five highs to the left and five highs to the right are all lower than the central high in the array high[5] & counter logic for lows
bool highPiv = array.max(highsArray) == high[5]
bool lowPiv = array.min(lowsArray) == low[5]

// Assigns most recent high pivot and low pivot float values
float lastHighPivPrice = ta.valuewhen(highPiv, high[5], 0)
float lastLowPivPrice = ta.valuewhen(lowPiv, low[5], 0)

// Function to determine the distance from the last high or low pivot to the nearest level in a given frame 
distanceFromStructureToPiv(taFloatValue, float[] y) => 
    thisScale = get_scale_func()
    get_dist = array.new_float(0)
    float minimisedValue = 0.0
    float arrayex_var = array.get(y, 0) * thisScale
    for k = 1 to array.size(y) - 2
        float arrayex_var2 = array.get(y, k) * thisScale
        if (math.abs(taFloatValue - arrayex_var2) < math.abs(taFloatValue - arrayex_var))
            arrayex_var := arrayex_var2
    array.push(get_dist, math.abs(taFloatValue - arrayex_var))
    minimisedValue := array.get(get_dist, 0)
    minimisedValue

// Creates six float values for data comparison each containing 1 minimised value
float highPiv_primeFrame = distanceFromStructureToPiv(lastHighPivPrice, primes),     float lowPiv_primeFrame = distanceFromStructureToPiv(lastLowPivPrice, primes)
float highPiv_eFrame = distanceFromStructureToPiv(lastHighPivPrice, eLevels),        float lowPiv_eFrame = distanceFromStructureToPiv(lastLowPivPrice, eLevels)
float highPiv_piFrame = distanceFromStructureToPiv(lastHighPivPrice, piLevels),      float lowPiv_piFrame = distanceFromStructureToPiv(lastLowPivPrice, piLevels)

// Creates array of each frames performance
superiorityFunction(xHigh, xLow, xArray, yHigh, yLow, yArray, zHigh, zLow, zArray) =>
    results = array.new_float(0)
    xSuperiority = (xHigh + xLow < yHigh + yLow) and (xHigh + xLow < zHigh + zLow) 
    var xSuperiorityCount = 0 
    if xSuperiority
        xSuperiorityCount := (xSuperiorityCount + 1)
    ySuperiority = (yHigh + yLow < xHigh + xLow) and (yHigh + yLow < zHigh + zLow) 
    var ySuperiorityCount = 0 
    if ySuperiority
        ySuperiorityCount := (ySuperiorityCount + 1)
    zSuperiority = (zHigh + zLow < xHigh + xLow) and (zHigh + zLow < yHigh + yLow) 
    var zSuperiorityCount = 0 
    if zSuperiority
        zSuperiorityCount := (zSuperiorityCount + 1)
    array.push(results, xSuperiorityCount / array.size(xArray))
    array.push(results, ySuperiorityCount / array.size(yArray))
    array.push(results, zSuperiorityCount / array.size(zArray))
    results

//superiorityFunction() call to create array of frame performances
float [] sfArray = superiorityFunction(highPiv_primeFrame, lowPiv_primeFrame, primes, highPiv_eFrame, lowPiv_eFrame, eLevels, highPiv_piFrame, lowPiv_piFrame, piLevels)

// Finds worst performing frame and retrieves index from array
lowest = array.max(sfArray, 0)
index = array.indexof(sfArray, lowest)

// bgcolors correspond to which frame to target trades at next.
//    ----> if bgcolor is olive target prime frame reversals
//    ----> if bgcolor is green target e frame reversals
//    ----> if bgcolor is maroon target pi frame reversals
bgcolor(color = index == 0 ? color.new(color.olive, 80) : na)
bgcolor(color = index == 1 ? color.new(color.green, 80) : na)
bgcolor(color = index == 2 ? color.new(color.maroon, 80) : na)

// Table showing which frame to target reversals on and the respective scores of each frame.
var dataTable = table.new(position = position.bottom_right, columns = 2, rows = 5, bgcolor = color.black, border_width = 1)
table.cell(table_id = dataTable, column = 0, row = 1, text = "Next target: Prime Superiority (Olive lines on chart)", bgcolor = index == 0 ? color.olive : color.white, text_color = index == 0 ? color.white : #000000)
table.cell(table_id = dataTable, column = 0, row = 2, text = "Next target: E Superiority (Green lines on chart)", bgcolor = index == 1 ? color.green : color.white, text_color = index == 1 ? color.white : #000000)
table.cell(table_id = dataTable, column = 0, row = 3, text = "Next target: Pi Superiority (Maroon Lines on chart)", bgcolor = index == 2 ? color.maroon : color.white, text_color = index == 2 ? color.white : #000000)
table.cell(table_id = dataTable, column = 0, row = 4, text = "[Prime Score, E Score, Pi Score]: " + str.tostring(sfArray), bgcolor = color.white, text_color = #000000)

//---------------------END OF SUPERIORITY CYCLE CODE-------------------//