// MACD zero lag is the calculation of MACD with double or triple exponential moving average // instead of simple exponential moving average // This is supposed to make it less lagging (but it will still be) // The top of every source code file must include this line #include "sierrachart.h" // For reference, refer to this page: // https://www.sierrachart.com/index.php?page=doc/AdvancedCustomStudyInterfaceAndLanguage.php SCDLLName("MACD_zerolag") SCSFExport scsf_MACD_zerolag(SCStudyInterfaceRef sc) { SCSubgraphRef MACDZL = sc.Subgraph[0]; SCSubgraphRef MovAvgOfMACDZL = sc.Subgraph[1]; SCSubgraphRef MACDZLDiff = sc.Subgraph[2]; SCSubgraphRef RefLine = sc.Subgraph[3]; SCInputRef InputData = sc.Input[0]; SCInputRef FastLength = sc.Input[3]; SCInputRef SlowLength = sc.Input[4]; SCInputRef MACDLength = sc.Input[5]; SCInputRef Zerolag = sc.Input[6]; SCFloatArrayRef FastMAOut=MACDZL.Arrays[0]; SCFloatArrayRef SlowMAOut = MACDZL.Arrays[1]; SCFloatArrayRef MovAvgOfMACDZLa = MovAvgOfMACDZL.Arrays[0]; SCFloatArrayRef MovAvgOfMACDZLb = MovAvgOfMACDZL.Arrays[1]; SCFloatArrayRef MovAvgOfMACDZLc = MovAvgOfMACDZL.Arrays[2]; if (sc.SetDefaults) { sc.GraphName = "MACD zero lag"; sc.AutoLoop = 1; sc.StudyDescription = " MACD zero lag is the calculation of MACD with double or triple exponential moving average, instead of simple exponential moving average. This is supposed to make it less lagging (but it will still be)"; sc.GraphRegion = 1; sc.ValueFormat = 3; MACDZL.Name = "MACD zero lag"; MACDZL.DrawStyle = DRAWSTYLE_LINE; MACDZL.DrawZeros = true; MACDZL.PrimaryColor = RGB(0, 255, 0); MovAvgOfMACDZL.Name = "MA of MACD zero lag"; MovAvgOfMACDZL.DrawStyle = DRAWSTYLE_LINE; MovAvgOfMACDZL.DrawZeros = true; MovAvgOfMACDZL.PrimaryColor = RGB(255, 0, 255); MACDZLDiff.Name = "MACD zero lag Diff"; MACDZLDiff.DrawStyle = DRAWSTYLE_BAR; MACDZLDiff.DrawZeros = true; MACDZLDiff.PrimaryColor = RGB(255, 255, 0); RefLine.Name = "Line"; RefLine.DrawStyle = DRAWSTYLE_LINE; RefLine.DrawZeros = true; RefLine.PrimaryColor = RGB(255, 127, 0); InputData.Name = "Input Data"; InputData.SetInputDataIndex(SC_LAST); FastLength.Name = "Fast Moving Average Length"; FastLength.SetInt(12); FastLength.SetIntLimits(1, MAX_STUDY_LENGTH); SlowLength.Name = "Slow Moving Average Length"; SlowLength.SetInt(26); SlowLength.SetIntLimits(1, MAX_STUDY_LENGTH); MACDLength.Name = "MACD Moving Average Length"; MACDLength.SetInt(9); MACDLength.SetIntLimits(1, MAX_STUDY_LENGTH); Zerolag.Name = "DEMA or TEMA"; Zerolag.SetCustomInputStrings("DEMA;TEMA"); Zerolag.SetCustomInputIndex(0); sc.Input[6].SetDescription("Double or triple exponential moving average"); return; } SCFloatArrayRef FastMAOuta = MACDZL.Arrays[2]; SCFloatArrayRef FastMAOutb = MACDZL.Arrays[3]; SCFloatArrayRef SlowMAOuta = MACDZL.Arrays[4]; SCFloatArrayRef SlowMAOutb = MACDZL.Arrays[5]; SCFloatArrayRef FastMAOutc = MACDZL.Arrays[6]; SCFloatArrayRef SlowMAOutc = MACDZL.Arrays[7]; switch (Zerolag.GetIndex()) { //DEMA case case 0 : sc.ExponentialMovAvg(sc.BaseDataIn[InputData.GetInputDataIndex()], FastMAOuta, sc.Index, FastLength.GetInt()); sc.ExponentialMovAvg(FastMAOuta, FastMAOutb, sc.Index, FastLength.GetInt()); FastMAOut[sc.Index] = 2 * FastMAOuta[sc.Index] - FastMAOutb[sc.Index]; sc.ExponentialMovAvg(sc.BaseDataIn[InputData.GetInputDataIndex()], SlowMAOuta, sc.Index, SlowLength.GetInt()); sc.ExponentialMovAvg(SlowMAOuta, SlowMAOutb, sc.Index, SlowLength.GetInt()); SlowMAOut[sc.Index] = 2 * SlowMAOuta[sc.Index] - SlowMAOutb[sc.Index]; MACDZL[sc.Index] = FastMAOut[sc.Index] - SlowMAOut[sc.Index]; sc.ExponentialMovAvg(MACDZL, MovAvgOfMACDZLa, sc.Index, MACDLength.GetInt()); sc.ExponentialMovAvg(MovAvgOfMACDZLa, MovAvgOfMACDZLb, sc.Index, MACDLength.GetInt()); MovAvgOfMACDZL[sc.Index] = 2 * MovAvgOfMACDZLa[sc.Index] - MovAvgOfMACDZLb[sc.Index]; break; //TEMA case case 1 : sc.ExponentialMovAvg(sc.BaseDataIn[InputData.GetInputDataIndex()], FastMAOuta, sc.Index, FastLength.GetInt()); sc.ExponentialMovAvg(FastMAOuta, FastMAOutb, sc.Index, FastLength.GetInt()); sc.ExponentialMovAvg(FastMAOutb, FastMAOutc, sc.Index, FastLength.GetInt()); FastMAOut[sc.Index] = 3 * FastMAOuta[sc.Index] - 3* FastMAOutb[sc.Index] + FastMAOutc[sc.Index]; sc.ExponentialMovAvg(sc.BaseDataIn[InputData.GetInputDataIndex()], SlowMAOuta, sc.Index, SlowLength.GetInt()); sc.ExponentialMovAvg(SlowMAOuta, SlowMAOutb, sc.Index, SlowLength.GetInt()); sc.ExponentialMovAvg(SlowMAOutb, SlowMAOutc, sc.Index, SlowLength.GetInt()); SlowMAOut[sc.Index] = 3 * SlowMAOuta[sc.Index] - 3*SlowMAOutb[sc.Index] + SlowMAOutc[sc.Index]; MACDZL[sc.Index] = FastMAOut[sc.Index] - SlowMAOut[sc.Index]; sc.ExponentialMovAvg(MACDZL, MovAvgOfMACDZLa, sc.Index, MACDLength.GetInt()); sc.ExponentialMovAvg(MovAvgOfMACDZLa, MovAvgOfMACDZLb, sc.Index, MACDLength.GetInt()); sc.ExponentialMovAvg(MovAvgOfMACDZLb, MovAvgOfMACDZLc, sc.Index, MACDLength.GetInt()); MovAvgOfMACDZL[sc.Index] = 3 * MovAvgOfMACDZLa[sc.Index] - 3 * MovAvgOfMACDZLb[sc.Index] + MovAvgOfMACDZLb[sc.Index]; break; } MACDZLDiff[sc.Index] = MACDZL[sc.Index] - MovAvgOfMACDZL[sc.Index]; RefLine[sc.Index] = 0; }