SMC_BOS_EA/SMC INDICATOR V1

431 lines
11 KiB
Text
Raw Permalink Normal View History

2026-08-11 09:15:11 +00:00
OUR SMC INDICATOR V1
Purpose:
Detect only valid setups according to our trading strategy.
Core rule:
NO CLEAR = NO SIGNAL.
2026-08-11 09:19:51 +00:00
NO CONFIRMATION = NO TRADE.
//+------------------------------------------------------------------+
//| Strategy Settings |
//+------------------------------------------------------------------+
input int SwingLookback = 3;
input int ConfirmationBars = 1;
input bool EnableBuySignals = true;
input bool EnableSellSignals = true;
input bool ShowStructure = true;
input bool ShowSignals = true;
2026-08-11 09:21:59 +00:00
input bool EnableAlerts = true;
//+------------------------------------------------------------------+
//| Swing Structure Detection |
//+------------------------------------------------------------------+
bool IsSwingHigh(int shift)
{
if(shift < SwingLookback || shift >= Bars(_Symbol,_Period)-SwingLookback)
return false;
double currentHigh = iHigh(_Symbol,_Period,shift);
for(int i=1; i<=SwingLookback; i++)
{
if(currentHigh <= iHigh(_Symbol,_Period,shift-i))
return false;
if(currentHigh <= iHigh(_Symbol,_Period,shift+i))
return false;
}
return true;
}
bool IsSwingLow(int shift)
{
if(shift < SwingLookback || shift >= Bars(_Symbol,_Period)-SwingLookback)
return false;
double currentLow = iLow(_Symbol,_Period,shift);
for(int i=1; i<=SwingLookback; i++)
{
if(currentLow >= iLow(_Symbol,_Period,shift-i))
return false;
if(currentLow >= iLow(_Symbol,_Period,shift+i))
return false;
}
return true;
2026-08-11 09:24:22 +00:00
}
//+------------------------------------------------------------------+
//| HH / HL / LH / LL Classification |
//+------------------------------------------------------------------+
enum StructureType
{
STRUCTURE_NONE,
STRUCTURE_HH,
STRUCTURE_HL,
STRUCTURE_LH,
STRUCTURE_LL
};
StructureType GetHighStructure(double currentHigh, double previousHigh)
{
if(currentHigh > previousHigh)
return STRUCTURE_HH;
if(currentHigh < previousHigh)
return STRUCTURE_LH;
return STRUCTURE_NONE;
}
StructureType GetLowStructure(double currentLow, double previousLow)
{
if(currentLow > previousLow)
return STRUCTURE_HL;
if(currentLow < previousLow)
return STRUCTURE_LL;
return STRUCTURE_NONE;
2026-08-11 09:27:17 +00:00
}
//+------------------------------------------------------------------+
//| Break of Structure (BOS) Detection |
//+------------------------------------------------------------------+
bool BullishBOS(int shift, double previousSwingHigh)
{
double closePrice = iClose(_Symbol, _Period, shift);
// Bullish BOS requires a candle CLOSE above the previous swing high.
if(closePrice > previousSwingHigh)
return true;
return false;
}
bool BearishBOS(int shift, double previousSwingLow)
{
double closePrice = iClose(_Symbol, _Period, shift);
// Bearish BOS requires a candle CLOSE below the previous swing low.
if(closePrice < previousSwingLow)
return true;
2026-08-11 09:29:30 +00:00
return false;
}
//+------------------------------------------------------------------+
//| Pullback / Retest Detection |
//+------------------------------------------------------------------+
bool BullishRetest(int shift, double brokenResistance)
{
double candleLow = iLow(_Symbol, _Period, shift);
double candleClose = iClose(_Symbol, _Period, shift);
// Price must return to the broken level
// and close back above it.
if(candleLow <= brokenResistance &&
candleClose > brokenResistance)
{
return true;
}
return false;
}
bool BearishRetest(int shift, double brokenSupport)
{
double candleHigh = iHigh(_Symbol, _Period, shift);
double candleClose = iClose(_Symbol, _Period, shift);
// Price must return to the broken level
// and close back below it.
if(candleHigh >= brokenSupport &&
candleClose < brokenSupport)
{
return true;
}
2026-08-11 09:32:25 +00:00
return false;
}
//+------------------------------------------------------------------+
//| Confirmation Candle Detection |
//+------------------------------------------------------------------+
bool BullishConfirmation(int shift)
{
double openPrice = iOpen(_Symbol, _Period, shift);
double closePrice = iClose(_Symbol, _Period, shift);
double highPrice = iHigh(_Symbol, _Period, shift);
double lowPrice = iLow(_Symbol, _Period, shift);
double bodySize = MathAbs(closePrice - openPrice);
double totalSize = highPrice - lowPrice;
if(totalSize <= 0)
return false;
// Bullish candle must close above its open.
// Require the candle body to represent at least
// half of the complete candle range.
if(closePrice > openPrice &&
bodySize >= totalSize * 0.50)
{
return true;
}
return false;
}
bool BearishConfirmation(int shift)
{
double openPrice = iOpen(_Symbol, _Period, shift);
double closePrice = iClose(_Symbol, _Period, shift);
double highPrice = iHigh(_Symbol, _Period, shift);
double lowPrice = iLow(_Symbol, _Period, shift);
double bodySize = MathAbs(closePrice - openPrice);
double totalSize = highPrice - lowPrice;
if(totalSize <= 0)
return false;
// Bearish candle must close below its open.
// Require the candle body to represent at least
// half of the complete candle range.
if(closePrice < openPrice &&
bodySize >= totalSize * 0.50)
{
return true;
}
2026-08-11 09:27:17 +00:00
return false;
2026-08-11 09:34:53 +00:00
}
//+------------------------------------------------------------------+
//| BUY / SELL Signal Engine |
//+------------------------------------------------------------------+
bool ValidBuySetup(int shift, double previousSwingHigh)
{
// Step 1: Bullish BOS
if(!BullishBOS(shift, previousSwingHigh))
return false;
// Step 2: Pullback / retest
if(!BullishRetest(shift, previousSwingHigh))
return false;
// Step 3: Confirmation candle
if(!BullishConfirmation(shift))
return false;
return true;
}
bool ValidSellSetup(int shift, double previousSwingLow)
{
// Step 1: Bearish BOS
if(!BearishBOS(shift, previousSwingLow))
return false;
// Step 2: Pullback / retest
if(!BearishRetest(shift, previousSwingLow))
return false;
// Step 3: Confirmation candle
if(!BearishConfirmation(shift))
return false;
return true;
2026-08-11 09:36:30 +00:00
}
//+------------------------------------------------------------------+
//| Signal Display |
//+------------------------------------------------------------------+
void DrawBuySignal(int shift)
{
if(!ShowSignals)
return;
datetime signalTime = iTime(_Symbol, _Period, shift);
double signalPrice = iLow(_Symbol, _Period, shift);
string name = "SMC_BUY_" + IntegerToString((int)signalTime);
if(ObjectFind(0, name) >= 0)
return;
ObjectCreate(0, name, OBJ_ARROW_BUY, 0, signalTime, signalPrice);
ObjectSetInteger(0, name, OBJPROP_WIDTH, 2);
}
void DrawSellSignal(int shift)
{
if(!ShowSignals)
return;
datetime signalTime = iTime(_Symbol, _Period, shift);
double signalPrice = iHigh(_Symbol, _Period, shift);
string name = "SMC_SELL_" + IntegerToString((int)signalTime);
if(ObjectFind(0, name) >= 0)
return;
ObjectCreate(0, name, OBJ_ARROW_SELL, 0, signalTime, signalPrice);
ObjectSetInteger(0, name, OBJPROP_WIDTH, 2);
2026-08-11 09:38:52 +00:00
}
//+------------------------------------------------------------------+
//| Main Chart Scanner |
//+------------------------------------------------------------------+
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[]
)
{
// We need enough candles to identify structure.
int minimumBars = (SwingLookback * 2) + 10;
if(rates_total < minimumBars)
return 0;
// Only process the most recently closed candle.
// Shift 1 = last completed candle.
int shift = 1;
// ---------------------------------------------------------------
// Find the most recent confirmed swing high and swing low.
// ---------------------------------------------------------------
double previousSwingHigh = 0.0;
double previousSwingLow = 0.0;
for(int i = shift + SwingLookback;
i < rates_total - SwingLookback;
i++)
{
if(IsSwingHigh(i))
{
previousSwingHigh = iHigh(_Symbol, _Period, i);
break;
}
}
for(int i = shift + SwingLookback;
i < rates_total - SwingLookback;
i++)
{
if(IsSwingLow(i))
{
previousSwingLow = iLow(_Symbol, _Period, i);
break;
}
}
// ---------------------------------------------------------------
// Check for a valid BUY setup.
// ---------------------------------------------------------------
if(EnableBuySignals && previousSwingHigh > 0.0)
{
if(ValidBuySetup(shift, previousSwingHigh))
DrawBuySignal(shift);
2026-08-11 09:46:55 +00:00
SendBuyAlert(shift);
2026-08-11 09:38:52 +00:00
}
// ---------------------------------------------------------------
// Check for a valid SELL setup.
// ---------------------------------------------------------------
if(EnableSellSignals && previousSwingLow > 0.0)
{
if(ValidSellSetup(shift, previousSwingLow))
DrawSellSignal(shift);
2026-08-11 09:46:55 +00:00
SendSellAlert(shift);
2026-08-11 09:38:52 +00:00
}
return rates_total;
2026-08-11 09:43:11 +00:00
}
//+------------------------------------------------------------------+
//| Alert System |
//+------------------------------------------------------------------+
datetime LastBuyAlertTime = 0;
datetime LastSellAlertTime = 0;
void SendBuyAlert(int shift)
{
if(!EnableAlerts)
return;
datetime signalTime = iTime(_Symbol, _Period, shift);
// Prevent repeated alerts for the same candle.
if(signalTime == LastBuyAlertTime)
return;
LastBuyAlertTime = signalTime;
string message =
_Symbol + " " +
EnumToString(_Period) +
" - SMC BUY setup confirmed";
Alert(message);
Print(message);
}
void SendSellAlert(int shift)
{
if(!EnableAlerts)
return;
datetime signalTime = iTime(_Symbol, _Period, shift);
// Prevent repeated alerts for the same candle.
if(signalTime == LastSellAlertTime)
return;
LastSellAlertTime = signalTime;
string message =
_Symbol + " " +
EnumToString(_Period) +
" - SMC SELL setup confirmed";
Alert(message);
Print(message);
2026-08-11 09:21:59 +00:00
}