242 lines
15 KiB
MQL5
242 lines
15 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| 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 <Trade\Trade.mqh>
|
|
|
|
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());
|
|
}
|
|
}
|
|
}
|