A session-based trading strategy lives or dies on knowing exactly when "the Asian session" or "the New York open" actually is — and that's a much harder problem than it sounds like, because your broker's server time, your platform's displayed time, and the real-world session boundaries are three different things that drift relative to each other, especially around daylight saving transitions. This post covers the actual bug patterns and the fix: never hardcode a session window in broker-server time, always normalize to a fixed reference (UTC/GMT), and treat DST as a first-class problem, not an edge case.
Why this bug is so easy to ship and so expensive to leave in production
Session-based strategies — anything that says "trade the Asian session open" or "watch the London/New York handover" — depend entirely on correctly identifying when those windows actually occur. That sounds trivial until you notice that none of your obvious reference points agree with each other:
Your broker's server time is set by the broker, often in a timezone chosen for their own operational reasons, and is not guaranteed to be UTC, GMT, or your local time. Different brokers running the identical MT5 platform can have servers reporting different times for the exact same real-world moment.
Your platform's displayed candle time is usually broker server time, not a global standard — which means a "15:00" candle on your chart isn't a fixed point in real-world time unless you know your specific broker's offset from UTC.
Real-world session boundaries (Asian, London, New York) are defined relative to UTC/GMT and don't move — but they also don't align cleanly with any single broker's server time without a conversion step.
Daylight saving time makes all of this worse, because it doesn't move in sync. The US, the EU, and your broker's server location can each shift DST on different calendar dates — and some brokers don't observe DST shifts on their server clock at all, meaning the broker-time-to-UTC offset itself changes twice a year and needs to be recalculated, not assumed constant.
A strategy that hardcodes "Asian session = server time 00:00–08:00" will work correctly for exactly as long as the broker's offset from UTC stays constant — which is not indefinitely, and often not for very long.
The bug pattern, concretely
Here's what this actually looks like in code that seems reasonable until you think about it:
# WRONG: assumes server time has a fixed, known relationship to UTC
def is_asian_session(candle_time):
hour = candle_time.hour # this is BROKER SERVER TIME, not UTC
return 0 <= hour < 8
This will appear to work in testing — right up until a DST transition shifts the broker's real offset from UTC by an hour, silently shifting your "Asian session" window along with it. Nothing crashes. No error is thrown. The strategy just quietly starts evaluating the wrong hours as the session, and depending on how aggressively you're trading, this can go unnoticed for weeks.
The fix: normalize everything to a fixed reference before defining any session
The core principle: session boundaries should be defined once, in UTC, and every timestamp you receive from your broker or platform needs to be converted to UTC before it's compared against those boundaries — never the reverse.
from datetime import datetime, timedelta
import pytz
# Define sessions ONCE, in UTC — this never changes regardless of broker
SESSION_WINDOWS_UTC = {
'asian': (0, 8),
'london': (8, 16),
'new_york': (13, 21),
}
def get_broker_utc_offset(broker_timestamp_utc, broker_timestamp_server):
"""
Compute the CURRENT offset by comparing a known-good UTC timestamp
(e.g. from an NTP-synced source or a UTC-timestamped tick) against
what the broker's server reports for the same moment. Recompute
this regularly — never cache it as a constant.
"""
delta = broker_timestamp_server - broker_timestamp_utc
return delta
def server_time_to_utc(server_time, current_offset):
return server_time - current_offset
def get_session(candle_time_utc):
hour = candle_time_utc.hour
for session, (start, end) in SESSION_WINDOWS_UTC.items():
if start <= hour < end:
return session
return None
The critical discipline here is recomputing the offset regularly rather than hardcoding it once. A value that's correct today can silently become wrong twice a year without any code change on your end — the failure is entirely in the broker's own DST behavior changing underneath you.
Testing this properly
The natural instinct is to unit test with a handful of example timestamps, but the actual bug surface is specifically at DST transition boundaries — so that's exactly where tests need to concentrate:
def test_session_detection_across_dst_transition():
# Test a date just before a known DST transition and just after,
# using real broker offset values captured on both sides
pre_dst_offset = timedelta(hours=2)
post_dst_offset = timedelta(hours=3)
server_time_pre = datetime(2026, 3, 28, 10, 0) # before EU DST shift
server_time_post = datetime(2026, 3, 30, 10, 0) # after EU DST shift
utc_pre = server_time_to_utc(server_time_pre, pre_dst_offset)
utc_post = server_time_to_utc(server_time_post, post_dst_offset)
# Same server-time hour, different actual UTC hour and likely
# different session — this is exactly the case that breaks
# hardcoded server-time session windows
assert get_session(utc_pre) != get_session(utc_post) or utc_pre.hour == utc_post.hour
The point of a test like this isn't to assert a specific outcome — it's to make the DST-induced discrepancy visible in a test run rather than discovering it live, three weeks after a transition, when your "Asian session" strategy has quietly been trading during London hours instead.
Why this matters more for session-based strategies than almost any other kind
A trend-following or indicator-based strategy that doesn't care about time of day is largely immune to this entire class of bug — it evaluates conditions continuously, and a shifted clock doesn't change what candle pattern is present. A session-based strategy is uniquely vulnerable because its entire premise depends on correctly bucketing time into windows that are defined in a reference frame (UTC) different from the one your data naturally arrives in (broker server time).
This is also, not coincidentally, one of the most common real-world mistakes traders make when running any session-timed system manually or automated — getting the broker-time-to-session-window mapping wrong at setup, and then wondering why a well-validated strategy performs inconsistently in live conditions despite backtesting cleanly.
Where this shows up in a real production system
This exact class of bug is why the Goldmine Trading Bot's setup process includes explicit broker-time calibration rather than assuming a fixed offset — the session windows (Asian open, New York open) are defined in UTC internally, and the broker's current offset is calibrated during setup and treated as something that can drift, not a constant. Full disclosure: that's a product I build and sell, but the underlying lesson — normalize to a fixed reference before doing time-based comparisons, and never assume a timezone offset is stable — applies to any session-based system regardless of what platform or broker you're running it against.
FAQ
Why doesn't my broker just report time in UTC to avoid all of this?
Some do, but many don't, often for legacy or regional operational reasons — and even brokers using a "UTC-like" server time don't always handle DST transitions identically, since some choose not to shift at all while others follow a specific regional DST calendar.
How often should I recompute my broker's UTC offset?
At minimum, around known DST transition dates for major regions (US, EU, UK) — recomputing it on every session start is a safe default that costs almost nothing computationally and eliminates an entire class of silent bugs.
Can I just hardcode my broker's current offset once I've figured it out?
No — this is exactly the mistake this post is about. A correct offset today is not guaranteed to still be correct in a few months, and the failure mode is silent, not an error you'll notice immediately.
Does this affect strategies that don't reference specific sessions at all?
Much less — a strategy with no time-of-day logic is largely unaffected, since it doesn't depend on correctly bucketing timestamps into named windows in the first place.
Is there a library that handles broker-time-to-UTC conversion automatically?
Not universally, since the mapping is broker-specific and can change — most platforms require you to either query a server-time endpoint and compare it against a known UTC source, or handle it manually as shown above.
Master The Gold Strategy I Used to Print Consistent Profit Every Asian Session.
If you've run a time-sensitive automated system — trading or otherwise — against a data source with its own ambiguous or drifting clock, what was the failure mode that actually surfaced the bug for you? DST transitions specifically seem to be the recurring blind spot across a lot of different domains, not just trading.
Top comments (0)