Summary: EURUSD TrendHarmony EA is an MQL4 expert advisor combining 200 EMA trend filter and Stochastic oscillator for precise entries. Suitable for H1 timeframe with fixed risk management.




EURUSD TrendHarmony EA is engineered for stable operation on EURUSD by combining trend direction filtering with stochastic oscillator mean-reversion entries. The EA trades only in the direction of the 200-period EMA on H1, then uses Stochastic(5,3,3) to identify oversold/overbought conditions for entry. ATR-based stop loss adapts to market volatility, and a time filter avoids low-liquidity sessions. The system limits itself to one trade at a time with daily loss protection.

Recommended Timeframe: H1
Trading Logic:
1. Trend Filter: Price above 200 EMA → long only; below 200 EMA → short only.
2. Stochastic Entry: Main line crosses above 20 (oversold) for buys or below 80 (overbought) for sells.
3. Confirmation: Wait for stochastic crossover and bar close in trend direction.
4. Risk Management: ATR-based stop loss (1.8x ATR), take profit at 3.6x ATR (2:1 ratio), max spread 25 points, daily loss limit 5%.

```mql4
//+------------------------------------------------------------------+
//| EURUSTrendHarmonyEA.mq4 |
//+------------------------------------------------------------------+
#property copyright ""
#property link ""
#property version "1.00"
#property strict

//--- input parameters with comments
input double LotSize = 0.01; // Fixed lot size (0.01 per trade)
input int TrendMAPeriod = 200; // EMA period for trend direction filter
input int StochasticK = 5; // Stochastic %K period
input int StochasticD = 3; // Stochastic %D period
input int StochasticSlow = 3; // Stochastic slowing factor
input int OversoldLevel = 20; // Stochastic oversold level (buy zone)
input int OverboughtLevel = 80; // Stochastic overbought level (sell zone)
input int ATRPeriod = 14; // ATR period for dynamic stop loss
input double ATRStopMultiplier = 1.8; // Stop loss as multiple of ATR
input double ATRTakeMultiplier = 3.6; // Take profit as multiple of ATR (2:1 ratio)
input int MagicNumber = 202416; // Unique EA identifier
input int MaxSpread = 25; // Maximum allowed spread in points
input double DailyLossLimit = 5.0; // Daily loss limit as percentage of balance
input bool UseFridayClose = true; // Close trades before Friday 21:00 GMT
input bool UseLondonFilter = true; // Trade only during London/NY session (8-20 GMT)

//--- global variables
double dailyStartBalance = 0;
datetime lastBarTime = 0;
bool fridayCloseExecuted = false;

//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
dailyStartBalance = AccountBalance();
lastBarTime = 0;
fridayCloseExecuted = false;
return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
Comment("");
}

//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Daily equity protection
double currentEquity = AccountEquity();
double lossPercent = (dailyStartBalance - currentEquity) / dailyStartBalance * 100;
if(lossPercent >= DailyLossLimit)
{
Comment("Daily loss limit reached. No new trades.");
return;
}

// Friday close before weekend
if(UseFridayClose && !fridayCloseExecuted)
{
datetime currentTime = TimeCurrent();
if(TimeDayOfWeek(currentTime) == 5 && TimeHour(currentTime) >= 21)
{
CloseAllOrders();
fridayCloseExecuted = true;
return;
}
if(TimeDayOfWeek(currentTime) != 5)
fridayCloseExecuted = false;
}

// London/NY session filter (8:00 - 20:00 GMT)
if(UseLondonFilter)
{
int hourGMT = TimeHour(TimeCurrent());
if(hourGMT < 8 || hourGMT >= 20)
{
Comment("Outside London/NY session. No trades.");
return;
}
}

// Spread filter
if(MarketInfo(Symbol(), MODE_SPREAD) > MaxSpread)
{
Comment("Spread too high: ", MarketInfo(Symbol(), MODE_SPREAD));
return;
}

// New bar logic (H1)
if(Time[0] == lastBarTime)
return;
lastBarTime = Time[0];

// Check for existing position
if(CountPositions() > 0)
return;

// Trend filter: 200 EMA
double trendEMA = iMA(Symbol(), PERIOD_H1, TrendMAPeriod, 0, MODE_EMA, PRICE_CLOSE, 1);
double close1 = iClose(Symbol(), PERIOD_H1, 1);

// Stochastic values on previous bar (use closed bar for stability)
double stochMain = iStochastic(Symbol(), PERIOD_H1, StochasticK, StochasticD, StochasticSlow, MODE_SMA, 0, MODE_MAIN, 1);
double stochMainPrev = iStochastic(Symbol(), PERIOD_H1, StochasticK, StochasticD, StochasticSlow, MODE_SMA, 0, MODE_MAIN, 2);
double stochSignal = iStochastic(Symbol(), PERIOD_H1, StochasticK, StochasticD, StochasticSlow, MODE_SMA, 0, MODE_SIGNAL, 1);
double stochSignalPrev = iStochastic(Symbol(), PERIOD_H1, StochasticK, StochasticD, StochasticSlow, MODE_SMA, 0, MODE_SIGNAL, 2);

// ATR for dynamic stop loss
double atr = iATR(Symbol(), PERIOD_H1, ATRPeriod, 1);
if(atr <= 0) atr = 150 * Point;

int cmd = -1;
double sl = 0, tp = 0;
double ask = Ask;
double bid = Bid;

// Long condition: price above trend EMA, stochastic main crosses above oversold level, main > signal
bool longCondition = (close1 > trendEMA) &&
(stochMainPrev <= OversoldLevel && stochMain > OversoldLevel) &&
(stochMain > stochSignal);

// Short condition: price below trend EMA, stochastic main crosses below overbought level, main < signal
bool shortCondition = (close1 < trendEMA) &&
(stochMainPrev >= OverboughtLevel && stochMain < OverboughtLevel) &&
(stochMain < stochSignal);

if(longCondition)
{
cmd = OP_BUY;
sl = bid - (atr * ATRStopMultiplier);
tp = bid + (atr * ATRTakeMultiplier);
}
else if(shortCondition)
{
cmd = OP_SELL;
sl = ask + (atr * ATRStopMultiplier);
tp = ask - (atr * ATRTakeMultiplier);
}

if(cmd != -1)
{
int ticket = OrderSend(Symbol(), cmd, LotSize, (cmd==OP_BUY?ask:bid), 3, sl, tp, "EURUSD TrendHarmony", MagicNumber, 0, clrNONE);
if(ticket < 0)
Print("OrderSend failed: ", GetLastError());
}
}

//+------------------------------------------------------------------+
//| Count open positions with this MagicNumber |
//+------------------------------------------------------------------+
int CountPositions()
{
int count = 0;
for(int i = OrdersTotal()-1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
count++;
}
}
return count;
}

//+------------------------------------------------------------------+
//| Close all orders for this symbol and magic |
//+------------------------------------------------------------------+
void CloseAllOrders()
{
for(int i = OrdersTotal()-1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
if(OrderType() == OP_BUY)
OrderClose(OrderTicket(), OrderLots(), Bid, 3, clrNONE);
else if(OrderType() == OP_SELL)
OrderClose(OrderTicket(), OrderLots(), Ask, 3, clrNONE);
}
}
}
}
//+------------------------------------------------------------------+
```
Reference: Original MQL4 code for educational purposes.
Disclaimer: Forex trading carries substantial risk. This EA is provided as-is without any guarantee of profit. Test thoroughly on demo before live trading. Past performance does not guarantee future results.