From 4b50e848c77c5f4d880482ac316ea1d559513b5c Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Mon, 21 Apr 2025 19:28:38 +0330 Subject: [PATCH] last ... --- Documents/BKP/forex.sessions.mq5 | 347 +++++++++++++++++++++++++++++ Documents/BKP/session.detector.mq5 | 318 ++++++++++++++++++++++++++ 2 files changed, 665 insertions(+) create mode 100644 Documents/BKP/forex.sessions.mq5 create mode 100644 Documents/BKP/session.detector.mq5 diff --git a/Documents/BKP/forex.sessions.mq5 b/Documents/BKP/forex.sessions.mq5 new file mode 100644 index 00000000..ee310f67 --- /dev/null +++ b/Documents/BKP/forex.sessions.mq5 @@ -0,0 +1,347 @@ +//+------------------------------------------------------------------+ +//| ForexSessionHighLowIndicator.mq5 | +//| Copyright 2023, MetaQuotes Software Corp. | +//| https://www.metaquotes.net/ | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2023, MetaQuotes Software Corp." +#property link "https://www.metaquotes.net/" +#property version "1.00" +#property indicator_chart_window +#property indicator_buffers 8 +#property indicator_plots 4 + +// Session times (in broker time) +input string SydneyStart = "22:00"; // Sydney session start (GMT+10 when DST) +input string SydneyEnd = "07:00"; // Sydney session end +input string TokyoStart = "00:00"; // Tokyo session start (GMT+9) +input string TokyoEnd = "09:00"; // Tokyo session end +input string LondonStart = "08:00"; // London session start (GMT+0) +input string LondonEnd = "17:00"; // London session end +input string NewYorkStart = "13:00"; // New York session start (GMT-4/5) +input string NewYorkEnd = "22:00"; // New York session end + +input color SydneyColor = clrDodgerBlue; // Sydney session color +input color TokyoColor = clrMediumSeaGreen; // Tokyo session color +input color LondonColor = clrGold; // London session color +input color NewYorkColor = clrTomato; // New York session color +input int LineWidth = 1; // Line width +input bool ShowLabels = true; // Show session labels +input bool ShowHighLow = true; // Show high/low prices + +// Buffers for session high/low +double SydneyHighBuffer[]; +double SydneyLowBuffer[]; +double TokyoHighBuffer[]; +double TokyoLowBuffer[]; +double LondonHighBuffer[]; +double LondonLowBuffer[]; +double NewYorkHighBuffer[]; +double NewYorkLowBuffer[]; + +// Global variables +int SydneyStartHour, SydneyStartMin; +int SydneyEndHour, SydneyEndMin; +int TokyoStartHour, TokyoStartMin; +int TokyoEndHour, TokyoEndMin; +int LondonStartHour, LondonStartMin; +int LondonEndHour, LondonEndMin; +int NewYorkStartHour, NewYorkStartMin; +int NewYorkEndHour, NewYorkEndMin; + +//+------------------------------------------------------------------+ +//| Custom indicator initialization function | +//+------------------------------------------------------------------+ +int OnInit() +{ + // Parse session times + ParseTime(SydneyStart, SydneyStartHour, SydneyStartMin); + ParseTime(SydneyEnd, SydneyEndHour, SydneyEndMin); + ParseTime(TokyoStart, TokyoStartHour, TokyoStartMin); + ParseTime(TokyoEnd, TokyoEndHour, TokyoEndMin); + ParseTime(LondonStart, LondonStartHour, LondonStartMin); + ParseTime(LondonEnd, LondonEndHour, LondonEndMin); + ParseTime(NewYorkStart, NewYorkStartHour, NewYorkStartMin); + ParseTime(NewYorkEnd, NewYorkEndHour, NewYorkEndMin); + + // Set indicator properties + SetIndexBuffer(0, SydneyHighBuffer, INDICATOR_DATA); + SetIndexBuffer(1, SydneyLowBuffer, INDICATOR_DATA); + SetIndexBuffer(2, TokyoHighBuffer, INDICATOR_DATA); + SetIndexBuffer(3, TokyoLowBuffer, INDICATOR_DATA); + SetIndexBuffer(4, LondonHighBuffer, INDICATOR_DATA); + SetIndexBuffer(5, LondonLowBuffer, INDICATOR_DATA); + SetIndexBuffer(6, NewYorkHighBuffer, INDICATOR_DATA); + SetIndexBuffer(7, NewYorkLowBuffer, INDICATOR_DATA); + + // Set drawing styles + PlotIndexSetInteger(0, PLOT_DRAW_TYPE, DRAW_LINE); + PlotIndexSetInteger(0, PLOT_LINE_COLOR, SydneyColor); + PlotIndexSetInteger(0, PLOT_LINE_WIDTH, LineWidth); + PlotIndexSetString(0, PLOT_LABEL, "Sydney High"); + + PlotIndexSetInteger(1, PLOT_DRAW_TYPE, DRAW_LINE); + PlotIndexSetInteger(1, PLOT_LINE_COLOR, SydneyColor); + PlotIndexSetInteger(1, PLOT_LINE_STYLE, STYLE_DOT); + PlotIndexSetInteger(1, PLOT_LINE_WIDTH, LineWidth); + PlotIndexSetString(1, PLOT_LABEL, "Sydney Low"); + + PlotIndexSetInteger(2, PLOT_DRAW_TYPE, DRAW_LINE); + PlotIndexSetInteger(2, PLOT_LINE_COLOR, TokyoColor); + PlotIndexSetInteger(2, PLOT_LINE_WIDTH, LineWidth); + PlotIndexSetString(2, PLOT_LABEL, "Tokyo High"); + + PlotIndexSetInteger(3, PLOT_DRAW_TYPE, DRAW_LINE); + PlotIndexSetInteger(3, PLOT_LINE_COLOR, TokyoColor); + PlotIndexSetInteger(3, PLOT_LINE_STYLE, STYLE_DOT); + PlotIndexSetInteger(3, PLOT_LINE_WIDTH, LineWidth); + PlotIndexSetString(3, PLOT_LABEL, "Tokyo Low"); + + return(INIT_SUCCEEDED); +} + +//+------------------------------------------------------------------+ +//| Custom indicator iteration function | +//+------------------------------------------------------------------+ +int OnCalculate(const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[]) +{ + // Check if we have enough data + if(rates_total < 2) return(0); + + // Set all buffers to EMPTY_VALUE initially + ArrayInitialize(SydneyHighBuffer, EMPTY_VALUE); + ArrayInitialize(SydneyLowBuffer, EMPTY_VALUE); + ArrayInitialize(TokyoHighBuffer, EMPTY_VALUE); + ArrayInitialize(TokyoLowBuffer, EMPTY_VALUE); + ArrayInitialize(LondonHighBuffer, EMPTY_VALUE); + ArrayInitialize(LondonLowBuffer, EMPTY_VALUE); + ArrayInitialize(NewYorkHighBuffer, EMPTY_VALUE); + ArrayInitialize(NewYorkLowBuffer, EMPTY_VALUE); + + // Calculate start position + int start = (prev_calculated == 0) ? 0 : prev_calculated - 1; + + // Main calculation loop + for(int i = start; i < rates_total; i++) + { + MqlDateTime dt; + TimeToStruct(time[i], dt); + + // Check if current time is within any session + bool inSydney = IsInSession(dt.hour, dt.min, SydneyStartHour, SydneyStartMin, SydneyEndHour, SydneyEndMin); + bool inTokyo = IsInSession(dt.hour, dt.min, TokyoStartHour, TokyoStartMin, TokyoEndHour, TokyoEndMin); + bool inLondon = IsInSession(dt.hour, dt.min, LondonStartHour, LondonStartMin, LondonEndHour, LondonEndMin); + bool inNewYork = IsInSession(dt.hour, dt.min, NewYorkStartHour, NewYorkStartMin, NewYorkEndHour, NewYorkEndMin); + + // Find session boundaries and calculate high/low + if(inSydney) + { + CalculateSessionHighLow(i, rates_total, time, high, low, SydneyHighBuffer, SydneyLowBuffer, SydneyStartHour, SydneyStartMin, SydneyEndHour, SydneyEndMin); + } + + if(inTokyo) + { + CalculateSessionHighLow(i, rates_total, time, high, low, TokyoHighBuffer, TokyoLowBuffer, TokyoStartHour, TokyoStartMin, TokyoEndHour, TokyoEndMin); + } + + if(inLondon) + { + CalculateSessionHighLow(i, rates_total, time, high, low, LondonHighBuffer, LondonLowBuffer, LondonStartHour, LondonStartMin, LondonEndHour, LondonEndMin); + } + + if(inNewYork) + { + CalculateSessionHighLow(i, rates_total, time, high, low, NewYorkHighBuffer, NewYorkLowBuffer, NewYorkStartHour, NewYorkStartMin, NewYorkEndHour, NewYorkEndMin); + } + + // Add labels if enabled + if(ShowLabels && i == rates_total - 1) + { + AddSessionLabels(time[rates_total-1], high[rates_total-1], low[rates_total-1]); + } + } + + return(rates_total); +} + +//+------------------------------------------------------------------+ +//| Parse time string into hours and minutes | +//+------------------------------------------------------------------+ +void ParseTime(string timeStr, int &hour, int &min) +{ + string parts[]; + StringSplit(timeStr, ':', parts); + hour = (int)StringToInteger(parts[0]); + min = (ArraySize(parts) > 1) ? (int)StringToInteger(parts[1]) : 0; +} + +//+------------------------------------------------------------------+ +//| Check if current time is within a session | +//+------------------------------------------------------------------+ +bool IsInSession(int currentHour, int currentMin, int startHour, int startMin, int endHour, int endMin) +{ + int currentTime = currentHour * 100 + currentMin; + int sessionStart = startHour * 100 + startMin; + int sessionEnd = endHour * 100 + endMin; + + // Handle sessions that cross midnight + if(sessionStart > sessionEnd) + { + return(currentTime >= sessionStart || currentTime < sessionEnd); + } + else + { + return(currentTime >= sessionStart && currentTime < sessionEnd); + } +} + +//+------------------------------------------------------------------+ +//| Calculate session high and low | +//+------------------------------------------------------------------+ +void CalculateSessionHighLow(int index, int rates_total, const datetime &time[], const double &high[], const double &low[], + double &highBuffer[], double &lowBuffer[], int startHour, int startMin, int endHour, int endMin) +{ + // Find the start of the current session + MqlDateTime currentDt, sessionStartDt; + TimeToStruct(time[index], currentDt); + TimeToStruct(time[index], sessionStartDt); + + sessionStartDt.hour = startHour; + sessionStartDt.min = startMin; + sessionStartDt.sec = 0; + + datetime sessionStartTime = StructToTime(sessionStartDt); + + // If session crosses midnight, adjust the start time + int sessionStart = startHour * 100 + startMin; + int sessionEnd = endHour * 100 + endMin; + + if(sessionStart > sessionEnd) + { + // Session crosses midnight, check if we need to use previous day + int currentTime = currentDt.hour * 100 + currentDt.min; + if(currentTime < sessionEnd) + { + sessionStartTime -= 86400; // Subtract one day + } + } + + // Find the bar index for the session start + int sessionStartIndex = iBarShift(NULL, 0, sessionStartTime); + if(sessionStartIndex < 0) sessionStartIndex = 0; + + // Calculate high and low for the session + double sessionHigh = high[sessionStartIndex]; + double sessionLow = low[sessionStartIndex]; + + for(int j = sessionStartIndex; j <= index; j++) + { + if(j >= rates_total) continue; + + if(high[j] > sessionHigh) sessionHigh = high[j]; + if(low[j] < sessionLow) sessionLow = low[j]; + } + + // Store the values in buffers + highBuffer[index] = sessionHigh; + lowBuffer[index] = sessionLow; + + // If ShowHighLow is enabled, draw the levels + if(ShowHighLow && index == rates_total - 1) + { + string sessionName = ""; + color sessionClr = clrNONE; + + if(startHour == SydneyStartHour && startMin == SydneyStartMin) + { + sessionName = "Sydney"; + sessionClr = SydneyColor; + } + else if(startHour == TokyoStartHour && startMin == TokyoStartMin) + { + sessionName = "Tokyo"; + sessionClr = TokyoColor; + } + else if(startHour == LondonStartHour && startMin == LondonStartMin) + { + sessionName = "London"; + sessionClr = LondonColor; + } + else if(startHour == NewYorkStartHour && startMin == NewYorkStartMin) + { + sessionName = "NewYork"; + sessionClr = NewYorkColor; + } + + if(sessionName != "") + { + string highLabel = sessionName + " High: " + DoubleToString(sessionHigh, _Digits); + string lowLabel = sessionName + " Low: " + DoubleToString(sessionLow, _Digits); + + ObjectCreate(0, highLabel, OBJ_HLINE, 0, 0, sessionHigh); + ObjectSetInteger(0, highLabel, OBJPROP_COLOR, sessionClr); + ObjectSetInteger(0, highLabel, OBJPROP_WIDTH, LineWidth); + ObjectSetInteger(0, highLabel, OBJPROP_BACK, true); + + ObjectCreate(0, lowLabel, OBJ_HLINE, 0, 0, sessionLow); + ObjectSetInteger(0, lowLabel, OBJPROP_COLOR, sessionClr); + ObjectSetInteger(0, lowLabel, OBJPROP_WIDTH, LineWidth); + ObjectSetInteger(0, lowLabel, OBJPROP_STYLE, STYLE_DOT); + ObjectSetInteger(0, lowLabel, OBJPROP_BACK, true); + } + } +} + +//+------------------------------------------------------------------+ +//| Add session labels to the chart | +//+------------------------------------------------------------------+ +void AddSessionLabels(datetime currentTime, double currentHigh, double currentLow) +{ + MqlDateTime dt; + TimeToStruct(currentTime, dt); + + // Remove previous labels + ObjectsDeleteAll(0, "SessionLabel_"); + + if(IsInSession(dt.hour, dt.min, SydneyStartHour, SydneyStartMin, SydneyEndHour, SydneyEndMin)) + { + ObjectCreate(0, "SessionLabel_Sydney", OBJ_TEXT, 0, currentTime, currentHigh + 10 * _Point); + ObjectSetString(0, "SessionLabel_Sydney", OBJPROP_TEXT, "Sydney Session"); + ObjectSetInteger(0, "SessionLabel_Sydney", OBJPROP_COLOR, SydneyColor); + ObjectSetInteger(0, "SessionLabel_Sydney", OBJPROP_ANCHOR, ANCHOR_LEFT_UPPER); + } + + if(IsInSession(dt.hour, dt.min, TokyoStartHour, TokyoStartMin, TokyoEndHour, TokyoEndMin)) + { + ObjectCreate(0, "SessionLabel_Tokyo", OBJ_TEXT, 0, currentTime, currentHigh + 20 * _Point); + ObjectSetString(0, "SessionLabel_Tokyo", OBJPROP_TEXT, "Tokyo Session"); + ObjectSetInteger(0, "SessionLabel_Tokyo", OBJPROP_COLOR, TokyoColor); + ObjectSetInteger(0, "SessionLabel_Tokyo", OBJPROP_ANCHOR, ANCHOR_LEFT_UPPER); + } + + if(IsInSession(dt.hour, dt.min, LondonStartHour, LondonStartMin, LondonEndHour, LondonEndMin)) + { + ObjectCreate(0, "SessionLabel_London", OBJ_TEXT, 0, currentTime, currentHigh + 30 * _Point); + ObjectSetString(0, "SessionLabel_London", OBJPROP_TEXT, "London Session"); + ObjectSetInteger(0, "SessionLabel_London", OBJPROP_COLOR, LondonColor); + ObjectSetInteger(0, "SessionLabel_London", OBJPROP_ANCHOR, ANCHOR_LEFT_UPPER); + } + + if(IsInSession(dt.hour, dt.min, NewYorkStartHour, NewYorkStartMin, NewYorkEndHour, NewYorkEndMin)) + { + ObjectCreate(0, "SessionLabel_NewYork", OBJ_TEXT, 0, currentTime, currentHigh + 40 * _Point); + ObjectSetString(0, "SessionLabel_NewYork", OBJPROP_TEXT, "New York Session"); + ObjectSetInteger(0, "SessionLabel_NewYork", OBJPROP_COLOR, NewYorkColor); + ObjectSetInteger(0, "SessionLabel_NewYork", OBJPROP_ANCHOR, ANCHOR_LEFT_UPPER); + } +} + +//+------------------------------------------------------------------+ \ No newline at end of file diff --git a/Documents/BKP/session.detector.mq5 b/Documents/BKP/session.detector.mq5 new file mode 100644 index 00000000..8ac3c89e --- /dev/null +++ b/Documents/BKP/session.detector.mq5 @@ -0,0 +1,318 @@ +//+------------------------------------------------------------------+ +//| Forex Sessions and Day Range Indicator | +//+------------------------------------------------------------------+ +#property copyright "Your Name" +#property link "https://www.example.com" +#property version "1.00" +#property indicator_chart_window +#property indicator_buffers 8 // 4 sessions * (High + Low) + +#include "../Libraries/x-saherelm.common.lib.mq5" +#include + +// Define an enumeration for DST rules +enum DST_RULE +{ + DST_SYDNEY, + DST_TOKYO, + DST_LONDON, + DST_NEW_YORK +}; + +struct SessionInfo +{ + string name; + int startHour; // Standard start hour (GMT) + int startMinute; + int endHour; // Standard end hour (GMT) + int endMinute; + DST_RULE dstRule; // DST rule for the session + int dstAdjustment; // Hours to add during DST +}; + +SessionInfo sessions[] = { + {"Sydney", 21, 0, 5, 0, DST_SYDNEY, 1}, + {"Tokyo", 23, 0, 8, 0, DST_TOKYO, 0}, + {"London", 7, 0, 15, 0, DST_LONDON, 1}, + {"New York", 12, 0, 17, 0, DST_NEW_YORK, 1}}; + +double sessionHighBuffers[]; // Buffer for session highs +double sessionLowBuffers[]; // Buffer for session lows + +bool sessionActive[]; +double sessionHigh[]; +double sessionLow[]; +datetime sessionStartTime[]; +datetime sessionEndTime[]; + +double dayHigh = 0; +double dayLow = 0; +datetime dayStartTime; + +// Function to extract the year from a datetime value +int GetYear(datetime time) +{ + return (int)StringSubstr(TimeToString(time, TIME_DATE), 0, 4); +} + +// Function to extract the day of the month from a datetime value +int GetDay(datetime time) +{ + MqlDateTime dt; + TimeToStruct(time, dt); + return dt.day; +} + +// Function to extract the day of the week from a datetime value (0=Sunday, 6=Saturday) +int GetDayOfWeek(datetime time) +{ + MqlDateTime dt; + TimeToStruct(time, dt); + return dt.day_of_week; +} + +//+------------------------------------------------------------------+ +//| Custom indicator initialization function | +//+------------------------------------------------------------------+ +int OnInit() +{ + ArrayResize(sessionActive, ArraySize(sessions)); + ArrayResize(sessionHigh, ArraySize(sessions)); + ArrayResize(sessionLow, ArraySize(sessions)); + ArrayResize(sessionStartTime, ArraySize(sessions)); + ArrayResize(sessionEndTime, ArraySize(sessions)); + + for (int i = 0; i < ArraySize(sessions); i++) + { + sessionActive[i] = false; + sessionHigh[i] = 0; + sessionLow[i] = 0; + sessionStartTime[i] = 0; + sessionEndTime[i] = 0; + } + + dayHigh = 0; + dayLow = 0; + dayStartTime = 0; + + // Initialize buffers for session highs and lows + int totalSessions = ArraySize(sessions); + int totalBars = iBars(NULL, 0); // Get the number of bars on the chart + + ArrayResize(sessionHighBuffers, totalBars); // Resize to match the number of bars + ArrayResize(sessionLowBuffers, totalBars); // Resize to match the number of bars + + for (int i = 0; i < totalSessions; i++) + { + SetIndexBuffer(i * 2, sessionHighBuffers, INDICATOR_DATA); + SetIndexBuffer(i * 2 + 1, sessionLowBuffers, INDICATOR_DATA); + + // Optional: Set colors for high and low buffers + PlotIndexSetInteger(i * 2, PLOT_LINE_COLOR, clrGreen); + PlotIndexSetInteger(i * 2 + 1, PLOT_LINE_COLOR, clrRed); + + IndicatorSetInteger(INDICATOR_LEVELS, 0); // No predefined levels + IndicatorSetString(INDICATOR_SHORTNAME, "Forex Sessions"); + } + + return (INIT_SUCCEEDED); +} + +//+------------------------------------------------------------------+ +//| Custom indicator iteration function | +//+------------------------------------------------------------------+ +int OnCalculate(const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[]) +{ + // Ensure buffers are resized to match the number of bars + if (ArraySize(sessionHighBuffers) < rates_total) + { + ArrayResize(sessionHighBuffers, rates_total); + ArrayResize(sessionLowBuffers, rates_total); + } + + datetime currentTime = TimeCurrent(); + + // Retrieve Ask and Bid prices dynamically + double askPrice = SymbolInfoDouble(Symbol(), SYMBOL_ASK); + double bidPrice = SymbolInfoDouble(Symbol(), SYMBOL_BID); + + // Check each session + for (int i = 0; i < ArraySize(sessions); i++) + { + SessionInfo session = sessions[i]; + + // Determine if DST is active using the session's DST rule + bool dstActive = IsDSTActive(session.dstRule, currentTime); + int adjStartHour = session.startHour + (dstActive ? session.dstAdjustment : 0); + int adjEndHour = session.endHour + (dstActive ? session.dstAdjustment : 0); + + datetime todayStart = StringToTime(TimeToString(currentTime, TIME_DATE) + " " + + IntegerToString(adjStartHour) + ":" + + IntegerToString(session.startMinute)); + datetime todayEnd = StringToTime(TimeToString(currentTime, TIME_DATE) + " " + + IntegerToString(adjEndHour) + ":" + + IntegerToString(session.endMinute)); + + // Handle sessions spanning midnight + if (adjEndHour < adjStartHour) + { + todayEnd += 24 * 3600; + } + + if (currentTime >= todayStart && currentTime < todayEnd) + { + if (!sessionActive[i]) + { + sessionActive[i] = true; + sessionStartTime[i] = todayStart; + sessionEndTime[i] = todayEnd; + sessionHigh[i] = askPrice; + sessionLow[i] = bidPrice; + } + else + { + if (askPrice > sessionHigh[i]) + sessionHigh[i] = askPrice; + if (bidPrice < sessionLow[i]) + sessionLow[i] = bidPrice; + } + + // Update buffers for the current bar + sessionHighBuffers[rates_total - 1] = sessionHigh[i]; + sessionLowBuffers[rates_total - 1] = sessionLow[i]; + } + else + { + sessionActive[i] = false; + sessionHighBuffers[rates_total - 1] = EMPTY_VALUE; // Clear buffer when session is inactive + sessionLowBuffers[rates_total - 1] = EMPTY_VALUE; + } + } + + // Check day range + bool dstActiveNY = IsDSTActive(DST_NEW_YORK, currentTime); + int dayStartHour = dstActiveNY ? 21 : 22; + datetime todayDayStart = StringToTime(TimeToString(currentTime, TIME_DATE) + " " + + IntegerToString(dayStartHour) + ":00"); + + if (currentTime < todayDayStart) + { + todayDayStart -= 24 * 3600; + } + + if (dayStartTime != todayDayStart) + { + dayStartTime = todayDayStart; + dayHigh = askPrice; + dayLow = bidPrice; + } + else + { + if (askPrice > dayHigh) + dayHigh = askPrice; + if (bidPrice < dayLow) + dayLow = bidPrice; + } + + // Display information on chart + string comment = "Active Forex Sessions:\n"; + for (int i = 0; i < ArraySize(sessions); i++) + { + if (sessionActive[i]) + { + comment += sessions[i].name + " Session\n" + + "High: " + DoubleToString(sessionHigh[i], _Digits) + "\n" + + "Low: " + DoubleToString(sessionLow[i], _Digits) + "\n"; + } + } + comment += "\nDay Range:\n" + + "High: " + DoubleToString(dayHigh, _Digits) + "\n" + + "Low: " + DoubleToString(dayLow, _Digits); + Comment(comment); + + return (rates_total); +} + +//+------------------------------------------------------------------+ +//| Check if DST is active for a given session | +//+------------------------------------------------------------------+ +bool IsDSTActive(DST_RULE dstRule, datetime time) +{ + switch (dstRule) + { + case DST_SYDNEY: + return IsSydneyDST(time); + case DST_TOKYO: + return IsTokyoDST(time); + case DST_LONDON: + return IsLondonDST(time); + case DST_NEW_YORK: + return IsNewYorkDST(time); + default: + return false; + } +} + +//+------------------------------------------------------------------+ +//| DST Check Functions | +//+------------------------------------------------------------------+ +bool IsLondonDST(datetime time) +{ + int year = GetYear(time); + datetime march31 = StringToTime(ToString(year) + ".03.31 00:00"); + int lastSundayMarch = GetDay(march31) - (GetDayOfWeek(march31) % 7); + datetime dstStart = StringToTime(ToString(year) + ".03." + IntegerToString(lastSundayMarch) + " 01:00"); + + datetime oct31 = StringToTime(ToString(year) + ".10.31 00:00"); + int lastSundayOct = GetDay(oct31) - (GetDayOfWeek(oct31) % 7); + datetime dstEnd = StringToTime(ToString(year) + ".10." + IntegerToString(lastSundayOct) + " 01:00"); + + return time >= dstStart && time < dstEnd; +} + +bool IsNewYorkDST(datetime time) +{ + int year = GetYear(time); + datetime march1 = StringToTime(ToString(year) + ".03.01 00:00"); + int dayOfWeekMarch1 = GetDayOfWeek(march1); + int secondSundayMarch = 1 + (7 - dayOfWeekMarch1) % 7 + 7; + datetime dstStart = StringToTime(ToString(year) + ".03." + IntegerToString(secondSundayMarch) + " 07:00"); + + datetime nov1 = StringToTime(ToString(year) + ".11.01 00:00"); + int dayOfWeekNov1 = GetDayOfWeek(nov1); + int firstSundayNov = 1 + (7 - dayOfWeekNov1) % 7; + datetime dstEnd = StringToTime(ToString(year) + ".11." + IntegerToString(firstSundayNov) + " 06:00"); + + return time >= dstStart && time < dstEnd; +} + +bool IsSydneyDST(datetime time) +{ + int year = GetYear(time); + datetime oct1 = StringToTime(ToString(year) + ".10.01 00:00"); + int dayOfWeekOct1 = GetDayOfWeek(oct1); + int firstSundayOct = 1 + (7 - dayOfWeekOct1) % 7; + datetime dstStart = StringToTime(ToString(year) + ".10." + IntegerToString(firstSundayOct) + " 13:00"); + + datetime apr1 = StringToTime(ToString(year) + ".04.01 00:00"); + int dayOfWeekApr1 = GetDayOfWeek(apr1); + int firstSundayApr = 1 + (7 - dayOfWeekApr1) % 7; + datetime dstEnd = StringToTime(ToString(year) + ".04." + IntegerToString(firstSundayApr) + " 15:00"); + + return time >= dstStart && time < dstEnd; +} + +bool IsTokyoDST(datetime time) +{ + // Tokyo does not observe Daylight Saving Time (DST) + return false; +} \ No newline at end of file