ForexSessionsPanel/ForexSessionsPanel.mq5
2026-11-01 16:48:54 +00:00
680 lines
28 KiB
MQL5
//+------------------------------------------------------------------+
//| 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;
}
//+------------------------------------------------------------------+