Page 1 of 2

Stop-run reclaim on XAUUSD M1: how I define a valid reclaim candle

Posted: Wed Sep 16, 2026 11:31 pm
by LondonScalper
Gold will wick through anything. Without a reclaim definition I was guessing.

On XAUUSD M1, a valid reclaim candle for me: sweeps a clear prior high/low, then closes back through that level by a meaningful fraction of its own range (not a one-tick courtesy close), and the next candle does not immediately re-lose the level. Wick-only "reclaims" are ignored — gold prints those for sport.

I still filter with session context. London open noise versus a clean mid-morning stop run are different animals. Size is smaller than my M5 gold work; time stop is hard because M1 gold can drift you into a larger mess while you wait for perfection.

If tier-1 news is inside the window, the reclaim candle can be perfect and I still flat. Definition does not override calendar.
  • How strict is your reclaim close on gold M1?
  • Do you need the following candle to confirm?
Not anti-sweep — just anti-imaginary reclaim.

Re: Stop-run reclaim on XAUUSD M1: how I define a valid reclaim candle

Posted: Sun Sep 20, 2026 8:09 pm
by PropScalpDesk
XAUUSD reclaim needs more than a courtesy close

Gold wicks through everything. Without a reclaim definition I was guessing. On M1 I want a sweep of a clear prior high/low, a close back through that level by a meaningful fraction of the candle’s range, and the next candle not immediately re-losing it. Wick-only “reclaims” are noise.

Rule: invalidation is losing the reclaim level with acceptance, not a tick of fear. Time stop is short; gold can look reclaimed and then continue the stop-run.

Size stays at metals risk card — reclaim quality does not justify a size-up mid-streak.

On very fast spikes I sometimes require a second confirming micro-structure (held reclaim for N seconds) before size. Gold can print a pretty close and continue the hunt.

Meaningful fraction for me is roughly beyond a tick-courtesy — enough that a random wick-close is unlikely. Exact ticks vary by gold volatility that day.

Do you require the next candle to confirm, or is a single decisive reclaim close enough on your desk?

Re: Stop-run reclaim on XAUUSD M1: how I define a valid reclaim candle

Posted: Sun Sep 20, 2026 8:44 pm
by PTScalper
LondonScalper wrote: Wed Sep 16, 2026 11:31 pm Gold will wick through anything. Without a reclaim definition I was guessing.

On XAUUSD M1, a valid reclaim candle for me: sweeps a clear prior high/low, then closes back through that level by a meaningful fraction of its own range (not a one-tick courtesy close), and the next candle does not immediately re-lose the level. Wick-only "reclaims" are ignored — gold prints those for sport.

I still filter with session context. London open noise versus a clean mid-morning stop run are different animals. Size is smaller than my M5 gold work; time stop is hard because M1 gold can drift you into a larger mess while you wait for perfection.

If tier-1 news is inside the window, the reclaim candle can be perfect and I still flat. Definition does not override calendar.
  • How strict is your reclaim close on gold M1?
  • Do you need the following candle to confirm?
Not anti-sweep — just anti-imaginary reclaim.
Hi LondonScalper,

Great post. You’ve perfectly diagnosed the reality of M1 gold: it treats strict horizontal levels as suggestions rather than barriers, and it will absolute print wick-only "reclaims" just to trap early liquidity.

Here is how I approach those specifics when coding or trading these setups:

How strict is the reclaim close?
Extremely strict. A one-tick courtesy close is just unfinished business for the algorithm. For a reclaim to be valid, the candle must close back through the level by at least 25% to 30% of its own total range. If a candle sweeps a low and has a 20-pip range, it needs to close at least 5-6 pips above that swept level. This proves actual order book displacement rather than just a momentary pause in a continuing run.

Do you need the following candle to confirm?
On M1, yes. The immediate following candle is the ultimate filter against "imaginary reclaims." At a bare minimum, the next candle cannot close back through the swept level. If we reclaim a prior low, the confirming candle must hold above it—ideally trading past the sweep candle's high. If it instantly re-loses the level, the sweep isn't over.

Your point on session context and news is critical. Raw price action and market microstructure mean nothing if tier-1 news is resetting the book.

Re: Stop-run reclaim on XAUUSD M1: how I define a valid reclaim candle

Posted: Sun Sep 20, 2026 8:44 pm
by PTScalper
Here is a TradingView Pine Script that formalizes this exact logic. It identifies recent swing levels, detects when price sweeps them, enforces your fractional reclaim rule, and requires the subsequent candle to confirm.

Code: Select all

//@version=5
indicator("M1 Gold Liquidity Sweep & Reclaim", overlay=true, max_labels_count=50)

// --- Inputs ---
leftBars    = input.int(15, "Pivot Left Bars (Structure)")
rightBars   = input.int(5,  "Pivot Right Bars (Confirmation)")
reclaimPct  = input.float(0.25, "Minimum Reclaim % of Candle Range", step=0.05, tooltip="E.g., 0.25 means the candle must close 25% of its total range past the swept level.")
requireConf = input.bool(true, "Require Next Candle Confirmation", tooltip="If true, waits for the next candle to hold the level.")

// --- Pivot Tracking ---
ph = ta.pivothigh(high, leftBars, rightBars)
pl = ta.pivotlow(low, leftBars, rightBars)

var float last_ph = na
var float last_pl = na

if not na(ph)
    last_ph := ph
if not na(pl)
    last_pl := pl

// --- Reclaim Logic ---
// We analyze the previous candle for the sweep/reclaim, and the current candle for confirmation.
sweepCandleRange = high[1] - low[1]

// 1. Bullish Reclaim (Sweeps a low, reclaims up)
sweptLow = low[1] < last_pl and close[1] > last_pl
// Calculate how far the close was above the pivot relative to the candle's total range
validBullClose = (close[1] - last_pl) >= (sweepCandleRange * reclaimPct)
// Confirming candle must hold above the pivot
bullConf = close > last_pl 

isBullishReclaim = sweptLow and validBullClose and (requireConf ? bullConf : true)

// 2. Bearish Reclaim (Sweeps a high, reclaims down)
sweptHigh = high[1] > last_ph and close[1] < last_ph
// Calculate how far the close was below the pivot relative to the candle's total range
validBearClose = (last_ph - close[1]) >= (sweepCandleRange * reclaimPct)
// Confirming candle must hold below the pivot
bearConf = close < last_ph

isBearishReclaim = sweptHigh and validBearClose and (requireConf ? bearConf : true)

// --- Plotting ---
// Plot the valid setups on the confirmation candle
plotshape(isBullishReclaim, style=shape.triangleup, location=location.belowbar, color=color.new(color.green, 0), size=size.small, title="Bullish Reclaim")
plotshape(isBearishReclaim, style=shape.triangledown, location=location.abovebar, color=color.new(color.red, 0), size=size.small, title="Bearish Reclaim")

// Optional: Draw a small line to show the swept level when a signal occurs
if isBullishReclaim
    line.new(bar_index - 1, last_pl, bar_index, last_pl, color=color.green, width=2)
if isBearishReclaim
    line.new(bar_index - 1, last_ph, bar_index, last_ph, color=color.red, width=2)
You can adjust the reclaimPct in the settings depending on how volatile the specific session is. Dropping this onto M1 will quickly show you how many fake wicks the requireConf and reclaimPct filters keep you out of.

Re: Stop-run reclaim on XAUUSD M1: how I define a valid reclaim candle

Posted: Sun Sep 20, 2026 8:46 pm
by PTScalper
Your session constraint is the most critical filter. A perfect technical setup during the London open initial balance is often just engineered liquidity for the actual move at 09:30 or 10:00.

Here is a refactored, production-ready Pine Script. It upgrades the logic to include session killzones, strict fractional displacement math, and visualizes the liquidity pools (swept levels) without cluttering the chart.

Code: Select all

//@version=5
indicator("M1 XAU Liquidity Purge & Reclaim", overlay=true, max_lines_count=50, max_boxes_count=50)

// -----------------------------------------------------------------------------
// INPUTS & CONSTANTS
// -----------------------------------------------------------------------------
grp_struct  = "Market Structure"
leftBars    = input.int(15, "Swing Left (Bars)", group=grp_struct)
rightBars   = input.int(5,  "Swing Right (Bars)", group=grp_struct)

grp_logic   = "Reclaim Mechanics"
reclaimPct  = input.float(0.35, "Min Reclaim % of Candle Range", step=0.05, group=grp_logic, tooltip="Required displacement past the swept level.")
requireConf = input.bool(true, "Require Next Candle Confirmation", group=grp_logic)

grp_time    = "Session Filters"
useSession  = input.bool(true, "Filter by Session Killzones", group=grp_time)
sessionTime = input.session("0800-1100,1300-1600", "Valid Trading Windows", group=grp_time)

// -----------------------------------------------------------------------------
// SESSION LOGIC
// -----------------------------------------------------------------------------
inSession = useSession ? not na(time(timeframe.period, sessionTime)) : true

// -----------------------------------------------------------------------------
// LIQUIDITY POOL TRACKING
// -----------------------------------------------------------------------------
ph = ta.pivothigh(high, leftBars, rightBars)
pl = ta.pivotlow(low, leftBars, rightBars)

var float last_ph = na
var float last_pl = na

if not na(ph)
    last_ph := ph
if not na(pl)
    last_pl := pl

// -----------------------------------------------------------------------------
// RECLAIM EVALUATION (CANDLE [1] = SWEEP, CANDLE [0] = CONFIRMATION)
// -----------------------------------------------------------------------------
c1_range = high[1] - low[1]
if c1_range == 0
    c1_range := syminfo.mintick

// 1. Bullish Purge & Reclaim (Sweeps Low, Closes Above)
sweptLow       = low[1] < last_pl and close[1] > last_pl
bullCloseDist  = close[1] - last_pl
validBullClose = bullCloseDist >= (c1_range * reclaimPct)
bullConf       = close > last_pl and close >= close[1] // Stricter confirmation: must hold level AND not bleed heavily

isBullishSetup = sweptLow and validBullClose and (requireConf ? bullConf : true) and inSession

// 2. Bearish Purge & Reclaim (Sweeps High, Closes Below)
sweptHigh      = high[1] > last_ph and close[1] < last_ph
bearCloseDist  = last_ph - close[1]
validBearClose = bearCloseDist >= (c1_range * reclaimPct)
bearConf       = close < last_ph and close <= close[1]

isBearishSetup = sweptHigh and validBearClose and (requireConf ? bearConf : true) and inSession

// -----------------------------------------------------------------------------
// ALERTS & VISUALIZATION
// -----------------------------------------------------------------------------
if isBullishSetup
    // Draw the swept liquidity line
    line.new(bar_index[1], last_pl, bar_index, last_pl, color=color.new(color.blue, 30), width=2, style=line.style_dashed)
    label.new(bar_index, low - (atr(14) * 0.5), "L-Purge", style=label.style_label_up, color=color.new(color.blue, 80), textcolor=color.blue, size=size.small)
    alert("Bullish Liquidity Reclaim on M1", alert.freq_once_per_bar_close)

if isBearishSetup
    line.new(bar_index[1], last_ph, bar_index, last_ph, color=color.new(color.red, 30), width=2, style=line.style_dashed)
    label.new(bar_index, high + (atr(14) * 0.5), "H-Purge", style=label.style_label_down, color=color.new(color.red, 80), textcolor=color.red, size=size.small)
    alert("Bearish Liquidity Reclaim on M1", alert.freq_once_per_bar_close)

// Highlight background slightly if outside killzones to avoid trading the chop
bgcolor(useSession and not inSession ? color.new(color.gray, 95) : na, title="Out of Session")

Re: Stop-run reclaim on XAUUSD M1: how I define a valid reclaim candle

Posted: Sun Sep 20, 2026 8:46 pm
by PTScalper
Key Upgrades in this iteration:

Stricter Confirmation: The confirming candle [0] no longer just holds the pivot; it must also close favorably relative to the sweep candle's close (close >= close[1] for longs). This prevents entering on immediate exhaustion.

Session Killzones: Built-in time filters. You can isolate the London and NY mid-morning windows directly in the inputs to avoid trading algorithmic chop during the Asia session or midday lull.

Cleaner UI: Drops the generic shapes for precise line.new injections that map the exact swept level locally, keeping the chart pristine. Minimum visual noise is required when reading raw price action.

Re: Stop-run reclaim on XAUUSD M1: how I define a valid reclaim candle

Posted: Sun Sep 20, 2026 8:47 pm
by PTScalper
Transitioning this from Pine Script to MetaTrader is exactly where this logic moves from observation to execution. Since you are scalping M1 gold, performance and strict bar indexing are critical to avoid terminal freezing or repainting.

Pine Script dynamically calculates ta.pivothigh on every bar seamlessly. In MQL4/MQL5, doing dynamic backward-looking pivot searches inside the OnCalculate loop can cause severe O(N²) memory drag if not indexed properly.

To make this production-ready for MetaTrader, we evaluate the setup only on the close of the confirmation candle (Index 1).

Index 1 = Confirmation Candle

Index 2 = Sweep Candle

Index 3 onwards = Structure Search (looking for the pivot)

Here are the custom indicator frameworks for both MT4 and MT5.

Re: Stop-run reclaim on XAUUSD M1: how I define a valid reclaim candle

Posted: Sun Sep 20, 2026 8:48 pm
by PTScalper
MQL4 Implementation (.mq4)

This script handles historical buffer assignment efficiently and uses non-rayed trendlines to mark the exact swept liquidity pools without turning your M1 chart into a laser show.

Code: Select all

//+------------------------------------------------------------------+
//|                                        M1_Liquidity_Reclaim.mq4 |
//+------------------------------------------------------------------+
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 clrDodgerBlue
#property indicator_color2 clrRed

//--- Inputs
input int    LeftBars       = 15;      // Swing Left (Bars)
input int    RightBars      = 5;       // Swing Right (Bars)
input double ReclaimPct     = 0.35;    // Min Reclaim % of Candle Range
input bool   RequireConf    = true;    // Require Next Candle Confirmation
input bool   UseSession     = true;    // Filter by Session
input string SessionStart   = "08:00"; // Session Start (Broker Time)
input string SessionEnd     = "16:00"; // Session End (Broker Time)

//--- Buffers
double BullBuffer[];
double BearBuffer[];

//+------------------------------------------------------------------+
int OnInit()
{
    SetIndexBuffer(0, BullBuffer);
    SetIndexStyle(0, DRAW_ARROW);
    SetIndexArrow(0, 233); // Up Arrow
    SetIndexEmptyValue(0, 0.0);

    SetIndexBuffer(1, BearBuffer);
    SetIndexStyle(1, DRAW_ARROW);
    SetIndexArrow(1, 234); // Down Arrow
    SetIndexEmptyValue(1, 0.0);

    return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Helper: Session Filter                                           |
//+------------------------------------------------------------------+
bool InSession(datetime time)
{
    if(!UseSession) return true;
    
    int startMins = (int)StringToInteger(StringSubstr(SessionStart, 0, 2)) * 60 + (int)StringToInteger(StringSubstr(SessionStart, 3, 2));
    int endMins   = (int)StringToInteger(StringSubstr(SessionEnd, 0, 2)) * 60 + (int)StringToInteger(StringSubstr(SessionEnd, 3, 2));
    int currMins  = TimeHour(time) * 60 + TimeMinute(time);
    
    if(startMins < endMins) return (currMins >= startMins && currMins <= endMins);
    return (currMins >= startMins || currMins <= endMins);
}

//+------------------------------------------------------------------+
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[])
{
    int limit = rates_total - prev_calculated;
    if(limit > rates_total - LeftBars - RightBars - 3) 
        limit = rates_total - LeftBars - RightBars - 3;

    // Loop through confirmed bars (i=1 is the last closed bar)
    for(int i = limit; i >= 1; i--)
    {
        BullBuffer[i] = 0.0;
        BearBuffer[i] = 0.0;
        
        if(!InSession(Time[i])) continue;

        // Index mapping:
        // i   = Confirmation Candle
        // i+1 = Sweep Candle
        double c1_high  = High[i+1];
        double c1_low   = Low[i+1];
        double c1_close = Close[i+1];
        double c1_range = c1_high - c1_low;
        if(c1_range == 0) c1_range = Point;

        // 1. Find recent Pivot Low (starting from i+2 backward)
        double lastPL = 0;
        for(int j = i + 2 + RightBars; j < rates_total - LeftBars; j++)
        {
            int lowestIdx = iLowest(Symbol(), Period(), MODE_LOW, LeftBars + RightBars + 1, j - RightBars);
            if(lowestIdx == j) { lastPL = Low[j]; break; }
        }

        // 2. Find recent Pivot High (starting from i+2 backward)
        double lastPH = 0;
        for(int j = i + 2 + RightBars; j < rates_total - LeftBars; j++)
        {
            int highestIdx = iHighest(Symbol(), Period(), MODE_HIGH, LeftBars + RightBars + 1, j - RightBars);
            if(highestIdx == j) { lastPH = High[j]; break; }
        }

        // 3. Evaluate Bullish Purge
        if(lastPL > 0 && c1_low < lastPL && c1_close > lastPL)
        {
            double bullCloseDist = c1_close - lastPL;
            bool validBullClose  = bullCloseDist >= (c1_range * ReclaimPct);
            bool bullConf        = Close[i] > lastPL && Close[i] >= c1_close;

            if(validBullClose && (!RequireConf || bullConf))
            {
                BullBuffer[i] = Low[i] - (10 * Point);
                
                string objName = "L_Purge_" + IntegerToString(Time[i]);
                if(ObjectFind(0, objName) < 0) {
                    ObjectCreate(0, objName, OBJ_TREND, 0, Time[i+1], lastPL, Time[i], lastPL);
                    ObjectSetInteger(0, objName, OBJPROP_COLOR, clrDodgerBlue);
                    ObjectSetInteger(0, objName, OBJPROP_STYLE, STYLE_DASH);
                    ObjectSetInteger(0, objName, OBJPROP_RAY_RIGHT, false);
                }
            }
        }

        // 4. Evaluate Bearish Purge
        if(lastPH > 0 && c1_high > lastPH && c1_close < lastPH)
        {
            double bearCloseDist = lastPH - c1_close;
            bool validBearClose  = bearCloseDist >= (c1_range * ReclaimPct);
            bool bearConf        = Close[i] < lastPH && Close[i] <= c1_close;

            if(validBearClose && (!RequireConf || bearConf))
            {
                BearBuffer[i] = High[i] + (10 * Point);
                
                string objName = "H_Purge_" + IntegerToString(Time[i]);
                if(ObjectFind(0, objName) < 0) {
                    ObjectCreate(0, objName, OBJ_TREND, 0, Time[i+1], lastPH, Time[i], lastPH);
                    ObjectSetInteger(0, objName, OBJPROP_COLOR, clrRed);
                    ObjectSetInteger(0, objName, OBJPROP_STYLE, STYLE_DASH);
                    ObjectSetInteger(0, objName, OBJPROP_RAY_RIGHT, false);
                }
            }
        }
    }
    return(rates_total);
}

Re: Stop-run reclaim on XAUUSD M1: how I define a valid reclaim candle

Posted: Sun Sep 20, 2026 8:49 pm
by PTScalper
MQL5 Implementation (.mq5)

MQL5 requires strict array management. The logic translates cleanly by setting the arrays AsSeries(true) so the indexing matches MQL4 ([0] is current, [1] is previous). This makes porting micro-structure logic between platforms seamless.

Code: Select all

//+------------------------------------------------------------------+
//|                                        M1_Liquidity_Reclaim.mq5 |
//+------------------------------------------------------------------+
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_plots   2

#property indicator_label1  "Bullish Reclaim"
#property indicator_type1   DRAW_ARROW
#property indicator_color1  clrDodgerBlue

#property indicator_label2  "Bearish Reclaim"
#property indicator_type2   DRAW_ARROW
#property indicator_color2  clrRed

//--- Inputs
input int    LeftBars       = 15;      // Swing Left (Bars)
input int    RightBars      = 5;       // Swing Right (Bars)
input double ReclaimPct     = 0.35;    // Min Reclaim % of Candle Range
input bool   RequireConf    = true;    // Require Next Candle Confirmation
input bool   UseSession     = true;    // Filter by Session
input string SessionStart   = "08:00"; // Session Start
input string SessionEnd     = "16:00"; // Session End

//--- Buffers
double BullBuffer[];
double BearBuffer[];

//+------------------------------------------------------------------+
int OnInit()
{
    SetIndexBuffer(0, BullBuffer, INDICATOR_DATA);
    PlotIndexSetInteger(0, PLOT_ARROW, 233);
    PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0.0);

    SetIndexBuffer(1, BearBuffer, INDICATOR_DATA);
    PlotIndexSetInteger(1, PLOT_ARROW, 234);
    PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, 0.0);

    return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
bool InSession(datetime time)
{
    if(!UseSession) return true;
    
    MqlDateTime dt;
    TimeToStruct(time, dt);
    
    int startMins = (int)StringToInteger(StringSubstr(SessionStart, 0, 2)) * 60 + (int)StringToInteger(StringSubstr(SessionStart, 3, 2));
    int endMins   = (int)StringToInteger(StringSubstr(SessionEnd, 0, 2)) * 60 + (int)StringToInteger(StringSubstr(SessionEnd, 3, 2));
    int currMins  = dt.hour * 60 + dt.min;
    
    if(startMins < endMins) return (currMins >= startMins && currMins <= endMins);
    return (currMins >= startMins || currMins <= endMins);
}

//+------------------------------------------------------------------+
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(rates_total < LeftBars + RightBars + 5) return 0;

    // Set arrays as series (Index 0 = Current Bar)
    ArraySetAsSeries(time, true);
    ArraySetAsSeries(high, true);
    ArraySetAsSeries(low, true);
    ArraySetAsSeries(close, true);
    ArraySetAsSeries(BullBuffer, true);
    ArraySetAsSeries(BearBuffer, true);

    int limit = rates_total - prev_calculated;
    if(prev_calculated == 0) 
        limit = rates_total - LeftBars - RightBars - 3;

    for(int i = limit; i >= 1; i--)
    {
        BullBuffer[i] = 0.0;
        BearBuffer[i] = 0.0;
        
        if(!InSession(time[i])) continue;

        double c1_high  = high[i+1];
        double c1_low   = low[i+1];
        double c1_close = close[i+1];
        double c1_range = c1_high - c1_low;
        if(c1_range == 0) c1_range = SymbolInfoDouble(_Symbol, SYMBOL_POINT);

        // Find Pivot Low
        double lastPL = 0;
        for(int j = i + 2 + RightBars; j < rates_total - LeftBars; j++)
        {
            int lowestIdx = ArrayMinimum(low, j - RightBars, LeftBars + RightBars + 1);
            if(lowestIdx == j) { lastPL = low[j]; break; }
        }

        // Find Pivot High
        double lastPH = 0;
        for(int j = i + 2 + RightBars; j < rates_total - LeftBars; j++)
        {
            int highestIdx = ArrayMaximum(high, j - RightBars, LeftBars + RightBars + 1);
            if(highestIdx == j) { lastPH = high[j]; break; }
        }

        // Bullish Reclaim Logic
        if(lastPL > 0 && c1_low < lastPL && c1_close > lastPL)
        {
            if((c1_close - lastPL) >= (c1_range * ReclaimPct))
            {
                if(!RequireConf || (close[i] > lastPL && close[i] >= c1_close))
                {
                    BullBuffer[i] = low[i] - (_Point * 10);
                    
                    string objName = "L_Purge_" + IntegerToString(time[i]);
                    if(ObjectFind(0, objName) < 0) {
                        ObjectCreate(0, objName, OBJ_TREND, 0, time[i+1], lastPL, time[i], lastPL);
                        ObjectSetInteger(0, objName, OBJPROP_COLOR, clrDodgerBlue);
                        ObjectSetInteger(0, objName, OBJPROP_STYLE, STYLE_DASH);
                        ObjectSetInteger(0, objName, OBJPROP_RAY_RIGHT, false);
                    }
                }
            }
        }

        // Bearish Reclaim Logic
        if(lastPH > 0 && c1_high > lastPH && c1_close < lastPH)
        {
            if((lastPH - c1_close) >= (c1_range * ReclaimPct))
            {
                if(!RequireConf || (close[i] < lastPH && close[i] <= c1_close))
                {
                    BearBuffer[i] = high[i] + (_Point * 10);
                    
                    string objName = "H_Purge_" + IntegerToString(time[i]);
                    if(ObjectFind(0, objName) < 0) {
                        ObjectCreate(0, objName, OBJ_TREND, 0, time[i+1], lastPH, time[i], lastPH);
                        ObjectSetInteger(0, objName, OBJPROP_COLOR, clrRed);
                        ObjectSetInteger(0, objName, OBJPROP_STYLE, STYLE_DASH);
                        ObjectSetInteger(0, objName, OBJPROP_RAY_RIGHT, false);
                    }
                }
            }
        }
    }
    return(rates_total);
}

Re: Stop-run reclaim on XAUUSD M1: how I define a valid reclaim candle

Posted: Sun Sep 20, 2026 8:49 pm
by PTScalper
Architectural Notes for MetaTrader

Array Indexing: I flipped the MT5 arrays to ArraySetAsSeries(true) immediately inside OnCalculate. This allows you to read the chart natively from right to left ([0] is current, [1] is previous), exactly matching Pine Script and MT4 logic without mental gymnastics.

Object Management: MetaTrader accumulates drawn objects infinitely. If you plan to drop this onto a VPS and let it run for weeks, you'll want to add an OnDeinit function containing ObjectsDeleteAll(0, "L_Purge_"); and ObjectsDeleteAll(0, "H_Purge_"); to clean the chart upon removal.

Trigger Logic: Both scripts evaluate exclusively on closed bars (scanning from i = 1). This permanently solves repainting. If you use this inside an Expert Advisor later, you can bind your order logic exactly to BullBuffer[1] != 0 triggering a pending or market order on the open of [0].