//── Project ─────────────────────────────────────────────────────────────────────
/*
Name:
Version:
Date:
Repository: Available @ https://fxcodebase.com/code/viewtopic.php?f=38&t=76343
License: GNU
*/
// ── Author ──────────────────────────────────────────────────────────────────────
/*
Developed by: Mario Jemic
Email: mario.jemic@gmail.com
Website: https://mario-jemic.com
*/
// ── Support & Donations ─────────────────────────────────────────────────────────
/*
PayPal: https://goo.gl/9Rj74e
Patreon: https://tiny.cc/1ybwxz
BuyMeACoffee:https://tiny.cc/bj7vxz
Crypto:
BTC : 16F5k43RXibTmna4np8bPVgmXM1CzjXFJJ
SOL : 3nh5rpUKopcYLNU4zGCdUFAkM3iRQq8VVUmuzVG6VDf2
ETH/BNB/USDT/XRP (ERC20/BEP20): 0xe53aab6bc468a963a02d1319660ee60cf80fc8e7
*/
// ── Copyright ───────────────────────────────────────────────────────────────────
/*
© 2025 Gehtsoft USA LLC — https://fxcodebase.com
*/
/* This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
.
*/
// MQL properties
#property copyright "© 2025 Gehtsoft USA LLC"
#property link "https://fxcodebase.com"
#property version "1.0"
#property indicator_chart_window
#property indicator_buffers 8
#property indicator_color1 Red
#property indicator_color2 Red
#property indicator_color3 Silver
#property indicator_color4 Silver
#property indicator_color5 Gold
#property indicator_color6 Gold
#property indicator_color7 Purple
#property indicator_color8 Purple
//---- input parameters for trendlines
extern bool EnableTrendlines = true;
extern bool EnableAlerts = true;
extern int TrendlineWidth = 1;
//---- input parameters
extern double Period1=5;
extern double Period2=8;
extern double Period3=13;
extern double Period4=34;
extern string Dev_Step_1="3,1";
extern string Dev_Step_2="5,3";
extern string Dev_Step_3="8,5";
extern string Dev_Step_4="13,8";
extern int Symbol_1_Kod=117;
extern int Symbol_2_Kod=117;
extern int Symbol_3U_Kod=117;
extern int Symbol_3D_Kod=117;
extern int Symbol_4U_Kod=233;
extern int Symbol_4D_Kod=234;
//---- buffers
double NP_BuferUp[];
double NP_BuferDn[];
double HP_BuferUp[];
double HP_BuferDn[];
double GP_BuferUp[];
double GP_BuferDn[];
double PP_BuferUp[];
double PP_BuferDn[];
int N_Period;
int H_Period;
int G_Period;
int P_Period;
int Dev1;
int Stp1;
int Dev2;
int Stp2;
int Dev3;
int Stp3;
int Dev4;
int Stp4;
//---- Global variables for trendlines
int LastPurpleUp = -1;
int LastPurpleDn = -1;
int LastGoldUp = -1;
int LastGoldDn = -1;
int LastSilverUp = -1;
int LastSilverDn = -1;
int LastRedUp = -1;
int LastRedDn = -1;
string TrendlinePrefix = "4LZZ_TL_";
bool IndicatorJustStarted = true;
datetime LastBarTime = 0;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
// --------- Period calculations
if (Period1>0) N_Period=MathCeil(Period1*Period()); else N_Period=0;
if (Period2>0) H_Period=MathCeil(Period2*Period()); else H_Period=0;
if (Period3>0) G_Period=MathCeil(Period3*Period()); else G_Period=0;
if (Period4>0) P_Period=MathCeil(Period4*Period()); else P_Period=0;
//---- Period 1
if (Period1>0)
{
SetIndexStyle(0,DRAW_ARROW,0,2);
SetIndexArrow(0,Symbol_1_Kod);
SetIndexBuffer(0,NP_BuferUp);
SetIndexEmptyValue(0,0.0);
SetIndexStyle(1,DRAW_ARROW,0,2);
SetIndexArrow(1,Symbol_1_Kod);
SetIndexBuffer(1,NP_BuferDn);
SetIndexEmptyValue(1,0.0);
}
//---- Period 2
if (Period2>0)
{
SetIndexStyle(2,DRAW_ARROW,0,4);
SetIndexArrow(2,Symbol_2_Kod);
SetIndexBuffer(2,HP_BuferUp);
SetIndexEmptyValue(2,0.0);
SetIndexStyle(3,DRAW_ARROW,0,4);
SetIndexArrow(3,Symbol_2_Kod);
SetIndexBuffer(3,HP_BuferDn);
SetIndexEmptyValue(3,0.0);
}
//---- Period 3
if (Period3>0)
{
SetIndexStyle(4,DRAW_ARROW,0,3);
SetIndexArrow(4,Symbol_3U_Kod);
SetIndexBuffer(4,GP_BuferUp);
SetIndexEmptyValue(4,0.0);
SetIndexStyle(5,DRAW_ARROW,0,3);
SetIndexArrow(5,Symbol_3D_Kod);
SetIndexBuffer(5,GP_BuferDn);
SetIndexEmptyValue(5,0.0);
}
//---- Period 4
if (Period4>0)
{
SetIndexStyle(6,DRAW_ARROW,0,3);
SetIndexArrow(6,Symbol_4U_Kod);
SetIndexBuffer(6,PP_BuferUp);
SetIndexEmptyValue(6,0.0);
SetIndexStyle(7,DRAW_ARROW,0,3);
SetIndexArrow(7,Symbol_4D_Kod);
SetIndexBuffer(7,PP_BuferDn);
SetIndexEmptyValue(7,0.0);
}
// Deviation and Backstep
int CDev=0;
int CSt=0;
int Mass[];
int C=0;
if (IntFromStr(Dev_Step_1,C, Mass)==1)
{
Stp1=Mass[1];
Dev1=Mass[0];
}
if (IntFromStr(Dev_Step_2,C, Mass)==1)
{
Stp2=Mass[1];
Dev2=Mass[0];
}
if (IntFromStr(Dev_Step_3,C, Mass)==1)
{
Stp3=Mass[1];
Dev3=Mass[0];
}
if (IntFromStr(Dev_Step_4,C, Mass)==1)
{
Stp4=Mass[1];
Dev4=Mass[0];
}
return(0);
}
//+------------------------------------------------------------------+
//| Custor indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----
// Delete all trendlines created by this indicator
DeleteAllTrendlines();
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
// Only process on new bar
if(Time[0] == LastBarTime)
{
return(0);
}
LastBarTime = Time[0];
if (Period1>0) CountZZ(NP_BuferUp,NP_BuferDn,Period1,Dev1,Stp1);
if (Period2>0) CountZZ(HP_BuferUp,HP_BuferDn,Period2,Dev2,Stp2);
if (Period3>0) CountZZ(GP_BuferUp,GP_BuferDn,Period3,Dev3,Stp3);
if (Period4>0) CountZZ(PP_BuferUp,PP_BuferDn,Period4,Dev4,Stp4);
if (EnableTrendlines)
{
CheckAndDrawTrendlines();
}
// After first run, allow alerts for new triggers only
if (IndicatorJustStarted)
{
IndicatorJustStarted = false;
}
return(0);
}
//+------------------------------------------------------------------+
//
//int Take
//+------------------------------------------------------------------+
//| Calculations for each ZZ Level |
//+------------------------------------------------------------------+
int CountZZ( double& ExtMapBuffer[], double& ExtMapBuffer2[], int ExtDepth, int ExtDeviation, int ExtBackstep )
{
int shift, back,lasthighpos,lastlowpos;
double val,res;
double curlow,curhigh,lasthigh,lastlow;
for(shift=Bars-ExtDepth; shift>=0; shift--)
{
val=Low[Lowest(NULL,0,MODE_LOW,ExtDepth,shift)];
if(val==lastlow) val=0.0;
else
{
lastlow=val;
if((Low[shift]-val)>(ExtDeviation*Point)) val=0.0;
else
{
for(back=1; back<=ExtBackstep; back++)
{
res=ExtMapBuffer[shift+back];
if((res!=0)&&(res>val)) ExtMapBuffer[shift+back]=0.0;
}
}
}
ExtMapBuffer[shift]=val;
//--- high
val=High[Highest(NULL,0,MODE_HIGH,ExtDepth,shift)];
if(val==lasthigh) val=0.0;
else
{
lasthigh=val;
if((val-High[shift])>(ExtDeviation*Point)) val=0.0;
else
{
for(back=1; back<=ExtBackstep; back++)
{
res=ExtMapBuffer2[shift+back];
if((res!=0)&&(res=0; shift--)
{
curlow=ExtMapBuffer[shift];
curhigh=ExtMapBuffer2[shift];
if((curlow==0)&&(curhigh==0)) continue;
//---
if(curhigh!=0)
{
if(lasthigh>0)
{
if(lasthigh0)
{
if(lastlow>curlow) ExtMapBuffer[lastlowpos]=0;
else ExtMapBuffer[shift]=0;
}
//---
if((curlow=0; shift--)
{
if(shift>=Bars-ExtDepth) ExtMapBuffer[shift]=0.0;
else
{
res=ExtMapBuffer2[shift];
if(res!=0.0) ExtMapBuffer2[shift]=res;
}
}
return(0);
}
int Str2Massive(string VStr, int& M_Count, int& VMass[])
{
int val=StrToInteger( VStr);
if (val>0)
{
M_Count++;
int mc=ArrayResize(VMass,M_Count);
if (mc==0)return(-1);
VMass[M_Count-1]=val;
return(1);
}
else return(0);
}
int IntFromStr(string ValStr,int& M_Count, int& VMass[])
{
if (StringLen(ValStr)==0) return(-1);
string SS=ValStr;
int NP=0;
string CS;
M_Count=0;
ArrayResize(VMass,M_Count);
while (StringLen(SS)>0)
{
NP=StringFind(SS,",");
if (NP>0)
{
CS=StringSubstr(SS,0,NP);
SS=StringSubstr(SS,NP+1,StringLen(SS));
}
else
{
if (StringLen(SS)>0)
{
CS=SS;
SS="";
}
}
if (Str2Massive(CS,M_Count,VMass)==0)
{
return(-2);
}
}
return(1);
}
//+------------------------------------------------------------------+
//| Check and Draw Trendlines between same level semafors |
//+------------------------------------------------------------------+
void CheckAndDrawTrendlines()
{
// Delete all existing trendlines first to avoid repaint issues
DeleteAllTrendlines();
// Check Purple level (Level 4) - through Silver (Level 2)
CheckTrendlineLevel(PP_BuferUp, PP_BuferDn, HP_BuferUp, HP_BuferDn, "Purple", "Silver", 4);
// Check Gold level (Level 3) - through Red (Level 1)
CheckTrendlineLevel(GP_BuferUp, GP_BuferDn, NP_BuferUp, NP_BuferDn, "Gold", "Red", 3);
// Check Silver level (Level 2) - through Red (Level 1)
CheckTrendlineLevel(HP_BuferUp, HP_BuferDn, NP_BuferUp, NP_BuferDn, "Silver", "Red", 2);
// Red level (Level 1) - temporarily disabled
// CheckTrendlineLevelDirect(NP_BuferUp, NP_BuferDn, "Red", 1);
}
//+------------------------------------------------------------------+
//| Check trendline for specific level |
//+------------------------------------------------------------------+
void CheckTrendlineLevel(double& LevelUp[], double& LevelDn[], double& ThroughUp[], double& ThroughDn[],
string LevelName, string ThroughName, int LevelNum)
{
// Find all valid semafors for this level
int upSemaforBars[];
double upSemaforPrices[];
int dnSemaforBars[];
double dnSemaforPrices[];
// Collect all Up semafors
for(int i = Bars-1; i >= 0; i--)
{
if(LevelUp[i] != 0 && LevelUp[i] != EMPTY_VALUE)
{
int upSize = ArraySize(upSemaforBars);
ArrayResize(upSemaforBars, upSize + 1);
ArrayResize(upSemaforPrices, upSize + 1);
upSemaforBars[upSize] = i;
upSemaforPrices[upSize] = LevelUp[i];
}
}
// Collect all Down semafors
for(int a = Bars-1; a >= 0; a--)
{
if(LevelDn[a] != 0 && LevelDn[a] != EMPTY_VALUE)
{
int dnSize = ArraySize(dnSemaforBars);
ArrayResize(dnSemaforBars, dnSize + 1);
ArrayResize(dnSemaforPrices, dnSize + 1);
dnSemaforBars[dnSize] = a;
dnSemaforPrices[dnSize] = LevelDn[a];
}
}
// Draw trendlines between Up semafors
for(int j = 0; j < ArraySize(upSemaforBars) - 1; j++)
{
DrawTrendlineThroughLevel(upSemaforBars[j], upSemaforBars[j+1],
upSemaforPrices[j], upSemaforPrices[j+1],
ThroughUp, ThroughDn, LevelName + "_Up_" + j, LevelNum);
}
// Draw trendlines between Down semafors
for(int k = 0; k < ArraySize(dnSemaforBars) - 1; k++)
{
DrawTrendlineThroughLevel(dnSemaforBars[k], dnSemaforBars[k+1],
dnSemaforPrices[k], dnSemaforPrices[k+1],
ThroughUp, ThroughDn, LevelName + "_Dn_" + k, LevelNum);
}
}
//+------------------------------------------------------------------+
//| Check trendline for Red level (direct connection) |
//+------------------------------------------------------------------+
void CheckTrendlineLevelDirect(double& LevelUp[], double& LevelDn[], string LevelName, int LevelNum)
{
for(int i = Bars-1; i >= 0; i--)
{
// Check for new Up semafor
if(LevelUp[i] != 0 && LevelUp[i] != EMPTY_VALUE)
{
if(LastRedUp != -1 && LastRedUp != i)
{
DrawDirectTrendline(LastRedUp, i, LevelUp[LastRedUp], LevelUp[i], LevelName + "_Up", LevelNum);
}
LastRedUp = i;
}
// Check for new Down semafor
if(LevelDn[i] != 0 && LevelDn[i] != EMPTY_VALUE)
{
if(LastRedDn != -1 && LastRedDn != i)
{
DrawDirectTrendline(LastRedDn, i, LevelDn[LastRedDn], LevelDn[i], LevelName + "_Dn", LevelNum);
}
LastRedDn = i;
}
}
}
//+------------------------------------------------------------------+
//| Draw direct trendline (no intermediate level) |
//+------------------------------------------------------------------+
void DrawDirectTrendline(int StartBar, int EndBar, double StartPrice, double EndPrice, string LineName, int LevelNum)
{
// Create trendline name
string trendlineName = TrendlinePrefix + LineName + "_" + TimeToStr(Time[StartBar]) + "_" + TimeToStr(Time[EndBar]);
// Delete existing trendline with same name
ObjectDelete(trendlineName);
// Create new trendline
if(ObjectCreate(trendlineName, OBJ_TREND, 0, Time[StartBar], StartPrice, Time[EndBar], EndPrice))
{
ObjectSet(trendlineName, OBJPROP_COLOR, GetLevelColor(LevelNum));
ObjectSet(trendlineName, OBJPROP_STYLE, STYLE_SOLID);
ObjectSet(trendlineName, OBJPROP_WIDTH, TrendlineWidth);
ObjectSet(trendlineName, OBJPROP_RAY_RIGHT, false);
ObjectSet(trendlineName, OBJPROP_RAY_LEFT, false);
}
// Check for trendline break and send alert (only for new triggers)
if(EnableAlerts && !IndicatorJustStarted)
{
CheckTrendlineBreak(trendlineName, StartBar, EndBar, StartPrice, EndPrice, LevelNum);
}
}
//+------------------------------------------------------------------+
//| Draw trendline through intermediate level |
//+------------------------------------------------------------------+
void DrawTrendlineThroughLevel(int StartBar, int EndBar, double StartPrice, double EndPrice,
double& ThroughUp[], double& ThroughDn[], string LineName, int LevelNum)
{
// Find intermediate point through the "through" level
int IntermediateBar = -1;
double IntermediatePrice = 0;
// Look for intermediate semafor between start and end
for(int i = StartBar; i >= EndBar; i--)
{
if(ThroughUp[i] != 0 && ThroughUp[i] != EMPTY_VALUE)
{
IntermediateBar = i;
IntermediatePrice = ThroughUp[i];
break;
}
if(ThroughDn[i] != 0 && ThroughDn[i] != EMPTY_VALUE)
{
IntermediateBar = i;
IntermediatePrice = ThroughDn[i];
break;
}
}
if(IntermediateBar == -1) return; // No intermediate point found
// Create trendline name
string trendlineName = TrendlinePrefix + LineName + "_" + TimeToStr(Time[StartBar]) + "_" + TimeToStr(Time[EndBar]);
// Delete existing trendline with same name
ObjectDelete(trendlineName);
// Create new trendline from start to end (not through intermediate)
if(ObjectCreate(trendlineName, OBJ_TREND, 0, Time[StartBar], StartPrice, Time[EndBar], EndPrice))
{
ObjectSet(trendlineName, OBJPROP_COLOR, GetLevelColor(LevelNum));
ObjectSet(trendlineName, OBJPROP_STYLE, STYLE_SOLID);
ObjectSet(trendlineName, OBJPROP_WIDTH, TrendlineWidth);
ObjectSet(trendlineName, OBJPROP_RAY_RIGHT, false);
ObjectSet(trendlineName, OBJPROP_RAY_LEFT, false);
}
// Check for trendline break and send alert (only for new triggers)
if(EnableAlerts && !IndicatorJustStarted)
{
CheckTrendlineBreak(trendlineName, StartBar, EndBar, StartPrice, EndPrice, LevelNum);
}
}
//+------------------------------------------------------------------+
//| Get color for trendline level |
//+------------------------------------------------------------------+
color GetLevelColor(int LevelNum)
{
switch(LevelNum)
{
case 4: return Purple; // Purple for Level 4
case 3: return Gold; // Gold for Level 3
case 2: return Silver; // Silver for Level 2
case 1: return Red; // Red for Level 1
default: return White;
}
}
//+------------------------------------------------------------------+
//| Check for trendline break and send alert |
//+------------------------------------------------------------------+
void CheckTrendlineBreak(string trendlineName, int StartBar, int EndBar, double StartPrice, double EndPrice, int LevelNum)
{
if(StartBar < 1) return;
// Calculate trendline value at current bar
double slope = (EndPrice - StartPrice) / (EndBar - StartBar);
double trendlineValue = StartPrice + slope * (1 - StartBar);
// Check if price crossed the trendline
bool crossedUp = (Close[1] <= trendlineValue && Close[0] > trendlineValue);
bool crossedDown = (Close[1] >= trendlineValue && Close[0] < trendlineValue);
if(crossedUp || crossedDown)
{
string alertMessage = "4LZZ Alert: Level " + LevelNum + " trendline broken ";
if(crossedUp) alertMessage += "UP";
else alertMessage += "DOWN";
alertMessage += " at " + DoubleToStr(Close[0], Digits);
Alert(alertMessage);
SendNotification(alertMessage);
}
}
//+------------------------------------------------------------------+
//| Delete all trendlines created by this indicator |
//+------------------------------------------------------------------+
void DeleteAllTrendlines()
{
int totalObjects = ObjectsTotal();
for(int i = totalObjects - 1; i >= 0; i--)
{
string objName = ObjectName(i);
// Check if object name starts with our prefix
if(StringFind(objName, TrendlinePrefix) == 0)
{
ObjectDelete(objName);
}
}
}
//── Project ─────────────────────────────────────────────────────────────────────
/*
Name:
Version:
Date:
Repository: Available @ https://fxcodebase.com/code/viewtopic.php?f=38&t=76343
License: GNU
*/
// ── Author ──────────────────────────────────────────────────────────────────────
/*
Developed by: Mario Jemic
Email: mario.jemic@gmail.com
Website: https://mario-jemic.com
*/
// ── Support & Donations ─────────────────────────────────────────────────────────
/*
PayPal: https://goo.gl/9Rj74e
Patreon: https://tiny.cc/1ybwxz
BuyMeACoffee:https://tiny.cc/bj7vxz
Crypto:
BTC : 16F5k43RXibTmna4np8bPVgmXM1CzjXFJJ
SOL : 3nh5rpUKopcYLNU4zGCdUFAkM3iRQq8VVUmuzVG6VDf2
ETH/BNB/USDT/XRP (ERC20/BEP20): 0xe53aab6bc468a963a02d1319660ee60cf80fc8e7
*/
// ── Copyright ───────────────────────────────────────────────────────────────────
/*
© 2025 Gehtsoft USA LLC — https://fxcodebase.com
*/
/* This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
.
*/