//── 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. . */