1
0
Fork 0
MACD_EA_Scalper/MACD_Scalper_EA.mq5

569 lines
37 KiB
MQL5
Raw Permalink Normal View History

2025-12-22 08:58:30 +00:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| MACD_Scalper_EA_v7.0.mq5 |
//| MACD Scalper Expert Advisor v7.0 - OPTIMIZED |
//| Improvements: Trend Filter, Risk Management, Better Signals |
//+------------------------------------------------------------------+
#property copyright "MACD Scalper Trading - v7.0"
#property link "https://www.mql5.com"
#property version "7.00"
#property strict
//+------------------------------------------------------------------+
//| INPUT PARAMETERS |
//+------------------------------------------------------------------+
//--- MACD INDICATOR
input int macdFastPeriod = 12; // MACD Fast EMA Period
input int macdSlowPeriod = 26; // MACD Slow EMA Period
input int macdSignalPeriod = 9; // MACD Signal Line Period
//--- STOCHASTIC INDICATOR (OPTIMIZED)
input int stochKPeriod = 14; // Stochastic K Period
input int stochDPeriod = 3; // Stochastic D Period
input int stochSlowing = 3; // Stochastic Slowing
input int stochOverbought = 85; // Overbought Level (WAS 80, NOW MORE EXTREME)
input int stochOversold = 15; // Oversold Level (WAS 20, NOW MORE EXTREME)
//--- TREND FILTER (NEW)
input int emaTrendPeriod = 50; // EMA Trend Confirmation Period
input double macdHistStrength = 0.0001; // Min MACD Histogram strength
//--- MONEY MANAGEMENT (OPTIMIZED)
input double lotSize = 0.05; // Lot Size (REDUCED from 0.1 for risk management)
input int slPips = 70; // Stop Loss (pips) (WAS 120, NOW TIGHTER)
input int tpPips = 150; // Take Profit (pips) (WAS 120, NOW LARGER - 1:2.14 R:R)
input int maxDailyLoss = 500; // Max Daily Loss in USD (NEW)
//--- FILTERS
input int maxSpread = 20; // Maximum Spread (pips)
input int maxSlippage = 15; // Maximum Slippage (pips)
input ulong magicNumber = 12347; // Magic Number (UPDATED for v7.0)
//--- INDICATOR INITIALIZATION
input int minBarsForMACD = 35; // Minimum bars for MACD
input int minBarsForStoch = 20; // Minimum bars for Stochastic
input int minBarsForEMA = 55; // Minimum bars for EMA
//--- TRADING HOURS FILTER (NEW)
input int startHour = 2; // Start trading hour (London open)
input int endHour = 22; // End trading hour
input bool useTradingHours = true; // Enable trading hours filter
//+------------------------------------------------------------------+
//| GLOBAL VARIABLES |
//+------------------------------------------------------------------+
int macdHandle = INVALID_HANDLE; // MACD Indicator Handle
int stochHandle = INVALID_HANDLE; // Stochastic Indicator Handle
int emaHandle = INVALID_HANDLE; // EMA Trend Indicator Handle (NEW)
int atrHandle = INVALID_HANDLE; // ATR Volatility Handle (NEW)
double macdMain[3]; // MACD Main Line (Buffer 0)
double macdSignal[3]; // MACD Signal Line (Buffer 1)
double macdHist[3]; // MACD Histogram (Manual: Main - Signal)
double stochK[3]; // Stochastic K Buffer (3 bars)
double emaTrend[2]; // EMA Trend (2 bars) (NEW)
double atrValue[2]; // ATR Value (2 bars) (NEW)
bool isInitialized = false; // Initialization Flag
bool indicatorsReady = false; // Indicators Ready Flag
int tradeCount = 0; // Total trades opened
double dailyProfit = 0; // Daily Profit Tracker (NEW)
datetime lastDayReset = 0; // Last daily reset time (NEW)
//+------------------------------------------------------------------+
//| HELPER FUNCTIONS |
//+------------------------------------------------------------------+
/// Get current Bid price
double GetBid()
{
return SymbolInfoDouble(Symbol(), SYMBOL_BID);
}
/// Get current Ask price
double GetAsk()
{
return SymbolInfoDouble(Symbol(), SYMBOL_ASK);
}
/// Get current Spread in pips
int GetSpread()
{
return (int)((GetAsk() - GetBid()) / Point());
}
/// Check if spread is acceptable
bool IsSpreadOK()
{
return GetSpread() <= maxSpread;
}
/// Check if trading within allowed hours (NEW) - FIXED
bool IsTradingHours()
{
if(!useTradingHours)
return true;
datetime currentTime = TimeCurrent();
MqlDateTime timeStruct;
TimeToStruct(currentTime, timeStruct);
int hour = timeStruct.hour;
return (hour >= startHour && hour < endHour);
}
/// Update daily profit tracker (NEW) - FIXED
void UpdateDailyProfit()
{
datetime currentTime = TimeCurrent();
MqlDateTime timeStruct;
TimeToStruct(currentTime, timeStruct);
// Get start of day (00:00:00)
datetime dayStart = currentTime - (timeStruct.hour * 3600 + timeStruct.min * 60 + timeStruct.sec);
if(lastDayReset != dayStart)
{
lastDayReset = dayStart;
dailyProfit = 0;
Print("' Daily profit reset: ", TimeToString(currentTime));
}
// Calculate current day P&L from all positions
dailyProfit = 0;
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
if(!PositionGetTicket(i)) continue;
if(PositionGetString(POSITION_SYMBOL) == Symbol() &&
PositionGetInteger(POSITION_MAGIC) == magicNumber)
{
double profit = PositionGetDouble(POSITION_PROFIT);
dailyProfit += profit;
}
}
}
/// Check daily loss limit (NEW)
bool IsDailyLossOK()
{
UpdateDailyProfit();
if(dailyProfit < -maxDailyLoss)
{
Print("<00>&<0F> Daily loss limit reached: ", DoubleToString(dailyProfit, 2), " USD");
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| INDICATOR UPDATE FUNCTION |
//+------------------------------------------------------------------+
/// Update indicator buffers - v7.0 with all filters
bool UpdateIndicators()
{
// Check handles validity
if(macdHandle == INVALID_HANDLE || stochHandle == INVALID_HANDLE ||
emaHandle == INVALID_HANDLE || atrHandle == INVALID_HANDLE)
return false;
// Check if indicators are calculated
if(BarsCalculated(macdHandle) < minBarsForMACD ||
BarsCalculated(stochHandle) < minBarsForStoch ||
BarsCalculated(emaHandle) < minBarsForEMA ||
BarsCalculated(atrHandle) < minBarsForEMA)
return false;
// Copy MACD Main Line (Buffer 0) - 3 bars
if(CopyBuffer(macdHandle, 0, 0, 3, macdMain) < 3)
return false;
// Copy MACD Signal Line (Buffer 1) - 3 bars
if(CopyBuffer(macdHandle, 1, 0, 3, macdSignal) < 3)
return false;
// Calculate MACD Histogram MANUALLY (Main - Signal)
for(int i = 0; i < 3; i++)
{
macdHist[i] = macdMain[i] - macdSignal[i];
}
// Copy Stochastic K (Buffer 0) - 3 bars
if(CopyBuffer(stochHandle, 0, 0, 3, stochK) < 3)
return false;
// Copy EMA Trend (Buffer 0) - 2 bars (NEW)
if(CopyBuffer(emaHandle, 0, 0, 2, emaTrend) < 2)
return false;
// Copy ATR Value (Buffer 0) - 2 bars (NEW)
if(CopyBuffer(atrHandle, 0, 0, 2, atrValue) < 2)
return false;
return true;
}
//+------------------------------------------------------------------+
//| SIGNAL CHECKING FUNCTIONS |
//+------------------------------------------------------------------+
/// Check for BUY signal (Enhanced with trend filter + volatility)
bool CheckBuySignal()
{
// FILTER 1: Trading hours check (NEW)
if(!IsTradingHours())
return false;
// FILTER 2: Daily loss limit (NEW)
if(!IsDailyLossOK())
return false;
// FILTER 3: Spread check
if(!IsSpreadOK())
return false;
// FILTER 4: Trend confirmation - Price above EMA50 (NEW)
double bid = GetBid();
if(bid <= emaTrend[1])
return false; // Not in uptrend
// FILTER 5: MACD Momentum strength check (NEW)
double macdHistAbs = MathAbs(macdHist[1]);
if(macdHistAbs < macdHistStrength)
return false; // Momentum too weak
// FILTER 6: MACD Momentum: crossed below zero <EFBFBD>! above zero
if(!(macdHist[2] <= 0 && macdHist[1] > 0))
return false;
// FILTER 7: Stochastic: in oversold area AND rising (OPTIMIZED)
// Now uses stricter levels: oversold < 15
if(!(stochK[2] < stochOversold && stochK[1] > stochK[2]))
return false; // Stoch not rising from extreme oversold
// FILTER 8: Volatility check - ATR sanity (NEW)
// Only trade if volatility is reasonable
if(atrValue[1] < 0.0005 * GetAsk())
return false; // Too low volatility
return true;
}
/// Check for SELL signal (Enhanced with trend filter + volatility)
bool CheckSellSignal()
{
// FILTER 1: Trading hours check (NEW)
if(!IsTradingHours())
return false;
// FILTER 2: Daily loss limit (NEW)
if(!IsDailyLossOK())
return false;
// FILTER 3: Spread check
if(!IsSpreadOK())
return false;
// FILTER 4: Trend confirmation - Price below EMA50 (NEW)
double ask = GetAsk();
if(ask >= emaTrend[1])
return false; // Not in downtrend
// FILTER 5: MACD Momentum strength check (NEW)
double macdHistAbs = MathAbs(macdHist[1]);
if(macdHistAbs < macdHistStrength)
return false; // Momentum too weak
// FILTER 6: MACD Momentum: crossed above zero <EFBFBD>! below zero
if(!(macdHist[2] >= 0 && macdHist[1] < 0))
return false;
// FILTER 7: Stochastic: in overbought area AND falling (OPTIMIZED)
// Now uses stricter levels: overbought > 85
if(!(stochK[2] > stochOverbought && stochK[1] < stochK[2]))
return false; // Stoch not falling from extreme overbought
// FILTER 8: Volatility check - ATR sanity (NEW)
if(atrValue[1] < 0.0005 * GetAsk())
return false; // Too low volatility
return true;
}
//+------------------------------------------------------------------+
//| ORDER FUNCTIONS |
//+------------------------------------------------------------------+
/// Check if position TP is reached
bool IsTPReached()
{
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
if(!PositionGetTicket(i)) continue;
if(PositionGetString(POSITION_SYMBOL) != Symbol() ||
PositionGetInteger(POSITION_MAGIC) != magicNumber) continue;
ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
double currentPrice = (posType == POSITION_TYPE_BUY) ? GetBid() : GetAsk();
if(posType == POSITION_TYPE_BUY)
{
if(currentPrice >= openPrice + (tpPips * Point()))
return true;
}
else
{
if(currentPrice <= openPrice - (tpPips * Point()))
return true;
}
}
return false;
}
/// Close all positions
void CloseAllPositions()
{
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
if(!PositionGetTicket(i)) continue;
if(PositionGetString(POSITION_SYMBOL) != Symbol() ||
PositionGetInteger(POSITION_MAGIC) != magicNumber) continue;
ulong ticket = PositionGetInteger(POSITION_TICKET);
ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
double closingProfit = PositionGetDouble(POSITION_PROFIT);
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_DEAL;
request.symbol = Symbol();
request.type = (posType == POSITION_TYPE_BUY) ? ORDER_TYPE_SELL : ORDER_TYPE_BUY;
request.position = ticket;
request.deviation = maxSlippage;
request.comment = "Close by TP";
request.type_filling = ORDER_FILLING_IOC;
if(!OrderSend(request, result))
{
Print("L' Failed to close position: ", GetLastError());
}
else
{
Print("' Position closed with profit: ", DoubleToString(closingProfit, 2), " USD");
}
}
}
/// Open BUY order
void OpenBuyOrder()
{
if(!IsSpreadOK())
return;
double ask = GetAsk();
double sl = ask - (slPips * Point());
double tp = ask + (tpPips * Point());
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_DEAL;
request.type = ORDER_TYPE_BUY;
request.symbol = Symbol();
request.volume = lotSize;
request.price = ask;
request.sl = sl;
request.tp = tp;
request.deviation = maxSlippage;
request.magic = magicNumber;
request.comment = "MACD Scalper v7.0 BUY";
request.type_filling = ORDER_FILLING_IOC;
if(OrderSend(request, result))
{
tradeCount++;
Print("' BUY #", tradeCount, " @ ", DoubleToString(ask, Digits()),
" SL=", DoubleToString(sl, Digits()), " TP=", DoubleToString(tp, Digits()),
" R:R=1:", DoubleToString((double)tpPips / (double)slPips, 2));
}
else
{
Print("L' Failed to open BUY: ", GetLastError());
}
}
/// Open SELL order
void OpenSellOrder()
{
if(!IsSpreadOK())
return;
double bid = GetBid();
double sl = bid + (slPips * Point());
double tp = bid - (tpPips * Point());
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_DEAL;
request.type = ORDER_TYPE_SELL;
request.symbol = Symbol();
request.volume = lotSize;
request.price = bid;
request.sl = sl;
request.tp = tp;
request.deviation = maxSlippage;
request.magic = magicNumber;
request.comment = "MACD Scalper v7.0 SELL";
request.type_filling = ORDER_FILLING_IOC;
if(OrderSend(request, result))
{
tradeCount++;
Print("' SELL #", tradeCount, " @ ", DoubleToString(bid, Digits()),
" SL=", DoubleToString(sl, Digits()), " TP=", DoubleToString(tp, Digits()),
" R:R=1:", DoubleToString((double)tpPips / (double)slPips, 2));
}
else
{
Print("L' Failed to open SELL: ", GetLastError());
}
}
//+------------------------------------------------------------------+
//| INITIALIZATION FUNCTION |
//+------------------------------------------------------------------+
int OnInit()
{
// Create MACD indicator
macdHandle = iMACD(Symbol(), Period(), macdFastPeriod, macdSlowPeriod,
macdSignalPeriod, PRICE_CLOSE);
if(macdHandle == INVALID_HANDLE)
{
Print("L' Error creating MACD");
return INIT_FAILED;
}
// Create Stochastic indicator
stochHandle = iStochastic(Symbol(), Period(), stochKPeriod, stochDPeriod,
stochSlowing, MODE_SMA, STO_LOWHIGH);
if(stochHandle == INVALID_HANDLE)
{
Print("L' Error creating Stochastic");
return INIT_FAILED;
}
// Create EMA Trend indicator (NEW)
emaHandle = iMA(Symbol(), Period(), emaTrendPeriod, 0, MODE_EMA, PRICE_CLOSE);
if(emaHandle == INVALID_HANDLE)
{
Print("L' Error creating EMA");
return INIT_FAILED;
}
// Create ATR indicator (NEW)
atrHandle = iATR(Symbol(), Period(), 14);
if(atrHandle == INVALID_HANDLE)
{
Print("L' Error creating ATR");
return INIT_FAILED;
}
// Set arrays as series
ArraySetAsSeries(macdMain, true);
ArraySetAsSeries(macdSignal, true);
ArraySetAsSeries(macdHist, true);
ArraySetAsSeries(stochK, true);
ArraySetAsSeries(emaTrend, true);
ArraySetAsSeries(atrValue, true);
isInitialized = true;
Print("' EA v7.0 Initialized Successfully!");
Print("' Improvements: EMA Trend, ATR Volatility, Daily Loss Limit");
Print("' Optimized Stoch Levels: Oversold=", stochOversold, " Overbought=", stochOverbought);
Print("' Better R:R Ratio: 1:", DoubleToString((double)tpPips / (double)slPips, 2));
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| DEINITIALIZATION FUNCTION |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
// Release indicator handles
if(macdHandle != INVALID_HANDLE)
IndicatorRelease(macdHandle);
if(stochHandle != INVALID_HANDLE)
IndicatorRelease(stochHandle);
if(emaHandle != INVALID_HANDLE)
IndicatorRelease(emaHandle);
if(atrHandle != INVALID_HANDLE)
IndicatorRelease(atrHandle);
Print("' EA v7.0 Deinitialized");
Print("' Total trades: ", tradeCount);
Print("' Final daily profit: ", DoubleToString(dailyProfit, 2), " USD");
}
//+------------------------------------------------------------------+
//| MAIN TRADING LOOP |
//+------------------------------------------------------------------+
void OnTick()
{
if(!isInitialized)
return;
// Update indicators
if(!UpdateIndicators())
{
if(!indicatorsReady)
return;
}
else if(!indicatorsReady)
{
indicatorsReady = true;
Print("' Indicators ready! Starting to trade...");
}
if(!indicatorsReady)
return;
// Check if position exists
bool hasPosition = false;
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
if(!PositionGetTicket(i)) continue;
if(PositionGetString(POSITION_SYMBOL) == Symbol() &&
PositionGetInteger(POSITION_MAGIC) == magicNumber)
{
hasPosition = true;
break;
}
}
// Close position if TP reached
if(hasPosition && IsTPReached())
CloseAllPositions();
// Check entry signals (only if no position)
if(!hasPosition)
{
if(CheckBuySignal())
OpenBuyOrder();
else if(CheckSellSignal())
OpenSellOrder();
}
}
//+------------------------------------------------------------------+
//| END OF EXPERT ADVISOR v7.0 - OPTIMIZED & IMPROVED |
//+------------------------------------------------------------------+