Moving this from TradingView to MetaTrader requires handling multi-timeframe synchronization explicitly, as MT4 and MT5 do not have Pine Script’s request.security abstraction.
Both scripts below use iBarShift to align the M1 and M5 timeframes perfectly to whatever chart timeframe you drop the indicator on. They use hidden buffers for the raw noise calculation and plot the smoothed averages. The alerts strictly trigger on the close of the candle (index 1) to prevent false intra-bar signals.
MT4 Implementation (MQL4)
Save this as TF_Noise_Visualizer.mq4 in your MQL4/Indicators folder.
Code: Select all
//+------------------------------------------------------------------+
//| TF_Noise_Visualizer.mq4 |
//+------------------------------------------------------------------+
#property copyright "Pavel Tucek"
#property indicator_separate_window
#property indicator_buffers 4
#property indicator_color1 clrRed
#property indicator_color2 clrDodgerBlue
#property indicator_width1 2
#property indicator_width2 2
// Visual Levels
#property indicator_level1 1.0
#property indicator_level2 5.0
#property indicator_levelcolor clrDarkGray
#property indicator_levelstyle STYLE_DOT
//--- Inputs
input int InpM1Bars = 60; // M1 Rolling Window (60 = 1 Hour)
input int InpM5Bars = 12; // M5 Rolling Window (12 = 1 Hour)
input int InpMAPeriod = 20; // Smoothing MA Period
input int InpMAMethod = 1; // 0: SMA, 1: EMA
input double InpChaosThreshold = 5.0; // High-Chaos Threshold (M1)
input bool InpUseAlerts = true; // Enable Push/Popup Alerts
//--- Buffers
double ExtSmoothedM1[];
double ExtSmoothedM5[];
double ExtRawM1[];
double ExtRawM5[];
//--- Global Variables
datetime lastAlertTime = 0;
//+------------------------------------------------------------------+
int OnInit()
{
SetIndexBuffer(0, ExtSmoothedM1);
SetIndexStyle(0, DRAW_LINE);
SetIndexLabel(0, "Smoothed M1 Noise");
SetIndexBuffer(1, ExtSmoothedM5);
SetIndexStyle(1, DRAW_LINE);
SetIndexLabel(1, "Smoothed M5 Noise");
// Hidden buffers for raw calculations
SetIndexBuffer(2, ExtRawM1);
SetIndexStyle(2, DRAW_NONE);
SetIndexBuffer(3, ExtRawM5);
SetIndexStyle(3, DRAW_NONE);
IndicatorShortName("TF Noise [" + IntegerToString(InpMAPeriod) + "]");
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
double CalculateNoise(int timeframe, datetime time, int lookback)
{
int shift = iBarShift(NULL, timeframe, time, false);
if(shift < 0) return 0.0;
double total_movement = 0;
int highest_idx = iHighest(NULL, timeframe, MODE_HIGH, lookback, shift);
int lowest_idx = iLowest(NULL, timeframe, MODE_LOW, lookback, shift);
if(highest_idx < 0 || lowest_idx < 0) return 0.0;
double highest_high = iHigh(NULL, timeframe, highest_idx);
double lowest_low = iLow(NULL, timeframe, lowest_idx);
double net_displacement = highest_high - lowest_low;
for(int i = 0; i < lookback; i++)
{
total_movement += (iHigh(NULL, timeframe, shift + i) - iLow(NULL, timeframe, shift + i));
}
if(net_displacement <= 0) return 1.0;
return total_movement / net_displacement;
}
//+------------------------------------------------------------------+
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 < InpMAPeriod) return(0);
int limit = rates_total - prev_calculated;
if(limit > 0) limit++;
if(prev_calculated == 0) limit = rates_total - 1;
// 1. Calculate Raw Noise
for(int i = limit; i >= 0; i--)
{
ExtRawM1[i] = CalculateNoise(PERIOD_M1, time[i], InpM1Bars);
ExtRawM5[i] = CalculateNoise(PERIOD_M5, time[i], InpM5Bars);
}
// 2. Apply Smoothing
double alpha = 2.0 / (InpMAPeriod + 1.0);
for(int i = limit; i >= 0; i--)
{
if(InpMAMethod == 0) // SMA
{
double sumM1 = 0, sumM5 = 0;
for(int k = 0; k < InpMAPeriod; k++)
{
sumM1 += ExtRawM1[i + k];
sumM5 += ExtRawM5[i + k];
}
ExtSmoothedM1[i] = sumM1 / InpMAPeriod;
ExtSmoothedM5[i] = sumM5 / InpMAPeriod;
}
else // EMA
{
if(i == rates_total - 1)
{
ExtSmoothedM1[i] = ExtRawM1[i];
ExtSmoothedM5[i] = ExtRawM5[i];
}
else
{
ExtSmoothedM1[i] = alpha * ExtRawM1[i] + (1 - alpha) * ExtSmoothedM1[i + 1];
ExtSmoothedM5[i] = alpha * ExtRawM5[i] + (1 - alpha) * ExtSmoothedM5[i + 1];
}
}
}
// 3. Process Alerts (Only strictly on closed bar [1])
if(InpUseAlerts && time[0] != lastAlertTime)
{
bool crossUnder = (ExtSmoothedM1[1] < InpChaosThreshold && ExtSmoothedM1[2] >= InpChaosThreshold);
bool crossOver = (ExtSmoothedM1[1] > InpChaosThreshold && ExtSmoothedM1[2] <= InpChaosThreshold);
if(crossUnder)
{
Alert(Symbol(), " TF Noise: M1 dropped below chaos threshold. Clean structure returning.");
lastAlertTime = time[0];
}
else if(crossOver)
{
Alert(Symbol(), " TF Noise: M1 exceeded chaos threshold. Messy range detected.");
lastAlertTime = time[0];
}
}
return(rates_total);
}
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.