Advertisement IC Markets

Using MAE to Test Whether Your Stop Is the Right Size

Document your personal trading journey. Track daily equity curves, review winning and losing streaks, share trade screenshots, and get constructive feedback.
PTScalper
Site Admin
Posts: 4805
Joined: Mon Jul 20, 2026 1:28 pm

Re: Using MAE to Test Whether Your Stop Is the Right Size

Post by PTScalper »

Ctrader version 1.0

Code: Select all

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

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class LiquiditySweep : Indicator
    {
        [Parameter("Pivot Left Bars", Group = "Structure", DefaultValue = 5, MinValue = 1)]
        public int LeftBars { get; set; }

        [Parameter("Pivot Right Bars", Group = "Structure", DefaultValue = 5, MinValue = 1)]
        public int RightBars { get; set; }

        // State variables to track the most recent structural liquidity pools
        private double _lastHigh = double.NaN;
        private double _lastLow = double.NaN;
        private int _lastHighIndex = -1;
        private int _lastLowIndex = -1;

        protected override void Initialize()
        {
            // Initialization logic (chart is clean by default)
        }

        public override void Calculate(int index)
        {
            // Ensure enough data is present to calculate lookbacks
            if (index < LeftBars + RightBars)
                return;

            // 1. Identify structural pivots historically at the (index - RightBars) shift
            int shiftIndex = index - RightBars;
            EvaluatePivot(shiftIndex);

            // 2. Sweep Logic evaluating on the current forming candle
            double currentHigh = Bars.High[index];
            double currentLow = Bars.Low[index];
            double currentClose = Bars.Close[index];
            
            // Calculate a dynamic gap to keep arrows from overlapping the candlestick wick
            double atrOffset = (currentHigh - currentLow) * 0.2; 

            // Bearish Sweep: Grab liquidity above the structural high, close below
            string bearSweepName = "BearSweep_" + index;
            if (!double.IsNaN(_lastHigh) && currentHigh > _lastHigh && currentClose < _lastHigh)
            {
                Chart.DrawIcon(bearSweepName, ChartIconType.DownArrow, index, currentHigh + atrOffset, Color.Red);
            }
            else
            {
                // If conditions invalidate mid-tick (e.g., candle closes above the level), erase the arrow
                Chart.RemoveObject(bearSweepName);
            }

            // Bullish Sweep: Grab liquidity below the structural low, close above
            string bullSweepName = "BullSweep_" + index;
            if (!double.IsNaN(_lastLow) && currentLow < _lastLow && currentClose > _lastLow)
            {
                Chart.DrawIcon(bullSweepName, ChartIconType.UpArrow, index, currentLow - atrOffset, Color.LimeGreen);
            }
            else
            {
                // Erase mid-tick if invalidated
                Chart.RemoveObject(bullSweepName);
            }

            // 3. Extend projection dashed lines dynamically to the current bar
            if (!double.IsNaN(_lastHigh))
            {
                Chart.DrawTrendLine("LiqHighLine", _lastHighIndex, _lastHigh, index, _lastHigh, Color.Red, 1, LineStyle.Lines);
            }

            if (!double.IsNaN(_lastLow))
            {
                Chart.DrawTrendLine("LiqLowLine", _lastLowIndex, _lastLow, index, _lastLow, Color.LimeGreen, 1, LineStyle.Lines);
            }
        }

        private void EvaluatePivot(int shiftIndex)
        {
            bool isHigh = true;
            bool isLow = true;

            double shiftHigh = Bars.High[shiftIndex];
            double shiftLow = Bars.Low[shiftIndex];

            // Check Left Side
            for (int i = 1; i <= LeftBars; i++)
            {
                if (Bars.High[shiftIndex - i] > shiftHigh) isHigh = false;
                if (Bars.Low[shiftIndex - i] < shiftLow) isLow = false;
            }

            // Check Right Side
            for (int i = 1; i <= RightBars; i++)
            {
                if (Bars.High[shiftIndex + i] >= shiftHigh) isHigh = false;
                if (Bars.Low[shiftIndex + i] <= shiftLow) isLow = false;
            }

            // Register Swing High
            if (isHigh)
            {
                _lastHigh = shiftHigh;
                _lastHighIndex = shiftIndex;
                Chart.DrawIcon("PivotHigh_" + shiftIndex, ChartIconType.DownTriangle, shiftIndex, shiftHigh, Color.Gray);
            }

            // Register Swing Low
            if (isLow)
            {
                _lastLow = shiftLow;
                _lastLowIndex = shiftIndex;
                Chart.DrawIcon("PivotLow_" + shiftIndex, ChartIconType.UpTriangle, shiftIndex, shiftLow, Color.Gray);
            }
        }
    }
}
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Recommended broker for automated trading & scalping IC Markets
PTScalper
Site Admin
Posts: 4805
Joined: Mon Jul 20, 2026 1:28 pm

Re: Using MAE to Test Whether Your Stop Is the Right Size

Post by PTScalper »

Key cTrader/C# Translation Differences:

Chart.RemoveObject() over Buffer Resets: Because Calculate(int index) executes on every incoming tick for the current live forming bar, we simply assign a unique ID (BearSweep_ + index) to the arrow. If the candle wicks past the high but later breaks structure and pushes its Close above the level, the else block fires and removes the false-trigger arrow instantly.

Modern Bars API: It uses Bars.High[index] instead of the older MarketSeries syntax, adhering to current cTrader standards.

LineStyle.Lines: This renders the projected liquidity pool lines as a clean dashed line matching the style of the MT4/MT5 versions. As the index increments forward, the DrawTrendLine command simply overwrites the line ending, stretching it cleanly across the chart without duplicating objects.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Post Reply