PracticeCode/OpenCandleTheoryIndicator.mq5
2025-11-20 10:14:26 +03:00

292 lines
23 KiB
MQL5

//+------------------------------------------------------------------+
//| 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);
}