Author MEssage:
This indicator transforms selected moving averages into a Z-Score oscillator, providing clear signals for potential buy and sell opportunities. The indicator includes options to choose from eleven different moving average types, each offering unique benefits and characteristics. It also provides additional features such as standard deviation levels, extreme levels, and divergence detection, enhancing its utility in various market conditions.
CODE:
CSS:
#// Indicator for TOS
#// © BackQuant
#indicator( title = "Moving Average Z-Score Suite [BackQuant]"
# Converted by Sam4Cok@Samer800 - 12/2024
declare lower;
input timeframe = AggregationPeriod.MIN;
input colorBars = yes;
input movAvgType = {"SMA", "Hull", "Ema", "Wma", "Dema", "RMA", "LINREG", "TEMA", "ALMA", default "Kalman Hull", "T3"};
input Source = FundamentalType.CLOSE; # "Calculation Source"
input length = 30; # "Calculation Period"
input ZScoreLookback = 30; # "Z-Score Lookback Period"
input SigmaForAlma = 6; # "Sigma for ALMA"
input measurementNoise = 3.0; # "Measurement Noise"
input processNoise = 0.01; # "Process Noise"
input showStandardLevels = yes; # "Show Standard Deviation Levels (0, 1, 2, -1, -2 Levels) ?"
input showExtremeLevels = yes; # "Show Extreme Levels ?"
def na = Double.NaN;
def last = IsNaN(close);
def cap = GetAggregationPeriod();
def tf = Max(cap, timeframe);
def src = Fundamental(FundamentalType = Source, Period = tf);
#-- Functions
Script t3 {
input source = close;
input length = 30;
input vf = 0.7;
def ema1 = ExpAverage(source, length);
def gd1 = ema1 * (1 + vf) - ExpAverage(ema1, length) * vf;
def ema2 = ExpAverage(gd1, length);
def gd2 = ema2 * (1 + vf) - ExpAverage(ema2, length) * vf;
def ema3 = ExpAverage(gd2, length);
def t3 = ema3 * (1 + vf) - ExpAverage(ema3, length) * vf;
plot out = t3;
}
script ALMA {
input Data = close;
input Window = 9;
input Offset = 0.0;
input Sigma = 6;
def m = (Offset * (Window - 1));
def s = Window/Sigma;
def SumVectorData = fold y = 0 to Window with WS do
WS + Exp(-(sqr(y-m))/(2*sqr(s))) * getvalue(Data, (Window-1)-y);
def SumVector = fold z = 0 to Window with CW do
CW + Exp(-(sqr(z-m))/(2*sqr(s)));
plot ALMA = SumVectorData / SumVector;
}
#// Kalman filter function
Script f_kalman {
input src = close;
input Noise = 3;
input process = 0.01;
input stateEst = close;
input errorCov = 1;
def pse = if isNaN(stateEst) then src else if !stateEst then src else stateEst;
def pec = CompoundValue(1, errorCov + process, 1);
def kg = pec / (pec + Noise);
def se = pse + kg * (src - pse);
def ec = (1 - kg) * pec;
plot stateEstimate = se;
plot errorCovariance = ec;
}
#// Hull Moving Average Function with Kalman instead of Weighted Moving Average
Script KHMA {
input pricesource = close;
input measurementNoise = 3;
input processNoise = 0.01;
input length = 30;
def len = Round(Sqrt(length), 0);
def se1; def ec1;
def se0 = f_kalman(pricesource, measurementNoise, processNoise, se1[1], ec1[1]).stateEstimate;
def ec0 = f_kalman(pricesource, measurementNoise, processNoise, se1[1], ec1[1]).errorCovariance;
se1 = f_kalman(pricesource, measurementNoise, processNoise, se0, ec0).stateEstimate;
ec1 = f_kalman(pricesource, measurementNoise, processNoise, se0, ec0).errorCovariance;
def khma1 = f_kalman(pricesource, measurementNoise/2, processNoise, se0, ec0).stateEstimate;
def khma2 = f_kalman(pricesource, measurementNoise, processNoise, se0, ec0).stateEstimate;
def KHMA = f_kalman(2 * khma1 - khma2, len, processNoise, se0, ec0).stateEstimate;
plot out = KHMA;
}
def subject;
Switch (movAvgType) {
Case "SMA" : subject = Average(src, length);
Case "Hull" : subject = HullMovingAvg(src, length);
Case "Ema" : subject = ExpAverage(src, length);
Case "Wma" : subject = WMA(src, length);
Case "Dema" : subject = DEMA(src, length);
Case "RMA" : subject = WildersAverage(src, length);
Case "LINREG" : subject = Inertia(src, length);
Case "TEMA" : subject = TEMA(src, length);
Case "ALMA" : subject = alma(src, length, 0, SigmaForAlma);
Case "T3" : subject = t3(src, length, 0.7);
Default: subject = KHMA(src, measurementNoise, processNoise, length);
}
def mean = ExpAverage(subject, ZScoreLookback);
def stdDev = stdev(subject, ZScoreLookback);
def zScore = (subject - mean) / stdDev;
#// Conditional Color
def posroc = zScore > zScore[1];
def negroc = zScore < zScore[1];
def col = if zScore > 0 and posroc then 2 else
if zScore > 0 and negroc then 1 else
if zScore < 0 and negroc then -2 else
if zScore < 0 and posroc then -1 else col[1];
#/ Adaptive Trend Strength Color
def trendStrength = AbsValue(zScore);
def maxStrength = 4.5;
def normalizedStrength = min(trendStrength / maxStrength * 100, 100);
def alphaValue = (100 - normalizedStrength);
#-- Zscore
plot demaZScore = zScore;
demaZScore.SetLineWeight(2);
demaZScore.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
demaZScore.AssignValueColor(if col == 2 then Color.CYAN else
if col == 1 then CreateColor(0, 100, 100) else
if col ==-2 then Color.MAGENTA else
if col ==-1 then Color.PLUM else Color.GRAY);
#----divergences
input showdivergences = no;
input LookBackRight = 10; # "Pivot Lookback Right"
input LookBackLeft = 10; # "Pivot Lookback Left"
Script Pivot {
input series = hl2;
input leftBars = 10;
input rightBars = 10;
input isHigh = yes;
def na = Double.NaN;
def HH = series == Highest(series, leftBars + 1);
def LL = series == Lowest(series, leftBars + 1);
def pivotRange = (leftBars + rightBars + 1);
def leftEdgeValue = if series[pivotRange] ==0 then na else series[pivotRange];
def pvtCond = !isNaN(series) and leftBars > 0 and rightBars > 0 and !isNaN(leftEdgeValue);
def barIndexH = if pvtCond then
fold i = 1 to rightBars + 1 with p=1 while p do
series > GetValue(series, - i) else na;
def barIndexL = if pvtCond then
fold j = 1 to rightBars + 1 with q=1 while q do
series < GetValue(series, - j) else na;
def PivotPoint;
if isHigh {
PivotPoint = if HH and barIndexH then series else na;
} else {
PivotPoint = if LL and barIndexL then series else na;
}
plot pvt = PivotPoint;
}
#_inRange(cond) =>
script _inRange {
input cond = yes;
def bars = if cond then 0 else bars[1] + 1;
def inrange = (-80 <= bars) and (bars <= 80);
plot retrun = inRange;
}
def bar = bar[1] + 1;
def plFound = if isNaN(pivot(zScore, LookBackLeft, LookBackRight, no)[LookBackRight]) then no else yes;
def phFound = if isNaN(pivot(zScore, LookBackLeft, LookBackRight, yes)[LookBackRight]) then no else yes;
#-- Pvt Low
def vlFound; def vlFound1;
def plPrice; def plPrice1;
def lastPlBar; def prePlBar;
if plFound {
vlFound = vlFound1[1];
vlFound1 = zScore[LookBackRight];
plPrice = plPrice1[1];
plPrice1 = low(Period = tf)[LookBackRight];
prePlBar = lastPlBar[1];
lastPlBar = bar - LookBackRight;
} else {
vlFound1 = vlFound1[1];
vlFound = vlFound[1];
plPrice1 = plPrice1[1];
plPrice = plPrice[1];
prePlBar = prePlBar[1];
lastPlBar = lastPlBar[1];
}
#-- Pvt High
def vhFound; def vhFound1;
def phPrice; def phPrice1;
def lastPhBar; def prePhBar;
if phFound {
vhFound = vhFound1[1];
vhFound1 = zScore[LookBackRight];
phPrice = phPrice1[1];
phPrice1 = high(Period = tf)[LookBackRight];
prePhBar = lastPhBar[1];
lastPhBar = bar - LookBackRight;
} else {
vhFound1 = vhFound1[1];
vhFound = vhFound[1];
phPrice1 = phPrice1[1];
phPrice = phPrice[1];
prePhBar = prePhBar[1];
lastPhBar = lastPhBar[1];
}
#// Regular Bullish
def oscHL = zScore[LookBackRight] > vlFound and _inRange(plFound[1]);
def priceLL = low(Period = tf)[LookBackRight] < plPrice and zScore <= 0;
def bullCond = plFound and oscHL and priceLL;
#// Regular Bearish
def inRangePh = _inRange(phFound[1]);
def oscLH = zScore[LookBackRight] < vhFound and inRangePh;
def priceHH = high(Period = tf)[LookBackRight] > phPrice and zScore >= 0;
def bearCond = phFound and oscLH and priceHH;
#------ Bubbles
def bullBub = showdivergences and bullCond;
def bearBub = showdivergences and bearCond;
addchartbubble(bullBub[-LookBackRight], zScore , "R", Color.CYAN, no);
addchartbubble(bearBub[-LookBackRight], zScore , "R", Color.MAGENTA, yes);
##### Lines
#-- Bear Line
def priorPHBar;
def lastBearBar;
if bearCond {
priorPHBar = prePhBar;
lastBearBar = bar - LookBackRight;
} else {
priorPHBar = 0;
lastBearBar = 0;
}
#-- Bull Line
def priorPLBar;
def lastBullBar;
if bullCond {
priorPLBar = prePlBar;
lastBullBar = bar - LookBackRight;
} else {
priorPLBar = 0;
lastBullBar = 0;
}
def pivotHigh = if bar == HighestAll(priorPHBar) then zScore else
if bar == HighestAll(lastBearBar) then zScore else na;
def pivotLow = if bar == HighestAll(priorPLBar) then zScore else
if bar == HighestAll(lastBullBar) then zScore else na;
plot PlotHline = if showdivergences then pivotHigh else na;
PlotHline.EnableApproximation();
PlotHline.SetDefaultColor(Color.MAGENTA);
plot PlotLline = if showdivergences then pivotLow else na;
PlotLline.EnableApproximation();
PlotLline.SetDefaultColor(Color.CYAN);
#// Upper Extreme Levels
plot u1 = if showExtremeLevels and !last then 4 else na; #, "Upper",
plot u2 = if showExtremeLevels and !last then 3 else na;
u1.SetPaintingStrategy(PaintingStrategy.LINE_VS_POINTS);
u2.SetPaintingStrategy(PaintingStrategy.LINE_VS_POINTS);
u1.AssignValueColor(if zScore>= 0 then CreateColor(255 - alphaValue * 2.55, 0, 0) else CreateColor(26, 0, 0));
u2.AssignValueColor(if zScore>= 0 then CreateColor(255 - alphaValue * 2.55, 0, 0) else CreateColor(26, 0, 0));
AddCloud(u1 , u2, Color.DARK_RED); # "Extreme Upper"
#// Lower Extreme Levels
plot l1 = if showExtremeLevels and !last then -4 else na; #, "Lower"
plot l2 = if showExtremeLevels and !last then -3 else na;
l1.SetPaintingStrategy(PaintingStrategy.LINE_VS_POINTS);
l2.SetPaintingStrategy(PaintingStrategy.LINE_VS_POINTS);
l1.AssignValueColor(if zScore< 0 then CreateColor(0, 255- alphaValue * 2.55, 0) else CreateColor(0, 26, 0));
l2.AssignValueColor(if zScore< 0 then CreateColor(0, 255- alphaValue * 2.55, 0) else CreateColor(0, 26, 0));
AddCloud(l2,l1, Color.DARK_GREEN);
#// Plotting Hlines
plot "0" = if showStandardLevels and !last then 0 else na;
plot "1" = if showStandardLevels and !last then 1 else na;
plot "2" = if showStandardLevels and !last then 2 else na;
plot "-1" = if showStandardLevels and !last then -1 else na;
plot "-2" = if showStandardLevels and !last then -2 else na;
"0".SetPaintingStrategy(PaintingStrategy.DASHES);
"1".SetPaintingStrategy(PaintingStrategy.DASHES);
"-1".SetPaintingStrategy(PaintingStrategy.DASHES);
"0".SetDefaultColor(Color.DARK_GRAY);
"1".SetDefaultColor(Color.DARK_GRAY);
"2".SetDefaultColor(Color.DARK_GRAY);
"-1".SetDefaultColor(Color.DARK_GRAY);
"-2".SetDefaultColor(Color.DARK_GRAY);
#-- Bar Color
AssignPriceColor(if !colorBars then Color.CURRENT else
if col == 2 then Color.GREEN else
if col == 1 then Color.DARK_GREEN else
if col ==-2 then Color.RED else
if col ==-1 then Color.DARK_RED else Color.GRAY);
#-- END of CODE
Last edited by a moderator: