From 4de2c7b31c908034113945dd7bd3d89a4328ed61 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Mon, 21 Oct 2024 16:58:12 +0330 Subject: [PATCH] Fix Market Sessions Timing Issues ... --- Classes/x-saherelm.x-chart-objects.class.mq5 | 5 + Classes/x-saherelm.x-poi.class.mq5 | 134 +++-------- Indicators/x-saherelm.x-time.indicator.mq5 | 237 +++++++++++++++++++ Indicators/x-saherelm.xct.mq5 | 11 +- Libraries/x-saherelm.common.lib.mq5 | 81 ++++++- 5 files changed, 365 insertions(+), 103 deletions(-) create mode 100644 Indicators/x-saherelm.x-time.indicator.mq5 diff --git a/Classes/x-saherelm.x-chart-objects.class.mq5 b/Classes/x-saherelm.x-chart-objects.class.mq5 index 798eea09..662b1677 100644 --- a/Classes/x-saherelm.x-chart-objects.class.mq5 +++ b/Classes/x-saherelm.x-chart-objects.class.mq5 @@ -96,6 +96,11 @@ class XCFromToObject : public CChartObject // Deconstructors ... void ~XCFromToObject() { + // + mToVLine.Detach(); + mFromVLine.Detach(); + mToVLine.Delete(); + mFromVLine.Delete(); } /** diff --git a/Classes/x-saherelm.x-poi.class.mq5 b/Classes/x-saherelm.x-poi.class.mq5 index 6eff53c7..dbdb77df 100644 --- a/Classes/x-saherelm.x-poi.class.mq5 +++ b/Classes/x-saherelm.x-poi.class.mq5 @@ -337,90 +337,30 @@ class XCPOI : public XSCBaseAlert } /** - * Get Session Label Font Size ... + * Get Session Working Hors ... * * @return ( int ) */ - int SessionFontSize() + int SessionOpenHours() { - return mSessionFontSize; + return mSessionOpenHours; } /** - * Set Session Label Font Size ... + * Set Session Working Hors ... * * @param value: Integer ... */ - void SessionFontSize(int value) + void SessionOpenHours(int value) { // - if (value < 2) + if (value <= 0) { - value = 2; + value = 9; } // - if (value > 30) - { - value = 30; - } - - // - mSessionFontSize = value; - } - - /** - * Get Session Label Font ... - * - * @return ( string ) - */ - string SessionFont() - { - return mSessionFont; - } - - /** - * Set Session Label Font ... - * - * @param value: String ... - */ - void SessionFont(string value) - { - // - if (!IsValid(value)) - { - value = "Arial"; - } - - // - mSessionFont = value; - } - - /** - * Get Session Label Angle ... - * - * @return ( double ) - */ - double SessionAngle() - { - return mSessionAngle; - } - - /** - * Set Session Label Angle ... - * - * @param value: Double ... - */ - void SessionAngle(double value) - { - // - if (value < 0) - { - value = 0; - } - - // - mSessionAngle = value; + mSessionOpenHours = value; } // @@ -1208,13 +1148,11 @@ class XCPOI : public XSCBaseAlert if (!IsValidIndex(marketSessionIDX)) { // - int offset = TimeGMTOffset(); - string zTimeString = GetTimeString(zBar.time); + datetime zTimeGMT = GetUTCTime(zBar.time); + string zTimeString = GetTimeString(zTimeGMT); // - datetime iStartTime = (datetime)((int)StringToTime(iSession.start) + offset); - string iStartTimeString = GetTimeString(iStartTime); - bool isStarted = iStartTimeString == zTimeString; + bool isStarted = iSession.start == zTimeString; // if (isStarted) @@ -1225,8 +1163,8 @@ class XCPOI : public XSCBaseAlert iMarketSession.from = zBar.time; // - int iSessionWorkingHoure = 8; - int iSessionWorkingSeconds = 8 * 60 * 60; + int iSessionWorkingHoure = SessionOpenHours(); + int iSessionWorkingSeconds = iSessionWorkingHoure * 60 * 60; iMarketSession.to = (datetime)((int)zBar.time + iSessionWorkingSeconds); // @@ -1474,7 +1412,7 @@ class XCPOI : public XSCBaseAlert XSession mSyndeySession; mSyndeySession.Init( X_SYDNEY, - "21:00", // Start ... + "20:00", // Start ... "05:00" // End Next Day ... ); mSyndeySession.startColor = clrFireBrick; @@ -1489,8 +1427,8 @@ class XCPOI : public XSCBaseAlert XSession mTokyoSession; mTokyoSession.Init( X_TOKYO, - "23:00", // Start ... - "07:00" // End Next Day ... + "00:00", // Start ... + "09:00" // End Next Day ... ); mTokyoSession.startColor = clrBlueViolet; mTokyoSession.endColor = clrBlueViolet; @@ -1505,7 +1443,7 @@ class XCPOI : public XSCBaseAlert mLondonSession.Init( X_LONDON, "07:00", // Start ... - "15:00" // End ... + "16:00" // End ... ); mLondonSession.startColor = clrLime; mLondonSession.endColor = clrLime; @@ -1520,7 +1458,7 @@ class XCPOI : public XSCBaseAlert mNewYorkSession.Init( X_NEW_YORK, "12:00", // Start ... - "20:00" // End ... + "21:00" // End ... ); mNewYorkSession.startColor = clrAqua; mNewYorkSession.endColor = clrAqua; @@ -1528,9 +1466,7 @@ class XCPOI : public XSCBaseAlert AddSession(mNewYorkSession); // - SessionFont("Arial"); - SessionFontSize(16); - SessionAngle(90); + SessionOpenHours(9); // MaxNumberOfPOIs(10); @@ -1893,18 +1829,12 @@ class XCPOI : public XSCBaseAlert } // - int offset = TimeGMTOffset(); - string zTimeString = GetTimeString(zBar.time); + datetime zTimeGMT = GetUTCTime(zBar.time); + string zTimeString = GetTimeString(zTimeGMT); // - 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; + bool isStarted = iSession.start == zTimeString; + bool isEnded = iSession.end == zTimeString; // // Detect Sessions Based on Time ... @@ -1926,8 +1856,8 @@ class XCPOI : public XSCBaseAlert iMarketSession.to = zBar.time; // - int iSessionWorkingHoure = 8; - int iSessionWorkingSeconds = 8 * 60 * 60; + int iSessionWorkingHoure = SessionOpenHours(); + int iSessionWorkingSeconds = iSessionWorkingHoure * 60 * 60; iMarketSession.from = (datetime)((int)zBar.time - iSessionWorkingSeconds); // @@ -3092,16 +3022,12 @@ class XCPOI : public XSCBaseAlert // iObj.ToColor(TradingDaysEndColor()); iObj.ToStyle(TradingDaysEndStyle()); - - // } // // Configure Sessions ... bool mAllowDrawMarketSessions; // Draw Market Sessions ... - int mSessionFontSize; // Session Label Font Size ... - string mSessionFont; // Session Label Font ... - double mSessionAngle; // Session Label Angle ... + int mSessionOpenHours; // How many Hours a Session is Open XSession mSessions[]; // Forex Sessions XMarketSession mMarketSessions[]; // Founded Market Sessions ... CArrayObj mMarketSessionObjects; // Founded Market Session Chart Ojects ... @@ -3157,6 +3083,14 @@ class XCPOI : public XSCBaseAlert iObj.ToStyle(mSessions[sessionIDX].endStyle); // + string msg = + ToString(session.session) + "\n" + + "Offset: " + ToString(TimeGMTOffset()) + "\n" + + "LOffset: " + ToString(GetLocalOffset()) + "\n" + + "UTCROffset: " + ToString(GetUTCRequiredTimeOffset()) + "\n" + + "First Bar: " + ToString(session.from) + "\n" + + "Last Bar: " + ToString(session.to) + "\n"; + LogAlert(msg); } // diff --git a/Indicators/x-saherelm.x-time.indicator.mq5 b/Indicators/x-saherelm.x-time.indicator.mq5 new file mode 100644 index 00000000..d2edf38a --- /dev/null +++ b/Indicators/x-saherelm.x-time.indicator.mq5 @@ -0,0 +1,237 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// --------------------------------------------- +// Name: XCTime +// Description: Timing Indicator ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XCTime Indicator" +#property strict + +// +// START Constants ... +// + +// +#define ShortName "XCTime" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input color clr = clrYellow; // Text Color +input ENUM_BASE_CORNER corner = CORNER_LEFT_LOWER; // Text Position + +// +input group "Presentation"; +input bool showTime = true; // Show Time + +// +// END Inputs ... +// + +// +// START Buffers ... +// + +// +#property indicator_chart_window + +// +#property indicator_buffers 0 +#property indicator_plots 0 + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (showTime) + { + CreateIndicatorObject(); + } + else + { + ObjectDelete(0, ShortName); + } + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + ulong chID = FindChartID( + _Symbol, + _Period + // + ); + + // + // Delete Object ... + ObjectDelete(chID, ShortName); + + // + Comment(""); +} + +// +// Calculating what we want ... +int OnCalculate( + const int rates_total, // Total Bars on Chart ... + const int prev_calculated, // Total Calculated Bars on Charts ... + const datetime &time[], // History of Open Time ... + const double &open[], // History of Open Price ... + const double &high[], // History of High Price ... + const double &low[], // History of Low Price ... + const double &close[], // History of Close Price ... + const long &tick_volume[], // History of Tick Volumes on Bar ... + const long &volume[], // History of Trade Volumes ... + const int &spread[] // History of Spread Price ... +) +{ + // + ArraySetAsSeries(time, true); + + // + if (!showTime) + { + return rates_total; + } + + // + ulong chID = FindChartID( + _Symbol, + _Period + // + ); + + //s + int offset = TimeGMTOffset(); + string timeString = + "Local: " + string(TimeLocal()) + + ", Server: " + string(TimeTradeServer()); + timeString = timeString; + + // + string objText = timeString; + + // + ObjectSetInteger(chID, ShortName, OBJPROP_COLOR, clr); + ObjectSetString(chID, ShortName, OBJPROP_TEXT, objText); + ObjectSetInteger(chID, ShortName, OBJPROP_FONTSIZE, 10); + ObjectSetString(chID, ShortName, OBJPROP_FONT, "Arial"); + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +void CreateIndicatorObject() +{ + // + if (!showTime) + { + return; + } + + // + ObjectCreate(0, ShortName, OBJ_LABEL, 0, 0, 0); + ObjectSetInteger(0, ShortName, OBJPROP_CORNER, corner); + ObjectSetInteger(0, ShortName, OBJPROP_XDISTANCE, 10); + ObjectSetInteger(0, ShortName, OBJPROP_YDISTANCE, 2); + + // + ENUM_ANCHOR_POINT Anchor = ANCHOR_LEFT_UPPER; + switch (corner) + { + case CORNER_LEFT_UPPER: + Anchor = ANCHOR_LEFT_UPPER; + break; + case CORNER_RIGHT_UPPER: + Anchor = ANCHOR_RIGHT_UPPER; + break; + case CORNER_LEFT_LOWER: + Anchor = ANCHOR_LEFT_LOWER; + break; + case CORNER_RIGHT_LOWER: + Anchor = ANCHOR_RIGHT_LOWER; + break; + } + + // + ObjectSetInteger(0, ShortName, OBJPROP_ANCHOR, Anchor); +} + +// +// END Functions ... +// diff --git a/Indicators/x-saherelm.xct.mq5 b/Indicators/x-saherelm.xct.mq5 index 25b3b073..92fbb28b 100644 --- a/Indicators/x-saherelm.xct.mq5 +++ b/Indicators/x-saherelm.xct.mq5 @@ -192,7 +192,16 @@ int OnCalculate( _sp = "."; // - string objText = "Spread: " + IntegerToString(mSpread) + _sp + " Next Bar in: " + msg; + // int offset = TimeGMTOffset(); + // string timeString = + // ", Time: " + string(TimeCurrent()) + "\n" + + // ", ServerTime: " + string(TimeTradeServer()) + "\n" + + // ", GMT Offset: " + (string)offset; + // timeString = timeString; + // Comment(timeString); + + // + string objText = "Spread: " + IntegerToString(mSpread) + _sp + ", Next Bar in: " + msg; // ObjectSetInteger(chID, ShortName, OBJPROP_COLOR, clr); diff --git a/Libraries/x-saherelm.common.lib.mq5 b/Libraries/x-saherelm.common.lib.mq5 index e9eb3a41..3d21b9f1 100644 --- a/Libraries/x-saherelm.common.lib.mq5 +++ b/Libraries/x-saherelm.common.lib.mq5 @@ -7942,7 +7942,8 @@ MqlDateTime GetCurrentTime() MqlDateTime result = {}; // - TimeCurrent(result); + datetime cTime = TimeCurrent(); + TimeToStruct(cTime, result); // return result; @@ -7976,10 +7977,86 @@ ulong GetCurrentTimeAsMilliSeconds() return result; } +// +int GetLocalOffset() +{ + // + MqlDateTime cTimeStruct; + datetime cTime = TimeCurrent(cTimeStruct); + + // + MqlDateTime cLTimeStruct; + datetime cLTime = TimeLocal(cLTimeStruct); + + // + cTimeStruct.sec = 0; + cTime = StructToTime(cTimeStruct); + + // + cLTimeStruct.sec = 0; + cLTime = StructToTime(cLTimeStruct); + + // + int result = ((int)cLTime - (int)cTime); + + // + return result; +} + +// +int GetUTCRequiredTimeOffset() +{ + // + int utcOffset = TimeGMTOffset(); + int localOffset = GetLocalOffset(); + + // + int result = utcOffset + localOffset; + + // + return result; +} + +// +datetime GetUTCTime( + datetime time = NULL, + bool applyTradeServerTime = false // +) +{ + // + datetime result = NULL; + + // + NormalizeTime(time); + + // + datetime cTime = TimeCurrent(); + datetime cTimeLocal = TimeLocal(); + + // + int cLocalOffset = ((int)cTimeLocal - (int)cTime); + int gmtOffset = TimeGMTOffset(); + int offsetDelte = gmtOffset + cLocalOffset; + int requiredUTCOffset = GetUTCRequiredTimeOffset(); + if (requiredUTCOffset > 0) { + requiredUTCOffset = -1 * requiredUTCOffset; + } + + // + int timeSeconds = (int)time; + int resultSeconds = timeSeconds + requiredUTCOffset; + + // + result = (datetime)(resultSeconds); + + // + return result; +} + // // Retrieve only Hour and Minute as String ... string GetTimeString( - datetime time = NULL + datetime time = NULL // ) { //