Best forex pairs to scalp during london session
Re: Best forex pairs to scalp during london session
How to execute with this data:
The RVOL Filter: If EURUSD has an RVOL of 0.8 and GBPUSD is sitting at 1.6, the institutional order flow is concentrated in Cable. Drop the Euro and focus your risk entirely on GBP.
ATR Calibration: Scalping requires range. If the ATR on your primary drops below your minimum pip threshold, the pair is just chopping. The dashboard standardizes this by converting raw ATR to pips across both USD and JPY pairs, allowing for an apples-to-apples comparison.
Session Discipline: The matrix clearly indicates when you are inside the active London core hours, keeping you out of the low-liquidity chop before the bell rings.
The RVOL Filter: If EURUSD has an RVOL of 0.8 and GBPUSD is sitting at 1.6, the institutional order flow is concentrated in Cable. Drop the Euro and focus your risk entirely on GBP.
ATR Calibration: Scalping requires range. If the ATR on your primary drops below your minimum pip threshold, the pair is just chopping. The dashboard standardizes this by converting raw ATR to pips across both USD and JPY pairs, allowing for an apples-to-apples comparison.
Session Discipline: The matrix clearly indicates when you are inside the active London core hours, keeping you out of the low-liquidity chop before the bell rings.
Re: Best forex pairs to scalp during london session
To operationalize this at a higher level, you shouldn't just look at relative volume (RVOL); you need to quantify real-time correlation to the dollar index (DXY). If two pairs are heavily correlated to the DXY at the open, they are the same trade.
Here is an upgraded, institutional-grade Pine Script v5 matrix. It incorporates a rolling DXY correlation engine and normalizes volume using Z-Scores, giving you a purely quantitative read on where the real session alpha lies.
Institutional Liquidity & Correlation Matrix
This script builds a heads-up display that actively measures each pair's localized volatility, its standardized volume (Z-Score), and its rolling correlation to the dollar index.
Here is an upgraded, institutional-grade Pine Script v5 matrix. It incorporates a rolling DXY correlation engine and normalizes volume using Z-Scores, giving you a purely quantitative read on where the real session alpha lies.
Institutional Liquidity & Correlation Matrix
This script builds a heads-up display that actively measures each pair's localized volatility, its standardized volume (Z-Score), and its rolling correlation to the dollar index.
Code: Select all
//@version=5
indicator("Desk Matrix: Vol & Beta", overlay=true)
// --- Parameters ---
grp1 = "System Parameters"
sessionTime = input.session("0800-1200", title="London Core (UTC)", group=grp1)
tz = input.string("UTC", title="Timezone", group=grp1)
benchmark = input.symbol("TVC:DXY", title="Macro Benchmark", group=grp1)
lookback = input.int(20, title="Rolling Window", group=grp1)
grp2 = "Order Book"
sym1 = input.symbol("OANDA:EURUSD", title="Ticker 1", group=grp2)
sym2 = input.symbol("OANDA:GBPUSD", title="Ticker 2", group=grp2)
sym3 = input.symbol("OANDA:GBPJPY", title="Ticker 3", group=grp2)
sym4 = input.symbol("OANDA:USDJPY", title="Ticker 4", group=grp2)
// --- Logic ---
inSession = not na(time(timeframe.period, sessionTime, tz))
benchClose = request.security(benchmark, timeframe.period, close)
// Metric Engine
getMetrics() =>
pipMult = str.contains(syminfo.tickerid, "JPY") ? 100 : 10000
atrPips = ta.atr(lookback) * pipMult
// Volume Z-Score
vSma = ta.sma(volume, lookback)
vDev = ta.stdev(volume, lookback)
volZ = vDev > 0 ? (volume - vSma) / vDev : 0.0
// Benchmark Correlation
corr = ta.correlation(close, benchClose, lookback)
[volZ, atrPips, corr]
[z1, atr1, c1] = request.security(sym1, timeframe.period, getMetrics())
[z2, atr2, c2] = request.security(sym2, timeframe.period, getMetrics())
[z3, atr3, c3] = request.security(sym3, timeframe.period, getMetrics())
[z4, atr4, c4] = request.security(sym4, timeframe.period, getMetrics())
// --- HUD Rendering ---
var table matrix = table.new(position.top_right, 5, 5, bgcolor=color.new(color.black, 10), border_width=1, border_color=color.new(color.gray, 80))
if barstate.islast
// Headers
table.cell(matrix, 0, 0, "Asset", text_color=color.gray, text_size=size.small)
table.cell(matrix, 1, 0, "Session", text_color=color.gray, text_size=size.small)
table.cell(matrix, 2, 0, "Vol Z-Score", text_color=color.gray, text_size=size.small)
table.cell(matrix, 3, 0, "ATR (Pips)", text_color=color.gray, text_size=size.small)
table.cell(matrix, 4, 0, "DXY Beta", text_color=color.gray, text_size=size.small)
// Row Population
renderRow(tbl, row, sym, z, atrVal, corr) =>
isHot = z > 1.5
table.cell(tbl, 0, row, sym, text_color=color.white, text_halign=text.align_left)
table.cell(tbl, 1, row, inSession ? "Live" : "Pre", text_color=inSession ? color.lime : color.gray)
table.cell(tbl, 2, row, str.tostring(z, "#.##"), text_color=isHot ? color.aqua : color.white)
table.cell(tbl, 3, row, str.tostring(atrVal, "#.1"), text_color=color.white)
table.cell(tbl, 4, row, str.tostring(corr, "#.##"), text_color=math.abs(corr) > 0.8 ? color.orange : color.white)
renderRow(matrix, 1, sym1, z1, atr1, c1)
renderRow(matrix, 2, sym2, z2, atr2, c2)
renderRow(matrix, 3, sym3, z3, atr3, c3)
renderRow(matrix, 4, sym4, z4, atr4, c4)Re: Best forex pairs to scalp during london session
Execution Protocol
Volume Z-Score over RVOL: Standard RVOL can be skewed by flat overnight sessions. A Z-Score mathematically standardizes the volume. Look for standard deviations above +1.5 (Aqua) to confirm genuine institutional footprint.
The DXY Beta Trap: The matrix calculates a 20-period rolling correlation against the DXY. If EURUSD and GBPUSD both show an absolute correlation above 0.80 (Orange), they are trading as pure dollar derivatives. You isolate the one with the higher Z-Score and discard the other.
Isolating Crosses: If GBPJPY fires a high Z-score while GBPUSD shows low correlation to the DXY, the flow is structurally driven by the Pound or the Yen, not the Dollar. This is when crosses become valid primary tickets.
Does your current trade management model adjust aggregate risk based on correlation metrics, or do you run fixed fractional sizing regardless of the overlapping DXY exposure?
Volume Z-Score over RVOL: Standard RVOL can be skewed by flat overnight sessions. A Z-Score mathematically standardizes the volume. Look for standard deviations above +1.5 (Aqua) to confirm genuine institutional footprint.
The DXY Beta Trap: The matrix calculates a 20-period rolling correlation against the DXY. If EURUSD and GBPUSD both show an absolute correlation above 0.80 (Orange), they are trading as pure dollar derivatives. You isolate the one with the higher Z-Score and discard the other.
Isolating Crosses: If GBPJPY fires a high Z-score while GBPUSD shows low correlation to the DXY, the flow is structurally driven by the Pound or the Yen, not the Dollar. This is when crosses become valid primary tickets.
Does your current trade management model adjust aggregate risk based on correlation metrics, or do you run fixed fractional sizing regardless of the overlapping DXY exposure?
Re: Best forex pairs to scalp during london session
Porting this logic from Pine Script to MetaTrader requires shifting from TradingView's cloud-based server architecture to managing localized, asynchronous tick history.
Since MetaTrader handles multi-currency data differently depending on the version, I have built two distinct, highly optimized implementations. Both use an OnTimer() event loop to prevent chart freezing (a common issue with multi-currency MT4/MT5 indicators) and avoid memory leaks by managing chart objects dynamically without relying on cumbersome indicator handles.
Below are the complete, institutional-grade Indicator scripts for both platforms.
Since MetaTrader handles multi-currency data differently depending on the version, I have built two distinct, highly optimized implementations. Both use an OnTimer() event loop to prevent chart freezing (a common issue with multi-currency MT4/MT5 indicators) and avoid memory leaks by managing chart objects dynamically without relying on cumbersome indicator handles.
Below are the complete, institutional-grade Indicator scripts for both platforms.
Re: Best forex pairs to scalp during london session
1. MetaTrader 5 (MQL5) Implementation
In MT5, we bypass heavy iATR handles and instead calculate True Range purely through raw price arrays. This keeps the indicator lightning fast and completely immune to handle-exhaustion.
Open MetaEditor 5, create a New Custom Indicator.
Name it LondonDeskMatrix.
Replace all the code with the following:
In MT5, we bypass heavy iATR handles and instead calculate True Range purely through raw price arrays. This keeps the indicator lightning fast and completely immune to handle-exhaustion.
Open MetaEditor 5, create a New Custom Indicator.
Name it LondonDeskMatrix.
Replace all the code with the following:
Code: Select all
//+------------------------------------------------------------------+
//| LondonDeskMatrix.mq5 |
//| Institutional Pro Desk |
//+------------------------------------------------------------------+
#property copyright "Pro Desk Matrix"
#property indicator_chart_window
#property indicator_buffers 0
input string InpSessionStart = "08:00"; // London Start (Broker Server Time)
input string InpSessionEnd = "12:00"; // London End (Broker Server Time)
input string InpBenchmark = "DXY"; // Macro Benchmark (e.g. DXY, USDX, or EURUSD)
input int InpLookback = 20; // Rolling Window
input string Sym1 = "EURUSD";
input string Sym2 = "GBPUSD";
input string Sym3 = "GBPJPY";
input string Sym4 = "USDJPY";
int OnInit() {
EventSetTimer(1); // 1-second refresh cycle
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason) {
EventKillTimer();
ObjectsDeleteAll(0, "Mat_");
ChartRedraw();
}
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[]) {
return(rates_total);
}
//--- Helper: Draw Text Object
void DrawLabel(string name, int x, int y, string text, color clr) {
if(ObjectFind(0, name) < 0) {
ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);
ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_RIGHT_UPPER);
ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_RIGHT_UPPER);
ObjectSetString(0, name, OBJPROP_FONT, "Consolas");
ObjectSetInteger(0, name, OBJPROP_FONTSIZE, 9);
ObjectSetInteger(0, name, OBJPROP_BACK, false);
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, name, OBJPROP_HIDDEN, true);
}
ObjectSetString(0, name, OBJPROP_TEXT, text);
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
}
//--- Math Engines
double GetATR(string sym, int lookback) {
double high[], low[], close[];
if(CopyHigh(sym, 0, 0, lookback+1, high) < lookback+1) return 0.0;
if(CopyLow(sym, 0, 0, lookback+1, low) < lookback+1) return 0.0;
if(CopyClose(sym, 0, 0, lookback+1, close) < lookback+1) return 0.0;
double trSum = 0;
for(int i = 1; i <= lookback; i++) {
double hl = high[i] - low[i];
double hc = MathAbs(high[i] - close[i-1]);
double lc = MathAbs(low[i] - close[i-1]);
trSum += MathMax(hl, MathMax(hc, lc));
}
double atr = trSum / lookback;
long digits = SymbolInfoInteger(sym, SYMBOL_DIGITS);
double point = SymbolInfoDouble(sym, SYMBOL_POINT);
double pipMult = (digits == 3 || digits == 5) ? 10.0 : 1.0;
return (point > 0) ? (atr / (point * pipMult)) : 0.0;
}
double GetVolZScore(string sym, int lookback) {
long vols[];
if(CopyTickVolume(sym, 0, 0, lookback+1, vols) < lookback+1) return 0.0;
double mean = 0.0;
for(int i = 0; i < lookback; i++) mean += (double)vols[i];
mean /= lookback;
double variance = 0.0;
for(int i = 0; i < lookback; i++) {
double d = (double)vols[i] - mean;
variance += (d * d);
}
double stddev = MathSqrt(variance / lookback);
if(stddev == 0.0) return 0.0;
return ((double)vols[lookback] - mean) / stddev;
}
double GetCorrelation(string symA, string symB, int lookback) {
double arrA[], arrB[];
if(CopyClose(symA, 0, 1, lookback, arrA) < lookback) return 0.0;
if(CopyClose(symB, 0, 1, lookback, arrB) < lookback) return 0.0;
double meanA = 0, meanB = 0;
for(int i = 0; i < lookback; i++) { meanA += arrA[i]; meanB += arrB[i]; }
meanA /= lookback; meanB /= lookback;
double sumAB = 0, sumA2 = 0, sumB2 = 0;
for(int i = 0; i < lookback; i++) {
double dA = arrA[i] - meanA; double dB = arrB[i] - meanB;
sumAB += (dA * dB); sumA2 += (dA * dA); sumB2 += (dB * dB);
}
if(sumA2 * sumB2 == 0) return 0.0;
return sumAB / MathSqrt(sumA2 * sumB2);
}
bool IsInSession(string startHM, string endHM) {
MqlDateTime tm;
TimeToStruct(TimeCurrent(), tm);
int currentMins = tm.hour * 60 + tm.min;
string sArr[], eArr[];
StringSplit(startHM, ':', sArr); StringSplit(endHM, ':', eArr);
if(ArraySize(sArr) < 2 || ArraySize(eArr) < 2) return false;
int sMins = (int)StringToInteger(sArr[0]) * 60 + (int)StringToInteger(sArr[1]);
int eMins = (int)StringToInteger(eArr[0]) * 60 + (int)StringToInteger(eArr[1]);
return (sMins <= eMins) ? (currentMins >= sMins && currentMins <= eMins) : (currentMins >= sMins || currentMins <= eMins);
}
void DrawRow(int rowIdx, string sym, bool inSession, double z, double atr, double corr) {
int y = 20 + (rowIdx * 22);
color colStat = inSession ? clrLime : clrDimGray;
color colVol = (z > 1.5) ? clrAqua : clrWhite;
color colBeta = (MathAbs(corr) > 0.8) ? clrOrange : clrWhite;
DrawLabel("Mat_R" + IntegerToString(rowIdx) + "_Asset", 320, y, sym, clrWhite);
DrawLabel("Mat_R" + IntegerToString(rowIdx) + "_Stat", 240, y, inSession ? "Live" : "Wait", colStat);
DrawLabel("Mat_R" + IntegerToString(rowIdx) + "_Vol", 160, y, DoubleToString(z, 2), colVol);
DrawLabel("Mat_R" + IntegerToString(rowIdx) + "_ATR", 90, y, DoubleToString(atr, 1), clrWhite);
DrawLabel("Mat_R" + IntegerToString(rowIdx) + "_Beta", 20, y, DoubleToString(corr, 2), colBeta);
}
void OnTimer() {
bool sessionLive = IsInSession(InpSessionStart, InpSessionEnd);
DrawLabel("Mat_H_Asset", 320, 20, "ASSET", clrGray);
DrawLabel("Mat_H_Stat", 240, 20, "STATUS", clrGray);
DrawLabel("Mat_H_Vol", 160, 20, "VOL Z", clrGray);
DrawLabel("Mat_H_ATR", 90, 20, "ATR", clrGray);
DrawLabel("Mat_H_Beta", 20, 20, "BETA", clrGray);
string symbols[4] = {Sym1, Sym2, Sym3, Sym4};
for(int i = 0; i < 4; i++) {
double z = GetVolZScore(symbols[i], InpLookback);
double atr = GetATR(symbols[i], InpLookback);
double corr = GetCorrelation(symbols[i], InpBenchmark, InpLookback);
DrawRow(i+1, symbols[i], sessionLive, z, atr, corr);
}
ChartRedraw();
}Re: Best forex pairs to scalp during london session
2. MetaTrader 4 (MQL4) Implementation
MT4 executes multi-currency calls through built-in legacy functions (iClose, iVolume). This code leverages strict compiling mode to allow MT5-style drawing and array behavior within MT4.
Open MetaEditor 4, create a New Custom Indicator.
Name it LondonDeskMatrix.
Replace all the code with the following:
MT4 executes multi-currency calls through built-in legacy functions (iClose, iVolume). This code leverages strict compiling mode to allow MT5-style drawing and array behavior within MT4.
Open MetaEditor 4, create a New Custom Indicator.
Name it LondonDeskMatrix.
Replace all the code with the following:
Code: Select all
//+------------------------------------------------------------------+
//| LondonDeskMatrix.mq4 |
//| Institutional Pro Desk |
//+------------------------------------------------------------------+
#property copyright "Pro Desk Matrix"
#property link ""
#property version "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 0
input string InpSessionStart = "08:00"; // London Start (Broker Server Time)
input string InpSessionEnd = "12:00"; // London End (Broker Server Time)
input string InpBenchmark = "USDX"; // Macro Benchmark (e.g. USDX, DXY, or EURUSD)
input int InpLookback = 20; // Rolling Window
input string Sym1 = "EURUSD";
input string Sym2 = "GBPUSD";
input string Sym3 = "GBPJPY";
input string Sym4 = "USDJPY";
int OnInit() {
EventSetTimer(1);
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason) {
EventKillTimer();
ObjectsDeleteAll(0, "Mat_");
ChartRedraw();
}
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[]) {
return(rates_total);
}
void DrawLabel(string name, int x, int y, string text, color clr) {
if(ObjectFind(0, name) < 0) {
ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);
ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_RIGHT_UPPER);
ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_RIGHT_UPPER);
ObjectSetString(0, name, OBJPROP_FONT, "Consolas");
ObjectSetInteger(0, name, OBJPROP_FONTSIZE, 9);
ObjectSetInteger(0, name, OBJPROP_BACK, false);
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, name, OBJPROP_HIDDEN, true);
}
ObjectSetString(0, name, OBJPROP_TEXT, text);
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
}
double GetATR(string sym, int lookback) {
double atr = iATR(sym, 0, lookback, 0);
if(atr == 0) return 0.0;
int digits = (int)SymbolInfoInteger(sym, SYMBOL_DIGITS);
double point = SymbolInfoDouble(sym, SYMBOL_POINT);
double pipMult = (digits == 3 || digits == 5) ? 10.0 : 1.0;
return atr / (point * pipMult);
}
double GetVolZScore(string sym, int lookback) {
double vols[]; ArrayResize(vols, lookback);
double mean = 0.0;
for(int i = 0; i < lookback; i++) {
vols[i] = (double)iVolume(sym, 0, i+1);
if(vols[i] == 0) return 0.0;
mean += vols[i];
}
mean /= lookback;
double variance = 0.0;
for(int i = 0; i < lookback; i++) {
double d = vols[i] - mean;
variance += (d * d);
}
double stddev = MathSqrt(variance / lookback);
if(stddev == 0.0) return 0.0;
return ((double)iVolume(sym, 0, 0) - mean) / stddev;
}
double GetCorrelation(string symA, string symB, int lookback) {
double arrA[], arrB[];
ArrayResize(arrA, lookback); ArrayResize(arrB, lookback);
double meanA = 0, meanB = 0;
for(int i = 0; i < lookback; i++) {
arrA[i] = iClose(symA, 0, i+1);
arrB[i] = iClose(symB, 0, i+1);
if(arrA[i] == 0 || arrB[i] == 0) return 0.0;
meanA += arrA[i]; meanB += arrB[i];
}
meanA /= lookback; meanB /= lookback;
double sumAB = 0, sumA2 = 0, sumB2 = 0;
for(int i = 0; i < lookback; i++) {
double dA = arrA[i] - meanA; double dB = arrB[i] - meanB;
sumAB += (dA * dB); sumA2 += (dA * dA); sumB2 += (dB * dB);
}
if(sumA2 * sumB2 == 0) return 0.0;
return sumAB / MathSqrt(sumA2 * sumB2);
}
bool IsInSession(string startHM, string endHM) {
MqlDateTime tm;
TimeToStruct(TimeCurrent(), tm);
int currentMins = tm.hour * 60 + tm.min;
string sArr[], eArr[];
StringSplit(startHM, ':', sArr); StringSplit(endHM, ':', eArr);
if(ArraySize(sArr) < 2 || ArraySize(eArr) < 2) return false;
int sMins = (int)StringToInteger(sArr[0]) * 60 + (int)StringToInteger(sArr[1]);
int eMins = (int)StringToInteger(eArr[0]) * 60 + (int)StringToInteger(eArr[1]);
return (sMins <= eMins) ? (currentMins >= sMins && currentMins <= eMins) : (currentMins >= sMins || currentMins <= eMins);
}
void DrawRow(int rowIdx, string sym, bool inSession, double z, double atr, double corr) {
int y = 20 + (rowIdx * 22);
color colStat = inSession ? clrLime : clrDimGray;
color colVol = (z > 1.5) ? clrAqua : clrWhite;
color colBeta = (MathAbs(corr) > 0.8) ? clrOrange : clrWhite;
DrawLabel("Mat_R" + IntegerToString(rowIdx) + "_Asset", 320, y, sym, clrWhite);
DrawLabel("Mat_R" + IntegerToString(rowIdx) + "_Stat", 240, y, inSession ? "Live" : "Wait", colStat);
DrawLabel("Mat_R" + IntegerToString(rowIdx) + "_Vol", 160, y, DoubleToString(z, 2), colVol);
DrawLabel("Mat_R" + IntegerToString(rowIdx) + "_ATR", 90, y, DoubleToString(atr, 1), clrWhite);
DrawLabel("Mat_R" + IntegerToString(rowIdx) + "_Beta", 20, y, DoubleToString(corr, 2), colBeta);
}
void OnTimer() {
bool sessionLive = IsInSession(InpSessionStart, InpSessionEnd);
DrawLabel("Mat_H_Asset", 320, 20, "ASSET", clrGray);
DrawLabel("Mat_H_Stat", 240, 20, "STATUS", clrGray);
DrawLabel("Mat_H_Vol", 160, 20, "VOL Z", clrGray);
DrawLabel("Mat_H_ATR", 90, 20, "ATR", clrGray);
DrawLabel("Mat_H_Beta", 20, 20, "BETA", clrGray);
string symbols[4] = {Sym1, Sym2, Sym3, Sym4};
for(int i = 0; i < 4; i++) {
double z = GetVolZScore(symbols[i], InpLookback);
double atr = GetATR(symbols[i], InpLookback);
double corr = GetCorrelation(symbols[i], InpBenchmark, InpLookback);
DrawRow(i+1, symbols[i], sessionLive, z, atr, corr);
}
ChartRedraw();
}Re: Best forex pairs to scalp during london session
Critical Execution Setup Notes:
Broker Server Time vs. UTC: Unlike TradingView where you normalize everything to UTC, MT4 and MT5 execute off your broker's server time. You must adjust the InpSessionStart and InpSessionEnd inputs to match when London opens on your broker's clock (e.g., if your broker is GMT+2, London open might be 10:00).
Benchmark Integrity: Not all brokers provide "DXY". If your broker calls it "USDX", update the input. If they do not offer a dollar index, use EURUSD as your macro benchmark. (Note that if you use EURUSD, the dashboard's correlation logic will naturally show heavily negative betas for dollar-long setups, which structurally serves the exact same analytical purpose).
Data Pre-loading: If the matrix initially displays 0.00 for a specific pair, it means your MT4/MT5 terminal lacks local history for that symbol on your current timeframe. Simply open a chart for that pair temporarily to force the broker to download the tick history, and the dashboard will instantly populate.
Broker Server Time vs. UTC: Unlike TradingView where you normalize everything to UTC, MT4 and MT5 execute off your broker's server time. You must adjust the InpSessionStart and InpSessionEnd inputs to match when London opens on your broker's clock (e.g., if your broker is GMT+2, London open might be 10:00).
Benchmark Integrity: Not all brokers provide "DXY". If your broker calls it "USDX", update the input. If they do not offer a dollar index, use EURUSD as your macro benchmark. (Note that if you use EURUSD, the dashboard's correlation logic will naturally show heavily negative betas for dollar-long setups, which structurally serves the exact same analytical purpose).
Data Pre-loading: If the matrix initially displays 0.00 for a specific pair, it means your MT4/MT5 terminal lacks local history for that symbol on your current timeframe. Simply open a chart for that pair temporarily to force the broker to download the tick history, and the dashboard will instantly populate.
Re: Best forex pairs to scalp during london session
To upgrade this from a standard retail indicator to a true institutional execution dashboard, we need to address three things that professional scalpers care about which the previous script lacked:
Transaction Cost (Live Spread): If you are scalping the London open, spread variance will eat your alpha. The dashboard must track real-time spread in pips and flag it if it widens beyond your acceptable threshold.
Volatility Exhaustion (ADR %): A pair might have high volume and perfect correlation, but if it has already moved 95% of its Average Daily Range (ADR), the institutional move is already over. You are buying the top. We need to track daily exhaustion.
GUI Architecture & Data Handling: Floating text over candlesticks is messy. We need a solid background plate (HUD) and forced Market Watch synchronization so you never get 0.00 errors on data loading.
Transaction Cost (Live Spread): If you are scalping the London open, spread variance will eat your alpha. The dashboard must track real-time spread in pips and flag it if it widens beyond your acceptable threshold.
Volatility Exhaustion (ADR %): A pair might have high volume and perfect correlation, but if it has already moved 95% of its Average Daily Range (ADR), the institutional move is already over. You are buying the top. We need to track daily exhaustion.
GUI Architecture & Data Handling: Floating text over candlesticks is messy. We need a solid background plate (HUD) and forced Market Watch synchronization so you never get 0.00 errors on data loading.
Re: Best forex pairs to scalp during london session
Here is the "Pro" build for both platforms. It features a dark-mode graphical panel, spread monitoring, ADR exhaustion, and bulletproof data loading.
1. MT5 Pro Build (MQL5)
1. MT5 Pro Build (MQL5)
Code: Select all
//+------------------------------------------------------------------+
//| LondonDeskMatrix_Pro.mq5 |
//| Institutional Pro Desk |
//+------------------------------------------------------------------+
#property copyright "Pro Desk Matrix"
#property indicator_chart_window
#property indicator_buffers 0
input string InpSessionStart = "08:00";
input string InpSessionEnd = "12:00";
input string InpBenchmark = "DXY";
input int InpLookback = 20;
input double InpMaxSpread = 1.5; // Max Acceptable Spread (Pips)
input string Sym1 = "EURUSD";
input string Sym2 = "GBPUSD";
input string Sym3 = "GBPJPY";
input string Sym4 = "USDJPY";
// GUI Coordinates
int startX = 20, startY = 20, rowH = 22, colW = 65;
int OnInit() {
// Force symbols into Market Watch for async data access
string syms[4] = {Sym1, Sym2, Sym3, Sym4};
for(int i=0; i<4; i++) {
SymbolSelect(syms[i], true);
}
SymbolSelect(InpBenchmark, true);
DrawPanel();
EventSetTimer(1);
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason) {
EventKillTimer();
ObjectsDeleteAll(0, "Mat_");
ChartRedraw();
}
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[]) {
return(rates_total);
}
//--- GUI Engine
void CreateRect(string name, int x, int y, int w, int h, color bgClr, color borderClr) {
if(ObjectFind(0, name) < 0) {
ObjectCreate(0, name, OBJ_RECTANGLE_LABEL, 0, 0, 0);
ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_RIGHT_UPPER);
ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_RIGHT_UPPER);
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, name, OBJPROP_HIDDEN, true);
}
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
ObjectSetInteger(0, name, OBJPROP_XSIZE, w);
ObjectSetInteger(0, name, OBJPROP_YSIZE, h);
ObjectSetInteger(0, name, OBJPROP_BGCOLOR, bgClr);
ObjectSetInteger(0, name, OBJPROP_COLOR, borderClr);
}
void DrawLabel(string name, int x, int y, string text, color clr, int fontSize=9, bool bold=false) {
if(ObjectFind(0, name) < 0) {
ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);
ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_RIGHT_UPPER);
ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_RIGHT_UPPER);
ObjectSetString(0, name, OBJPROP_FONT, bold ? "Consolas Bold" : "Consolas");
ObjectSetInteger(0, name, OBJPROP_BACK, false);
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, name, OBJPROP_HIDDEN, true);
}
ObjectSetString(0, name, OBJPROP_TEXT, text);
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
ObjectSetInteger(0, name, OBJPROP_FONTSIZE, fontSize);
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
}
void DrawPanel() {
CreateRect("Mat_BG", startX, startY, (colW*6)+10, (rowH*6)+10, clrBlack, clrDimGray);
CreateRect("Mat_HeadBG", startX, startY, (colW*6)+10, rowH+5, color'20,20,20', clrDimGray);
DrawLabel("Mat_H1", startX + colW*5.5, startY+5, "ASSET", clrGray, 9, true);
DrawLabel("Mat_H2", startX + colW*4.5, startY+5, "SPREAD", clrGray, 9, true);
DrawLabel("Mat_H3", startX + colW*3.5, startY+5, "VOL Z", clrGray, 9, true);
DrawLabel("Mat_H4", startX + colW*2.5, startY+5, "ADR %", clrGray, 9, true);
DrawLabel("Mat_H5", startX + colW*1.5, startY+5, "BETA", clrGray, 9, true);
DrawLabel("Mat_H6", startX + colW*0.5, startY+5, "STATUS", clrGray, 9, true);
}
//--- Math & Metric Engines
double GetPipMultiplier(string sym) {
long digits = SymbolInfoInteger(sym, SYMBOL_DIGITS);
return (digits == 3 || digits == 5) ? 10.0 : 1.0;
}
double GetLiveSpread(string sym) {
long spr = SymbolInfoInteger(sym, SYMBOL_SPREAD);
double point = SymbolInfoDouble(sym, SYMBOL_POINT);
return (spr * point) / (point * GetPipMultiplier(sym));
}
double GetADRExhaustion(string sym) {
double high[], low[];
if(CopyHigh(sym, PERIOD_D1, 0, 15, high) < 15) return 0.0;
if(CopyLow(sym, PERIOD_D1, 0, 15, low) < 15) return 0.0;
double adrSum = 0;
for(int i=1; i<=14; i++) adrSum += (high[i] - low[i]);
double currentRange = high[0] - low[0];
if(adrSum == 0) return 0;
return (currentRange / (adrSum / 14.0)) * 100.0;
}
// (VolZScore and Correlation functions remain identical to previous version, omitted for brevity but required in compile. Paste them here).
double GetVolZScore(string sym, int lookback) {
long vols[];
if(CopyTickVolume(sym, 0, 0, lookback+1, vols) < lookback+1) return 0.0;
double mean = 0.0;
for(int i = 0; i < lookback; i++) mean += (double)vols[i];
mean /= lookback;
double variance = 0.0;
for(int i = 0; i < lookback; i++) { double d = (double)vols[i] - mean; variance += (d * d); }
double stddev = MathSqrt(variance / lookback);
if(stddev == 0.0) return 0.0;
return ((double)vols[lookback] - mean) / stddev;
}
double GetCorrelation(string symA, string symB, int lookback) {
double arrA[], arrB[];
if(CopyClose(symA, 0, 1, lookback, arrA) < lookback) return 0.0;
if(CopyClose(symB, 0, 1, lookback, arrB) < lookback) return 0.0;
double meanA = 0, meanB = 0;
for(int i = 0; i < lookback; i++) { meanA += arrA[i]; meanB += arrB[i]; }
meanA /= lookback; meanB /= lookback;
double sumAB = 0, sumA2 = 0, sumB2 = 0;
for(int i = 0; i < lookback; i++) {
double dA = arrA[i] - meanA; double dB = arrB[i] - meanB;
sumAB += (dA * dB); sumA2 += (dA * dA); sumB2 += (dB * dB);
}
if(sumA2 * sumB2 == 0) return 0.0;
return sumAB / MathSqrt(sumA2 * sumB2);
}
bool IsInSession(string startHM, string endHM) {
MqlDateTime tm; TimeToStruct(TimeCurrent(), tm);
int currentMins = tm.hour * 60 + tm.min;
string sArr[], eArr[]; StringSplit(startHM, ':', sArr); StringSplit(endHM, ':', eArr);
int sMins = (int)StringToInteger(sArr[0]) * 60 + (int)StringToInteger(sArr[1]);
int eMins = (int)StringToInteger(eArr[0]) * 60 + (int)StringToInteger(eArr[1]);
return (sMins <= eMins) ? (currentMins >= sMins && currentMins <= eMins) : (currentMins >= sMins || currentMins <= eMins);
}
void OnTimer() {
bool isLive = IsInSession(InpSessionStart, InpSessionEnd);
string syms[4] = {Sym1, Sym2, Sym3, Sym4};
for(int i = 0; i < 4; i++) {
int y = startY + 30 + (i * rowH);
string id = "Mat_R" + IntegerToString(i);
double spread = GetLiveSpread(syms[i]);
double volZ = GetVolZScore(syms[i], InpLookback);
double adrPct = GetADRExhaustion(syms[i]);
double beta = GetCorrelation(syms[i], InpBenchmark, InpLookback);
color cSpr = (spread <= InpMaxSpread) ? clrWhite : clrRed;
color cVol = (volZ > 1.5) ? clrAqua : clrWhite;
color cAdr = (adrPct > 80) ? clrOrange : ((adrPct < 30) ? clrDimGray : clrWhite);
color cBeta = (MathAbs(beta) > 0.8) ? clrOrange : clrWhite;
color cStat = isLive ? clrLime : clrDimGray;
DrawLabel(id+"_Sym", startX + colW*5.5, y, syms[i], clrWhite, 9, true);
DrawLabel(id+"_Spr", startX + colW*4.5, y, DoubleToString(spread, 1), cSpr);
DrawLabel(id+"_Vol", startX + colW*3.5, y, DoubleToString(volZ, 2), cVol);
DrawLabel(id+"_Adr", startX + colW*2.5, y, DoubleToString(adrPct, 0)+"%", cAdr);
DrawLabel(id+"_Beta", startX + colW*1.5, y, DoubleToString(beta, 2), cBeta);
DrawLabel(id+"_Stat", startX + colW*0.5, y, isLive ? "LIVE" : "WAIT", cStat);
}
ChartRedraw();
}Re: Best forex pairs to scalp during london session
2. MT4 Pro Build (MQL4)
Code: Select all
//+------------------------------------------------------------------+
//| LondonDeskMatrix_Pro.mq4 |
//| Institutional Pro Desk |
//+------------------------------------------------------------------+
#property copyright "Pro Desk Matrix"
#property strict
#property indicator_chart_window
#property indicator_buffers 0
input string InpSessionStart = "08:00";
input string InpSessionEnd = "12:00";
input string InpBenchmark = "USDX";
input int InpLookback = 20;
input double InpMaxSpread = 1.5;
input string Sym1 = "EURUSD";
input string Sym2 = "GBPUSD";
input string Sym3 = "GBPJPY";
input string Sym4 = "USDJPY";
int startX = 20, startY = 20, rowH = 22, colW = 65;
int OnInit() {
DrawPanel();
EventSetTimer(1);
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason) {
EventKillTimer();
ObjectsDeleteAll(0, "Mat_");
ChartRedraw();
}
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[]) {
return(rates_total);
}
void CreateRect(string name, int x, int y, int w, int h, color bgClr, color borderClr) {
if(ObjectFind(name) < 0) {
ObjectCreate(name, OBJ_RECTANGLE_LABEL, 0, 0, 0);
ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_RIGHT_UPPER);
ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_RIGHT_UPPER);
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, name, OBJPROP_HIDDEN, true);
}
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
ObjectSetInteger(0, name, OBJPROP_XSIZE, w);
ObjectSetInteger(0, name, OBJPROP_YSIZE, h);
ObjectSetInteger(0, name, OBJPROP_BGCOLOR, bgClr);
ObjectSetInteger(0, name, OBJPROP_COLOR, borderClr);
}
void DrawLabel(string name, int x, int y, string text, color clr, int fontSize=9) {
if(ObjectFind(name) < 0) {
ObjectCreate(name, OBJ_LABEL, 0, 0, 0);
ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_RIGHT_UPPER);
ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_RIGHT_UPPER);
ObjectSetString(0, name, OBJPROP_FONT, "Consolas");
ObjectSetInteger(0, name, OBJPROP_BACK, false);
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, name, OBJPROP_HIDDEN, true);
}
ObjectSetString(0, name, OBJPROP_TEXT, text);
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
ObjectSetInteger(0, name, OBJPROP_FONTSIZE, fontSize);
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
}
void DrawPanel() {
CreateRect("Mat_BG", startX, startY, (colW*6)+10, (rowH*6)+10, clrBlack, clrDimGray);
CreateRect("Mat_HeadBG", startX, startY, (colW*6)+10, rowH+5, 3289650, clrDimGray); // Dark Gray
DrawLabel("Mat_H1", startX + colW*5.5, startY+5, "ASSET", clrGray);
DrawLabel("Mat_H2", startX + colW*4.5, startY+5, "SPREAD", clrGray);
DrawLabel("Mat_H3", startX + colW*3.5, startY+5, "VOL Z", clrGray);
DrawLabel("Mat_H4", startX + colW*2.5, startY+5, "ADR %", clrGray);
DrawLabel("Mat_H5", startX + colW*1.5, startY+5, "BETA", clrGray);
DrawLabel("Mat_H6", startX + colW*0.5, startY+5, "STATUS", clrGray);
}
double GetPipMultiplier(string sym) {
int digits = (int)MarketInfo(sym, MODE_DIGITS);
return (digits == 3 || digits == 5) ? 10.0 : 1.0;
}
double GetLiveSpread(string sym) {
double spr = MarketInfo(sym, MODE_SPREAD);
double point = MarketInfo(sym, MODE_POINT);
return (spr * point) / (point * GetPipMultiplier(sym));
}
double GetADRExhaustion(string sym) {
double adrSum = 0;
for(int i=1; i<=14; i++) {
double h = iHigh(sym, PERIOD_D1, i);
double l = iLow(sym, PERIOD_D1, i);
if(h == 0 || l == 0) return 0.0;
adrSum += (h - l);
}
double currentRange = iHigh(sym, PERIOD_D1, 0) - iLow(sym, PERIOD_D1, 0);
if(adrSum == 0) return 0;
return (currentRange / (adrSum / 14.0)) * 100.0;
}
// Include the MT4 VolZScore, Correlation, and IsInSession functions from the previous block here.
double GetVolZScore(string sym, int lookback) {
double vols[]; ArrayResize(vols, lookback);
double mean = 0.0;
for(int i = 0; i < lookback; i++) {
vols[i] = (double)iVolume(sym, 0, i+1);
if(vols[i] == 0) return 0.0;
mean += vols[i];
}
mean /= lookback;
double variance = 0.0;
for(int i = 0; i < lookback; i++) { double d = vols[i] - mean; variance += (d * d); }
double stddev = MathSqrt(variance / lookback);
if(stddev == 0.0) return 0.0;
return ((double)iVolume(sym, 0, 0) - mean) / stddev;
}
double GetCorrelation(string symA, string symB, int lookback) {
double arrA[], arrB[]; ArrayResize(arrA, lookback); ArrayResize(arrB, lookback);
double meanA = 0, meanB = 0;
for(int i = 0; i < lookback; i++) {
arrA[i] = iClose(symA, 0, i+1); arrB[i] = iClose(symB, 0, i+1);
if(arrA[i] == 0 || arrB[i] == 0) return 0.0;
meanA += arrA[i]; meanB += arrB[i];
}
meanA /= lookback; meanB /= lookback;
double sumAB = 0, sumA2 = 0, sumB2 = 0;
for(int i = 0; i < lookback; i++) {
double dA = arrA[i] - meanA; double dB = arrB[i] - meanB;
sumAB += (dA * dB); sumA2 += (dA * dA); sumB2 += (dB * dB);
}
if(sumA2 * sumB2 == 0) return 0.0;
return sumAB / MathSqrt(sumA2 * sumB2);
}
bool IsInSession(string startHM, string endHM) {
MqlDateTime tm; TimeToStruct(TimeCurrent(), tm);
int currentMins = tm.hour * 60 + tm.min;
string sArr[], eArr[]; StringSplit(startHM, ':', sArr); StringSplit(endHM, ':', eArr);
int sMins = (int)StringToInteger(sArr[0]) * 60 + (int)StringToInteger(sArr[1]);
int eMins = (int)StringToInteger(eArr[0]) * 60 + (int)StringToInteger(eArr[1]);
return (sMins <= eMins) ? (currentMins >= sMins && currentMins <= eMins) : (currentMins >= sMins || currentMins <= eMins);
}
void OnTimer() {
bool isLive = IsInSession(InpSessionStart, InpSessionEnd);
string syms[4] = {Sym1, Sym2, Sym3, Sym4};
for(int i = 0; i < 4; i++) {
int y = startY + 30 + (i * rowH);
string id = "Mat_R" + IntegerToString(i);
double spread = GetLiveSpread(syms[i]);
double volZ = GetVolZScore(syms[i], InpLookback);
double adrPct = GetADRExhaustion(syms[i]);
double beta = GetCorrelation(syms[i], InpBenchmark, InpLookback);
color cSpr = (spread <= InpMaxSpread) ? clrWhite : clrRed;
color cVol = (volZ > 1.5) ? clrAqua : clrWhite;
color cAdr = (adrPct > 80) ? clrOrange : ((adrPct < 30) ? clrDimGray : clrWhite);
color cBeta = (MathAbs(beta) > 0.8) ? clrOrange : clrWhite;
color cStat = isLive ? clrLime : clrDimGray;
DrawLabel(id+"_Sym", startX + colW*5.5, y, syms[i], clrWhite);
DrawLabel(id+"_Spr", startX + colW*4.5, y, DoubleToString(spread, 1), cSpr);
DrawLabel(id+"_Vol", startX + colW*3.5, y, DoubleToString(volZ, 2), cVol);
DrawLabel(id+"_Adr", startX + colW*2.5, y, DoubleToString(adrPct, 0)+"%", cAdr);
DrawLabel(id+"_Beta", startX + colW*1.5, y, DoubleToString(beta, 2), cBeta);
DrawLabel(id+"_Stat", startX + colW*0.5, y, isLive ? "LIVE" : "WAIT", cStat);
}
ChartRedraw();
}