MQL5 Implementation (ScalpingMomentum.mq5)
The MQL5 version utilizes indicator handles (iMA, iRSI) within OnInit() and dynamically copies buffer arrays into memory using CopyBuffer during the calculation loop to maximize execution speed.
Code: Select all
//+------------------------------------------------------------------+
//| ScalpingMomentumFilter.mq5 |
//+------------------------------------------------------------------+
#property copyright "Custom Indicator"
#property version "1.00"
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_plots 2
//--- Plot 1: Buy Signal
#property indicator_label1 "Buy Signal"
#property indicator_type1 DRAW_ARROW
#property indicator_color1 clrLime
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1
//--- Plot 2: Sell Signal
#property indicator_label2 "Sell Signal"
#property indicator_type2 DRAW_ARROW
#property indicator_color2 clrRed
#property indicator_style2 STYLE_SOLID
#property indicator_width2 1
//--- Input Parameters
input int InpEmaPeriod = 200; // Trend EMA Period
input int InpRsiPeriod = 14; // RSI Period
input int InpRsiOverbought = 70; // RSI Overbought Level
input int InpRsiOversold = 30; // RSI Oversold Level
//--- Indicator Buffers
double BuyBuffer[];
double SellBuffer[];
//--- Core Handles and Arrays
int emaHandle;
int rsiHandle;
double emaArr[];
double rsiArr[];
//--- Alert Timer
datetime lastAlertTime = 0;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Bind buffers
SetIndexBuffer(0, BuyBuffer, INDICATOR_DATA);
PlotIndexSetInteger(0, PLOT_ARROW, 233); // Up Arrow
PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0.0);
SetIndexBuffer(1, SellBuffer, INDICATOR_DATA);
PlotIndexSetInteger(1, PLOT_ARROW, 234); // Down Arrow
PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, 0.0);
// Initialize Indicator Handles
emaHandle = iMA(_Symbol, _Period, InpEmaPeriod, 0, MODE_EMA, PRICE_CLOSE);
if(emaHandle == INVALID_HANDLE) { Print("EMA handle error"); return(INIT_FAILED); }
rsiHandle = iRSI(_Symbol, _Period, InpRsiPeriod, PRICE_CLOSE);
if(rsiHandle == INVALID_HANDLE) { Print("RSI handle error"); return(INIT_FAILED); }
// Set array indexing (0 = current forming candle)
ArraySetAsSeries(BuyBuffer, true);
ArraySetAsSeries(SellBuffer, true);
ArraySetAsSeries(emaArr, true);
ArraySetAsSeries(rsiArr, true);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| 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[])
{
// Wait for sufficient data
if(rates_total < InpEmaPeriod) return 0;
ArraySetAsSeries(time, true);
ArraySetAsSeries(low, true);
ArraySetAsSeries(high, true);
ArraySetAsSeries(close, true);
// Determine how much data needs updating
int to_copy = (prev_calculated == 0) ? rates_total : rates_total - prev_calculated + 1;
// Copy indicator data
if(CopyBuffer(emaHandle, 0, 0, to_copy, emaArr) <= 0) return 0;
if(CopyBuffer(rsiHandle, 0, 0, to_copy + 1, rsiArr) <= 0) return 0; // Request +1 to check the previous bar
int limit = to_copy - 1;
if(prev_calculated == 0) limit = rates_total - 2;
for(int i = limit; i >= 0; i--)
{
// Reset buffers
BuyBuffer[i] = 0.0;
SellBuffer[i] = 0.0;
double ema = emaArr[i];
double rsi = rsiArr[i];
double rsi_prev = rsiArr[i+1];
// Buy Entry Logic
if(close[i] > ema && rsi_prev < InpRsiOversold && rsi >= InpRsiOversold)
{
BuyBuffer[i] = low[i] - 10 * _Point;
}
// Sell Entry Logic
if(close[i] < ema && rsi_prev > InpRsiOverbought && rsi <= InpRsiOverbought)
{
SellBuffer[i] = high[i] + 10 * _Point;
}
// Fire alerts on closed candles (index 1)
if(i == 1)
{
if(BuyBuffer[1] != 0.0 && time[1] != lastAlertTime)
{
Alert(_Symbol, " [", EnumToString(_Period), "] Long Scalp Triggered");
lastAlertTime = time[1];
}
if(SellBuffer[1] != 0.0 && time[1] != lastAlertTime)
{
Alert(_Symbol, " [", EnumToString(_Period), "] Short Scalp Triggered");
lastAlertTime = time[1];
}
}
}
return(rates_total);
}
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.