SmartATR/SmartATR.mq5

233 lines
8.8 KiB
MQL5
Raw Permalink Normal View History

2025-07-20 08:02:23 +00:00
//+------------------------------------------------------------------+
//| SmartATR MT5 - Adaptive, Volume & News-Weighted ATR |
//| Project: SmartATR MT5 (Open Source, MIT License) |
//| Author: Steve Rosenstock & Community |
//| Repository: https://forge.mql5.io/steverosenstock/SmartATR |
//| Git: https://forge.mql5.io/steverosenstock/SmartATR.git |
//+------------------------------------------------------------------+
#property copyright "Steve Rosenstock & Community"
#property link "https://forge.mql5.io/steverosenstock/SmartATR"
#property version "1.0"
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_plots 2
#property indicator_label1 "SmartATR"
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrDodgerBlue
#property indicator_width1 2
#property indicator_label2 "News Event Overlay"
#property indicator_type2 DRAW_HISTOGRAM
#property indicator_color2 clrOrangeRed
#property indicator_width2 3
//--- INPUT PARAMETERS
input int ATR_Period = 14; // Initial ATR period (used for first calculation, adaptively changes)
input bool Adaptive_Mode = true; // Enable adaptive period (dynamic lookback)
input int Min_Period = 7; // Minimum ATR period (adaptive mode)
input int Max_Period = 28; // Maximum ATR period (adaptive mode)
input bool Volume_Filter = true; // Weight True Range by volume
input bool News_Filter = true; // Weight True Range by economic news events (MT5 Calendar)
input double Alert_Threshold= 2.0; // Multiplier: alert if ATR exceeds this factor of average
input bool Enable_Alerts = true; // Enable pop-up & sound alerts on high volatility
//--- BUFFERS
double SmartATRBuffer[]; // Main SmartATR output
double NewsBarBuffer[]; // For chart overlays on news events
//--- GLOBALS
int current_period; // Adaptive ATR period in use
double avgVolume = 0; // Rolling average volume for weighting
datetime lastAlertTime = 0; // For alert throttling
//+------------------------------------------------------------------+
//| INIT: Buffers & Setup |
//+------------------------------------------------------------------+
int OnInit()
{
SetIndexBuffer(0, SmartATRBuffer, INDICATOR_DATA);
SetIndexBuffer(1, NewsBarBuffer, INDICATOR_DATA);
PlotIndexSetString(0, PLOT_LABEL, "SmartATR");
PlotIndexSetString(1, PLOT_LABEL, "News Event Overlay");
IndicatorSetInteger(INDICATOR_DIGITS, 2);
ArrayInitialize(SmartATRBuffer, 0.0);
ArrayInitialize(NewsBarBuffer, 0.0);
Print("SmartATR MT5 initialized! Project: https://forge.mql5.io/steverosenstock/SmartATR");
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| MAIN CALCULATION: SmartATR |
//+------------------------------------------------------------------+
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 < Max_Period+2)
return(0);
int start = Max_Period; // avoid lookback errors
//--- average volume calculation for weighting
int volWindow = 20;
double volSum = 0;
for(int i=0; i<volWindow && i<rates_total; i++)
volSum += tick_volume[i];
avgVolume = volSum / MathMax(volWindow,1);
//--- rolling ATR mean for alerts
double rollingATRmean = 0.0;
int rollingWindow = 50;
for(int i=0; i<rollingWindow && i<rates_total; i++)
rollingATRmean += SmartATRBuffer[i];
rollingATRmean = rollingATRmean / MathMax(rollingWindow,1);
//--- MAIN LOOP
for(int i=start; i<rates_total; i++)
{
// 1. True Range Calculation
double tr1 = high[i] - low[i];
double tr2 = MathAbs(high[i] - close[i-1]);
double tr3 = MathAbs(low[i] - close[i-1]);
double trueRange = MathMax(tr1, MathMax(tr2, tr3));
// 2. Volume Weighting
double vol_weight = 1.0;
if(Volume_Filter)
{
if(tick_volume[i] > avgVolume)
vol_weight = 1.2;
else if(tick_volume[i] < avgVolume*0.5)
vol_weight = 0.7;
}
// 3. News Weighting (MT5 Calendar)
double news_weight = 1.0;
bool newsDetected = false;
if(News_Filter)
{
newsDetected = IsEconomicNewsEvent(time[i]);
if(newsDetected)
{
news_weight = 1.5;
NewsBarBuffer[i] = trueRange; // draw histogram at bar height
}
else
NewsBarBuffer[i] = 0.0;
}
else
NewsBarBuffer[i] = 0.0;
// 4. Adaptive ATR period
if(Adaptive_Mode)
{
int window = 20;
double localTRsum = 0;
for(int j=1; j<=window && i-j>=0; j++)
{
double ltr1 = high[i-j] - low[i-j];
double ltr2 = MathAbs(high[i-j] - close[i-j-1]);
double ltr3 = MathAbs(low[i-j] - close[i-j-1]);
double ltr = MathMax(ltr1, MathMax(ltr2,ltr3));
localTRsum += ltr;
}
double localTRmean = localTRsum / window;
if(trueRange > localTRmean*1.5)
current_period = MathMax(Min_Period, current_period-1);
else if(trueRange < localTRmean*0.7)
current_period = MathMin(Max_Period, current_period+1);
// else keep as is
}
else
current_period = ATR_Period;
// 5. SmartATR Calculation (EMA-like smoothing)
if(i==start)
SmartATRBuffer[i] = trueRange * vol_weight * news_weight;
else
SmartATRBuffer[i] = (SmartATRBuffer[i-1]*(current_period-1) + trueRange*vol_weight*news_weight) / current_period;
// 6. Alerts for High Volatility
if(Enable_Alerts && SmartATRBuffer[i] > rollingATRmean*Alert_Threshold)
{
// Only alert once per bar!
if(lastAlertTime != time[i])
{
string msg = StringFormat("SmartATR ALERT: Volatility Spike at %s! ATR = %.5f (%.2fx mean)\nProject: https://forge.mql5.io/steverosenstock/SmartATR",
TimeToString(time[i]), SmartATRBuffer[i], SmartATRBuffer[i]/rollingATRmean);
Alert(msg);
lastAlertTime = time[i];
}
}
}
return(rates_total);
}
//+------------------------------------------------------------------+
//| News Event Detection (MT5 Calendar) |
//| Uses MQL5 built-in economic news database. |
//| Returns true if news event detected for the bar's time. |
//+------------------------------------------------------------------+
bool IsEconomicNewsEvent(datetime bartime)
{
MqlCalendarValue news[];
datetime fromTime = bartime - 60; // look 1 min before bar
datetime toTime = bartime + 60; // and 1 min after
int count = CalendarValueHistory(news, fromTime, toTime);
if(count>0)
{
// Check if any high/medium-impact event exists
for(int i=0; i<count; i++)
{
if(news[i].impact>=CALENDAR_IMPORTANCE_MEDIUM)
return(true);
}
}
return(false);
}
//+------------------------------------------------------------------+
//| --- DEVELOPER NOTES & EXTENSION HOOKS --- |
//| |
//| - SmartATRBuffer[] holds the final ATR output, use in EAs etc. |
//| - NewsBarBuffer[] overlays colored bars on news-event candles |
//| - You can extend IsEconomicNewsEvent() to add more logic |
//| - Adaptive period logic can be improved for other markets |
//| - For more overlays: add custom graphics via OnChartEvent |
//| - For multi-symbol operation: adapt buffer logic as needed |
//+------------------------------------------------------------------+
/*
README FOR DEVELOPERS
SmartATR MT5 is a fully open-source, community-friendly, adaptive ATR indicator for MetaTrader 5.
It combines classic ATR with volume weighting, news sensitivity (using the native MT5 economic calendar), and an adaptive lookback window.
- Ready for plug-and-play use in all markets.
- All main settings are input parameters.
- All calculation logic is fully documented and extensible.
- Alerts and chart overlays are included.
Contributions, improvements and bugfixes are highly encouraged!
- Project home: https://forge.mql5.io/steverosenstock/SmartATR
- Repository: https://forge.mql5.io/steverosenstock/SmartATR.git
License: MIT
Author: Steve Rosenstock & Community
*/