diff --git a/Classes/x-saherelm.x-chart-objects.class.mq5 b/Classes/x-saherelm.x-chart-objects.class.mq5 index edb4eb52..798eea09 100644 --- a/Classes/x-saherelm.x-chart-objects.class.mq5 +++ b/Classes/x-saherelm.x-chart-objects.class.mq5 @@ -20,7 +20,7 @@ #property strict // -#include "../Libraries/x-saherelm.common.lib.mq5" +#include "../Libraries/x-saherelm.x-poi.lib.mq5" // #include @@ -31,13 +31,15 @@ enum ENUM_XCHARTOBJECTS { + X_FROM_TO, X_TRADE_DAY, + X_MARKET_SESSION, }; -enum ENUM_X_TRADE_DAY_IDS +enum ENUM_X_CHART_IDS { - X_TRADE_DAY_FROM, - X_TRADE_DAY_TO + X_FROM, + X_TO }; // @@ -50,7 +52,7 @@ enum ENUM_X_TRADE_DAY_IDS * * @return ( string ) */ -string ToString(ENUM_X_TRADE_DAY_IDS value) +string ToString(ENUM_X_CHART_IDS value) { // string result = NULL; @@ -59,12 +61,12 @@ string ToString(ENUM_X_TRADE_DAY_IDS value) switch (value) { // - case X_TRADE_DAY_FROM: + case X_FROM: result = "XFROM"; break; // - case X_TRADE_DAY_TO: + case X_TO: result = "XTO"; break; } @@ -75,7 +77,10 @@ string ToString(ENUM_X_TRADE_DAY_IDS value) // // Implementation ... -class XCTardeDayObject : public CChartObject + +// +// From To Chart Object ... +class XCFromToObject : public CChartObject { // public: @@ -83,18 +88,18 @@ class XCTardeDayObject : public CChartObject // // Constructors ... - void XCTardeDayObject() + void XCFromToObject() { } // // Deconstructors ... - void ~XCTardeDayObject() + void ~XCFromToObject() { } /** - * Create XTradeDayChartObject ... + * Create XCFromToObject ... * * @param chart_id: Long ... * @param name: String ... @@ -109,14 +114,19 @@ class XCTardeDayObject : public CChartObject const string name, const int window, const datetime from, - const datetime to // + const datetime to, + const string objprefix = NULL // ) { // bool result = false; // - string mFromVLineName = ToString(X_TRADE_DAY_FROM) + "_" + name; + string mPrefix = (IsValid(objprefix) ? objprefix + "_" : ""); + + // + string mFromVLineName = + mPrefix + ToString(X_FROM) + "_" + name; result = mFromVLine.Create(chart_id, mFromVLineName, window, from); if (!result) { @@ -124,20 +134,14 @@ class XCTardeDayObject : public CChartObject } // - string mToVLineName = ToString(X_TRADE_DAY_TO) + "_" + name; + string mToVLineName = + mPrefix + ToString(X_TO) + "_" + name; result = mToVLine.Create(chart_id, mToVLineName, window, to); if (!result) { return result; } - // - // result = Attach(chart_id, name, window, 2); - // if (!result) - // { - // return result; - // } - // return result; } @@ -149,7 +153,7 @@ class XCTardeDayObject : public CChartObject */ virtual ENUM_XCHARTOBJECTS Type() { - return X_TRADE_DAY; + return X_FROM_TO; } /** @@ -214,3 +218,132 @@ class XCTardeDayObject : public CChartObject }; // +// XTradeDay Object ... +class XCTardeDayObject : public XCFromToObject +{ + // + public: + // + + // + // Constructors ... + void XCTardeDayObject() + { + } + + // + // Deconstructors ... + void ~XCTardeDayObject() + { + } + + bool CreateByDay( + long chart_id, + const string name, + const int window, + XTradeDay &day // + ) + { + // + bool result = false; + + // + result = Create( + chart_id, + name, + window, + day.from, + day.to, + "XTDAY" // + ); + + // + return result; + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_TRADE_DAY; + } + + // + protected: + // + + // + private: + // + // +}; + +// +// XMarketSession Object ... +class XCMarketSessionObject : public XCFromToObject +{ + // + public: + // + + // + // Constructors ... + void XCMarketSessionObject() + { + } + + // + // Deconstructors ... + void ~XCMarketSessionObject() + { + } + + bool CreateByMarketSession( + long chart_id, + const string name, + const int window, + XMarketSession &session // + ) + { + // + bool result = false; + + // + string sessionLabel = ToString(session.session); + result = Create( + chart_id, + name, + window, + session.from, + session.to, + sessionLabel // + ); + + // + return result; + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_MARKET_SESSION; + } + + // + protected: + // + + // + private: + // + // +}; + +// diff --git a/Classes/x-saherelm.x-poi.class.mq5 b/Classes/x-saherelm.x-poi.class.mq5 index 18284778..6eff53c7 100644 --- a/Classes/x-saherelm.x-poi.class.mq5 +++ b/Classes/x-saherelm.x-poi.class.mq5 @@ -33,394 +33,6 @@ #include #include -// -// Definitions ... - -// -// All Available POI(s) ... -enum ENUM_XPOIS -{ - // - // Momentum Bar ... - X_POI_MOMENTUM_BAR, // Momentum Bar ... - // - // Rejection Bar ... - X_POI_REJECTION_BAR, // Rejection Bar ... - // - // Swings ... - X_POI_SWING_HIGH, // Simple Swing High ... - X_POI_SWING_LOW, // Simple Swing Low ... - // - // Support nad Resistance ... - X_POI_SUPPORT, // Support Zone ... - X_POI_RESISTANCE, // Resistance Zone ... -}; - -// -// Event Types ... -enum ENUM_XPOI_EVENTS -{ - // - // Trading Days ... - X_TRADE_DAY_FIRST_BAR, // Trading Day Start ... - X_TRADE_DAY_LAST_BAR, // Trading Day End ... - // - // Session ... - X_SESSION_OPEN, // Session Open ... - X_SESSION_CLOsSE, // Session Close ... - // - // Momentum Bar ... - X_MOMENTUM_BAR_DETECTED, // Momentum Bar ... - // - // Rejection Bar ... - X_REJECTION_BAR_DETECTED, // Rejection Bar ... - // - // Swings ... - X_SWING_HIGH_DETECTED, - X_SWING_LOW_DETECTED, - // - // Support nad Resistance ... - X_SUPPORT_DETECTED, - X_RESISTANCE_DETECTED, -}; - -// -// Forext Sessions ... -enum ENUM_XSESSION -{ - X_TOKYO, - X_SYDNEY, - X_LONDON, - X_NEW_YORK -}; - -// -// Represent a Session Working Time ... -struct XSession -{ - // - // Props ... - ENUM_XSESSION session; // Session Identifier - string start; // Start Time - string end; // End Time - - // - color startColor; - color endColor; - bool allowDraw; - bool drawLabel; - - /** - * Constructor ... - */ - void XSession() - { - Clean(); - } - - /** - * Clean Structure ... - */ - void Clean() - { - // - start = NULL; - end = NULL; - - // - startColor = clrAqua; - endColor = clrAqua; - allowDraw = false; - drawLabel = false; - } - - /** - * Validate Structure ... - * - * @return ( bool ) - */ - bool IsValid() - { - // - bool result = false; - - // - result = IsValid(start) && - IsValid(end); - - // - return result; - } - - /** - * Initialize Specified Session ... - * - * @param _session: ENUM_XSESSION member ... - * @param _start: String (Session Start Time) ... - * @param _end: String (Session End Time) ... - * - * @return ( bool ) - */ - bool Init( - ENUM_XSESSION _session, - string _start, - string _end // - ) - { - // - bool result = false; - - // - result = IsValid(_start) && - IsValid(_end); - if (!result) - { - return result; - } - - // - end = _end; - start = _start; - session = _session; - - // - result = IsValid(); - - // - return result; - } - - // -}; - -// -struct XTradeDay -{ - // - datetime from; - datetime to; - - // - void XTradeDay() - { - Clean(); - } - - // - void Clean() - { - // - from = NULL; - to = NULL; - } - - // - bool IsValid() - { - // - bool result = false; - - // - result = IsValid(from) && - IsValid(to); - - // - return result; - } - - // - string GetTag() - { - // - string result = NULL; - - // - if (!IsValid()) - { - return result; - } - - // - result = "XDay_" + ToFormatString(from) + "_" + ToFormatString(to); - - // - return result; - } - - // -}; - -// -// Detected Session ... -struct XMarketSession -{ - // - ENUM_XSESSION session; - datetime from; - datetime to; - - // - void XMarketSession() - { - Clean(); - } - - // - void Clean() - { - from = NULL; - to = NULL; - } - - // - bool IsValid() - { - // - bool result = false; - - // - result = IsValid(from) && - IsValid(to); - - // - return result; - } - - // - string GetTage() - { - // - string result = NULL; - - // - if (!IsValid()) - { - return result; - } - - // - result = - ToString(session) + "_" + - ToFormatString(from) + "_" + - ToFormatString(to) + "_"; - - // - return result; - } -}; - -// -// XOHCL Event Handler ... -typedef void (*TXOHCLEventHandler)( - XOHCL &bar // -); - -// -// POI Event Handler ... -typedef void (*TXPOIEventHandler)( - ENUM_XPOI_EVENTS event // -); - -// -// Session Event Handler ... -typedef void (*TXSessionEventHandler)( - ENUM_XSESSION session, - ENUM_XPOI_EVENTS event // -); - -// -// Extensions ... - -/** - * Converts ENUM_XPOI value to String Representation ... - * - * @param value: ENUM_XPOI member ... - * - * @return ( string ) - */ -string ToString(ENUM_XPOIS value) -{ - // - string result = NULL; - - // - switch (value) - { - // - case X_POI_MOMENTUM_BAR: - result = "XMNTMB"; - break; - - // - case X_POI_REJECTION_BAR: - result = "XRJCTB"; - break; - - // - case X_POI_SWING_HIGH: - result = "XSPH"; - break; - - // - case X_POI_SWING_LOW: - result = "XSPL"; - break; - - // - case X_POI_SUPPORT: - result = "XSUP"; - break; - - // - case X_POI_RESISTANCE: - result = "XRES"; - break; - } - - // - return result; -} - -/** - * Converts ENUM_XSESSION value to String Representation ... - * - * @param value: ENUM_XSESSION member ... - * - * @return ( string ) - */ -string ToString(ENUM_XSESSION value) -{ - // - string result = NULL; - - // - switch (value) - { - // - case X_SYDNEY: - result = "SydneyY"; - break; - - // - case X_TOKYO: - result = "Tokyo"; - break; - - // - case X_LONDON: - result = "London"; - break; - - // - case X_NEW_YORK: - result = "New York"; - break; - } - - // - return result; -} - // // Implementation ... @@ -704,6 +316,26 @@ class XCPOI : public XSCBaseAlert // // Sessions ... + /** + * Get Draw Market Sessions State ... + * + * @return ( bool ) + */ + bool AllowDrawMarketSessions() + { + return mAllowDrawMarketSessions; + } + + /** + * Set Draw Market Sessions State ... + * + * @param value: Boolean ... + */ + void AllowDrawMarketSessions(bool value) + { + mAllowDrawMarketSessions = value; + } + /** * Get Session Label Font Size ... * @@ -1555,6 +1187,107 @@ class XCPOI : public XSCBaseAlert } } + // + // Market Session ... + int marketSessionsCount = ArraySize(mMarketSessions); + int sessionsCount = ArraySize(mSessions); + bool isSessionFound = false; + if (IsValidSize(sessionsCount)) + { + // + for (int i = 0; i < sessionsCount; i++) + { + // + XSession iSession = mSessions[i]; + int marketSessionIDX = HasMarketSessionByStartTime( + iSession.session, + zBar.time // + ); + + // + if (!IsValidIndex(marketSessionIDX)) + { + // + int offset = TimeGMTOffset(); + string zTimeString = GetTimeString(zBar.time); + + // + datetime iStartTime = (datetime)((int)StringToTime(iSession.start) + offset); + string iStartTimeString = GetTimeString(iStartTime); + bool isStarted = iStartTimeString == zTimeString; + + // + if (isStarted) + { + // + XMarketSession iMarketSession; + iMarketSession.session = iSession.session; + iMarketSession.from = zBar.time; + + // + int iSessionWorkingHoure = 8; + int iSessionWorkingSeconds = 8 * 60 * 60; + iMarketSession.to = (datetime)((int)zBar.time + iSessionWorkingSeconds); + + // + isSessionFound = AddRef( + iMarketSession, + mMarketSessions // + ); + + // + marketSessionsCount = ArraySize(mMarketSessions); + + // + DrawMarketSessions(); + + // + Add( + X_SESSION_FIRST_BAR, + state // + ); + OnMarketSessionEvent( + iMarketSession.session, + X_SESSION_FIRST_BAR // + ); + NotifyMarketSessionEventListeners( + iMarketSession.session, + X_SESSION_FIRST_BAR // + ); + } + } + + // + // Check End Time for Last Bar ... + for (int i = 0; i < marketSessionsCount; i++) + { + // + XMarketSession iMarketSession = mMarketSessions[i]; + + // + // Calculate Last Bar Time ... + datetime endTime = iMarketSession.to; + datetime lastBarTime = (datetime)((int)endTime - PeriodSeconds(mPeriod)); + if (zBar.time == lastBarTime) + { + // + Add( + X_SESSION_LAST_BAR, + state // + ); + OnMarketSessionEvent( + iMarketSession.session, + X_SESSION_LAST_BAR // + ); + NotifyMarketSessionEventListeners( + iMarketSession.session, + X_SESSION_LAST_BAR // + ); + } + } + } + } + // // Detect Swing High ... int swingHighsCount = ArraySize(mSwingHighs); @@ -1661,11 +1394,12 @@ class XCPOI : public XSCBaseAlert bool state = true; // - AllowDrawTradingDays(state); - AllowDrawSwingHighs(state); AllowDrawSwingLows(state); + AllowDrawSwingHighs(state); + AllowDrawTradingDays(state); AllowDrawMomentumBars(state); AllowDrawRejectionBars(state); + AllowDrawMarketSessions(state); // // Sessions ... @@ -1677,7 +1411,6 @@ class XCPOI : public XSCBaseAlert { // mSessions[i].allowDraw = state; - mSessions[i].drawLabel = state; } } } @@ -1691,11 +1424,12 @@ class XCPOI : public XSCBaseAlert bool state = false; // - AllowDrawTradingDays(state); - AllowDrawSwingHighs(state); AllowDrawSwingLows(state); + AllowDrawSwingHighs(state); + AllowDrawTradingDays(state); AllowDrawMomentumBars(state); AllowDrawRejectionBars(state); + AllowDrawMarketSessions(state); // // Sessions ... @@ -1707,7 +1441,6 @@ class XCPOI : public XSCBaseAlert { // mSessions[i].allowDraw = state; - mSessions[i].drawLabel = state; } } } @@ -1747,7 +1480,6 @@ class XCPOI : public XSCBaseAlert mSyndeySession.startColor = clrFireBrick; mSyndeySession.endColor = clrFireBrick; mSyndeySession.allowDraw = true; - mSyndeySession.drawLabel = true; AddSession(mSyndeySession); // @@ -1763,7 +1495,6 @@ class XCPOI : public XSCBaseAlert mTokyoSession.startColor = clrBlueViolet; mTokyoSession.endColor = clrBlueViolet; mTokyoSession.allowDraw = true; - mTokyoSession.drawLabel = true; AddSession(mTokyoSession); // @@ -1779,7 +1510,6 @@ class XCPOI : public XSCBaseAlert mLondonSession.startColor = clrLime; mLondonSession.endColor = clrLime; mLondonSession.allowDraw = true; - mLondonSession.drawLabel = true; AddSession(mLondonSession); // @@ -1788,14 +1518,13 @@ class XCPOI : public XSCBaseAlert // End: (UTC) 22:00 XSession mNewYorkSession; mNewYorkSession.Init( - X_LONDON, + X_NEW_YORK, "12:00", // Start ... "20:00" // End ... ); mNewYorkSession.startColor = clrAqua; mNewYorkSession.endColor = clrAqua; mNewYorkSession.allowDraw = true; - mNewYorkSession.drawLabel = true; AddSession(mNewYorkSession); // @@ -2062,298 +1791,350 @@ class XCPOI : public XSCBaseAlert } // - // Define Index of Bars ... - int zIndex = barIndex; - int cIndex = zIndex + 1; - - // - datetime cTime = TimeCurrent(); - - // - XOHCL zBar; - bool isRetrieved = mBarTracker.GetBar(zBar, zIndex); - if (!isRetrieved) - { - return; - } - - // - XOHCL cBar; - isRetrieved = mBarTracker.GetBar(cBar, cIndex); - if (!isRetrieved) - { - return; - } - - // - XOHCL zDayBar; - isRetrieved = zDayBar.Init( - mSymbol, - PERIOD_D1, - zIndex // - ); - if (!isRetrieved) - { - return; - } - - // - XOHCL cDayBar; - isRetrieved = cDayBar.Init( - mSymbol, - PERIOD_D1, - cIndex // - ); - if (!isRetrieved) - { - return; - } - - // - // Detect POI(s) based On Current Bar ... - - // - // XTradeDays ... - int daysCount = ArraySize(mTradingDays); - if (daysCount < requiredPOIs) + bool canContinue = true; + int maxAllowedScanPrevBars = 2000; + while (canContinue) { // - XTradeDay tradeDay; - tradeDay.from = zDayBar.time; + // Define Index of Bars ... + int zIndex = barIndex; + int cIndex = zIndex + 1; // - datetime lastBarTime = zDayBar.GetLastBarTimeOfPeriod(mPeriod); - tradeDay.to = lastBarTime; + datetime cTime = TimeCurrent(); // - int idx = HasTradeDay(tradeDay.from); - if (!IsValidIndex(idx)) + XOHCL zBar; + bool isRetrieved = mBarTracker.GetBar(zBar, zIndex); + if (!isRetrieved) { - // - AddRef( - tradeDay, - mTradingDays // - ); - - // - daysCount = ArraySize(mTradingDays); + break; } - } - // - // Session ... - int sessionsCount = ArraySize(mSessions); - int marketSessionsCount = ArraySize(mMarketSessions); - if (IsValidSize(sessionsCount) && - marketSessionsCount < sessionsCount * requiredPOIs) - { // - for (int i = 0; i < sessionsCount; i++) + XOHCL cBar; + isRetrieved = mBarTracker.GetBar(cBar, cIndex); + if (!isRetrieved) + { + break; + } + + // + // Detect POI(s) based On Current Bar ... + + // + // XTradeDays ... + int daysCount = ArraySize(mTradingDays); + if (daysCount < requiredPOIs) { // - XSession iSession = mSessions[i]; - - // - int offset = TimeGMTOffset(); - string zTimeString = GetTimeString(zBar.time); - - // - datetime iStartTime = (datetime)((int)StringToTime(iSession.start) + offset); - string iStartTimeString = GetTimeString(iStartTime); - bool isStarted = iStartTimeString == zTimeString; - - // - datetime iEndTime = (datetime)((int)StringToTime(iSession.end) + offset); - string iEndTimeString = GetTimeString(iEndTime); - bool isEnded = iEndTimeString == zTimeString; - - // - // Detect Sessions Based on Time ... - // Since All Session Close Times Related to Current Date and - // in Required POIs we Moving Back from Current Date ... - if (isEnded) { - Print("Session: " + ToString(iSession.session) + ", Last Bar ..."); + XOHCL zDayBar; + isRetrieved = zDayBar.Init( + mSymbol, + PERIOD_D1, + zIndex // + ); + if (!isRetrieved) + { + break; } // + XOHCL cDayBar; + isRetrieved = cDayBar.Init( + mSymbol, + PERIOD_D1, + cIndex // + ); + if (!isRetrieved) + { + break; + } + + // + XTradeDay tradeDay; + tradeDay.from = zDayBar.time; + + // + datetime lastBarTime = zDayBar.GetLastBarTimeOfPeriod(mPeriod); + tradeDay.to = lastBarTime; + + // + int idx = HasTradeDay(tradeDay.from); + if (!IsValidIndex(idx)) + { + // + AddRef( + tradeDay, + mTradingDays // + ); + + // + daysCount = ArraySize(mTradingDays); + } } - } - // - // Swing Highs ... - int swingHighsCount = ArraySize(mSwingHighs); - if (swingHighsCount < requiredPOIs) - { // - bool isSwingHigh = cBar.IsSimpleSwingHigh(SwingHighThreshold()); - if (isSwingHigh) + // Session ... + int sessionsCount = ArraySize(mSessions); + int marketSessionsCount = ArraySize(mMarketSessions); + if (IsValidSize(sessionsCount) && + marketSessionsCount < sessionsCount * requiredPOIs) { // - AddRef( - cBar, - mSwingHighs // + for (int i = 0; i < sessionsCount; i++) + { + // + XSession iSession = mSessions[i]; + int iCount = CountMarketSessions(iSession.session); + if (iCount >= requiredPOIs) + { + continue; + } + + // + int offset = TimeGMTOffset(); + string zTimeString = GetTimeString(zBar.time); + + // + datetime iStartTime = (datetime)((int)StringToTime(iSession.start) + offset); + string iStartTimeString = GetTimeString(iStartTime); + bool isStarted = iStartTimeString == zTimeString; + + // + datetime iEndTime = (datetime)((int)StringToTime(iSession.end) + offset); + string iEndTimeString = GetTimeString(iEndTime); + bool isEnded = iEndTimeString == zTimeString; + + // + // Detect Sessions Based on Time ... + // Since All Session Close Times Related to Current Date and + // in Required POIs we Moving Back from Current Date ... + if (isEnded && iCount < requiredPOIs) + { + // + // Check Market Session Doesnt Exists by End Time ... + int iIDX = HasMarketSessionByEndTime( + iSession.session, + zBar.time // + ); + if (!IsValidIndex(iIDX)) + { + // + XMarketSession iMarketSession; + iMarketSession.session = iSession.session; + iMarketSession.to = zBar.time; + + // + int iSessionWorkingHoure = 8; + int iSessionWorkingSeconds = 8 * 60 * 60; + iMarketSession.from = (datetime)((int)zBar.time - iSessionWorkingSeconds); + + // + AddRef( + iMarketSession, + mMarketSessions // + ); + + // + marketSessionsCount = ArraySize(mMarketSessions); + } + } + + // + } + } + + // + // Swing Highs ... + int swingHighsCount = ArraySize(mSwingHighs); + if (swingHighsCount < requiredPOIs) + { + // + bool isSwingHigh = cBar.IsSimpleSwingHigh(SwingHighThreshold()); + if (isSwingHigh) + { + // + AddRef( + cBar, + mSwingHighs // + ); + + // + swingHighsCount = ArraySize(mSwingHighs); + } + } + + // + // Swing Low ... + int swingLowsCount = ArraySize(mSwingLows); + if (swingLowsCount < requiredPOIs) + { + // + bool isSwingLow = cBar.IsSimpleSwingLow(SwingLowThreshold()); + if (isSwingLow) + { + // + AddRef( + cBar, + mSwingLows // + ); + + // + swingLowsCount = ArraySize(mSwingLows); + } + } + + // + // Momentum Bars ... + int momentumBarsCount = ArraySize(mMomentumBars); + if (momentumBarsCount < requiredPOIs) + { + // + bool isStrongBar = cBar.IsStrong(MomentumBarPercent()); + + // + // Bullish ... + bool isSharpBullish = cBar.IsSharpBullish( + MomentumBarLoopBack(), + MomentumBarSharpRatio() // ); // - swingHighsCount = ArraySize(mSwingHighs); - } - } - - // - // Swing Low ... - int swingLowsCount = ArraySize(mSwingLows); - if (swingLowsCount < requiredPOIs) - { - // - bool isSwingLow = cBar.IsSimpleSwingLow(SwingLowThreshold()); - if (isSwingLow) - { - // - AddRef( - cBar, - mSwingLows // + // Bearish ... + bool isSharpBearish = cBar.IsSharpBearish( + MomentumBarLoopBack(), + MomentumBarSharpRatio() // ); // - swingLowsCount = ArraySize(mSwingLows); + bool isMomentumBar = + isStrongBar && + (isSharpBearish || + isSharpBullish); + if (isMomentumBar) + { + // + AddRef( + cBar, + mMomentumBars // + ); + + // + momentumBarsCount = ArraySize(mMomentumBars); + } } - } - - // - // Momentum Bars ... - int momentumBarsCount = ArraySize(mMomentumBars); - if (momentumBarsCount < requiredPOIs) - { - // - bool isStrongBar = cBar.IsStrong(MomentumBarPercent()); // - // Bullish ... - bool isSharpBullish = cBar.IsSharpBullish( - MomentumBarLoopBack(), - MomentumBarSharpRatio() // - ); - - // - // Bearish ... - bool isSharpBearish = cBar.IsSharpBearish( - MomentumBarLoopBack(), - MomentumBarSharpRatio() // - ); - - // - bool isMomentumBar = - isStrongBar && - (isSharpBearish || - isSharpBullish); - if (isMomentumBar) + // Rejection Bars ... + int rejectionBarsCount = ArraySize(mRejectionBars); + if (rejectionBarsCount < requiredPOIs) { // - AddRef( - cBar, - mMomentumBars // - ); + } + // + bool isNeedMoreMarketSessions = (!IsValidSize(sessionsCount) + ? true + : marketSessionsCount < (sessionsCount * requiredPOIs)); + canContinue = // - momentumBarsCount = ArraySize(mMomentumBars); + daysCount < requiredPOIs || + // + isNeedMoreMarketSessions || + // + swingHighsCount < requiredPOIs || + swingLowsCount < requiredPOIs || + // + momentumBarsCount < requiredPOIs + // + ; + if (canContinue) + { + barIndex++; } } // - // Rejection Bars ... - int rejectionBarsCount = ArraySize(mRejectionBars); - if (rejectionBarsCount < requiredPOIs) - { - // - } + // Complete Calculations ... // - bool canContinue = - // - daysCount < requiredPOIs || - // - (IsValidSize(sessionsCount) && - marketSessionsCount < (sessionsCount * requiredPOIs)) || - // - swingHighsCount < requiredPOIs || - swingLowsCount < requiredPOIs || - // - momentumBarsCount < requiredPOIs - // - ; - if (canContinue) - { - DetectRequiredPOIs(barIndex + 1); - } - else - { - // - // Complete Calculations ... + // Reverse Trading Days ... + XTradeDay tmpDays[]; + Copy( + mTradingDays, + tmpDays // + ); + Clean(mTradingDays); + ArrayReverse(tmpDays); + Copy( + tmpDays, + mTradingDays // + ); + Clean(tmpDays); - // - // Reverse Trading Days ... - XTradeDay tmpDays[]; - Copy( - mTradingDays, - tmpDays // - ); - Clean(mTradingDays); - ArrayReverse(tmpDays); - Copy( - tmpDays, - mTradingDays // - ); - Clean(tmpDays); + // + // Reverse Market Sessions ... + XMarketSession tmpSessions[]; + Copy( + mMarketSessions, + tmpSessions // + ); + Clean(mMarketSessions); + ArrayReverse(tmpSessions); + Copy( + tmpSessions, + mMarketSessions // + ); - // - XOHCL tmpBars[]; + // + XOHCL tmpBars[]; - // - // Reverse Swing Highs ... - Copy( - mSwingHighs, - tmpBars // - ); - Clean(mSwingHighs); - ArrayReverse(tmpBars); - Copy( - tmpBars, - mSwingHighs // - ); - Clean(tmpBars); + // + // Reverse Swing Highs ... + Copy( + mSwingHighs, + tmpBars // + ); + Clean(mSwingHighs); + ArrayReverse(tmpBars); + Copy( + tmpBars, + mSwingHighs // + ); + Clean(tmpBars); - // - // Reverse Swing Lows ... - Copy( - mSwingLows, - tmpBars // - ); - Clean(mSwingLows); - ArrayReverse(tmpBars); - Copy( - tmpBars, - mSwingLows // - ); - Clean(tmpBars); + // + // Reverse Swing Lows ... + Copy( + mSwingLows, + tmpBars // + ); + Clean(mSwingLows); + ArrayReverse(tmpBars); + Copy( + tmpBars, + mSwingLows // + ); + Clean(tmpBars); - // - // Reverse Momentum Bars ... - Copy( - mMomentumBars, - tmpBars // - ); - Clean(mMomentumBars); - ArrayReverse(tmpBars); - Copy( - tmpBars, - mMomentumBars // - ); - Clean(tmpBars); + // + // Reverse Momentum Bars ... + Copy( + mMomentumBars, + tmpBars // + ); + Clean(mMomentumBars); + ArrayReverse(tmpBars); + Copy( + tmpBars, + mMomentumBars // + ); + Clean(tmpBars); - // - Unlock(); - DrawPOIs(); - } + // + Unlock(); + DrawPOIs(); } // @@ -2633,7 +2414,39 @@ class XCPOI : public XSCBaseAlert void DrawMarketSessions() { // - // TODO: Implement Market Sessions ... + bool allow = AllowDrawMarketSessions(); + if (!allow) + { + return; + } + + // + int count = ArraySize(mMarketSessions); + if (!IsValidSize(count)) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + XMarketSession iMarketSession = mMarketSessions[i]; + + // + string iName = iMarketSession.GetTag(); + int iIDX = HasObject( + iName, + mMarketSessionObjects // + ); + if (IsValidIndex(iIDX)) + { + continue; + } + + // + CreateMarketSessionObject(iMarketSession, iName); + } } // @@ -3080,11 +2893,15 @@ class XCPOI : public XSCBaseAlert /** * Find Market Session by Providing Start Time ... * + * @param session: ENUM_XSESSION member ... * @param start: DateTime ... * * @return ( int ) */ - int HasMarketSessionByStartTime(datetime start) + int HasMarketSessionByStartTime( + ENUM_XSESSION session, + datetime start // + ) { // int result = -1; @@ -3107,6 +2924,15 @@ class XCPOI : public XSCBaseAlert { // XMarketSession iMarketSession = mMarketSessions[i]; + + // + if (iMarketSession.session == session && + iMarketSession.from == start) + { + // + result = i; + break; + } } // @@ -3116,15 +2942,84 @@ class XCPOI : public XSCBaseAlert /** * Find Market Session by Providing Start Time ... * + * @param session: ENUM_XSESSION member ... * @param end: DateTime ... * * @return ( int ) */ - int HasMarketSessionByEndTime(datetime end) + int HasMarketSessionByEndTime( + ENUM_XSESSION session, + datetime end // + ) { // int result = -1; + // + if (!IsValid(end)) + { + return result; + } + + // + int count = ArraySize(mMarketSessions); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XMarketSession iMarketSession = mMarketSessions[i]; + + // + if (iMarketSession.session == session && + iMarketSession.to == end) + { + // + result = i; + break; + } + } + + // + return result; + } + + /** + * Count Specified Market Sessions ... + * + * @param session: ENUM_XSESSION member ... + * + * @return ( int ) + */ + int CountMarketSessions(ENUM_XSESSION session) + { + // + int result = 0; + + // + int count = ArraySize(mMarketSessions); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XMarketSession iMarketSession = mMarketSessions[i]; + + // + if (iMarketSession.session == session) + { + result++; + } + } + // return result; } @@ -3179,12 +3074,11 @@ class XCPOI : public XSCBaseAlert // XCTardeDayObject *iObj; iObj = new XCTardeDayObject(); - bool isCreated = iObj.Create( + bool isCreated = iObj.CreateByDay( ChartID(), name, Window(), - day.from, - day.to // + day // ); if (!isCreated) { @@ -3204,6 +3098,7 @@ class XCPOI : public XSCBaseAlert // // Configure Sessions ... + bool mAllowDrawMarketSessions; // Draw Market Sessions ... int mSessionFontSize; // Session Label Font Size ... string mSessionFont; // Session Label Font ... double mSessionAngle; // Session Label Angle ... @@ -3212,6 +3107,58 @@ class XCPOI : public XSCBaseAlert CArrayObj mMarketSessionObjects; // Founded Market Session Chart Ojects ... TXSessionEventHandler mMarketSessionEventListeners[]; // Market Sessions Event Listeners ... + /** + * Create an Object to Represent Market Session on Chart ... + * + * @param session: XMarketSession instance ... + * @param name: String ... + */ + void CreateMarketSessionObject( + XMarketSession &session, + string name // + ) + { + // + if (!session.IsValid() || + !IsValid(name)) + { + return; + } + + // + // Find XSession Instance ... + int sessionIDX = FindSession(session.session); + if (!IsValidIndex(sessionIDX) || + !mSessions[sessionIDX].allowDraw) + { + return; + } + + // + XCMarketSessionObject *iObj; + iObj = new XCMarketSessionObject(); + bool isCreated = iObj.CreateByMarketSession( + ChartID(), + name, + Window(), + session // + ); + if (!isCreated) + { + return; + } + + // + iObj.FromColor(mSessions[sessionIDX].startColor); + iObj.FromStyle(mSessions[sessionIDX].startStyle); + + // + iObj.ToColor(mSessions[sessionIDX].endColor); + iObj.ToStyle(mSessions[sessionIDX].endStyle); + + // + } + // // POI Holders ... diff --git a/Libraries/x-saherelm.x-poi.lib.mq5 b/Libraries/x-saherelm.x-poi.lib.mq5 new file mode 100644 index 00000000..385b7382 --- /dev/null +++ b/Libraries/x-saherelm.x-poi.lib.mq5 @@ -0,0 +1,416 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Seriallize Library +// --------------------------------------- +// Name: XPOILib +// Description: All models related to POIs ... +// +// +// 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 "../Libraries/x-saherelm.common.lib.mq5" + +// +// Definitions ... + +// +// Definitions ... + +// +// All Available POI(s) ... +enum ENUM_XPOIS +{ + // + // Momentum Bar ... + X_POI_MOMENTUM_BAR, // Momentum Bar ... + // + // Rejection Bar ... + X_POI_REJECTION_BAR, // Rejection Bar ... + // + // Swings ... + X_POI_SWING_HIGH, // Simple Swing High ... + X_POI_SWING_LOW, // Simple Swing Low ... + // + // Support nad Resistance ... + X_POI_SUPPORT, // Support Zone ... + X_POI_RESISTANCE, // Resistance Zone ... +}; + +// +// Event Types ... +enum ENUM_XPOI_EVENTS +{ + // + // Trading Days ... + X_TRADE_DAY_FIRST_BAR, // Trading Day Start ... + X_TRADE_DAY_LAST_BAR, // Trading Day End ... + // + // Session ... + X_SESSION_FIRST_BAR, // Session First Bar ... + X_SESSION_LAST_BAR, // Session Last Bar ... + // + // Momentum Bar ... + X_MOMENTUM_BAR_DETECTED, // Momentum Bar ... + // + // Rejection Bar ... + X_REJECTION_BAR_DETECTED, // Rejection Bar ... + // + // Swings ... + X_SWING_HIGH_DETECTED, + X_SWING_LOW_DETECTED, + // + // Support nad Resistance ... + X_SUPPORT_DETECTED, + X_RESISTANCE_DETECTED, +}; + +// +// Forext Sessions ... +enum ENUM_XSESSION +{ + X_TOKYO, + X_SYDNEY, + X_LONDON, + X_NEW_YORK +}; + +// +// Represent a Session Working Time ... +struct XSession +{ + // + // Props ... + ENUM_XSESSION session; // Session Identifier + string start; // Start Time + string end; // End Time + + // + bool allowDraw; + color startColor; + ENUM_LINE_STYLE startStyle; + color endColor; + ENUM_LINE_STYLE endStyle; + + /** + * Constructor ... + */ + void XSession() + { + Clean(); + } + + /** + * Clean Structure ... + */ + void Clean() + { + // + start = NULL; + end = NULL; + + // + allowDraw = false; + endColor = clrAqua; + endStyle = STYLE_DOT; + startColor = clrAqua; + endStyle = STYLE_DOT; + } + + /** + * Validate Structure ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = IsValid(start) && + IsValid(end); + + // + return result; + } + + /** + * Initialize Specified Session ... + * + * @param _session: ENUM_XSESSION member ... + * @param _start: String (Session Start Time) ... + * @param _end: String (Session End Time) ... + * + * @return ( bool ) + */ + bool Init( + ENUM_XSESSION _session, + string _start, + string _end // + ) + { + // + bool result = false; + + // + result = IsValid(_start) && + IsValid(_end); + if (!result) + { + return result; + } + + // + end = _end; + start = _start; + session = _session; + + // + result = IsValid(); + + // + return result; + } + + // +}; + +// +struct XTradeDay +{ + // + datetime from; + datetime to; + + // + void XTradeDay() + { + Clean(); + } + + // + void Clean() + { + // + from = NULL; + to = NULL; + } + + // + bool IsValid() + { + // + bool result = false; + + // + result = IsValid(from) && + IsValid(to); + + // + return result; + } + + // + string GetTag() + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + result = "XDay_" + ToFormatString(from) + "_" + ToFormatString(to); + + // + return result; + } + + // +}; + +// +// Detected Session ... +struct XMarketSession +{ + // + ENUM_XSESSION session; + datetime from; + datetime to; + + // + void XMarketSession() + { + Clean(); + } + + // + void Clean() + { + from = NULL; + to = NULL; + } + + // + bool IsValid() + { + // + bool result = false; + + // + result = IsValid(from) && + IsValid(to); + + // + return result; + } + + // + string GetTag() + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + result = + ToFormatString(from) + "_" + + ToFormatString(to) + "_"; + + // + return result; + } +}; + +// +// XOHCL Event Handler ... +typedef void (*TXOHCLEventHandler)( + XOHCL &bar // +); + +// +// POI Event Handler ... +typedef void (*TXPOIEventHandler)( + ENUM_XPOI_EVENTS event // +); + +// +// Session Event Handler ... +typedef void (*TXSessionEventHandler)( + ENUM_XSESSION session, + ENUM_XPOI_EVENTS event // +); + +// +// Extensions ... + +/** + * Converts ENUM_XPOI value to String Representation ... + * + * @param value: ENUM_XPOI member ... + * + * @return ( string ) + */ +string ToString(ENUM_XPOIS value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_POI_MOMENTUM_BAR: + result = "XMNTMB"; + break; + + // + case X_POI_REJECTION_BAR: + result = "XRJCTB"; + break; + + // + case X_POI_SWING_HIGH: + result = "XSPH"; + break; + + // + case X_POI_SWING_LOW: + result = "XSPL"; + break; + + // + case X_POI_SUPPORT: + result = "XSUP"; + break; + + // + case X_POI_RESISTANCE: + result = "XRES"; + break; + } + + // + return result; +} + +/** + * Converts ENUM_XSESSION value to String Representation ... + * + * @param value: ENUM_XSESSION member ... + * + * @return ( string ) + */ +string ToString(ENUM_XSESSION value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_SYDNEY: + result = "Sydney"; + break; + + // + case X_TOKYO: + result = "Tokyo"; + break; + + // + case X_LONDON: + result = "London"; + break; + + // + case X_NEW_YORK: + result = "NewYork"; + break; + } + + // + return result; +}