IC Markets

ICT Silver Bullet EA MT4, MT5, Ctrader and TradingView

Share, develop, and backtest custom MQL4/MQL5 Expert Advisors, Python data-scraping scripts, trading bots, and automated market alert systems.
PTScalper
Site Admin
Posts: 771
Joined: Mon Jul 20, 2026 1:28 pm

Re: ICT Silver Bullet EA MT4, MT5, Ctrader and TradingView

Post by PTScalper »

3. Execution & Sizing Implementation

Notice the shift from raw functions to object methods (m_account.Balance(), m_symbol.TickValue()).

Code: Select all

bool CSilverManager::IsExecutionSafe() {
    m_symbol.RefreshRates();
    
    int currentSpread = m_symbol.Spread();
    if(currentSpread > InpMaxSpreadPoints) {
        PrintFormat("Blocked: Spread %d > %d", currentSpread, InpMaxSpreadPoints);
        return false;
    }
    return true;
}

double CSilverManager::CalculateLotSize(double entryPrice, double stopLossPrice) {
    double riskAmount = m_account.Balance() * (InpRiskPercent / 100.0);
    double slDistancePoints = MathAbs(entryPrice - stopLossPrice) / m_symbol.Point();
    
    if (slDistancePoints == 0 || m_symbol.TickSize() == 0) return 0.0;
    
    // Normalize tick value for metals
    double pointValue = m_symbol.TickValue() * (m_symbol.Point() / m_symbol.TickSize());
    double riskPerLot = slDistancePoints * pointValue;
    
    if (riskPerLot == 0) return 0.0;
    
    double rawLotSize = riskAmount / riskPerLot;
    
    // Floor to nearest broker step
    double step = m_symbol.LotsStep();
    double finalLot = MathFloor(rawLotSize / step) * step;
    
    finalLot = MathMax(finalLot, m_symbol.LotsMin());
    finalLot = MathMin(finalLot, m_symbol.LotsMax());
    
    return finalLot;
}
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 771
Joined: Mon Jul 20, 2026 1:28 pm

Re: ICT Silver Bullet EA MT4, MT5, Ctrader and TradingView

Post by PTScalper »

4. OOP Trade Management

Instead of manual variable tracking, m_position.SelectByIndex(i) automatically loads all attributes of that position into the CPositionInfo object. The script checks m_trade.ResultRetcode() to professionally handle server execution errors.

Code: Select all

void CSilverManager::ManageOpenPositions() {
    m_symbol.RefreshRates();
    
    for (int i = PositionsTotal() - 1; i >= 0; i--) {
        if(m_position.SelectByIndex(i)) {
            if(m_position.Symbol() == m_symbol.Name() && m_position.Magic() == InpMagicNumber) {
                
                ENUM_POSITION_TYPE type = m_position.PositionType();
                double openPrice = m_position.PriceOpen();
                double currentSL = m_position.StopLoss();
                double volume    = m_position.Volume();
                
                double bePrice = (type == POSITION_TYPE_BUY) ? 
                                 openPrice + (m_beOffsetPts * m_symbol.Point()) : 
                                 openPrice - (m_beOffsetPts * m_symbol.Point());

                // State check
                if ((type == POSITION_TYPE_BUY && currentSL >= bePrice) || 
                    (type == POSITION_TYPE_SELL && currentSL <= bePrice && currentSL != 0)) {
                    continue;
                }

                double riskDist = MathAbs(openPrice - currentSL);
                if(riskDist == 0) continue;

                bool targetHit = false;
                if(type == POSITION_TYPE_BUY && m_symbol.Bid() >= openPrice + (riskDist * InpRR_Target)) targetHit = true;
                if(type == POSITION_TYPE_SELL && m_symbol.Ask() <= openPrice - (riskDist * InpRR_Target)) targetHit = true;

                if (targetHit) {
                    // 1. Move SL to Breakeven
                    if (m_trade.PositionModify(m_position.Ticket(), bePrice, m_position.TakeProfit())) {
                        
                        // 2. Partial Volume Close
                        double step = m_symbol.LotsStep();
                        double lotsToClose = MathFloor((volume * (InpPartialClosePct / 100.0)) / step) * step;

                        if (lotsToClose >= m_symbol.LotsMin() && lotsToClose < volume) {
                            if(!m_trade.PositionClosePartial(m_position.Ticket(), lotsToClose)) {
                                PrintFormat("Partial close failed. Retcode: %d", m_trade.ResultRetcode());
                            }
                        }
                    } else {
                        PrintFormat("BE modification failed. Retcode: %d", m_trade.ResultRetcode());
                    }
                }
            }
        }
    }
}

void CSilverManager::ApplyTrailingStop() {
    m_symbol.RefreshRates();
    
    double trailPoints = InpTrailingDistPips * (m_pip / m_symbol.Point());
    double stepPoints  = InpTrailingStepPips * (m_pip / m_symbol.Point());
    
    for (int i = PositionsTotal() - 1; i >= 0; i--) {
        if(m_position.SelectByIndex(i)) {
            if(m_position.Symbol() == m_symbol.Name() && m_position.Magic() == InpMagicNumber) {
                
                ENUM_POSITION_TYPE type = m_position.PositionType();
                double openPrice = m_position.PriceOpen();
                double currentSL = m_position.StopLoss();
                
                double bePrice = (type == POSITION_TYPE_BUY) ? 
                                 openPrice + (m_beOffsetPts * m_symbol.Point()) : 
                                 openPrice - (m_beOffsetPts * m_symbol.Point());

                // Ensure position is past BE before trailing
                bool isPastBE = false;
                if(type == POSITION_TYPE_BUY && currentSL >= bePrice) isPastBE = true;
                if(type == POSITION_TYPE_SELL && currentSL <= bePrice && currentSL != 0) isPastBE = true;
                
                if(!isPastBE) continue;

                if (type == POSITION_TYPE_BUY) {
                    double newSL = m_symbol.Bid() - (trailPoints * m_symbol.Point());
                    if (newSL > currentSL + (stepPoints * m_symbol.Point())) {
                        m_trade.PositionModify(m_position.Ticket(), newSL, m_position.TakeProfit());
                    }
                } 
                else if (type == POSITION_TYPE_SELL) {
                    double newSL = m_symbol.Ask() + (trailPoints * m_symbol.Point());
                    if (newSL < currentSL - (stepPoints * m_symbol.Point()) || currentSL == 0) {
                        m_trade.PositionModify(m_position.Ticket(), newSL, m_position.TakeProfit());
                    }
                }
            }
        }
    }
}
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 771
Joined: Mon Jul 20, 2026 1:28 pm

Re: ICT Silver Bullet EA MT4, MT5, Ctrader and TradingView

Post by PTScalper »

5. The Main Event Loop

Because the complexity is now hidden inside the class, the main OnInit() and OnTick() functions remain incredibly clean and readable.

Code: Select all

//--- Instantiate the Manager Object globally
CSilverManager Manager;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit() {
    if(!Manager.Init(_Symbol, InpMagicNumber)) {
        Print("Failed to initialize CSilverManager");
        return INIT_FAILED;
    }
    return INIT_SUCCEEDED;
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick() {
    // 1. Defend open capital
    Manager.ManageOpenPositions();
    Manager.ApplyTrailingStop();
    
    // 2. Scan for entries
    /*
    if (IsSilverBulletWindow() && Manager.IsExecutionSafe()) {
        double lots = Manager.CalculateLotSize(entry, sl);
        // ... execute logic via m_trade ...
    }
    */
}
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 771
Joined: Mon Jul 20, 2026 1:28 pm

Re: ICT Silver Bullet EA MT4, MT5, Ctrader and TradingView

Post by PTScalper »

For Ctrader and ICtrader traders i have prepared this version :-)

MetaTrader forces you to build complex workarounds for basic market mechanics—like "ticket splitting" on partial closes and manual point-to-pip normalizations for 3-digit silver brokers. The cAlgo API handles all of this natively. In cTrader:

Partial Closes don't destroy the Position ID. position.Close(volume) simply reduces the size of the open position. Your tracking logic remains perfectly intact.

Symbol.PipSize is absolute. cTrader abstracts away the fractional tick sizing in the backend, meaning your pip calculations work exactly the same on a 2-digit, 3-digit, or fractional broker.

Here is the complete, professional-grade C# cBot architecture for the Silver Bullet manager.

The cTrader C# Implementation

Code: Select all

using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Internals;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class SilverBulletManager : Robot
    {
        [Parameter("Risk Percent", DefaultValue = 1.0, Group = "Risk & Sizing", MinValue = 0.1)]
        public double RiskPercent { get; set; }

        [Parameter("Max Spread (Pips)", DefaultValue = 4.0, Group = "Risk & Sizing")]
        public double MaxSpreadPips { get; set; }

        [Parameter("RR Target", DefaultValue = 1.0, Group = "Trade Management")]
        public double RR_Target { get; set; }

        [Parameter("Partial Close %", DefaultValue = 50.0, Group = "Trade Management", MinValue = 10, MaxValue = 90)]
        public double PartialClosePct { get; set; }

        [Parameter("Breakeven Offset (Pips)", DefaultValue = 1.0, Group = "Trade Management")]
        public double BreakevenOffsetPips { get; set; }

        [Parameter("Trailing Distance (Pips)", DefaultValue = 15.0, Group = "Trade Management")]
        public double TrailingDistPips { get; set; }

        [Parameter("Trailing Step (Pips)", DefaultValue = 2.0, Group = "Trade Management")]
        public double TrailingStepPips { get; set; }

        // Unique identifier for the strategy's trades
        private const string Label = "SilverBullet";

        protected override void OnTick()
        {
            // 1. Defend open capital first
            ManageOpenPositions();
            ApplyTrailingStop();
            
            // 2. Scan & execute new entries here
            // if (IsSilverBulletWindow() && IsExecutionSafe()) { 
            //     PlaceLimitOrder(TradeType.Buy, SymbolName, volume, entry, Label, slPips, tpPips);
            // }
        }

        //+------------------------------------------------------------------+
        //| Dynamic Sizing & Safety                                          |
        //+------------------------------------------------------------------+
        
        public bool IsExecutionSafe()
        {
            // cTrader directly provides spread divided by PipSize
            double currentSpread = Symbol.Spread / Symbol.PipSize;
            
            if (currentSpread > MaxSpreadPips)
            {
                Print("Execution Blocked: Spread {0} pips > {1} pips", Math.Round(currentSpread, 1), MaxSpreadPips);
                return false;
            }
            return true;
        }

        public double CalculateVolume(double entryPrice, double stopLossPrice)
        {
            double riskAmount = Account.Balance * (RiskPercent / 100.0);
            double slDistancePips = Math.Abs(entryPrice - stopLossPrice) / Symbol.PipSize;

            if (slDistancePips == 0) return 0;

            // Symbol.PipValue in cTrader is the value of 1 pip for Symbol.VolumeInUnitsMin
            double riskPerMinVolume = slDistancePips * Symbol.PipValue;
            double rawVolume = (riskAmount / riskPerMinVolume) * Symbol.VolumeInUnitsMin;

            // Natively normalizes to the broker's minimum, maximum, and lot step limits
            return Symbol.NormalizeVolumeInUnits(rawVolume, RoundingMode.Down);
        }

        //+------------------------------------------------------------------+
        //| Trade Management: Native Partial Close                           |
        //+------------------------------------------------------------------+
        
        private void ManageOpenPositions()
        {
            // Easily isolate positions managed by this specific cBot
            var positions = Positions.FindAll(Label, SymbolName);

            foreach (var position in positions)
            {
                if (!position.StopLoss.HasValue) continue;

                double bePrice = position.TradeType == TradeType.Buy
                    ? position.EntryPrice + (BreakevenOffsetPips * Symbol.PipSize)
                    : position.EntryPrice - (BreakevenOffsetPips * Symbol.PipSize);

                // State check: Skip if SL is already moved to/past BE
                if ((position.TradeType == TradeType.Buy && position.StopLoss.Value >= bePrice) ||
                    (position.TradeType == TradeType.Sell && position.StopLoss.Value <= bePrice))
                {
                    continue;
                }

                double riskDist = Math.Abs(position.EntryPrice - position.StopLoss.Value);
                if (riskDist == 0) continue;

                bool targetHit = false;
                if (position.TradeType == TradeType.Buy && Symbol.Bid >= position.EntryPrice + (riskDist * RR_Target)) targetHit = true;
                if (position.TradeType == TradeType.Sell && Symbol.Ask <= position.EntryPrice - (riskDist * RR_Target)) targetHit = true;

                if (targetHit)
                {
                    // 1. Move SL to Breakeven
                    var modifyResult = position.ModifyStopLossPrice(bePrice);

                    // 2. Execute Partial Volume Close
                    if (modifyResult.IsSuccessful)
                    {
                        double volumeToClose = Symbol.NormalizeVolumeInUnits(position.VolumeInUnits * (PartialClosePct / 100.0), RoundingMode.Down);
                        
                        if (volumeToClose >= Symbol.VolumeInUnitsMin && volumeToClose < position.VolumeInUnits)
                        {
                            // cTrader simply reduces the position volume without creating a new ticket
                            position.Close(volumeToClose);
                        }
                    }
                }
            }
        }

        //+------------------------------------------------------------------+
        //| Trailing Stop Engine                                             |
        //+------------------------------------------------------------------+
        
        private void ApplyTrailingStop()
        {
            var positions = Positions.FindAll(Label, SymbolName);

            foreach (var position in positions)
            {
                if (!position.StopLoss.HasValue) continue;

                double bePrice = position.TradeType == TradeType.Buy
                    ? position.EntryPrice + (BreakevenOffsetPips * Symbol.PipSize)
                    : position.EntryPrice - (BreakevenOffsetPips * Symbol.PipSize);

                // Ensure position is past BE before trailing
                bool isPastBE = false;
                if (position.TradeType == TradeType.Buy && position.StopLoss.Value >= bePrice) isPastBE = true;
                if (position.TradeType == TradeType.Sell && position.StopLoss.Value <= bePrice) isPastBE = true;

                if (!isPastBE) continue;

                double trailPoints = TrailingDistPips * Symbol.PipSize;
                double stepPoints = TrailingStepPips * Symbol.PipSize;

                if (position.TradeType == TradeType.Buy)
                {
                    double newSL = Symbol.Bid - trailPoints;
                    
                    // Step filter to prevent server spam
                    if (newSL > position.StopLoss.Value + stepPoints)
                    {
                        position.ModifyStopLossPrice(newSL);
                    }
                }
                else if (position.TradeType == TradeType.Sell)
                {
                    double newSL = Symbol.Ask + trailPoints;
                    
                    // Step filter to prevent server spam
                    if (newSL < position.StopLoss.Value - stepPoints)
                    {
                        position.ModifyStopLossPrice(newSL);
                    }
                }
            }
        }
    }
}
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 771
Joined: Mon Jul 20, 2026 1:28 pm

Re: ICT Silver Bullet EA MT4, MT5, Ctrader and TradingView

Post by PTScalper »

Key Architectural Advantages in cTrader
Symbol.NormalizeVolumeInUnits: Instead of writing manual flooring logic to fit the broker's minimum lot sizes, this single cAlgo method natively parses your raw mathematical risk, rounds it correctly (RoundingMode.Down to protect risk ceilings), and formats it into broker-safe units.

The Label Parameter: Filtering by Positions.FindAll(Label, SymbolName) is a massive upgrade over MT4's MagicNumber system. It allows you to run multiple different strategies on Silver concurrently, and this class will only manage trades labeled "SilverBullet".

Time Zone Agnostic: Because cBots run on a server that might be in an entirely different timezone than your broker's price feed, you can set [Robot(TimeZone = TimeZones.UTC)] at the top level. This makes programming the strict New York Silver Bullet time windows highly precise, regardless of local machine configuration.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 771
Joined: Mon Jul 20, 2026 1:28 pm

Re: ICT Silver Bullet EA MT4, MT5, Ctrader and TradingView

Post by PTScalper »

In MetaTrader, coding session times requires writing complex offset functions to calculate the difference between the broker's server time (often GMT+2/GMT+3) and New York time, while manually adjusting for Daylight Saving Time (DST) twice a year.

cTrader's cAlgo API completely abstracts this away. By defining the timezone at the class level, the C# environment automatically handles both the UTC offset and US Daylight Saving Time (switching between EST and EDT seamlessly).

Here is how you accurately script the ICT Silver Bullet windows.

1. The TimeZone Attribute
You set the time zone natively in the [Robot] attribute before the class declaration. By assigning TimeZones.EasternStandardTime, you are instructing the cBot to run in New York time.

2. The Server.Time Abstraction
Once the attribute is set, any call to Server.Time will represent the current time in New York. You do not need to use DateTime.UtcNow or calculate offsets.

The C# Implementation

Code: Select all

using cAlgo.API;
using System;

namespace cAlgo.Robots
{
    // 1. Force the cBot to run in New York Local Time (handles DST automatically)
    [Robot(TimeZone = TimeZones.EasternStandardTime, AccessRights = AccessRights.None)]
    public class SilverBulletManager : Robot
    {
        [Parameter("Trade London Open (03:00 - 04:00 NY)", DefaultValue = false, Group = "ICT Sessions")]
        public bool TradeLondonOpen { get; set; }

        [Parameter("Trade NY AM (10:00 - 11:00 NY)", DefaultValue = true, Group = "ICT Sessions")]
        public bool TradeNyAm { get; set; }

        [Parameter("Trade NY PM (14:00 - 15:00 NY)", DefaultValue = true, Group = "ICT Sessions")]
        public bool TradeNyPm { get; set; }

        [Parameter("Hard Close at Session End?", DefaultValue = true, Group = "ICT Sessions")]
        public bool HardClosePositions { get; set; }

        // Unique identifier for the strategy
        private const string Label = "SilverBullet";

        protected override void OnTick()
        {
            if (IsSilverBulletWindow())
            {
                // Your Market Structure Shift & FVG scanning logic goes here
            }
            else if (HardClosePositions)
            {
                // Prevent holding trades in dead zones or overnight
                EnforceSessionClose();
            }
        }

        //+------------------------------------------------------------------+
        //| The Time Window Gatekeeper                                       |
        //+------------------------------------------------------------------+
        private bool IsSilverBulletWindow()
        {
            // Server.Time is now natively Eastern Time (EST/EDT)
            int currentHour = Server.Time.Hour;

            // ICT London Open: 3:00 AM - 3:59 AM NY Time
            if (TradeLondonOpen && currentHour == 3) return true;

            // ICT NY AM Session: 10:00 AM - 10:59 AM NY Time
            if (TradeNyAm && currentHour == 10) return true;

            // ICT NY PM Session: 2:00 PM - 2:59 PM (14:00 - 14:59) NY Time
            if (TradeNyPm && currentHour == 14) return true;

            return false;
        }

        //+------------------------------------------------------------------+
        //| Session End Liquidation                                          |
        //+------------------------------------------------------------------+
        private void EnforceSessionClose()
        {
            var positions = Positions.FindAll(Label, SymbolName);
            
            // If we are outside the 3AM, 10AM, and 2PM hours, flatten the book
            foreach (var position in positions)
            {
                position.Close();
            }
            
            // Cancel any pending limit orders at the FVG that never triggered
            var pendingOrders = PendingOrders.Where(o => o.Label == Label && o.SymbolName == SymbolName);
            foreach (var order in pendingOrders)
            {
                CancelPendingOrder(order);
            }
        }
    }
}
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 771
Joined: Mon Jul 20, 2026 1:28 pm

Re: ICT Silver Bullet EA MT4, MT5, Ctrader and TradingView

Post by PTScalper »

Architectural Notes for Backtesting
Because cTrader's backtester simulates the historical data through the lens of your [Robot] attribute, a backtest run in February will automatically apply a UTC-5 offset, and a backtest run in June will apply a UTC-4 offset.

This guarantees that your algorithmic 10:00 AM execution always perfectly aligns with the opening hour of the New York stock market and the resulting silver volatility, regardless of the season.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 771
Joined: Mon Jul 20, 2026 1:28 pm

Re: ICT Silver Bullet EA MT4, MT5, Ctrader and TradingView

Post by PTScalper »

To mathematically model market microstructure—sweeps, structural shifts, and imbalances—you must transition from tick-level execution to the OnBar() event loop. Scanning for structural shifts on every tick invites "intra-bar repainting," where a candle temporarily breaches a level and triggers your logic, only to wick back before the close.

In cTrader, the Bars collection handles this elegantly. Unlike MT4’s reverse arrays, cTrader’s Bars.Last(int index) method makes it incredibly intuitive to map out the 3-candle sequences required for Fair Value Gaps (FVGs) and Market Structure Shifts (MSS).

Here is the C# blueprint for the structural state machine.

1. The State Machine & Global Variables

We need an enum to track the chronological sequence. The algorithm must remain locked in its current state until the next geometric rule is satisfied.

Code: Select all

using cAlgo.API;
using System.Linq;

namespace cAlgo.Robots
{
    public partial class SilverBulletManager : Robot
    {
        [Parameter("Liquidity Lookback (Bars)", DefaultValue = 50, Group = "Market Structure")]
        public int LiquidityLookback { get; set; }

        private enum SetupState
        {
            Monitoring,
            BuysideSwept,
            SellsideSwept,
            MssConfirmed
        }

        private SetupState _currentState = SetupState.Monitoring;
        private double _bsl;             // Buyside Liquidity
        private double _ssl;             // Sellside Liquidity
        private double _mssLevel;        // The structural level that must be broken
        
        // ... (previous time window and sizing parameters)
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 771
Joined: Mon Jul 20, 2026 1:28 pm

Re: ICT Silver Bullet EA MT4, MT5, Ctrader and TradingView

Post by PTScalper »

2. Capturing Liquidity at the Window Open

When the time window (e.g., 10:00 AM NY) opens, you must lock in the liquidity pools based on previous session data. You do not want these values updating continuously during the execution window.

Code: Select all

protected override void OnBar()
        {
            // 1. Reset state if outside the trading window
            if (!IsSilverBulletWindow())
            {
                _currentState = SetupState.Monitoring;
                return;
            }

            // 2. Lock in BSL and SSL on the very first bar of the window
            if (Server.Time.Minute == 0) 
            {
                // cTrader's DataSeries allows LINQ-style maximums over a specific range
                // We start reading from index 1 to exclude the currently forming bar
                _bsl = Bars.HighPrices.SkipLast(1).TakeLast(LiquidityLookback).Max();
                _ssl = Bars.LowPrices.SkipLast(1).TakeLast(LiquidityLookback).Min();
            }

            // 3. Progress the State Machine
            switch (_currentState)
            {
                case SetupState.Monitoring:
                    ScanForLiquiditySweep();
                    break;
                case SetupState.BuysideSwept:
                case SetupState.SellsideSwept:
                    ScanForMarketStructureShift();
                    break;
                case SetupState.MssConfirmed:
                    ScanForFairValueGap();
                    break;
            }
        }
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 771
Joined: Mon Jul 20, 2026 1:28 pm

Re: ICT Silver Bullet EA MT4, MT5, Ctrader and TradingView

Post by PTScalper »

3. Scanning for the Sweep & MSS

A sweep is defined as price piercing the liquidity pool but failing to hold it, printing a rejection wick. A Market Structure Shift is confirmed when the price subsequently closes past the fractal low/high that initiated the sweep.

Code: Select all

private void ScanForLiquiditySweep()
        {
            var lastBar = Bars.Last(1); // The most recently closed candle

            // Buyside Sweep: Pierced BSL, but closed below it
            if (lastBar.High > _bsl && lastBar.Close < _bsl)
            {
                _currentState = SetupState.BuysideSwept;
                
                // Identify the most recent fractal low prior to the sweep to act as our MSS line
                _mssLevel = Bars.LowPrices.SkipLast(2).TakeLast(5).Min();
                Print("Buyside Liquidity Swept. Awaiting MSS below: {0}", _mssLevel);
            }
            // Sellside Sweep: Pierced SSL, but closed above it
            else if (lastBar.Low < _ssl && lastBar.Close > _ssl)
            {
                _currentState = SetupState.SellsideSwept;
                
                // Identify the most recent fractal high prior to the sweep
                _mssLevel = Bars.HighPrices.SkipLast(2).TakeLast(5).Max();
                Print("Sellside Liquidity Swept. Awaiting MSS above: {0}", _mssLevel);
            }
        }

        private void ScanForMarketStructureShift()
        {
            var lastBar = Bars.Last(1);

            // If we swept buyside, we need a strong bearish close below the MSS low
            if (_currentState == SetupState.BuysideSwept && lastBar.Close < _mssLevel)
            {
                _currentState = SetupState.MssConfirmed;
                Print("Bearish MSS Confirmed. Awaiting FVG.");
            }
            // If we swept sellside, we need a strong bullish close above the MSS high
            else if (_currentState == SetupState.SellsideSwept && lastBar.Close > _mssLevel)
            {
                _currentState = SetupState.MssConfirmed;
                Print("Bullish MSS Confirmed. Awaiting FVG.");
            }
        }
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Post Reply