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,
EURUSD order flow tells I watch at the open discretionary
Re: EURUSD order flow tells I watch at the open discretionary
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: EURUSD order flow tells I watch at the open discretionary
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.
Re: EURUSD order flow tells I watch at the open discretionary
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.
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.
Re: EURUSD order flow tells I watch at the open discretionary
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.
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.
Re: EURUSD order flow tells I watch at the open discretionary
Here is the clean, optimized C# implementation using the modern Bars API (cTrader 4.0+).
cTrader / cAlgo C# Implementation
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.
Re: EURUSD order flow tells I watch at the open discretionary
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.
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
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.
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
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