//+------------------------------------------------------------------+ //| One Candle Theory Signals.mq5 | //| Copyright 2025, ElOportunista | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, ElOportunista" #property link "https://www.mql5.com" #property version "1.00" #property indicator_chart_window #property indicator_buffers 2 #property indicator_plots 2 #property indicator_label1 "Buy Signal" #property indicator_type1 DRAW_ARROW #property indicator_color1 clrLime #property indicator_width1 3 #property indicator_label2 "Sell Signal" #property indicator_type2 DRAW_ARROW #property indicator_color2 clrRed #property indicator_width2 3 input int Maperiod = 20; input bool Use_MediaMovil = false; input int MinCandleSize = 200; input double MinPurpleZone = 50; input double MaxPurpleZonePercent = 80; input bool ShowAlerts = true; input bool DrawLevels = true; input bool See_text = true; input int mult = 2; //--- indicator buffers double BuySignalBuffer[]; double SellSignalBuffer[]; //--- global variables datetime lastProcessedH4 = 0; string symbol; int digits; double mypoint; int emaHandle; //+------------------------------------------------------------------+ int OnInit() { SetIndexBuffer(0, BuySignalBuffer, INDICATOR_DATA); SetIndexBuffer(1, SellSignalBuffer, INDICATOR_DATA); PlotIndexSetInteger(0, PLOT_ARROW, 233); PlotIndexSetInteger(1, PLOT_ARROW, 234); PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0.0); PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, 0.0); ArraySetAsSeries(BuySignalBuffer, true); ArraySetAsSeries(SellSignalBuffer, true); symbol = _Symbol; digits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS); mypoint = SymbolInfoDouble(symbol, SYMBOL_POINT); if(digits % 2 == 1) mypoint *= 10; if(Use_MediaMovil) { emaHandle = iMA(symbol, PERIOD_H4, Maperiod, 0, MODE_EMA, PRICE_CLOSE); if(emaHandle == INVALID_HANDLE) return(INIT_FAILED); } Print("Indicador iniciado en ", EnumToString(Period()), " - Analizando H4"); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ void OnDeinit(const int reason) { ObjectsDeleteAll(0, "OCT_", 0, -1); if(Use_MediaMovil && emaHandle != INVALID_HANDLE) IndicatorRelease(emaHandle); } //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) { ArraySetAsSeries(time, true); datetime currentH4Time = iTime(symbol, PERIOD_H4, 1); if(currentH4Time != lastProcessedH4) { DrawH4Analysis(currentH4Time); lastProcessedH4 = currentH4Time; } return(rates_total); } //+------------------------------------------------------------------+ void DrawH4Analysis(datetime h4Time) { datetime temp = iTime(symbol, PERIOD_H4, 1); 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); datetime temp2 = iTime(symbol, PERIOD_H4, 2); double hi2 = iHigh(symbol, PERIOD_H4, 2); double lo2 = iLow(symbol, PERIOD_H4, 2); datetime tempw = iTime(symbol, PERIOD_W1, 1); double hiw = iHigh(symbol, PERIOD_W1, 1); double lo_w = iLow(symbol, PERIOD_W1, 1); datetime tempd = iTime(symbol, PERIOD_D1, 1); double hid = iHigh(symbol, PERIOD_D1, 1); double lod = iLow(symbol, PERIOD_D1, 1); double candlesize = (hi - lo) / mypoint; double purpleZoneUp = (cl - lo) / mypoint; double purpleZoneDn = (hi - cl) / mypoint; if(candlesize < MinCandleSize) return; if(DrawLevels) { string suffix = TimeToString(temp, TIME_DATE|TIME_MINUTES); TrendCreate(0, "OCT_trendwhi_"+suffix, 0, tempw, hiw, tempw + 2*PeriodSeconds(PERIOD_W1), hiw, clrGray, STYLE_SOLID, 1, false); TrendCreate(0, "OCT_trendwlo_"+suffix, 0, tempw, lo_w, tempw + 2*PeriodSeconds(PERIOD_W1), lo_w, clrGray, STYLE_SOLID, 1, false); TrendCreate(0, "OCT_trenddhi_"+suffix, 0, tempd, hid, tempd + 4*PeriodSeconds(PERIOD_D1), hid, clrDodgerBlue, STYLE_SOLID, 1, false); TrendCreate(0, "OCT_trenddlo_"+suffix, 0, tempd, lod, tempd + 4*PeriodSeconds(PERIOD_D1), lod, clrDodgerBlue, STYLE_SOLID, 1, false); if(See_text) { TextCreate(0, "OCT_text1_"+suffix, 0, tempw+PeriodSeconds(PERIOD_W1), hiw+10*mypoint, "Weekly High: "+DoubleToString(hiw,digits), "Arial", 8, clrWhite); TextCreate(0, "OCT_text2_"+suffix, 0, tempw+PeriodSeconds(PERIOD_W1), lo_w-5*mypoint, "Weekly Low: "+DoubleToString(lo_w,digits), "Arial", 8, clrWhite); TextCreate(0, "OCT_text3_"+suffix, 0, tempd+PeriodSeconds(PERIOD_D1), hid+10*mypoint, "Daily High: "+DoubleToString(hid,digits), "Arial", 8, clrWhite); TextCreate(0, "OCT_text4_"+suffix, 0, tempd+PeriodSeconds(PERIOD_D1), lod-5*mypoint, "Daily Low: "+DoubleToString(lod,digits), "Arial", 8, clrWhite); } } bool isBullish = (cl >= op); double purpleZone = isBullish ? purpleZoneUp : purpleZoneDn; double purplePercent = (candlesize > 0) ? (purpleZone / candlesize) * 100 : 0; // Validar purple zone if(purpleZone < MinPurpleZone || purplePercent > MaxPurpleZonePercent) return; // Verificar EMA si está activo 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; } } string suffix = TimeToString(temp, TIME_DATE|TIME_MINUTES); if(isBullish) { RectangleCreate(0, "OCT_rect_"+suffix, 0, temp, cl, temp+mult*PeriodSeconds(PERIOD_H4), lo, clrPurple); TrendCreate(0, "OCT_trend1_"+suffix, 0, temp, hi, temp+mult*PeriodSeconds(PERIOD_H4), hi, clrGray, STYLE_SOLID, 1, false); TrendCreate(0, "OCT_trend2_"+suffix, 0, temp, lo, temp+mult*PeriodSeconds(PERIOD_H4), lo, clrGray, STYLE_SOLID, 1, false); TrendCreate(0, "OCT_trend3_"+suffix, 0, temp, hi2, temp+mult*PeriodSeconds(PERIOD_H4), hi2, clrGray, STYLE_SOLID, 1, false); TrendCreate(0, "OCT_trend4_"+suffix, 0, temp, lo2, temp+mult*PeriodSeconds(PERIOD_H4), lo2, clrGray, STYLE_SOLID, 1, false); if(See_text) { string rangeText = "Range: " + DoubleToString(candlesize, (digits==2||digits==4)?digits:2) + " pips"; string zoneText = "Zone: " + DoubleToString(purpleZoneUp, (digits==2||digits==4)?digits:2) + " pips"; TextCreate(0, "OCT_text5_"+suffix, 0, temp+PeriodSeconds(PERIOD_H1), hi+(5*mypoint), rangeText, "Arial", 8, clrWhite); TextCreate(0, "OCT_text6_"+suffix, 0, temp+PeriodSeconds(PERIOD_H1), lo-(5*mypoint), zoneText, "Arial", 8, clrWhite); } int barShift = iBarShift(symbol, PERIOD_CURRENT, temp); if(barShift >= 0) { BuySignalBuffer[barShift] = iLow(symbol, PERIOD_CURRENT, barShift) - (10*mypoint); } if(ShowAlerts) Alert("ONE CANDLE THEORY BUY - ", symbol, " - Range: ", DoubleToString(candlesize,1), " pips"); } else { RectangleCreate(0, "OCT_rect_"+suffix, 0, temp, cl, temp+mult*PeriodSeconds(PERIOD_H4), hi, clrPurple); TrendCreate(0, "OCT_trend1_"+suffix, 0, temp, hi, temp+mult*PeriodSeconds(PERIOD_H4), hi, clrGray, STYLE_SOLID, 1, false); TrendCreate(0, "OCT_trend2_"+suffix, 0, temp, lo, temp+mult*PeriodSeconds(PERIOD_H4), lo, clrGray, STYLE_SOLID, 1, false); TrendCreate(0, "OCT_trend3_"+suffix, 0, temp, hi2, temp+mult*PeriodSeconds(PERIOD_H4), hi2, clrGray, STYLE_SOLID, 1, false); TrendCreate(0, "OCT_trend4_"+suffix, 0, temp, lo2, temp+mult*PeriodSeconds(PERIOD_H4), lo2, clrGray, STYLE_SOLID, 1, false); if(See_text) { string rangeText = "Range: " + DoubleToString(candlesize, (digits==2||digits==4)?digits:2) + " pips"; string zoneText = "Zone: " + DoubleToString(purpleZoneDn, (digits==2||digits==4)?digits:2) + " pips"; TextCreate(0, "OCT_text5_"+suffix, 0, temp+PeriodSeconds(PERIOD_H1), hi+(5*mypoint), rangeText, "Arial", 8, clrWhite); TextCreate(0, "OCT_text6_"+suffix, 0, temp+PeriodSeconds(PERIOD_H1), lo-(5*mypoint), zoneText, "Arial", 8, clrWhite); } int barShift = iBarShift(symbol, PERIOD_CURRENT, temp); if(barShift >= 0) { SellSignalBuffer[barShift] = iHigh(symbol, PERIOD_CURRENT, barShift) + (10*mypoint); } if(ShowAlerts) Alert("ONE CANDLE THEORY SELL - ", symbol, " - Range: ", DoubleToString(candlesize,1), " pips"); } ChartRedraw(); } //+------------------------------------------------------------------+ bool TrendCreate(const long chart_ID, const string name, const int sub_window, datetime time1, double price1, datetime time2, double price2, const color clr, const ENUM_LINE_STYLE style, const int width, const bool ray_right) { ObjectDelete(chart_ID, name); if(!ObjectCreate(chart_ID, name, OBJ_TREND, sub_window, time1, price1, time2, price2)) return(false); ObjectSetInteger(chart_ID, name, OBJPROP_COLOR, clr); ObjectSetInteger(chart_ID, name, OBJPROP_STYLE, style); ObjectSetInteger(chart_ID, name, OBJPROP_WIDTH, width); ObjectSetInteger(chart_ID, name, OBJPROP_RAY_RIGHT, ray_right); ObjectSetInteger(chart_ID, name, OBJPROP_BACK, true); return(true); } //+------------------------------------------------------------------+ bool TextCreate(const long chart_ID, const string name, const int sub_window, datetime time, double price, const string text, const string font, const int font_size, const color clr) { ObjectDelete(chart_ID, name); if(!ObjectCreate(chart_ID, name, OBJ_TEXT, sub_window, time, price)) return(false); ObjectSetString(chart_ID, name, OBJPROP_TEXT, text); ObjectSetString(chart_ID, name, OBJPROP_FONT, font); ObjectSetInteger(chart_ID, name, OBJPROP_FONTSIZE, font_size); ObjectSetInteger(chart_ID, name, OBJPROP_COLOR, clr); return(true); } //+------------------------------------------------------------------+ bool RectangleCreate(const long chart_ID, const string name, const int sub_window, datetime time1, double price1, datetime time2, double price2, const color clr) { ObjectDelete(chart_ID, name); if(!ObjectCreate(chart_ID, name, OBJ_RECTANGLE, sub_window, time1, price1, time2, price2)) return(false); ObjectSetInteger(chart_ID, name, OBJPROP_COLOR, clr); ObjectSetInteger(chart_ID, name, OBJPROP_FILL, true); ObjectSetInteger(chart_ID, name, OBJPROP_BACK, true); return(true); }