//+------------------------------------------------------------------+ //| Ichimoku_Complete_Pro.mq5 | //| Version 2.10 - Daily Loss Limit + Direction Filter | //+------------------------------------------------------------------+ #property copyright "Educational - Optimized Version" #property version "2.10" #property strict #include CTrade trade; //+------------------------------------------------------------------+ //| Eingabeparameter | //+------------------------------------------------------------------+ input group "=== Ichimoku Einstellungen ===" input int InpTenkanPeriod = 9; input int InpKijunPeriod = 26; input int InpSenkouPeriod = 52; input group "=== ATR Risk Management ===" input double InpSL_Multiplier = 1.5; input double InpTP_Multiplier = 2.5; input double InpTrail_Start = 1.2; input double InpTrail_Distance = 1.0; input double InpBE_Trigger = 1.0; input double InpBE_Offset = 0.2; input group "=== Handelsrichtung ===" enum ENUM_TRADE_DIRECTION { DIR_BOTH = 0, // Beide Richtungen DIR_LONG = 1, // Nur Long DIR_SHORT = 2 // Nur Short }; input ENUM_TRADE_DIRECTION InpTradeDirection = DIR_BOTH; input group "=== Tagesverlust-Limit ===" input bool InpUseDailyLossLimit = true; input double InpMaxDailyLoss = 50.0; // Maximaler Verlust in Account-Währung (z.B. 50 $) input group "=== Filter ===" input bool InpUseSessionFilter = true; input int InpLondonStart = 8; input int InpLondonEnd = 17; input int InpNYStart = 13; input int InpNYEnd = 22; input int InpMaxSpreadPoints = 25; input group "=== Benachrichtigungen ===" input bool InpSendPush = true; input bool InpSendMail = false; input string InpMailSubject = "Ichimoku EA"; input group "=== Allgemein ===" input double InpLotSize = 0.01; input int InpMagicNumber = 20260915; input bool InpOnlyOneTrade = true; //+------------------------------------------------------------------+ //| Globale Variablen | //+------------------------------------------------------------------+ int handleIchimoku = INVALID_HANDLE; int handleATR = INVALID_HANDLE; int atrPeriod = 14; double tenkan[], kijun[], senkouA[], senkouB[], chikou[], atr[]; double dailyStartBalance = 0; datetime lastDayChecked = 0; bool tradingAllowedToday = true; //+------------------------------------------------------------------+ int GetATRPeriodByTimeframe() { ENUM_TIMEFRAMES tf = Period(); if(tf <= PERIOD_M5) return 20; if(tf <= PERIOD_M15) return 14; if(tf <= PERIOD_M30) return 12; if(tf <= PERIOD_H1) return 10; if(tf <= PERIOD_H4) return 10; return 8; } //+------------------------------------------------------------------+ int OnInit() { atrPeriod = GetATRPeriodByTimeframe(); handleIchimoku = iIchimoku(_Symbol, PERIOD_CURRENT, InpTenkanPeriod, InpKijunPeriod, InpSenkouPeriod); handleATR = iATR(_Symbol, PERIOD_CURRENT, atrPeriod); if(handleIchimoku == INVALID_HANDLE || handleATR == INVALID_HANDLE) { Print("Fehler beim Erstellen der Indikatoren"); return INIT_FAILED; } ArraySetAsSeries(tenkan, true); ArraySetAsSeries(kijun, true); ArraySetAsSeries(senkouA, true); ArraySetAsSeries(senkouB, true); ArraySetAsSeries(chikou, true); ArraySetAsSeries(atr, true); trade.SetExpertMagicNumber(InpMagicNumber); trade.SetDeviationInPoints(30); trade.SetTypeFilling(ORDER_FILLING_FOK); // Tagesstart-Balance initialisieren dailyStartBalance = AccountInfoDouble(ACCOUNT_BALANCE); lastDayChecked = iTime(_Symbol, PERIOD_D1, 0); tradingAllowedToday = true; Print("Ichimoku EA v2.10 gestartet | ATR-Periode: ", atrPeriod); return INIT_SUCCEEDED; } //+------------------------------------------------------------------+ void OnDeinit(const int reason) { if(handleIchimoku != INVALID_HANDLE) IndicatorRelease(handleIchimoku); if(handleATR != INVALID_HANDLE) IndicatorRelease(handleATR); } //+------------------------------------------------------------------+ void CheckDailyLossLimit() { if(!InpUseDailyLossLimit) { tradingAllowedToday = true; return; } datetime currentDay = iTime(_Symbol, PERIOD_D1, 0); // Neuer Tag → Reset if(currentDay != lastDayChecked) { dailyStartBalance = AccountInfoDouble(ACCOUNT_BALANCE); lastDayChecked = currentDay; tradingAllowedToday = true; Print("Neuer Handelstag – Tagesverlust-Limit zurückgesetzt"); } double currentEquity = AccountInfoDouble(ACCOUNT_EQUITY); double dailyPL = currentEquity - dailyStartBalance; if(dailyPL <= -InpMaxDailyLoss) { if(tradingAllowedToday) { tradingAllowedToday = false; Notify("Tagesverlust-Limit erreicht (" + DoubleToString(dailyPL, 2) + "). Trading für heute gestoppt."); } } } //+------------------------------------------------------------------+ bool IsTradingSession() { if(!InpUseSessionFilter) return true; MqlDateTime dt; TimeToStruct(TimeCurrent(), dt); int hour = dt.hour; bool london = (hour >= InpLondonStart && hour < InpLondonEnd); bool ny = (hour >= InpNYStart && hour < InpNYEnd); return (london || ny); } //+------------------------------------------------------------------+ bool IsSpreadOK() { return (SymbolInfoInteger(_Symbol, SYMBOL_SPREAD) <= InpMaxSpreadPoints); } //+------------------------------------------------------------------+ void Notify(string message) { if(InpSendPush) SendNotification(message); if(InpSendMail) SendMail(InpMailSubject, message); Print(message); } //+------------------------------------------------------------------+ void ManageOpenPosition() { if(!PositionSelect(_Symbol)) return; if(PositionGetInteger(POSITION_MAGIC) != InpMagicNumber) return; if(CopyBuffer(handleATR, 0, 0, 2, atr) < 2) return; double currentATR = atr[0]; if(currentATR <= 0) return; int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS); long type = PositionGetInteger(POSITION_TYPE); double openPrice = PositionGetDouble(POSITION_PRICE_OPEN); double currentSL = PositionGetDouble(POSITION_SL); double currentTP = PositionGetDouble(POSITION_TP); double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); double beTrigger = currentATR * InpBE_Trigger; double beOffset = currentATR * InpBE_Offset; double trailStart = currentATR * InpTrail_Start; double trailDistance = currentATR * InpTrail_Distance; double minMove = currentATR * 0.12; // LONG if(type == POSITION_TYPE_BUY) { double profit = bid - openPrice; if(profit >= beTrigger) { double newSL = NormalizeDouble(openPrice + beOffset, digits); if(newSL > currentSL + minMove || currentSL == 0) if(trade.PositionModify(_Symbol, newSL, currentTP)) Notify("Break-Even BUY | SL: " + DoubleToString(newSL, digits)); } if(profit >= trailStart) { double newSL = NormalizeDouble(bid - trailDistance, digits); if(newSL > currentSL + minMove) trade.PositionModify(_Symbol, newSL, currentTP); } } // SHORT if(type == POSITION_TYPE_SELL) { double profit = openPrice - ask; if(profit >= beTrigger) { double newSL = NormalizeDouble(openPrice - beOffset, digits); if(currentSL == 0 || newSL < currentSL - minMove) if(trade.PositionModify(_Symbol, newSL, currentTP)) Notify("Break-Even SELL | SL: " + DoubleToString(newSL, digits)); } if(profit >= trailStart) { double newSL = NormalizeDouble(ask + trailDistance, digits); if(currentSL == 0 || newSL < currentSL - minMove) trade.PositionModify(_Symbol, newSL, currentTP); } } } //+------------------------------------------------------------------+ void OnTick() { // Tagesverlust prüfen CheckDailyLossLimit(); // Offene Positionen verwalten ManageOpenPosition(); // Filter if(!tradingAllowedToday) return; if(!IsTradingSession()) return; if(!IsSpreadOK()) return; // Nur bei neuer Kerze static datetime lastBarTime = 0; datetime currentBarTime = iTime(_Symbol, PERIOD_CURRENT, 0); if(currentBarTime == lastBarTime) return; lastBarTime = currentBarTime; if(InpOnlyOneTrade && PositionSelect(_Symbol)) return; // Indikatoren if(CopyBuffer(handleIchimoku, 0, 0, 3, tenkan) < 3) return; if(CopyBuffer(handleIchimoku, 1, 0, 3, kijun) < 3) return; if(CopyBuffer(handleIchimoku, 2, 0, 3, senkouA) < 3) return; if(CopyBuffer(handleIchimoku, 3, 0, 3, senkouB) < 3) return; if(CopyBuffer(handleIchimoku, 4, 0, 30, chikou) < 30) return; if(CopyBuffer(handleATR, 0, 1, 2, atr) < 2) return; double atrValue = atr[0]; double close1 = iClose(_Symbol, PERIOD_CURRENT, 1); double cloudTop = MathMax(senkouA[1], senkouB[1]); double cloudBottom = MathMin(senkouA[1], senkouB[1]); bool buySignal = (close1 > cloudTop) && (tenkan[1] > kijun[1] && tenkan[2] <= kijun[2]) && (chikou[26] > close1); bool sellSignal = (close1 < cloudBottom) && (tenkan[1] < kijun[1] && tenkan[2] >= kijun[2]) && (chikou[26] < close1); // Handelsrichtung filtern if(InpTradeDirection == DIR_LONG) sellSignal = false; if(InpTradeDirection == DIR_SHORT) buySignal = false; int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS); // BUY if(buySignal) { double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); double sl = NormalizeDouble(ask - atrValue * InpSL_Multiplier, digits); double tp = NormalizeDouble(ask + atrValue * InpTP_Multiplier, digits); if(trade.Buy(InpLotSize, _Symbol, ask, sl, tp, "Ichimoku Buy")) Notify("BUY | " + _Symbol + " | SL: " + DoubleToString(sl, digits) + " | TP: " + DoubleToString(tp, digits)); } // SELL if(sellSignal) { double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); double sl = NormalizeDouble(bid + atrValue * InpSL_Multiplier, digits); double tp = NormalizeDouble(bid - atrValue * InpTP_Multiplier, digits); if(trade.Sell(InpLotSize, _Symbol, bid, sl, tp, "Ichimoku Sell")) Notify("SELL | " + _Symbol + " | SL: " + DoubleToString(sl, digits) + " | TP: " + DoubleToString(tp, digits)); } } //+------------------------------------------------------------------+