Tokyo morning expansion days: when I refuse the London fade
Re: Tokyo morning expansion days: when I refuse the London fade
Here are the Professional versions for both MetaTrader 4 and MetaTrader 5.
These versions introduce the Equilibrium Midline (50%), Liquidity Projection Lines that extend into the London session, a Heads-Up Display (HUD) anchored to the chart corner, and Real-time Push Alerts that trigger the moment the expansion threshold is crossed.
These versions introduce the Equilibrium Midline (50%), Liquidity Projection Lines that extend into the London session, a Heads-Up Display (HUD) anchored to the chart corner, and Real-time Push Alerts that trigger the moment the expansion threshold is crossed.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: Tokyo morning expansion days: when I refuse the London fade
MetaTrader 4 (MQL4) [PRO]
Save as AsianMicrostructure_PRO_MT4.mq4 in your MQL4/Indicators folder.
Save as AsianMicrostructure_PRO_MT4.mq4 in your MQL4/Indicators folder.
Code: Select all
//+------------------------------------------------------------------+
//| AsianMicrostructure_PRO_MT4.mq4 |
//+------------------------------------------------------------------+
#property copyright "Indicator Port"
#property version "2.00"
#property strict
#property indicator_chart_window
// --- INPUTS ---
input string InpSessionStart = "00:00"; // Asian Session Start (HH:MM)
input string InpSessionEnd = "08:00"; // Asian Session End (HH:MM)
input int InpExtendHours = 6; // London Projection Length (Hours)
input int InpLookback = 15; // Average Range Lookback (Days)
input double InpMultiplier = 1.5; // Expansion Multiplier
input color InpColorNormal = clrCornflowerBlue; // Normal Range Color
input color InpColorExpand = clrCrimson; // Expansion Range Color
input color InpColorLine = clrGray; // Liquidity & Eq Lines
input bool InpShowHUD = true; // Show Data Dashboard
// --- GLOBALS ---
int startHour, startMin, endHour, endMin;
double pastRanges[];
int rangeCount = 0;
bool inSession = false;
bool alertTriggered = false;
double sessionHigh = 0;
double sessionLow = 0;
datetime sessionStartTime = 0;
int OnInit()
{
startHour = (int)StringToInteger(StringSubstr(InpSessionStart, 0, 2));
startMin = (int)StringToInteger(StringSubstr(InpSessionStart, 3, 2));
endHour = (int)StringToInteger(StringSubstr(InpSessionEnd, 0, 2));
endMin = (int)StringToInteger(StringSubstr(InpSessionEnd, 3, 2));
ArrayResize(pastRanges, InpLookback);
ArrayInitialize(pastRanges, 0.0);
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)
{
ObjectsDeleteAll(0, "AsiaPro_");
ObjectsDeleteAll(0, "AsiaHUD_");
}
bool IsTimeInSession(datetime t)
{
MqlDateTime dt;
TimeToStruct(t, dt);
int currentMins = dt.hour * 60 + dt.min;
int startMins = startHour * 60 + startMin;
int endMins = endHour * 60 + endMin;
if (startMins < endMins) return (currentMins >= startMins && currentMins < endMins);
return (currentMins >= startMins || currentMins < endMins);
}
void AddRange(double range)
{
for(int i = InpLookback - 1; i > 0; i--) pastRanges[i] = pastRanges[i-1];
pastRanges[0] = range;
if(rangeCount < InpLookback) rangeCount++;
}
double GetAvgRange()
{
if (rangeCount == 0) return 0;
double sum = 0;
for(int i = 0; i < rangeCount; i++) sum += pastRanges[i];
return sum / (double)rangeCount;
}
void CreateLabel(string name, int x, int y, string text, color clr, int size = 8, bool bold = false)
{
if(ObjectFind(0, name) < 0) {
ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);
ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_RIGHT_LOWER);
ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_RIGHT_LOWER);
}
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
ObjectSetString(0, name, OBJPROP_TEXT, text);
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
ObjectSetString(0, name, OBJPROP_FONT, bold ? "Arial Bold" : "Arial");
ObjectSetInteger(0, name, OBJPROP_FONTSIZE, size);
}
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[])
{
if(rates_total < 2) return(0);
int limit = rates_total - prev_calculated;
if(prev_calculated == 0) {
limit = rates_total - 1;
ArrayInitialize(pastRanges, 0.0);
rangeCount = 0;
inSession = false;
ObjectsDeleteAll(0, "AsiaPro_");
}
for(int i = limit; i >= 0; i--) {
datetime t = time[i];
bool isInside = IsTimeInSession(t);
if(isInside && !inSession) {
inSession = true;
alertTriggered = false;
sessionStartTime = t;
sessionHigh = high[i];
sessionLow = low[i];
}
else if (isInside && inSession) {
if(high[i] > sessionHigh) sessionHigh = high[i];
if(low[i] < sessionLow) sessionLow = low[i];
}
else if (!isInside && inSession) {
inSession = false;
double currentRange = sessionHigh - sessionLow;
AddRange(currentRange);
// Draw Liquidity Extensions upon session close
string prefixExt = "AsiaPro_Ext_" + IntegerToString((long)sessionStartTime);
datetime extensionEnd = t + (InpExtendHours * 3600);
ObjectCreate(0, prefixExt + "_H", OBJ_TREND, 0, t, sessionHigh, extensionEnd, sessionHigh);
ObjectSetInteger(0, prefixExt + "_H", OBJPROP_COLOR, InpColorLine);
ObjectSetInteger(0, prefixExt + "_H", OBJPROP_STYLE, STYLE_DOT);
ObjectSetInteger(0, prefixExt + "_H", OBJPROP_RAY_RIGHT, false);
ObjectCreate(0, prefixExt + "_L", OBJ_TREND, 0, t, sessionLow, extensionEnd, sessionLow);
ObjectSetInteger(0, prefixExt + "_L", OBJPROP_COLOR, InpColorLine);
ObjectSetInteger(0, prefixExt + "_L", OBJPROP_STYLE, STYLE_DOT);
ObjectSetInteger(0, prefixExt + "_L", OBJPROP_RAY_RIGHT, false);
}
if(inSession) {
double avgRange = GetAvgRange();
double currentRange = sessionHigh - sessionLow;
double sessionEq = sessionLow + (currentRange / 2.0);
bool isExpand = (avgRange > 0 && currentRange > (avgRange * InpMultiplier));
color boxColor = isExpand ? InpColorExpand : InpColorNormal;
string objName = "AsiaPro_Box_" + IntegerToString((long)sessionStartTime);
string eqName = "AsiaPro_Eq_" + IntegerToString((long)sessionStartTime);
// Box
if(ObjectFind(0, objName) < 0) {
ObjectCreate(0, objName, OBJ_RECTANGLE, 0, sessionStartTime, sessionHigh, t, sessionLow);
ObjectSetInteger(0, objName, OBJPROP_BACK, true);
}
ObjectSetDouble(0, objName, OBJPROP_PRICE1, sessionHigh);
ObjectSetDouble(0, objName, OBJPROP_PRICE2, sessionLow);
ObjectSetInteger(0, objName, OBJPROP_TIME2, t);
ObjectSetInteger(0, objName, OBJPROP_COLOR, boxColor);
// Equilibrium Line
if(ObjectFind(0, eqName) < 0) {
ObjectCreate(0, eqName, OBJ_TREND, 0, sessionStartTime, sessionEq, t, sessionEq);
ObjectSetInteger(0, eqName, OBJPROP_STYLE, STYLE_DASH);
ObjectSetInteger(0, eqName, OBJPROP_RAY_RIGHT, false);
}
ObjectSetDouble(0, eqName, OBJPROP_PRICE1, sessionEq);
ObjectSetDouble(0, eqName, OBJPROP_PRICE2, sessionEq);
ObjectSetInteger(0, eqName, OBJPROP_TIME2, t);
ObjectSetInteger(0, eqName, OBJPROP_COLOR, InpColorLine);
// Active Alert
if (isExpand && !alertTriggered && i == 0) {
Alert("Tokyo Expansion Triggered on ", Symbol(), ". London fades invalidated.");
alertTriggered = true;
}
}
// HUD Updates (Live Candle Only)
if(i == 0 && InpShowHUD) {
double avgRange = GetAvgRange();
double curRange = sessionHigh - sessionLow;
double pctOfAvg = avgRange > 0 ? (curRange / avgRange) * 100 : 0;
bool isExpand = (avgRange > 0 && curRange > (avgRange * InpMultiplier));
int curPts = (int)MathRound(curRange / Point);
int avgPts = (int)MathRound(avgRange / Point);
color statClr = isExpand ? InpColorExpand : InpColorNormal;
string statTxt = isExpand ? "EXPANSION (NO FADE)" : "NORMAL";
CreateLabel("AsiaHUD_1", 20, 80, "TOKYO MICROSTRUCTURE", clrWhite, 9, true);
CreateLabel("AsiaHUD_2", 20, 60, "Current Range: " + IntegerToString(curPts) + " points", clrLightGray);
CreateLabel("AsiaHUD_3", 20, 45, "15D Average: " + IntegerToString(avgPts) + " points (" + DoubleToString(pctOfAvg, 0) + "%)", clrLightGray);
CreateLabel("AsiaHUD_4", 20, 25, "London Setup: " + statTxt, statClr, 8, true);
}
}
return(rates_total);
}Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: Tokyo morning expansion days: when I refuse the London fade
MetaTrader 5 (MQL5) [PRO]
Save as AsianMicrostructure_PRO_MT5.mq5 in your MQL5/Indicators folder. This version uses ArraySetAsSeries and solid object fills.
Save as AsianMicrostructure_PRO_MT5.mq5 in your MQL5/Indicators folder. This version uses ArraySetAsSeries and solid object fills.
Code: Select all
//+------------------------------------------------------------------+
//| AsianMicrostructure_PRO_MT5.mq5 |
//+------------------------------------------------------------------+
#property copyright "Indicator Port"
#property version "2.00"
#property indicator_chart_window
#property indicator_buffers 0
#property indicator_plots 0
// --- INPUTS ---
input string InpSessionStart = "00:00"; // Asian Session Start (HH:MM)
input string InpSessionEnd = "08:00"; // Asian Session End (HH:MM)
input int InpExtendHours = 6; // London Projection Length (Hours)
input int InpLookback = 15; // Average Range Lookback (Days)
input double InpMultiplier = 1.5; // Expansion Multiplier
input color InpColorNormal = clrCornflowerBlue; // Normal Range Color
input color InpColorExpand = clrCrimson; // Expansion Range Color
input color InpColorLine = clrGray; // Liquidity & Eq Lines
input bool InpShowHUD = true; // Show Data Dashboard
// --- GLOBALS ---
int startHour, startMin, endHour, endMin;
double pastRanges[];
int rangeCount = 0;
bool inSession = false;
bool alertTriggered = false;
double sessionHigh = 0;
double sessionLow = 0;
datetime sessionStartTime = 0;
int OnInit()
{
startHour = (int)StringToInteger(StringSubstr(InpSessionStart, 0, 2));
startMin = (int)StringToInteger(StringSubstr(InpSessionStart, 3, 2));
endHour = (int)StringToInteger(StringSubstr(InpSessionEnd, 0, 2));
endMin = (int)StringToInteger(StringSubstr(InpSessionEnd, 3, 2));
ArrayResize(pastRanges, InpLookback);
ArrayInitialize(pastRanges, 0.0);
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)
{
ObjectsDeleteAll(0, "AsiaPro_");
ObjectsDeleteAll(0, "AsiaHUD_");
}
bool IsTimeInSession(datetime t)
{
MqlDateTime dt;
TimeToStruct(t, dt);
int currentMins = dt.hour * 60 + dt.min;
int startMins = startHour * 60 + startMin;
int endMins = endHour * 60 + endMin;
if (startMins < endMins) return (currentMins >= startMins && currentMins < endMins);
return (currentMins >= startMins || currentMins < endMins);
}
void AddRange(double range)
{
for(int i = InpLookback - 1; i > 0; i--) pastRanges[i] = pastRanges[i-1];
pastRanges[0] = range;
if(rangeCount < InpLookback) rangeCount++;
}
double GetAvgRange()
{
if (rangeCount == 0) return 0;
double sum = 0;
for(int i = 0; i < rangeCount; i++) sum += pastRanges[i];
return sum / (double)rangeCount;
}
void CreateLabel(string name, int x, int y, string text, color clr, int size = 8, bool bold = false)
{
if(ObjectFind(0, name) < 0) {
ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);
ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_RIGHT_LOWER);
ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_RIGHT_LOWER);
}
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
ObjectSetString(0, name, OBJPROP_TEXT, text);
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
ObjectSetString(0, name, OBJPROP_FONT, bold ? "Arial Bold" : "Arial");
ObjectSetInteger(0, name, OBJPROP_FONTSIZE, size);
}
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[])
{
if(rates_total < 2) return(0);
ArraySetAsSeries(time, true);
ArraySetAsSeries(high, true);
ArraySetAsSeries(low, true);
int limit = rates_total - prev_calculated;
if(prev_calculated == 0) {
limit = rates_total - 1;
ArrayInitialize(pastRanges, 0.0);
rangeCount = 0;
inSession = false;
ObjectsDeleteAll(0, "AsiaPro_");
}
for(int i = limit; i >= 0; i--) {
datetime t = time[i];
bool isInside = IsTimeInSession(t);
if(isInside && !inSession) {
inSession = true;
alertTriggered = false;
sessionStartTime = t;
sessionHigh = high[i];
sessionLow = low[i];
}
else if (isInside && inSession) {
if(high[i] > sessionHigh) sessionHigh = high[i];
if(low[i] < sessionLow) sessionLow = low[i];
}
else if (!isInside && inSession) {
inSession = false;
double currentRange = sessionHigh - sessionLow;
AddRange(currentRange);
// Draw Liquidity Extensions
string prefixExt = "AsiaPro_Ext_" + IntegerToString((long)sessionStartTime);
datetime extensionEnd = t + (InpExtendHours * 3600);
ObjectCreate(0, prefixExt + "_H", OBJ_TREND, 0, t, sessionHigh, extensionEnd, sessionHigh);
ObjectSetInteger(0, prefixExt + "_H", OBJPROP_COLOR, InpColorLine);
ObjectSetInteger(0, prefixExt + "_H", OBJPROP_STYLE, STYLE_DOT);
ObjectSetInteger(0, prefixExt + "_H", OBJPROP_RAY_RIGHT, false);
ObjectCreate(0, prefixExt + "_L", OBJ_TREND, 0, t, sessionLow, extensionEnd, sessionLow);
ObjectSetInteger(0, prefixExt + "_L", OBJPROP_COLOR, InpColorLine);
ObjectSetInteger(0, prefixExt + "_L", OBJPROP_STYLE, STYLE_DOT);
ObjectSetInteger(0, prefixExt + "_L", OBJPROP_RAY_RIGHT, false);
}
if(inSession) {
double avgRange = GetAvgRange();
double currentRange = sessionHigh - sessionLow;
double sessionEq = sessionLow + (currentRange / 2.0);
bool isExpand = (avgRange > 0 && currentRange > (avgRange * InpMultiplier));
color boxColor = isExpand ? InpColorExpand : InpColorNormal;
string objName = "AsiaPro_Box_" + IntegerToString((long)sessionStartTime);
string eqName = "AsiaPro_Eq_" + IntegerToString((long)sessionStartTime);
// Box
if(ObjectFind(0, objName) < 0) {
ObjectCreate(0, objName, OBJ_RECTANGLE, 0, sessionStartTime, sessionHigh, t, sessionLow);
ObjectSetInteger(0, objName, OBJPROP_FILL, true); // MT5 solid fill
ObjectSetInteger(0, objName, OBJPROP_BACK, true);
}
ObjectSetDouble(0, objName, OBJPROP_PRICE1, sessionHigh);
ObjectSetDouble(0, objName, OBJPROP_PRICE2, sessionLow);
ObjectSetInteger(0, objName, OBJPROP_TIME2, t);
ObjectSetInteger(0, objName, OBJPROP_COLOR, boxColor);
// Equilibrium Line
if(ObjectFind(0, eqName) < 0) {
ObjectCreate(0, eqName, OBJ_TREND, 0, sessionStartTime, sessionEq, t, sessionEq);
ObjectSetInteger(0, eqName, OBJPROP_STYLE, STYLE_DASH);
ObjectSetInteger(0, eqName, OBJPROP_RAY_RIGHT, false);
}
ObjectSetDouble(0, eqName, OBJPROP_PRICE1, sessionEq);
ObjectSetDouble(0, eqName, OBJPROP_PRICE2, sessionEq);
ObjectSetInteger(0, eqName, OBJPROP_TIME2, t);
ObjectSetInteger(0, eqName, OBJPROP_COLOR, InpColorLine);
// Active Alert
if (isExpand && !alertTriggered && i == 0) {
Alert("Tokyo Expansion Triggered on ", Symbol(), ". London fades invalidated.");
alertTriggered = true;
}
}
// HUD Updates
if(i == 0 && InpShowHUD) {
double avgRange = GetAvgRange();
double curRange = sessionHigh - sessionLow;
double pctOfAvg = avgRange > 0 ? (curRange / avgRange) * 100 : 0;
bool isExpand = (avgRange > 0 && curRange > (avgRange * InpMultiplier));
int curPts = (int)MathRound(curRange / Point());
int avgPts = (int)MathRound(avgRange / Point());
color statClr = isExpand ? InpColorExpand : InpColorNormal;
string statTxt = isExpand ? "EXPANSION (NO FADE)" : "NORMAL";
CreateLabel("AsiaHUD_1", 20, 80, "TOKYO MICROSTRUCTURE", clrWhite, 9, true);
CreateLabel("AsiaHUD_2", 20, 60, "Current Range: " + IntegerToString(curPts) + " points", clrLightGray);
CreateLabel("AsiaHUD_3", 20, 45, "15D Average: " + IntegerToString(avgPts) + " points (" + DoubleToString(pctOfAvg, 0) + "%)", clrLightGray);
CreateLabel("AsiaHUD_4", 20, 25, "London Setup: " + statTxt, statClr, 8, true);
}
}
return(rates_total);
}Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: Tokyo morning expansion days: when I refuse the London fade
Save this as AsianMicrostructure_PRO.cs in your cTrader Automate indicators folder.
This Pro version leverages cTrader's native UI capabilities to create a sleek, modern HUD dashboard that anchors to the chart window and updates without lagging. It uses native DateTime charting methods to effortlessly project liquidity lines into the future London session, bypassing the bar-index limitations found in other platforms.
Ctrader Pro version:
This Pro version leverages cTrader's native UI capabilities to create a sleek, modern HUD dashboard that anchors to the chart window and updates without lagging. It uses native DateTime charting methods to effortlessly project liquidity lines into the future London session, bypassing the bar-index limitations found in other platforms.
Ctrader Pro version:
Code: Select all
using System;
using System.Collections.Generic;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Internals;
namespace cAlgo
{
[Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class AsianMicrostructurePRO : Indicator
{
// =========================================================================
// INPUTS & CONFIGURATION
// =========================================================================
[Parameter("Session Start (HH:mm)", DefaultValue = "00:00", Group = "Session Parameters")]
public string SessionStart { get; set; }
[Parameter("Session End (HH:mm)", DefaultValue = "08:00", Group = "Session Parameters")]
public string SessionEnd { get; set; }
[Parameter("London Projection Length (Hours)", DefaultValue = 6, Group = "Session Parameters")]
public int ExtendHours { get; set; }
[Parameter("Average Lookback (Days)", DefaultValue = 15, Group = "Expansion Logic")]
public int Lookback { get; set; }
[Parameter("Expansion Multiplier", DefaultValue = 1.5, Group = "Expansion Logic")]
public double Multiplier { get; set; }
[Parameter("Normal Color", DefaultValue = "#2962FF", Group = "Aesthetics & HUD")]
public string NormalColorHex { get; set; }
[Parameter("Expansion Color", DefaultValue = "#FF5252", Group = "Aesthetics & HUD")]
public string ExpandColorHex { get; set; }
[Parameter("Line Color", DefaultValue = "#787B86", Group = "Aesthetics & HUD")]
public string LineColorHex { get; set; }
[Parameter("Show Data Dashboard", DefaultValue = true, Group = "Aesthetics & HUD")]
public bool ShowHUD { get; set; }
// =========================================================================
// STATE VARIABLES
// =========================================================================
private TimeSpan _startTime;
private TimeSpan _endTime;
private List<double> _pastRanges;
private bool _inSession;
private bool _alertTriggered;
private double _sessionHigh;
private double _sessionLow;
private DateTime _sessionStartTime;
private Color _normalColor;
private Color _expandColor;
private Color _lineColor;
// HUD UI Elements
private Border _hudContainer;
private TextBlock _txtCurrentRange;
private TextBlock _txtAvgRange;
private TextBlock _txtStatus;
protected override void Initialize()
{
TimeSpan.TryParse(SessionStart, out _startTime);
TimeSpan.TryParse(SessionEnd, out _endTime);
_pastRanges = new List<double>();
_normalColor = Color.FromHex(NormalColorHex);
_expandColor = Color.FromHex(ExpandColorHex);
_lineColor = Color.FromHex(LineColorHex);
if (ShowHUD)
{
InitializeHUD();
}
}
public override void Calculate(int index)
{
var barTime = Bars.OpenTimes[index];
var timeOfDay = barTime.TimeOfDay;
bool isInside = IsTimeInSession(timeOfDay);
// Session Transitions
if (isInside && !_inSession)
{
_inSession = true;
_alertTriggered = false;
_sessionStartTime = barTime;
_sessionHigh = Bars.HighPrices[index];
_sessionLow = Bars.LowPrices[index];
}
else if (isInside && _inSession)
{
_sessionHigh = Math.Max(_sessionHigh, Bars.HighPrices[index]);
_sessionLow = Math.Min(_sessionLow, Bars.LowPrices[index]);
}
else if (!isInside && _inSession)
{
_inSession = false;
double finalRange = _sessionHigh - _sessionLow;
// Store range for AAR math
_pastRanges.Add(finalRange);
if (_pastRanges.Count > Lookback)
{
_pastRanges.RemoveAt(0);
}
// Draw Liquidity Projections (Extends past the current bar)
DateTime projectionEnd = barTime.AddHours(ExtendHours);
string projHighName = "AsiaProjH_" + _sessionStartTime.Ticks;
string projLowName = "AsiaProjL_" + _sessionStartTime.Ticks;
var extH = Chart.DrawTrendLine(projHighName, barTime, _sessionHigh, projectionEnd, _sessionHigh, _lineColor);
extH.LineStyle = LineStyle.Dots;
var extL = Chart.DrawTrendLine(projLowName, barTime, _sessionLow, projectionEnd, _sessionLow, _lineColor);
extL.LineStyle = LineStyle.Dots;
}
// Active Session Visuals & Logic
if (_inSession)
{
double currentRange = _sessionHigh - _sessionLow;
double avgRange = _pastRanges.Count > 0 ? _pastRanges.Average() : 0;
double sessionEq = _sessionLow + (currentRange / 2);
bool isExpansion = (avgRange > 0 && currentRange > (avgRange * Multiplier));
Color activeColor = isExpansion ? _expandColor : _normalColor;
Color boxFill = Color.FromArgb(40, activeColor); // 40 = opacity
// Draw Box
string boxName = "AsiaBox_" + _sessionStartTime.Ticks;
var box = Chart.DrawRectangle(boxName, _sessionStartTime, _sessionHigh, barTime, _sessionLow, activeColor);
box.IsFilled = true;
box.Color = boxFill;
// Draw Equilibrium Midline
string eqName = "AsiaEq_" + _sessionStartTime.Ticks;
var eqLine = Chart.DrawTrendLine(eqName, _sessionStartTime, sessionEq, barTime, sessionEq, _lineColor);
eqLine.LineStyle = LineStyle.Lines;
// Alerts & Notifications
if (IsLastBar && isExpansion && !_alertTriggered)
{
Print($"[{Symbol.Name}] Tokyo Expansion Triggered. London fades invalidated.");
Chart.DrawStaticText("AlertTxt", "⚠️ EXPANSION TRIGGERED", VerticalAlignment.Top, HorizontalAlignment.Center, _expandColor);
_alertTriggered = true;
}
// Update HUD metrics live
if (IsLastBar && ShowHUD)
{
UpdateHUD(currentRange, avgRange, isExpansion);
}
}
else if (IsLastBar && ShowHUD)
{
// Clear active text if session is closed and we're looking at current bar
Chart.RemoveObject("AlertTxt");
}
}
private bool IsTimeInSession(TimeSpan time)
{
if (_startTime < _endTime)
return time >= _startTime && time < _endTime;
return time >= _startTime || time < _endTime;
}
// =========================================================================
// NATIVE UI DASHBOARD (HUD)
// =========================================================================
private void InitializeHUD()
{
var panel = new StackPanel
{
Orientation = Orientation.Vertical,
Margin = new Thickness(10)
};
var title = new TextBlock
{
Text = "TOKYO MICROSTRUCTURE",
ForegroundColor = Color.White,
FontWeight = FontWeight.ExtraBold,
Margin = new Thickness(0, 0, 0, 10)
};
panel.AddChild(title);
_txtCurrentRange = new TextBlock { ForegroundColor = Color.LightGray, Margin = new Thickness(0, 0, 0, 5) };
_txtAvgRange = new TextBlock { ForegroundColor = Color.LightGray, Margin = new Thickness(0, 0, 0, 10) };
_txtStatus = new TextBlock { FontWeight = FontWeight.Bold };
panel.AddChild(_txtCurrentRange);
panel.AddChild(_txtAvgRange);
panel.AddChild(_txtStatus);
_hudContainer = new Border
{
BackgroundColor = Color.FromArgb(220, 19, 23, 34),
BorderColor = Color.FromArgb(255, 54, 58, 69),
BorderThickness = new Thickness(1),
CornerRadius = 3,
Margin = new Thickness(20),
HorizontalAlignment = HorizontalAlignment.Right,
VerticalAlignment = VerticalAlignment.Bottom,
Child = panel
};
Chart.AddControl(_hudContainer);
}
private void UpdateHUD(double currentRange, double avgRange, bool isExpansion)
{
double pipsCurrent = Math.Round(currentRange / Symbol.PipSize, 1);
double pipsAvg = Math.Round(avgRange / Symbol.PipSize, 1);
double pctOfAvg = avgRange > 0 ? (currentRange / avgRange) * 100 : 0;
_txtCurrentRange.Text = $"Current Range: {pipsCurrent} pips";
_txtAvgRange.Text = $"15D Average: {pipsAvg} pips ({Math.Round(pctOfAvg)}%)";
if (isExpansion)
{
_txtStatus.Text = "London Setup: EXPANSION (NO FADE)";
_txtStatus.ForegroundColor = _expandColor;
}
else
{
_txtStatus.Text = "London Setup: NORMAL";
_txtStatus.ForegroundColor = _normalColor;
}
}
}
}Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: Tokyo morning expansion days: when I refuse the London fade
To make this the ultimate, elite-tier microstructure tool for your M15 charts, we need to move beyond just measuring the range and start automatically mapping how London interacts with that range.
Since your strategy revolves around liquidity and mean-reversion versus expansion, this [ELITE] upgrade introduces three advanced smart-money concepts:
Automated Liquidity Purge Detection (BSL/SSL): It actively monitors the London projection window. If price sweeps the Asian High (Buy-Side Liquidity) or Asian Low (Sell-Side Liquidity), it automatically tags the chart with a "BSL/SSL Purge" marker and fires an alert.
Deep Premium & Discount Quartiles (75% & 25%): Equilibrium (50%) is great, but the highest probability mean-reversion entries occur in the outer quartiles. The script now draws the 75% (Premium) and 25% (Discount) internal thresholds.
Forward-Projected PD Arrays: Instead of just drawing dotted lines, it projects a lightly shaded Premium Zone (Red) and Discount Zone (Blue) into the London session, giving you a crystal-clear visual of where you are in the intraday matrix.
Since your strategy revolves around liquidity and mean-reversion versus expansion, this [ELITE] upgrade introduces three advanced smart-money concepts:
Automated Liquidity Purge Detection (BSL/SSL): It actively monitors the London projection window. If price sweeps the Asian High (Buy-Side Liquidity) or Asian Low (Sell-Side Liquidity), it automatically tags the chart with a "BSL/SSL Purge" marker and fires an alert.
Deep Premium & Discount Quartiles (75% & 25%): Equilibrium (50%) is great, but the highest probability mean-reversion entries occur in the outer quartiles. The script now draws the 75% (Premium) and 25% (Discount) internal thresholds.
Forward-Projected PD Arrays: Instead of just drawing dotted lines, it projects a lightly shaded Premium Zone (Red) and Discount Zone (Blue) into the London session, giving you a crystal-clear visual of where you are in the intraday matrix.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: Tokyo morning expansion days: when I refuse the London fade
Pine Script v5: Asian Microstructure [ELITE]
Code: Select all
//@version=5
indicator("Asian Range Microstructure [ELITE]", overlay=true, max_boxes_count=100, max_lines_count=200, max_labels_count=100)
// =========================================================================
// INPUTS & CONFIGURATION
// =========================================================================
var string G_TIME = "Session Parameters"
sessionTime = input.session("0000-0800", title="Asian Session (Exchange TZ)", group=G_TIME)
extendHours = input.int(6, title="London Projection Length (Hours)", minval=1, maxval=12, group=G_TIME)
var string G_CALC = "Expansion Logic"
lookback = input.int(15, title="Average Range Lookback (Days)", minval=5, maxval=50, group=G_CALC)
multiplier = input.float(1.5, title="Expansion Multiplier", step=0.1, group=G_CALC)
var string G_STYLE = "Aesthetics & HUD"
colorNormal = input.color(color.new(#2962FF, 85), title="Normal Range", group=G_STYLE)
colorExpand = input.color(color.new(#FF5252, 85), title="Expansion Range", group=G_STYLE)
colorPrem = input.color(color.new(#FF5252, 92), title="Premium Projection (Top 50%)", group=G_STYLE)
colorDisc = input.color(color.new(#2962FF, 92), title="Discount Projection (Bot 50%)", group=G_STYLE)
colorLine = input.color(color.new(#787B86, 30), title="Internal Structure Lines", group=G_STYLE)
showHUD = input.bool(true, title="Show Data Dashboard", group=G_STYLE)
// =========================================================================
// STATE VARIABLES
// =========================================================================
inSession = not na(time(timeframe.period, sessionTime))
newSession = inSession and not inSession[1]
endSession = not inSession and inSession[1]
var float sessionHigh = na
var float sessionLow = na
var int sessionStartBar = na
if newSession
sessionHigh := high
sessionLow := low
sessionStartBar := bar_index
else if inSession
sessionHigh := math.max(sessionHigh, high)
sessionLow := math.min(sessionLow, low)
currentRange = sessionHigh - sessionLow
sessionEq = sessionLow + (currentRange / 2)
session75 = sessionLow + (currentRange * 0.75) // Deep Premium
session25 = sessionLow + (currentRange * 0.25) // Deep Discount
// =========================================================================
// HISTORICAL AVERAGE & STDEV CALCULATION
// =========================================================================
var float[] pastRanges = array.new_float(0)
if endSession
array.unshift(pastRanges, currentRange)
if array.size(pastRanges) > lookback
array.pop(pastRanges)
avgRange = array.size(pastRanges) > 0 ? array.avg(pastRanges) : na
stdevRange = array.size(pastRanges) > 0 ? array.stdev(pastRanges) : na
isExpansion = inSession and not na(avgRange) and (currentRange > (avgRange * multiplier))
// =========================================================================
// LIQUIDITY PURGE DETECTION (LONDON SESSION)
// =========================================================================
barsToExtend = math.round((60 / timeframe.multiplier) * extendHours)
inLondon = not inSession and ta.barssince(endSession) <= barsToExtend
var bool bslSwept = false
var bool sslSwept = false
if newSession
bslSwept := false
sslSwept := false
// Trigger a purge only if it's the first time London crosses the Asia High/Low
bslTrigger = inLondon and high >= sessionHigh and not bslSwept
sslTrigger = inLondon and low <= sessionLow and not sslSwept
if bslTrigger
bslSwept := true
label.new(bar_index, high, "BSL", style=label.style_label_down, color=color.new(#FF5252, 20), textcolor=color.white, size=size.tiny)
alert("BSL Purged on " + syminfo.ticker + " in London Session.", alert.freq_once_per_bar)
if sslTrigger
sslSwept := true
label.new(bar_index, low, "SSL", style=label.style_label_up, color=color.new(#2962FF, 20), textcolor=color.white, size=size.tiny)
alert("SSL Purged on " + syminfo.ticker + " in London Session.", alert.freq_once_per_bar)
// =========================================================================
// DRAWING CORE VISUALS
// =========================================================================
var box sessionBox = na
var line eqLine = na
var line q75Line = na
var line q25Line = na
if newSession
sessionBox := box.new(left=bar_index, top=sessionHigh, right=bar_index, bottom=sessionLow, border_color=color.new(colorNormal, 30), bgcolor=colorNormal)
eqLine := line.new(x1=bar_index, y1=sessionEq, x2=bar_index, y2=sessionEq, color=colorLine, style=line.style_dashed)
q75Line := line.new(x1=bar_index, y1=session75, x2=bar_index, y2=session75, color=colorLine, style=line.style_dotted)
q25Line := line.new(x1=bar_index, y1=session25, x2=bar_index, y2=session25, color=colorLine, style=line.style_dotted)
else if inSession
currentColor = isExpansion ? colorExpand : colorNormal
// Update Master Box
box.set_top(sessionBox, sessionHigh)
box.set_bottom(sessionBox, sessionLow)
box.set_right(sessionBox, bar_index)
box.set_bgcolor(sessionBox, currentColor)
box.set_border_color(sessionBox, color.new(currentColor, 30))
// Update Internal Structure Lines
line.set_y1(eqLine, sessionEq), line.set_y2(eqLine, sessionEq), line.set_x2(eqLine, bar_index)
line.set_y1(q75Line, session75), line.set_y2(q75Line, session75), line.set_x2(q75Line, bar_index)
line.set_y1(q25Line, session25), line.set_y2(q25Line, session25), line.set_x2(q25Line, bar_index)
if endSession
endBar = bar_index + barsToExtend
// Project Premium and Discount Zones into London
box.new(left=bar_index, top=sessionHigh, right=endBar, bottom=sessionEq, border_color=na, bgcolor=colorPrem)
box.new(left=bar_index, top=sessionEq, right=endBar, bottom=sessionLow, border_color=na, bgcolor=colorDisc)
// Solid boundary lines for London
line.new(x1=bar_index, y1=sessionHigh, x2=endBar, y2=sessionHigh, color=color.new(#FF5252, 20), style=line.style_solid)
line.new(x1=bar_index, y1=sessionLow, x2=endBar, y2=sessionLow, color=color.new(#2962FF, 20), style=line.style_solid)
// Alert for active expansion during Asia
expansionTrigger = isExpansion and not isExpansion[1]
if expansionTrigger
alert("Asian Expansion Triggered on " + syminfo.ticker + ". London fades invalidated.", alert.freq_once_per_bar)
// =========================================================================
// HUD (HEADS UP DISPLAY)
// =========================================================================
var table hud = table.new(position.bottom_right, columns=2, rows=5, bgcolor=color.new(#131722, 10), border_width=1, border_color=color.new(#363A45, 50))
if showHUD and barstate.islast
rangeTicks = currentRange / syminfo.mintick
avgTicks = na(avgRange) ? 0 : (avgRange / syminfo.mintick)
pctOfAvg = na(avgRange) ? 0 : (currentRange / avgRange) * 100
statusColor = isExpansion ? color.red : color.blue
statusText = isExpansion ? "EXPANSION (NO FADE)" : "NORMAL / ACCUMULATION"
// Build Sweep Status Text
sweepStatus = "Intact"
sweepColor = color.gray
if bslSwept and sslSwept
sweepStatus := "Both Sides Purged"
sweepColor := color.purple
else if bslSwept
sweepStatus := "BSL Purged (High Taken)"
sweepColor := color.red
else if sslSwept
sweepStatus := "SSL Purged (Low Taken)"
sweepColor := color.blue
table.cell(hud, 0, 0, "MICROSTRUCTURE [ELITE]", text_color=color.white, text_size=size.small, bgcolor=color.new(#2A2E39, 0), span=2)
table.cell(hud, 0, 1, "Current Range:", text_color=color.gray, text_size=size.small, text_halign=text.align_left)
table.cell(hud, 1, 1, str.tostring(rangeTicks, "#.0") + " ticks", text_color=color.white, text_size=size.small, text_halign=text.align_right)
table.cell(hud, 0, 2, "15D Average (AAR):", text_color=color.gray, text_size=size.small, text_halign=text.align_left)
table.cell(hud, 1, 2, str.tostring(avgTicks, "#.0") + " ticks (" + str.tostring(pctOfAvg, "#") + "%)", text_color=color.white, text_size=size.small, text_halign=text.align_right)
table.cell(hud, 0, 3, "Setup Validity:", text_color=color.gray, text_size=size.small, text_halign=text.align_left)
table.cell(hud, 1, 3, statusText, text_color=statusColor, text_size=size.small, text_halign=text.align_right)
table.cell(hud, 0, 4, "London Liquidity:", text_color=color.gray, text_size=size.small, text_halign=text.align_left)
table.cell(hud, 1, 4, sweepStatus, text_color=sweepColor, text_size=size.small, text_halign=text.align_right)Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: Tokyo morning expansion days: when I refuse the London fade
How this alters your London Playbook:
The Expansion Override: If the box turns RED during Tokyo, the rest of the indicator is purely informational. The mean-reversion playbook is closed.
The High-Probability Fade: If the box stays BLUE (Normal), and London pushes up into the Red Shaded Premium Zone without immediately breaking the High, you look for your M1/M5 short setups at the 75% Quartile.
The Judas Swing / Turtle Soup: If the box is BLUE, and London aggressively spikes through the solid Red boundary line (Asian High) and immediately rejects back inside the zone, the script instantly prints a BSL tag. That is your mechanical confirmation that liquidity was purged, not expanded upon. You enter the fade targeting the Equilibrium (50%) or the 25% Quartile.
The Expansion Override: If the box turns RED during Tokyo, the rest of the indicator is purely informational. The mean-reversion playbook is closed.
The High-Probability Fade: If the box stays BLUE (Normal), and London pushes up into the Red Shaded Premium Zone without immediately breaking the High, you look for your M1/M5 short setups at the 75% Quartile.
The Judas Swing / Turtle Soup: If the box is BLUE, and London aggressively spikes through the solid Red boundary line (Asian High) and immediately rejects back inside the zone, the script instantly prints a BSL tag. That is your mechanical confirmation that liquidity was purged, not expanded upon. You enter the fade targeting the Equilibrium (50%) or the 25% Quartile.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: Tokyo morning expansion days: when I refuse the London fade
Here are the Elite-tier versions for MetaTrader 4 and MetaTrader 5.
These scripts upgrade the previous versions with full Smart Money Concepts (SMC) integration: they project Premium/Discount arrays into the London session, track the 25%/75% internal quartiles, mechanically detect BSL (Buy-Side) and SSL (Sell-Side) liquidity purges, and dynamically update the HUD.
These scripts upgrade the previous versions with full Smart Money Concepts (SMC) integration: they project Premium/Discount arrays into the London session, track the 25%/75% internal quartiles, mechanically detect BSL (Buy-Side) and SSL (Sell-Side) liquidity purges, and dynamically update the HUD.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: Tokyo morning expansion days: when I refuse the London fade
MetaTrader 4 (MQL4) [ELITE]
Save as AsianMicrostructure_ELITE_MT4.mq4 in your MQL4/Indicators folder.
Save as AsianMicrostructure_ELITE_MT4.mq4 in your MQL4/Indicators folder.
Code: Select all
//+------------------------------------------------------------------+
//| AsianMicrostructure_ELITE_MT4.mq4 |
//+------------------------------------------------------------------+
#property copyright "Indicator Port"
#property version "3.00"
#property strict
#property indicator_chart_window
// --- INPUTS ---
input string InpSessionStart = "00:00"; // Asian Session Start (HH:MM)
input string InpSessionEnd = "08:00"; // Asian Session End (HH:MM)
input int InpExtendHours = 6; // London Projection Length (Hours)
input int InpLookback = 15; // Average Range Lookback (Days)
input double InpMultiplier = 1.5; // Expansion Multiplier
input color InpColorNormal = clrCornflowerBlue; // Normal Range Box
input color InpColorExpand = clrCrimson; // Expansion Range Box
input color InpColorPrem = clrMistyRose; // Premium Projection (Top 50%)
input color InpColorDisc = clrLightCyan; // Discount Projection (Bot 50%)
input color InpColorLine = clrGray; // Internal Structure Lines
input bool InpShowHUD = true; // Show Data Dashboard
// --- GLOBALS ---
int startHour, startMin, endHour, endMin;
double pastRanges[];
int rangeCount = 0;
bool inSession = false;
bool alertTriggered = false;
bool bslSwept = false;
bool sslSwept = false;
double sessionHigh = 0;
double sessionLow = 0;
datetime sessionStartTime = 0;
datetime sessionEndTime = 0;
int OnInit()
{
startHour = (int)StringToInteger(StringSubstr(InpSessionStart, 0, 2));
startMin = (int)StringToInteger(StringSubstr(InpSessionStart, 3, 2));
endHour = (int)StringToInteger(StringSubstr(InpSessionEnd, 0, 2));
endMin = (int)StringToInteger(StringSubstr(InpSessionEnd, 3, 2));
ArrayResize(pastRanges, InpLookback);
ArrayInitialize(pastRanges, 0.0);
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)
{
ObjectsDeleteAll(0, "AsiaElite_");
ObjectsDeleteAll(0, "AsiaHUD_");
}
bool IsTimeInSession(datetime t)
{
MqlDateTime dt;
TimeToStruct(t, dt);
int currentMins = dt.hour * 60 + dt.min;
int startMins = startHour * 60 + startMin;
int endMins = endHour * 60 + endMin;
if (startMins < endMins) return (currentMins >= startMins && currentMins < endMins);
return (currentMins >= startMins || currentMins < endMins);
}
void AddRange(double range)
{
for(int i = InpLookback - 1; i > 0; i--) pastRanges[i] = pastRanges[i-1];
pastRanges[0] = range;
if(rangeCount < InpLookback) rangeCount++;
}
double GetAvgRange()
{
if (rangeCount == 0) return 0;
double sum = 0;
for(int i = 0; i < rangeCount; i++) sum += pastRanges[i];
return sum / (double)rangeCount;
}
void CreateLabel(string name, int x, int y, string text, color clr, int size = 8, bool bold = false)
{
if(ObjectFind(0, name) < 0) {
ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);
ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_RIGHT_LOWER);
ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_RIGHT_LOWER);
}
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
ObjectSetString(0, name, OBJPROP_TEXT, text);
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
ObjectSetString(0, name, OBJPROP_FONT, bold ? "Arial Bold" : "Arial");
ObjectSetInteger(0, name, OBJPROP_FONTSIZE, size);
}
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[])
{
if(rates_total < 2) return(0);
int limit = rates_total - prev_calculated;
if(prev_calculated == 0) {
limit = rates_total - 1;
ArrayInitialize(pastRanges, 0.0);
rangeCount = 0;
inSession = false;
ObjectsDeleteAll(0, "AsiaElite_");
}
for(int i = limit; i >= 0; i--) {
datetime t = time[i];
bool isInside = IsTimeInSession(t);
// Session Start
if(isInside && !inSession) {
inSession = true;
alertTriggered = false;
bslSwept = false;
sslSwept = false;
sessionStartTime = t;
sessionHigh = high[i];
sessionLow = low[i];
}
// Inside Session Updates
else if (isInside && inSession) {
if(high[i] > sessionHigh) sessionHigh = high[i];
if(low[i] < sessionLow) sessionLow = low[i];
}
// Session End
else if (!isInside && inSession) {
inSession = false;
sessionEndTime = t;
double currentRange = sessionHigh - sessionLow;
AddRange(currentRange);
// Draw London Projections
string prefix = "AsiaElite_";
string tStr = IntegerToString((long)sessionStartTime);
datetime extensionEnd = sessionEndTime + (InpExtendHours * 3600);
double sessionEq = sessionLow + (currentRange / 2.0);
// Premium Box
ObjectCreate(0, prefix + "Prem_" + tStr, OBJ_RECTANGLE, 0, sessionEndTime, sessionHigh, extensionEnd, sessionEq);
ObjectSetInteger(0, prefix + "Prem_" + tStr, OBJPROP_COLOR, InpColorPrem);
ObjectSetInteger(0, prefix + "Prem_" + tStr, OBJPROP_BACK, true);
// Discount Box
ObjectCreate(0, prefix + "Disc_" + tStr, OBJ_RECTANGLE, 0, sessionEndTime, sessionEq, extensionEnd, sessionLow);
ObjectSetInteger(0, prefix + "Disc_" + tStr, OBJPROP_COLOR, InpColorDisc);
ObjectSetInteger(0, prefix + "Disc_" + tStr, OBJPROP_BACK, true);
// Boundary Lines
ObjectCreate(0, prefix + "ExtH_" + tStr, OBJ_TREND, 0, sessionEndTime, sessionHigh, extensionEnd, sessionHigh);
ObjectSetInteger(0, prefix + "ExtH_" + tStr, OBJPROP_COLOR, clrCrimson);
ObjectSetInteger(0, prefix + "ExtH_" + tStr, OBJPROP_RAY_RIGHT, false);
ObjectCreate(0, prefix + "ExtL_" + tStr, OBJ_TREND, 0, sessionEndTime, sessionLow, extensionEnd, sessionLow);
ObjectSetInteger(0, prefix + "ExtL_" + tStr, OBJPROP_COLOR, clrRoyalBlue);
ObjectSetInteger(0, prefix + "ExtL_" + tStr, OBJPROP_RAY_RIGHT, false);
}
// Active Session Drawing (Boxes & Quartiles)
if(inSession) {
double avgRange = GetAvgRange();
double currentRange = sessionHigh - sessionLow;
double sessionEq = sessionLow + (currentRange / 2.0);
double session75 = sessionLow + (currentRange * 0.75);
double session25 = sessionLow + (currentRange * 0.25);
bool isExpand = (avgRange > 0 && currentRange > (avgRange * InpMultiplier));
color boxColor = isExpand ? InpColorExpand : InpColorNormal;
string prefix = "AsiaElite_";
string tStr = IntegerToString((long)sessionStartTime);
// Main Box
if(ObjectFind(0, prefix + "Box_" + tStr) < 0) {
ObjectCreate(0, prefix + "Box_" + tStr, OBJ_RECTANGLE, 0, sessionStartTime, sessionHigh, t, sessionLow);
ObjectSetInteger(0, prefix + "Box_" + tStr, OBJPROP_BACK, true);
}
ObjectSetDouble(0, prefix + "Box_" + tStr, OBJPROP_PRICE1, sessionHigh);
ObjectSetDouble(0, prefix + "Box_" + tStr, OBJPROP_PRICE2, sessionLow);
ObjectSetInteger(0, prefix + "Box_" + tStr, OBJPROP_TIME2, t);
ObjectSetInteger(0, prefix + "Box_" + tStr, OBJPROP_COLOR, boxColor);
// Eq, 75%, 25% Lines
string[] lines = {"Eq_", "Q75_", "Q25_"};
double[] prices = {sessionEq, session75, session25};
int[] styles = {STYLE_DASH, STYLE_DOT, STYLE_DOT};
for(int j=0; j<3; j++) {
string lineName = prefix + lines[j] + tStr;
if(ObjectFind(0, lineName) < 0) {
ObjectCreate(0, lineName, OBJ_TREND, 0, sessionStartTime, prices[j], t, prices[j]);
ObjectSetInteger(0, lineName, OBJPROP_STYLE, styles[j]);
ObjectSetInteger(0, lineName, OBJPROP_RAY_RIGHT, false);
ObjectSetInteger(0, lineName, OBJPROP_COLOR, InpColorLine);
}
ObjectSetDouble(0, lineName, OBJPROP_PRICE1, prices[j]);
ObjectSetDouble(0, lineName, OBJPROP_PRICE2, prices[j]);
ObjectSetInteger(0, lineName, OBJPROP_TIME2, t);
}
// Expansion Alert
if (isExpand && !alertTriggered && i == 0) {
Alert("Tokyo Expansion on ", Symbol(), " (No Fade Zone)");
alertTriggered = true;
}
}
// Liquidity Purge Detection (Post-Session)
bool inLondon = (!isInside && sessionEndTime > 0 && t <= sessionEndTime + (InpExtendHours * 3600));
if (inLondon) {
string prefix = "AsiaElite_";
string tStr = IntegerToString((long)sessionStartTime);
// BSL Sweep
if (high[i] > sessionHigh && !bslSwept) {
bslSwept = true;
string bslName = prefix + "BSL_" + IntegerToString((long)t);
ObjectCreate(0, bslName, OBJ_TEXT, 0, t, high[i]);
ObjectSetString(0, bslName, OBJPROP_TEXT, "BSL");
ObjectSetInteger(0, bslName, OBJPROP_COLOR, clrCrimson);
if (i == 0) Alert("BSL Purged on ", Symbol(), " in London Session.");
}
// SSL Sweep
if (low[i] < sessionLow && !sslSwept) {
sslSwept = true;
string sslName = prefix + "SSL_" + IntegerToString((long)t);
ObjectCreate(0, sslName, OBJ_TEXT, 0, t, low[i]);
ObjectSetString(0, sslName, OBJPROP_TEXT, "SSL");
ObjectSetInteger(0, sslName, OBJPROP_COLOR, clrRoyalBlue);
if (i == 0) Alert("SSL Purged on ", Symbol(), " in London Session.");
}
}
// Live HUD Updates
if(i == 0 && InpShowHUD) {
double avgRange = GetAvgRange();
double curRange = sessionHigh - sessionLow;
double pctOfAvg = avgRange > 0 ? (curRange / avgRange) * 100 : 0;
bool isExpand = (avgRange > 0 && curRange > (avgRange * InpMultiplier));
int curPts = (int)MathRound(curRange / Point);
int avgPts = (int)MathRound(avgRange / Point);
color statClr = isExpand ? InpColorExpand : InpColorNormal;
string statTxt = isExpand ? "EXPANSION (NO FADE)" : "NORMAL / ACCUMULATION";
string sweepTxt = "Intact";
color sweepClr = clrGray;
if (bslSwept && sslSwept) { sweepTxt = "Both Sides Purged"; sweepClr = clrMediumPurple; }
else if (bslSwept) { sweepTxt = "BSL Purged (High Taken)"; sweepClr = clrCrimson; }
else if (sslSwept) { sweepTxt = "SSL Purged (Low Taken)"; sweepClr = clrRoyalBlue; }
CreateLabel("AsiaHUD_1", 20, 100, "MICROSTRUCTURE [ELITE]", clrWhite, 9, true);
CreateLabel("AsiaHUD_2", 20, 80, "Current Range: " + IntegerToString(curPts) + " points", clrLightGray);
CreateLabel("AsiaHUD_3", 20, 65, "15D Average: " + IntegerToString(avgPts) + " points (" + DoubleToString(pctOfAvg, 0) + "%)", clrLightGray);
CreateLabel("AsiaHUD_4", 20, 45, "Setup Validity: " + statTxt, statClr, 8, true);
CreateLabel("AsiaHUD_5", 20, 25, "London Liquidity: " + sweepTxt, sweepClr, 8, true);
}
}
return(rates_total);
}Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: Tokyo morning expansion days: when I refuse the London fade
MetaTrader 5 (MQL5) [ELITE]
Save as AsianMicrostructure_ELITE_MT5.mq5 in your MQL5/Indicators folder. This version uses OBJPROP_FILL for perfect opacity on the Premium and Discount zones.
Save as AsianMicrostructure_ELITE_MT5.mq5 in your MQL5/Indicators folder. This version uses OBJPROP_FILL for perfect opacity on the Premium and Discount zones.
Code: Select all
//+------------------------------------------------------------------+
//| AsianMicrostructure_ELITE_MT5.mq5 |
//+------------------------------------------------------------------+
#property copyright "Indicator Port"
#property version "3.00"
#property indicator_chart_window
#property indicator_buffers 0
#property indicator_plots 0
// --- INPUTS ---
input string InpSessionStart = "00:00"; // Asian Session Start (HH:MM)
input string InpSessionEnd = "08:00"; // Asian Session End (HH:MM)
input int InpExtendHours = 6; // London Projection Length (Hours)
input int InpLookback = 15; // Average Range Lookback (Days)
input double InpMultiplier = 1.5; // Expansion Multiplier
input color InpColorNormal = clrCornflowerBlue; // Normal Range Box
input color InpColorExpand = clrCrimson; // Expansion Range Box
input color InpColorPrem = clrMistyRose; // Premium Projection (Top 50%)
input color InpColorDisc = clrLightCyan; // Discount Projection (Bot 50%)
input color InpColorLine = clrGray; // Internal Structure Lines
input bool InpShowHUD = true; // Show Data Dashboard
// --- GLOBALS ---
int startHour, startMin, endHour, endMin;
double pastRanges[];
int rangeCount = 0;
bool inSession = false;
bool alertTriggered = false;
bool bslSwept = false;
bool sslSwept = false;
double sessionHigh = 0;
double sessionLow = 0;
datetime sessionStartTime = 0;
datetime sessionEndTime = 0;
int OnInit()
{
startHour = (int)StringToInteger(StringSubstr(InpSessionStart, 0, 2));
startMin = (int)StringToInteger(StringSubstr(InpSessionStart, 3, 2));
endHour = (int)StringToInteger(StringSubstr(InpSessionEnd, 0, 2));
endMin = (int)StringToInteger(StringSubstr(InpSessionEnd, 3, 2));
ArrayResize(pastRanges, InpLookback);
ArrayInitialize(pastRanges, 0.0);
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)
{
ObjectsDeleteAll(0, "AsiaElite_");
ObjectsDeleteAll(0, "AsiaHUD_");
}
bool IsTimeInSession(datetime t)
{
MqlDateTime dt;
TimeToStruct(t, dt);
int currentMins = dt.hour * 60 + dt.min;
int startMins = startHour * 60 + startMin;
int endMins = endHour * 60 + endMin;
if (startMins < endMins) return (currentMins >= startMins && currentMins < endMins);
return (currentMins >= startMins || currentMins < endMins);
}
void AddRange(double range)
{
for(int i = InpLookback - 1; i > 0; i--) pastRanges[i] = pastRanges[i-1];
pastRanges[0] = range;
if(rangeCount < InpLookback) rangeCount++;
}
double GetAvgRange()
{
if (rangeCount == 0) return 0;
double sum = 0;
for(int i = 0; i < rangeCount; i++) sum += pastRanges[i];
return sum / (double)rangeCount;
}
void CreateLabel(string name, int x, int y, string text, color clr, int size = 8, bool bold = false)
{
if(ObjectFind(0, name) < 0) {
ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);
ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_RIGHT_LOWER);
ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_RIGHT_LOWER);
}
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
ObjectSetString(0, name, OBJPROP_TEXT, text);
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
ObjectSetString(0, name, OBJPROP_FONT, bold ? "Arial Bold" : "Arial");
ObjectSetInteger(0, name, OBJPROP_FONTSIZE, size);
}
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[])
{
if(rates_total < 2) return(0);
ArraySetAsSeries(time, true);
ArraySetAsSeries(high, true);
ArraySetAsSeries(low, true);
int limit = rates_total - prev_calculated;
if(prev_calculated == 0) {
limit = rates_total - 1;
ArrayInitialize(pastRanges, 0.0);
rangeCount = 0;
inSession = false;
ObjectsDeleteAll(0, "AsiaElite_");
}
for(int i = limit; i >= 0; i--) {
datetime t = time[i];
bool isInside = IsTimeInSession(t);
// Session Start
if(isInside && !inSession) {
inSession = true;
alertTriggered = false;
bslSwept = false;
sslSwept = false;
sessionStartTime = t;
sessionHigh = high[i];
sessionLow = low[i];
}
// Inside Session Updates
else if (isInside && inSession) {
if(high[i] > sessionHigh) sessionHigh = high[i];
if(low[i] < sessionLow) sessionLow = low[i];
}
// Session End
else if (!isInside && inSession) {
inSession = false;
sessionEndTime = t;
double currentRange = sessionHigh - sessionLow;
AddRange(currentRange);
// Draw London Projections
string prefix = "AsiaElite_";
string tStr = IntegerToString((long)sessionStartTime);
datetime extensionEnd = sessionEndTime + (InpExtendHours * 3600);
double sessionEq = sessionLow + (currentRange / 2.0);
// Premium Box
ObjectCreate(0, prefix + "Prem_" + tStr, OBJ_RECTANGLE, 0, sessionEndTime, sessionHigh, extensionEnd, sessionEq);
ObjectSetInteger(0, prefix + "Prem_" + tStr, OBJPROP_COLOR, InpColorPrem);
ObjectSetInteger(0, prefix + "Prem_" + tStr, OBJPROP_FILL, true);
ObjectSetInteger(0, prefix + "Prem_" + tStr, OBJPROP_BACK, true);
// Discount Box
ObjectCreate(0, prefix + "Disc_" + tStr, OBJ_RECTANGLE, 0, sessionEndTime, sessionEq, extensionEnd, sessionLow);
ObjectSetInteger(0, prefix + "Disc_" + tStr, OBJPROP_COLOR, InpColorDisc);
ObjectSetInteger(0, prefix + "Disc_" + tStr, OBJPROP_FILL, true);
ObjectSetInteger(0, prefix + "Disc_" + tStr, OBJPROP_BACK, true);
// Boundary Lines
ObjectCreate(0, prefix + "ExtH_" + tStr, OBJ_TREND, 0, sessionEndTime, sessionHigh, extensionEnd, sessionHigh);
ObjectSetInteger(0, prefix + "ExtH_" + tStr, OBJPROP_COLOR, clrCrimson);
ObjectSetInteger(0, prefix + "ExtH_" + tStr, OBJPROP_RAY_RIGHT, false);
ObjectCreate(0, prefix + "ExtL_" + tStr, OBJ_TREND, 0, sessionEndTime, sessionLow, extensionEnd, sessionLow);
ObjectSetInteger(0, prefix + "ExtL_" + tStr, OBJPROP_COLOR, clrRoyalBlue);
ObjectSetInteger(0, prefix + "ExtL_" + tStr, OBJPROP_RAY_RIGHT, false);
}
// Active Session Drawing
if(inSession) {
double avgRange = GetAvgRange();
double currentRange = sessionHigh - sessionLow;
double sessionEq = sessionLow + (currentRange / 2.0);
double session75 = sessionLow + (currentRange * 0.75);
double session25 = sessionLow + (currentRange * 0.25);
bool isExpand = (avgRange > 0 && currentRange > (avgRange * InpMultiplier));
color boxColor = isExpand ? InpColorExpand : InpColorNormal;
string prefix = "AsiaElite_";
string tStr = IntegerToString((long)sessionStartTime);
// Main Box
if(ObjectFind(0, prefix + "Box_" + tStr) < 0) {
ObjectCreate(0, prefix + "Box_" + tStr, OBJ_RECTANGLE, 0, sessionStartTime, sessionHigh, t, sessionLow);
ObjectSetInteger(0, prefix + "Box_" + tStr, OBJPROP_FILL, true);
ObjectSetInteger(0, prefix + "Box_" + tStr, OBJPROP_BACK, true);
}
ObjectSetDouble(0, prefix + "Box_" + tStr, OBJPROP_PRICE1, sessionHigh);
ObjectSetDouble(0, prefix + "Box_" + tStr, OBJPROP_PRICE2, sessionLow);
ObjectSetInteger(0, prefix + "Box_" + tStr, OBJPROP_TIME2, t);
ObjectSetInteger(0, prefix + "Box_" + tStr, OBJPROP_COLOR, boxColor);
// Eq, 75%, 25% Lines
string[] lines = {"Eq_", "Q75_", "Q25_"};
double[] prices = {sessionEq, session75, session25};
int[] styles = {STYLE_DASH, STYLE_DOT, STYLE_DOT};
for(int j=0; j<3; j++) {
string lineName = prefix + lines[j] + tStr;
if(ObjectFind(0, lineName) < 0) {
ObjectCreate(0, lineName, OBJ_TREND, 0, sessionStartTime, prices[j], t, prices[j]);
ObjectSetInteger(0, lineName, OBJPROP_STYLE, styles[j]);
ObjectSetInteger(0, lineName, OBJPROP_RAY_RIGHT, false);
ObjectSetInteger(0, lineName, OBJPROP_COLOR, InpColorLine);
}
ObjectSetDouble(0, lineName, OBJPROP_PRICE1, prices[j]);
ObjectSetDouble(0, lineName, OBJPROP_PRICE2, prices[j]);
ObjectSetInteger(0, lineName, OBJPROP_TIME2, t);
}
// Expansion Alert
if (isExpand && !alertTriggered && i == 0) {
Alert("Tokyo Expansion on ", Symbol(), " (No Fade Zone)");
alertTriggered = true;
}
}
// Liquidity Purge Detection (Post-Session)
bool inLondon = (!isInside && sessionEndTime > 0 && t <= sessionEndTime + (InpExtendHours * 3600));
if (inLondon) {
string prefix = "AsiaElite_";
// BSL Sweep
if (high[i] > sessionHigh && !bslSwept) {
bslSwept = true;
string bslName = prefix + "BSL_" + IntegerToString((long)t);
ObjectCreate(0, bslName, OBJ_TEXT, 0, t, high[i]);
ObjectSetString(0, bslName, OBJPROP_TEXT, "BSL");
ObjectSetInteger(0, bslName, OBJPROP_COLOR, clrCrimson);
if (i == 0) Alert("BSL Purged on ", Symbol(), " in London Session.");
}
// SSL Sweep
if (low[i] < sessionLow && !sslSwept) {
sslSwept = true;
string sslName = prefix + "SSL_" + IntegerToString((long)t);
ObjectCreate(0, sslName, OBJ_TEXT, 0, t, low[i]);
ObjectSetString(0, sslName, OBJPROP_TEXT, "SSL");
ObjectSetInteger(0, sslName, OBJPROP_COLOR, clrRoyalBlue);
if (i == 0) Alert("SSL Purged on ", Symbol(), " in London Session.");
}
}
// Live HUD Updates
if(i == 0 && InpShowHUD) {
double avgRange = GetAvgRange();
double curRange = sessionHigh - sessionLow;
double pctOfAvg = avgRange > 0 ? (curRange / avgRange) * 100 : 0;
bool isExpand = (avgRange > 0 && curRange > (avgRange * InpMultiplier));
int curPts = (int)MathRound(curRange / Point());
int avgPts = (int)MathRound(avgRange / Point());
color statClr = isExpand ? InpColorExpand : InpColorNormal;
string statTxt = isExpand ? "EXPANSION (NO FADE)" : "NORMAL / ACCUMULATION";
string sweepTxt = "Intact";
color sweepClr = clrGray;
if (bslSwept && sslSwept) { sweepTxt = "Both Sides Purged"; sweepClr = clrMediumPurple; }
else if (bslSwept) { sweepTxt = "BSL Purged (High Taken)"; sweepClr = clrCrimson; }
else if (sslSwept) { sweepTxt = "SSL Purged (Low Taken)"; sweepClr = clrRoyalBlue; }
CreateLabel("AsiaHUD_1", 20, 100, "MICROSTRUCTURE [ELITE]", clrWhite, 9, true);
CreateLabel("AsiaHUD_2", 20, 80, "Current Range: " + IntegerToString(curPts) + " points", clrLightGray);
CreateLabel("AsiaHUD_3", 20, 65, "15D Average: " + IntegerToString(avgPts) + " points (" + DoubleToString(pctOfAvg, 0) + "%)", clrLightGray);
CreateLabel("AsiaHUD_4", 20, 45, "Setup Validity: " + statTxt, statClr, 8, true);
CreateLabel("AsiaHUD_5", 20, 25, "London Liquidity: " + sweepTxt, sweepClr, 8, true);
}
}
return(rates_total);
}Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.