Files
2026-06-08 10:36:15 +02:00

258 lines
7.5 KiB
Plaintext

/*
============================================================
Demo File: Range_Breakout_EA - Signal Logic Showcase
Category: Breakout
Platform: MetaTrader 4 (MQL4)
Version: 1.0
Author: Giacomo Cipolat Bares
Portfolio: MQL4 Expert Advisors Portfolio
============================================================
Description:
This is a simplified public demo derived from the full
Range Breakout EA.
Included in this demo:
- range high/low detection
- breakout trigger calculation
- breakout buffer logic
- one-breakout-per-range logic
- breakout cooldown logic
- basic on-chart signal output
Excluded from this demo:
- order execution
- risk management engine
- break-even / trailing stop
- retry logic
- broker protection handling
- full production trade framework
- chart visualization layer
============================================================
*/
#property strict
#property version "1.00"
//========================= INPUTS ==================================
input string __01_BreakoutSettings = "01 ======== Breakout Settings ========";
input int BreakoutBars = 20;
input double BreakoutBufferPips = 0.5;
input bool UseCloseBreakout = false;
input bool OneBreakoutPerRange = true;
input bool ResetRangeAfterTrade = true;
input bool UseBreakoutCooldown = true;
input int BreakoutCooldownBars = 5;
//======================= BREAKOUT GLOBALS ==========================
double g_lastRangeHigh = 0.0;
double g_lastRangeLow = 0.0;
bool g_rangeAlreadyTraded = false;
int g_lastTradeBarIndex = -1;
//======================= GENERAL GLOBALS ===========================
double g_point;
double g_pip;
int g_digits;
datetime g_lastBarTime = 0;
//+------------------------------------------------------------------+
//| Expert initialization |
//+------------------------------------------------------------------+
int OnInit()
{
g_point = Point;
g_digits = Digits;
if(g_digits == 5 || g_digits == 3)
g_pip = g_point * 10.0;
else
g_pip = g_point;
Print("Range Breakout demo initialized");
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Detects a new bar |
//+------------------------------------------------------------------+
bool IsNewBar()
{
datetime currentBarTime = iTime(NULL, 0, 0);
if(currentBarTime != g_lastBarTime)
{
g_lastBarTime = currentBarTime;
return true;
}
return false;
}
//+------------------------------------------------------------------+
//| Range high from previous N bars |
//+------------------------------------------------------------------+
double GetBreakoutHigh()
{
int highestIndex = iHighest(NULL, 0, MODE_HIGH, BreakoutBars, 1);
return High[highestIndex];
}
//+------------------------------------------------------------------+
//| Range low from previous N bars |
//+------------------------------------------------------------------+
double GetBreakoutLow()
{
int lowestIndex = iLowest(NULL, 0, MODE_LOW, BreakoutBars, 1);
return Low[lowestIndex];
}
//+------------------------------------------------------------------+
//| Bullish breakout condition |
//+------------------------------------------------------------------+
bool IsBullishBreakout()
{
double breakoutHigh = GetBreakoutHigh();
double triggerPrice = breakoutHigh + BreakoutBufferPips * g_pip;
if(UseCloseBreakout)
return (Close[1] > triggerPrice);
return (Ask > triggerPrice);
}
//+------------------------------------------------------------------+
//| Bearish breakout condition |
//+------------------------------------------------------------------+
bool IsBearishBreakout()
{
double breakoutLow = GetBreakoutLow();
double triggerPrice = breakoutLow - BreakoutBufferPips * g_pip;
if(UseCloseBreakout)
return (Close[1] < triggerPrice);
return (Bid < triggerPrice);
}
//+------------------------------------------------------------------+
//| Checks if current range is same as previous tracked range |
//+------------------------------------------------------------------+
bool IsSameRange(double rangeHigh, double rangeLow)
{
if(MathAbs(rangeHigh - g_lastRangeHigh) < (g_point * 0.5) &&
MathAbs(rangeLow - g_lastRangeLow) < (g_point * 0.5))
{
return true;
}
return false;
}
//+------------------------------------------------------------------+
//| Updates tracked breakout range |
//+------------------------------------------------------------------+
void UpdateRangeState()
{
double currentRangeHigh = GetBreakoutHigh();
double currentRangeLow = GetBreakoutLow();
if(!IsSameRange(currentRangeHigh, currentRangeLow))
{
g_lastRangeHigh = currentRangeHigh;
g_lastRangeLow = currentRangeLow;
if(ResetRangeAfterTrade)
g_rangeAlreadyTraded = false;
}
}
//+------------------------------------------------------------------+
//| One breakout per range filter |
//+------------------------------------------------------------------+
bool CanTradeCurrentRange()
{
if(!OneBreakoutPerRange)
return true;
if(g_rangeAlreadyTraded)
return false;
return true;
}
//+------------------------------------------------------------------+
//| Breakout cooldown filter |
//+------------------------------------------------------------------+
bool BreakoutCooldownPassed()
{
if(!UseBreakoutCooldown)
return true;
if(g_lastTradeBarIndex < 0)
return true;
int barsPassed = Bars - g_lastTradeBarIndex;
if(barsPassed >= BreakoutCooldownBars)
return true;
return false;
}
//+------------------------------------------------------------------+
//| Demo buy signal wrapper |
//+------------------------------------------------------------------+
bool BuySignal()
{
if(!CanTradeCurrentRange())
return false;
if(!BreakoutCooldownPassed())
return false;
return IsBullishBreakout();
}
//+------------------------------------------------------------------+
//| Demo sell signal wrapper |
//+------------------------------------------------------------------+
bool SellSignal()
{
if(!CanTradeCurrentRange())
return false;
if(!BreakoutCooldownPassed())
return false;
return IsBearishBreakout();
}
//+------------------------------------------------------------------+
//| Expert tick |
//+------------------------------------------------------------------+
void OnTick()
{
if(!IsNewBar())
return;
UpdateRangeState();
if(BuySignal())
{
g_lastTradeBarIndex = Bars;
g_rangeAlreadyTraded = true;
Comment("Demo Signal: BUY breakout detected");
return;
}
if(SellSignal())
{
g_lastTradeBarIndex = Bars;
g_rangeAlreadyTraded = true;
Comment("Demo Signal: SELL breakout detected");
return;
}
Comment("Demo Signal: No valid breakout");
}