Advertisement IC Markets

My own scalping strategies on GOLD (XAU/USD)

Discuss 1-minute to 15-minute price action setups, fading intraday momentum, key support/resistance zones, and proven short-term trading methodologies.
FTtrader
Posts: 954
Joined: Mon Aug 03, 2026 2:43 pm

My own scalping strategies on GOLD (XAU/USD)

Post by FTtrader »

Hi guys,

assuming you are trading XAU/USD CFDs with standard leverage, scalping gold requires strict discipline because of its high volatility and propensity for sudden reversals.

Here are three advanced tips for scalping gold effectively:

1. Capitalize on the NYLON Overlap
Gold spreads and volatility are most favorable during the London and New York session overlap (8:00 AM – 12:00 PM EST). When operating in fast-execution environments like cTrader or MetaTrader, minimizing spread drag is critical. This specific window provides the deep liquidity needed to get in and out of the market quickly without losing your profit margin to execution costs.

2. Align 15M Structure with 1M Execution
Gold is notorious for sharp wicks and fake breakouts (liquidity sweeps) that easily trap early buyers or sellers. Anchor your directional bias on a higher timeframe, such as the 15-minute chart, by checking if the price is holding above or below a major moving average like the 200 EMA. Once the trend is established, drop to the 1-minute chart to execute. Wait for price to attempt a false breakout against the trend and fail before entering your scalp.

3. Implement Volatility-Based Stop Losses
Using fixed pip stops in gold often results in getting stopped out prematurely by normal market noise. Instead, use an Average True Range (ATR) indicator to gauge current volatility. Place your hard stop-losses just outside the ATR range to survive sudden wicks, ensuring your profit target still maintains at least a 1:1.5 or 1:2 risk-to-reward ratio.

To implement the scalping strategy discussed previously within MetaTrader 4, you can leverage custom indicators to automate visual cues and mechanical rules.

Here is how you can use MT4 custom indicators to apply the three core tactics:

1. Visualizing the NYLON Overlap
Since you trade on MetaTrader, tracking session overlaps visually on lower timeframes is crucial for timing your entries.

Indicator Type: You need a Custom Session Overlay Indicator (e.g., "Global Trading Sessions Overlay" or similar tools available on MQL5).

Configuration:

Set the London Session parameters to visually map from 3:00 AM EST to 12:00 PM EST.

Set the New York Session parameters from 8:00 AM EST to 5:00 PM EST.

Application: Configure the indicator to highlight the 8:00 AM – 12:00 PM EST window (the overlap) in a distinct, slightly opaque background color. You will only look for scalping setups when price action occurs within this highlighted zone.

2. Multi-Timeframe (MTF) EMA Trend Filtering
Instead of manually switching between the 15-minute and 1-minute charts to determine the trend bias, you can use an MTF indicator to bring the higher timeframe data directly onto your execution chart.

Indicator Type: A Multi-Timeframe Moving Average Indicator (e.g., "TG Multi Timeframe Moving Average MT4").

Configuration:

Open your 1-minute execution chart.

In the custom indicator settings, set the TimeFrame parameter to M15 (15-minute).

Set the Method to Exponential (EMA) and the Period to your preferred trend baseline (e.g., 200).

Application: The indicator will plot the 15-minute 200 EMA directly on your 1-minute chart.

Rule: If the 1-minute price is below the plotted 15-minute EMA line, you only take short (sell) scalps. If the price is above it, you only take long (buy) scalps.

3. Dynamic Stop Loss with ATR
Gold's volatility requires a stop loss that adapts to current market conditions rather than a static pip amount.

Indicator Type: An ATR Trailing Stop Custom Indicator (e.g., "ATR Trailing Stop" from LuxAlgo or EarnForex).

Configuration:

Set the ATR Period short, typically between 5 and 7 for scalping.

Set the ATR Multiplier lower, such as 2.0. (A higher multiplier like 3.5 is for swing trading and will create too wide a stop for a 1-minute scalp).

Application: The indicator plots a dynamic trailing line above or below the price.

When you enter a buy trade based on your false breakout setup, place your initial hard stop-loss just below the plotted ATR trailing line.

If using an Expert Advisor version of the tool, it can automatically trail your stop loss based on the ATR line as the trade moves in your favor.
Recommended broker for automated trading & scalping IC Markets
PTScalper
Site Admin
Posts: 3349
Joined: Mon Jul 20, 2026 1:28 pm

Re: My own scalping strategies on GOLD (XAU/USD)

Post by PTScalper »

Hi FTtrader,

i read your strategy and make EA from it.
Please let me know, if it is like should be.

To translate the conceptual "false breakout" into executable code, this EA uses a price action liquidity sweep pattern: it looks for a candle that sweeps the previous candle's high/low against the 15-minute trend, but gets rejected and closes in the opposite direction (forming a pin bar or rejection wick).

Code for MT4 (MQL4)

Code: Select all

//+------------------------------------------------------------------+
//|                                                Gold_NYLON_EA.mq4 |
//|                                                                  |
//+------------------------------------------------------------------+
#property strict

//--- Input Parameters
input string   __1__             = "--- Time Filter (Broker Time) ---";
input int      StartHour         = 15;      // 8:00 AM EST (Adjust to your Broker GMT offset)
input int      EndHour           = 19;      // 12:00 PM EST (Adjust to your Broker GMT offset)

input string   __2__             = "--- Trend Filter (MTF) ---";
input ENUM_TIMEFRAMES TrendTF    = PERIOD_M15;
input int      EmaPeriod         = 200;

input string   __3__             = "--- Volatility & Risk ---";
input double   LotSize           = 0.1;
input int      AtrPeriod         = 7;
input double   AtrMultiplier     = 2.0;
input double   RiskReward        = 1.5;     // 1.5 means 1:1.5 R:R
input int      MagicNumber       = 888111;
input int      Slippage          = 30;      // In points for XAUUSD

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   // 1. Check if we already have an open trade
   if(CountOpenPositions() > 0) return;

   // 2. NYLON Overlap Time Filter
   int currentHour = TimeHour(TimeCurrent());
   if(currentHour < StartHour || currentHour >= EndHour) return;

   // 3. Multi-Timeframe EMA Calculation (15M 200 EMA)
   // Shift 1 is used to ensure we evaluate the closed 15M candle, preventing repainting
   double ema15m = iMA(Symbol(), TrendTF, EmaPeriod, 0, MODE_EMA, PRICE_CLOSE, 1);
   
   // 4. ATR Calculation for Volatility Stop
   double atr = iATR(Symbol(), 0, AtrPeriod, 1);

   // 5. Price Action Execution (1M Chart)
   // We look for a liquidity sweep (false breakout) and a rejection candle.
   
   double currentClose = Close[1];
   double currentOpen  = Open[1];
   double currentHigh  = High[1];
   double currentLow   = Low[1];
   double prevHigh     = High[2];
   double prevLow      = Low[2];

   // BUY LOGIC
   // Condition 1: Price is above the 15M 200 EMA (Uptrend)
   bool buyTrend = (currentClose > ema15m);
   
   // Condition 2: False breakdown (Sweeps previous low, but closes bullish in upper half)
   bool buySweep = (currentLow < prevLow) && 
                   (currentClose > currentOpen) && 
                   (currentClose > currentLow + (currentHigh - currentLow) * 0.5);

   if(buyTrend && buySweep)
     {
      double slDist = atr * AtrMultiplier;
      double sl = Ask - slDist;
      double tp = Ask + (slDist * RiskReward);
      
      sl = NormalizeDouble(sl, Digits);
      tp = NormalizeDouble(tp, Digits);
      
      int ticket = OrderSend(Symbol(), OP_BUY, LotSize, Ask, Slippage, sl, tp, "NYLON Gold Scalp", MagicNumber, 0, clrBlue);
      if(ticket < 0) Print("Buy Order Failed. Error: ", GetLastError());
     }

   // SELL LOGIC
   // Condition 1: Price is below the 15M 200 EMA (Downtrend)
   bool sellTrend = (currentClose < ema15m);
   
   // Condition 2: False breakout (Sweeps previous high, but closes bearish in lower half)
   bool sellSweep = (currentHigh > prevHigh) && 
                    (currentClose < currentOpen) && 
                    (currentClose < currentHigh - (currentHigh - currentLow) * 0.5);

   if(sellTrend && sellSweep)
     {
      double slDist = atr * AtrMultiplier;
      double sl = Bid + slDist;
      double tp = Bid - (slDist * RiskReward);
      
      sl = NormalizeDouble(sl, Digits);
      tp = NormalizeDouble(tp, Digits);
      
      int ticket = OrderSend(Symbol(), OP_SELL, LotSize, Bid, Slippage, sl, tp, "NYLON Gold Scalp", MagicNumber, 0, clrRed);
      if(ticket < 0) Print("Sell Order Failed. Error: ", GetLastError());
     }
  }

//+------------------------------------------------------------------+
//| Count open positions for this EA                                 |
//+------------------------------------------------------------------+
int CountOpenPositions()
  {
   int count = 0;
   for(int i = OrdersTotal() - 1; i >= 0; i--)
     {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
        {
         if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
           {
            count++;
           }
        }
     }
   return count;
  }
//+------------------------------------------------------------------+
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3349
Joined: Mon Jul 20, 2026 1:28 pm

Re: My own scalping strategies on GOLD (XAU/USD)

Post by PTScalper »

Key Implementation Details

Time Normalization: MT4 uses broker server time, not local or EST. You must adjust StartHour and EndHour to match your broker's GMT offset. If your broker is GMT+3 (standard for New York close pricing), 8:00 AM EST translates to 15:00 broker time.

The Sweep Trigger: Since standard indicators lag in fast execution, the logic uses pure 1-minute price action. A buy triggers if the price dips below the previous minute's low (the liquidity sweep/false breakout) but manages to close bullishly in the upper 50% of the candle's range.

ATR Math on XAU/USD: The ATR calculation naturally handles gold's point/pip decimal structure. Ask - (atr * AtrMultiplier) accurately sets the stop-loss distance without requiring manual point multiplication on standard CFD structures.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3349
Joined: Mon Jul 20, 2026 1:28 pm

Re: My own scalping strategies on GOLD (XAU/USD)

Post by PTScalper »

To elevate this from a basic script to a production-grade, professional Expert Advisor, we need to address the architectural reality of live MT4 environments. As a developer and trader, you know that raw strategy logic is only 20% of an EA; the other 80% is risk management, execution safety, and error handling.

Here are the architectural upgrades implemented in this "Pro" version:

ECN/STP Execution Compliance: Institutional and true ECN brokers often reject OrderSend requests that include pre-defined Stop Loss and Take Profit levels on market execution. This EA executes the market order first with 0 SL/TP, validates the ticket, and then routes it through OrderModify to apply the levels.

Bar-Close State Machine (IsNewBar): The previous script evaluated ticks dynamically, which risks intrabar repainting and multiple triggers. This version restricts entry evaluation strictly to the opening tick of a new 1-minute bar, locking in the previous candle's sweep and close conditions.

Dynamic Risk Auto-Sizing: Replaced fixed lots with a dynamic risk model calculating position size based on account balance percentage, tick value, and the dynamic ATR stop distance.

Trade Management (Break-Even & Trailing): Added logic to move the SL to break-even once a 1:1 risk-to-reward ratio is achieved, alongside an ATR-based trailing stop to ride extended liquidity runs.

Environmental Filters: Added a Maximum Spread filter to prevent execution during news spikes or rollover illiquidity, and an on-chart telemetry dashboard.

Code: Select all

//+------------------------------------------------------------------+
//|                                            Gold_NYLON_PRO_EA.mq4 |
//|                                        Production Grade Revision |
//+------------------------------------------------------------------+
#property strict

//--- 1. Risk Management
input string   __1__             = "--- Risk Management ---";
input bool     UseAutoLot        = true;
input double   RiskPercent       = 1.0;     // % of Balance to risk per trade
input double   FixedLot          = 0.1;     // Used if UseAutoLot is false

//--- 2. Strategy Parameters
input string   __2__             = "--- Strategy Logic ---";
input ENUM_TIMEFRAMES TrendTF    = PERIOD_M15;
input int      EmaPeriod         = 200;
input int      AtrPeriod         = 7;
input double   AtrStopMultiplier = 2.0;
input double   RiskRewardRatio   = 1.5;     // SL to TP Ratio

//--- 3. Trade Management
input string   __3__             = "--- Trade Management ---";
input bool     UseBreakEven      = true;    // Move SL to BE at 1:1 RR
input bool     UseTrailingStop   = false;   // Trail SL using ATR
input int      MaxSpreadPoints   = 40;      // Max allowed spread (in points)
input int      SlippagePoints    = 30;

//--- 4. Time Filters (Broker Time)
input string   __4__             = "--- Time Filter ---";
input int      StartHour         = 15;      // NYLON Start (e.g., 15:00 Broker Time)
input int      EndHour           = 19;      // NYLON End (e.g., 19:00 Broker Time)

//--- 5. EA System
input string   __5__             = "--- System ---";
input int      MagicNumber       = 888111;
input string   TradeComment      = "NYLON_PRO";

// Global Variables
datetime lastBarTime;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   if(Digits == 3 || Digits == 5) SlippagePoints *= 10; // Auto-adjust for 3/5 digit brokers
   lastBarTime = Time[0];
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   UpdateDashboard();
   ManageOpenTrades();

   // Only evaluate entries on the close of a candle (New Bar)
   if(!IsNewBar()) return;

   // Filter 1: Max Spread
   int currentSpread = (int)MarketInfo(Symbol(), MODE_SPREAD);
   if(currentSpread > MaxSpreadPoints) return;

   // Filter 2: Session Hours
   int currentHour = TimeHour(TimeCurrent());
   if(currentHour < StartHour || currentHour >= EndHour) return;

   // Filter 3: Existing Positions
   if(CountOpenPositions() > 0) return;

   EvaluateEntrySetups();
  }

//+------------------------------------------------------------------+
//| Core Entry Logic (Evaluated once per bar)                        |
//+------------------------------------------------------------------+
void EvaluateEntrySetups()
  {
   double ema15m = iMA(Symbol(), TrendTF, EmaPeriod, 0, MODE_EMA, PRICE_CLOSE, 1);
   double atr    = iATR(Symbol(), 0, AtrPeriod, 1);
   double slDist = atr * AtrStopMultiplier;
   
   // Candle 1 (Just Closed) & Candle 2 (Previous)
   double c1_Close = Close[1]; double c1_Open = Open[1];
   double c1_High  = High[1];  double c1_Low  = Low[1];
   double c2_High  = High[2];  double c2_Low  = Low[2];

   // --- BUY LOGIC ---
   bool buyTrend  = (c1_Close > ema15m);
   // Sweep: Pierced previous low, closed bullish, closed in upper 50% of range
   bool buySweep  = (c1_Low < c2_Low) && (c1_Close > c1_Open) && (c1_Close > c1_Low + (c1_High - c1_Low) * 0.5);

   if(buyTrend && buySweep)
     {
      double sl = Ask - slDist;
      double tp = Ask + (slDist * RiskRewardRatio);
      ExecuteTrade(OP_BUY, Ask, sl, tp, slDist);
      return;
     }

   // --- SELL LOGIC ---
   bool sellTrend = (c1_Close < ema15m);
   // Sweep: Pierced previous high, closed bearish, closed in lower 50% of range
   bool sellSweep = (c1_High > c2_High) && (c1_Close < c1_Open) && (c1_Close < c1_High - (c1_High - c1_Low) * 0.5);

   if(sellTrend && sellSweep)
     {
      double sl = Bid + slDist;
      double tp = Bid - (slDist * RiskRewardRatio);
      ExecuteTrade(OP_SELL, Bid, sl, tp, slDist);
     }
  }

//+------------------------------------------------------------------+
//| ECN Compliant Execution & Risk Sizing                            |
//+------------------------------------------------------------------+
void ExecuteTrade(int type, double price, double sl, double tp, double slDist)
  {
   sl = NormalizeDouble(sl, Digits);
   tp = NormalizeDouble(tp, Digits);
   
   double lot = FixedLot;
   if(UseAutoLot) lot = CalculateLotSize(slDist);
   
   color orderColor = (type == OP_BUY) ? clrBlue : clrRed;

   // 1. Send Order with 0 SL/TP for ECN/STP compatibility
   int ticket = OrderSend(Symbol(), type, lot, price, SlippagePoints, 0, 0, TradeComment, MagicNumber, 0, orderColor);
   
   // 2. Modify Order to apply SL/TP
   if(ticket > 0)
     {
      if(OrderSelect(ticket, SELECT_BY_TICKET))
        {
         bool mod = OrderModify(ticket, OrderOpenPrice(), sl, tp, 0, orderColor);
         if(!mod) Print("Error Modifying SL/TP for ticket ", ticket, " - Error: ", GetLastError());
        }
     }
   else
     {
      Print("Order Execution Failed. Error: ", GetLastError());
     }
  }

//+------------------------------------------------------------------+
//| Dynamic Position Sizing Math                                     |
//+------------------------------------------------------------------+
double CalculateLotSize(double slDistance)
  {
   double riskAmount = AccountBalance() * (RiskPercent / 100.0);
   double tickValue  = MarketInfo(Symbol(), MODE_TICKVALUE);
   double tickSize   = MarketInfo(Symbol(), MODE_TICKSIZE);
   
   if(tickSize == 0 || slDistance == 0) return FixedLot; // Failsafe
   
   double pointsAtRisk = slDistance / tickSize;
   double riskPerLot   = pointsAtRisk * tickValue;
   
   double calcLot = riskAmount / riskPerLot;
   
   // Normalize to broker step limits
   double minLot  = MarketInfo(Symbol(), MODE_MINLOT);
   double maxLot  = MarketInfo(Symbol(), MODE_MAXLOT);
   double lotStep = MarketInfo(Symbol(), MODE_LOTSTEP);
   
   calcLot = MathRound(calcLot / lotStep) * lotStep;
   if(calcLot < minLot) calcLot = minLot;
   if(calcLot > maxLot) calcLot = maxLot;
   
   return calcLot;
  }

//+------------------------------------------------------------------+
//| Trade Management (Break Even & Trailing)                         |
//+------------------------------------------------------------------+
void ManageOpenTrades()
  {
   for(int i = OrdersTotal() - 1; i >= 0; i--)
     {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
        {
         if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
           {
            double openPrice = OrderOpenPrice();
            double currentSL = OrderStopLoss();
            double currentTP = OrderTakeProfit();
            double initialSlDist = MathAbs(openPrice - currentSL); // Approximation if SL hasn't moved
            
            // BREAK EVEN LOGIC (Triggers when 1:1 RR is hit)
            if(UseBreakEven)
              {
               if(OrderType() == OP_BUY)
                 {
                  if(Bid >= openPrice + initialSlDist && currentSL < openPrice)
                    {
                     OrderModify(OrderTicket(), openPrice, openPrice + (2 * Point), currentTP, 0, clrGreen);
                    }
                 }
               else if(OrderType() == OP_SELL)
                 {
                  if(Ask <= openPrice - initialSlDist && (currentSL > openPrice || currentSL == 0))
                    {
                     OrderModify(OrderTicket(), openPrice, openPrice - (2 * Point), currentTP, 0, clrGreen);
                    }
                 }
              }

            // ATR TRAILING STOP LOGIC
            if(UseTrailingStop)
              {
               double atr = iATR(Symbol(), 0, AtrPeriod, 1);
               double trailDist = atr * AtrStopMultiplier;
               
               if(OrderType() == OP_BUY)
                 {
                  double newSL = NormalizeDouble(Bid - trailDist, Digits);
                  if(newSL > currentSL && Bid - newSL > Point)
                     OrderModify(OrderTicket(), openPrice, newSL, currentTP, 0, clrBlue);
                 }
               else if(OrderType() == OP_SELL)
                 {
                  double newSL = NormalizeDouble(Ask + trailDist, Digits);
                  if((newSL < currentSL || currentSL == 0) && newSL - Ask > Point)
                     OrderModify(OrderTicket(), openPrice, newSL, currentTP, 0, clrRed);
                 }
              }
           }
        }
     }
  }

//+------------------------------------------------------------------+
//| Utility: Check for New Bar                                       |
//+------------------------------------------------------------------+
bool IsNewBar()
  {
   datetime currentBarTime = Time[0];
   if(currentBarTime != lastBarTime)
     {
      lastBarTime = currentBarTime;
      return true;
     }
   return false;
  }

//+------------------------------------------------------------------+
//| Utility: Count Positions                                         |
//+------------------------------------------------------------------+
int CountOpenPositions()
  {
   int count = 0;
   for(int i = OrdersTotal() - 1; i >= 0; i--)
     {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
        if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
           count++;
     }
   return count;
  }

//+------------------------------------------------------------------+
//| Utility: On-Chart Telemetry Dashboard                            |
//+------------------------------------------------------------------+
void UpdateDashboard()
  {
   int currentSpread = (int)MarketInfo(Symbol(), MODE_SPREAD);
   double atr = iATR(Symbol(), 0, AtrPeriod, 1);
   double ema15m = iMA(Symbol(), TrendTF, EmaPeriod, 0, MODE_EMA, PRICE_CLOSE, 1);
   string trendStr = (Close[1] > ema15m) ? "BULLISH" : "BEARISH";
   
   string display = StringFormat(
      "--- NYLON Scalper Pro ---\n" +
      "Trend (15M 200 EMA): %s\n" +
      "Current Spread: %d points (Max: %d)\n" +
      "Current ATR: %.3f", 
      trendStr, currentSpread, MaxSpreadPoints, atr
   );
   
   Comment(display);
  }
//+------------------------------------------------------------------+
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3349
Joined: Mon Jul 20, 2026 1:28 pm

Re: My own scalping strategies on GOLD (XAU/USD)

Post by PTScalper »

Key Engineering Notes

Tick Value Abstraction: Calculating lot sizes on Gold CFDs is notoriously messy because brokers map contract sizes differently (e.g., 100 oz vs 1 oz). The CalculateLotSize function abstracts this by strictly relying on MODE_TICKVALUE and MODE_TICKSIZE from the MT4 server, making it mathematically universal across any broker's XAUUSD specification.

Bar Shifting: You'll notice iATR, iMA, and all price metrics (Close[1], High[1]) are hardcoded to shift 1. Because we gate the entire logic sequence behind IsNewBar(), shift 1 represents the newly closed bar, guaranteeing that the script runs against locked historical data and never repaints intra-minute.

Slippage Normalization: Standard MT4 Slippage is calculated in points, but 5-digit brokers require 10x the padding of 4-digit brokers. The OnInit() block automatically intercepts this and scales the integer so your inputs behave identically regardless of where you deploy it.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3349
Joined: Mon Jul 20, 2026 1:28 pm

Re: My own scalping strategies on GOLD (XAU/USD)

Post by PTScalper »

Plus i prepared version for MT5 traders:

Transitioning this architecture to MetaTrader 5 requires moving away from MQL4's procedural execution style and utilizing MT5’s object-oriented Standard Library.

Here is the production-grade MQL5 implementation. It leverages CTrade for execution safety and precise time-based buffer querying to prevent multi-timeframe repainting.

Code: Select all

//+------------------------------------------------------------------+
//|                                            Gold_NYLON_PRO_EA.mq5 |
//|                                  Production Grade MT5 Transition |
//+------------------------------------------------------------------+
#property strict

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

//--- 1. Risk Management
input string   __1__             = "--- Risk Management ---";
input bool     UseAutoLot        = true;
input double   RiskPercent       = 1.0;     // % of Balance to risk per trade
input double   FixedLot          = 0.1;     // Used if UseAutoLot is false

//--- 2. Strategy Parameters
input string   __2__             = "--- Strategy Logic ---";
input ENUM_TIMEFRAMES TrendTF    = PERIOD_M15;
input int      EmaPeriod         = 200;
input int      AtrPeriod         = 7;
input double   AtrStopMultiplier = 2.0;
input double   RiskRewardRatio   = 1.5;     // SL to TP Ratio

//--- 3. Trade Management
input string   __3__             = "--- Trade Management ---";
input bool     UseBreakEven      = true;    // Move SL to BE at 1:1 RR
input bool     UseTrailingStop   = false;   // Trail SL using ATR
input int      MaxSpreadPoints   = 40;      // Max allowed spread (in points)
input int      SlippagePoints    = 30;

//--- 4. Time Filters (Broker Time)
input string   __4__             = "--- Time Filter ---";
input int      StartHour         = 15;      // NYLON Start 
input int      EndHour           = 19;      // NYLON End 

//--- 5. EA System
input string   __5__             = "--- System ---";
input int      MagicNumber       = 888111;
input string   TradeComment      = "NYLON_PRO_MT5";

//--- Global Objects & Variables
CTrade         trade;
CSymbolInfo    symb;
CPositionInfo  posInfo;

int            atrHandle;
int            maHandle;
datetime       lastBarTime;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   symb.Name(_Symbol);
   symb.Refresh();
   
   if(_Digits == 3 || _Digits == 5) SlippagePoints *= 10;
   
   trade.SetExpertMagicNumber(MagicNumber);
   trade.SetDeviationInPoints(SlippagePoints);
   
   // Initialize Indicator Handles
   atrHandle = iATR(_Symbol, PERIOD_CURRENT, AtrPeriod);
   maHandle  = iMA(_Symbol, TrendTF, EmaPeriod, 0, MODE_EMA, PRICE_CLOSE);
   
   if(atrHandle == INVALID_HANDLE || maHandle == INVALID_HANDLE)
     {
      Print("Critical Error: Failed to initialize indicator handles.");
      return INIT_FAILED;
     }
     
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   UpdateDashboard();
   ManageOpenTrades();

   if(!IsNewBar()) return;

   int currentSpread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
   if(currentSpread > MaxSpreadPoints) return;

   MqlDateTime currentTime;
   TimeCurrent(currentTime);
   if(currentTime.hour < StartHour || currentTime.hour >= EndHour) return;

   if(CountOpenPositions() > 0) return;

   EvaluateEntrySetups();
  }

//+------------------------------------------------------------------+
//| Core Entry Logic                                                 |
//+------------------------------------------------------------------+
void EvaluateEntrySetups()
  {
   MqlRates rates[];
   ArraySetAsSeries(rates, true);
   
   // Copy last 3 M1 candles (0 = open/current, 1 = last closed, 2 = previous closed)
   if(CopyRates(_Symbol, PERIOD_CURRENT, 0, 3, rates) < 3) return;
   
   double atrBuffer[];
   if(CopyBuffer(atrHandle, 0, 1, 1, atrBuffer) <= 0) return;
   double atr = atrBuffer[0];
   double slDist = atr * AtrStopMultiplier;
   
   double maBuffer[];
   // Pro-level Data Sync: Fetch M15 MA value valid at the exact closing time of the M1 candle
   if(CopyBuffer(maHandle, 0, rates[1].time, 1, maBuffer) <= 0) return; 
   double ema15m = maBuffer[0];
   
   double c1_Close = rates[1].close; double c1_Open = rates[1].open;
   double c1_High  = rates[1].high;  double c1_Low  = rates[1].low;
   double c2_High  = rates[2].high;  double c2_Low  = rates[2].low;

   // --- BUY LOGIC ---
   bool buyTrend = (c1_Close > ema15m);
   bool buySweep = (c1_Low < c2_Low) && (c1_Close > c1_Open) && (c1_Close > c1_Low + (c1_High - c1_Low) * 0.5);

   if(buyTrend && buySweep)
     {
      double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
      double sl = ask - slDist;
      double tp = ask + (slDist * RiskRewardRatio);
      ExecuteTrade(ORDER_TYPE_BUY, ask, sl, tp, slDist);
      return;
     }

   // --- SELL LOGIC ---
   bool sellTrend = (c1_Close < ema15m);
   bool sellSweep = (c1_High > c2_High) && (c1_Close < c1_Open) && (c1_Close < c1_High - (c1_High - c1_Low) * 0.5);

   if(sellTrend && sellSweep)
     {
      double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
      double sl = bid + slDist;
      double tp = bid - (slDist * RiskRewardRatio);
      ExecuteTrade(ORDER_TYPE_SELL, bid, sl, tp, slDist);
     }
  }

//+------------------------------------------------------------------+
//| Object-Oriented Execution & Risk Sizing                          |
//+------------------------------------------------------------------+
void ExecuteTrade(ENUM_ORDER_TYPE type, double price, double sl, double tp, double slDist)
  {
   sl = NormalizeDouble(sl, _Digits);
   tp = NormalizeDouble(tp, _Digits);
   
   double lot = FixedLot;
   if(UseAutoLot) lot = CalculateLotSize(slDist);
   
   if(type == ORDER_TYPE_BUY)
     {
      if(!trade.Buy(lot, _Symbol, price, sl, tp, TradeComment))
         Print("Buy Order Failed: ", trade.ResultRetcodeDescription());
     }
   else if(type == ORDER_TYPE_SELL)
     {
      if(!trade.Sell(lot, _Symbol, price, sl, tp, TradeComment))
         Print("Sell Order Failed: ", trade.ResultRetcodeDescription());
     }
  }

//+------------------------------------------------------------------+
//| Dynamic Position Sizing Math (Universal CFD handling)            |
//+------------------------------------------------------------------+
double CalculateLotSize(double slDistance)
  {
   double riskAmount = AccountInfoDouble(ACCOUNT_BALANCE) * (RiskPercent / 100.0);
   double tickValue  = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
   double tickSize   = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
   
   if(tickSize == 0 || slDistance == 0) return FixedLot;
   
   double pointsAtRisk = slDistance / tickSize;
   double riskPerLot   = pointsAtRisk * tickValue;
   
   if(riskPerLot <= 0) return FixedLot;
   double calcLot = riskAmount / riskPerLot;
   
   double minLot  = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
   double maxLot  = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
   double lotStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
   
   calcLot = MathRound(calcLot / lotStep) * lotStep;
   if(calcLot < minLot) calcLot = minLot;
   if(calcLot > maxLot) calcLot = maxLot;
   
   return calcLot;
  }

//+------------------------------------------------------------------+
//| Trade Management (Break Even & Trailing)                         |
//+------------------------------------------------------------------+
void ManageOpenTrades()
  {
   for(int i = PositionsTotal() - 1; i >= 0; i--)
     {
      ulong posTicket = PositionGetTicket(i);
      if(posTicket > 0 && PositionGetString(POSITION_SYMBOL) == _Symbol && PositionGetInteger(POSITION_MAGIC) == MagicNumber)
        {
         double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
         double currentSL = PositionGetDouble(POSITION_SL);
         double currentTP = PositionGetDouble(POSITION_TP);
         ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
         
         double initialSlDist = MathAbs(openPrice - currentSL);
         if(initialSlDist == 0) continue; 
         
         double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
         double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
         
         // Break Even Logic
         if(UseBreakEven)
           {
            if(posType == POSITION_TYPE_BUY)
              {
               if(bid >= openPrice + initialSlDist && currentSL < openPrice)
                  trade.PositionModify(posTicket, openPrice + (2 * _Point), currentTP);
              }
            else if(posType == POSITION_TYPE_SELL)
              {
               if(ask <= openPrice - initialSlDist && (currentSL > openPrice || currentSL == 0))
                  trade.PositionModify(posTicket, openPrice - (2 * _Point), currentTP);
              }
           }

         // Trailing Stop Logic
         if(UseTrailingStop)
           {
            double atrBuf[];
            if(CopyBuffer(atrHandle, 0, 1, 1, atrBuf) > 0)
              {
               double trailDist = atrBuf[0] * AtrStopMultiplier;
               
               if(posType == POSITION_TYPE_BUY)
                 {
                  double newSL = NormalizeDouble(bid - trailDist, _Digits);
                  if(newSL > currentSL && bid - newSL > _Point)
                     trade.PositionModify(posTicket, newSL, currentTP);
                 }
               else if(posType == POSITION_TYPE_SELL)
                 {
                  double newSL = NormalizeDouble(ask + trailDist, _Digits);
                  if((newSL < currentSL || currentSL == 0) && newSL - ask > _Point)
                     trade.PositionModify(posTicket, newSL, currentTP);
                 }
              }
           }
        }
     }
  }

//+------------------------------------------------------------------+
//| Utility: Check for New Bar                                       |
//+------------------------------------------------------------------+
bool IsNewBar()
  {
   datetime time[1];
   if(CopyTime(_Symbol, PERIOD_CURRENT, 0, 1, time) > 0)
     {
      if(time[0] != lastBarTime)
        {
         lastBarTime = time[0];
         return true;
        }
     }
   return false;
  }

//+------------------------------------------------------------------+
//| Utility: Count Positions                                         |
//+------------------------------------------------------------------+
int CountOpenPositions()
  {
   int count = 0;
   for(int i = PositionsTotal() - 1; i >= 0; i--)
     {
      ulong ticket = PositionGetTicket(i);
      if(ticket > 0 && PositionGetString(POSITION_SYMBOL) == _Symbol && PositionGetInteger(POSITION_MAGIC) == MagicNumber)
         count++;
     }
   return count;
  }

//+------------------------------------------------------------------+
//| Utility: On-Chart Telemetry Dashboard                            |
//+------------------------------------------------------------------+
void UpdateDashboard()
  {
   int currentSpread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
   
   double atrBuf[], maBuf[];
   CopyBuffer(atrHandle, 0, 1, 1, atrBuf);
   CopyBuffer(maHandle, 0, 1, 1, maBuf);
   
   MqlRates r[];
   CopyRates(_Symbol, PERIOD_CURRENT, 1, 1, r);
   
   string trendStr = "WAITING";
   if(ArraySize(r) > 0 && ArraySize(maBuf) > 0)
      trendStr = (r[0].close > maBuf[0]) ? "BULLISH" : "BEARISH";
   
   string display = StringFormat(
      "--- NYLON Scalper Pro (MT5) ---\n" +
      "Trend (15M 200 EMA): %s\n" +
      "Current Spread: %d points (Max: %d)\n" +
      "Current ATR: %.3f", 
      trendStr, currentSpread, MaxSpreadPoints, (ArraySize(atrBuf) > 0 ? atrBuf[0] : 0.0)
   );
   
   Comment(display);
  }
//+------------------------------------------------------------------+
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3349
Joined: Mon Jul 20, 2026 1:28 pm

Re: My own scalping strategies on GOLD (XAU/USD)

Post by PTScalper »

Key MT5 Architectural Upgrades

CTrade Class Abstraction: Unlike MQL4's rigid OrderSend, MT5 utilizes the CTrade class to heavily abstract execution routing. When you pass SL and TP parameters via trade.Buy(), the library automatically maps out the request structure, processes broker-specific execution models, and checks permissions natively.

Time-Synced Buffer Querying: In the MT4 version, using iMA on a 15-minute timeframe while operating on a 1-minute chart introduces repainting risks. This MT5 architecture uses CopyBuffer(maHandle, 0, rates[1].time, 1, maBuffer). Querying the buffer strictly by the rates[1].time locks the exact EMA value that existed at the precise moment the 1-minute entry candle closed.

Array Series Manipulation: MT5 handles arrays sequentially (oldest data first) by default. Implementing ArraySetAsSeries(rates, true) flips the memory indexing to mirror MQL4 behavior, allowing identical visual syntax (0 = current open, 1 = last closed candle) for your liquidity sweep logic mapping.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3349
Joined: Mon Jul 20, 2026 1:28 pm

Re: My own scalping strategies on GOLD (XAU/USD)

Post by PTScalper »

Here is version for Ctraders:

Transitioning this architecture to cTrader means shifting from MQL’s procedural environment to C# and the cAlgo.API. Because cTrader is a modern, object-oriented platform built natively for ECN execution, we can bypass the complex order modification loops required in MT4/MT5 and submit exact stop-loss and take-profit distances in pips directly with the market order.

Here is the production-grade cBot implementation. It utilizes MarketData.GetBars() to pull higher timeframe data and syncs it perfectly to the 1-minute execution chart using exact time-indexing to eliminate any repainting or lookahead bias.

Code: Select all

//+------------------------------------------------------------------+
//|                                          Gold_NYLON_PRO_cBot.cs  |
//|                                     Production Grade cTrader API |
//+------------------------------------------------------------------+
using System;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class NylonGoldScalperPro : Robot
    {
        // --- 1. Risk Management ---
        [Parameter("Use Auto Lot", DefaultValue = true, Group = "Risk Management")]
        public bool UseAutoLot { get; set; }

        [Parameter("Risk Percent (%)", DefaultValue = 1.0, Group = "Risk Management", MinValue = 0.1, Step = 0.1)]
        public double RiskPercent { get; set; }

        [Parameter("Fixed Volume (Units)", DefaultValue = 100, Group = "Risk Management")]
        public double FixedVolumeUnits { get; set; }

        // --- 2. Strategy Logic ---
        [Parameter("EMA Period (15M)", DefaultValue = 200, Group = "Strategy Logic")]
        public int EmaPeriod { get; set; }

        [Parameter("ATR Period (1M)", DefaultValue = 7, Group = "Strategy Logic")]
        public int AtrPeriod { get; set; }

        [Parameter("ATR Stop Multiplier", DefaultValue = 2.0, Group = "Strategy Logic")]
        public double AtrStopMultiplier { get; set; }

        [Parameter("Risk Reward Ratio", DefaultValue = 1.5, Group = "Strategy Logic")]
        public double RiskRewardRatio { get; set; }

        // --- 3. Trade Management ---
        [Parameter("Use Break Even", DefaultValue = true, Group = "Trade Management")]
        public bool UseBreakEven { get; set; }

        [Parameter("Use Trailing Stop", DefaultValue = false, Group = "Trade Management")]
        public bool UseTrailingStop { get; set; }

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

        // --- 4. Time Filters ---
        [Parameter("Start Hour (Server Time)", DefaultValue = 15, Group = "Time Filter")]
        public int StartHour { get; set; }

        [Parameter("End Hour (Server Time)", DefaultValue = 19, Group = "Time Filter")]
        public int EndHour { get; set; }

        // --- 5. System ---
        [Parameter("Trade Label", DefaultValue = "NYLON_PRO_CBOT", Group = "System")]
        public string TradeLabel { get; set; }

        private Bars _bars15m;
        private ExponentialMovingAverage _ema15m;
        private AverageTrueRange _atr;

        protected override void OnStart()
        {
            // Initialize Multi-Timeframe data
            _bars15m = MarketData.GetBars(TimeFrame.Minute15);
            _ema15m = Indicators.ExponentialMovingAverage(_bars15m.ClosePrices, EmaPeriod);
            
            // Initialize Execution Timeframe data
            _atr = Indicators.AverageTrueRange(AtrPeriod, MovingAverageType.Simple);
        }

        protected override void OnTick()
        {
            UpdateDashboard();
            ManageOpenTrades();
        }

        protected override void OnBar()
        {
            // Data availability check
            if (Bars.Count < 3 || _bars15m.Count < EmaPeriod) return;

            // Filter 1: Max Open Positions
            if (Positions.FindAll(TradeLabel, SymbolName).Length > 0) return;

            // Filter 2: Session Hours (Broker Server Time)
            if (Server.Time.Hour < StartHour || Server.Time.Hour >= EndHour) return;

            // Filter 3: Maximum Spread
            double spreadPips = Symbol.Spread / Symbol.PipSize;
            if (spreadPips > MaxSpreadPips) return;

            EvaluateEntrySetups();
        }

        private void EvaluateEntrySetups()
        {
            // c1 = The 1-minute candle that just closed
            // c2 = The 1-minute candle before that
            var c1 = Bars.Last(1);
            var c2 = Bars.Last(2);

            // Pro-Level Sync: Find the exact 15M EMA value as it stood when the 1M candle closed
            int index15m = _bars15m.OpenTimes.GetIndexByTime(c1.OpenTime);
            if (index15m < 1) return;
            
            // Subtract 1 to reference the last fully closed 15M candle, preventing intrabar repainting
            double emaValueClosed = _ema15m.Result[index15m - 1];

            // Calculate Volatility Stop
            double atr = _atr.Result.Last(1);
            double slDist = atr * AtrStopMultiplier;
            double slPips = Math.Round(slDist / Symbol.PipSize, 1);
            double tpPips = Math.Round(slPips * RiskRewardRatio, 1);

            // --- BUY LOGIC ---
            bool buyTrend = (c1.Close > emaValueClosed);
            bool buySweep = (c1.Low < c2.Low) && 
                            (c1.Close > c1.Open) && 
                            (c1.Close > c1.Low + (c1.High - c1.Low) * 0.5);

            if (buyTrend && buySweep)
            {
                double volume = CalculateVolume(slPips);
                ExecuteMarketOrder(TradeType.Buy, SymbolName, volume, TradeLabel, slPips, tpPips);
                return;
            }

            // --- SELL LOGIC ---
            bool sellTrend = (c1.Close < emaValueClosed);
            bool sellSweep = (c1.High > c2.High) && 
                             (c1.Close < c1.Open) && 
                             (c1.Close < c1.High - (c1.High - c1.Low) * 0.5);

            if (sellTrend && sellSweep)
            {
                double volume = CalculateVolume(slPips);
                ExecuteMarketOrder(TradeType.Sell, SymbolName, volume, TradeLabel, slPips, tpPips);
            }
        }

        private double CalculateVolume(double slPips)
        {
            if (!UseAutoLot)
                return Symbol.NormalizeVolumeInUnits(FixedVolumeUnits, RoundingMode.Down);

            double riskAmount = Account.Balance * (RiskPercent / 100.0);
            
            if (slPips <= 0 || Symbol.PipValue == 0) return Symbol.VolumeInUnitsMin;

            // In cTrader, PipValue is strictly defined as the value of 1 pip for 1 unit of volume
            double exactVolume = riskAmount / (slPips * Symbol.PipValue);
            
            double normalizedVolume = Symbol.NormalizeVolumeInUnits(exactVolume, RoundingMode.Down);
            
            if (normalizedVolume < Symbol.VolumeInUnitsMin) return Symbol.VolumeInUnitsMin;
            if (normalizedVolume > Symbol.VolumeInUnitsMax) return Symbol.VolumeInUnitsMax;

            return normalizedVolume;
        }

        private void ManageOpenTrades()
        {
            var position = Positions.Find(TradeLabel, SymbolName);
            if (position != null && position.TakeProfit.HasValue && position.StopLoss.HasValue)
            {
                // Reverse-engineer the initial SL distance in points using the fixed TP
                double tpDist = Math.Abs(position.TakeProfit.Value - position.EntryPrice);
                double slDist = tpDist / RiskRewardRatio;
                double currentSl = position.StopLoss.Value;

                // Break-Even Logic (Triggers at 1:1 RR)
                if (UseBreakEven)
                {
                    if (position.TradeType == TradeType.Buy)
                    {
                        if (Symbol.Bid >= position.EntryPrice + slDist && currentSl < position.EntryPrice)
                            ModifyPosition(position, position.EntryPrice + (2 * Symbol.TickSize), position.TakeProfit);
                    }
                    else if (position.TradeType == TradeType.Sell)
                    {
                        if (Symbol.Ask <= position.EntryPrice - slDist && currentSl > position.EntryPrice)
                            ModifyPosition(position, position.EntryPrice - (2 * Symbol.TickSize), position.TakeProfit);
                    }
                }

                // ATR Trailing Stop Logic
                if (UseTrailingStop)
                {
                    double trailDist = _atr.Result.LastValue * AtrStopMultiplier;
                    
                    if (position.TradeType == TradeType.Buy)
                    {
                        double newSl = Math.Round(Symbol.Bid - trailDist, Symbol.Digits);
                        if (newSl > currentSl && Symbol.Bid - newSl > Symbol.PipSize)
                            ModifyPosition(position, newSl, position.TakeProfit);
                    }
                    else if (position.TradeType == TradeType.Sell)
                    {
                        double newSl = Math.Round(Symbol.Ask + trailDist, Symbol.Digits);
                        if (newSl < currentSl && newSl - Symbol.Ask > Symbol.PipSize)
                            ModifyPosition(position, newSl, position.TakeProfit);
                    }
                }
            }
        }

        private void UpdateDashboard()
        {
            double spreadPips = Math.Round(Symbol.Spread / Symbol.PipSize, 1);
            
            string trendStr = "WAITING";
            if (Bars.Count > 0 && _bars15m.Count > 0)
            {
                var c1 = Bars.Last(1);
                int idx = _bars15m.OpenTimes.GetIndexByTime(c1.OpenTime);
                if (idx >= 1) trendStr = (c1.Close > _ema15m.Result[idx - 1]) ? "BULLISH" : "BEARISH";
            }

            string display = $"--- NYLON Scalper Pro (cBot) ---\n" +
                             $"Trend (15M 200 EMA): {trendStr}\n" +
                             $"Current Spread: {spreadPips} pips (Max: {MaxSpreadPips})\n" +
                             $"Current ATR: {_atr.Result.LastValue:F3}";
                             
            Chart.DrawStaticText("telemetry", display, VerticalAlignment.Top, HorizontalAlignment.Left, Color.Lime);
        }
    }
}
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3349
Joined: Mon Jul 20, 2026 1:28 pm

Re: My own scalping strategies on GOLD (XAU/USD)

Post by PTScalper »

Key cTrader Architectural Upgrades

Pips Abstraction on Execution: In MQL, executing an order requires calculating SL/TP at hard price levels. The cAlgo.API abstracts this beautifully. In the ExecuteMarketOrder() method, we pass slPips and tpPips directly. The server handles the ECN-compliant relative placement against the exact fill price, completely eliminating execution slippage errors related to tight stops.

Time-Series Indexing via GetIndexByTime: Combining timeframes in cBots requires strict synchronization. _bars15m.OpenTimes.GetIndexByTime(c1.OpenTime) matches the 1-minute execution candle to the exact 15-minute period it falls within. Shifting this index by -1 safely retrieves the last fully formed 15-minute EMA, making the logic completely immune to repainting.

Stateless Break-Even Mathematics: Complex C# state tracking is prone to wiping data during terminal restarts. The ManageOpenTrades() function reverse-engineers the original SL distance dynamically from the open trade’s fixed Take Profit price using the known RiskRewardRatio. This guarantees the cBot can crash, reboot, and instantly resume managing open trades.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3349
Joined: Mon Jul 20, 2026 1:28 pm

Re: My own scalping strategies on GOLD (XAU/USD)

Post by PTScalper »

Here is the production-grade, Pine Script v5 implementation. It natively handles session logic, overlays the NYLON window visually, and includes an on-chart telemetry dashboard.

Code: Select all

// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0
//@version=5
strategy("Gold NYLON Scalper Pro", overlay=true, calc_on_every_tick=false, initial_capital=1000, default_qty_type=strategy.percent_of_equity, default_qty_value=1.0)

// --- 1. Risk Management ---
useAutoLot = input.bool(true, title="Use Auto Risk Sizing", group="1. Risk Management")
riskPercent = input.float(1.0, title="Risk Percent (%)", group="1. Risk Management", minval=0.1, step=0.1)
fixedLot = input.float(1.0, title="Fixed Volume (Units)", group="1. Risk Management")

// --- 2. Strategy Logic ---
tf_15m = input.timeframe("15", title="Trend Timeframe", group="2. Strategy Logic")
emaPeriod = input.int(200, title="EMA Period", group="2. Strategy Logic")
atrPeriod = input.int(7, title="ATR Period (1M)", group="2. Strategy Logic")
atrMult = input.float(2.0, title="ATR Stop Multiplier", group="2. Strategy Logic")
rrRatio = input.float(1.5, title="Risk Reward Ratio", group="2. Strategy Logic")

// --- 3. Time Filter ---
sessionTime = input.session("0800-1200", title="NYLON Session (EST)", group="3. Time Filter")
sessionZone = input.string("America/New_York", title="Session Timezone", group="3. Time Filter")

// Check if current bar time is within the session
inSession = time(timeframe.period, sessionTime, sessionZone)

// --- 4. MTF & Indicators ---
atr = ta.atr(atrPeriod)
slDist = atr * atrMult

// Pro-Level MTF Sync: Lock in the previous 15M close to prevent lookahead and repainting
ema15m = ta.ema(close, emaPeriod)
ema15m_htf = request.security(syminfo.tickerid, tf_15m, ema15m[1], lookahead=barmerge.lookahead_on)

// --- 5. Entry Logic (Evaluated on Bar Close) ---
// BUY LOGIC: Price > 15M EMA, swept previous low, closed bullish, closed in upper 50%
buyTrend = close > ema15m_htf
buySweep = (low < low[1]) and (close > open) and (close > (low + (high - low) * 0.5))

// SELL LOGIC: Price < 15M EMA, swept previous high, closed bearish, closed in lower 50%
sellTrend = close < ema15m_htf
sellSweep = (high > high[1]) and (close < open) and (close < (high - (high - low) * 0.5))

validBuy = buyTrend and buySweep and not na(inSession)
validSell = sellTrend and sellSweep and not na(inSession)

// --- 6. Execution ---
tradeRiskAmount = strategy.equity * (riskPercent / 100)
// Calculate quantity based on ATR distance mapped to account currency via syminfo.pointvalue
qty = useAutoLot ? (tradeRiskAmount / (slDist * syminfo.pointvalue)) : fixedLot

if validBuy and strategy.position_size == 0
    strategy.entry("Long", strategy.long, qty=qty)
    sl = close - slDist
    tp = close + (slDist * rrRatio)
    strategy.exit("Exit Long", "Long", stop=sl, limit=tp)

if validSell and strategy.position_size == 0
    strategy.entry("Short", strategy.short, qty=qty)
    sl = close + slDist
    tp = close - (slDist * rrRatio)
    strategy.exit("Exit Short", "Short", stop=sl, limit=tp)

// --- 7. UI & Visuals ---
// Overlay session hours dynamically
bgcolor(not na(inSession) ? color.new(color.blue, 95) : na, title="NYLON Session Window")

// Paint 15M EMA on the 1M chart
plot(ema15m_htf, color=color.white, linewidth=2, title="15M 200 EMA")

// Telemetry Dashboard
var table dash = table.new(position.top_right, 2, 4, border_width=1, border_color=color.new(color.gray, 70), frame_color=color.new(color.gray, 70))

if barstate.islast
    trendStr = close > ema15m_htf ? "BULLISH" : "BEARISH"
    trendCol = close > ema15m_htf ? color.new(color.green, 50) : color.new(color.red, 50)
    sesCol   = not na(inSession) ? color.new(color.green, 50) : color.new(color.red, 50)
    
    table.cell(dash, 0, 0, "NYLON Pro", text_color=color.white, bgcolor=color.new(color.blue, 20))
    table.cell(dash, 1, 0, "Telemetry", text_color=color.white, bgcolor=color.new(color.blue, 20))
    
    table.cell(dash, 0, 1, "15M Trend", text_color=color.white, bgcolor=color.new(color.gray, 80))
    table.cell(dash, 1, 1, trendStr, text_color=color.white, bgcolor=trendCol)
    
    table.cell(dash, 0, 2, "Current ATR", text_color=color.white, bgcolor=color.new(color.gray, 80))
    table.cell(dash, 1, 2, str.tostring(atr, "#.###"), text_color=color.white, bgcolor=color.new(color.gray, 80))
    
    table.cell(dash, 0, 3, "Session Active", text_color=color.white, bgcolor=color.new(color.gray, 80))
    table.cell(dash, 1, 3, not na(inSession) ? "YES" : "NO", text_color=color.white, bgcolor=sesCol)
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Post Reply