OVERVIEW
Broker server time is not UTC, and most servers move their clock by one hour twice a year. Code that works with sessions, daily opens or news times therefore needs to know the server offset - not only today, but for every bar in the history and inside the Strategy Tester, where TimeGMT() cannot be used.
BrokerTime.mqh collects the small functions needed for this in one self-contained include file. All names start with BT_, so it does not clash with your own code.
The included script BrokerTimeDemo.mq5 never trades. It prints a short report to the Experts log (and shows it in the chart corner): server time, UTC, the live offset, the DST state and this year's switch dates, the model estimated from the history, and the current time in the main trading centres.

WHAT IS INSIDE
1. DST rules (all results in UTC)
- BT_DstStartUtc(rule, year), BT_DstEndUtc(rule, year)
- BT_IsDst(rule, utc), BT_IsUsDst(utc), BT_IsEuDst(utc), BT_IsAuDst(utc)
Rules: BT_DST_US (2nd Sunday of March 02:00 local to 1st Sunday of November 02:00 local; 1987-2006: 1st Sunday of April to last Sunday of October), BT_DST_EU (last Sunday of March 01:00 UTC to last Sunday of October 01:00 UTC; before 1996 the end is the last Sunday of September, the continental rule; the UK differed), BT_DST_AU (1st Sunday of October to 1st Sunday of April, southern hemisphere), BT_DST_NONE.
2. Time zones
- BT_ZoneOffsetSec(zone, utc), BT_UtcToZone(zone, utc), BT_ZoneToUtc(zone, local)
Zones: BT_ZONE_UTC, BT_ZONE_LONDON, BT_ZONE_FRANKFURT, BT_ZONE_NEW_YORK, BT_ZONE_TOKYO, BT_ZONE_SYDNEY.
3. Live server offset
- BT_ServerOffsetNow(offsetSec): TimeTradeServer() - TimeGMT(), rounded to 15 minutes.
Returns false in the Strategy Tester, while the terminal is not connected to the trade server, or when the value is not plausible.
4. Broker time model
A model is a winter offset plus the DST rule the server clock follows, e.g. "UTC+2, UTC+3 during US DST" = BT_MakeModel(2, BT_DST_US).
- BT_ModelOffsetSec(model, utc)
- BT_UtcToServer(model, utc), BT_ServerToUtc(model, server)
- BT_ServerToZone(model, zone, server), BT_ZoneToServer(model, zone, local)
- BT_ModelFromLiveOffset(rule, model): builds a model from the live offset when you know the DST rule
- BT_ModelToString(model)
Because the model knows the DST rule, it gives the correct offset for any past date, and it works in the Strategy Tester.
5. Estimate of the model from the history
- BT_EstimateFromHistory(symbol, weeks, estimate)
The Forex week opens on Sunday 17:00 New York time. For every weekend gap in the H1 bars of a Forex symbol, the first bar after the gap is compared with that moment in UTC; the difference is the server offset of that week. The DST rule (none, US or EU) that explains the most weeks with one winter offset is chosen. The result also tells you how many weeks fit (weeksMatched of weeksFound) and whether another DST rule fits equally well (dstRuleSure). This works in the Strategy Tester as well. Use a Forex pair only - see NOTES.
Helpers: BT_NthSunday(), BT_LastSunday(), BT_MakeDate(), BT_DayOfWeek(), BT_Year(), BT_DateOnly(), BT_OffsetToString(), BT_ZoneName(), BT_RuleName().
HOW TO USE
1. Copy BrokerTime.mqh to MQL5\Include\.
2. In your code:
#include <BrokerTime.mqh>
BTBrokerModel g_model;
int OnInit()
{
BTEstimate est;
if(BT_EstimateFromHistory("EURUSD", 60, est))
g_model = est.model;
else
g_model = BT_MakeModel(2, BT_DST_US); // your own fallback
Print("Server clock: ", BT_ModelToString(g_model));
return(INIT_SUCCEEDED);
}
void Example()
{
// UTC time of a bar, and London time of the same bar
datetime utc = BT_ServerToUtc(g_model, iTime(_Symbol, PERIOD_H1, 1));
datetime london = BT_UtcToZone(BT_ZONE_LONDON, utc);
// 08:00 London on the same day, in server time
datetime srv0800 = BT_ZoneToServer(g_model, BT_ZONE_LONDON, BT_DateOnly(london) + 8 * 3600);
Print(TimeToString(utc), " UTC = ", TimeToString(london), " London; 08:00 London = ", TimeToString(srv0800), " server");
} 3. The demo: copy BrokerTimeDemo.mq5 to MQL5\Scripts\, compile and drop it on a Forex chart. Inputs: the Forex pair for the history estimate (default EURUSD; "" = chart symbol), the number of weeks to scan (8 to 520), and whether to show the report on the chart. The report stays in the chart corner until another program writes a comment; drop the script again or remove the chart comment to clear it.
NOTES - PLEASE READ
- The live offset comes from TimeGMT(), which is based on the PC clock and its time zone setting. If the PC clock is wrong, the live offset is wrong. The history estimate does not use the PC clock.
- Right after the terminal starts, TimeTradeServer() simply equals TimeGMT() until the terminal is connected. BT_ServerOffsetNow() therefore returns false while not connected; call it again later (from OnTimer or OnTick). The demo waits up to 15 seconds.
- ALWAYS USE A FOREX PAIR (e.g. EURUSD) for BT_EstimateFromHistory(). The estimate assumes that the first H1 bar of the week is the Sunday 17:00 New York open. Metals, indices and crypto usually open the week at other times. Because the difference is the same every week, the result is then a WRONG model that still fits 100% of the weeks with dstRuleSure = true; weeksMatched does not warn you. Example from a test: on one demo server the Forex pairs gave the correct UTC+2 (UTC+3 in summer), while GOLD and two stock index symbols gave UTC+3.
- Symbols whose week starts at a fixed server time (for example crypto) can also make the estimate pick the wrong DST rule, again with a high fit and dstRuleSure = true (in the same test a crypto symbol over 520 weeks gave "US DST" with 173 of 175 weeks).
- Minutes are ignored (H1 bars). If a server's Forex feed starts one hour or more later or earlier than Sunday 17:00 New York every week, the offset is wrong by that many hours.
- Weeks that do not start near the Sunday open (holidays, missing data) are skipped or counted as weeks that do not fit.
- About one year of history (52 weeks or more) is needed to tell the US rule from the EU rule, because they differ only for a few weeks in March and in October / November. With less data, dstRuleSure is often false.
- Recommended: on a live chart, compare the model with BT_ServerOffsetNow() when it is available (BT_ModelOffsetSec(model, utcNow) should equal the live offset). The demo does this and prints "same as live" or "DIFFERS from live".
- Servers that use another DST rule, change their rule, or use half-hour offsets are not covered by the model. Use BT_ServerOffsetNow() for the present moment in such cases.
- In the hour that is repeated when the clocks go back, a local or server time is ambiguous; the conversion functions then return the standard-time reading (the later of the two possible UTC times). A time inside the hour skipped in spring is also read as standard time.
- The EU rule before 1996 is the continental one (end on the last Sunday of September); the UK used other dates before 1996.
- US dates before 1987 use the 1987-2006 rule, and AU dates before 2008 use the current rule.
- Inside the Strategy Tester, BT_ServerOffsetNow() returns false (TimeGMT() equals the simulated server time there). Use a model.
COMPATIBILITY
- MetaTrader 5 (MQL5).
- No DLL, no WebRequest, no file access, no global variables of the terminal. The demo never trades.
This code is a programming example. It does not contain any trading method.
デイリー・ピボットポイント - クラシック、フィボナッチ、カマリラ
3つのレジスタンスと3つのサポートを含むデイリー・ピボットポイント。クラシック、フィボナッチ、またはカマリラの計算式。
USDX Trader EA - Trade the US Dollar Index even if your broker does not include the USDX among their symbols.
USDX Trader v1.33 — MetaTrader 5 向け合成ドル指数チャートおよびバスケット取引 バージョン 1.33 · MetaTrader 5 · 主要な米ドルペアを取り扱うすべてのブローカー
Symbol Spec Dump - export the trading conditions of all symbols to CSV
A script that writes the trading conditions of the Market Watch symbols (or of all symbols of the server) to one CSV file: spread, stops level, freeze level, volume min / max / step / limit, contract size, tick size and value, swaps, margin, filling, order and expiration modes, and the quote and trade sessions of every weekday. Useful for comparing accounts and for checking the limits your EA must respect. It never trades and does not change Market Watch.
Equity Guard - daily loss, max drawdown and profit target lock
1日の損失上限、最大ドローダウン、または1日の利益目標に達すると、すべての取引を決済し、口座残高をゼロに保ちます。プロップファーム式のルール、チャート上のパネル、およびターミナルの再起動後も状態が保持される機能を備えています。