#===============================================================================
# AutoCorrelationPeriodogram for Dominant Cycle Period
#
# Charles Schwab & Co. (c) 2008-2025
#
input lag = 48;
def x = EhlersRoofingFilter("cutoff length" = 8, "roof cutoff length" = 48);
def cosinePart = fold i = 3 to 48 with cosPart do cosPart + (3 * (x * GetValue(x, i) + GetValue(x, 1) * GetValue(x, i + 1) + GetValue(x, 2) * GetValue(x, i + 2)) - (x + GetValue(x, 1) + GetValue(x, 2)) * (GetValue(x, i) + GetValue(x, i + 1) + GetValue(x, i + 2))) / Sqrt((3 * (x * x + GetValue(x, 1) * GetValue(x, 1) + GetValue(x, 2) * GetValue(x, 2)) - Sqr(x + GetValue(x, 1) + GetValue(x, 2))) * (3 * (GetValue(x, i) * GetValue(x, i) + GetValue(x, i + 1) * GetValue(x, i + 1) + GetValue(x, i + 2) * GetValue(x, i + 2)) - Sqr(GetValue(x, i) + GetValue(x, i + 1) + GetValue(x, i + 2)))) * Cos(2 * Double.Pi * i / lag);
def sinePart = fold j = 3 to 48 with sinPart do sinPart + (3 * (x * GetValue(x, j) + GetValue(x, 1) * GetValue(x, j + 1) + GetValue(x, 2) * GetValue(x, j + 2)) - (x + GetValue(x, 1) + GetValue(x, 2)) * (GetValue(x, j) + GetValue(x, j + 1) + GetValue(x, j + 2))) / Sqrt((3 * (x * x + GetValue(x, 1) * GetValue(x, 1) + GetValue(x, 2) * GetValue(x, 2)) - Sqr(x + GetValue(x, 1) + GetValue(x, 2))) * (3 * (GetValue(x, j) * GetValue(x, j) + GetValue(x, j + 1) * GetValue(x, j + 1) + GetValue(x, j + 2) * GetValue(x, j + 2)) - Sqr(GetValue(x, j) + GetValue(x, j + 1) + GetValue(x, j + 2)))) * Sin(2 * Double.Pi * j / lag);
def sqSum = Sqr(cosinePart) + Sqr(sinePart);
def Periodogram = ExpAverage(sqSum, 9);
#================================================================================
# Makes the CorrelationCylinderIndicator Adaptable
#
# Charles Schwab & Co. (c) 2008-2025
#
# Modified by implementing nested folds to enable adaptable indicator
def length = Periodogram;
def limit = if IsNaN(length) then limit[1] else Floor(length); #ensures length is not NaN and rounds it down to nearest integer
def sx = fold ii = 0 to limit with S do S + GetValue(close, ii); #Sum(close, length);
def sxx = fold jj = 0 to limit with SS do SS + GetValue(Sqr(close), jj); #Sum(Sqr(close), length);
#def sy1 = fold i1 = 0 to length with s1 do (s1 + Cos(2 * Double.Pi * i1 / length));
def sy1 = fold i1 = 0 to limit with s1 do (s1 + fold loop21 = 0 to 1 with c11 do c11 + COS(2 * Double.Pi * i1 / limit));
#def sxy1 = fold i2 = 0 to length with s2 do (s2 + GetValue(close, i2) * Cos(2 * Double.Pi * i2 / length));
def sxy1 = fold i2 = 0 to limit with s2 do (s2 + fold loop22 = 0 to 1 with c12 do c12 + GetValue(close, i2) * Cos(2 * Double.Pi * i2 / limit));
#def syy1 = fold i3 = 0 to length with s3 do (s3 + Sqr(Cos(2 * Double.Pi * i3 / length)));
def syy1 = fold i3 = 0 to limit with s3 do (s3 + fold loop23 = 0 to 1 with c13 do c13 + Sqr(Cos(2 * Double.Pi * i3 / limit)));
def sxx_sx = length * sxx - Sqr(sx);
def corrCosine = if sxx_sx == 0 then 0 else (limit * sxy1 - sx * sy1) / Sqrt(sxx_sx * (limit * syy1 - Sqr(sy1)));
#def sy2 = fold j1 = 0 to limit with t1 do (t1 - Sin(2 * Double.Pi * t1 / limit));
def sy2 = fold j1 = 0 to limit with t1 do (t1 - fold loop24 = 0 to 1 with c14 do c14 + Sin(2 * Double.Pi * t1 / limit));
#def sxy2 = fold j2 = 0 to limit with t2 do (t2 - GetValue(close, j2) * Sin(2 * Double.Pi * j2 / limit));
def sxy2 = fold j2 = 0 to limit with t2 do (t2 - fold loop25 = 0 to 1 with c15 do c15 + GetValue(close, j2) * Sin(2 * Double.Pi * j2 / limit));
#def syy2 = fold j3 = 0 to limit with t3 do (t3 + Sqr(Sin(2 * Double.Pi * j3 / limit)));
def syy2 = fold j3 = 0 to limit with t3 do (t3 + fold loop26 = 0 to 1 with c16 do c16 + Sqr(Sin(2 * Double.Pi * j3 / limit)));
def corrNegSine = if sxx_sx == 0 then 0 else (limit * sxy2 - sx * sy2) / Sqrt(sxx_sx * (limit * syy2 - Sqr(sy2)));
plot CorrelationWithCosine = corrCosine;
plot CorrelationWithNegativeSine = corrNegSine;
plot ZeroLine = 0;
CorrelationWithCosine.SetDefaultColor(GetColor(5));
CorrelationWithNegativeSine.SetDefaultColor(GetColor(6));
ZeroLine.SetDefaultColor(GetColor(7));