//+------------------------------------------------------------------+ //| ForexSessionsPanel.mq5 | //| Sydney / Tokyo / London / New York sessions with automatic DST | //| Chart boxes + info panel | Bilingual (FA/EN) inputs | //+------------------------------------------------------------------+ #property copyright "Forex Sessions Panel" #property version "2.00" #property description "Forex sessions (Sydney, Tokyo, London, New York) with automatic DST detection." #property description "Session times are entered in each market's LOCAL time; UTC conversion is automatic." #property indicator_chart_window #property indicator_buffers 0 #property indicator_plots 0 #define PREFIX "FSP_" //--- DST rule ids #define RULE_NONE 0 #define RULE_US 1 #define RULE_EU 2 #define RULE_AU 3 //--- enums (the comment after each item is shown in the dropdown) enum ENUM_SERVER_MODE { SRV_AUTO_US = 0, // Auto - US DST rule (recommended) | خودکار - قانون ساعت تابستانی آمریکا (پیشنهادی) SRV_AUTO_EU = 1, // Auto - EU DST rule | خودکار - قانون ساعت تابستانی اروپا SRV_DETECT = 2, // Live detect from terminal | تشخیص زنده از ترمینال (فقط چارت زنده) SRV_FIXED = 3 // Fixed, no DST | ثابت و بدون تغییر ساعت }; enum ENUM_DISPLAY_TZ { TZ_SERVER = 0, // Broker server time | ساعت سرور بروکر TZ_UTC = 1, // UTC / GMT | ساعت جهانی UTC TZ_LOCAL = 2 // My computer time | ساعت کامپیوتر من }; //+==================================================================+ //| INPUTS | //+==================================================================+ input group "██ بخش ۱ ▪ تنظیمات زمان و ساعت تابستانی ▪ SECTION 1 · TIME & DST ██" input ENUM_SERVER_MODE InpServerMode = SRV_AUTO_US; // حالت ساعت سرور بروکر | Broker server time mode input double InpServerWinterGMT = 2.0; // اختلاف سرور با GMT در زمستان (ساعت) | Server GMT offset in winter (h) input bool InpAutoSessionDST = true; // تغییر خودکار ساعت تابستانی سشن‌ها | Auto DST for sessions input ENUM_DISPLAY_TZ InpDisplayTZ = TZ_SERVER; // منطقه زمانی نمایش در جدول | Panel time zone input group "██ بخش ۲ ▪ تنظیمات نمایش سشن‌ها ▪ SECTION 2 · DISPLAY OPTIONS ██" input int InpDaysBack = 5; // تعداد روزهای گذشته روی چارت | Days of history on chart input bool InpSkipWeekends = true; // حذف سشن‌های زمان تعطیلی بازار | Skip market-closed sessions input group "██ بخش ۳ ▪ سشن سیدنی (ساعت محلی سیدنی) ▪ SECTION 3 · SYDNEY (local) ██" input bool InpSydShow = true; // نمایش این سشن | Show session input int InpSydSH = 8; // ساعت شروع | Start hour input int InpSydSM = 0; // دقیقه شروع | Start minute input int InpSydEH = 17; // ساعت پایان | End hour input int InpSydEM = 0; // دقیقه پایان | End minute input color InpSydClr = C'30,60,110'; // رنگ سشن | Session color input group "██ بخش ۴ ▪ سشن آسیا - توکیو (ساعت محلی ژاپن) ▪ SECTION 4 · ASIA / TOKYO (local) ██" input bool InpTokShow = true; // نمایش این سشن | Show session input int InpTokSH = 9; // ساعت شروع | Start hour input int InpTokSM = 0; // دقیقه شروع | Start minute input int InpTokEH = 18; // ساعت پایان | End hour input int InpTokEM = 0; // دقیقه پایان | End minute input color InpTokClr = C'110,45,45'; // رنگ سشن | Session color input group "██ بخش ۵ ▪ سشن لندن (ساعت محلی لندن) ▪ SECTION 5 · LONDON (local) ██" input bool InpLonShow = true; // نمایش این سشن | Show session input int InpLonSH = 8; // ساعت شروع | Start hour input int InpLonSM = 0; // دقیقه شروع | Start minute input int InpLonEH = 17; // ساعت پایان | End hour input int InpLonEM = 0; // دقیقه پایان | End minute input color InpLonClr = C'30,95,50'; // رنگ سشن | Session color input group "██ بخش ۶ ▪ سشن نیویورک (ساعت محلی نیویورک) ▪ SECTION 6 · NEW YORK (local) ██" input bool InpNYShow = true; // نمایش این سشن | Show session input int InpNYSH = 8; // ساعت شروع | Start hour input int InpNYSM = 0; // دقیقه شروع | Start minute input int InpNYEH = 17; // ساعت پایان | End hour input int InpNYEM = 0; // دقیقه پایان | End minute input color InpNYClr = C'120,90,20'; // رنگ سشن | Session color input group "██ بخش ۷ ▪ ظاهر چارت ▪ SECTION 7 · CHART APPEARANCE ██" input bool InpFillBoxes = true; // پر کردن باکس‌ها | Fill session boxes input bool InpShowLabels = true; // نمایش نام سشن روی چارت | Show session names input group "██ بخش ۸ ▪ پنل اطلاعات ▪ SECTION 8 · INFO PANEL ██" input bool InpShowPanel = true; // نمایش پنل | Show panel input bool InpShowOverlap = true; // نمایش جدول همپوشانی همه سشن‌ها | Show all-sessions overlap table input int InpPanelX = 10; // فاصله از چپ (پیکسل) | X offset (px) input int InpPanelY = 20; // فاصله از بالا (پیکسل) | Y offset (px) input int InpFontSize = 9; // اندازه فونت | Font size input color InpPanelBg = C'25,25,30'; // رنگ پس‌زمینه پنل | Panel background input color InpTextClr = clrWhite; // رنگ متن | Text color //+------------------------------------------------------------------+ struct SSession { string name; bool show; int sMin; // start minute of day, market LOCAL time int eMin; // end minute of day, market LOCAL time color clr; int stdOff; // standard (winter) UTC offset in hours int rule; // DST rule }; SSession g_s[4]; int g_tick = 0; //+==================================================================+ //| DATE / DST HELPERS | //+==================================================================+ datetime MakeDT(int y, int m, int d, int h) { MqlDateTime t; t.year = y; t.mon = m; t.day = d; t.hour = h; t.min = 0; t.sec = 0; return StructToTime(t); } //+------------------------------------------------------------------+ int DayOfWeekOf(int y, int m, int d) { MqlDateTime t; t.year = y; t.mon = m; t.day = d; t.hour = 12; t.min = 0; t.sec = 0; datetime dt = StructToTime(t); TimeToStruct(dt, t); return t.day_of_week; // 0 = Sunday } //+------------------------------------------------------------------+ int DaysInMonth(int y, int m) { int dm[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; bool leap = ((y % 4 == 0 && y % 100 != 0) || (y % 400 == 0)); if(m == 2 && leap) return 29; return dm[m - 1]; } //+------------------------------------------------------------------+ int NthSunday(int y, int m, int n) { int dow = DayOfWeekOf(y, m, 1); int first = (dow == 0) ? 1 : (8 - dow); return first + 7 * (n - 1); } //+------------------------------------------------------------------+ int LastSunday(int y, int m) { int dim = DaysInMonth(y, m); int dow = DayOfWeekOf(y, m, dim); return dim - dow; } //+------------------------------------------------------------------+ int YearOf(datetime u) { MqlDateTime t; TimeToStruct(u, t); return t.year; } //+------------------------------------------------------------------+ // US: 2nd Sunday of March 07:00 UTC -> 1st Sunday of November 06:00 UTC bool IsUSDST(datetime u) { int y = YearOf(u); datetime s = MakeDT(y, 3, NthSunday(y, 3, 2), 7); datetime e = MakeDT(y, 11, NthSunday(y, 11, 1), 6); return (u >= s && u < e); } //+------------------------------------------------------------------+ // EU/UK: last Sunday of March 01:00 UTC -> last Sunday of October 01:00 UTC bool IsEUDST(datetime u) { int y = YearOf(u); datetime s = MakeDT(y, 3, LastSunday(y, 3), 1); datetime e = MakeDT(y, 10, LastSunday(y, 10), 1); return (u >= s && u < e); } //+------------------------------------------------------------------+ // Australia (Sydney): 1st Sunday of October -> 1st Sunday of April bool IsAUDST(datetime u) { int y = YearOf(u); datetime s = (datetime)(MakeDT(y, 10, NthSunday(y, 10, 1), 0) - 8 * 3600); datetime e = (datetime)(MakeDT(y, 4, NthSunday(y, 4, 1), 0) - 8 * 3600); return (u >= s || u < e); } //+------------------------------------------------------------------+ bool ZoneDST(int rule, datetime u) { switch(rule) { case RULE_US: return IsUSDST(u); case RULE_EU: return IsEUDST(u); case RULE_AU: return IsAUDST(u); } return false; } //+------------------------------------------------------------------+ long ZoneOffset(int s, datetime u) { long o = (long)g_s[s].stdOff * 3600; if(InpAutoSessionDST && ZoneDST(g_s[s].rule, u)) o += 3600; return o; } //+------------------------------------------------------------------+ long ServerOffsetSec(datetime u) { long base = (long)MathRound(InpServerWinterGMT * 3600.0); switch(InpServerMode) { case SRV_AUTO_US: return base + (IsUSDST(u) ? 3600 : 0); case SRV_AUTO_EU: return base + (IsEUDST(u) ? 3600 : 0); case SRV_DETECT: { long d = (long)(TimeTradeServer() - TimeGMT()); return (long)MathRound((double)d / 900.0) * 900; } } return base; } //+------------------------------------------------------------------+ datetime NowUtc() { datetime s = TimeTradeServer(); long base = (long)MathRound(InpServerWinterGMT * 3600.0); long off = ServerOffsetSec((datetime)(s - base)); return (datetime)(s - off); } //+------------------------------------------------------------------+ long DisplayOffsetSec(datetime u) { if(InpDisplayTZ == TZ_UTC) return 0; if(InpDisplayTZ == TZ_LOCAL) { long d = (long)(TimeLocal() - TimeGMT()); return (long)MathRound((double)d / 900.0) * 900; } return ServerOffsetSec(u); } //+------------------------------------------------------------------+ string FmtT(datetime utc) { datetime t = (datetime)(utc + DisplayOffsetSec(utc)); MqlDateTime m; TimeToStruct(t, m); return StringFormat("%02d:%02d", m.hour, m.min); } //+------------------------------------------------------------------+ string SecToHMS(long sec) { if(sec < 0) sec = 0; return StringFormat("%02d:%02d:%02d", (int)(sec / 3600), (int)((sec % 3600) / 60), (int)(sec % 60)); } //+------------------------------------------------------------------+ // Forex market closed: Friday 17:00 New York -> Sunday 17:00 New York bool MarketClosed(datetime utc) { long off = -5 * 3600 + (IsUSDST(utc) ? 3600 : 0); MqlDateTime t; TimeToStruct((datetime)(utc + off), t); if(t.day_of_week == 6) return true; if(t.day_of_week == 5 && t.hour >= 17) return true; if(t.day_of_week == 0 && t.hour < 17) return true; return false; } //+==================================================================+ //| SESSION INSTANCES | //+==================================================================+ // d = day offset relative to the market's own "today" (0 = today, -1 = yesterday ...) void Instance(int s, int d, datetime nowUtc, datetime &st, datetime &en) { long o0 = ZoneOffset(s, nowUtc); datetime lnow = (datetime)(nowUtc + o0); datetime ld0 = (datetime)(lnow - (lnow % 86400)); datetime L = (datetime)(ld0 + (long)d * 86400 + (long)g_s[s].sMin * 60); long o1 = ZoneOffset(s, (datetime)(L - o0)); st = (datetime)(L - o1); long o2 = ZoneOffset(s, st); st = (datetime)(L - o2); int dur = (g_s[s].eMin > g_s[s].sMin) ? (g_s[s].eMin - g_s[s].sMin) : (g_s[s].eMin + 1440 - g_s[s].sMin); en = (datetime)(st + (long)dur * 60); } //+------------------------------------------------------------------+ bool InstValid(datetime a, datetime b) { return !MarketClosed((datetime)(a + (b - a) / 2)); } //+------------------------------------------------------------------+ // Current (or next) instance of a session void SessionState(int s, datetime nowUtc, bool &open, bool &found, datetime &st, datetime &en) { open = false; found = false; st = 0; en = 0; bool closedNow = MarketClosed(nowUtc); for(int d = -1; d <= 4; d++) { datetime a, b; Instance(s, d, nowUtc, a, b); if(!InstValid(a, b)) continue; if(a <= nowUtc && nowUtc < b) { open = !closedNow; found = true; st = a; en = b; return; } if(a > nowUtc && (!found || a < st)) { found = true; st = a; en = b; } } } //+------------------------------------------------------------------+ // Current or next overlap between two sessions (s1 < s2) bool PairOverlap(int s1, int s2, datetime nowUtc, datetime &os, datetime &oe, bool &active) { bool found = false; active = false; os = 0; oe = 0; for(int d1 = -1; d1 <= 4; d1++) { datetime a1, b1; Instance(s1, d1, nowUtc, a1, b1); if(!InstValid(a1, b1)) continue; for(int d2 = -1; d2 <= 4; d2++) { datetime a2, b2; Instance(s2, d2, nowUtc, a2, b2); if(!InstValid(a2, b2)) continue; datetime a = (a1 > a2) ? a1 : a2; datetime b = (b1 < b2) ? b1 : b2; if(b > a && b > nowUtc && (!found || a < os)) { os = a; oe = b; found = true; } } } if(found) active = (os <= nowUtc && nowUtc < oe && !MarketClosed(nowUtc)); return found; } //+==================================================================+ //| PANEL | //+==================================================================+ void CreateLabel(const string name, int x, int y, string text, color clr, int size, bool bold = false) { if(text == "") text = " "; string n = PREFIX + name; if(ObjectFind(0, n) < 0) { ObjectCreate(0, n, OBJ_LABEL, 0, 0, 0); ObjectSetInteger(0, n, OBJPROP_CORNER, CORNER_LEFT_UPPER); ObjectSetInteger(0, n, OBJPROP_ANCHOR, ANCHOR_LEFT_UPPER); ObjectSetInteger(0, n, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, n, OBJPROP_HIDDEN, true); ObjectSetInteger(0, n, OBJPROP_ZORDER, 10); } ObjectSetInteger(0, n, OBJPROP_XDISTANCE, x); ObjectSetInteger(0, n, OBJPROP_YDISTANCE, y); ObjectSetString(0, n, OBJPROP_FONT, bold ? "Consolas Bold" : "Consolas"); ObjectSetInteger(0, n, OBJPROP_FONTSIZE, size); ObjectSetInteger(0, n, OBJPROP_COLOR, clr); ObjectSetString(0, n, OBJPROP_TEXT, text); } //+------------------------------------------------------------------+ string GMTText(long offSec) { double h = (double)offSec / 3600.0; string s = DoubleToString(MathAbs(h), (MathMod(MathAbs((double)offSec), 3600.0) == 0.0) ? 0 : 1); return "GMT" + (h < 0 ? "-" : "+") + s; } //+------------------------------------------------------------------+ void UpdatePanel() { if(!InpShowPanel) return; const int rowH = 20; const int w = 460; int x0 = InpPanelX, y0 = InpPanelY; datetime nowSrv = TimeTradeServer(); datetime nowUtc = NowUtc(); long srvOff = ServerOffsetSec(nowUtc); // --- collect overlaps of all session pairs, sorted by overlap start time string shortN[4] = {"SYD", "TOK", "LDN", "NY"}; int ovCnt = 0; int ovA[6], ovB[6], idx[6]; datetime ovS[6], ovE[6]; bool ovAct[6]; if(InpShowOverlap) { for(int a = 0; a < 4; a++) for(int b = a + 1; b < 4; b++) { if(!g_s[a].show || !g_s[b].show) continue; datetime os, oe; bool act; if(PairOverlap(a, b, nowUtc, os, oe, act)) { ovA[ovCnt] = a; ovB[ovCnt] = b; ovS[ovCnt] = os; ovE[ovCnt] = oe; ovAct[ovCnt] = act; idx[ovCnt] = ovCnt; ovCnt++; } } for(int i = 0; i < ovCnt - 1; i++) for(int j = 0; j < ovCnt - 1 - i; j++) if(ovS[idx[j]] > ovS[idx[j + 1]]) { int tmp = idx[j]; idx[j] = idx[j + 1]; idx[j + 1] = tmp; } } int rows = 8 + (ovCnt > 0 ? ovCnt + 1 : 0); // background string bg = PREFIX + "PanelBG"; if(ObjectFind(0, bg) < 0) { ObjectCreate(0, bg, OBJ_RECTANGLE_LABEL, 0, 0, 0); ObjectSetInteger(0, bg, OBJPROP_CORNER, CORNER_LEFT_UPPER); ObjectSetInteger(0, bg, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, bg, OBJPROP_HIDDEN, true); ObjectSetInteger(0, bg, OBJPROP_BORDER_TYPE, BORDER_FLAT); ObjectSetInteger(0, bg, OBJPROP_ZORDER, 0); } ObjectSetInteger(0, bg, OBJPROP_XDISTANCE, x0); ObjectSetInteger(0, bg, OBJPROP_YDISTANCE, y0); ObjectSetInteger(0, bg, OBJPROP_XSIZE, w); ObjectSetInteger(0, bg, OBJPROP_YSIZE, rowH * rows + 10); ObjectSetInteger(0, bg, OBJPROP_BGCOLOR, InpPanelBg); ObjectSetInteger(0, bg, OBJPROP_COLOR, C'70,70,80'); string tzName = (InpDisplayTZ == TZ_SERVER ? "Server" : (InpDisplayTZ == TZ_UTC ? "UTC" : "Local")); int cx[5] = {10, 115, 185, 255, 345}; int y = y0 + 5; CreateLabel("T_Title", x0 + 10, y, "FOREX SESSIONS", clrGold, InpFontSize + 1, true); y += rowH; CreateLabel("T_Clock", x0 + 10, y, StringFormat("Server %s | UTC %s | Shown: %s", TimeToString(nowSrv, TIME_MINUTES | TIME_SECONDS), TimeToString(nowUtc, TIME_MINUTES | TIME_SECONDS), tzName), clrSilver, InpFontSize); y += rowH; string dst; if(InpAutoSessionDST) dst = StringFormat("%s | DST AU:%s UK:%s US:%s", GMTText(srvOff), IsAUDST(nowUtc) ? "ON" : "OFF", IsEUDST(nowUtc) ? "ON" : "OFF", IsUSDST(nowUtc) ? "ON" : "OFF"); else dst = StringFormat("%s | Session DST: disabled", GMTText(srvOff)); CreateLabel("T_DST", x0 + 10, y, dst, clrKhaki, InpFontSize); y += rowH; string hdr[5] = {"Session", "Start", "End", "Status", "Remaining"}; for(int c = 0; c < 5; c++) CreateLabel("H_" + IntegerToString(c), x0 + cx[c], y, hdr[c], clrDeepSkyBlue, InpFontSize, true); y += rowH; bool closedNow = MarketClosed(nowUtc); for(int i = 0; i < 4; i++) { string id = IntegerToString(i); bool open, found; datetime st, en; SessionState(i, nowUtc, open, found, st, en); string status, remTxt = "--:--:--", sTxt = "--:--", eTxt = "--:--"; color sc; if(found) { sTxt = FmtT(st); eTxt = FmtT(en); } if(open) { status = "OPEN"; sc = clrLime; remTxt = "ends " + SecToHMS((long)(en - nowUtc)); } else { status = closedNow ? "WEEKEND" : "CLOSED"; sc = closedNow ? clrDimGray : clrTomato; if(found) remTxt = (st <= nowUtc) ? "soon" : ("in " + SecToHMS((long)(st - nowUtc))); } color nameClr = g_s[i].show ? g_s[i].clr : clrGray; color txt = (color)(nameClr | 0x606060); CreateLabel("R" + id + "_0", x0 + cx[0], y, g_s[i].name, txt, InpFontSize, true); CreateLabel("R" + id + "_1", x0 + cx[1], y, sTxt, InpTextClr, InpFontSize); CreateLabel("R" + id + "_2", x0 + cx[2], y, eTxt, InpTextClr, InpFontSize); CreateLabel("R" + id + "_3", x0 + cx[3], y, status, sc, InpFontSize, true); CreateLabel("R" + id + "_4", x0 + cx[4], y, remTxt, InpTextClr, InpFontSize); y += rowH; } // Overlap table (all session pairs, chronological) if(ovCnt > 0) { CreateLabel("OVT", x0 + 10, y, "SESSION OVERLAPS (chronological)", clrGold, InpFontSize, true); y += rowH; for(int k = 0; k < ovCnt; k++) { int n = idx[k]; string kid = IntegerToString(k); string rem = ovAct[n] ? ("ends " + SecToHMS((long)(ovE[n] - nowUtc))) : ("in " + SecToHMS((long)(ovS[n] - nowUtc))); CreateLabel("OV" + kid + "_0", x0 + cx[0], y, shortN[ovA[n]] + "/" + shortN[ovB[n]], clrOrange, InpFontSize, true); CreateLabel("OV" + kid + "_1", x0 + cx[1], y, FmtT(ovS[n]), InpTextClr, InpFontSize); CreateLabel("OV" + kid + "_2", x0 + cx[2], y, FmtT(ovE[n]), InpTextClr, InpFontSize); CreateLabel("OV" + kid + "_3", x0 + cx[3], y, ovAct[n] ? "OVERLAP" : "WAIT", ovAct[n] ? clrLime : clrDimGray, InpFontSize, true); CreateLabel("OV" + kid + "_4", x0 + cx[4], y, rem, InpTextClr, InpFontSize); y += rowH; } } else ObjectDelete(0, PREFIX + "OVT"); // remove stale overlap rows for(int k = ovCnt; k < 6; k++) for(int c = 0; c < 5; c++) ObjectDelete(0, PREFIX + "OV" + IntegerToString(k) + "_" + IntegerToString(c)); } //+==================================================================+ //| CHART BOXES | //+==================================================================+ void DrawSessions() { datetime nowSrv = TimeTradeServer(); datetime nowUtc = NowUtc(); for(int i = 0; i < 4; i++) { for(int d = 1; d >= -InpDaysBack; d--) { int j = 1 - d; string rn = StringFormat("%sBox_%d_%d", PREFIX, i, j); string ln = StringFormat("%sLbl_%d_%d", PREFIX, i, j); datetime st, en; Instance(i, d, nowUtc, st, en); bool skip = (!g_s[i].show || st > nowUtc); if(!skip && InpSkipWeekends && !InstValid(st, en)) skip = true; datetime stS = (datetime)(st + ServerOffsetSec(st)); datetime enS = (datetime)(en + ServerOffsetSec(en)); double hi = 0, lo = 0; if(!skip) { datetime endCalc = (enS > nowSrv) ? nowSrv : enS; if(endCalc <= stS) skip = true; else { double ha[], la[]; int c1 = CopyHigh(_Symbol, PERIOD_M15, stS, endCalc, ha); int c2 = CopyLow(_Symbol, PERIOD_M15, stS, endCalc, la); if(c1 <= 0 || c2 <= 0) skip = true; else { hi = ha[ArrayMaximum(ha)]; lo = la[ArrayMinimum(la)]; } } } if(skip) { ObjectDelete(0, rn); ObjectDelete(0, ln); continue; } if(ObjectFind(0, rn) < 0) { ObjectCreate(0, rn, OBJ_RECTANGLE, 0, stS, hi, enS, lo); ObjectSetInteger(0, rn, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, rn, OBJPROP_HIDDEN, true); ObjectSetInteger(0, rn, OBJPROP_BACK, true); } ObjectSetInteger(0, rn, OBJPROP_TIME, 0, stS); ObjectSetDouble(0, rn, OBJPROP_PRICE, 0, hi); ObjectSetInteger(0, rn, OBJPROP_TIME, 1, enS); ObjectSetDouble(0, rn, OBJPROP_PRICE, 1, lo); ObjectSetInteger(0, rn, OBJPROP_COLOR, g_s[i].clr); ObjectSetInteger(0, rn, OBJPROP_FILL, InpFillBoxes); ObjectSetString(0, rn, OBJPROP_TOOLTIP, StringFormat("%s | %s - %s (server)", g_s[i].name, TimeToString(stS, TIME_DATE | TIME_MINUTES), TimeToString(enS, TIME_DATE | TIME_MINUTES))); if(InpShowLabels) { if(ObjectFind(0, ln) < 0) { ObjectCreate(0, ln, OBJ_TEXT, 0, stS, hi); ObjectSetInteger(0, ln, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, ln, OBJPROP_HIDDEN, true); ObjectSetInteger(0, ln, OBJPROP_ANCHOR, ANCHOR_LEFT_LOWER); ObjectSetInteger(0, ln, OBJPROP_FONTSIZE, 8); } ObjectSetInteger(0, ln, OBJPROP_TIME, 0, stS); ObjectSetDouble(0, ln, OBJPROP_PRICE, 0, hi); ObjectSetInteger(0, ln, OBJPROP_COLOR, (color)(g_s[i].clr | 0x808080)); ObjectSetString(0, ln, OBJPROP_TEXT, g_s[i].name); } else ObjectDelete(0, ln); } } } //+==================================================================+ //| EVENT HANDLERS | //+==================================================================+ int OnInit() { g_s[0].name = "Sydney"; g_s[0].show = InpSydShow; g_s[0].sMin = InpSydSH * 60 + InpSydSM; g_s[0].eMin = InpSydEH * 60 + InpSydEM; g_s[0].clr = InpSydClr; g_s[0].stdOff = 10; g_s[0].rule = RULE_AU; g_s[1].name = "Tokyo"; g_s[1].show = InpTokShow; g_s[1].sMin = InpTokSH * 60 + InpTokSM; g_s[1].eMin = InpTokEH * 60 + InpTokEM; g_s[1].clr = InpTokClr; g_s[1].stdOff = 9; g_s[1].rule = RULE_NONE; g_s[2].name = "London"; g_s[2].show = InpLonShow; g_s[2].sMin = InpLonSH * 60 + InpLonSM; g_s[2].eMin = InpLonEH * 60 + InpLonEM; g_s[2].clr = InpLonClr; g_s[2].stdOff = 0; g_s[2].rule = RULE_EU; g_s[3].name = "New York"; g_s[3].show = InpNYShow; g_s[3].sMin = InpNYSH * 60 + InpNYSM; g_s[3].eMin = InpNYEH * 60 + InpNYEM; g_s[3].clr = InpNYClr; g_s[3].stdOff = -5; g_s[3].rule = RULE_US; ObjectsDeleteAll(0, PREFIX); IndicatorSetString(INDICATOR_SHORTNAME, "Forex Sessions Panel"); EventSetTimer(1); DrawSessions(); UpdatePanel(); ChartRedraw(); return INIT_SUCCEEDED; } //+------------------------------------------------------------------+ void OnDeinit(const int reason) { EventKillTimer(); ObjectsDeleteAll(0, PREFIX); ChartRedraw(); } //+------------------------------------------------------------------+ void OnTimer() { UpdatePanel(); g_tick++; if(g_tick % 5 == 0) DrawSessions(); ChartRedraw(); } //+------------------------------------------------------------------+ 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[]) { if(prev_calculated == 0) { DrawSessions(); UpdatePanel(); } return rates_total; } //+------------------------------------------------------------------+