Plus if you want to take it further i prepared Version 3 as well.
level, we need to address the most common issues algorithmic traders face: Signal Spam (multiple arrows firing in a row), Bad Context (trading against the macro trend), and Static Visuals (arrows getting buried inside large candles on higher timeframes).
Dynamic ATR Arrow Placement: Instead of fixed pips (which look huge on the 1-Minute chart and invisible on the Daily chart), this version uses the Average True Range (ATR) to calculate exactly how far above/below the candle to place the arrow. It perfectly adapts to any timeframe.
I've added an optional 200 EMA Trend Filter. The indicator will block Buy signals in a macro downtrend and block Sell signals in a macro uptrend, drastically increasing your win rate.
It now requires a "fresh" signal. If the price hovers near the EMA for 5 candles, you won't get 5 arrows in a row. It only prints the first valid setup.
It automatically generates a sleek, non-intrusive dashboard in the corner of your chart showing the live Trend, RSI value, and Proximity status in real-time.
Code: Select all
//+------------------------------------------------------------------+
//| MomentumPivot_EliteAlert.mq4 |
//| Upgraded to Institutional Level |
//+------------------------------------------------------------------+
#property copyright "YourForumName"
#property link "http://yourforumlink.com"
#property version "3.00"
#property strict
#property description "Elite Momentum Pivot with ATR Placement, Trend Filtering, and HUD."
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_plots 2
//--- Plot Settings: Buy Signal
#property indicator_type1 DRAW_ARROW
#property indicator_color1 clrMediumSeaGreen
#property indicator_width1 2
#property indicator_label1 "Buy Signal"
//--- Plot Settings: Sell Signal
#property indicator_type2 DRAW_ARROW
#property indicator_color2 clrCrimson
#property indicator_width2 2
#property indicator_label2 "Sell Signal"
//--- Enums for User Interface
enum ENUM_SIGNAL_BAR {
SIGNAL_CLOSED_BAR = 1, // Confirmed Signal (Bar 1 - Recommended)
SIGNAL_CURRENT_BAR = 0 // Repainting Signal (Bar 0 - Live)
};
//--- Input Parameters ---
sinput string sec1 = "--- Core Strategy Settings ---";
input int FastEMA_Period = 9; // Fast EMA Period
input int SlowEMA_Period = 21; // Slow EMA Period
input int RSI_Period = 14; // RSI Period
input int RSI_UpperLimit = 60; // RSI Upper Threshold (Sell)
input int RSI_LowerLimit = 40; // RSI Lower Threshold (Buy)
input double ProximityPips = 2.5; // Distance to Slow EMA (in Pips)
sinput string sec2 = "--- Elite Filters ---";
input bool UseTrendFilter = true; // Use Macro Trend Filter
input int Trend_EMA = 200; // Macro Trend EMA Period
input bool PreventSpam = true; // Prevent consecutive identical signals
sinput string sec3 = "--- Visuals & Dashboard ---";
input double ATR_Multiplier = 0.5; // Arrow distance from candle (ATR based)
input bool ShowHUD = true; // Show On-Chart Dashboard
sinput string sec4 = "--- Alert Settings ---";
input ENUM_SIGNAL_BAR AlertBar= SIGNAL_CLOSED_BAR; // Alert Trigger Candle
input bool EnableAlerts = true; // Enable Pop-up Alerts
input bool EnablePush = true; // Enable Push Notifications
input bool EnableEmail = false; // Enable Email Alerts
//--- Buffers & Globals
double BuyBuffer[];
double SellBuffer[];
double pipMultiplier;
datetime lastAlertTime;
int lastSignalDirection = 0; // 1 for Buy, -1 for Sell
//+------------------------------------------------------------------+
//| Initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
SetIndexBuffer(0, BuyBuffer);
SetIndexStyle(0, DRAW_ARROW);
SetIndexArrow(0, 233); // Up Arrow
SetIndexEmptyValue(0, EMPTY_VALUE);
SetIndexBuffer(1, SellBuffer);
SetIndexStyle(1, DRAW_ARROW);
SetIndexArrow(1, 234); // Down Arrow
SetIndexEmptyValue(1, EMPTY_VALUE);
IndicatorShortName("Elite Pivot HUD");
pipMultiplier = (_Digits == 3 || _Digits == 5) ? _Point * 10 : _Point;
return(INIT_SUCCESS);
}
//+------------------------------------------------------------------+
//| De-Initialization function (Clean up chart) |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
ObjectsDeleteAll(0, "HUD_"); // Remove dashboard when indicator is removed
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
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 < Trend_EMA) return(0); // Wait for enough data
int limit = rates_total - prev_calculated;
if(limit > 1) {
limit = rates_total - 1;
ArrayInitialize(BuyBuffer, EMPTY_VALUE);
ArrayInitialize(SellBuffer, EMPTY_VALUE);
lastSignalDirection = 0;
}
// Main historical and live loop
for(int i = limit; i >= 0; i--)
{
// 1. Fetch Indicators
double fastEMA = iMA(Symbol(), 0, FastEMA_Period, 0, MODE_EMA, PRICE_CLOSE, i);
double slowEMA = iMA(Symbol(), 0, SlowEMA_Period, 0, MODE_EMA, PRICE_CLOSE, i);
double trendEMA = iMA(Symbol(), 0, Trend_EMA, 0, MODE_EMA, PRICE_CLOSE, i);
double rsiValue = iRSI(Symbol(), 0, RSI_Period, PRICE_CLOSE, i);
double atrValue = iATR(Symbol(), 0, 14, i); // Used for dynamic arrow placement
// 2. Logic & Filters
bool isNearEMA = MathAbs(close[i] - slowEMA) <= (ProximityPips * pipMultiplier);
bool trendBullish = (!UseTrendFilter || close[i] > trendEMA);
bool trendBearish = (!UseTrendFilter || close[i] < trendEMA);
BuyBuffer[i] = EMPTY_VALUE;
SellBuffer[i] = EMPTY_VALUE;
// 3. Buy Signal Calculation
if(fastEMA > slowEMA && rsiValue < RSI_LowerLimit && isNearEMA && trendBullish)
{
if(!PreventSpam || lastSignalDirection != 1)
{
BuyBuffer[i] = low[i] - (atrValue * ATR_Multiplier); // Dynamic distance
lastSignalDirection = 1;
}
}
// 4. Sell Signal Calculation
if(fastEMA < slowEMA && rsiValue > RSI_UpperLimit && isNearEMA && trendBearish)
{
if(!PreventSpam || lastSignalDirection != -1)
{
SellBuffer[i] = high[i] + (atrValue * ATR_Multiplier); // Dynamic distance
lastSignalDirection = -1;
}
}
}
//--- Draw HUD on live bar ---
if(ShowHUD) UpdateHUD(close[0], iMA(Symbol(), 0, Trend_EMA, 0, MODE_EMA, PRICE_CLOSE, 0), iRSI(Symbol(), 0, RSI_Period, PRICE_CLOSE, 0));
//--- Alert Logic ---
if(EnableAlerts || EnablePush || EnableEmail)
{
int bar = (int)AlertBar;
if(prev_calculated > 0 && time[bar] != lastAlertTime)
{
if(BuyBuffer[bar] != EMPTY_VALUE) TriggerAlert("BUY", time[bar]);
else if(SellBuffer[bar] != EMPTY_VALUE) TriggerAlert("SELL", time[bar]);
}
}
return(rates_total);
}
//+------------------------------------------------------------------+
//| Helper: HUD Generation |
//+------------------------------------------------------------------+
void UpdateHUD(double currentPrice, double trendEMA, double currentRSI)
{
string trendText = (currentPrice > trendEMA) ? "BULLISH" : "BEARISH";
color trendColor = (currentPrice > trendEMA) ? clrMediumSeaGreen : clrCrimson;
if(!UseTrendFilter) { trendText = "DISABLED"; trendColor = clrDarkGray; }
DrawLabel("HUD_Bg", 1, 15, "g", clrDarkSlateGray, 70, "Webdings");
DrawLabel("HUD_Title", 1, 15, "Elite Momentum Pivot", clrWhite, 10, "Arial Bold");
DrawLabel("HUD_Trend", 1, 35, "Macro Trend: " + trendText, trendColor, 9, "Arial");
DrawLabel("HUD_RSI", 1, 50, StringFormat("Live RSI: %.1f", currentRSI), clrLightGray, 9, "Arial");
}
void DrawLabel(string name, int x, int y, string text, color clr, int size, string font)
{
if(ObjectFind(0, name) < 0)
{
ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);
ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_RIGHT_UPPER); // Top Right
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x + 150);
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
}
ObjectSetString(0, name, OBJPROP_TEXT, text);
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
ObjectSetInteger(0, name, OBJPROP_FONTSIZE, size);
ObjectSetString(0, name, OBJPROP_FONT, font);
}
//+------------------------------------------------------------------+
//| Custom Alert Trigger Function |
//+------------------------------------------------------------------+
void TriggerAlert(string signalType, datetime triggerTime)
{
string message = StringFormat("Elite Pivot [%s - %s]: %s Signal @ %g", Symbol(), EnumToString((ENUM_TIMEFRAMES)Period()), signalType, Close[0]);
if(EnableAlerts) Alert(message);
if(EnablePush) SendNotification(message);
if(EnableEmail) SendMail("Elite Pivot Alert", message);
lastAlertTime = triggerTime;
}
//+------------------------------------------------------------------+