My own scalping strategies on GOLD (XAU/USD)
My own scalping strategies on GOLD (XAU/USD)
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.
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.
Re: My own scalping strategies on GOLD (XAU/USD)
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)
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.
Re: My own scalping strategies on GOLD (XAU/USD)
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.
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.
Re: My own scalping strategies on GOLD (XAU/USD)
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.
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.
Re: My own scalping strategies on GOLD (XAU/USD)
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.
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.
Re: My own scalping strategies on GOLD (XAU/USD)
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.
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.
Re: My own scalping strategies on GOLD (XAU/USD)
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.
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.
Re: My own scalping strategies on GOLD (XAU/USD)
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.
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.
Re: My own scalping strategies on GOLD (XAU/USD)
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.
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.
Re: My own scalping strategies on GOLD (XAU/USD)
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.