Page 18 of 18

Re: Free SMC Trading Setups

Posted: Thu Oct 01, 2026 5:01 pm
by PTScalper
How to Install & Optimize

1.) Open your MetaTrader terminal.

2.) Press F4 to open the MetaEditor.

3.) In the Navigator on the left, right-click Indicators -> New File -> Custom Indicator.

4.) Paste the appropriate code above, replacing all existing template code.

5.) Click Compile at the top. Ensure there are 0 errors in the bottom log.

6.) Attach it to a 4H or Daily Chart.

Performance Note: Both versions are optimized to calculate only on the close of a bar (IsNewBar logic). Checking for swing points on every single live tick crushes MetaTrader's CPU. By running the logic when the candle closes, your terminal stays incredibly fast while accurately printing mitigated levels and Breaker Blocks.

Re: Free SMC Trading Setups

Posted: Thu Oct 01, 2026 5:04 pm
by PTScalper
To elevate this indicator to a true Institutional-Grade (Pro) level, we need to move beyond simply identifying swing highs and lows. A professional algorithm filters out the noise by verifying institutional participation, manages terminal memory to prevent lag, and routes alerts directly to your phone.

Here are the three major upgrades added to this "Pro" version:

Displacement (Momentum) Filter: Retail traders map every single swing. Institutions only care about swings that caused a massive imbalance in the market. The algorithm now calculates the average candle body size dynamically. A zone is only created if the move away from the pivot is at least 1.5x larger than the average candle (proving institutional volume stepped in).

Garbage Collection & Memory Management: Amateurs let their indicators draw 5,000 objects, lagging their MT4/MT5 terminals. This pro version includes a strict garbage collector. When a zone (or Breaker Block) is fully mitigated and no longer relevant, the algorithm automatically deletes the graphical object from your chart to free up memory.

Full Alert Suite: Added Push Notifications (to the MetaTrader mobile app) and Email alerts, so you can map your Daily/4H charts on your VPS and get pinged on your phone only when price taps a high-probability institutional POI.

Re: Free SMC Trading Setups

Posted: Thu Oct 01, 2026 5:04 pm
by PTScalper
Here is the ultimate Pro version for both platforms.

1. MetaTrader 4 (MQL4) Pro Version
Save as Pro_Institutional_Zones.mq4 in MQL4/Indicators.

Code: Select all

//+------------------------------------------------------------------+
//|                                      Pro_Institutional_Zones.mq4 |
//|                SMC Zones + Displacement Filter + Push Alerts     |
//+------------------------------------------------------------------+
#property strict
#property indicator_chart_window

//--- Professional Inputs
input string   ___SMC_SETTINGS___ = "--- Zone Settings ---";
input int      LeftLen          = 20;            // Pivot Lookback (Left)
input int      RightLen         = 15;            // Pivot Lookback (Right)
input double   DisplacementMult = 1.5;           // Momentum Multiplier (1.5x avg body)
input bool     ShowBreakers     = true;          // Enable Breaker Blocks

input string   ___STYLE___        = "--- Visual Settings ---";
input color    ColorSup         = clrMediumSeaGreen; // Support POI
input color    ColorRes         = clrCrimson;        // Resistance POI
input color    ColorBrkSup      = clrDodgerBlue;     // Breaker (Res -> Sup)
input color    ColorBrkRes      = clrDarkOrange;     // Breaker (Sup -> Res)

input string   ___ALERTS___       = "--- Alert Suite ---";
input bool     UsePopUp         = true;          // Terminal Pop-up Alert
input bool     UsePush          = false;         // Send to Mobile App
input bool     UseEmail         = false;         // Send Email

//--- Zone Tracking Structure
struct Zone {
    string name;
    double top;
    double bot;
    bool   isSup;
    bool   isActive;
    bool   isBreaker;
};

Zone activeZones[];
datetime lastBarTime = 0;

//+------------------------------------------------------------------+
int OnInit() {
    ObjectsDeleteAll(0, "SMC_PRO_"); 
    return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason) {
    ObjectsDeleteAll(0, "SMC_PRO_");
}

//--- Advanced Alert Manager
void TriggerAlert(string message) {
    string prefix = "[" + Symbol() + " " + EnumToString((ENUM_TIMEFRAMES)Period()) + "] ";
    if(UsePopUp) Alert(prefix + message);
    if(UsePush)  SendNotification(prefix + message);
    if(UseEmail) SendMail("SMC Institutional Alert", prefix + message);
}

//--- Rectangle Manager
void DrawZone(string name, datetime t1, double p1, datetime t2, double p2, color clr) {
    if(ObjectFind(0, name) < 0) {
        ObjectCreate(0, name, OBJ_RECTANGLE, 0, t1, p1, t2, p2);
        ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
        ObjectSetInteger(0, name, OBJPROP_BACK, true); 
        ObjectSetInteger(0, name, OBJPROP_FILL, true); 
    } else {
        ObjectSetInteger(0, name, OBJPROP_TIME2, t2); 
    }
}

//--- Pro Displacement Filter (Checks if institutions stepped in)
bool HasDisplacement(int index) {
    double avgBody = 0;
    for(int i=1; i<=15; i++) {
        if(index+i < Bars) avgBody += MathAbs(Open[index+i] - Close[index+i]);
    }
    avgBody /= 15.0;
    
    // Check if the candle moving away from the pivot is significantly larger than average
    double moveAwayBody = MathAbs(Open[index-1] - Close[index-1]);
    return (moveAwayBody > (avgBody * DisplacementMult));
}

bool IsPivotHigh(int index) {
    double val = High[index];
    for(int i=1; i<=LeftLen; i++)  if(index+i < Bars && High[index+i] > val) return false;
    for(int i=1; i<=RightLen; i++) if(index-i >= 0 && High[index-i] >= val) return false;
    return HasDisplacement(index); // Must have momentum!
}

bool IsPivotLow(int index) {
    double val = Low[index];
    for(int i=1; i<=LeftLen; i++)  if(index+i < Bars && Low[index+i] < val) return false;
    for(int i=1; i<=RightLen; i++) if(index-i >= 0 && Low[index-i] <= val) return false;
    return HasDisplacement(index); // Must have momentum!
}

//+------------------------------------------------------------------+
int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) {
    
    if(Time[0] == lastBarTime) return(rates_total);
    lastBarTime = Time[0];

    int limit = MathMax(rates_total - prev_calculated, RightLen + 1);
    datetime futureTime = Time[0] + PeriodSeconds() * 50; 

    // 1. Process active zones
    for(int i = ArraySize(activeZones) - 1; i >= 0; i--) {
        if(activeZones[i].isActive) {
            bool brokenUp = Close[1] > activeZones[i].top;
            bool brokenDn = Close[1] < activeZones[i].bot;

            if((activeZones[i].isSup && brokenDn) || (!activeZones[i].isSup && brokenUp)) {
                
                activeZones[i].isActive = false;
                
                if(!activeZones[i].isBreaker) {
                    TriggerAlert("Institutional POI Mitigated at " + DoubleToStr(Close[1], Digits));
                }

                if(ShowBreakers && !activeZones[i].isBreaker) {
                    // Turn into Breaker Block
                    DrawZone(activeZones[i].name, 0, activeZones[i].top, Time[0], activeZones[i].bot, clrNONE); // Stop old box
                    
                    int size = ArraySize(activeZones);
                    ArrayResize(activeZones, size + 1);
                    bool newIsSup = !activeZones[i].isSup;
                    activeZones[size].name = "SMC_PRO_BRK_" + IntegerToString(Time[0]);
                    activeZones[size].top = activeZones[i].top;
                    activeZones[size].bot = activeZones[i].bot;
                    activeZones[size].isSup = newIsSup;
                    activeZones[size].isActive = true;
                    activeZones[size].isBreaker = true;
                    
                    color clr = newIsSup ? ColorBrkSup : ColorBrkRes;
                    DrawZone(activeZones[size].name, Time[1], activeZones[size].top, futureTime, activeZones[size].bot, clr);
                } else {
                    // Garbage Collection: Completely remove mitigated breakers or if breakers are off
                    ObjectDelete(0, activeZones[i].name);
                }
            } else {
                ObjectSetInteger(0, activeZones[i].name, OBJPROP_TIME2, futureTime);
            }
        }
    }

    // 2. Scan for new Swing Points
    for(int i = limit; i >= RightLen; i--) {
        if(IsPivotHigh(i)) {
            int size = ArraySize(activeZones);
            ArrayResize(activeZones, size + 1);
            activeZones[size].name = "SMC_PRO_RES_" + IntegerToString(Time[i]);
            activeZones[size].top = High[i];
            activeZones[size].bot = MathMax(Close[i], Open[i]);
            activeZones[size].isSup = false;
            activeZones[size].isActive = true;
            activeZones[size].isBreaker = false;
            
            DrawZone(activeZones[size].name, Time[i], activeZones[size].top, futureTime, activeZones[size].bot, ColorRes);
        }
        if(IsPivotLow(i)) {
            int size = ArraySize(activeZones);
            ArrayResize(activeZones, size + 1);
            activeZones[size].name = "SMC_PRO_SUP_" + IntegerToString(Time[i]);
            activeZones[size].top = MathMin(Close[i], Open[i]);
            activeZones[size].bot = Low[i];
            activeZones[size].isSup = true;
            activeZones[size].isActive = true;
            activeZones[size].isBreaker = false;
            
            DrawZone(activeZones[size].name, Time[i], activeZones[size].top, futureTime, activeZones[size].bot, ColorSup);
        }
    }
    return(rates_total);
}

Re: Free SMC Trading Setups

Posted: Thu Oct 01, 2026 5:05 pm
by PTScalper
2. MetaTrader 5 (MQL5) Pro Version

Save as Pro_Institutional_Zones.mq5 in MQL5/Indicators. This version implements strict array-as-series handling to ensure the mathematical algorithms run perfectly in MT5's architecture.

Code: Select all

//+------------------------------------------------------------------+
//|                                      Pro_Institutional_Zones.mq5 |
//|                SMC Zones + Displacement Filter + Push Alerts     |
//+------------------------------------------------------------------+
#property indicator_chart_window
#property indicator_buffers 0
#property indicator_plots   0

//--- Professional Inputs
input string   ___SMC_SETTINGS___ = "--- Zone Settings ---";
input int      LeftLen          = 20;            
input int      RightLen         = 15;            
input double   DisplacementMult = 1.5;           
input bool     ShowBreakers     = true;          

input string   ___STYLE___        = "--- Visual Settings ---";
input color    ColorSup         = clrMediumSeaGreen; 
input color    ColorRes         = clrCrimson;        
input color    ColorBrkSup      = clrDodgerBlue;     
input color    ColorBrkRes      = clrDarkOrange;     

input string   ___ALERTS___       = "--- Alert Suite ---";
input bool     UsePopUp         = true;          
input bool     UsePush          = false;         
input bool     UseEmail         = false;         

struct Zone {
    string name;
    double top;
    double bot;
    bool   isSup;
    bool   isActive;
    bool   isBreaker;
};

Zone activeZones[];
datetime lastBarTime = 0;

int OnInit() {
    ObjectsDeleteAll(0, "SMC_PRO_"); 
    return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason) {
    ObjectsDeleteAll(0, "SMC_PRO_");
}

void TriggerAlert(string message) {
    string prefix = "[" + Symbol() + " " + EnumToString((ENUM_TIMEFRAMES)Period()) + "] ";
    if(UsePopUp) Alert(prefix + message);
    if(UsePush)  SendNotification(prefix + message);
    if(UseEmail) SendMail("SMC Institutional Alert", prefix + message);
}

void DrawZone(string name, datetime t1, double p1, datetime t2, double p2, color clr) {
    if(ObjectFind(0, name) < 0) {
        ObjectCreate(0, name, OBJ_RECTANGLE, 0, t1, p1, t2, p2);
        ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
        ObjectSetInteger(0, name, OBJPROP_BGCOLOR, clr);
        ObjectSetInteger(0, name, OBJPROP_BACK, true); 
        ObjectSetInteger(0, name, OBJPROP_FILL, true); 
    } else {
        ObjectSetInteger(0, name, OBJPROP_TIME2, t2); 
    }
}

bool HasDisplacement(int index, const double &o[], const double &c[]) {
    double avgBody = 0;
    int limit = ArraySize(o);
    for(int i=1; i<=15; i++) {
        if(index+i < limit) avgBody += MathAbs(o[index+i] - c[index+i]);
    }
    avgBody /= 15.0;
    
    double moveAwayBody = MathAbs(o[index-1] - c[index-1]);
    return (moveAwayBody > (avgBody * DisplacementMult));
}

bool IsPivotHigh(int index, const double &h[], const double &o[], const double &c[]) {
    double val = h[index];
    for(int i=1; i<=LeftLen; i++)  if(index+i < ArraySize(h) && h[index+i] > val) return false;
    for(int i=1; i<=RightLen; i++) if(index-i >= 0 && h[index-i] >= val) return false;
    return HasDisplacement(index, o, c);
}

bool IsPivotLow(int index, const double &l[], const double &o[], const double &c[]) {
    double val = l[index];
    for(int i=1; i<=LeftLen; i++)  if(index+i < ArraySize(l) && l[index+i] < val) return false;
    for(int i=1; i<=RightLen; i++) if(index-i >= 0 && l[index-i] <= val) return false;
    return HasDisplacement(index, o, c);
}

int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) {
    
    ArraySetAsSeries(time, true);
    ArraySetAsSeries(open, true);
    ArraySetAsSeries(high, true);
    ArraySetAsSeries(low, true);
    ArraySetAsSeries(close, true);

    if(rates_total < LeftLen + RightLen + 15) return(0);
    if(time[0] == lastBarTime) return(rates_total);
    lastBarTime = time[0];

    int limit = prev_calculated == 0 ? rates_total - LeftLen - 16 : MathMax(rates_total - prev_calculated, RightLen + 1);
    datetime futureTime = time[0] + PeriodSeconds() * 50; 

    // 1. Process active zones & Garbage Collection
    for(int i = ArraySize(activeZones) - 1; i >= 0; i--) {
        if(activeZones[i].isActive) {
            bool brokenUp = close[1] > activeZones[i].top;
            bool brokenDn = close[1] < activeZones[i].bot;

            if((activeZones[i].isSup && brokenDn) || (!activeZones[i].isSup && brokenUp)) {
                
                activeZones[i].isActive = false;
                
                if(!activeZones[i].isBreaker) {
                    TriggerAlert("Institutional POI Mitigated!");
                }

                if(ShowBreakers && !activeZones[i].isBreaker) {
                    DrawZone(activeZones[i].name, 0, activeZones[i].top, time[0], activeZones[i].bot, clrNONE); 
                    
                    int size = ArraySize(activeZones);
                    ArrayResize(activeZones, size + 1);
                    bool newIsSup = !activeZones[i].isSup;
                    activeZones[size].name = "SMC_PRO_BRK_" + IntegerToString(time[0]);
                    activeZones[size].top = activeZones[i].top;
                    activeZones[size].bot = activeZones[i].bot;
                    activeZones[size].isSup = newIsSup;
                    activeZones[size].isActive = true;
                    activeZones[size].isBreaker = true;
                    
                    color clr = newIsSup ? ColorBrkSup : ColorBrkRes;
                    DrawZone(activeZones[size].name, time[1], activeZones[size].top, futureTime, activeZones[size].bot, clr);
                } else {
                    ObjectDelete(0, activeZones[i].name); // Strict Memory Cleanup
                }
            } else {
                ObjectSetInteger(0, activeZones[i].name, OBJPROP_TIME2, futureTime);
            }
        }
    }

    // 2. Scan for new Swing Points
    for(int i = limit; i >= RightLen; i--) {
        if(IsPivotHigh(i, high, open, close)) {
            int size = ArraySize(activeZones);
            ArrayResize(activeZones, size + 1);
            activeZones[size].name = "SMC_PRO_RES_" + IntegerToString(time[i]);
            activeZones[size].top = high[i];
            activeZones[size].bot = MathMax(close[i], open[i]);
            activeZones[size].isSup = false;
            activeZones[size].isActive = true;
            activeZones[size].isBreaker = false;
            
            DrawZone(activeZones[size].name, time[i], activeZones[size].top, futureTime, activeZones[size].bot, ColorRes);
        }
        if(IsPivotLow(i, low, open, close)) {
            int size = ArraySize(activeZones);
            ArrayResize(activeZones, size + 1);
            activeZones[size].name = "SMC_PRO_SUP_" + IntegerToString(time[i]);
            activeZones[size].top = MathMin(close[i], open[i]);
            activeZones[size].bot = low[i];
            activeZones[size].isSup = true;
            activeZones[size].isActive = true;
            activeZones[size].isBreaker = false;
            
            DrawZone(activeZones[size].name, time[i], activeZones[size].top, futureTime, activeZones[size].bot, ColorSup);
        }
    }
    return(rates_total);
}

Re: Free SMC Trading Setups

Posted: Thu Oct 01, 2026 5:05 pm
by PTScalper
Pro Tuning Guide:

The 1.5x Rule (DisplacementMult): The default setting requires the breakout candle to be 1.5x larger than the recent average candle. If you are trading a highly volatile asset like Gold or BTC, you might want to raise this to 2.0 to filter out minor swings and only catch massive algorithmic buying/selling.

VPS Workflow: Install this on a 4-Hour chart on a Virtual Private Server (VPS). Turn on UsePush (ensure your MetaQuotes ID is set up in MT4/MT5 Tools > Options > Notifications). You can now close your laptop. You will receive a mobile push notification the exact minute institutional liquidity is breached or mitigated.

Re: Free SMC Trading Setups

Posted: Thu Oct 01, 2026 5:06 pm
by PTScalper
Translating this institutional algorithm to cTrader (cAlgo / C#) requires adapting to the .NET framework and cTrader’s specific rendering engine.

cTrader is exceptionally powerful for this type of logic because it handles object-oriented programming (OOP) natively. We can treat our Zones and Breaker Blocks as true C# objects, dynamically updating their future projections (Time2) and smoothly handling memory garbage collection.

Here is the Institutional-Grade SMC Zones & Breakers indicator, perfectly translated and optimized for cTrader.

Re: Free SMC Trading Setups

Posted: Thu Oct 01, 2026 5:07 pm
by PTScalper
How to Install in cTrader:

1.) Open cTrader and go to the Automate tab (on the left panel).

2.) Expand Indicators, click New, and name it ProSMCZones.

3.) Delete the default template code.

4.) Paste the C# code below.

5.) Click Build (or press F6). Once built, you can add it to any chart.

Code: Select all

using System;
using System.Collections.Generic;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;

namespace cAlgo.Indicators
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class ProSMCZones : Indicator
    {
        // ==============================================================================
        // PROFESSIONAL INPUTS
        // ==============================================================================
        [Parameter("Pivot Lookback (Left)", Group = "Institutional Logic", DefaultValue = 20, MinValue = 5)]
        public int LeftLen { get; set; }

        [Parameter("Pivot Lookback (Right)", Group = "Institutional Logic", DefaultValue = 15, MinValue = 5)]
        public int RightLen { get; set; }

        [Parameter("Displacement Filter (x Avg Body)", Group = "Institutional Logic", DefaultValue = 1.5, MinValue = 1.0)]
        public double DisplacementMult { get; set; }

        [Parameter("Show Breaker Blocks", Group = "Institutional Logic", DefaultValue = true)]
        public bool ShowBreakers { get; set; }

        // ==============================================================================
        // VISUAL SETTINGS
        // ==============================================================================
        [Parameter("Support POI", Group = "Style", DefaultValue = "MediumSeaGreen")]
        public string SupColorStr { get; set; }

        [Parameter("Resistance POI", Group = "Style", DefaultValue = "Crimson")]
        public string ResColorStr { get; set; }

        [Parameter("Breaker (Res -> Sup)", Group = "Style", DefaultValue = "DodgerBlue")]
        public string BrkSupColorStr { get; set; }

        [Parameter("Breaker (Sup -> Res)", Group = "Style", DefaultValue = "DarkOrange")]
        public string BrkResColorStr { get; set; }

        [Parameter("Zone Opacity (0-255)", Group = "Style", DefaultValue = 70, MinValue = 10, MaxValue = 255)]
        public int Opacity { get; set; }

        // ==============================================================================
        // ALERTS
        // ==============================================================================
        [Parameter("Use Terminal Sound", Group = "Alerts", DefaultValue = true)]
        public bool UseSound { get; set; }

        [Parameter("Send Email", Group = "Alerts", DefaultValue = false)]
        public bool UseEmail { get; set; }

        // ==============================================================================
        // ZONE STRUCTURE & CACHE
        // ==============================================================================
        private class Zone
        {
            public string Name;
            public double Top;
            public double Bot;
            public bool IsSup;
            public bool IsActive;
            public bool IsBreaker;
            public ChartRectangle ChartObj;
        }

        private List<Zone> _activeZones = new List<Zone>();
        private int _lastProcessedIndex = -1;
        private TimeSpan _barDuration;

        protected override void Initialize()
        {
            // Clean up any old objects if indicator is reloaded
            var existingRects = Chart.FindAllObjects(ChartObjectType.Rectangle);
            foreach (var obj in existingRects)
            {
                if (obj.Name.StartsWith("SMC_PRO_")) Chart.RemoveObject(obj.Name);
            }
        }

        public override void Calculate(int index)
        {
            // Only process logic when a candle fully CLOSES to save CPU and avoid repainting
            if (index <= _lastProcessedIndex) return;

            // Target the most recently closed candle
            int closedIndex = index - 1;
            if (closedIndex < LeftLen + 20) return; // Wait for enough data to calculate displacement

            _lastProcessedIndex = index;

            // Dynamically calculate timeframe duration to project zones accurately into the future
            _barDuration = Bars.OpenTimes[index] - Bars.OpenTimes[index - 1];
            DateTime futureTime = Bars.OpenTimes[index].Add(TimeSpan.FromTicks(_barDuration.Ticks * 50));

            // ==============================================================================
            // 1. MITIGATION & GARBAGE COLLECTION
            // ==============================================================================
            for (int i = _activeZones.Count - 1; i >= 0; i--)
            {
                var zone = _activeZones[i];
                if (!zone.IsActive) continue;

                bool brokenUp = Bars.ClosePrices[closedIndex] > zone.Top;
                bool brokenDn = Bars.ClosePrices[closedIndex] < zone.Bot;

                if ((zone.IsSup && brokenDn) || (!zone.IsSup && brokenUp))
                {
                    // Zone Mitigated!
                    zone.IsActive = false;
                    
                    // Alert Logic (Only alert on raw institutional levels, not breakers)
                    if (!zone.IsBreaker && IsRealTime)
                    {
                        string msg = string.Format("[{0} {1}] Institutional POI Mitigated at {2}", 
                            SymbolName, TimeFrame.ToString(), Bars.ClosePrices[closedIndex]);
                        Print(msg);
                        if (UseSound) Notifications.PlaySound(SoundType.Doorbell);
                        if (UseEmail) Notifications.SendEmail("sender@email.com", "receiver@email.com", "SMC Alert", msg);
                    }

                    if (ShowBreakers && !zone.IsBreaker)
                    {
                        // Spawn a Breaker Block
                        Chart.RemoveObject(zone.Name); // Remove the old mitigated zone
                        
                        bool newIsSup = !zone.IsSup;
                        string newName = "SMC_PRO_BRK_" + closedIndex;
                        Color baseClr = Color.FromName(newIsSup ? BrkSupColorStr : BrkResColorStr);
                        Color fillClr = Color.FromArgb(Opacity, baseClr);

                        var rect = Chart.DrawRectangle(newName, Bars.OpenTimes[closedIndex], zone.Top, futureTime, zone.Bot, fillClr);
                        rect.IsFilled = true;
                        rect.Thickness = 1;
                        rect.Color = baseClr;

                        _activeZones.Add(new Zone {
                            Name = newName, Top = zone.Top, Bot = zone.Bot, IsSup = newIsSup, 
                            IsActive = true, IsBreaker = true, ChartObj = rect
                        });
                    }
                    else
                    {
                        // Strict Memory Management: Remove mitigated breakers and unwanted objects entirely
                        Chart.RemoveObject(zone.Name);
                    }

                    // Remove the old zone reference from the active array to save RAM
                    _activeZones.RemoveAt(i);
                }
                else
                {
                    // Keep projecting active zones into the future
                    zone.ChartObj.Time2 = futureTime;
                }
            }

            // ==============================================================================
            // 2. SCAN FOR NEW SWING PIVOTS
            // ==============================================================================
            int pivotIndex = closedIndex - RightLen;

            if (IsPivotHigh(pivotIndex))
            {
                double top = Bars.HighPrices[pivotIndex];
                double bot = Math.Max(Bars.ClosePrices[pivotIndex], Bars.OpenPrices[pivotIndex]);
                string name = "SMC_PRO_RES_" + pivotIndex;
                
                Color baseClr = Color.FromName(ResColorStr);
                Color fillClr = Color.FromArgb(Opacity, baseClr);

                var rect = Chart.DrawRectangle(name, Bars.OpenTimes[pivotIndex], top, futureTime, bot, fillClr);
                rect.IsFilled = true;
                rect.Thickness = 1;
                rect.Color = baseClr; // Outline color

                _activeZones.Add(new Zone { Name = name, Top = top, Bot = bot, IsSup = false, IsActive = true, IsBreaker = false, ChartObj = rect });
            }

            if (IsPivotLow(pivotIndex))
            {
                double bot = Bars.LowPrices[pivotIndex];
                double top = Math.Min(Bars.ClosePrices[pivotIndex], Bars.OpenPrices[pivotIndex]);
                string name = "SMC_PRO_SUP_" + pivotIndex;

                Color baseClr = Color.FromName(SupColorStr);
                Color fillClr = Color.FromArgb(Opacity, baseClr);

                var rect = Chart.DrawRectangle(name, Bars.OpenTimes[pivotIndex], top, futureTime, bot, fillClr);
                rect.IsFilled = true;
                rect.Thickness = 1;
                rect.Color = baseClr; // Outline color

                _activeZones.Add(new Zone { Name = name, Top = top, Bot = bot, IsSup = true, IsActive = true, IsBreaker = false, ChartObj = rect });
            }
        }

        // ==============================================================================
        // INSTITUTIONAL DISPLACEMENT LOGIC
        // ==============================================================================
        private bool HasDisplacement(int pivotIndex)
        {
            double avgBody = 0;
            for (int i = 1; i <= 15; i++)
            {
                int pastIdx = pivotIndex - i;
                avgBody += Math.Abs(Bars.OpenPrices[pastIdx] - Bars.ClosePrices[pastIdx]);
            }
            avgBody /= 15.0;
            
            // The candle immediately following the pivot (the push away)
            int moveIdx = pivotIndex + 1;
            double moveAwayBody = Math.Abs(Bars.OpenPrices[moveIdx] - Bars.ClosePrices[moveIdx]);
            
            // Only validates if institutional volume pushed the price away violently
            return moveAwayBody > (avgBody * DisplacementMult);
        }

        private bool IsPivotHigh(int index)
        {
            double val = Bars.HighPrices[index];
            for (int i = 1; i <= LeftLen; i++)  if (Bars.HighPrices[index - i] > val) return false;
            for (int i = 1; i <= RightLen; i++) if (Bars.HighPrices[index + i] >= val) return false;
            return HasDisplacement(index);
        }

        private bool IsPivotLow(int index)
        {
            double val = Bars.LowPrices[index];
            for (int i = 1; i <= LeftLen; i++)  if (Bars.LowPrices[index - i] < val) return false;
            for (int i = 1; i <= RightLen; i++) if (Bars.LowPrices[index + i] <= val) return false;
            return HasDisplacement(index);
        }
    }
}

Re: Free SMC Trading Setups

Posted: Thu Oct 01, 2026 5:08 pm
by PTScalper
Pro cTrader Features Included:

Dynamic Time Projection: Unlike basic MT4 objects, cTrader relies heavily on exact DateTime coordinates. This script dynamically calculates the duration of the current timeframe's candles (15m, 4H, Daily) and elegantly projects the active zones exactly 50 bars into the future so they always hover gracefully on the right edge of your screen.

True Memory Release: When a Breaker Block is finally mitigated (broken through), it doesn't just turn invisible. The script executes Chart.RemoveObject() and physically drops the reference from the C# List<>, preventing your RAM footprint from bloating if you leave the platform running for weeks on a VPS.

Alpha Opacity Blending: cTrader supports advanced rendering. We use Color.FromArgb(Opacity, baseClr) to fill the zones with beautiful transparency (default 70/255) while keeping a sharp, solid 1-pixel border for precision entry marking.