Advertisement IC Markets

Scalping XAU/USD

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

Scalping XAU/USD

Post by PTScalper »

Hi traders, scalpers,

Scalping XAUUSD (Spot Gold) effectively requires stripping away lagging indicators and focusing on institutional liquidity zones, multi-timeframe structure, and session volatility. Because gold exhibits aggressive stop-runs and sharp mean-reversion sweeps before continuing its primary move, combining higher-timeframe structural zones (H4/D1) with an execution trigger on the M15 (and optionally M5/M1 for micro-refinement) filters out intraday chop while capturing high-momentum price bursts.

1. Multi-Timeframe Architecture & Session Timing

Gold is heavily driven by institutional order flow during specific liquidity windows. Executing outside these windows exposes positions to erratic spread widening and low-volume whipsaws.

Structural Charts: D1 & H4 + Map major Support/Resistance (S/R) zones, previous day's High/Low (PDH/PDL), and major swing liquidity pools.

Primary Execution: M15 + Identify local market structure, rejection wicks, engulfing momentum candles, and false-breakout traps at H4/D1 levels.

Optional Micro-Timing: M5 / M1 + Fine-tune entry inside the M15 zone once a liquidity sweep completes.

Prime Trading Windows: Frankfurt / London Open (07:00–10:00 UTC) + London / NY Overlap (12:00–16:00 UTC) + Highest tick volume, cleanest structural breakouts, and tightest raw spreads on ECN accounts.

No-Trade Windows: + Rollover (21:00–23:00 UTC) & 5 mins pre/post Tier-1 US News (CPI, NFP, FOMC) + Avoids severe slippage and liquidity vacuums.
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: 7643
Joined: Mon Jul 20, 2026 1:28 pm

Re: Scalping XAU/USD

Post by PTScalper »

2. Two Core Pure Price Action Setups

Rather than relying on lagging oscillators, this framework focuses on how price reacts when it tests pre-marked H4/D1 horizontal zones during active sessions.

Setup A: Liquidity Sweep & Reclaim (The Stop-Run Fade)

Gold frequently pierces obvious H4/D1 support or resistance by $1.50 to $4.00 (15–40 pips) to trigger retail breakout buyers and sweep resting stop-losses before reversing sharply.

Zone Preparation: Mark key H4/D1 horizontal S/R zones, along with the Previous Day High (PDH), Previous Day Low (PDL), and Asian/London session extremes.

The Trap (Sweep): Wait for price to aggressively spike through the marked H4/D1 level during the London or NY session.

M15 Confirmation (Reclaim): Do not fade the move blindly. Wait for the M15 candle to close back inside the structural level, leaving a pronounced rejection wick (pin bar) or forming an immediate M15 engulfing candle in the opposite direction.

Execution: Enter at the close of the M15 confirmation candle (or on a quick micro-retest of the broken level's body).
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 7643
Joined: Mon Jul 20, 2026 1:28 pm

Re: Scalping XAU/USD

Post by PTScalper »

Setup B: Impulse Breakout & Micro-Retest (Momentum Continuation)

When macroeconomic flows drive heavy directional volume, gold breaks through H4 zones without looking back.

Breakout Identification: An M15 candle closes decisively beyond an H4/D1 S/R zone or intraday consolidation box with a full-bodied marubozu candle (minimal upper/lower wicks).

The Pullback: Wait for the subsequent 1 to 3 candles on the M15 (or M5) chart to pull back into the broken resistance-turned-support (or support-turned-resistance) zone.

Trigger: Enter as soon as price stalls at the retest level and prints a rejection wick or bullish/bearish momentum shift, riding the immediate continuation impulse.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 7643
Joined: Mon Jul 20, 2026 1:28 pm

Re: Scalping XAU/USD

Post by PTScalper »

3. Risk, Position Sizing & Series Money Management

High-frequency gold scalping works best when structured into defined trading series (e.g., 2 to 6 weeks) using isolated risk capital and exponential profit compounding.

Hard Stop-Loss & Target Structure: Place your hard stop-loss just beyond the extreme wick of the liquidity sweep (typically $3.00 to $6.00 on XAUUSD depending on current M15 volatility). For high-win-rate momentum scalping where you capture the immediate meat of the impulse (e.g., targeting $1.50 to $2.50 per scalp with a wider structural stop at a 3:1 risk-to-reward profile, or 1:1 to 1:1.5 when fading extreme wicks), execution discipline is paramount: if price fails to move in your favor within 2–3 M15 candles, scratch the trade early rather than waiting for the full stop to be hit.

Risk-Free Exponential Scaling (Series Approach):

Phase 1 (Base Cushion): Start the 2–6 week series risking a fixed 2% to 5% of your dedicated series risk capital per setup.

Phase 2 (Compounding Accrued Profits): Once you build a profit buffer (e.g., +15% to +20% on the series), lock in your initial deposit baseline and calculate subsequent position sizes using a portion of the accrued profits. This allows lot sizes to scale exponentially during hot streaks while keeping your core capital protected.

Daily Circuit Breaker: Enforce a hard daily drawdown limit (e.g., 2 consecutive full stop-outs in a single session). When hit, close the charts and step away to preserve the series equity curve.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 7643
Joined: Mon Jul 20, 2026 1:28 pm

Re: Scalping XAU/USD

Post by PTScalper »

4. Pre-Session Execution Checklist

Mark Higher-Timeframe Levels: Before Frankfurt/London open, plot the nearest H4 and D1 horizontal S/R zones, plus PDH and PDL.

Check the Macro Calendar: Identify exact times for US Bond Auctions, CPI, PPI, NFP, Jobless Claims, and Fed speakers.

Wait for Price to Reach the Zone: Ignore mid-range price action. Set price alerts at your H4 boundaries so you only engage when XAUUSD taps institutional liquidity.

Verify M15 Candle Closure: Let the M15 candle finish forming at the key level—never pre-empt a rejection while the candle is still expanding.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 7643
Joined: Mon Jul 20, 2026 1:28 pm

Re: Scalping XAU/USD

Post by PTScalper »

Below is the complete, production-ready MQL5 Expert Advisor (XAUUSD_PurePriceAction_Scalper.mq5) implementing the multi-timeframe liquidity sweep and breakout-retest strategy.

The architecture uses native MQL5 CTrade execution, multi-timeframe structural fractal scanning (H4 & D1), Previous Day High/Low (PDH/PDL) mapping, session time filtering, a time-based scratch exit for stalled trades, and Two-Phase Series Exponential Money Management (compounding accrued profits once your target cushion is reached).
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 7643
Joined: Mon Jul 20, 2026 1:28 pm

Re: Scalping XAU/USD

Post by PTScalper »

Complete MQL5 Expert Advisor Code

Save this file in your MetaTrader 5 MQL5/Experts/ directory and compile it in MetaEditor (F7). Attach it directly to an XAUUSD M15 chart.

Code: Select all

//+------------------------------------------------------------------+
//|                               XAUUSD_PurePriceAction_Scalper.mq5 |
//|                     Multi-TF H4/D1 Zone & M15 Price Action EA    |
//+------------------------------------------------------------------+
#property copyright "PTScalper Quant Architecture"
#property version   "1.00"
#property strict

#include <Trade\Trade.mqh>
#include <Trade\PositionInfo.mqh>
#include <Trade\AccountInfo.mqh>

//--- Input Parameters: Strategy & Zones
input group "=== 1. Multi-Timeframe Structure (H4 / D1) ==="
input int      InpLookbackH4         = 120;      // H4 Bars Lookback for Swing Zones
input int      InpLookbackD1         = 40;       // D1 Bars Lookback for Swing Zones
input int      InpFractalStrength    = 2;        // Swing Fractal Bars Left/Right
input double   InpZoneToleranceUSD   = 0.80;     // Zone Touch / Merge Tolerance ($ in Gold)
input double   InpMaxSweepDepthUSD   = 4.50;     // Max Allowed Liquidity Sweep Pierce ($ in Gold)
input bool     InpEnableSetupA       = true;     // Enable Setup A: Liquidity Sweep & Reclaim
input bool     InpEnableSetupB       = true;     // Enable Setup B: Breakout & Micro-Retest
input bool     InpDrawZones          = true;     // Draw H4/D1 Structural Lines on Chart

//--- Input Parameters: Execution, Stops & Scratch Filter
input group "=== 2. Risk-Reward & Time Scratch Rules ==="
input double   InpMinStopLossUSD     = 3.00;     // Minimum Structural Stop Loss ($ in Gold)
input double   InpMaxStopLossUSD     = 6.50;     // Maximum Structural Stop Loss ($ in Gold)
input double   InpStopBufferUSD      = 0.50;     // Extra Buffer Beyond Sweep Wick ($ in Gold)
input double   InpRiskToRewardRatio  = 3.0;      // Risk-to-Reward Ratio (e.g., 3.0 = Risk 3 : Reward 1)
input int      InpScratchMaxBars     = 3;        // Time-Scratch: Max M15 Bars if Trade Stalls (0=Off)
input double   InpScratchMinProfitUSD= 0.25;     // Min Favorable Move ($) to Avoid Time-Scratch

//--- Input Parameters: Series Money Management
input group "=== 3. Series Exponential Money Management ==="
input double   InpSeriesStartCapital = 5000.0;   // Series Baseline Capital (Account Currency)
input double   InpPhase1BaseRiskPct  = 3.0;      // Phase 1: Base Risk % per Trade (2% - 5%)
input double   InpPhase2TriggerPct   = 15.0;     // Profit Buffer % to Unlock Phase 2 Compounding
input double   InpPhase2ProfitRiskPct= 25.0;     // Phase 2: % of Accrued Profits Risked per Trade
input int      InpMaxDailyLosses     = 2;        // Daily Circuit Breaker (Max Consecutive Full Losses)

//--- Input Parameters: Session & Broker Filters
input group "=== 4. Session Windows (Server / UTC Time) ==="
input bool     InpUseSessionFilter   = true;     // Restrict to London & NY Sessions
input int      InpSession1StartHour  = 7;        // Session 1 Start Hour (Frankfurt/London Open)
input int      InpSession1EndHour    = 10;       // Session 1 End Hour
input int      InpSession2StartHour  = 12;       // Session 2 Start Hour (London/NY Overlap)
input int      InpSession2EndHour    = 16;       // Session 2 End Hour
input int      InpMaxSpreadPoints    = 35;       // Max Allowed Spread (in Broker Points)
input ulong    InpMagicNumber        = 20261025; // EA Magic Number

//--- Global Objects & State Variables
CTrade         ExtTrade;
CPositionInfo  ExtPosition;
CAccountInfo   ExtAccount;

datetime       g_lastM15BarTime      = 0;
datetime       g_lastZoneUpdateH4    = 0;
double         g_srLevels[];

// Breakout State Tracking for Setup B
double         g_activeBreakoutLevel = 0.0;
int            g_breakoutDirection   = 0;        // 1 = Bullish Breakout, -1 = Bearish Breakout
datetime       g_breakoutBarTime     = 0;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   ExtTrade.SetExpertMagicNumber(InpMagicNumber);
   ExtTrade.SetMarginMode();
   ExtTrade.SetTypeFillingBySymbol(_Symbol);
   ExtTrade.SetDeviationInPoints(20);

   RebuildStructuralZones();
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   ObjectsDeleteAll(0, "XAU_SR_");
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
   // 1. Manage Open Positions (Time-Based Scratch Exit on Stalled Momentum)
   ManageOpenPositions();

   // 2. Process New M15 Candle Closure Only for Pure Price Action Signals
   datetime currentM15Bar = iTime(_Symbol, PERIOD_M15, 0);
   if(currentM15Bar == g_lastM15BarTime)
      return;

   // Check Session Filter & Daily Circuit Breaker before evaluating signals
   if(!IsWithinTradingSession())
      return;

   if(IsDailyCircuitBreakerHit())
      return;

   // Check Spread Filter
   long currentSpread = SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
   if(currentSpread > InpMaxSpreadPoints)
      return;

   // Refresh H4/D1 Structural Zones when a new H4 bar opens
   datetime currentH4Bar = iTime(_Symbol, PERIOD_H4, 0);
   if(currentH4Bar != g_lastZoneUpdateH4)
   {
      RebuildStructuralZones();
      g_lastZoneUpdateH4 = currentH4Bar;
   }

   // Mark current M15 bar as processed
   g_lastM15BarTime = currentM15Bar;

   // Skip new entries if a position is already open
   if(HasOpenPosition())
      return;

   // 3. Evaluate Pure Price Action Setups on Closed M15 Bar (Shift 1)
   EvaluateM15PriceAction();
}

//+------------------------------------------------------------------+
//| Build & Merge H4, D1, and PDH/PDL Support/Resistance Zones       |
//+------------------------------------------------------------------+
void RebuildStructuralZones()
{
   ArrayResize(g_srLevels, 0);

   // 1. Add Previous Day High (PDH) and Previous Day Low (PDL)
   double pdh = iHigh(_Symbol, PERIOD_D1, 1);
   double pdl = iLow(_Symbol, PERIOD_D1, 1);
   if(pdh > 0) AddOrMergeLevel(pdh);
   if(pdl > 0) AddOrMergeLevel(pdl);

   // 2. Scan D1 Swing Fractals
   ScanTimeframeFractals(PERIOD_D1, InpLookbackD1);

   // 3. Scan H4 Swing Fractals
   ScanTimeframeFractals(PERIOD_H4, InpLookbackH4);

   // 4. Render Structural Lines on Chart
   if(InpDrawZones)
      DrawZonesOnChart();
}

//+------------------------------------------------------------------+
//| Scan Timeframe for Swing High/Low Fractals                       |
//+------------------------------------------------------------------+
void ScanTimeframeFractals(ENUM_TIMEFRAMES tf, int lookback)
{
   int s = InpFractalStrength;
   for(int i = s + 1; i <= lookback - s; i++)
   {
      double highVal = iHigh(_Symbol, tf, i);
      double lowVal  = iLow(_Symbol, tf, i);
      bool isSwingHigh = true;
      bool isSwingLow  = true;

      for(int k = 1; k <= s; k++)
      {
         if(iHigh(_Symbol, tf, i - k) >= highVal || iHigh(_Symbol, tf, i + k) > highVal)
            isSwingHigh = false;
         if(iLow(_Symbol, tf, i - k) <= lowVal || iLow(_Symbol, tf, i + k) < lowVal)
            isSwingLow = false;
      }

      if(isSwingHigh) AddOrMergeLevel(highVal);
      if(isSwingLow)  AddOrMergeLevel(lowVal);
   }
}

//+------------------------------------------------------------------+
//| Deduplicate and cluster nearby S/R levels                        |
//+------------------------------------------------------------------+
void AddOrMergeLevel(double price)
{
   int total = ArraySize(g_srLevels);
   for(int i = 0; i < total; i++)
   {
      if(MathAbs(g_srLevels[i] - price) <= InpZoneToleranceUSD)
      {
         // Average the level cluster
         g_srLevels[i] = (g_srLevels[i] + price) * 0.5;
         return;
      }
   }
   ArrayResize(g_srLevels, total + 1);
   g_srLevels[total] = price;
}

//+------------------------------------------------------------------+
//| Evaluate Setup A (Sweep & Reclaim) and Setup B (Break & Retest)  |
//+------------------------------------------------------------------+
void EvaluateM15PriceAction()
{
   double o1 = iOpen(_Symbol, PERIOD_M15, 1);
   double h1 = iHigh(_Symbol, PERIOD_M15, 1);
   double l1 = iLow(_Symbol, PERIOD_M15, 1);
   double c1 = iClose(_Symbol, PERIOD_M15, 1);

   double o2 = iOpen(_Symbol, PERIOD_M15, 2);
   double c2 = iClose(_Symbol, PERIOD_M15, 2);

   double range1     = MathMax(h1 - l1, 0.01);
   double body1      = MathAbs(c1 - o1);
   double upperWick1 = h1 - MathMax(o1, c1);
   double lowerWick1 = MathMin(o1, c1) - l1;

   int totalLevels = ArraySize(g_srLevels);

   //-----------------------------------------------------------------
   // SETUP A: Liquidity Sweep & Reclaim (Stop-Run Fade)
   //-----------------------------------------------------------------
   if(InpEnableSetupA)
   {
      for(int i = 0; i < totalLevels; i++)
      {
         double lvl = g_srLevels[i];

         // 1. Bullish Sweep & Reclaim at Support:
         // Low pierces below lvl, Close reclaims above lvl, strong lower rejection wick OR bullish engulfing
         double bullSweepDepth = lvl - l1;
         if(l1 < lvl && c1 > lvl && bullSweepDepth >= 0.25 && bullSweepDepth <= InpMaxSweepDepthUSD)
         {
            bool isPinRejection = (lowerWick1 >= range1 * 0.45);
            bool isBullEngulf   = (c1 > o1 && c1 > MathMax(o2, c2) && body1 >= range1 * 0.45);

            if(isPinRejection || isBullEngulf)
            {
               ExecuteScalpOrder(ORDER_TYPE_BUY, l1 - InpStopBufferUSD, "SetupA_BullSweep");
               return;
            }
         }

         // 2. Bearish Sweep & Reclaim at Resistance:
         // High pierces above lvl, Close reclaims below lvl, strong upper rejection wick OR bearish engulfing
         double bearSweepDepth = h1 - lvl;
         if(h1 > lvl && c1 < lvl && bearSweepDepth >= 0.25 && bearSweepDepth <= InpMaxSweepDepthUSD)
         {
            bool isPinRejection = (upperWick1 >= range1 * 0.45);
            bool isBearEngulf   = (c1 < o1 && c1 < MathMin(o2, c2) && body1 >= range1 * 0.45);

            if(isPinRejection || isBearEngulf)
            {
               ExecuteScalpOrder(ORDER_TYPE_SELL, h1 + InpStopBufferUSD, "SetupA_BearSweep");
               return;
            }
         }
      }
   }

   //-----------------------------------------------------------------
   // SETUP B: Impulse Breakout & Micro-Retest
   //-----------------------------------------------------------------
   if(InpEnableSetupB)
   {
      datetime bar1Time = iTime(_Symbol, PERIOD_M15, 1);

      // Step 1: Check if an active breakout is currently waiting for a 1-3 bar micro-retest
      if(g_breakoutDirection != 0 && g_activeBreakoutLevel > 0)
      {
         int barsSinceBreakout = iBarShift(_Symbol, PERIOD_M15, g_breakoutBarTime);

         if(barsSinceBreakout >= 1 && barsSinceBreakout <= 3)
         {
            // Bullish Retest: Price pulls back to touch broken resistance (within tolerance) and closes above
            if(g_breakoutDirection == 1)
            {
               if(l1 <= g_activeBreakoutLevel + InpZoneToleranceUSD && c1 > g_activeBreakoutLevel && (c1 > o1 || lowerWick1 >= range1 * 0.40))
               {
                  double sl = l1 - InpStopBufferUSD;
                  g_breakoutDirection = 0;
                  ExecuteScalpOrder(ORDER_TYPE_BUY, sl, "SetupB_BullRetest");
                  return;
               }
            }
            // Bearish Retest: Price pulls back to touch broken support (within tolerance) and closes below
            else if(g_breakoutDirection == -1)
            {
               if(h1 >= g_activeBreakoutLevel - InpZoneToleranceUSD && c1 < g_activeBreakoutLevel && (c1 < o1 || upperWick1 >= range1 * 0.40))
               {
                  double sl = h1 + InpStopBufferUSD;
                  g_breakoutDirection = 0;
                  ExecuteScalpOrder(ORDER_TYPE_SELL, sl, "SetupB_BearRetest");
                  return;
               }
            }
         }
         else if(barsSinceBreakout > 3)
         {
            // Expire un-retested breakout after 3 M15 bars
            g_breakoutDirection   = 0;
            g_activeBreakoutLevel = 0.0;
         }
      }

      // Step 2: Detect a fresh Marubozu Impulse Breakout across an H4/D1 Zone
      bool isImpulseBody = (body1 >= range1 * 0.68 && range1 >= 1.80);
      if(isImpulseBody)
      {
         for(int i = 0; i < totalLevels; i++)
         {
            double lvl = g_srLevels[i];
            // Bullish Impulse Breakout
            if(o1 < lvl && c1 > lvl + (InpZoneToleranceUSD * 0.5))
            {
               g_activeBreakoutLevel = lvl;
               g_breakoutDirection   = 1;
               g_breakoutBarTime     = bar1Time;
               break;
            }
            // Bearish Impulse Breakout
            if(o1 > lvl && c1 < lvl - (InpZoneToleranceUSD * 0.5))
            {
               g_activeBreakoutLevel = lvl;
               g_breakoutDirection   = -1;
               g_breakoutBarTime     = bar1Time;
               break;
            }
         }
      }
   }
}

//+------------------------------------------------------------------+
//| Execute Scalp Order with Series Compounding & 3:1 Risk/Reward    |
//+------------------------------------------------------------------+
void ExecuteScalpOrder(ENUM_ORDER_TYPE orderType, double rawStopPrice, string setupTag)
{
   double entryPrice = (orderType == ORDER_TYPE_BUY)
                       ? SymbolInfoDouble(_Symbol, SYMBOL_ASK)
                       : SymbolInfoDouble(_Symbol, SYMBOL_BID);

   double slDistanceUSD = MathAbs(entryPrice - rawStopPrice);

   // Clamp Stop Loss within structural min/max bounds ($3.00 to $6.50 default)
   if(slDistanceUSD < InpMinStopLossUSD)
      slDistanceUSD = InpMinStopLossUSD;
   if(slDistanceUSD > InpMaxStopLossUSD)
      return; // Skip trade if structural stop is abnormally wide

   // Calculate Target Distance based on Risk:Reward Ratio
   // Note: InpRiskToRewardRatio = 3.0 means Risk 3 units to make 1 unit of quick scalp reward
   double tpDistanceUSD = slDistanceUSD / InpRiskToRewardRatio;

   double slPrice = (orderType == ORDER_TYPE_BUY)
                    ? NormalizeDouble(entryPrice - slDistanceUSD, _Digits)
                    : NormalizeDouble(entryPrice + slDistanceUSD, _Digits);

   double tpPrice = (orderType == ORDER_TYPE_BUY)
                    ? NormalizeDouble(entryPrice + tpDistanceUSD, _Digits)
                    : NormalizeDouble(entryPrice - tpDistanceUSD, _Digits);

   // Calculate Dynamic Lot Size via Series Money Management
   double lots = CalculateSeriesPositionSize(slDistanceUSD);
   if(lots <= 0.0)
      return;

   if(orderType == ORDER_TYPE_BUY)
      ExtTrade.Buy(lots, _Symbol, entryPrice, slPrice, tpPrice, setupTag);
   else
      ExtTrade.Sell(lots, _Symbol, entryPrice, slPrice, tpPrice, setupTag);
}

//+------------------------------------------------------------------+
//| Two-Phase Series Exponential Money Management                    |
//+------------------------------------------------------------------+
double CalculateSeriesPositionSize(double slDistancePrice)
{
   double currentBalance = ExtAccount.Balance();
   double accruedProfit  = currentBalance - InpSeriesStartCapital;
   double profitTrigger  = InpSeriesStartCapital * (InpPhase2TriggerPct / 100.0);

   double riskMoney = 0.0;

   // Phase 2: Accrued Profit Cushion Reached -> Risk % of Accrued Profits (Core Protected)
   if(accruedProfit >= profitTrigger)
   {
      riskMoney = accruedProfit * (InpPhase2ProfitRiskPct / 100.0);
   }
   // Phase 1: Building Base Cushion -> Risk Fixed % of Series Capital
   else
   {
      double effectiveCapital = MathMin(currentBalance, InpSeriesStartCapital);
      riskMoney = effectiveCapital * (InpPhase1BaseRiskPct / 100.0);
   }

   double tickSize  = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
   double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
   if(tickSize <= 0 || tickValue <= 0 || slDistancePrice <= 0)
      return 0.0;

   double lossPerLot = (slDistancePrice / tickSize) * tickValue;
   if(lossPerLot <= 0)
      return 0.0;

   double rawLots  = riskMoney / lossPerLot;
   double minLot   = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
   double maxLot   = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
   double lotStep  = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);

   double normalizedLots = MathFloor(rawLots / lotStep) * lotStep;
   normalizedLots = MathMax(minLot, MathMin(maxLot, normalizedLots));

   return NormalizeDouble(normalizedLots, 2);
}

//+------------------------------------------------------------------+
//| Time-Based Scratch Exit if Momentum Fails Within N M15 Candles   |
//+------------------------------------------------------------------+
void ManageOpenPositions()
{
   if(InpScratchMaxBars <= 0)
      return;

   for(int i = PositionsTotal() - 1; i >= 0; i--)
   {
      if(!ExtPosition.SelectByIndex(i))
         continue;

      if(ExtPosition.Symbol() != _Symbol || ExtPosition.Magic() != InpMagicNumber)
         continue;

      datetime openTime = (datetime)ExtPosition.Time();
      int barsHeld      = iBarShift(_Symbol, PERIOD_M15, openTime);

      if(barsHeld >= InpScratchMaxBars)
      {
         double openPrice    = ExtPosition.PriceOpen();
         double currentPrice = ExtPosition.PriceCurrent();
         double priceDelta   = (ExtPosition.PositionType() == POSITION_TYPE_BUY)
                               ? (currentPrice - openPrice)
                               : (openPrice - currentPrice);

         // If trade has not moved favorably by at least InpScratchMinProfitUSD after N M15 candles, scratch it
         if(priceDelta < InpScratchMinProfitUSD)
         {
            ExtTrade.PositionClose(ExtPosition.Ticket());
         }
      }
   }
}

//+------------------------------------------------------------------+
//| Helper: Check if an EA Position is Currently Open                |
//+------------------------------------------------------------------+
bool HasOpenPosition()
{
   for(int i = PositionsTotal() - 1; i >= 0; i--)
   {
      if(ExtPosition.SelectByIndex(i))
      {
         if(ExtPosition.Symbol() == _Symbol && ExtPosition.Magic() == InpMagicNumber)
            return true;
      }
   }
   return false;
}

//+------------------------------------------------------------------+
//| Helper: Check London & NY Liquidity Windows                      |
//+------------------------------------------------------------------+
bool IsWithinTradingSession()
{
   if(!InpUseSessionFilter)
      return true;

   MqlDateTime dt;
   TimeGMT(dt); // Evaluates against UTC time

   bool inSession1 = (dt.hour >= InpSession1StartHour && dt.hour < InpSession1EndHour);
   bool inSession2 = (dt.hour >= InpSession2StartHour && dt.hour < InpSession2EndHour);

   return (inSession1 || inSession2);
}

//+------------------------------------------------------------------+
//| Helper: Daily Circuit Breaker (Consecutive Stop-Outs Today)      |
//+------------------------------------------------------------------+
bool IsDailyCircuitBreakerHit()
{
   if(InpMaxDailyLosses <= 0)
      return false;

   MqlDateTime dt;
   TimeCurrent(dt);
   dt.hour = 0; dt.min = 0; dt.sec = 0;
   datetime dayStart = StructToTime(dt);

   if(!HistorySelect(dayStart, TimeCurrent()))
      return false;

   int consecutiveLosses = 0;
   int totalDeals        = HistoryDealsTotal();

   for(int i = totalDeals - 1; i >= 0; i--)
   {
      ulong dealTicket = HistoryDealGetTicket(i);
      if(HistoryDealGetInteger(dealTicket, DEAL_MAGIC) != (long)InpMagicNumber)
         continue;
      if(HistoryDealGetString(dealTicket, DEAL_SYMBOL) != _Symbol)
         continue;
      if(HistoryDealGetInteger(dealTicket, DEAL_ENTRY) != DEAL_ENTRY_OUT)
         continue;

      double profit = HistoryDealGetDouble(dealTicket, DEAL_PROFIT);
      long reason   = HistoryDealGetInteger(dealTicket, DEAL_REASON);

      // Count full SL hits (ignore minor time-scratches unless significant)
      if(profit < 0 && reason == DEAL_REASON_SL)
      {
         consecutiveLosses++;
         if(consecutiveLosses >= InpMaxDailyLosses)
            return true;
      }
      else if(profit > 0)
      {
         break; // Streak broken by a winning trade
      }
   }
   return false;
}

//+------------------------------------------------------------------+
//| Render H4/D1 Structural Lines on Chart                           |
//+------------------------------------------------------------------+
void DrawZonesOnChart()
{
   ObjectsDeleteAll(0, "XAU_SR_");
   int total = ArraySize(g_srLevels);
   for(int i = 0; i < total; i++)
   {
      string objName = "XAU_SR_" + IntegerToString(i);
      ObjectCreate(0, objName, OBJ_HLINE, 0, 0, g_srLevels[i]);
      ObjectSetInteger(0, objName, OBJPROP_COLOR, clrGoldenrod);
      ObjectSetInteger(0, objName, OBJPROP_STYLE, STYLE_DOT);
      ObjectSetInteger(0, objName, OBJPROP_WIDTH, 1);
      ObjectSetInteger(0, objName, OBJPROP_BACK, true);
   }
}
//+------------------------------------------------------------------+
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 7643
Joined: Mon Jul 20, 2026 1:28 pm

Re: Scalping XAU/USD

Post by PTScalper »

How Key Architectural Mechanisms Work

Dynamic H4/D1 Zone Engine:

RebuildStructuralZones() runs automatically at the start of every new H4 candle. It fetches PDH/PDL and scans PERIOD_D1 and PERIOD_H4 for swing fractals, clustering any levels within $0.80 (InpZoneToleranceUSD) into a single unified liquidity zone.

3:1 Risk-to-Reward Profile:

Controlled by InpRiskToRewardRatio = 3.0. When a $4.50 structural stop is placed behind a liquidity sweep wick, the take-profit is automatically set at $1.50 (slDistanceUSD / 3.0) to capture the high-probability post-sweep impulse. Set it to 0.5 or 0.33 if you ever want to invert the ratio for runner tests.

Time-Based Scratch Filter:

ManageOpenPositions() checks iBarShift on the open position. If 3 M15 candles (InpScratchMaxBars) close and XAUUSD hasn't moved at least $0.25 in your favor, the EA closes the trade immediately at market to protect your 3:1 win-rate math from stagnant chop.

Two-Phase Series Sizing:

CalculateSeriesPositionSize() tracks account balance against InpSeriesStartCapital. Once accrued profit exceeds 15% (InpPhase2TriggerPct), it automatically locks in the initial deposit and calculates lot sizes using 25% of the accrued profit buffer.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
FXS HongKong Scalper
Posts: 407
Joined: Sat Oct 24, 2026 10:15 pm

Re: Scalping XAU/USD

Post by FXS HongKong Scalper »

The time-based scratch after 3 M15 candles is a good idea for gold. One concern with the 3:1 setting as described: a 4.50 stop with a 1.50 target needs a win rate above 75% after spread, and on XAUUSD the spread alone can be 0.20 to 0.40 in Asian hours, which is 13 to 27% of that target.

It would be worth printing the break even win rate including the average spread at entry time into the log, so users can see when the setup simply cannot pay for itself during the thin hours.
FXS Official Team | Hong Kong Session Desk
Shadow Trader
Posts: 5438
Joined: Wed Sep 09, 2026 5:19 pm

Re: Scalping XAU/USD

Post by Shadow Trader »

Each morning the People's Bank of China publishes a reference rate for the onshore yuan, and the market reads it as a signal. A fixing that is weaker than expected suggests the authorities are leaning against yuan strength, and a stronger one suggests the opposite. Offshore CNH trades freely around it, which makes it a live gauge of how markets feel about the arrangement.

That reading spills outward. AUD often behaves like a proxy for Chinese sentiment, so a sharp move in USD/CNH around the Asian morning can show up in AUD/USD within minutes. Other Asian currencies, such as the Korean won and Singapore dollar, sometimes follow as well.

Timing matters as well, since the reaction usually comes in the first stretch after the fixing and fades as Tokyo and other regional flows take over.

The link is not constant. On days dominated by US data or by Japanese flows, the yuan signal gets drowned out, and chasing it produces false starts.

Has anyone checked how closely AUD/USD follows USD/CNH after the fixing, and does it hold on quiet days as well as eventful ones?
Post Reply