0% found this document useful (0 votes)
49 views12 pages

SMC Auto Trader: Market Structure EA

Code for a Bot that works on Automation.

Uploaded by

ahmadtra22
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
49 views12 pages

SMC Auto Trader: Market Structure EA

Code for a Bot that works on Automation.

Uploaded by

ahmadtra22
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

//+------------------------------------------------------------------+

//| SMC_AUTO_TRADER.mq5 |

//| A lightweight MT5 Expert Advisor to detect market structure: |

//| HH, HL, LL, LH, BOS (Break of Structure) and Inducement. |

//| - Reads internal and external timeframe structures |

//| - Draws BOS & Inducement as precise line segments |

//| - Displays a simple black panel with white text showing entry, |

//| SL and TP values (calculated from last BOS) |

//| - No automatic trading executed (ready to add order logic later) |

//+------------------------------------------------------------------+

#property copyright "(c) 2025"

#property version "1.00"

#property strict

#property description "SMC structure detection EA (visual) - ready for automation later"

#include <Trade\[Link]>

//--- Inputs

input ENUM_TIMEFRAMES Inp_InternalTF = PERIOD_M1; // Internal timeframe (any


ENUM_TIMEFRAMES)

input ENUM_TIMEFRAMES Inp_ExternalTF = PERIOD_H1; // External timeframe (any


ENUM_TIMEFRAMES)

input int Inp_SwingBars = 5; // Bars to left/right to consider a swing high/low

input int Inp_MaxBarsScan = 500; // How many bars to scan (keeps lightweight)

input color Inp_BOS_Color = clrRed; // Color for BOS line

input color Inp_Ind_Color = clrDodgerBlue; // Color for Inducement line

input ENUM_LINE_STYLE Inp_LineStyle = STYLE_DOT; // BOS/Inducement line style

input double Inp_SL_Pips = 50.0; // Default SL in pips for panel calc

input double Inp_TP_Mult = 2.0; // TP multiplier of SL


input bool Inp_ShowPanel = true; // Show entry/SL/TP panel

input string Inp_PanelPrefix = "SMC:"; // Panel prefix

//--- Variable Colors for Structure Labels

input color Inp_HH_Color = clrLime; // Color for Higher High label

input color Inp_HL_Color = clrCyan; // Color for Higher Low label

input color Inp_LH_Color = clrYellow; // Color for Lower High label

input color Inp_LL_Color = clrOrange; // Color for Lower Low label

//--- Globals

string g_prefix_internal = "SMC_INT_";

string g_prefix_external = "SMC_EXT_";

string g_panel_bg_name = "SMC_PANEL_BG";

string g_panel_txt_name = "SMC_PANEL_TXT";

//--- utility: convert pips to price

double PipsToPrice(double pips, string symbol)

double point = SymbolInfoDouble(symbol, SYMBOL_POINT);

// Adjust for JPY pairs and other 3/5 digit pairs

if(_Digits == 3 || _Digits == 5) point *= 10;

return pips * point;

//--- structure point type

enum ESwingType { SWING_NONE=0, SWING_HIGH=1, SWING_LOW=2 };

//--- Structure record

struct SPoint
{

datetime time;

double price;

ESwingType type;

};

//+------------------------------------------------------------------+

//| Expert initialization function |

//+------------------------------------------------------------------+

int OnInit()

if(Inp_ShowPanel) CreatePanel();

EventSetTimer(5); // periodic update (every 5 seconds)

return(INIT_SUCCEEDED);

//+------------------------------------------------------------------+

//| Expert deinitialization function |

//+------------------------------------------------------------------+

void OnDeinit(const int reason)

DeleteObjectsByPrefix(g_prefix_internal);

DeleteObjectsByPrefix(g_prefix_external);

DeleteObjectsByPrefix(g_panel_bg_name);

DeleteObjectsByPrefix(g_panel_txt_name);

EventKillTimer();

//+------------------------------------------------------------------+
//| Timer function - run detection regularly |

//+------------------------------------------------------------------+

void OnTimer()

string symbol = _Symbol;

ProcessTimeframe(symbol, Inp_InternalTF, g_prefix_internal);

ProcessTimeframe(symbol, Inp_ExternalTF, g_prefix_external);

UpdatePanel(symbol);

//+------------------------------------------------------------------+

//| OnTick - also trigger immediate update |

//+------------------------------------------------------------------+

void OnTick()

OnTimer();

//+------------------------------------------------------------------+

//| Get candles and detect swing points |

//+------------------------------------------------------------------+

void ProcessTimeframe(string symbol, ENUM_TIMEFRAMES tf, string prefix)

MqlRates rates[];

int toCopy = MathMin(Inp_MaxBarsScan, 2000);

if(CopyRates(symbol, tf, 0, toCopy, rates) <= 0) return;

ArraySetAsSeries(rates, true);

SPoint swings[];
ArrayResize(swings,0);

int bars = ArraySize(rates);

for(int i=Inp_SwingBars; i<bars-Inp_SwingBars; ++i)

bool isHigh = true, isLow = true;

double priceHigh = rates[i].high, priceLow = rates[i].low;

for(int j=1; j<=Inp_SwingBars; ++j)

if(rates[i+j].high >= priceHigh || rates[i-j].high >= priceHigh) isHigh = false;

if(rates[i+j].low <= priceLow || rates[i-j].low <= priceLow ) isLow = false;

if(isHigh)

SPoint p; [Link] = rates[i].time; [Link] = priceHigh; [Link] = SWING_HIGH;

SPoint temp_array[1]; temp_array[0] = p; ArrayInsert(swings, temp_array, 0);

else if(isLow)

SPoint p; [Link] = rates[i].time; [Link] = priceLow; [Link] = SWING_LOW;

SPoint temp_array[1]; temp_array[0] = p; ArrayInsert(swings, temp_array, 0);

DeleteObjectsByPrefix(prefix);

for(int s=ArraySize(swings)-1; s>=0; --s)

string lbl = prefix + "SW_" + IntegerToString(s);


string txt = (swings[s].type==SWING_HIGH)? "HH?" : "LL?";

DrawTextAtTime(lbl, swings[s].time, swings[s].price, txt, clrWhite);

AnalyzeStructureAndDraw(symbol, tf, prefix, swings);

//+------------------------------------------------------------------+

//| Analyze swings sequence and draw structure lines |

//+------------------------------------------------------------------+

void AnalyzeStructureAndDraw(string symbol, ENUM_TIMEFRAMES tf, string prefix, SPoint &swings[])

int n = ArraySize(swings);

if(n < 3) return;

// Loop through swing points to find BOS/IDM events

for(int i=0; i<n-1; ++i)

SPoint cur = swings[i];

SPoint prev = swings[i+1];

// Label HH, HL, LH, LL

if([Link]==SWING_HIGH && [Link]==SWING_HIGH)

DrawLabel(prefix + "STRUCT_" + IntegerToString(i), [Link], [Link], ([Link] > [Link]) ?


"H.H" : "L.H", ([Link] > [Link]) ? Inp_HH_Color : Inp_LH_Color);

else if([Link]==SWING_LOW && [Link]==SWING_LOW)

DrawLabel(prefix + "STRUCT_" + IntegerToString(i), [Link], [Link], ([Link] < [Link]) ?


"L.L" : "H.L", ([Link] < [Link]) ? Inp_LL_Color : Inp_HL_Color);
// --- Refined BOS/IDM Detection ---

datetime levelTime = [Link];

double levelPrice = [Link];

int startBarIndex = iBarShift(_Symbol, tf, [Link]) - 1; // Start scanning from the bar after the current
swing

// Bearish BOS: break of a swing low

if([Link] == SWING_LOW)

for(int bar = startBarIndex; bar >= 0; bar--)

if(iLow(_Symbol, tf, bar) < levelPrice)

datetime breakTime = iTime(_Symbol, tf, bar);

bool isInducement = (bar > 0 && iClose(_Symbol, tf, bar-1) > levelPrice);

if(isInducement)

DrawHorizontalLineSegment(prefix + "IND_" + IntegerToString(i), levelTime, breakTime,


levelPrice, Inp_Ind_Color, STYLE_DASH);

DrawLabel(prefix + "IND_L_" + IntegerToString(i), breakTime, levelPrice, "IDM",


Inp_Ind_Color);

else

DrawHorizontalLineSegment(prefix + "BOS_" + IntegerToString(i), levelTime, breakTime,


levelPrice, Inp_BOS_Color, Inp_LineStyle);

DrawLabel(prefix + "BOS_L_" + IntegerToString(i), breakTime, levelPrice, "B.O.S",


Inp_BOS_Color);

}
break; // Found the break, stop scanning for this level

// Bullish BOS: break of a swing high

else if([Link] == SWING_HIGH)

for(int bar = startBarIndex; bar >= 0; bar--)

if(iHigh(_Symbol, tf, bar) > levelPrice)

datetime breakTime = iTime(_Symbol, tf, bar);

bool isInducement = (bar > 0 && iClose(_Symbol, tf, bar-1) < levelPrice);

if(isInducement)

DrawHorizontalLineSegment(prefix + "IND_" + IntegerToString(i), levelTime, breakTime,


levelPrice, Inp_Ind_Color, STYLE_DASH);

DrawLabel(prefix + "IND_L_" + IntegerToString(i), breakTime, levelPrice, "IDM",


Inp_Ind_Color);

else

DrawHorizontalLineSegment(prefix + "BOS_" + IntegerToString(i), levelTime, breakTime,


levelPrice, Inp_BOS_Color, Inp_LineStyle);

DrawLabel(prefix + "BOS_L_" + IntegerToString(i), breakTime, levelPrice, "B.O.S",


Inp_BOS_Color);

break; // Found the break, stop scanning for this level

}
}

//+------------------------------------------------------------------+

//| Drawing helpers |

//+------------------------------------------------------------------+

void DrawHorizontalLineSegment(string name, datetime time1, datetime time2, double price, color col,
ENUM_LINE_STYLE style)

if(ObjectFind(0, name) >= 0) ObjectDelete(0, name);

if(!ObjectCreate(0, name, OBJ_TREND, 0, time1, price, time2, price)) return;

ObjectSetInteger(0, name, OBJPROP_COLOR, col);

ObjectSetInteger(0, name, OBJPROP_STYLE, style);

ObjectSetInteger(0, name, OBJPROP_WIDTH, 2);

ObjectSetInteger(0, name, OBJPROP_RAY_RIGHT, false); // Do not extend the line

void DrawTextAtTime(string name, datetime when, double price, string txt, color col)

if(ObjectFind(0, name) >= 0) ObjectDelete(0, name);

if(!ObjectCreate(0, name, OBJ_TEXT, 0, when, price)) return;

ObjectSetString(0, name, OBJPROP_TEXT, txt);

ObjectSetInteger(0, name, OBJPROP_COLOR, col);

ObjectSetString(0, name, OBJPROP_FONT, "Arial");

ObjectSetInteger(0, name, OBJPROP_FONTSIZE, 8);

ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_LEFT_UPPER);


}

void DrawLabel(string name, datetime when, double price, string txt, color col)

if(ObjectFind(0, name) >= 0) ObjectDelete(0, name);

if(!ObjectCreate(0, name, OBJ_TEXT, 0, when, price)) return;

ObjectSetString(0, name, OBJPROP_TEXT, txt);

ObjectSetInteger(0, name, OBJPROP_COLOR, col);

ObjectSetString(0, name, OBJPROP_FONT, "Arial");

ObjectSetInteger(0, name, OBJPROP_FONTSIZE, 9);

ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_LEFT);

//+------------------------------------------------------------------+

//| Delete objects by prefix |

//+------------------------------------------------------------------+

void DeleteObjectsByPrefix(string prefix)

int total = ObjectsTotal(0);

for(int i=total-1; i>=0; --i)

string name = ObjectName(0, i);

if(StringFind(name, prefix) == 0) ObjectDelete(0, name);

//+------------------------------------------------------------------+

//| Panel creation / update |

//+------------------------------------------------------------------+
void CreatePanel()

if(ObjectFind(0, g_panel_bg_name) >= 0) ObjectDelete(0, g_panel_bg_name);

if(!ObjectCreate(0, g_panel_bg_name, OBJ_RECTANGLE_LABEL, 0, 0, 0)) return;

ObjectSetInteger(0, g_panel_bg_name, OBJPROP_CORNER, CORNER_LEFT_UPPER);

ObjectSetInteger(0, g_panel_bg_name, OBJPROP_XDISTANCE, 10);

ObjectSetInteger(0, g_panel_bg_name, OBJPROP_YDISTANCE, 10);

ObjectSetInteger(0, g_panel_bg_name, OBJPROP_XSIZE, 150);

ObjectSetInteger(0, g_panel_bg_name, OBJPROP_YSIZE, 80);

ObjectSetInteger(0, g_panel_bg_name, OBJPROP_BGCOLOR, clrBlack);

ObjectSetInteger(0, g_panel_bg_name, OBJPROP_BORDER_TYPE, BORDER_FLAT);

ObjectSetInteger(0, g_panel_bg_name, OBJPROP_COLOR, clrNONE);

if(ObjectFind(0, g_panel_txt_name) >= 0) ObjectDelete(0, g_panel_txt_name);

if(!ObjectCreate(0, g_panel_txt_name, OBJ_LABEL, 0, 0, 0)) return;

ObjectSetInteger(0, g_panel_txt_name, OBJPROP_CORNER, CORNER_LEFT_UPPER);

ObjectSetInteger(0, g_panel_txt_name, OBJPROP_XDISTANCE, 15);

ObjectSetInteger(0, g_panel_txt_name, OBJPROP_YDISTANCE, 15);

ObjectSetString(0, g_panel_txt_name, OBJPROP_TEXT, "");

ObjectSetString(0, g_panel_txt_name, OBJPROP_FONT, "Courier New");

ObjectSetInteger(0, g_panel_txt_name, OBJPROP_FONTSIZE, 9);

ObjectSetInteger(0, g_panel_txt_name, OBJPROP_COLOR, clrWhite);

void UpdatePanel(string symbol)

if(!Inp_ShowPanel) return;

double entry = 0, sl = 0, tp = 0;

string bosPrefix = g_prefix_internal + "BOS_";


int total = ObjectsTotal(0);

string latestBOS = "";

for(int i=0; i<total; ++i)

string name = ObjectName(0, i);

if(StringFind(name, bosPrefix) == 0) latestBOS = name;

if(latestBOS != "")

double price = ObjectGetDouble(0, latestBOS, OBJPROP_PRICE, 0);

entry = price;

double bid = SymbolInfoDouble(symbol, SYMBOL_BID);

if(bid > entry) { sl = entry - PipsToPrice(Inp_SL_Pips, symbol); tp = entry + PipsToPrice(Inp_SL_Pips *


Inp_TP_Mult, symbol); }

else { sl = entry + PipsToPrice(Inp_SL_Pips, symbol); tp = entry - PipsToPrice(Inp_SL_Pips *


Inp_TP_Mult, symbol); }

string txt = Inp_PanelPrefix + "\n";

if(entry != 0) txt += StringFormat("Entry: %s\nSL: %s\nTP: %s", DoubleToString(entry, _Digits),


DoubleToString(sl, _Digits), DoubleToString(tp, _Digits));

else txt += "No BOS detected";

ObjectSetString(0, g_panel_txt_name, OBJPROP_TEXT, txt);

//+------------------------------------------------------------------+

//| End of file |

//+------------------------------------------------------------------+

You might also like