This script is designed as a technical analysis tool for the MetaTrader 4 platform, specifically engineered to identify trend reversals and provide visual signals on a trading chart. It functions by monitoring price action over a specific look-back period to determine when a market shift is likely occurring.
Core Logic and Methodology
1. Market Volatility Assessment The script begins by calculating the "Average Range" of the market. It looks at the difference between highs and lows over a set number of recent candles. By establishing this average, the tool creates a baseline for "normal" price movement, allowing it to distinguish between standard market noise and significant price movements.
2. Trend Strength Evaluation To determine the current strength of the trend, the logic employs two primary checks:
- Gap Analysis: It looks for significant jumps between the opening price of one candle and the closing price of the previous one.
- Momentum Comparison: It compares the closing prices of current candles against those from several bars back to see if the price is moving with sufficient velocity. Based on these checks, the script dynamically adjusts its internal sensitivity settings, effectively "tuning" itself to the current speed of the market.
3. Signal Identification The script uses a specialized calculation (similar to a Williams %R oscillator) to measure where the current price sits relative to a recent high and low range. It then looks for specific "breakout" conditions:
- Sell Signals: When the price falls below a specific lower threshold and moves back upward into a designated zone, it identifies a potential trend reversal.
- Buy Signals: When the price rises above a specific upper threshold and moves back downward into a designated zone, it identifies an opposite reversal.
Visual and Notification Features
Once the logic identifies these conditions, the script performs three primary actions:
- Visual Markers: It places physical arrows on your trading chart (Magenta for Sell signals and Aqua for Buy signals) to highlight exactly where the trend change was detected.
- Audio Alerts: If the sound settings are enabled, the tool will trigger a real-time audio alert as soon as a signal is confirmed.
- Email Notifications: For traders who are away from their computers, the script can automatically send an email alert containing the specific price (Ask and Bid), the date, time, and the symbol being traded.
Smart Filtering
The script includes a "flag" system to ensure that it does not spam the user with repetitive alerts. It tracks whether a signal has already been sent for a specific timeframe and prevents duplicate notifications until a new, valid trend change is confirmed by the logic.
//+-------------------------------------------------------------------+
//| ASCTrendExpert snd e-mail.mq4 |
//| Copyright © 2004, MetaQuotes Software Corp. |
//| http://www.metaquotes.net |
//| Made/Modified by Alejandro Galindo |
//| |
//| You are free to use it |
//| |
//| If you want and if this work/modification is helpful to you |
//| send me a PayPal donation to ag@elcactus.com |
//| any help is apreciated :) |
//| Thanks. |
//+-------------------------------------------------------------------+
//| Original Version ASCTrend1sig_noSound.mq4
//| Ramdass - Conversion only
//+------------------------------------------------------------------+
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 Magenta
#property indicator_color2 Aqua
//---- input parameters
extern int RISK=3;
extern int CountBars=300;
extern int SoundON=1;
extern int EmailON=0;
//---- buffers
double val1[];
double val2[];
int flagval1 = 0;
int flagval2 = 0;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//---- indicator line
IndicatorBuffers(2);
SetIndexStyle(0,DRAW_ARROW);
SetIndexArrow(0,234);
SetIndexStyle(1,DRAW_ARROW);
SetIndexArrow(1,233);
SetIndexBuffer(0,val1);
SetIndexBuffer(1,val2);
GlobalVariableSet("AlertTime"+Symbol()+Period(),CurTime());
GlobalVariableSet("SignalType"+Symbol()+Period(),OP_SELLSTOP);
//----
return(0);
}
int deinit()
{
GlobalVariableDel("AlertTime"+Symbol()+Period());
GlobalVariableDel("SignalType"+Symbol()+Period());
return(0);
}
//+------------------------------------------------------------------+
//| ASCTrend1sig |
//+------------------------------------------------------------------+
int start()
{
if (CountBars>=1000) CountBars=950;
SetIndexDrawBegin(0,Bars-CountBars+11+1);
SetIndexDrawBegin(1,Bars-CountBars+11+1);
int i,shift,counted_bars=IndicatorCounted();
int Counter,i1,value10,value11;
double value1,x1,x2;
double value2,value3;
double TrueCount,Range,AvgRange,MRO1,MRO2;
double Table_value2[1000];
double tmp=0;
value10=3+RISK*2;
x1=67+RISK;
x2=33-RISK;
value11=value10;
//----
if(Bars<=11+1) return(0);
//---- initial zero
if(counted_bars<11+1)
{
for(i=1;i<=0;i++) val1[CountBars-i]=0.0;
for(i=1;i<=0;i++) val2[CountBars-i]=0.0;
}
//----
shift=CountBars-11-1;
while(shift>=0)
{
Counter=shift;
Range=0.0;
AvgRange=0.0;
for (Counter=shift; Counter<=shift+9; Counter++) AvgRange=AvgRange+MathAbs(High[Counter]-Low[Counter]);
Range=AvgRange/10;
Counter=shift;
TrueCount=0;
while (Counter<shift+9 && TrueCount<1)
{if (MathAbs(Open[Counter]-Close[Counter+1])>=Range*2.0) TrueCount=TrueCount+1;
Counter=Counter+1;
}
if (TrueCount>=1) {MRO1=Counter;} else {MRO1=-1;}
Counter=shift;
TrueCount=0;
while (Counter<shift+6 && TrueCount<1)
{if (MathAbs(Close[Counter+3]-Close[Counter])>=Range*4.6) TrueCount=TrueCount+1;
Counter=Counter+1;
}
if (TrueCount>=1) {MRO2=Counter;} else {MRO2=-1;}
if (MRO1>-1) {value11=3;} else {value11=value10;}
if (MRO2>-1) {value11=4;} else {value11=value10;}
value2=100-MathAbs(iWPR(NULL,0,value11,shift)); // PercentR(value11=9)
Table_value2[shift]=value2;
val1[shift]=0;
val2[shift]=0;
value3=0;
if (value2<x2)
{i1=1;
while (Table_value2[shift+i1]>=x2 && Table_value2[shift+i1]<=x1){i1++;}
if (Table_value2[shift+i1]>x1)
{
value3=High[shift]+Range*0.5;
if (shift == 1 && flagval1==0){ flagval1=1; flagval2=0; }
val1[shift]=value3;
}
}
if (value2>x1)
{i1=1;
while (Table_value2[shift+i1]>=x2 && Table_value2[shift+i1]<=x1){i1++;}
if (Table_value2[shift+i1]<x2)
{
value3=Low[shift]-Range*0.5;
if (shift == 1 && flagval2==0) { flagval2=1; flagval1=0; }
val2[shift]=value3;
}
}
shift--;
}
if (flagval1==1 && CurTime() > GlobalVariableGet("AlertTime"+Symbol()+Period()) && GlobalVariableGet("SignalType"+Symbol()+Period())!=OP_BUY) {
if (SoundON==1) Alert("SELL signal at Ask=",Ask,", Bid=",Bid,", Date=",TimeToStr(CurTime(),TIME_DATE)," ",TimeHour(CurTime()),":",TimeMinute(CurTime())," Symbol=",Symbol()," Period=",Period());
if (EmailON==1) SendMail("SELL signal alert","SELL signal at Ask="+DoubleToStr(Ask,4)+", Bid="+DoubleToStr(Bid,4)+", Date="+TimeToStr(CurTime(),TIME_DATE)+" "+TimeHour(CurTime())+":"+TimeMinute(CurTime())+" Symbol="+Symbol()+" Period="+Period());
tmp = CurTime() + (Period()-MathMod(Minute(),Period()))*60;
GlobalVariableSet("AlertTime"+Symbol()+Period(),tmp);
GlobalVariableSet("SignalType"+Symbol()+Period(),OP_BUY);
}
if (flagval2==1 && CurTime() > GlobalVariableGet("AlertTime"+Symbol()+Period()) && GlobalVariableGet("SignalType"+Symbol()+Period())!=OP_SELL) {
if (SoundON==1) Alert("BUY signal at Ask=",Ask,", Bid=",Bid,", Time=",TimeToStr(CurTime(),TIME_DATE)," ",TimeHour(CurTime()),":",TimeMinute(CurTime())," Symbol=",Symbol()," Period=",Period());
if (EmailON==1) SendMail("BUY signal alert","BUY signal at Ask="+DoubleToStr(Ask,4)+", Bid="+DoubleToStr(Bid,4)+", Date="+TimeToStr(CurTime(),TIME_DATE)+" "+TimeHour(CurTime())+":"+TimeMinute(CurTime())+" Symbol="+Symbol()+" Period="+Period());
tmp = CurTime() + (Period()-MathMod(Minute(),Period()))*60;
GlobalVariableSet("AlertTime"+Symbol()+Period(),tmp);
GlobalVariableSet("SignalType"+Symbol()+Period(),OP_SELL);
}
return(0);
}
//+------------------------------------------------------------------+
Comments