
Author Message:
The Standardized MACD Heikin-Ashi Transformed (St. MACD) is an advanced indicator designed to overcome the limitations of the traditional MACD. It offers a more robust and standardized measure of momentum, making it comparable across different timeframes and securities. By incorporating the Heikin-Ashi transformation, the St. MACD provides a smoother visualization of trends and potential reversals, enhancing its utility for traders seeking a clearer view of the underlying market direction.
More Details : https://www.tradingview.com/v/g5qN1YDp/
Update:
I update the script to include dynamic levels. Can plot better signals I guess. Try it out!
More details on "MACD Fake Filter [RH]" indicator can found here:
https://www.tradingview.com/v/X1YMOQGm/
CODE:
CSS:
# https://www.tradingview.com/v/g5qN1YDp/
#//@QuantiLuxe
#indicator("Standardized MACD Heikin-Ashi Transformed"
# Converted by Sam4Cok@Samer800 - 07/2023
# upDate - Added Dynamic Levels - 08/2023
# Dynamic level from "MACD Fake Filter [RH]" indicator by © HasanRifat
# https://www.tradingview.com/v/X1YMOQGm/
declare lower;
input useDynamicLevels = {Default "Yes", "No"};
input Source = close; # "Source"
input MovAvgType = AverageType.EXPONENTIAL;
input CalcMethod = {Default "High/Low", "Open/Close"};
input fastLength = 12; # "Fast Length"
input slowLength = 26; # "Slow Length"
input signalLength = 9; # "Signal Length"
input HeikinAshiSmoothing = {Default "No", "Yes"};
input ShowMacdSignalLine = yes;
input DisplayMode = {default "Hybrid", "MACD", "Histogram"}; # "Display Mode"
input signalThreshold = {"Don't Show Signals", "75", Default "100", "150"}; # "Reversion Threshold"
input BarColoringMode = {default "None","MidLine","Candles","Signal Cross","Extremities","Reversions"};
input HollowCandles = no; # "Hollow Candles"
input HeikinAshiFactor = 1.0; # "Heikin Ashi factor"
input UseModifiedCalc = no; # "Use modified calculation?"
input smoothedHeikinAshi = no; # "Do HA 2nd time?"
input UseModifiedCalcForSmoothedHa = no; # "Use modified calculation (2nd time)?"
def na = Double.NaN;
def last = IsNaN(close);
def pos = Double.POSITIVE_INFINITY;
def neg = Double.NEGATIVE_INFINITY;
def ModHA2 = UseModifiedCalcForSmoothedHa;
def histo = DisplayMode == DisplayMode."Histogram";
def mac = DisplayMode == DisplayMode."MACD";
def revt;
Switch (signalThreshold) {
Case "Don't Show Signals" : revt = na;
Case "75" : revt = 75;
Case "100" : revt = 100;
Case "150" : revt = 150;
}
def hiLo = high - low;
def OpCl = AbsValue(open - close);
def SrcDif;
Switch (CalcMethod) {
Case "High/Low" : SrcDif = hiLo;
Case "Open/Close" : SrcDif = OpCl;
}
#-- Color--
DefineGlobalColor("up", CreateColor(0, 188, 212));
DefineGlobalColor("dn", CreateColor(252, 31, 31));
DefineGlobalColor("lvlup1", CreateColor(182, 2, 2));
DefineGlobalColor("lvlup2", CreateColor(85, 1, 1));
DefineGlobalColor("lvldn1", CreateColor(0, 170, 192));
DefineGlobalColor("lvldn2", CreateColor(0, 101, 114));
#// functions
#mkHA0(o_, h_, l_, c_, useModif) =>
script mkHA0 {
input o_ = open;
input h_ = high;
input l_ = low;
input c_ = close;
input HAfact = 1;
input useModif = no;
def mintick = TickSize();
def ohlc = (o_ + h_ + l_ + c_) / 4;
def cl = Round(ohlc / mintick, 0) * mintick;# // needs to be before /op/
def op;# = float(na)
if useModif {
op = if isNaN(o_[1]) then (o_ + HAfact*c_)/(1+HAfact) else
(op[1] + HAfact * cl[1]) / (1 + HAfact);
} else {
op = if isNaN(o_[1]) then (o_ + HAfact*c_)/(1+HAfact) else
(o_[1] + HAfact * c_[1]) / (1 + HAfact);
}
def op_ = Round(op / mintick, 0) * mintick;
def max = Max(h_, Max(op, cl));
def min = Min(l_, Min(op, cl));
def hi = Round(Max / mintick, 0) * mintick;
def lo = Round(Min / mintick, 0) * mintick;
plot haop = op;
plot haHi = hi;
plot haLo = lo;
plot haCl = cl;
}
#mkHA(o_, h_, l_, c_, useModif_, twice, useModif2) =>
script mkHA {
input o_ = open;
input h_ = high;
input l_ = low;
input c_ = close;
input HAfact = 1;
input useModif_ = no;
input twice = no;
input useModif2 = no;
def op1 = mkHA0(o_, h_, l_, c_, HAfact, useModif_).haop;
def hi1 = mkHA0(o_, h_, l_, c_, HAfact, useModif_).haHi;
def lo1 = mkHA0(o_, h_, l_, c_, HAfact, useModif_).haLo;
def cl1 = mkHA0(o_, h_, l_, c_, HAfact, useModif_).haCl;
def op2 = mkHA0(op1, hi1, lo1, cl1, HAfact, useModif2).haop;
def hi2 = mkHA0(op1, hi1, lo1, cl1, HAfact, useModif2).haHi;
def lo2 = mkHA0(op1, hi1, lo1, cl1, HAfact, useModif2).haLo;
def cl2 = mkHA0(op1, hi1, lo1, cl1, HAfact, useModif2).haCl;
def op;
def hi;
def lo;
def cl;
if twice {
op = op2;
hi = hi2;
lo = lo2;
cl = cl2;
} else {
op = op1;
hi = hi1;
lo = lo1;
cl = cl1;
}
plot haop = op;
plot haHi = hi;
plot haLo = lo;
plot haCl = cl;
}
#f_macd(src, fast, slow) =>
script f_macd {
input type = close;
input src = close;
input fast = 12;
input slow = 26;
input MovAvgType = AverageType.EXPONENTIAL;
def diff = type;
def fasMov = MovingAverage(MovAvgType, src, fast);
def slowMov = MovingAverage(MovAvgType, src, slow);
def value = fasMov - slowMov;
def sign = MovingAverage(MovAvgType, diff, slow);
def macd = (value / sign) * 100;
plot out = macd;
}
#-- functions
def macd = f_macd(SrcDif, Source, fastLength, slowLength, MovAvgType);
def sig = MovingAverage(MovAvgType, macd, signalLength);
def hist = macd - sig;
def o_macd = macd[1];
def h_macd = Max(macd, macd[1]);
def l_macd = Min(macd, macd[1]);
def c_macd = macd;
def haO = mkHA(o_macd, h_macd, l_macd, c_macd, HeikinAshiFactor, UseModifiedCalc, smoothedHeikinAshi, ModHA2).haop;
def haH = mkHA(o_macd, h_macd, l_macd, c_macd, HeikinAshiFactor, UseModifiedCalc, smoothedHeikinAshi, ModHA2).haHi;
def haL = mkHA(o_macd, h_macd, l_macd, c_macd, HeikinAshiFactor, UseModifiedCalc, smoothedHeikinAshi, ModHA2).haLo;
def haC = mkHA(o_macd, h_macd, l_macd, c_macd, HeikinAshiFactor, UseModifiedCalc, smoothedHeikinAshi, ModHA2).haCl;
def haClose = haC;
def haOpen = haO;
def haHigh = haH;
def haLow = haL;
def haSrcdiff;
def haHiLo = haHigh - haLow;
def haOpCl = AbsValue(haOpen - haClose);
Switch (CalcMethod) {
Case "High/Low" : haSrcdiff = haHiLo;
Case "Open/Close" : haSrcdiff = haOpCl;
}
def hamacd = f_macd(haSrcdiff, haClose, fastLength, slowLength, MovAvgType);
def hasig = MovingAverage(MovAvgType, hamacd, signalLength);
def hahist = hamacd - hasig;
def hist1;def macd1; def sig1;def macdL;
Switch (HeikinAshiSmoothing) {
Case "yes" :
macd1 = hamacd;
sig1 = hasig;
hist1 = hahist;
macdL = hamacd;
Case "No" :
macd1 = macd;
sig1 = sig;
hist1 = hist;
macdL = na;
}
def h_col = if hist1 > 0 then
(if hist1 > hist1[1] then 2 else 1) else
(if hist1 > hist1[1] then -1 else -2);
#--Heikin-Ashi
def candleUp = haClose > haOpen;
def haopenUp = if Histo then na else if candleUp then if HollowCandles then haOpen else haClose else na;
def hacloseUp = if Histo then na else if candleUp then if HollowCandles then haClose else haOpen else na;
def hahigh_ = if Histo then na else haHigh;
def halow_ = if Histo then na else haLow;
def haopenDn = if Histo or candleUp then na else haOpen;
def hacloseDn = if Histo or candleUp then na else haClose;
AddChart(high = haHigh_, low = haLow_, open = haopenUp, close = hacloseUp,
type = ChartType.CANDLE, growcolor = Color.CYAN);
AddChart(high = haHigh_ , low = haLow_ , open = haopenDn, close = hacloseDn,
type = ChartType.CANDLE, growcolor = Color.MAGENTA);
#-- midLine
plot MidLine = if last then na else 0;
MidLine.SetStyle(Curve.SHORT_DASH);
MidLine.SetDefaultColor(Color.GRAY);
# macd Line
plot macdLine = if ShowMacdSignalLine then macdL else na;
macdLine.SetDefaultColor(Color.LIGHT_ORANGE);
#-- Signal Line
plot macdSig = if ShowMacdSignalLine then sig1 else na; # "Signal"
macdSig.SetDefaultColor(Color.WHITE);
#-- Histogram
plot macdHist = if !mac then hist1 else na; # "Histogram"
macdHist.SetLineWeight(3);
macdHist.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
macdHist.AssignValueColor(if h_col == 2 then Color.LIGHT_GREEN else
if h_col == 1 then Color.DARK_GRAY else#
if h_col == -2 then Color.PINK else Color.DARK_GRAY);
#-- Dynamic Levels
def macdZeroCrossOver = !isNaN(macd1[1]) and macd1 > 0 and macd1[1] <= 0;
def macdZeroCrossUnder = !isNaN(macd1[1]) and macd1 < 0 and macd1[1] >= 0;
def activeWave;
if macdZeroCrossOver {
activeWave = 1;
} else
if macdZeroCrossUnder {
activeWave = -1;
} else {
activeWave = activeWave[1];
}
def dirUp = activeWave == 1;
def dirDn = activeWave == -1;
def positiveTop;def negatieTop;
def AvgHi; def AvgLo; def countUp; def countDn;
if dirUp {
positiveTop = max(positiveTop[1], macd1);
negatieTop = 0;
AvgHi = AvgHi[1];
AvgLo = if !dirUp[1] then AvgLo[1] + negatieTop[1] else AvgLo[1];
countUp = countUp[1];
countDn = if !dirUp[1] then countDn[1] + 1 else countDn[1];
} else
if dirDn {
negatieTop = min(negatieTop[1], macd1);
positiveTop = 0;
AvgHi = if !dirDn[1] then AvgHi[1] + positiveTop[1] else AvgHi[1];
AvgLo = AvgLo[1];
countUp = if !dirDn[1] then countUp[1] + 1 else countUp[1];
countDn = countDn[1];
} else {
negatieTop = 0;
positiveTop = 0;
AvgHi = AvgHi[1];
AvgLo = AvgLo[1];
countUp = countUp[1];
countDn = countDn[1];
}
def posAvgHi = AvgHi;
def cntUp = countUp;
def positiveAverageHeight = posAvgHi / cntUp;
def negAvgHi = AvgLo;
def cntDn = countDn;
def negativeAverageHeight = negAvgHi / cntDn;
def bearishCrossunder = (macd1 < sig1) and (macd1[1] >= sig1[1]);
def bullishCrossover = (macd1 > sig1) and (macd1[1] <= sig1[1]);
def crossunderAboveAvg = bearishCrossunder and macd1 > positiveAverageHeight;
def crossaboveBelowAvg = bullishCrossover and macd1 < negativeAverageHeight;
#-- OB/OS highlight
def max; def hh;def lh;def min;def ll;def hl;
Switch (useDynamicLevels) {
Case "Yes":
max = if last then na else pos;
hh = if last then na else if !histo then
if positiveAverageHeight > 150 then positiveAverageHeight else 150 else
if positiveAverageHeight > 75 then positiveAverageHeight else 75;
lh = if last then na else positiveAverageHeight;
min = if last then na else neg;
ll = if last then na else if !histo then
if negativeAverageHeight < -150 then negativeAverageHeight else -150 else
if negativeAverageHeight < -75 then negativeAverageHeight else -75;
hl = if last then na else negativeAverageHeight;
Case "No":
max = if last then na else pos;
hh = if last then na else if !histo then 150 else 75;
lh = if last then na else if !histo then 100 else 50;
min = if last then na else neg;
ll = if last then na else if !histo then -150 else -75;
hl = if last then na else if !histo then -100 else -50;
}
AddCloud(hh, lh, GlobalColor("lvlup2"), GlobalColor("lvlup2"));
AddCloud(max, hh, GlobalColor("lvlup1"), GlobalColor("lvlup1"));
AddCloud(hl, ll, GlobalColor("lvldn2"), GlobalColor("lvldn2"));
AddCloud(ll, min, GlobalColor("lvldn1"), GlobalColor("lvldn1"));
#-- Signal
def SigDn;def SigUp;
Switch (useDynamicLevels) {
Case "Yes":
SigDn = if Histo then na else
if crossunderAboveAvg then haHigh + 30 else na;
SigUp = if Histo then na else
if crossaboveBelowAvg then haLow - 30 else na;
Case "No":
SigDn = if Histo then na else
if haHigh > revt and haClose < haOpen and !(haClose[1] < haOpen[1]) then
haHigh + 30 else na;
SigUp = if Histo then na else
if haLow < -revt and haClose > haOpen and !(haClose[1] > haOpen[1]) then
haLow - 30 else na;
}
plot OB = SigDn;
plot OS = SigUp;
OB.SetPaintingStrategy(PaintingStrategy.SQUARES);
OS.SetPaintingStrategy(PaintingStrategy.SQUARES);
OB.SetDefaultColor(Color.RED);
OS.SetDefaultColor(Color.GREEN);
#-- Bar Color
def col;
switch (BarColoringMode) {
Case "None": col = na;
Case "MidLine" : col = if macd1 > 0 then 1 else -1;
Case "Extremities": col = if macd1 > revt then -1 else if macd1 < -revt then 1 else 0;
Case "Reversions" : col = if macd1 > revt and macd1 < macd1[1] and !(macd1[1] < macd1[2]) then -1 else
if macd1 < -revt and macd1 > macd1[1] and !(macd1[1] > macd1[2]) then 1 else 0;
Case "Candles" : col = if haClose > haOpen then 1 else -1;
Case "Signal Cross" : col = if sig1 > haClose then -1 else 1;
}
AssignPriceColor(if isNaN(col) then Color.CURRENT else
if col >0 then GlobalColor("up") else
if col <0 then GlobalColor("dn") else Color.GRAY);
#--- END of Code
Last edited: