diff --git a/Documents/BKP/smc.ea.mq5 b/Documents/BKP/smc.ea.mq5 new file mode 100644 index 00000000..d8e5e617 --- /dev/null +++ b/Documents/BKP/smc.ea.mq5 @@ -0,0 +1,418 @@ +//+------------------------------------------------------------------+ +//| SMC_OrderBlock_EA.mq5| +//| Copyright 2023, MetaQuotes Software Corp. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2023, MetaQuotes Software Corp." +#property link "https://www.mql5.com" +#property version "1.00" +#property strict + +#include +#include + +// +// Input parameters +input ENUM_TIMEFRAMES TimeFrame = PERIOD_M15; // Timeframe for analysis +input double RiskPercent = 1.0; // Risk per trade (1-2%) +input int ATR_Period = 14; // ATR period for volatility +input int OrderBlockLength = 20; // Bars for consolidation +input int ConfirmationCandles = 3; // Candles to confirm breakout +input double StopLossMultiplier = 1.5; // Stop loss buffer +input double TakeProfitRatio = 2.0; // Risk:Reward ratio +input int TrailingStopPips = 50; // Trailing stop in pips + +// +CTrade trade; +CAccountInfo accountInfo; + +// +double Ask = 0; +double Bid = 0; + +// +// Order Block structure +struct OrderBlock +{ + datetime startTime; + double high; + double low; +}; + +// +int atrHandler = INVALID_HANDLE; +int maFastHandler = INVALID_HANDLE; +int maSlowHandler = INVALID_HANDLE; + +// +double atrs[]; +double fastMAs[]; +double slowMAs[]; + +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() +{ + // + trade.SetExpertMagicNumber(123456); // Unique magic number + + // + atrHandler = iATR(_Symbol, TimeFrame, ATR_Period); + maFastHandler = iMA(_Symbol, TimeFrame, 20, 0, MODE_SMA, PRICE_CLOSE); + maSlowHandler = iMA(_Symbol, TimeFrame, 50, 0, MODE_SMA, PRICE_CLOSE); + + // + bool isValid = + atrHandler != INVALID_HANDLE && + maFastHandler != INVALID_HANDLE && + maSlowHandler != INVALID_HANDLE; + if (!isValid) + { + return (INIT_FAILED); + } + + // + return (INIT_SUCCEEDED); +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) +{ + // + // Cleanup code if needed ... + IndicatorRelease(atrHandler); + IndicatorRelease(maFastHandler); + IndicatorRelease(maSlowHandler); + + // + ZeroMemory(atrs); + ZeroMemory(fastMAs); + ZeroMemory(slowMAs); +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() +{ + // Avoid multiple orders + if (CheckOpenOrders()) + return; + + // + CopyBuffer(atrHandler, MAIN_LINE, 0, 200, atrs); + + // + CopyBuffer(maFastHandler, MAIN_LINE, 0, 2, fastMAs); + CopyBuffer(maSlowHandler, MAIN_LINE, 0, 2, slowMAs); + + // + Ask = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits); // Get the Ask Price + Bid = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits); // Get the Bid Price + + // + // Check for trend and execute trades + if (IsUptrend()) + { + OrderBlock block = FindBullishOrderBlock(); + if (block.startTime != 0 && IsPriceInBlock(block)) + { + if (ConfirmBullishEntry()) + ExecuteTrade(block, ORDER_TYPE_BUY); + } + } + else if (IsDowntrend()) + { + OrderBlock block = FindBearishOrderBlock(); + if (block.startTime != 0 && IsPriceInBlock(block)) + { + if (ConfirmBearishEntry()) + ExecuteTrade(block, ORDER_TYPE_SELL); + } + } + + // Manage trailing stops + TrailStop(); +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Check if price is within the order block | +//+------------------------------------------------------------------+ +bool IsPriceInBlock(OrderBlock &block) +{ + double currentPrice = (Ask + Bid) / 2; // Mid-price + return (currentPrice >= block.low && currentPrice <= block.high); +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Detect uptrend using moving averages | +//+------------------------------------------------------------------+ +bool IsUptrend() +{ + // + double maFast = fastMAs[0]; + double maSlow = slowMAs[0]; + + // + return (maFast > maSlow); +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Detect downtrend using moving averages | +//+------------------------------------------------------------------+ +bool IsDowntrend() +{ + // + double maFast = fastMAs[0]; + double maSlow = slowMAs[0]; + + // + return (maFast < maSlow); +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Find bullish order blocks | +//+------------------------------------------------------------------+ +OrderBlock FindBullishOrderBlock() +{ + // + OrderBlock block; + block.startTime = 0; + + // + for (int i = 1; i < 100; i++) + { + double prevHigh = iHigh(NULL, TimeFrame, i); + double prevLow = iLow(NULL, TimeFrame, i); + double prevClose = iClose(NULL, TimeFrame, i); + double prevOpen = iOpen(NULL, TimeFrame, i); + + double atr = atrs[i]; + if (prevClose - prevOpen > 1.5 * atr) + { // Strong bullish candle + double consolidationHigh = prevHigh; + double consolidationLow = prevLow; + bool isConsolidation = true; + + for (int j = 1; j <= OrderBlockLength; j++) + { + double newHigh = iHigh(NULL, TimeFrame, i - j); + double newLow = iLow(NULL, TimeFrame, i - j); + consolidationHigh = MathMax(consolidationHigh, newHigh); + consolidationLow = MathMin(consolidationLow, newLow); + + if ((consolidationHigh - consolidationLow) > 0.5 * atr) + { + isConsolidation = false; + break; + } + } + + if (isConsolidation) + { + block.high = consolidationHigh; + block.low = consolidationLow; + block.startTime = iTime(NULL, TimeFrame, i); + return block; + } + } + } + return block; +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Find bearish order blocks | +//+------------------------------------------------------------------+ +OrderBlock FindBearishOrderBlock() +{ + // + OrderBlock block; + block.startTime = 0; + + // + for (int i = 1; i < 100; i++) + { + double prevHigh = iHigh(NULL, TimeFrame, i); + double prevLow = iLow(NULL, TimeFrame, i); + double prevClose = iClose(NULL, TimeFrame, i); + double prevOpen = iOpen(NULL, TimeFrame, i); + + double atr = atrs[i]; + if (prevOpen - prevClose > 1.5 * atr) + { // Strong bearish candle + double consolidationHigh = prevHigh; + double consolidationLow = prevLow; + bool isConsolidation = true; + + for (int j = 1; j <= OrderBlockLength; j++) + { + double newHigh = iHigh(NULL, TimeFrame, i - j); + double newLow = iLow(NULL, TimeFrame, i - j); + consolidationHigh = MathMax(consolidationHigh, newHigh); + consolidationLow = MathMin(consolidationLow, newLow); + + if ((consolidationHigh - consolidationLow) > 0.5 * atr) + { + isConsolidation = false; + break; + } + } + + if (isConsolidation) + { + block.high = consolidationHigh; + block.low = consolidationLow; + block.startTime = iTime(NULL, TimeFrame, i); + return block; + } + } + } + return block; +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Confirm bullish entry with candle pattern | +//+------------------------------------------------------------------+ +bool ConfirmBullishEntry() +{ + // + int shift = iBarShift(NULL, TimeFrame, TimeCurrent()); + double prevLow = iLow(NULL, TimeFrame, shift + 1); + double currentClose = iClose(NULL, TimeFrame, shift); + return (currentClose > prevLow && iOpen(NULL, TimeFrame, shift) < currentClose); +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Confirm bearish entry with candle pattern | +//+------------------------------------------------------------------+ +bool ConfirmBearishEntry() +{ + // + int shift = iBarShift(NULL, TimeFrame, TimeCurrent()); + double prevHigh = iHigh(NULL, TimeFrame, shift + 1); + double currentClose = iClose(NULL, TimeFrame, shift); + return (currentClose < prevHigh && iOpen(NULL, TimeFrame, shift) > currentClose); +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Execute trade with risk management | +//+------------------------------------------------------------------+ +void ExecuteTrade(OrderBlock &block, ENUM_ORDER_TYPE orderType) +{ + // + double atr = atrs[0]; + double stopLoss, takeProfit, lotSize; + double entryPrice = (orderType == ORDER_TYPE_BUY) ? Ask : Bid; + + // Calculate stop loss and take profit + if (orderType == ORDER_TYPE_BUY) + { + stopLoss = block.low - StopLossMultiplier * atr; + takeProfit = entryPrice + (entryPrice - stopLoss) * TakeProfitRatio; + } + else + { + stopLoss = block.high + StopLossMultiplier * atr; + takeProfit = entryPrice - (stopLoss - entryPrice) * TakeProfitRatio; + } + + // Calculate lot size based on risk + lotSize = CalculateLotSize(stopLoss, entryPrice, orderType); + if (lotSize <= 0) + return; + + // Place order + if (orderType == ORDER_TYPE_BUY) + { + trade.Buy(lotSize, _Symbol, entryPrice, stopLoss, takeProfit, "SMC Bullish Order Block"); + } + else + { + trade.Sell(lotSize, _Symbol, entryPrice, stopLoss, takeProfit, "SMC Bearish Order Block"); + } +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Calculate lot size based on risk per trade | +//+------------------------------------------------------------------+ +double CalculateLotSize(double stopLoss, double entryPrice, ENUM_ORDER_TYPE orderType) +{ + double riskAmount = AccountBalance() * RiskPercent / 100; + double stopLossPips = MathAbs((entryPrice - stopLoss) / SymbolInfoDouble(_Symbol, SYMBOL_POINT)); + + if (stopLossPips == 0) + return 0; + + double pipValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE); + double lotSize = riskAmount / (stopLossPips * pipValue); + lotSize = NormalizeDouble(lotSize, 2); // Adjust to symbol's lot precision + + return MathMax(lotSize, SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN)); +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Check for existing open orders | +//+------------------------------------------------------------------+ +bool CheckOpenOrders() +{ + for (int i = 0; i < PositionsTotal(); i++) + { + if (PositionGetSymbol(i) == _Symbol) + return true; + } + return false; +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Trailing stop logic | +//+------------------------------------------------------------------+ +void TrailStop() +{ + for (int i = 0; i < PositionsTotal(); i++) + { + if (PositionGetSymbol(i) != _Symbol) + continue; + + ulong ticket = PositionGetInteger(POSITION_TICKET); + ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); + double currentPrice = (type == POSITION_TYPE_BUY) ? Bid : Ask; + double openPrice = PositionGetDouble(POSITION_PRICE_OPEN); + double stopLoss = PositionGetDouble(POSITION_SL); + double trailingStopPrice = (type == POSITION_TYPE_BUY) + ? currentPrice - TrailingStopPips * SymbolInfoDouble(_Symbol, SYMBOL_POINT) + : currentPrice + TrailingStopPips * SymbolInfoDouble(_Symbol, SYMBOL_POINT); + + // Update stop loss if price moves favorably + if ((type == POSITION_TYPE_BUY && trailingStopPrice > stopLoss) || + (type == POSITION_TYPE_SELL && trailingStopPrice < stopLoss)) + { + trade.PositionModify(ticket, trailingStopPrice, PositionGetDouble(POSITION_TP)); + } + } +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Calculate Account Balance | +//+------------------------------------------------------------------+ +double AccountBalance() +{ + return accountInfo.Balance(); +} +//+------------------------------------------------------------------+ diff --git a/Libraries/x-saherelm.x-poi.extensions.lib.mq5 b/Libraries/x-saherelm.x-poi.extensions.lib.mq5 index 2f39a149..12a6f82e 100644 --- a/Libraries/x-saherelm.x-poi.extensions.lib.mq5 +++ b/Libraries/x-saherelm.x-poi.extensions.lib.mq5 @@ -1324,6 +1324,83 @@ bool HasInsideBox( return result; } +bool IsValidBox( + XBoxZone &box, + int barIndex = 0, + ENUM_TIMEFRAMES forPeriod = NULL // +) +{ + // + bool result = false; + + // + result = box.IsValid(); + if (!result) + { + return result; + } + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = box.period; + } + + // + int fromIndex = iBarShift( + box.symbol, + forPeriod, + box.from // + ); + result = IsValidIndex(fromIndex); + if (!result) + { + return result; + } + + // + XOHCL iBar; + bool isBullish = box.IsBullish(); + for (int i = barIndex; i < fromIndex; i++) + { + // + result = iBar.Init( + box.symbol, + forPeriod, + i // + ); + if (!result) + { + break; + } + + // + result = + isBullish + ? iBar.GetDown() > box.lower + : iBar.GetUp() < box.upper; + if (!result) + { + break; + } + + // + iBar.Clean(); + } + + // + iBar.Clean(); + + // + return result; +} + /** * Converts to XBoxZone ... * @@ -2899,14 +2976,14 @@ int FilterZones( /** * Detect Nearest Price Out of Specified Box ... - * + * * @param box: XBoxZone instance Reference ... * @param outSideBar: XOHCL instance Reference which Represents Out Side Bar if Exists ... * @param forPeriod: ENUM_TIMEFRAMES member which provides time frame of Out Bar, if not Provides used box Period as Default ... - * @param forDir: ENUM_X_DIRECTION member which Specified outSide Direction, use Box Dir as Default ... + * @param forDir: ENUM_X_DIRECTION member which Specified outSide Direction, use Box Dir as Default ... * @param forceBodyIn: bool value which Specifyed Body Breakes or not, Default is false ... * @param barIndex: integer value which Specified Start Bar Index, Default is 0 ... - * + * * @return ( bool ) */ bool DetectBoxNearestPriceOut( diff --git a/Libraries/x-saherelm.x-poi.state.lib.mq5 b/Libraries/x-saherelm.x-poi.state.lib.mq5 index d633525b..f50bc125 100644 --- a/Libraries/x-saherelm.x-poi.state.lib.mq5 +++ b/Libraries/x-saherelm.x-poi.state.lib.mq5 @@ -488,11 +488,17 @@ struct XOBFVG continue; } + // + // bool isBarAbove = + // bar.low > iFVG.Upper(); + // bool isBarBelow = + // bar.high < iFVG.Lower(); + // bool isBarAbove = - bar.low > iFVG.Upper(); + bar.GetDown() > iFVG.Upper(); bool isBarBelow = - bar.high < iFVG.Lower(); + bar.GetUp() < iFVG.Lower(); // isValidFVG = diff --git a/X121SMCEA/Signals/x-121.smc.xwz.signal.class.mq5 b/X121SMCEA/Signals/x-121.smc.xwz.signal.class.mq5 index 322d4928..047ff7c4 100644 --- a/X121SMCEA/Signals/x-121.smc.xwz.signal.class.mq5 +++ b/X121SMCEA/Signals/x-121.smc.xwz.signal.class.mq5 @@ -164,12 +164,14 @@ class XCX121SMCXWZSignalDetector : public XCBase double targets[]; double reward = 0; XBoxZone signalBox; - int activatedFVGIDX = 0; - int activatedZoneIDX = 0; - double amountPercent = 0; bool hasPriority = false; + int activatedFVGIDX = -1; + int activatedBoxIDX = -1; + int activatedZoneIDX = -1; + double amountPercent = -1; bool hasSignalBox = false; bool hasWaitingZones = false; + bool hasWaitingBoxes = false; bool hasRewardAmount = false; bool isSignalBoxReversal = false; bool hasWorkingZoneOveralDirection = false; @@ -214,10 +216,14 @@ class XCX121SMCXWZSignalDetector : public XCBase .DetectOveralDirection(wzOveralDir); // + // Detect Zones and Boxes ... hasWaitingZones = workingZone.DetectZone( provider // ); + // + hasWaitingBoxes = workingZone.HasWaitingBoxes(); + // // Checking Working Zone Destory or not ... bool isWorkingZoneDestroyed = workingZone.IsDestroyed( @@ -264,8 +270,7 @@ class XCX121SMCXWZSignalDetector : public XCBase // true, // Draw Supply Zone ... true, // Draw Demand Zone ... - true, // Draw Waiting Zones ... - true // Draw Waiting Zones Box Area ... + true // Draw Waiting Zones ... // ); } @@ -276,7 +281,9 @@ class XCX121SMCXWZSignalDetector : public XCBase // // Detect Signal Box ... - hasSignalBox = + + // + bool isZoneActivated = hasWorkingZone && hasWaitingZones && workingZone.IsZoneActivated( @@ -285,23 +292,38 @@ class XCX121SMCXWZSignalDetector : public XCBase provider, zIndex // ); + + // + bool isBoxActivated = + hasWorkingZone && + hasWaitingBoxes && + workingZone.IsBoxActivated( + activatedBoxIDX, + provider, + zIndex // + ); + + // + hasSignalBox = + isBoxActivated || + isZoneActivated; if (hasSignalBox) { // signalBox.Clean(); // - XOBFVG iOBFVG = workingZone.waitingZones[activatedZoneIDX]; - XCFVG *activatedFVG = iOBFVG.fvgs[activatedFVGIDX]; - hasSignalBox = ToBox( - signalBox, - activatedFVG // - ); - if (hasSignalBox) + if (isZoneActivated) { // - signalBox.to = cTime; - signalBoxDir = signalBox.dir; + XOBFVG iOBFVG = workingZone.waitingZones[activatedZoneIDX]; + XCFVG *activatedFVG = iOBFVG.fvgs[activatedFVGIDX]; + hasSignalBox = ToBox( + signalBox, + activatedFVG // + ); + + // signalProvider = X121SMC_XWZ_PROVIDER_ACTIVATED_ZONE; // @@ -326,13 +348,48 @@ class XCX121SMCXWZSignalDetector : public XCBase 1 // ); } + + // + iOBFVG.Clean(); + ZeroMemory(activatedFVG); } // - iOBFVG.Clean(); - ZeroMemory(activatedFVG); + if (isBoxActivated) + { + // + signalBox = workingZone.waitingBoxes[activatedBoxIDX]; + + // + signalProvider = X121SMC_XWZ_PROVIDER_ACTIVATED_BOX; + + // + AddRef( + signalBox, + workingZone.unavailableBoxes // + ); + + // + ArrayRemove( + workingZone.waitingBoxes, + activatedBoxIDX, + 1 // + ); + } + + // + if (hasSignalBox) + { + // + signalBox.to = cTime; + signalBoxDir = signalBox.dir; + } } + // + // + // + // // Remove Invalidate Zones ... if (hasWaitingZones) @@ -343,6 +400,16 @@ class XCX121SMCXWZSignalDetector : public XCBase hasWaitingZones = workingZone.HasWaitingZones(); } + // + // Remove InValidate Boxes ... + if (hasWaitingBoxes) + { + // + // Validate Waiting Boxes ... + workingZone.ValidateWaitingBoxes(zIndex); + hasWaitingBoxes = workingZone.HasWaitingBoxes(); + } + // // // @@ -413,6 +480,12 @@ class XCX121SMCXWZSignalDetector : public XCBase ? signalBox.upper : signalBox.lower; + // + double entry = GetEntry( + signalBox.symbol, + signalBoxDir // + ); + // double iSL = 0; @@ -432,6 +505,11 @@ class XCX121SMCXWZSignalDetector : public XCBase // } // + double iAtr = provider.decisionXConditions.atrBuffer[1]; + iAtr *= 1.5; + + // + // Default SL ... iSL = pivot; // @@ -443,19 +521,13 @@ class XCX121SMCXWZSignalDetector : public XCBase // // Select Condition SL ... - // - double entry = GetEntry( - signalBox.symbol, - signalBoxDir // - ); - // double slsMin = GetMin(sls); double slsMax = GetMax(sls); // - double longSL = slsMin; - double shortSL = slsMax; + double longSL = slsMin - iAtr; + double shortSL = slsMax + iAtr; // sl = isBullish diff --git a/X121SMCEA/Signals/x-121.smc.xwz.signal.lib.mq5 b/X121SMCEA/Signals/x-121.smc.xwz.signal.lib.mq5 index f4470969..8fbd3d7b 100644 --- a/X121SMCEA/Signals/x-121.smc.xwz.signal.lib.mq5 +++ b/X121SMCEA/Signals/x-121.smc.xwz.signal.lib.mq5 @@ -30,10 +30,8 @@ enum ENUM_X121SMC_XWZ_PROVIDERS { X121SMC_XWZ_PROVIDER_NONE, - X121SMC_XWZ_PROVIDER_PV_ZONE, + X121SMC_XWZ_PROVIDER_ACTIVATED_BOX, X121SMC_XWZ_PROVIDER_ACTIVATED_ZONE, - X121SMC_XWZ_PROVIDER_ACTIVATED_CHOCH, - X121SMC_XWZ_PROVIDER_PRICE_INSIDE_ZONE, }; // @@ -73,6 +71,10 @@ struct X121SMCStrategyXWZWorkingZone XOBFVG waitingZones[]; XOBFVG unavailableZones[]; + // + XBoxZone waitingBoxes[]; + XBoxZone unavailableBoxes[]; + // CArrayObj mDrawnObjects; CArrayObj mWorkingZoneObjects; @@ -101,6 +103,11 @@ struct X121SMCStrategyXWZWorkingZone // Clean(waitingZones); + Clean(unavailableZones); + + // + Clean(waitingBoxes); + Clean(unavailableBoxes); // ZeroMemory(supplyZone); @@ -461,7 +468,8 @@ struct X121SMCStrategyXWZWorkingZone // // Detect OB FVG ... - if (hasNewOrderBlock) + if (false && + hasNewOrderBlock) { // XOHCL obStartedBar; @@ -596,6 +604,104 @@ struct X121SMCStrategyXWZWorkingZone obStartedBar.Clean(); } + // + // + // + + // + // Check New Order Block Detection Analyse ... + XBoxZone analyseOBBox; + XCOrderBlock *analyseOB = NULL; + bool hasNewAnalyseOrderBlock = + Contains( + X_BULLISH_ORDERBLOCK_DETECTED, + provider + .analysePoiEvents // + ) || + Contains( + X_BEARISH_ORDERBLOCK_DETECTED, + provider + .analysePoiEvents // + ); + if (hasNewAnalyseOrderBlock) + { + // + idx = GetYoungest(provider + .analyseState + .orderBlocks // + ); + has = IsValidIndex(idx); + if (has) + { + // + analyseOB = provider + .analyseState + .orderBlocks[idx]; + has = ToBox( + analyseOBBox, + analyseOB // + ); + if (has) + { + // + analyseOB.To(cTime); + analyseOBBox.to = cTime; + hasNewAnalyseOrderBlock = analyseOBBox.IsValid(); + } + } + } + + // + // Checking Analyse Order Block ... + if (hasNewAnalyseOrderBlock) + { + // + XCBaseObject *iObj; + has = provider + .visionCycleHelper + .mPOIDrawer + .CreateOrderBlock( + analyseOB, + iObj // + ); + if (has) + { + // + XOHCL obStartedBar; + bool isOBStartedBodyOut = false; + bool isOBStarted = analyseOB.IsStarted( + analyseOB.GetDirection(), + obStartedBar, + isOBStartedBodyOut // + ); + + // + has = isOBStarted && + isOBStartedBodyOut; + if (has) + { + // + has = IsExists(analyseOBBox); + if (!has) + { + // + AddRef( + analyseOBBox, + waitingBoxes // + ); + } + } + } + } + + // + analyseOBBox.Clean(); + ZeroMemory(analyseOB); + + // + // + // + // result = HasWaitingZones(); @@ -694,6 +800,83 @@ struct X121SMCStrategyXWZWorkingZone return result; } + // + int ValidateWaitingBoxes( + int barIndex = 0 // + ) + { + // + int result = 0; + + // + bool has = false; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (barIndex == 0) + { + barIndex = 1; + } + + // + has = IsValid() && + HasWaitingBoxes(); + if (!has) + { + return result; + } + + // + int removeIDX[]; + result = CountWaitingBoxes(); + for (int i = 0; i < result; i++) + { + // + has = IsValidBox( + waitingBoxes[i], + barIndex, + period // + ); + if (!has) + { + // + Add( + i, + removeIDX // + ); + + // + AddRef( + waitingBoxes[i], + unavailableBoxes // + ); + } + } + + // + has = HasChild(removeIDX); + if (has) + { + // + CleanupArray( + removeIDX, + waitingBoxes // + ); + } + Clean(removeIDX); + + // + result = CountWaitingBoxes(); + + // + return result; + } + // bool IsZoneActivated( int &zoneIDX, @@ -848,17 +1031,17 @@ struct X121SMCStrategyXWZWorkingZone // Activate Zone Using PV ... bool isPVPassed = isBullish - ? vale < iBox.upper && - vale > iBox.lower - : peak < iBox.upper && - peak > iBox.lower; + ? vale <= iBox.upper && + vale >= iBox.lower + : peak <= iBox.upper && + peak >= iBox.lower; bool isPV50Passed = isBullish ? vale < iBox.upper && - vale < iRange && + vale <= iRange && vale > iBox.lower : peak < iBox.upper && - peak < iRange && + peak >= iRange && peak > iBox.lower; // @@ -872,7 +1055,8 @@ struct X121SMCStrategyXWZWorkingZone // // Combine Result ... - result = isPV50Passed; + result = isPVPassed; + // || isPVPassed // || isPV50Passed // || isRejected; if (result) @@ -933,6 +1117,194 @@ struct X121SMCStrategyXWZWorkingZone return result; } + // + bool IsBoxActivated( + int &boxIDX, + X121SMCStrategySignalProviderData &provider, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + boxIDX = -1; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + result = IsValid() && + HasWaitingBoxes(); + if (!result) + { + return result; + } + + // + XOHCL bar; + XOHCL cBar; + result = bar.Init( + symbol, + period, + barIndex // + ); + result = + result && + bar.GetPreviousBar(cBar); + if (!result) + { + // + bar.Clean(); + cBar.Clean(); + + // + return result; + } + + // + // Retrieve Some Required Data ... + + // + double peak = provider.decisionXConditions.peaksBuffer[1]; + double vale = provider.decisionXConditions.valesBuffer[1]; + + // + double analysePeak = provider.analyseXConditions.peaksBuffer[1]; + double analyseVale = provider.analyseXConditions.valesBuffer[1]; + + // + double consolidationPeak = provider.consolidationXConditions.peaksBuffer[1]; + double consolidationVale = provider.consolidationXConditions.valesBuffer[1]; + + // + double visionPeak = provider.visionXConditions.peaksBuffer[1]; + double visionVale = provider.visionXConditions.valesBuffer[1]; + + // + bool isPeaksSame = + peak == analysePeak && + analysePeak == consolidationPeak; + + // + bool isValesSame = + vale == analyseVale && + analyseVale == consolidationVale; + + // + // Calculate Scores Conditions ... + + // + bool isDecisionScoreBullish = + provider.decisionBullishScore > provider.decisionBearishScore; + + // + bool isDecisionScoreBearish = + provider.decisionBearishScore > provider.decisionBullishScore; + + // + bool isAnalyseScoreBullish = + provider.analyseBullishScore > provider.analyseBearishScore; + + // + bool isAnalyseScoreBearish = + provider.analyseBearishScore > provider.analyseBullishScore; + + // + bool isConsolidationScoreBullish = + provider.consolidationBullishScore > provider.consolidationBearishScore; + + // + bool isConsolidationScoreBearish = + provider.consolidationBearishScore > provider.consolidationBullishScore; + + // + bool isVisionScoreBullish = + provider.visionBullishScore > provider.visionBearishScore; + + // + bool isVisionScoreBearish = + provider.visionBearishScore > provider.visionBullishScore; + + // + int count = CountWaitingBoxes(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = waitingBoxes[i]; + bool isBullish = iBox.IsBullish(); + + // + // Checking Rejection ... + + // + // Bullish ... + bool isBullishRejected = + isBullish && + cBar.low <= iBox.upper && + cBar.GetDown() > iBox.upper; + + // + // Bearish ... + bool isBearishRejected = + !isBullish && + cBar.high >= iBox.lower && + cBar.GetUp() < iBox.lower; + + // + // Rejection ... + bool isRejected = isBullishRejected || + isBearishRejected; + + // + // Checking Breaktion ... + + // + // Bullish ... + bool isBullishBreaked = + isBullish && + cBar.high > iBox.upper && + cBar.GetUp() > iBox.upper && + cBar.low >= iBox.lower; + + // + // Bearish ... + bool isBearishBreaked = + !isBullish && + cBar.low < iBox.lower && + cBar.GetDown() < iBox.lower && + cBar.high <= iBox.upper; + + // + // Breaktion ... + bool isBreaked = isBullishBreaked || + isBearishBreaked; + + // + result = isRejected || + isBreaked; + + // + if (result) + { + // + boxIDX = i; + break; + } + // + } + + // + bar.Clean(); + cBar.Clean(); + + // + return result; + } + // bool IsExists(XOBFVG &zone) { @@ -941,8 +1313,9 @@ struct X121SMCStrategyXWZWorkingZone // // Check Validation ... - result = HasWaitingZones() || - HasUnavailableZones(); + result = zone.IsValid() && + (HasWaitingZones() || + HasUnavailableZones()); if (!result) { return result; @@ -979,6 +1352,53 @@ struct X121SMCStrategyXWZWorkingZone return result; } + // + bool IsExists(XBoxZone &box) + { + // + bool result = false; + + // + // Check Validation ... + result = box.IsValid() && + (HasWaitingBoxes() || + HasUnavailableBoxes()); + if (!result) + { + return result; + } + + // + int idx = -1; + + // + // Check Index in Waiting Zones ... + idx = FindIndex( + box, + waitingBoxes // + ); + result = IsValidIndex(idx); + if (result) + { + return result; + } + + // + // Check Index in Unavailable Zones ... + idx = FindIndex( + box, + unavailableBoxes // + ); + result = IsValidIndex(idx); + if (result) + { + return result; + } + + // + return result; + } + // bool IsDestroyed( int barIndex = 0, @@ -1330,6 +1750,18 @@ struct X121SMCStrategyXWZWorkingZone } } + // + has = HasWaitingBoxes(); + if (has) + { + // + count = CountWaitingBoxes(); + for (int i = 0; i < count; i++) + { + waitingBoxes[i].to = value; + } + } + // } @@ -1338,9 +1770,7 @@ struct X121SMCStrategyXWZWorkingZone XCPOIDrawer *drawer, bool drawSupplyZone = false, bool drawDemandZone = false, - bool drawWaitingZones = false, - bool drawWaitingZonesBoxArea = false // - ) + bool drawWaitingZones = false) { // if (drawer == NULL) @@ -1605,30 +2035,54 @@ struct X121SMCStrategyXWZWorkingZone } // - if (drawWaitingZonesBoxArea) - { - // - XBoxZone iBox; - has = waitingZones[i].ToZone( - iBox // - ); - if (has) - { - // - XCBoxObject *iBoxObj; - has = drawer.DrawBox( - iBox, - iBoxObj // - ); - if (has) - { - mDrawnObjects.Add(iBoxObj); - } - } + // if (drawWaitingZonesBoxArea) + // { + // // + // XBoxZone iBox; + // has = waitingZones[i].ToZone( + // iBox // + // ); + // if (has) + // { + // // + // XCBoxObject *iBoxObj; + // has = drawer.DrawBox( + // iBox, + // iBoxObj // + // ); + // if (has) + // { + // mDrawnObjects.Add(iBoxObj); + // } + // } - // - iBox.Clean(); + // // + // iBox.Clean(); + // } + } + } + + // + has = HasWaitingBoxes(); + if (has) + { + // + count = CountWaitingBoxes(); + for (int i = 0; i < count; i++) + { + // + XCBoxObject *iBoxObj; + has = drawer.DrawBox( + waitingBoxes[i], + iBoxObj // + ); + if (has) + { + mDrawnObjects.Add(iBoxObj); } + + // + ZeroMemory(iBoxObj); } } } @@ -1678,6 +2132,30 @@ struct X121SMCStrategyXWZWorkingZone return ArraySize(unavailableZones); } + // + bool HasWaitingBoxes() + { + return HasChild(waitingBoxes); + } + + // + int CountWaitingBoxes() + { + return ArraySize(waitingBoxes); + } + + // + bool HasUnavailableBoxes() + { + return HasChild(unavailableBoxes); + } + + // + int CountUnavailableBoxes() + { + return ArraySize(unavailableBoxes); + } + // };