/////////////////////////////////////////////////////// // // 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; } // // Reading Indicator's Conditions ... XCHVWAPConditions chvwapConditions; chvwapHelper.GetConditions( chvwapConditions, cIndex, loopback // ); // // Select a Supply Zone which Price is Inside it ... XZone supplyZone; XZone aSupplyZone; bool hasSupplyZoneArroundCBar = false; 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; } // if ((!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())) { aSupplyZone = iZone; } } } // 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 && // // 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] // ) // ) // ) // ); // 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); } } // // 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; } // }; //