MA_RangeAlert
Download scriptTechnical Logic Overview
This script is designed to monitor market volatility and alert traders when price action shifts significantly beyond established "normal" ranges. Instead of simply looking at price movement in isolation, the logic utilizes a multi-layered approach involving Moving Averages (MA) and relative range calculations to identify specific breakout moments.
Core Functionality
The primary objective of this tool is to detect when the market transitions between two distinct states:
- Entering a Range: When volatility stabilizes and stays within a predefined threshold.
- Exiting a Range (Breakout): When volatility expands rapidly beyond that same threshold.
How the Logic Works
1. Volatility Measurement The script calculates the average range of recent price candles. It looks at a window of 10 bars to determine the typical distance between the high and low prices. This provides a baseline for what "normal" volatility looks like in the current market condition.
2. Moving Average Variance (The "Range Limit") To define what constitutes a significant shift, the script employs three different Moving Averages simultaneously. By analyzing these three averages, the tool calculates the distance between the highest and lowest average values.
- If the gap between these averages exceeds a user-defined limit (the
MA_RangeLimit), the market is considered to be in a high-volatility or breakout state. - If the gap remains below this limit, the market is considered to be within a stable range.
3. Transition Detection & Alerts The script constantly compares the current bar's average variance against the previous bar. It triggers an action only at the exact moment the status flips:
- Breakout Alert: If the variance was previously below the limit but has now jumped above it, the script identifies this as "Coming out of range."
- Stabilization Alert: If the variance was previously above the limit but has now dropped below it, the script identifies this as "Going into range."
4. Visual and Notification Outputs When these specific transitions occur, the script provides three types of feedback:
- Visual Cues: It places symbols (arrows) on the chart at the point of the transition to highlight where the breakout or stabilization occurred.
- Audio Alerts: It triggers a sound notification to grab the trader's attention immediately.
- Email Notifications: It can be configured to send an automated email with the specific date, time, currency symbol, and timeframe of the event.
Summary for the User
In plain terms, this tool acts as a "volatility watchdog." Rather than telling you where to trade, it monitors the "stretch" of the market. It notifies you the moment the market stops moving sideways (stabilizes) or the moment it starts expanding aggressively (breaks out), allowing you to react to changes in momentum in real-time.
//+------------------------------------------------------------------+
//| CandleSizeAlert.mq4 |
//| Copyright © 2008, Robert Hill |
//| |
//| Will send alert when a candle meets the size criteria entered |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2006, Robert Hill"
#property indicator_chart_window
#property indicator_buffers 5
#property indicator_color1 LawnGreen
#property indicator_color2 Red
#property indicator_color3 Red
#property indicator_color4 Aqua
#property indicator_color5 Yellow
#property indicator_width1 2
#property indicator_width2 2
#property indicator_width3 2
#property indicator_width4 2
#property indicator_width5 2
extern bool SoundON=true;
extern bool EmailON=false;
extern int MAPeriod1=7;
extern int MAPeriod2=14;
extern int MAPeriod3=35;
extern string m = "--Moving Average Types--";
extern string m0 = " 0 = SMA";
extern string m1 = " 1 = EMA";
extern string m2 = " 2 = SMMA";
extern string m3 = " 3 = LWMA";
extern string m4 = " 4 = LSMA";
extern int MAType1=1;
extern int MAType2=1;
extern int MAType3=1;
extern string p = "--Applied Price Types--";
extern string p0 = " 0 = close";
extern string p1 = " 1 = open";
extern string p2 = " 2 = high";
extern string p3 = " 3 = low";
extern string p4 = " 4 = median(high+low)/2";
extern string p5 = " 5 = typical(high+low+close)/3";
extern string p6 = " 6 = weighted(high+low+close+close)/4";
extern int MAAppliedPrice1 = 0;
extern int MAAppliedPrice2 = 0;
extern int MAAppliedPrice3 = 0;
extern int MA_RangeLimit = 10;
extern int MaxBars = 300;
double CrossUp[];
double CrossDown[];
double Ma1[];
double Ma2[];
double Ma3[];
int flagval1 = 0;
int flagval2 = 0;
double myPoint;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//---- indicators
// IndicatorBuffers(5);
SetIndexStyle(0, DRAW_ARROW, EMPTY);
SetIndexArrow(0, 233);
SetIndexBuffer(0, CrossUp);
SetIndexStyle(1, DRAW_ARROW, EMPTY);
SetIndexArrow(1, 234);
SetIndexBuffer(1, CrossDown);
SetIndexStyle(2, DRAW_LINE, STYLE_SOLID);
SetIndexBuffer(2, Ma1);
SetIndexStyle(3, DRAW_LINE, STYLE_SOLID);
SetIndexBuffer(3, Ma2);
SetIndexStyle(4, DRAW_LINE, STYLE_SOLID);
SetIndexBuffer(4, Ma3);
myPoint = SetPoint(Symbol());
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start() {
int limit, i, counter;
double tmp=0;
double Range, AvgRange;
datetime tc;
int MA_RangeNow, MA_RangePrev;
int counted_bars=IndicatorCounted();
//---- check for possible errors
if(counted_bars<0) return(-1);
//---- last counted bar will be recounted
if(counted_bars>0) counted_bars--;
limit=MaxBars;
for(i = 0; i <= limit; i++) {
counter=i;
Range=0;
AvgRange=0;
for (counter=i ;counter<=i+9;counter++)
{
AvgRange=AvgRange+MathAbs(High[counter]-Low[counter]);
}
Range=AvgRange/10;
MA_RangeNow = GetMA_Range(i, true);
MA_RangePrev = GetMA_Range(i+1, false);
CrossUp[i] = 0;
CrossDown[i] = 0;
if (MA_RangeNow >= MA_RangeLimit && MA_RangePrev < MA_RangeLimit)
{
if (i == 1 && flagval1==0)
{
flagval1=1;
flagval2=0;
tc = TimeCurrent();
if (SoundON) Alert("Coming out of range","\n Date=",TimeToStr(tc,TIME_DATE)," ",TimeHour(tc),":",TimeMinute(tc),"\n Symbol=",Symbol()," Period=",Period());
if (EmailON) SendMail("Coming out of range"," Date="+TimeToStr(tc,TIME_DATE)+" "+TimeHour(tc)+":"+TimeMinute(tc)+" Symbol="+Symbol()+" Period="+Period());
}
CrossUp[i] = Low[i] - Range*0.75;
}
else if (MA_RangeNow <= MA_RangeLimit && MA_RangePrev > MA_RangeLimit)
{
if (i == 1 && flagval2==0)
{
flagval2=1;
flagval1=0;
tc = TimeCurrent();
if (SoundON) Alert("Going into range","\n Date=",TimeToStr(tc,TIME_DATE)," ",TimeHour(tc),":",TimeMinute(tc),"\n Symbol=",Symbol()," Period=",Period());
if (EmailON) SendMail("Going into range"," Date="+TimeToStr(tc,TIME_DATE)+" "+TimeHour(tc)+":"+TimeMinute(tc)+" Symbol="+Symbol()+" Period="+Period());
}
CrossDown[i] = High[i] + Range*0.75;
}
}
return(0);
}
double SetPoint(string mySymbol)
{
double mPoint, myDigits;
myDigits = MarketInfo (mySymbol, MODE_DIGITS);
if (myDigits < 4)
mPoint = 0.01;
else
mPoint = 0.0001;
return(mPoint);
}
double iLsma(int TimeFrame, int LSMAPeriod, int LSMAPrice,int shift)
{
double wt;
double ma1=iMA(NULL,TimeFrame,LSMAPeriod,0,MODE_SMA ,LSMAPrice,shift);
double ma2=iMA(NULL,TimeFrame,LSMAPeriod,0,MODE_LWMA,LSMAPrice,shift);
wt = MathFloor((3.0*ma2-2.0*ma1)/Point)*Point;
return(wt);
}
int GetMA_Range(int pos, bool ShowMAs)
{
double ma_1, ma_2, ma_3;
double max_ma, min_ma;
int MA_Dif;
switch (MAType1)
{
case 4 :
ma_1 = iLsma(0, MAPeriod1, MAAppliedPrice1,pos);
break;
default :
ma_1 = iMA(NULL,0,MAPeriod1,0,MAType1, MAAppliedPrice1,pos);
}
switch (MAType2)
{
case 4 :
ma_2 = iLsma(0, MAPeriod2, MAAppliedPrice2,pos);
break;
default :
ma_2 = iMA(NULL,0,MAPeriod2,0,MAType2, MAAppliedPrice2,pos);
}
switch (MAType3)
{
case 4 :
ma_3 = iLsma(0, MAPeriod3, MAAppliedPrice3,pos);
break;
default :
ma_3 = iMA(NULL,0,MAPeriod3,0,MAType3, MAAppliedPrice3,pos);
}
ma_1 = NormalizeDouble(ma_1, Digits);
ma_2 = NormalizeDouble(ma_2, Digits);
ma_3 = NormalizeDouble(ma_3, Digits);
if (ShowMAs)
{
Ma1[pos] = ma_1;
Ma2[pos] = ma_2;
Ma3[pos] = ma_3;
}
max_ma = ma_1;
if (ma_2 > max_ma) max_ma = ma_2;
if (ma_3 > max_ma) max_ma = ma_3;
min_ma = ma_1;
if (ma_2 < min_ma) min_ma = ma_2;
if (ma_3 < min_ma) min_ma = ma_3;
MA_Dif = (max_ma - min_ma) / myPoint;
return(MA_Dif);
}
Comments