156 lines
5.8 KiB
MQL5
156 lines
5.8 KiB
MQL5
//+------------------------------------------------------------------+
| |||
//| MTF_Pullback_Strategy_v2.mq5 |
| |||
//| Copyright 2026, AlgoTrader peer |
| |||
//| https://www.mql5.com |
| |||
//+------------------------------------------------------------------+
| |||
#property copyright "Copyright 2026, AlgoTrader peer"
| |||
#property link "https://www.mql5.com"
| |||
#property version "2.00"
| |||
| |||
#include <Trade\Trade.mqh>
| |||
CTrade trade;
| |||
| |||
//--- Input parameters
| |||
input group "---- Risk Management ----"
| |||
input double InpLotSize = 0.1; // Lot Size
| |||
input int InpStopLossPips = 20; // Stop Loss in Pips
| |||
input int InpTakeProfitPips = 40; // Take Profit in Pips
| |||
input ulong InpMagicNumber = 123456; // EA Magic Number
| |||
| |||
input group "---- Filter Settings ----"
| |||
input int InpADXPeriod = 14; // ADX Period
| |||
input int InpADXThreshold = 25; // Ignore markets if ADX is below this
| |||
input int InpEMAPeriod = 200; // Trend Filter EMA Period
| |||
| |||
//--- Global variables
| |||
double pipsMultiplier;
| |||
datetime lastBarTime;
| |||
int adxHandle; // Handle for the ADX indicator
| |||
int emaHandle; // Handle for the H4 EMA indicator
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Expert initialization function |
| |||
//+------------------------------------------------------------------+
| |||
int OnInit()
| |||
{
| |||
if(_Digits == 3 || _Digits == 5) pipsMultiplier = 10 * _Point;
| |||
else pipsMultiplier = _Point;
| |||
| |||
trade.SetExpertMagicNumber(InpMagicNumber);
| |||
lastBarTime = 0;
| |||
| |||
// Initialize the ADX indicator on the M15 timeframe to spot local choppiness
| |||
adxHandle = iADX(_Symbol, PERIOD_M15, InpADXPeriod);
| |||
if(adxHandle == INVALID_HANDLE)
| |||
{
| |||
Print("Failed to create ADX indicator handle.");
| |||
return(INIT_FAILED);
| |||
}
| |||
| |||
// Initialize the 200 EMA on the H4 timeframe to capture the macro trend direction
| |||
emaHandle = iMA(_Symbol, PERIOD_H4, InpEMAPeriod, 0, MODE_EMA, PRICE_CLOSE);
| |||
if(emaHandle == INVALID_HANDLE)
| |||
{
| |||
Print("Failed to create H4 EMA indicator handle.");
| |||
return(INIT_FAILED);
| |||
}
| |||
| |||
return(INIT_SUCCEEDED);
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Expert deinitialization function |
| |||
//+------------------------------------------------------------------+
| |||
void OnDeinit(const int reason)
| |||
{
| |||
// Release indicator handles to free up system memory
| |||
IndicatorRelease(adxHandle);
| |||
IndicatorRelease(emaHandle);
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Expert tick function |
| |||
//+------------------------------------------------------------------+
| |||
void OnTick()
| |||
{
| |||
// 1. New Candle Filter (M15)
| |||
datetime currentBarTime = iTime(_Symbol, PERIOD_M15, 0);
| |||
if(currentBarTime == lastBarTime) return;
| |||
| |||
// 2. Check open positions
| |||
if(PositionsTotal() > 0)
| |||
{
| |||
for(int i=PositionsTotal()-1; i>=0; i--)
| |||
{
| |||
if(PositionGetSymbol(i) == _Symbol && PositionGetInteger(POSITION_MAGIC) == InpMagicNumber)
| |||
{
| |||
return;
| |||
}
| |||
}
| |||
}
| |||
| |||
// 3. Choppy Market Filter (Fetch current ADX values)
| |||
double adxValues[];
| |||
ArraySetAsSeries(adxValues, true);
| |||
if(CopyBuffer(adxHandle, MAIN_LINE, 1, 1, adxValues) < 1) return; // Read last closed M15 bar value
| |||
| |||
// If ADX is below our threshold (e.g. 25), market is ranging/choppy. Do not trade.
| |||
if(adxValues[0] < InpADXThreshold) return;
| |||
| |||
// 4. Macro Trend Filter (Fetch H4 200 EMA and Price)
| |||
double emaValues[];
| |||
MqlRates ratesH4Trend[];
| |||
ArraySetAsSeries(emaValues, true);
| |||
ArraySetAsSeries(ratesH4Trend, true);
| |||
| |||
if(CopyBuffer(emaHandle, 0, 1, 1, emaValues) < 1) return;
| |||
if(CopyRates(_Symbol, PERIOD_H4, 1, 1, ratesH4Trend) < 1) return;
| |||
| |||
bool isAbove200EMA = (ratesH4Trend[0].close > emaValues[0]);
| |||
| |||
// 5. Fetch Multi-Timeframe Candle Directions
| |||
MqlRates ratesH4[], ratesH1[], ratesM15[];
| |||
ArraySetAsSeries(ratesH4, true);
| |||
ArraySetAsSeries(ratesH1, true);
| |||
ArraySetAsSeries(ratesM15, true);
| |||
| |||
if(CopyRates(_Symbol, PERIOD_H4, 1, 1, ratesH4) < 1) return;
| |||
if(CopyRates(_Symbol, PERIOD_H1, 1, 1, ratesH1) < 1) return;
| |||
if(CopyRates(_Symbol, PERIOD_M15, 1, 1, ratesM15) < 1) return;
| |||
| |||
bool isH4Bullish = (ratesH4[0].close > ratesH4[0].open);
| |||
bool isH1Bullish = (ratesH1[0].close > ratesH1[0].open);
| |||
bool isM15Bullish = (ratesM15[0].close > ratesM15[0].open);
| |||
| |||
// 6. Strategy Rules (Now incorporating the 200 EMA filter)
| |||
// BUY: H4 Bullish, H1 Bearish Pullback, M15 Bullish Trigger AND Price must be above H4 200 EMA
| |||
bool buyCondition = (isH4Bullish && !isH1Bullish && isM15Bullish && isAbove200EMA);
| |||
| |||
// SELL: H4 Bearish, H1 Bullish Pullback, M15 Bearish Trigger AND Price must be below H4 200 EMA
| |||
bool sellCondition = (!isH4Bullish && isH1Bullish && !isM15Bullish && !isAbove200EMA);
| |||
| |||
// 7. Execution
| |||
if(buyCondition)
| |||
{
| |||
double askPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
| |||
double sl = askPrice - (InpStopLossPips * pipsMultiplier);
| |||
double tp = askPrice + (InpTakeProfitPips * pipsMultiplier);
| |||
| |||
if(trade.Buy(InpLotSize, _Symbol, askPrice, sl, tp, "Filtered Buy"))
| |||
{
| |||
lastBarTime = currentBarTime;
| |||
}
| |||
}
| |||
else if(sellCondition)
| |||
{
| |||
double bidPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
| |||
double sl = bidPrice + (InpStopLossPips * pipsMultiplier);
| |||
double tp = bidPrice - (InpTakeProfitPips * pipsMultiplier);
| |||
| |||
if(trade.Sell(InpLotSize, _Symbol, bidPrice, sl, tp, "Filtered Sell"))
| |||
{
| |||
lastBarTime = currentBarTime;
| |||
}
| |||
}
| |||
}
| |||
|