//+------------------------------------------------------------------+ //| InstitutionalTickHybridEA.mq5 | //| FIXED VERSION + HIGH IMPACT NEWS FILTER | //+------------------------------------------------------------------+ #property strict #property version "1.20" #include CTrade trade; //==================================================== // INPUTS //==================================================== input ulong MagicNumber = 880001; input double ForexLot = 0.01; input double GoldLot = 0.01; input int EMAFastPeriod = 20; input int EMATrendPeriod = 200; input int ATRPeriod = 14; input double ATRMultiplierSL = 2.0; input double ATRTrailingMultiplier = 1.5; input int TickBufferSize = 30; input double ZScoreThreshold = 1.3; input int CooldownSeconds = 10; input int MaxPositionsPerSymbol = 3; input double MaxSpreadPoints = 40; input double MinATRPointsForex = 15; input double MinATRPointsGold = 150; input double ProfitTargetPerLot = 20.0; input bool UseBreakeven = true; input double BreakevenOffsetPoints = 10; input bool EnableDebug = true; //==================================================== // NEWS FILTER //==================================================== input bool UseNewsFilter = true; input int NewsPauseBeforeMin = 60; input int NewsPauseAfterMin = 60; //==================================================== // GLOBALS //==================================================== double TickBuffer[]; datetime LastTradeTime = 0; int emaFastHandle; int emaTrendHandle; int atrHandle; //==================================================== // INIT //==================================================== int OnInit() { ArrayResize(TickBuffer, TickBufferSize); emaFastHandle = iMA(_Symbol,_Period,EMAFastPeriod,0,MODE_EMA,PRICE_CLOSE); emaTrendHandle = iMA(_Symbol,_Period,EMATrendPeriod,0,MODE_EMA,PRICE_CLOSE); atrHandle = iATR(_Symbol,_Period,ATRPeriod); if(emaFastHandle==INVALID_HANDLE || emaTrendHandle==INVALID_HANDLE || atrHandle==INVALID_HANDLE) { Print("Indicator init failed"); return INIT_FAILED; } Print("EA WITH NEWS FILTER INITIALIZED"); return INIT_SUCCEEDED; } //==================================================== // DEINIT //==================================================== void OnDeinit(const int reason) { IndicatorRelease(emaFastHandle); IndicatorRelease(emaTrendHandle); IndicatorRelease(atrHandle); } //==================================================== // ON TICK //==================================================== void OnTick() { UpdateTickBuffer(); //================================================ // HIGH IMPACT NEWS FILTER //================================================ if(UseNewsFilter && IsHighImpactNewsTime()) { CloseAllPositions(); Debug("Trading paused due to HIGH IMPACT NEWS"); return; } ManagePositions(); if(!CanTrade()) return; if(CountPositionsBySymbol() >= MaxPositionsPerSymbol) return; double z = CalculateZScore(); double emaFast = GetEMA(emaFastHandle); double emaTrend = GetEMA(emaTrendHandle); double atr = GetATR(); double bid = SymbolInfoDouble(_Symbol,SYMBOL_BID); bool bullish = bid > emaTrend; bool bearish = bid < emaTrend; bool reversalBuy = (z < -1.0); bool reversalSell = (z > 1.0); if(bullish && reversalBuy) OpenBuy(atr); if(bearish && reversalSell) OpenSell(atr); } //==================================================== // NEWS FILTER FUNCTION //==================================================== //==================================================== // NEWS FILTER FUNCTION //==================================================== bool IsHighImpactNewsTime() { MqlCalendarValue values[]; datetime now = TimeCurrent(); datetime from = now - 60; datetime to = now + (NewsPauseBeforeMin * 60); int count = CalendarValueHistory(values, from, to); if(count <= 0) return false; string symbolCurrency1 = StringSubstr(_Symbol,0,3); string symbolCurrency2 = StringSubstr(_Symbol,3,3); for(int i=0; i USD NEWS ONLY if(StringFind(_Symbol,"XAU") >= 0 || StringFind(_Symbol,"GOLD") >= 0) { if(currency == "USD") relevant = true; } else { if(currency == symbolCurrency1 || currency == symbolCurrency2) relevant = true; } if(!relevant) continue; datetime eventTime = values[i].time; datetime blockStart = eventTime - (NewsPauseBeforeMin * 60); datetime blockEnd = eventTime + (NewsPauseAfterMin * 60); if(now >= blockStart && now <= blockEnd) { Debug("High impact news detected"); return true; } } return false; } //==================================================== // CLOSE ALL POSITIONS //==================================================== void CloseAllPositions() { for(int i=PositionsTotal()-1;i>=0;i--) { ulong ticket=PositionGetTicket(i); if(ticket==0) continue; if(!PositionSelectByTicket(ticket)) continue; if(PositionGetInteger(POSITION_MAGIC)!=MagicNumber) continue; if(PositionGetString(POSITION_SYMBOL)!=_Symbol) continue; trade.PositionClose(ticket); } } //==================================================== // UPDATE TICKS //==================================================== void UpdateTickBuffer() { for(int i=TickBufferSize-1;i>0;i--) TickBuffer[i]=TickBuffer[i-1]; TickBuffer[0]=SymbolInfoDouble(_Symbol,SYMBOL_BID); } //==================================================== // Z SCORE //==================================================== double CalculateZScore() { double sum=0; for(int i=0;i MaxSpreadPoints) { Debug("Spread too high"); return false; } double atrPoints = GetATR()/_Point; string sym=_Symbol; StringToUpper(sym); double minATR = MinATRPointsForex; if(StringFind(sym,"XAU")>=0 || StringFind(sym,"GOLD")>=0) minATR = MinATRPointsGold; if(atrPoints < minATR) { Debug("ATR too low: " + DoubleToString(atrPoints,1)); return false; } if(TimeCurrent()-LastTradeTime < CooldownSeconds) return false; return true; } //==================================================== // OPEN BUY //==================================================== void OpenBuy(double atr) { double ask=SymbolInfoDouble(_Symbol,SYMBOL_ASK); double sl=ask-(atr*ATRMultiplierSL); AdjustStopsForBroker(sl,true); double lot=GetLotSize(); trade.SetExpertMagicNumber(MagicNumber); if(trade.Buy(lot,_Symbol,ask,sl,0,"BUY WITH NEWS FILTER")) LastTradeTime=TimeCurrent(); } //==================================================== // OPEN SELL //==================================================== void OpenSell(double atr) { double bid=SymbolInfoDouble(_Symbol,SYMBOL_BID); double sl=bid+(atr*ATRMultiplierSL); AdjustStopsForBroker(sl,false); double lot=GetLotSize(); trade.SetExpertMagicNumber(MagicNumber); if(trade.Sell(lot,_Symbol,bid,sl,0,"SELL WITH NEWS FILTER")) LastTradeTime=TimeCurrent(); } //==================================================== // LOT SIZE //==================================================== double GetLotSize() { string s=_Symbol; StringToUpper(s); if(StringFind(s,"XAU")>=0 || StringFind(s,"GOLD")>=0) return GoldLot; return ForexLot; } //==================================================== // POSITION COUNT //==================================================== int CountPositionsBySymbol() { int c=0; for(int i=PositionsTotal()-1;i>=0;i--) { ulong t=PositionGetTicket(i); if(t==0) continue; if(!PositionSelectByTicket(t)) continue; if(PositionGetInteger(POSITION_MAGIC)!=MagicNumber) continue; if(PositionGetString(POSITION_SYMBOL)!=_Symbol) continue; c++; } return c; } //==================================================== // POSITION MANAGEMENT //==================================================== void ManagePositions() { for(int i=PositionsTotal()-1;i>=0;i--) { ulong t=PositionGetTicket(i); if(t==0) continue; if(!PositionSelectByTicket(t)) continue; if(PositionGetInteger(POSITION_MAGIC)!=MagicNumber) continue; if(PositionGetString(POSITION_SYMBOL)!=_Symbol) continue; double vol=PositionGetDouble(POSITION_VOLUME); double sl=PositionGetDouble(POSITION_SL); double profit=PositionGetDouble(POSITION_PROFIT); double atr=GetATR(); double target=vol*ProfitTargetPerLot; if(profit>=target) { trade.PositionClose(t); continue; } ENUM_POSITION_TYPE type= (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); if(type==POSITION_TYPE_BUY) { double bid=SymbolInfoDouble(_Symbol,SYMBOL_BID); double newSL=bid-(atr*ATRTrailingMultiplier); if(newSL>sl) trade.PositionModify(t,newSL,0); } if(type==POSITION_TYPE_SELL) { double ask=SymbolInfoDouble(_Symbol,SYMBOL_ASK); double newSL=ask+(atr*ATRTrailingMultiplier); if(sl==0 || newSL