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;
|
|
}
|
|
}
|
|
}
|
|
|