IC Markets

Golden Momentum Forex trading strategy

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

Golden Momentum Forex trading strategy

Post by FTtrader »

Hi scalpers, traders,

Gold (Xau/USD) trends exceptionally well, making momentum and trend-following approaches highly effective. This strategy waits for short-term momentum to align with a medium-term trend before executing a trade on the closing of a candle.

Asset: XAUUSD (Gold)Timeframe: M15 (15-Minute Chart)
Indicators:Fast EMA: 20-periodSlow EMA: 50-period RSI: 14-period
Buy Rules: The 20 EMA crosses above the 50 EMA AND the RSI closes above 50.
Sell Rules: The 20 EMA crosses below the 50 EMA AND the RSI closes below 50.
Risk Management: Set a fixed Stop Loss of 50 pips and a Take Profit of 100 pips (a 1:2 Risk-to-Reward ratio).

Disclaimer: Please run this on a DEMO account first. Gold is volatile and spreads can widen during NY/London overlap. Let me know your results or if you have ideas on how to improve the exit logic!

MT4 (MQL4) Expert Advisor Code

To use this, open your MetaEditor in MT4, click New > Expert Advisor, name it GoldenMomentum, and paste this code over the default template. Compile it, and it will appear in your Navigator panel.

Code: Select all

//+------------------------------------------------------------------+
//|                                          Golden_Momentum_XAU.mq4 |
//|                                                      Open Source |
//+------------------------------------------------------------------+
#property strict

//--- Input parameters
input double LotSize = 0.01;       // Lot Size
input int FastEMA = 20;            // Fast EMA Period
input int SlowEMA = 50;            // Slow EMA Period
input int RSIPeriod = 14;          // RSI Period
input int StopLoss = 500;          // Stop Loss (in points, 500 = 50 pips on 2-digit brokers)
input int TakeProfit = 1000;       // Take Profit (in points, 1000 = 100 pips)
input int MagicNumber = 88888;     // EA Magic Number to track trades

//+------------------------------------------------------------------+
//| Check if we already have open orders for this EA                 |
//+------------------------------------------------------------------+
int OpenOrdersCount()
  {
   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;
  }

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   // 1. Ensure only one trade is open at a time
   if(OpenOrdersCount() > 0) return;

   // 2. Indicator Calculations (Shift 1 = previous closed candle, Shift 2 = candle before that)
   // We use closed candles to prevent the EA from entering on a repainting signal
   double emaFastCurrent = iMA(Symbol(), 0, FastEMA, 0, MODE_EMA, PRICE_CLOSE, 1);
   double emaFastPrev    = iMA(Symbol(), 0, FastEMA, 0, MODE_EMA, PRICE_CLOSE, 2);
   
   double emaSlowCurrent = iMA(Symbol(), 0, SlowEMA, 0, MODE_EMA, PRICE_CLOSE, 1);
   double emaSlowPrev    = iMA(Symbol(), 0, SlowEMA, 0, MODE_EMA, PRICE_CLOSE, 2);
   
   double rsiCurrent     = iRSI(Symbol(), 0, RSIPeriod, PRICE_CLOSE, 1);

   double pt = Point; // Broker's point value
   
   // 3. Buy Setup: Fast EMA crosses above Slow EMA AND RSI > 50
   if(emaFastPrev <= emaSlowPrev && emaFastCurrent > emaSlowCurrent && rsiCurrent > 50)
     {
      double sl = Ask - (StopLoss * pt);
      double tp = Ask + (TakeProfit * pt);
      
      int ticket = OrderSend(Symbol(), OP_BUY, LotSize, Ask, 3, sl, tp, "Golden Momentum Buy", MagicNumber, 0, clrBlue);
      if(ticket < 0) Print("Buy Order Failed! Error: ", GetLastError());
     }
     
   // 4. Sell Setup: Fast EMA crosses below Slow EMA AND RSI < 50
   if(emaFastPrev >= emaSlowPrev && emaFastCurrent < emaSlowCurrent && rsiCurrent < 50)
     {
      double sl = Bid + (StopLoss * pt);
      double tp = Bid - (TakeProfit * pt);
      
      int ticket = OrderSend(Symbol(), OP_SELL, LotSize, Bid, 3, sl, tp, "Golden Momentum Sell", MagicNumber, 0, clrRed);
      if(ticket < 0) Print("Sell Order Failed! Error: ", GetLastError());
     }
  }
//+------------------------------------------------------------------+
FTtrader
Posts: 309
Joined: Mon Aug 03, 2026 2:43 pm

Re: Golden Momentum Forex trading strategy

Post by FTtrader »

Note on Broker Digits: Depending on whether your broker quotes Gold with 2 decimal places (e.g., $1950.50) or 3 decimal places (e.g., $1950.500), you may need to add an extra zero to your inputs. If your broker uses 3 decimals, a 50-pip stop loss is 5000 points instead of 500.

So please test it on demo first before you will run it on real account.
FTtrader
Posts: 309
Joined: Mon Aug 03, 2026 2:43 pm

Re: Golden Momentum Forex trading strategy

Post by FTtrader »

Here are the translated versions of the "Golden Momentum" strategy for both MetaTrader 5 (MQL5) and cTrader (C#).

MetaTrader 5 (MQL5) Expert Advisor

In MT5, indicators are managed via handles and data is retrieved using CopyBuffer. To use this, open MetaEditor 5, create a new Expert Advisor, and paste this code over the default template.

Code: Select all

//+------------------------------------------------------------------+
//|                                          Golden_Momentum_XAU.mq5 |
//+------------------------------------------------------------------+
#property strict
#include <Trade\Trade.mqh>

//--- Input parameters
input double LotSize = 0.01;       // Lot Size
input int FastEMA = 20;            // Fast EMA Period
input int SlowEMA = 50;            // Slow EMA Period
input int RSIPeriod = 14;          // RSI Period
input int StopLoss = 500;          // Stop Loss (in points, 500 = 50 pips)
input int TakeProfit = 1000;       // Take Profit (in points, 1000 = 100 pips)
input ulong MagicNumber = 88888;   // EA Magic Number

CTrade trade;
int handleFastEMA;
int handleSlowEMA;
int handleRSI;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   trade.SetExpertMagicNumber(MagicNumber);
   
   // Initialize indicator handles
   handleFastEMA = iMA(_Symbol, PERIOD_CURRENT, FastEMA, 0, MODE_EMA, PRICE_CLOSE);
   handleSlowEMA = iMA(_Symbol, PERIOD_CURRENT, SlowEMA, 0, MODE_EMA, PRICE_CLOSE);
   handleRSI     = iRSI(_Symbol, PERIOD_CURRENT, RSIPeriod, PRICE_CLOSE);
   
   if(handleFastEMA == INVALID_HANDLE || handleSlowEMA == INVALID_HANDLE || handleRSI == INVALID_HANDLE)
     {
      Print("Error creating indicator handles");
      return(INIT_FAILED);
     }
     
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   // 1. Ensure only one trade is open at a time
   if(PositionsTotal() > 0) return; 

   double emaFast[2], emaSlow[2], rsi[1];
   
   // 2. Copy data for previous closed candles (Index 1 = closed candle, Index 2 = previous)
   if(CopyBuffer(handleFastEMA, 0, 1, 2, emaFast) <= 0) return;
   if(CopyBuffer(handleSlowEMA, 0, 1, 2, emaSlow) <= 0) return;
   if(CopyBuffer(handleRSI, 0, 1, 1, rsi) <= 0) return;

   // By default, CopyBuffer fills older data in lower indices: [0] is older, [1] is newer.
   double emaFastPrev    = emaFast[0];
   double emaFastCurrent = emaFast[1];
   double emaSlowPrev    = emaSlow[0];
   double emaSlowCurrent = emaSlow[1];
   double rsiCurrent     = rsi[0];

   double pt = _Point;
   
   // 3. Buy Setup
   if(emaFastPrev <= emaSlowPrev && emaFastCurrent > emaSlowCurrent && rsiCurrent > 50)
     {
      double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
      double sl = ask - (StopLoss * pt);
      double tp = ask + (TakeProfit * pt);
      
      trade.Buy(LotSize, _Symbol, ask, sl, tp, "Golden Momentum Buy");
     }
     
   // 4. Sell Setup
   if(emaFastPrev >= emaSlowPrev && emaFastCurrent < emaSlowCurrent && rsiCurrent < 50)
     {
      double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
      double sl = bid + (StopLoss * pt);
      double tp = bid - (TakeProfit * pt);
      
      trade.Sell(LotSize, _Symbol, bid, sl, tp, "Golden Momentum Sell");
     }
  }
//+------------------------------------------------------------------+
Please test it first on your demo account.
FTtrader
Posts: 309
Joined: Mon Aug 03, 2026 2:43 pm

Re: Golden Momentum Forex trading strategy

Post by FTtrader »

And here is the version for Ctraders:

cTrader (C#) cBot
cTrader utilizes modern C# and handles historical chart data much more naturally using the OnBarClosed() method, which automatically guarantees trades are only evaluated and fired when a 15-minute candle completes.

To use this, open the cTrader Automate tab, add a new cBot, name it GoldenMomentumXAU, and replace the template with this code.

Code: Select all

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

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class GoldenMomentumXAU : Robot
    {
        [Parameter("Lot Size", DefaultValue = 0.01, MinValue = 0.01, Step = 0.01)]
        public double LotSize { get; set; }

        [Parameter("Fast EMA Period", DefaultValue = 20, MinValue = 1)]
        public int FastEMA { get; set; }

        [Parameter("Slow EMA Period", DefaultValue = 50, MinValue = 1)]
        public int SlowEMA { get; set; }

        [Parameter("RSI Period", DefaultValue = 14, MinValue = 1)]
        public int RSIPeriod { get; set; }

        [Parameter("Stop Loss (Pips)", DefaultValue = 50)]
        public double StopLoss { get; set; }

        [Parameter("Take Profit (Pips)", DefaultValue = 100)]
        public double TakeProfit { get; set; }
        
        [Parameter("Magic Name", DefaultValue = "GoldenMomentum")]
        public string MagicName { get; set; }

        private ExponentialMovingAverage _fastEma;
        private ExponentialMovingAverage _slowEma;
        private RelativeStrengthIndex _rsi;

        protected override void OnStart()
        {
            // Initialize indicators based on Close prices
            _fastEma = Indicators.ExponentialMovingAverage(Bars.ClosePrices, FastEMA);
            _slowEma = Indicators.ExponentialMovingAverage(Bars.ClosePrices, SlowEMA);
            _rsi = Indicators.RelativeStrengthIndex(Bars.ClosePrices, RSIPeriod);
        }

        // Firing strictly on Bar Close avoids repainting
        protected override void OnBarClosed()
        {
            // Ensure only one trade is active per symbol for this specific bot
            if (Positions.Count(p => p.SymbolName == SymbolName && p.Label == MagicName) > 0)
                return;

            // .Last(1) accesses the candle that just closed. .Last(2) accesses the one before it.
            double emaFastCurrent = _fastEma.Result.Last(1);
            double emaFastPrev    = _fastEma.Result.Last(2);

            double emaSlowCurrent = _slowEma.Result.Last(1);
            double emaSlowPrev    = _slowEma.Result.Last(2);

            double rsiCurrent     = _rsi.Result.Last(1);
            
            // Convert lots to standard volume units for cTrader execution
            var volumeInUnits = Symbol.QuantityToVolumeInUnits(LotSize);

            // Buy Setup
            if (emaFastPrev <= emaSlowPrev && emaFastCurrent > emaSlowCurrent && rsiCurrent > 50)
            {
                ExecuteMarketOrder(TradeType.Buy, SymbolName, volumeInUnits, MagicName, StopLoss, TakeProfit);
            }

            // Sell Setup
            else if (emaFastPrev >= emaSlowPrev && emaFastCurrent < emaSlowCurrent && rsiCurrent < 50)
            {
                ExecuteMarketOrder(TradeType.Sell, SymbolName, volumeInUnits, MagicName, StopLoss, TakeProfit);
            }
        }
    }
}
FTtrader
Posts: 309
Joined: Mon Aug 03, 2026 2:43 pm

Re: Golden Momentum Forex trading strategy

Post by FTtrader »

And do not worry, i did not forgot for traders in Trading view.

Here is the "Golden Momentum" strategy translated into TradingView’s Pine Script (version 5).

By default, TradingView strategies execute on the close of the bar, which perfectly aligns with the strategy's anti-repainting rules.

TradingView Pine Script (v5)
To use this, open TradingView, go to the Pine Editor tab at the bottom, replace the default code with this script, and click Add to Chart.

Code: Select all

//@version=5
strategy("Golden Momentum XAU", overlay=true, initial_capital=1000, default_qty_type=strategy.fixed, default_qty_value=1)

// --- Inputs ---
fastPeriod = input.int(20, title="Fast EMA Period", group="Indicators")
slowPeriod = input.int(50, title="Slow EMA Period", group="Indicators")
rsiPeriod  = input.int(14, title="RSI Period", group="Indicators")

// Note: On TradingView, XAUUSD tick size is usually 0.01. 
// 50 pips = $5.00 movement = 500 ticks/points.
slPoints = input.int(500, title="Stop Loss (Ticks/Points)", group="Risk Management")
tpPoints = input.int(1000, title="Take Profit (Ticks/Points)", group="Risk Management")

// --- Indicators ---
fastEma = ta.ema(close, fastPeriod)
slowEma = ta.ema(close, slowPeriod)
rsiValue = ta.rsi(close, rsiPeriod)

// Plot EMAs on the chart for visual confirmation
plot(fastEma, color=color.new(color.blue, 0), title="Fast EMA", linewidth=2)
plot(slowEma, color=color.new(color.red, 0), title="Slow EMA", linewidth=2)

// --- Entry Logic ---
// ta.crossover checks if the current close crossed above the previous close.
// Combined with strategy default (calc_on_every_tick=false), this strictly evaluates on candle close.
longCondition  = ta.crossover(fastEma, slowEma) and rsiValue > 50
shortCondition = ta.crossunder(fastEma, slowEma) and rsiValue < 50

// --- Execution & Trade Management ---
// Ensure we only take one position at a time
if (longCondition and strategy.position_size == 0)
    strategy.entry("Long", strategy.long)
    // Attach fixed Stop Loss and Take Profit to the entry
    strategy.exit("Exit Long", from_entry="Long", loss=slPoints, profit=tpPoints)

if (shortCondition and strategy.position_size == 0)
    strategy.entry("Short", strategy.short)
    strategy.exit("Exit Short", from_entry="Short", loss=slPoints, profit=tpPoints)
FTtrader
Posts: 309
Joined: Mon Aug 03, 2026 2:43 pm

Re: Golden Momentum Forex trading strategy

Post by FTtrader »

Important Notes for TradingView:
Ticks vs. Pips: In Pine Script's strategy.exit(), the loss and profit parameters are calculated in ticks (the minimum price movement). For most XAUUSD data feeds on TradingView (like OANDA or FOREX.com), the minimum tick is 0.01. Therefore, a 50-pip ($5.00) stop loss is input as 500 ticks.

Backtesting Setup: You can test this on any timeframe, but since the system was designed for the M15 chart, apply it there first. You can easily adjust the date ranges or starting capital via the script's visual settings gear icon without touching the code.

Please let me know, if it helped you. Or if you found any way how to improve it :-)
Thanks, have a good day.
Post Reply