Advertisement IC Markets

Pre-NY overlap checklist for GBPUSD when London has already run

Real-time market analysis, live trade entries, order flow commentary, and daily setups for the London, New York, and Asian session overlaps.
PTScalper
Site Admin
Posts: 3027
Joined: Mon Jul 20, 2026 1:28 pm

Re: Pre-NY overlap checklist for GBPUSD when London has already run

Post by PTScalper »

Here is the C# cAlgo implementation for cTrader.

Since you are a .NET engineer, you'll appreciate how much cleaner this is in C# compared to MQL. Instead of passing symbol names to global functions like iHigh(), we retrieve the daily timeframe natively using MarketData.GetBars(TimeFrame.Daily) in the Initialize() method and reference it synchronously without blocking.

I used TimeSpan for fast intraday time-bound checks, preventing the need to parse strings on every tick.

Save this in cTrader's Automate tab as a new Indicator:

Code: Select all

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

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class LondonNYOverlapADR : Indicator
    {
        [Parameter("London Start (HH:MM)", Group = "Session Settings", DefaultValue = "08:00")]
        public string LondonStartStr { get; set; }

        [Parameter("London End (HH:MM)", Group = "Session Settings", DefaultValue = "13:00")]
        public string LondonEndStr { get; set; }

        [Parameter("Overlap End (HH:MM)", Group = "Session Settings", DefaultValue = "17:00")]
        public string OverlapEndStr { get; set; }

        [Parameter("ADR Lookback", Group = "ADR Exhaustion", DefaultValue = 14, MinValue = 1)]
        public int AdrLookback { get; set; }

        [Parameter("Exhaustion Threshold (%)", Group = "ADR Exhaustion", DefaultValue = 80.0)]
        public double AdrThreshold { get; set; }

        [Parameter("Log Alerts to Journal", Group = "Alerts", DefaultValue = true)]
        public bool EnableLog { get; set; }

        [Parameter("Play Sound", Group = "Alerts", DefaultValue = false)]
        public bool EnableSound { get; set; }

        [Output("London High", LineColor = "SeaGreen", Thickness = 2, PlotType = PlotType.Line)]
        public IndicatorDataSeries OutHigh { get; set; }

        [Output("London Low", LineColor = "Crimson", Thickness = 2, PlotType = PlotType.Line)]
        public IndicatorDataSeries OutLow { get; set; }

        [Output("London Mid", LineColor = "SlateGray", Thickness = 1, PlotType = PlotType.Points)]
        public IndicatorDataSeries OutMid { get; set; }

        private TimeSpan _lonStart, _lonEnd, _overlapEnd;
        private Bars _dailyBars;
        private int _lastHighSweepDay = -1;
        private int _lastLowSweepDay = -1;

        protected override void Initialize()
        {
            TimeSpan.TryParse(LondonStartStr, out _lonStart);
            TimeSpan.TryParse(LondonEndStr, out _lonEnd);
            TimeSpan.TryParse(OverlapEndStr, out _overlapEnd);

            // Fetch higher timeframe data natively for the ADR check
            _dailyBars = MarketData.GetBars(TimeFrame.Daily);
        }

        public override void Calculate(int index)
        {
            var currentTime = Bars.OpenTimes[index];
            var timeOfDay = currentTime.TimeOfDay;

            // Process only inside the active window
            if (timeOfDay >= _lonStart && timeOfDay < _overlapEnd)
            {
                double hi = double.MinValue;
                double lo = double.MaxValue;

                // Scan backwards to find the extremes of today's London session
                for (int i = index; i >= 0; i--)
                {
                    var barTime = Bars.OpenTimes[i];
                    if (barTime.Date != currentTime.Date) break;

                    if (barTime.TimeOfDay >= _lonStart && barTime.TimeOfDay < _lonEnd)
                    {
                        hi = Math.Max(hi, Bars.HighPrices[i]);
                        lo = Math.Min(lo, Bars.LowPrices[i]);
                    }
                }

                // If valid extremes were found, plot them
                if (hi > double.MinValue && lo < double.MaxValue)
                {
                    OutHigh[index] = hi;
                    OutLow[index] = lo;
                    OutMid[index] = (hi + lo) / 2.0;

                    if (IsLastBar)
                    {
                        HandleLiveEdgeLogic(index, hi, lo, currentTime);
                    }
                }
                else
                {
                    ClearOutputs(index);
                }
            }
            else
            {
                ClearOutputs(index);
                if (IsLastBar) Chart.RemoveObject("ADR_HUD");
            }
        }

        private void HandleLiveEdgeLogic(int index, double hi, double lo, DateTime currentTime)
        {
            double adr = GetHistoricalADR();
            double currentRange = hi - lo;
            double pctConsumed = (currentRange / adr) * 100;
            bool isExhausted = pctConsumed >= AdrThreshold;

            // Draw non-blocking HUD (cTrader handles this natively in the chart overlay)
            string status = isExhausted ? "NO-GO (EXHAUSTED)" : "GO (ROOM TO MOVE)";
            Color statusColor = isExhausted ? Color.Red : Color.LimeGreen;
            string hudText = $"London ADR Consumed: {pctConsumed:F1}% | {status}";
            
            Chart.DrawStaticText("ADR_HUD", hudText, VerticalAlignment.Top, HorizontalAlignment.Right, statusColor);

            // Process Alerts specifically inside the NY Overlap timeframe
            var timeOfDay = currentTime.TimeOfDay;
            if (timeOfDay >= _lonEnd && timeOfDay < _overlapEnd && !isExhausted)
            {
                if (Bars.HighPrices[index] > hi && _lastHighSweepDay != currentTime.DayOfYear)
                {
                    string msg = $"NY Overlap Sweep (GO): {SymbolName} swept London High at {hi}. (ADR: {pctConsumed:F1}%)";
                    TriggerAlert(msg);
                    _lastHighSweepDay = currentTime.DayOfYear;
                }

                if (Bars.LowPrices[index] < lo && _lastLowSweepDay != currentTime.DayOfYear)
                {
                    string msg = $"NY Overlap Sweep (GO): {SymbolName} swept London Low at {lo}. (ADR: {pctConsumed:F1}%)";
                    TriggerAlert(msg);
                    _lastLowSweepDay = currentTime.DayOfYear;
                }
            }
        }

        private double GetHistoricalADR()
        {
            double sum = 0;
            int count = 0;
            
            // _dailyBars.Count - 2 ensures we only look at fully closed daily candles, avoiding repainting
            int lastClosedDailyIndex = _dailyBars.Count - 2; 

            for (int i = 0; i < AdrLookback; i++)
            {
                int idx = lastClosedDailyIndex - i;
                if (idx < 0) break;
                
                sum += (_dailyBars.HighPrices[idx] - _dailyBars.LowPrices[idx]);
                count++;
            }

            return count > 0 ? sum / count : 0.0001; // Avoid divide-by-zero
        }

        private void ClearOutputs(int index)
        {
            OutHigh[index] = double.NaN;
            OutLow[index] = double.NaN;
            OutMid[index] = double.NaN;
        }

        private void TriggerAlert(string msg)
        {
            if (EnableLog) Print(msg);
            if (EnableSound) Notifications.PlaySound(SoundType.Doorbell);
        }
    }
}
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Recommended broker for automated trading & scalping IC Markets
PTScalper
Site Admin
Posts: 3027
Joined: Mon Jul 20, 2026 1:28 pm

Re: Pre-NY overlap checklist for GBPUSD when London has already run

Post by PTScalper »

cTrader Notes:

Unlike MT4/MT5, cTrader's sandbox limits native popup alerts without pulling in Windows Forms DLLs (which breaks cross-platform compatibility). This script writes alerts safely directly to the Log (visible in your automate journal tab), natively plays the terminal's doorbell sound, and updates the HUD safely via Chart.DrawStaticText.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3027
Joined: Mon Jul 20, 2026 1:28 pm

Re: Pre-NY overlap checklist for GBPUSD when London has already run

Post by PTScalper »

To add the Average Daily Range (ADR) exhaustion check, we need to pull higher-timeframe daily data using request.security(). We calculate the historic ADR based on closed daily candles, compare it against the live London range, and change the visual state of the chart if the threshold is breached.

This updated version does two things when London consumes your defined ADR threshold (default 80%):

Background Warning: The NY overlap background shifts from a neutral orange to a warning red.

Live Status Table: A small monitor appears in the top-right corner during active sessions, showing the exact percentage consumed and a clear "GO" or "NO-GO" signal.

Code: Select all

//@version=5
indicator("London-NY Overlap + ADR Exhaustion", overlay=true)

// =========================================================================
// Inputs
// =========================================================================
grp_sessions = "Session Times (Exchange Timezone)"
lon_session = input.session("0800-1300", title="London Session", group=grp_sessions)
overlap_session = input.session("1300-1700", title="NY Overlap Session", group=grp_sessions)
tz = input.string("Europe/London", title="Timezone", group=grp_sessions)

grp_adr = "ADR Exhaustion Logic"
adr_length = input.int(14, title="ADR Lookback (Days)", minval=1, group=grp_adr)
adr_threshold = input.float(80.0, title="Exhaustion Threshold (%)", minval=1, group=grp_adr)

// =========================================================================
// ADR Calculation (Strictly historical daily data to prevent repainting)
// =========================================================================
// Calculate the Simple Moving Average of the daily range (High - Low) of past closed days
daily_range = ta.sma(high[1] - low[1], adr_length)
adr = request.security(syminfo.tickerid, "D", daily_range)

// =========================================================================
// Session & Range Logic
// =========================================================================
in_london = time(timeframe.period, lon_session, tz)
in_overlap = time(timeframe.period, overlap_session, tz)

var float lon_high = na
var float lon_low = na

// Reset at the start of a new London session
if in_london and not in_london[1]
    lon_high := high
    lon_low := low
else if in_london
    // Track the extremes
    lon_high := math.max(lon_high, high)
    lon_low := math.min(lon_low, low)

lon_mid = (lon_high + lon_low) / 2
lon_range = lon_high - lon_low

// Exhaustion Math
pct_consumed = (lon_range / adr) * 100
is_exhausted = pct_consumed >= adr_threshold

// =========================================================================
// Visuals & Backgrounds
// =========================================================================
bgcolor(in_london ? color.new(color.blue, 92) : na, title="London Background")

// The overlap background turns Red if the setup is exhausted, otherwise Orange
overlap_bg = is_exhausted ? color.new(color.red, 85) : color.new(color.orange, 92)
bgcolor(in_overlap ? overlap_bg : na, title="Overlap Background")

show_lines = in_london or in_overlap
plot(show_lines ? lon_high : na, title="London High", color=color.new(color.green, 30), style=plot.style_linebr, linewidth=2)
plot(show_lines ? lon_low : na, title="London Low", color=color.new(color.red, 30), style=plot.style_linebr, linewidth=2)
plot(show_lines ? lon_mid : na, title="London Mid (Balance)", color=color.new(color.gray, 40), style=plot.style_cross, linewidth=1)

// =========================================================================
// Live Status Monitor (Top Right)
// =========================================================================
var table adr_table = table.new(position.top_right, 2, 2, bgcolor=color.new(color.black, 40), border_width=1, border_color=color.gray)

if barstate.islast
    if show_lines
        status_color = is_exhausted ? color.red : color.green
        status_text = is_exhausted ? "NO-GO (EXHAUSTED)" : "GO (ROOM TO MOVE)"
        
        table.cell(adr_table, 0, 0, "London ADR Consumed:", text_color=color.white, text_size=size.small, text_halign=text.align_left)
        table.cell(adr_table, 1, 0, str.tostring(pct_consumed, "#.1") + "%", text_color=status_color, text_size=size.small, text_halign=text.align_right)
        
        table.cell(adr_table, 0, 1, "Overlap Status:", text_color=color.white, text_size=size.small, text_halign=text.align_left)
        table.cell(adr_table, 1, 1, status_text, text_color=status_color, text_size=size.small, text_halign=text.align_right)
    else
        // Hide the table when outside of the trading windows to keep the chart clean
        table.clear(adr_table, 0, 0, 1, 1)
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
LondonScalper
Posts: 701
Joined: Sat Sep 05, 2026 7:54 am

Re: Pre-NY overlap checklist for GBPUSD when London has already run

Post by LondonScalper »

PTScalper wrote:The "No-Go": London already trended heavily and consumed 80%+ of the Average Daily Range (ADR)... If price is just lingering at the London high with thinning order book volume, it's a pass.
Agree on the ADR filter — once London has already spent most of the day, treating NY as a fresh open is how clean weeks get given back.

I run a similar go/no-go, with one extra desk check before the overlap: I mark London’s realised range as a % of our 20-day ADR at 12:30 London, then note whether the last hour was still thrusting or already digesting. If we’re past ~80% ADR and the book is thinning into the London high/low, I leave the order ticket blank. No “owing myself a trade.”

The go case you described — tight London consolidation, then a fast NY sweep/rejection with a structural shift back — is the only overlap setup I still size normally. Everything else is half-size or stand-aside.

Clear rule here: overlap is a continuation phase, not a reset. If London already ran, what is your hard ADR cutoff before you refuse any NY ticket on Cable?
PropScalpDesk
Posts: 273
Joined: Sat Sep 19, 2026 7:50 pm

Re: Pre-NY overlap checklist for GBPUSD when London has already run

Post by PropScalpDesk »

PTScalper wrote:By the time New York joins, GBPUSD has often already printed the morning’s range. My mistake for years was treating 13:00–15:00 London as a second open with fresh risk.
Cable overlap recycle is real. Sometimes continuation; often two-way. Your five-minute checklist is the difference between optional participation and compulsive repair. One-sentence thesis or flat. Tier-1 inside the next hour means stand-aside or microscopic size. If spreads still look like London-open costs, you are late, not early.

I run the same go/no-go from Frankfurt. Morning P&L state changes aggressiveness on purpose. Correlation with EURUSD is checked so I do not stack the same USD idea twice into NY.

Visualisers help; behaviour rules decide. Funded soft stops care more about the latter.

EURUSD correlation sits on the same card. Stacking cable and euro into NY as “two ideas” is how one USD impulse becomes two tickets and one ugly equity print.

After a busy London morning, what usually wins for you — protect the day, or hunt one overlap A+?
LondonNewsTrader
Posts: 79
Joined: Mon Sep 21, 2026 9:30 am

Re: Pre-NY overlap checklist for GBPUSD when London has already run

Post by LondonNewsTrader »

PTScalper wrote:MQL5 Indicator (LondonNYOverlap.mq5) Save in MQL5/Indicators/ and compile in MetaEditor: Code: Select all //+------------------------------------------------------------------+ //| LondonNYOverlap.mq5 | //| London-NY Overlap Session Range | //+------------------------------------------------------------------+ #property copyright "Community Script" #property version "1.
Useful to have the London range carried into the overlap as buffers rather than drawn objects; you can read the values from an EA or the data window later.

The inputs are in broker time, and that's where most people will go wrong. The majority of MT5 brokers run their servers on GMT+2 in winter and GMT+3 in summer, so London's 08:00 is 10:00 on the server, and an overlap starting at 13:00 London is 15:00 server. Leaving the defaults at 08:00/13:00/17:00 on a typical broker measures the wrong part of the day entirely. A comment next to the inputs with that example would save a lot of confusion.

There's a subtler problem twice a year. The US and UK change clocks on different dates, so for two or three weeks in March and again around late October the gap between London and New York is four hours instead of five. With fixed times the overlap box is out by an hour during those weeks. Worth knowing even if it isn't worth coding.

For the checklist itself, this overlap window contains 13:30 London, when most US releases come out. On data days I'd treat the London mid as the first reference after the release rather than something to trade into before it.
Post Reply