//+------------------------------------------------------------------+ //| 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; }