//+------------------------------------------------------------------+ //| One Candle Theory EA.mq5 | //| Copyright 2025, ElOportunista | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, ElOportunista" #property link "https://www.mql5.com" #property version "1.01" #property link "usen con cuidado" #include input group "Strategy Parameters" input string InpIndicatorFileName = "OpenCandleTheory"; // Nombre del archivo del indicador (sin .ex5) input int Maperiod = 20; // EMA Period input bool Use_MediaMovil = false; // Use EMA Filter input int MinCandleSize = 200; // Min Candle Size (points) input double MinPurpleZone = 50; // Min Purple Zone (points) input double MaxPurpleZonePercent = 80; // Max Purple Zone % input group "Risk Management" input double LotSize = 0.1; // Fixed Lot Size input int ATR_Period = 14; // ATR Period for SL/TP input double ATR_SL_Multiplier = 1.5; // ATR Multiplier for Stop Loss input double ATR_TP_Multiplier = 2.0; // ATR Multiplier for Take Profit input int MagicNumber = 123456; // Magic Number input group "Trading Time Window" input int HoraInit = 8; // Start hour input int HoraEnd = 20; // End hour //--- Global variables CTrade trade; int emaHandle; int atrHandle; int indicatorHandle = INVALID_HANDLE; // Handle for the visual indicator datetime lastProcessedH4 = 0; double mypoint; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { // Initialize Point value (handle 3/5 digit brokers) mypoint = SymbolInfoDouble(_Symbol, SYMBOL_POINT); if(SymbolInfoInteger(_Symbol, SYMBOL_DIGITS) % 2 == 1) mypoint *= 10; trade.SetExpertMagicNumber(MagicNumber); trade.SetTypeFillingBySymbol(_Symbol); trade.SetDeviationInPoints(10); indicatorHandle = iCustom(_Symbol, PERIOD_CURRENT, InpIndicatorFileName, Maperiod, Use_MediaMovil, MinCandleSize, MinPurpleZone, MaxPurpleZonePercent, true, true, true, 2); // Extra params: ShowAlerts, DrawLevels, See_text, mult if(indicatorHandle != INVALID_HANDLE) { if(!ChartIndicatorAdd(0, 0, indicatorHandle)) { Print("Warning: Could not add indicator to chart. Error: ", GetLastError()); } else { Print("Indicator added to chart successfully."); } } else { Print("Warning: Could not find indicator file '", InpIndicatorFileName, "'. Visuals will not be shown."); } if(Use_MediaMovil) { emaHandle = iMA(_Symbol, PERIOD_H4, Maperiod, 0, MODE_EMA, PRICE_CLOSE); if(emaHandle == INVALID_HANDLE) { Print("Error creating EMA handle"); return(INIT_FAILED); } } // Initialize ATR for SL/TP (Using H4 to match strategy timeframe) atrHandle = iATR(_Symbol, PERIOD_H4, ATR_Period); if(atrHandle == INVALID_HANDLE) { Print("Error creating ATR handle"); return(INIT_FAILED); } Print("EA Initialized. Strategy: One Candle Theory on H4"); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { if(emaHandle != INVALID_HANDLE) IndicatorRelease(emaHandle); if(atrHandle != INVALID_HANDLE) IndicatorRelease(atrHandle); if(indicatorHandle != INVALID_HANDLE) { IndicatorRelease(indicatorHandle); } } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { // --- Trading Time Filter --- // MqlDateTime dt; TimeToStruct(TimeCurrent(), dt); int hour = dt.hour; if(!(hour >= HoraInit && hour < HoraEnd)) { return; } datetime currentH4Time = iTime(_Symbol, PERIOD_H4, 0); if(currentH4Time == 0) return; // Data not ready if(currentH4Time == lastProcessedH4) return; CheckSignalAndTrade(); lastProcessedH4 = currentH4Time; } //+------------------------------------------------------------------+ //| Main Logic Function | //+------------------------------------------------------------------+ void CheckSignalAndTrade() { int total = PositionsTotal(); for(int i = 0; i < total; i++) { string sym = PositionGetSymbol(i); ulong mg = (ulong)PositionGetInteger(POSITION_MAGIC); if(sym == _Symbol && mg == MagicNumber) { Print("Trade already open. No new trades allowed."); return; // } } double hi = iHigh(_Symbol, PERIOD_H4, 1); double lo = iLow(_Symbol, PERIOD_H4, 1); double op = iOpen(_Symbol, PERIOD_H4, 1); double cl = iClose(_Symbol, PERIOD_H4, 1); if(hi == 0 || lo == 0) return; double candlesize = (hi - lo) / mypoint; double purpleZoneUp = (cl - lo) / mypoint; double purpleZoneDn = (hi - cl) / mypoint; if(candlesize < MinCandleSize) return; bool isBullish = (cl >= op); double purpleZone = isBullish ? purpleZoneUp : purpleZoneDn; double purplePercent = (candlesize > 0) ? (purpleZone / candlesize) * 100 : 0; if(purpleZone < MinPurpleZone || purplePercent > MaxPurpleZonePercent) return; if(Use_MediaMovil) { double ema[]; ArraySetAsSeries(ema, true); if(CopyBuffer(emaHandle, 0, 1, 1, ema) > 0) { if(isBullish && cl < ema[0]) return; if(!isBullish && cl > ema[0]) return; } else return; } double atr[]; ArraySetAsSeries(atr, true); if(CopyBuffer(atrHandle, 0, 1, 1, atr) <= 0) { Print("Error copying ATR data"); return; } double currentATR = atr[0]; if(isBullish) { double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); double sl = ask - (currentATR * ATR_SL_Multiplier); double tp = ask + (currentATR * ATR_TP_Multiplier); sl = NormalizeDouble(sl, _Digits); tp = NormalizeDouble(tp, _Digits); Print("BUY Signal Detected. Opening Trade..."); if(trade.Buy(LotSize, _Symbol, ask, sl, tp, "OCT Buy")) { Print("Buy Order Opened. SL: ", sl, " TP: ", tp); } else { Print("Error opening Buy: ", GetLastError()); } } else { double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); double sl = bid + (currentATR * ATR_SL_Multiplier); double tp = bid - (currentATR * ATR_TP_Multiplier); sl = NormalizeDouble(sl, _Digits); tp = NormalizeDouble(tp, _Digits); Print("SELL Signal Detected. Opening Trade..."); if(trade.Sell(LotSize, _Symbol, bid, sl, tp, "OCT Sell")) { Print("Sell Order Opened. SL: ", sl, " TP: ", tp); } else { Print("Error opening Sell: ", GetLastError()); } } }