diff --git a/Indicators/x-saherelm.xsmc.mq5 b/Indicators/x-saherelm.xsmc.mq5 new file mode 100644 index 00000000..337f3a0d --- /dev/null +++ b/Indicators/x-saherelm.xsmc.mq5 @@ -0,0 +1,186 @@ +//+------------------------------------------------------------------+ +//| SMC_Indicator.mq5 | +//| Smart Money Concepts Indicator for MT5 | +//+------------------------------------------------------------------+ + +#include "../Libraries/x-saherelm.common.lib.mq5"; + +#property indicator_chart_window +#property indicator_buffers 8 +#property indicator_color1 clrGreen // BOS Up +#property indicator_color2 clrRed // BOS Down +#property indicator_color3 clrBlue // Order Block +#property indicator_color4 clrOrange // FVG +#property indicator_color5 clrPurple // Liquidity Zones +#property indicator_color6 clrMagenta // Premium/Discount Levels +#property indicator_color7 clrYellow // Equal Highs +#property indicator_color8 clrCyan // Equal Lows + +// Indicator buffers +double BosUpBuffer[]; +double BosDownBuffer[]; +double OrderBlockBuffer[]; +double FvgBuffer[]; +double LiquidityBuffer[]; +double PremiumBuffer[]; +double EqualHighBuffer[]; +double EqualLowBuffer[]; + +// Input parameters for customization +input int swingRange = 2; // Range to detect swing highs/lows +input int orderBlockLookback = 20; // Bars to look back for order blocks +input int fvgDepth = 3; // Depth for fair value gaps +input bool enableAlerts = true; // Enable alerts for SMC signals + +//+------------------------------------------------------------------+ +//| Initialization | +//+------------------------------------------------------------------+ +int OnInit() +{ + SetIndexBuffer(0, BosUpBuffer, INDICATOR_DATA); + SetIndexBuffer(1, BosDownBuffer, INDICATOR_DATA); + SetIndexBuffer(2, OrderBlockBuffer, INDICATOR_DATA); + SetIndexBuffer(3, FvgBuffer, INDICATOR_DATA); + SetIndexBuffer(4, LiquidityBuffer, INDICATOR_DATA); + SetIndexBuffer(5, PremiumBuffer, INDICATOR_DATA); + SetIndexBuffer(6, EqualHighBuffer, INDICATOR_DATA); + SetIndexBuffer(7, EqualLowBuffer, INDICATOR_DATA); + + IndicatorSetString(INDICATOR_SHORTNAME, "Smart Money Concepts Indicator"); + + return INIT_SUCCEEDED; +} + +//+------------------------------------------------------------------+ +//| Swing High and Low Detection | +//+------------------------------------------------------------------+ +bool isSwingHigh(int index) +{ + double high = iHigh(_Symbol, _Period, index); + for (int i = 1; i <= swingRange; i++) + { + if (iHigh(_Symbol, _Period, index + i) >= high || iHigh(_Symbol, _Period, index - i) >= high) + return false; + } + return true; +} + +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +bool isSwingLow(int index) +{ + double low = iLow(_Symbol, _Period, index); + for (int i = 1; i <= swingRange; i++) + { + if (iLow(_Symbol, _Period, index + i) <= low || iLow(_Symbol, _Period, index - i) <= low) + return false; + } + return true; +} + +//+------------------------------------------------------------------+ +//| Detect Order Blocks | +//+------------------------------------------------------------------+ +void detectOrderBlocks(int rates_total) +{ + ArrayInitialize(OrderBlockBuffer, 0); + + for (int i = rates_total - orderBlockLookback - 1; i >= swingRange; i--) + { + if (isSwingHigh(i)) + { + OrderBlockBuffer[i] = iHigh(_Symbol, _Period, i); // Bullish Order Block + } + else if (isSwingLow(i)) + { + OrderBlockBuffer[i] = iLow(_Symbol, _Period, i); // Bearish Order Block + } + } +} + +//+------------------------------------------------------------------+ +//| Detect Fair Value Gaps | +//+------------------------------------------------------------------+ +void detectFairValueGaps(int rates_total) +{ + ArrayInitialize(FvgBuffer, 0); + + for (int i = rates_total - fvgDepth - 1; i >= swingRange; i--) + { + if (iHigh(_Symbol, _Period, i) < iLow(_Symbol, _Period, i - fvgDepth)) + { + FvgBuffer[i] = (iHigh(_Symbol, _Period, i) + iLow(_Symbol, _Period, i - fvgDepth)) / 2.0; // FVG midpoint + } + } +} + +//+------------------------------------------------------------------+ +//| Detect Liquidity Zones | +//+------------------------------------------------------------------+ +void detectLiquidityZones(int rates_total) +{ + // + ArrayInitialize(LiquidityBuffer, 0); + + // + double points = GetPoints(_Symbol); + + // + for (int i = rates_total - swingRange - 1; i >= swingRange; i--) + { + if (isSwingHigh(i)) + { + LiquidityBuffer[i] = iHigh(_Symbol, _Period, i) + (points * 10); // Above swing high for liquidity pool + } + else if (isSwingLow(i)) + { + LiquidityBuffer[i] = iLow(_Symbol, _Period, i) - (points * 10); // Below swing low for liquidity pool + } + } +} + +//+------------------------------------------------------------------+ +//| Detect Equal Highs and Lows | +//+------------------------------------------------------------------+ +void detectEqualHighsLows(int rates_total) +{ + ArrayInitialize(EqualHighBuffer, 0); + ArrayInitialize(EqualLowBuffer, 0); + + for (int i = rates_total - swingRange - 1; i >= swingRange; i--) + { + if (isSwingHigh(i) && iHigh(_Symbol, _Period, i) == iHigh(_Symbol, _Period, i + swingRange)) + { + EqualHighBuffer[i] = iHigh(_Symbol, _Period, i); + } + else if (isSwingLow(i) && iLow(_Symbol, _Period, i) == iLow(_Symbol, _Period, i + swingRange)) + { + EqualLowBuffer[i] = iLow(_Symbol, _Period, i); + } + } +} + +//+------------------------------------------------------------------+ +//| Main Calculation Loop | +//+------------------------------------------------------------------+ +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[]) +{ + + detectOrderBlocks(rates_total); + detectFairValueGaps(rates_total); + detectLiquidityZones(rates_total); + detectEqualHighsLows(rates_total); + + return rates_total; +} +//+------------------------------------------------------------------+ diff --git a/Libraries/x-saherelm.x-poi.lib.mq5 b/Libraries/x-saherelm.x-poi.lib.mq5 index 284bd0dc..284c47d0 100644 --- a/Libraries/x-saherelm.x-poi.lib.mq5 +++ b/Libraries/x-saherelm.x-poi.lib.mq5 @@ -347,6 +347,229 @@ class XCZone : public XCBasePOI // }; +// +// From To Zone ... +class XCFromToZone : public XCBasePOI +{ + // + public: + // + + // + // Constructor ... + void XCFromToZone() + { + } + + // + // Deconstructor ... + void ~XCFromToZone() + { + } + + // + // Tools ... + + bool InitFromTo( + ENUM_XPOIS type, + string title, + datetime from // + ) + { + // + bool result = false; + + // + result = type != X_POI_NONE && + IsSpecifiedValid(from) && + IsSpecifiedValid(title); + + // + mType = type; + mFrom = from; + mTitle = title; + mTo = TimeCurrent(); + + // + result = IsValid(); + + // + return result; + } + + bool InitFromTo( + ENUM_XPOIS type, + string title, + datetime from, + datetime to // + ) + { + // + bool result = false; + + // + result = IsValid(); + + // + result = InitFromTo( + type, + title, + from // + ); + if (!result) + { + return result; + } + + // + to = NormalizeTime(to); + mTo = to; + + // + result = IsValid(); + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Get Zone Start Time ... + * + * @return ( datetime ) + */ + datetime From() + { + return mFrom; + } + + /** + * Set Zone Start Time ... + * + * @param value: Datetime + */ + void From(datetime value) + { + // + value = NormalizeTime(value); + + // + mFrom = value; + } + + /** + * Get Zone End Time ... + * + * @return ( datetime ) + */ + datetime To() + { + return mTo; + } + + /** + * Set Zone End Time ... + * + * @param value: Datetime + */ + void To(datetime value) + { + // + value = NormalizeTime(value); + + // + mTo = value; + } + + /** + * Get Title ... + * + * @return ( string ) + */ + string Title() + { + return mTitle; + } + + /** + * Set Title ... + * + * @param value: String ... + */ + // void Title(string value) + // { + // mTitle = value; + // } + + // + // Overrides ... + + void Clean() override + { + // + mTo = NULL; + mFrom = NULL; + mType = X_POI_NONE; + } + + bool IsValid() override + { + // + bool result = false; + + // + result = + // + mType != X_POI_NONE && + IsSpecifiedValid(mTo) && + IsSpecifiedValid(mFrom) && + IsSpecifiedValid(mTitle) + // + ; + + // + return result; + } + + string GetTag() override + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + string hash = TypeAsString() + mSep + ToString(From()) + mSep + Title(); + hash = ToMD5(hash); + + // + result = TypeAsString() + "[" + Title() + "]" + mSep + hash; + + // + return result; + } + + // + protected: + // + + // + private: + // + // Props ... + datetime mFrom; // Start Date + datetime mTo; // End Date + string mTitle; // Zone Title + + // +}; + // // Bar Zone ... class XCBarZone : public XCZone @@ -1820,7 +2043,7 @@ class XCFVG : public XCTwoBarZone // result = InitTwoBarZone( - firstBar, + startBar, endBar, mTT, useFistForUpper, @@ -1887,7 +2110,7 @@ class XCFVG : public XCTwoBarZone bool result = false; // - result = IsValidBarZone() && + result = IsValidTwoBarZone() && (mType == X_POI_BULLISH_ORDERBLOCK || mType == X_POI_BEARISH_ORDERBLOCK); @@ -1906,6 +2129,18 @@ class XCFVG : public XCTwoBarZone // }; +// +// TODO: Implement this ... +class XCDay : public XCFromToZone +{ +}; + +// +// TODO: Implement this ... +class XCSession : public XCFromToZone +{ +}; + // //