Page 2 of 2
Re: EURUSD order flow tells I watch at the open discretionary
Posted: Fri Oct 02, 2026 9:26 am
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,
Re: EURUSD order flow tells I watch at the open discretionary
Posted: Fri Oct 02, 2026 9:26 am
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);
}
//+------------------------------------------------------------------+
Re: EURUSD order flow tells I watch at the open discretionary
Posted: Fri Oct 02, 2026 9:26 am
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);
}
//+------------------------------------------------------------------+
Re: EURUSD order flow tells I watch at the open discretionary
Posted: Fri Oct 02, 2026 9:27 am
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.
Re: EURUSD order flow tells I watch at the open discretionary
Posted: Fri Oct 02, 2026 9:28 am
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);
}
}
}
}
Re: EURUSD order flow tells I watch at the open discretionary
Posted: Fri Oct 02, 2026 9:28 am
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.
Re: EURUSD order flow tells I watch at the open discretionary
Posted: Mon Oct 05, 2026 8:19 am
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.
Re: EURUSD order flow tells I watch at the open discretionary
Posted: Sun Oct 18, 2026 8:50 am
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.