Advertisement IC Markets

EURUSD order flow tells I watch at the open discretionary

Discuss 1-minute to 15-minute price action setups, fading intraday momentum, key support/resistance zones, and proven short-term trading methodologies.
PTScalper
Site Admin
Posts: 7645
Joined: Mon Jul 20, 2026 1:28 pm

Re: EURUSD order flow tells I watch at the open discretionary

Post by PTScalper »

MetaTrader handles session timings and custom candlesticks a bit differently than TradingView. To achieve the exact same "overlay" effect where the underlying candles show through unless it's the London window, we use DRAW_COLOR_CANDLES. Outside the London window, the buffers are set to EMPTY_VALUE, letting the standard chart pass through.

The script dynamically calculates the Asian Box, draws it as a background rectangle, extends it into the London session,
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: 7645
Joined: Mon Jul 20, 2026 1:28 pm

Re: EURUSD order flow tells I watch at the open discretionary

Post by PTScalper »

1. MetaTrader 4 Version (.mq4)

Code: Select all

//+------------------------------------------------------------------+
//|                                        EUR_Open_Context_Pace.mq4 |
//+------------------------------------------------------------------+
#property strict
#property indicator_chart_window
#property indicator_buffers 5
#property indicator_type1 DRAW_COLOR_CANDLES
#property indicator_color1 clrLime, clrRed, clrTeal, clrMaroon
#property indicator_width1 2

//--- Inputs
input int    AsiaStartHour   = 0;    // Asian Box Start Hour
input int    AsiaEndHour     = 8;    // Asian Box End Hour
input int    LondonStartHour = 8;    // London Window Start Hour
input int    LondonEndHour   = 10;   // London Window End Hour
input int    VolLength       = 20;   // Tick Volume Average Length
input double VolMult         = 1.5;  // High Pace Multiplier

//--- Buffers
double BufO[], BufH[], BufL[], BufC[], BufCol[];

//--- State variables for the Box
bool     inAsiaPrev    = false;
double   asiaHigh      = 0;
double   asiaLow       = 999999;
datetime asiaStartTime = 0;

//+------------------------------------------------------------------+
int OnInit()
{
    SetIndexBuffer(0, BufO); SetIndexEmptyValue(0, EMPTY_VALUE);
    SetIndexBuffer(1, BufH); SetIndexEmptyValue(1, EMPTY_VALUE);
    SetIndexBuffer(2, BufL); SetIndexEmptyValue(2, EMPTY_VALUE);
    SetIndexBuffer(3, BufC); SetIndexEmptyValue(3, EMPTY_VALUE);
    SetIndexBuffer(4, BufCol, INDICATOR_COLOR_INDEX);
    
    IndicatorShortName("EUR Open Context & Pace");
    return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
    // Clean up all drawn boxes
    ObjectsDeleteAll(0, "AsiaBox_");
}

//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
    int limit = rates_total - prev_calculated - 1;
    if (limit > rates_total - VolLength - 1) 
        limit = rates_total - VolLength - 1;

    // Loop from oldest to newest to handle state and objects properly
    for(int i = limit; i >= 0; i--)
    {
        int h = TimeHour(Time[i]);
        bool inAsia = (h >= AsiaStartHour && h < AsiaEndHour);
        bool inLondon = (h >= LondonStartHour && h < LondonEndHour);

        // Track Asian High/Low dynamically
        if(inAsia)
        {
            if(!inAsiaPrev) // Just entered Asia
            {
                asiaHigh = High[i];
                asiaLow = Low[i];
                asiaStartTime = Time[i];
            }
            else
            {
                if(High[i] > asiaHigh) asiaHigh = High[i];
                if(Low[i] < asiaLow) asiaLow = Low[i];
            }
        }

        // Draw Box upon transition out of Asia
        if(!inAsia && inAsiaPrev)
        {
            string name = "AsiaBox_" + TimeToString(Time[i], TIME_DATE);
            datetime londonEndTime = Time[i] + (LondonEndHour - h) * 3600;
            
            ObjectCreate(0, name, OBJ_RECTANGLE, 0, asiaStartTime, asiaHigh, londonEndTime, asiaLow);
            ObjectSetInteger(0, name, OBJPROP_COLOR, clrDarkBlue);
            ObjectSetInteger(0, name, OBJPROP_BACK, true); // Keep behind candles
            ObjectSetInteger(0, name, OBJPROP_FILL, true);
        }
        inAsiaPrev = inAsia;

        // Pace logic and Candle Coloring for London Window
        if(inLondon)
        {
            long sumVol = 0;
            for(int j = 1; j <= VolLength; j++) {
                sumVol += (long)Volume[i+j];
            }
            double avgVol = (double)sumVol / VolLength;
            bool highPace = Volume[i] > (avgVol * VolMult);
            bool isBull = Close[i] > Open[i];

            BufO[i] = Open[i];
            BufH[i] = High[i];
            BufL[i] = Low[i];
            BufC[i] = Close[i];

            if(highPace)
                BufCol[i] = isBull ? 0 : 1; // 0:Lime, 1:Red (The Snap)
            else
                BufCol[i] = isBull ? 2 : 3; // 2:Teal, 3:Maroon (The Slog)
        }
        else
        {
            BufO[i] = EMPTY_VALUE;
            BufH[i] = EMPTY_VALUE;
            BufL[i] = EMPTY_VALUE;
            BufC[i] = EMPTY_VALUE;
        }
    }
    return(rates_total);
}
//+------------------------------------------------------------------+
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 7645
Joined: Mon Jul 20, 2026 1:28 pm

Re: EURUSD order flow tells I watch at the open discretionary

Post by PTScalper »

2. MetaTrader 5 Version (.mq5)

MQL5 handles arrays natively from oldest (index 0) to newest. The math and indexing have been optimized for MQL5's array structure.

Code: Select all

//+------------------------------------------------------------------+
//|                                        EUR_Open_Context_Pace.mq5 |
//+------------------------------------------------------------------+
#property indicator_chart_window
#property indicator_buffers 5
#property indicator_plots   1
#property indicator_type1   DRAW_COLOR_CANDLES
#property indicator_color1  clrLime, clrRed, clrTeal, clrMaroon
#property indicator_width1  2

//--- Inputs
input int    InpAsiaStartHour   = 0;    // Asian Box Start Hour
input int    InpAsiaEndHour     = 8;    // Asian Box End Hour
input int    InpLondonStartHour = 8;    // London Window Start Hour
input int    InpLondonEndHour   = 10;   // London Window End Hour
input int    InpVolLength       = 20;   // Tick Volume Average Length
input double InpVolMult         = 1.5;  // High Pace Multiplier

//--- Buffers
double BufO[], BufH[], BufL[], BufC[], BufCol[];

//--- State variables for the Box
bool     inAsiaPrev    = false;
double   asiaHigh      = 0;
double   asiaLow       = 999999;
datetime asiaStartTime = 0;

//+------------------------------------------------------------------+
int OnInit()
{
    SetIndexBuffer(0, BufO, INDICATOR_DATA);
    SetIndexBuffer(1, BufH, INDICATOR_DATA);
    SetIndexBuffer(2, BufL, INDICATOR_DATA);
    SetIndexBuffer(3, BufC, INDICATOR_DATA);
    SetIndexBuffer(4, BufCol, INDICATOR_COLOR_INDEX);

    PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0.0);
    IndicatorSetString(INDICATOR_SHORTNAME, "EUR Open Context & Pace");
    return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
    ObjectsDeleteAll(0, "AsiaBox_");
}

//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
    // MQL5 processes from 0 (oldest) to rates_total-1 (newest)
    int start = (prev_calculated == 0) ? InpVolLength : prev_calculated - 1;

    for(int i = start; i < rates_total; i++)
    {
        MqlDateTime dt;
        TimeToStruct(time[i], dt);
        int h = dt.hour;
        
        bool inAsia = (h >= InpAsiaStartHour && h < InpAsiaEndHour);
        bool inLondon = (h >= InpLondonStartHour && h < InpLondonEndHour);

        // Track Asian High/Low dynamically
        if(inAsia)
        {
            if(!inAsiaPrev) 
            {
                asiaHigh = high[i];
                asiaLow = low[i];
                asiaStartTime = time[i];
            }
            else
            {
                if(high[i] > asiaHigh) asiaHigh = high[i];
                if(low[i] < asiaLow) asiaLow = low[i];
            }
        }

        // Draw Box upon transition out of Asia
        if(!inAsia && inAsiaPrev)
        {
            string name = "AsiaBox_" + TimeToString(time[i], TIME_DATE);
            datetime londonEndTime = time[i] + (InpLondonEndHour - h) * 3600;
            
            ObjectCreate(0, name, OBJ_RECTANGLE, 0, asiaStartTime, asiaHigh, londonEndTime, asiaLow);
            ObjectSetInteger(0, name, OBJPROP_COLOR, clrDarkBlue);
            ObjectSetInteger(0, name, OBJPROP_BACK, true); 
            ObjectSetInteger(0, name, OBJPROP_FILL, true);
        }
        inAsiaPrev = inAsia;

        // Pace logic and Candle Coloring
        if(inLondon)
        {
            long sumVol = 0;
            for(int j = 1; j <= InpVolLength; j++) {
                if((i - j) >= 0) sumVol += tick_volume[i - j];
            }
            double avgVol = (double)sumVol / InpVolLength;
            bool highPace = tick_volume[i] > (avgVol * InpVolMult);
            bool isBull = close[i] > open[i];

            BufO[i] = open[i];
            BufH[i] = high[i];
            BufL[i] = low[i];
            BufC[i] = close[i];

            if(highPace)
                BufCol[i] = isBull ? 0 : 1; // 0:Lime, 1:Red
            else
                BufCol[i] = isBull ? 2 : 3; // 2:Teal, 3:Maroon
        }
        else
        {
            BufO[i] = 0.0;
            BufH[i] = 0.0;
            BufL[i] = 0.0;
            BufC[i] = 0.0;
        }
    }
    return(rates_total);
}
//+------------------------------------------------------------------+
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 7645
Joined: Mon Jul 20, 2026 1:28 pm

Re: EURUSD order flow tells I watch at the open discretionary

Post by PTScalper »

Installation Notes for MetaTrader:

Since you configure C# and Pine already, hit F4 to open the MetaEditor.

Under Indicators, create a new Custom Indicator. Paste the respective code.

Important Configuration Note: MetaTrader broker server times differ. Check your Market Watch time. If your broker runs GMT+3 (like IC Markets or Pepperstone in summer), the Frankfurt/London transition will be roughly 09:00 - 11:00 server time. Adjust the input parameters accordingly; the default 08:00 - 10:00 assumes GMT+2.

The background rectangle (OBJ_RECTANGLE) handles the Asian Box structure, sweeping, and liquidity grabs, while the overlaid colored candles isolate the tape pace specifically during your high-value execution window.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 7645
Joined: Mon Jul 20, 2026 1:28 pm

Re: EURUSD order flow tells I watch at the open discretionary

Post by PTScalper »

Here is the clean, optimized C# implementation using the modern Bars API (cTrader 4.0+).

cTrader / cAlgo C# Implementation

Code: Select all

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

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class EUR_Open_Context_Pace : Indicator
    {
        [Parameter("Asia Start Hour", DefaultValue = 0, Group = "Session Times (Server Time)")]
        public int AsiaStartHour { get; set; }

        [Parameter("Asia End Hour", DefaultValue = 8, Group = "Session Times (Server Time)")]
        public int AsiaEndHour { get; set; }

        [Parameter("London Start Hour", DefaultValue = 8, Group = "Session Times (Server Time)")]
        public int LondonStartHour { get; set; }

        [Parameter("London End Hour", DefaultValue = 10, Group = "Session Times (Server Time)")]
        public int LondonEndHour { get; set; }

        [Parameter("Tick Volume Length", DefaultValue = 20, Group = "Pace / Flow Proxy")]
        public int VolLength { get; set; }

        [Parameter("High Pace Multiplier", DefaultValue = 1.5, Group = "Pace / Flow Proxy", 
            DefaultValue = 1.5, MinValue = 1.0, Step = 0.1)]
        public double VolMult { get; set; }

        private SimpleMovingAverage _volSma;
        private double _asiaHigh;
        private double _asiaLow = double.MaxValue;
        private DateTime _asiaStartTime;
        private bool _inAsiaPrev;

        protected override void Initialize()
        {
            // Utilize built-in SMA for tick volumes
            _volSma = Indicators.SimpleMovingAverage(Bars.TickVolumes, VolLength);
        }

        public override void Calculate(int index)
        {
            var time = Bars.OpenTimes[index];
            int h = time.Hour;

            bool inAsia = (h >= AsiaStartHour && h < AsiaEndHour);
            bool inLondon = (h >= LondonStartHour && h < LondonEndHour);

            // Track Asian High/Low dynamically
            if (inAsia)
            {
                if (!_inAsiaPrev)
                {
                    _asiaHigh = Bars.HighPrices[index];
                    _asiaLow = Bars.LowPrices[index];
                    _asiaStartTime = time;
                }
                else
                {
                    if (Bars.HighPrices[index] > _asiaHigh) _asiaHigh = Bars.HighPrices[index];
                    if (Bars.LowPrices[index] < _asiaLow) _asiaLow = Bars.LowPrices[index];
                }
            }

            // Draw the Box upon transition out of Asia
            if (!inAsia && _inAsiaPrev)
            {
                string name = "AsiaBox_" + time.Date.ToString("yyyyMMdd");
                
                // Project the right side of the box to the end of the London execution window
                DateTime londonEndTime = time.Date.AddHours(LondonEndHour);
                if (LondonEndHour < h) londonEndTime = londonEndTime.AddDays(1); // Midnight wrap guard

                // Semi-transparent blue for the background structure
                var boxColor = Color.FromArgb(40, Color.DodgerBlue);
                var rect = Chart.DrawRectangle(name, _asiaStartTime, _asiaHigh, londonEndTime, _asiaLow, boxColor);
                
                rect.IsFilled = true;
                rect.ZIndex = -1; // Keep it strictly behind the price action
            }

            _inAsiaPrev = inAsia;

            // Pace logic and Candle Coloring for London Window
            if (inLondon && index >= VolLength)
            {
                // We use the previous bar's SMA to prevent the current bar's anomalous volume 
                // from dragging the average up and masking the true relative pace.
                double avgVol = _volSma.Result[index - 1]; 
                double currentVol = Bars.TickVolumes[index];
                
                bool highPace = currentVol > (avgVol * VolMult);
                bool isBull = Bars.ClosePrices[index] > Bars.OpenPrices[index];

                Color barColor;

                if (highPace)
                    barColor = isBull ? Color.Lime : Color.Red;       // The "Snap"
                else
                    barColor = isBull ? Color.Teal : Color.Maroon;    // The "Slog"

                // Overrides the standard chart candle color for this specific index
                Chart.SetBarColor(index, barColor);
            }
        }
    }
}
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 7645
Joined: Mon Jul 20, 2026 1:28 pm

Re: EURUSD order flow tells I watch at the open discretionary

Post by PTScalper »

Key Differences & Execution Context:

Direct DOM Override: Instead of generating entirely new plot buffers like MQL, Chart.SetBarColor(index, barColor) elegantly hijacks the default candle rendering during the London window, leaving the rest of the chart entirely standard.

Z-Indexing for Visuals: cAlgo gives us direct access to rect.ZIndex = -1, ensuring your Asian box never visually competes with the actual price structure.

Calculation Anchor: I anchored the tick volume SMA comparison to _volSma.Result[index - 1]. If you compare the current tick volume to a moving average that includes the current massive spike, the math dampens the relative percentage increase. Using the previous bar's moving average preserves the true magnitude of the breakout/sweep volume.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
LondonScalper
Posts: 965
Joined: Sat Sep 05, 2026 7:54 am

Re: EURUSD order flow tells I watch at the open discretionary

Post by LondonScalper »

Veto-only is the boundary I trust. The moment I let a fast tape “confirm” an entry I did not already have from level and time, I start paying for theatre.

Pace and aggressive prints in the first half hour can talk me out of a fade into strength. They do not talk me into a chase. Soft tells, hard rules underneath: if the spread is wrong or the time stop is due, the tell does not get a vote.

I have sat through enough footprint webinars to know what cosplay looks like from the inside. The open is noisy enough without inventing a second job as a market-maker.
FXS Prop Desk
Posts: 1572
Joined: Wed Oct 07, 2026 9:52 am

Re: EURUSD order flow tells I watch at the open discretionary

Post by FXS Prop Desk »

Using the spread as a sentiment indicator at the open is a good point. Many platforms do not show spread history, so a simple indicator that plots the spread on each M1 bar makes it visible. Over a few weeks it becomes clear what "normal" looks like 10–15 minutes into London for your broker, which is necessary before treating a wide spread as a signal.
FXS Official Team | The Idea Lab & Strategy
Post Reply