/////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 Class Library // -------------------------------------- // Name: XCX121SMCTestStrategy // Description: provides all based classes for use ... // // // Maintainer: // ------------ // Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) // ////////////////////////////////////////////////////// // // Global Properties ... #property library #property copyright "Copyright 2023, SaherElm IT Center" #property link "https://www.saherelm.ir" #property version "1.00" #property strict // // Imports ... // #include "../../Helpers/x-saherelm.xchvwap.helper.mq5" #include "../../Helpers/x-saherelm.xpv.helper.mq5" #include "../Classes/x-121.smc.base.strategy.class.mq5" // // Helper(s) ... // // XStrategy Class Implementation(s) ... class XCX121SMCTestStrategy : public XCX121SMCBaseStrategy { // // Public ... public: // // // Constructor(s) ... void XCX121SMCTestStrategy( // // Base ... string _symbol, // Trading Symbol ENUM_TIMEFRAMES _period // Trading TimeFrame ) : XCX121SMCBaseStrategy(_symbol, _period) { InitialHelpers(); } // // Deconstructor ... void ~XCX121SMCTestStrategy() { // delete pvHelper; delete chvwapHelper; } // // Overrides Actions ... // // Check Conditions For Signal ... bool HasSignal( XSignal &signal, X121SMCStrategyConditions &conditions // ) override { // bool result = false; // signal.Clean(); conditions.Clean(); // int pushers = 0; // double sl = 0; double tp = 0; double risk = 0; double entry = 0; double reward = 0; double r2r = R2R(); double volume = Volume(); ENUM_POSITION_TYPE type = POSITION_TYPE_BUY; ENUM_X_ORDER_MODES mode = X_ORDER_MODE_MARKET; // bool hasLong = false; bool hasShort = false; // bool isAllowLong = AllowLong(); bool isAllowShort = AllowShort(); result = isAllowLong || isAllowShort; if (!result) { return result; ; } // // Start Calculations ... // string _symbol = GetSymbol(); ENUM_TIMEFRAMES _period = GetPeriod(); // double points = GetPoints(_symbol); double pip = GetPipPrice(_symbol); double pip2 = 2 * pip; double pip3 = 3 * pip; // int zIndex = 0; int cIndex = zIndex + 1; int pIndex = cIndex + 1; int ppIndex = pIndex + 1; // int loopback = 7; string symbol = _symbol; int dest = cIndex + loopback; datetime cTime = TimeCurrent(); ENUM_TIMEFRAMES period = _period; // // Retrieve Bars ... // // Zero Bar ... XOHCL zBar; result = zBar.Init( _symbol, _period, zIndex // ); if (!result) { return result; } // // Last Bar ... XOHCL cBar; result = cBar.Init( _symbol, _period, cIndex // ); if (!result) { return result; } // // Previous Bar ... XOHCL pBar; result = pBar.Init( _symbol, _period, pIndex // ); if (!result) { return result; } // bool isSpreadPassed = IsSpreadPass(); result = isSpreadPassed; if (!result) { return result; } // // Ticks States ... bool isTicksBullish = IsTicksBullish(); bool isTicksBearish = IsTicksBearish(); bool isTicksHasMomentum = IsTicksHasMomentum(); // // Reading Indicator's Conditions ... XCHVWAPConditions chvwapConditions; chvwapHelper.GetConditions( chvwapConditions, cIndex, loopback // ); // // Select a Supply Zone which Price is Inside it ... XZone aSupplyZone; XZone aSupplyZoneTrigger; bool hasSupplyZoneArroundCBar = false; bool hasTriggerSupplyZoneArroundCBar = false; int aSupplyZonesCount = ArraySize(_15MState.supplyZones); int aSupplyZonesTriggerCount = ArraySize(_5MState.supplyZones); if (!hasSupplyZoneArroundCBar || !hasTriggerSupplyZoneArroundCBar) { for (int i = 0; i < aSupplyZonesCount; i++) { // XZone iZone = _15MState.supplyZones[i]; // bool canSetZone = (!hasSupplyZoneArroundCBar && iZone.lower < cBar.low && iZone.upper > cBar.high) || (hasSupplyZoneArroundCBar && aSupplyZone.lower < cBar.low && aSupplyZone.upper > cBar.high && iZone.lower < cBar.low && iZone.upper > cBar.high && iZone.GetRange() < aSupplyZone.GetRange()); if (canSetZone && !hasTriggerSupplyZoneArroundCBar && IsValidSize(aSupplyZonesTriggerCount)) { // for (int j = 0; j < aSupplyZonesTriggerCount; j++) { // XZone jZone = _5MState.supplyZones[j]; // bool canSetTriggerZone = (!hasTriggerSupplyZoneArroundCBar && jZone.lower < cBar.low && jZone.upper > cBar.high) || (hasTriggerSupplyZoneArroundCBar && aSupplyZoneTrigger.lower < cBar.low && aSupplyZoneTrigger.upper > cBar.high && jZone.lower < cBar.low && jZone.upper > cBar.high && jZone.GetRange() < aSupplyZoneTrigger.GetRange()); if (canSetTriggerZone) { // iZone.to = cTime; jZone.to = cTime; aSupplyZone = iZone; aSupplyZoneTrigger = jZone; hasSupplyZoneArroundCBar = true; hasTriggerSupplyZoneArroundCBar = true; // break; } } } } } // // XZone supplyZone; // int supplyZonesCount = ArraySize(_5MState.supplyZones); // bool hasSupplyZoneOverCBar = IsValidSize(supplyZonesCount); // if (hasSupplyZoneOverCBar) // { // // // hasSupplyZoneOverCBar = false; // for (int i = 0; i < supplyZonesCount; i++) // { // // // XZone iZone = _5MState.supplyZones[i]; // // // if (!hasSupplyZoneOverCBar && // iZone.lower > cBar.high) // { // // // iZone.to = cTime; // supplyZone = iZone; // hasSupplyZoneOverCBar = true; // // // // // break; // } // } // } // XZone demandZone; int demandZonesCount = ArraySize(_5MState.demandZones); bool hasDemandZoneUnderCBar = IsValidSize(demandZonesCount); if (hasDemandZoneUnderCBar) { // hasDemandZoneUnderCBar = false; for (int i = 0; i < demandZonesCount; i++) { // XZone iZone = _5MState.demandZones[i]; // if (!hasDemandZoneUnderCBar && iZone.upper < cBar.low) { // iZone.to = cTime; demandZone = iZone; hasDemandZoneUnderCBar = true; // break; } } } // XOHCL swingHigh; int swingHighsCount = ArraySize(_5MState.swingHighs); bool hasSwingHighOverCBar = IsValidSize(swingHighsCount); if (hasSwingHighOverCBar) { // hasSwingHighOverCBar = false; for (int i = 0; i < swingHighsCount; i++) { // XOHCL iBar = _5MState.swingHighs[i]; // if (!hasSwingHighOverCBar && iBar.high > cBar.high) { // swingHigh = iBar; hasSwingHighOverCBar = true; // break; } } } // XOHCL swingLow; int swingLowsCount = ArraySize(_5MState.swingLows); bool hasSwingLowUnderCBar = IsValidSize(swingLowsCount); if (hasSwingLowUnderCBar) { // hasSwingLowUnderCBar = false; for (int i = 0; i < swingLowsCount; i++) { // XOHCL iBar = _5MState.swingLows[i]; // if (!hasSwingLowUnderCBar && iBar.low < cBar.low) { // swingLow = iBar; hasSwingLowUnderCBar = true; // break; } } } // XOHCL bullishRejectionBar; XOHCL bearishRejectionBar; bool hasBullishRejectionBarUnderCBar = false; bool hasBearishRejectionBarOverCBar = false; int rejectionBarsCount = ArraySize(_5MState.rejectionBars); if (IsValidSize(rejectionBarsCount)) { // for (int i = 0; i < rejectionBarsCount; i++) { // XOHCL iBar = _5MState.rejectionBars[i]; // bool isBullish = iBar.GetLowShadow() > iBar.GetHighShadow(); bool isBearish = iBar.GetHighShadow() > iBar.GetLowShadow(); // if (isBullish && !hasBullishRejectionBarUnderCBar && iBar.high < cBar.low) { // bullishRejectionBar = iBar; hasBullishRejectionBarUnderCBar = true; } // if (isBearish && !hasBearishRejectionBarOverCBar && iBar.low > cBar.high) { // bearishRejectionBar = iBar; hasBearishRejectionBarOverCBar = true; } } } // // // bool isBullish = // // // ( // // // ( // // // // Common Conditions ... // // // // Check Has Swing Low Under CBar ... // hasSwingLowUnderCBar && // // // // Check has a Demand Zone Under CBar ... // hasDemandZoneUnderCBar && // // // // Check Candle is Strong ... // cBar.IsBullishDecision() && // // // // Check Has a Bullish Rejection Bar Under CBar ... // hasBullishRejectionBarUnderCBar && // // // ( // // // // First ... // ( // // // cBar.open < chvwapConditions.s[0] && // cBar.open < chvwapConditions.m[0] && // cBar.open < chvwapConditions.l[0] && // cBar.open < chvwapConditions.h[0] && // // // cBar.close > chvwapConditions.s[0] && // cBar.close > chvwapConditions.m[0] && // cBar.close > chvwapConditions.l[0] && // cBar.close > chvwapConditions.h[0] // // // ) // // // || // // // // Seccend ... // ( // // // chvwapConditions.s[0] > chvwapConditions.m[0] && // chvwapConditions.m[0] > chvwapConditions.l[0] && // chvwapConditions.l[0] > chvwapConditions.h[0] && // // // cBar.close > chvwapConditions.s[0] // // // ) // // // ) // // // ) // // // ); // // // bool isBearish = // // // ( // // // ( // // // // Common Conditions ... // // // // Check Has Swing High Over CBar ... // hasSwingHighOverCBar && // // // // Check Has Supply Zone Over CBar ... // hasSupplyZoneOverCBar && // // hasTriggerSupplyZoneArroundCBar && // // // // Check Candle is Strong ... // cBar.IsBearishDecision() && // // // // Check Has a Bearish Rejection Bar Over CBar ... // hasBearishRejectionBarOverCBar && // // // ( // // // // First ... // ( // // // cBar.open > chvwapConditions.s[0] && // cBar.open > chvwapConditions.m[0] && // cBar.open > chvwapConditions.l[0] && // cBar.open > chvwapConditions.h[0] && // // // cBar.close < chvwapConditions.s[0] && // cBar.close < chvwapConditions.m[0] && // cBar.close < chvwapConditions.l[0] && // cBar.close < chvwapConditions.h[0] // // // ) // // // || // // // // Second ... // ( // // // chvwapConditions.s[0] < chvwapConditions.m[0] && // chvwapConditions.m[0] < chvwapConditions.l[0] && // chvwapConditions.l[0] < chvwapConditions.h[0] && // // // cBar.close < chvwapConditions.s[0] // // // ) // // // ) // // // ) // // // ); // // Not Have Demand Zone inside Supply ... bool notHaveDemandInsideSupplyZone = !hasTriggerSupplyZoneArroundCBar ? false : !demandZone.IsValid() ? true : demandZone.lower > aSupplyZone.upper; // // Check Breakeout ... double lowerlow = aSupplyZoneTrigger.lower; // aSupplyZoneTrigger.lower < aSupplyZone.lower // ? aSupplyZoneTrigger.lower // : aSupplyZone.lower; // bool isBreaked = // cBar.GetUp() > lowerlow && cBar.GetDown() < lowerlow // ; // bool isBullish = // false // ; // bool isBearish = // ( // // Common Conditions ... // // Check Break of Zone ... // isBreaked && // // Bar Trend ... cBar.IsBearish() && (cBar.IsShootingStar() || cBar.IsBearishDecision() || cBar.IsBearishEngulfing() || cBar.IsBearishMarubozu() || cBar.HasStrongHighShadow()) && // // Ticks Conditions ... // isTicksBearish && isTicksHasMomentum && // // Swing ... hasSwingHighOverCBar && // // Rejection Bar ... hasBearishRejectionBarOverCBar && // // Check Demand not be in down of supply ... notHaveDemandInsideSupplyZone && // // Supply Zone ... hasTriggerSupplyZoneArroundCBar // ) // ; // if (isBullish || isBearish) { // double pvPOIss[]; DetectPVPOIs( pvPOIss // ); // // Draw supply if Exists ... // if (hasSupplyZoneOverCBar) // { // // // XCSupplyZoneObject *iObj; // bool isCreated = mPOIDrawer.CreateSupplyZone( // supplyZone, // iObj // // ); // if (isCreated) // { // mDrawnObjects.Add(iObj); // } // } // if (hasSupplyZoneArroundCBar) { // XCSupplyZoneObject *iObj; bool isCreated = mPOIDrawer.CreateSupplyZone( aSupplyZone, iObj // ); if (isCreated) { mDrawnObjects.Add(iObj); } } // if (hasTriggerSupplyZoneArroundCBar) { // XCSupplyZoneObject *iObj; bool isCreated = mPOIDrawer.CreateSupplyZone( aSupplyZoneTrigger, iObj // ); // if (isCreated) { mDrawnObjects.Add(iObj); } } // // Draw Demand if Exists ... if (hasDemandZoneUnderCBar) { // XCDemandZoneObject *iObj; bool isCreated = mPOIDrawer.CreateDemandZone( demandZone, iObj // ); if (isCreated) { mDrawnObjects.Add(iObj); } } // // Draw Swing High ... if (hasSwingHighOverCBar) { // XCSwingHighObject *iObj; bool isCreated = mPOIDrawer.CreateSwingHigh( swingHigh, iObj // ); if (isCreated) { mDrawnObjects.Add(iObj); } } // // Draw Swing Low ... if (hasSwingLowUnderCBar) { // XCSwingLowObject *iObj; bool isCreated = mPOIDrawer.CreateSwingLow( swingLow, iObj // ); if (isCreated) { mDrawnObjects.Add(iObj); } } // // Draw Bullish Rejection Bar ... if (hasBullishRejectionBarUnderCBar) { // XCBullishRejectionBarObject *iObj; bool isCreated = mPOIDrawer.CreateBullishRejectionBar( bullishRejectionBar, iObj // ); if (isCreated) { mDrawnObjects.Add(iObj); } } // // Draw Bearish Rejection Bar ... if (hasBearishRejectionBarOverCBar) { // XCBearishRejectionBarObject *iObj; bool isCreated = mPOIDrawer.CreateBearishRejectionBar( bearishRejectionBar, iObj // ); if (isCreated) { mDrawnObjects.Add(iObj); } } // Print(""); // hasLong = isBullish; // hasShort = isBearish; } // result = hasLong || hasShort; if (!result) { conditions.Clean(); } // // Rmove Signal Condition ... if (result) { // // TYPE ... type = hasLong ? POSITION_TYPE_BUY : POSITION_TYPE_SELL; ENUM_X_POSITION_TYPES xType = hasLong ? X_POSITION_TYPE_LONG : X_POSITION_TYPE_SHORT; // entry = GetEntry( conditions.symbol, type // ); // double slCandidates[]; // double selectedSL = hasLong ? GetMin(slCandidates) : GetMax(slCandidates); sl = hasLong ? selectedSL - pip3 : selectedSL + pip3; // // RISK Reward ... risk = hasLong ? entry - sl : sl - entry; reward = risk * r2r; tp = hasLong ? entry + reward : entry - reward; // signal.sl = sl; signal.tp = tp; signal.type = type; signal.mode = mode; signal.entry = entry; signal.volume = volume; signal.symbol = _symbol; signal.pushers = pushers; signal.provider = GetTag(); signal.time = TimeCurrent(); signal.period = _5MState.period; // result = PrepareSignal(signal); // hasLong = false; hasShort = false; } // return result; } // // Customize Strategy Identifier ... string GetTag() override { return X121SMCSUPDEMStrategyToken; } // // Protected ... protected: // // // Props ... // // XPV ... XPVInputs pvInputs; XSCXPVHelper *pvHelper; // // XCHVWAP ... XCHVWAPInputs chvwapInputs; XSCXCHVWAPHelper *chvwapHelper; // // Private ... private: // // Props ... /** * Initial Required Indicators Helper ... */ void InitialHelpers() { // string symbol = GetSymbol(); ENUM_TIMEFRAMES period = GetPeriod(); // // Short ... ENUM_X_PERIOD_METHOD scMethod = X_PERIOD_MANUALLY; // How to Find Period ENUM_TIMEFRAMES scPeriod = PERIOD_M15; // Time Period // // Medium ... ENUM_X_PERIOD_METHOD mcMethod = X_PERIOD_MANUALLY; // How to Find Period ENUM_TIMEFRAMES mcPeriod = PERIOD_H1; // Time Period // // Long ... ENUM_X_PERIOD_METHOD lcMethod = X_PERIOD_MANUALLY; // How to Find Period ENUM_TIMEFRAMES lcPeriod = PERIOD_H4; // Time Period // // Hind ... ENUM_X_PERIOD_METHOD hcMethod = X_PERIOD_MANUALLY; // How to Find Period ENUM_TIMEFRAMES hcPeriod = PERIOD_D1; // Time Period // // XPV ... // pvInputs.Default(); // pvInputs.scMethod = scMethod; pvInputs.scPeriod = scPeriod; pvInputs.mcMethod = mcMethod; pvInputs.mcPeriod = mcPeriod; pvInputs.lcMethod = lcMethod; pvInputs.lcPeriod = lcPeriod; pvInputs.hcMethod = hcMethod; pvInputs.hcPeriod = hcPeriod; // pvInputs.showPeaksAndVales = true; pvInputs.showLevels = false; pvInputs.showConsolidations = false; pvInputs.showFibo1Levels = false; pvInputs.showFibo2Levels = false; pvInputs.showFibo3Levels = true; pvInputs.showFibo4Levels = false; pvInputs.showFibo5Levels = false; // pvHelper = new XSCXPVHelper(); pvHelper.Init( symbol, period, pvInputs // ); // // XCHVWAP ... // chvwapInputs.Default(); // chvwapInputs.scMethod = scMethod; chvwapInputs.scPeriod = scPeriod; chvwapInputs.mcMethod = mcMethod; chvwapInputs.mcPeriod = mcPeriod; chvwapInputs.lcMethod = lcMethod; chvwapInputs.lcPeriod = lcPeriod; chvwapInputs.hcMethod = hcMethod; chvwapInputs.hcPeriod = hcPeriod; // chvwapInputs.showShort = true; chvwapInputs.showMedium = true; chvwapInputs.showLong = true; chvwapInputs.showHind = true; // chvwapHelper = new XSCXCHVWAPHelper(); chvwapHelper.Init( symbol, period, chvwapInputs // ); } /** * Detect Direction of VWAP ... * * @return ( bool ) */ ENUM_X_DIRECTION DetectVWAPDirection() { // ENUM_X_DIRECTION result = X_DIRECTION_NONE; // int zIndex = 0; int cIndex = zIndex + 1; int pIndex = cIndex + 1; // int loopback = 7; int dest = cIndex + loopback; string symbol = GetSymbol(); datetime cTime = TimeCurrent(); ENUM_TIMEFRAMES period = GetPeriod(); // // Reading Indicator's Conditions ... XCHVWAPConditions chvwapConditions; chvwapHelper.GetConditions( chvwapConditions, cIndex, loopback // ); // bool isBullishOrdered = // chvwapConditions.m[0] > chvwapConditions.l[0] && chvwapConditions.l[0] > chvwapConditions.h[0] // ; bool isBullishState = // chvwapHelper.IsBullish(chvwapConditions.mState[0]) && chvwapHelper.IsBullish(chvwapConditions.lState[0]) && chvwapHelper.IsBullish(chvwapConditions.hState[0]) // ; bool isBullishDirection = isBullishState && isBullishOrdered; // bool isBearishOrdered = // chvwapConditions.m[0] < chvwapConditions.l[0] && chvwapConditions.l[0] < chvwapConditions.h[0] // ; bool isBearishState = // chvwapHelper.IsBearish(chvwapConditions.mState[0]) && chvwapHelper.IsBearish(chvwapConditions.lState[0]) && chvwapHelper.IsBearish(chvwapConditions.hState[0]) // ; bool isBearishDirection = isBearishState && isBearishOrdered; // if (isBullishDirection && !isBearishDirection) { result = X_DIRECTION_BULLISH; } else if ( isBearishDirection && !isBullishDirection) { result = X_DIRECTION_BEARISH; } // return result; } /** * Detect XPV POIs ... * * @param hhs: Double array ... * @param lls: Double array ... * * @return ( int ) */ int DetectPVPOIs( double &values[] // ) { // int result = 0; // Clean(values); // int zIndex = 0; int cIndex = zIndex + 1; int pIndex = cIndex + 1; // int requiredCount = 10; long chartID = ChartIdentification(); int subWindow = SubWindowIdentification(); // int loopback = 300; int dest = cIndex + loopback; string symbol = GetSymbol(); datetime cTime = TimeCurrent(); ENUM_TIMEFRAMES period = GetPeriod(); // XOHCL cBar; bool isInited = cBar.Init( symbol, period, cIndex // ); if (!isInited) { return result; } // XPVConditions pvConditions; pvHelper.GetConditions( pvConditions, cIndex, loopback // ); // // Find POI ... for (int i = 0; i < loopback; i++) { // int iCount = 0; double iValue = pvConditions.sCHHs[i]; // // Peaks ... for (int j = 0; j < loopback; j++) { // double jValue = pvConditions.peaks[j]; // if (jValue == iValue) { iCount++; } } // // Values ... for (int j = 0; j < loopback; j++) { // double jValue = pvConditions.vales[j]; // if (jValue == iValue) { iCount++; } } // // Resistance ... for (int j = 0; j < loopback; j++) { // double jValue = pvConditions.resistances[j]; // if (jValue == iValue) { iCount++; } } // // Support ... for (int j = 0; j < loopback; j++) { // double jValue = pvConditions.supports[j]; // if (jValue == iValue) { iCount++; } } // // Short Cycle Highest Highs ... for (int j = i + 1; j < loopback; j++) { // double jValue = pvConditions.sCHHs[j]; // if (jValue == iValue) { iCount++; } } // // Short Cycle Lowest Low ... for (int j = 0; j < loopback; j++) { // double jValue = pvConditions.sCLLs[j]; // if (jValue == iValue) { iCount++; } } // // Medium Cycle Highest Highs ... for (int j = 0; j < loopback; j++) { // double jValue = pvConditions.mCHHs[j]; // if (jValue == iValue) { iCount++; } } // // Medium Cycle Lowest Low ... for (int j = 0; j < loopback; j++) { // double jValue = pvConditions.mCLLs[j]; // if (jValue == iValue) { iCount++; } } // // Long Cycle Highest Highs ... for (int j = 0; j < loopback; j++) { // double jValue = pvConditions.lCHHs[j]; // if (jValue == iValue) { iCount++; } } // // Long Cycle Lowest Low ... for (int j = 0; j < loopback; j++) { // double jValue = pvConditions.lCLLs[j]; // if (jValue == iValue) { iCount++; } } // // Hind Cycle Highest Highs ... for (int j = 0; j < loopback; j++) { // double jValue = pvConditions.hCHHs[j]; // if (jValue == iValue) { iCount++; } } // // Hind Cycle Lowest Low ... for (int j = 0; j < loopback; j++) { // double jValue = pvConditions.hCLLs[j]; // if (jValue == iValue) { iCount++; } } // if (iCount >= requiredCount) { // AddIfNotExists( iValue, values // ); } } // result = ArraySize(values); // bool drawPOIs = true; int width = 1; ENUM_LINE_STYLE lineStyle = STYLE_DOT; color clrResistance = clrOrange; color clrSupport = clrTeal; // if (drawPOIs && IsValidSize(result)) { // for (int i = 0; i < result; i++) { // double iValue = values[i]; // datetime time1 = (datetime)((int)cBar.time - (2 * PeriodSeconds(cBar.period))); datetime time2 = (datetime)((int)cBar.time + (2 * PeriodSeconds(cBar.period))); // string hash = "POI_" + ToString(iValue) + "_" + ToString(time1) + ToString(time2); hash = ToMD5(hash); // string iName = "POI_" + ToString(iValue) + "_" + hash; // CChartObjectTrend *iObj; iObj = new CChartObjectTrend(); bool isCreated = iObj.Create( chartID, iName, subWindow, time1, iValue, time2, iValue // ); if (isCreated) { // iObj.Width(width); iObj.Style(lineStyle); // if (iValue > cBar.close) { iObj.Color(clrResistance); } else if (iValue < cBar.close) { iObj.Color(clrSupport); } // mDrawnObjects.Add(iObj); } } } // return result; } // }; //