Authoritative MetaQuotes-Demo tick timestamp and copy_ticks_range time-domain semantics
- Authoritative Python tick timestamp semantics for the MetaQuotes demo service
- MetaQuotes-Demo server timezone / UTC offset on historical dates
- MetaQuotes-Demo build 6182: Python timestamps appear 3 hours ahead of UTC
Forum on trading, automated trading systems and testing trading strategies
MetaQuotes-Demo: matching M1/H1 gaps at 23:00 and 00:00 on XAUAUD/XPTUSD, 15–17 Sep 2026
Alain Verleyen, 2026.09.22 17:38
The problem is the documentation is wrong. The data returned from MT5 has the broker server time zone, not UTC.I reported the documentation issue about datetime and timezone to MetaQuotes.
Where is the documentation wrong ? Each time it claims the following :
When creating the 'datetime' object, Python uses the local time zone, while MetaTrader 5 stores tick and bar open time in UTC time zone (without the shift). Therefore, 'datetime' should be created in UTC time for executing functions that use time. Data received from the MetaTrader 5 terminal has UTC time.
The confusion comes from how Python datetime is working, by default it will use the local timezone, the one of the computer where the python code is running, so to avoid returning different data depending where your code run, it's requested to set UTC timezone for each datetime parameter used in a python/MQL5 functions. So you need to use an UTC timezone datetime to finally receive data using the broker server timezone including DST.
An example to illustrate this :
# set time zone to UTC timezone = pytz.timezone("Etc/UTC") # create 'datetime' object in UTC time zone to avoid the implementation of a local time zone offset utc_from = datetime(2025, 1, 10, 0, 0, tzinfo=timezone) # get 10 EURUSD H4 bars starting from 01.10.2020 in UTC time zone rates = mt5.copy_rates_from("EURUSD", mt5.TIMEFRAME_H1, utc_from, 1) # Check without any UTC reference dt_from = datetime(2025, 1, 10, 0, 0) ratesCheck = mt5.copy_rates_from("EURUSD", mt5.TIMEFRAME_H1, dt_from, 1) # shut down connection to the MetaTrader 5 terminal mt5.shutdown() # display each element of obtained data in a new line print("Display obtained 'UTC TZ' data 'as is'") for rate in rates: print(rate) # create DataFrame out of the obtained data rates_frame = pd.DataFrame(rates) # convert time in seconds into the datetime format rates_frame['time']=pd.to_datetime(rates_frame['time'], unit='s') # display data print("\nDisplay dataframe with date_from using UTC") print(rates_frame) # display each element of obtained data in a new line print("Display obtained 'local TZ' data 'as is'") for rate in rates: print(ratesCheck) # create DataFrame out of the obtained data rates_frame_check = pd.DataFrame(ratesCheck) # convert time in seconds into the datetime format rates_frame_check['time']=pd.to_datetime(rates_frame_check['time'], unit='s') # display data print("\nDisplay dataframe with date_from using local time (no TZ specified)") print(rates_frame_check)
2026.09.24 13:27:39.878 Display obtained 'UTC TZ' data 'as is'
2026.09.24 13:27:39.878 (1736467200, 1.03011, 1.03011, 1.0294, 1.02998, 288, 4, 0)
2026.09.24 13:27:39.878
2026.09.24 13:27:39.878 Display dataframe with date_from using UTC
2026.09.24 13:27:39.878 time open high low close tick_volume spread real_volume
2026.09.24 13:27:39.878 0 2025-01-10 1.03011 1.03011 1.0294 1.02998 288 4 0
2026.09.24 13:27:39.878 Display obtained 'local TZ' data 'as is'
2026.09.24 13:27:39.878 [(1736485200, 1.03016, 1.03031, 1.02975, 1.02983, 698, 0, 0)]
2026.09.24 13:27:39.878
2026.09.24 13:27:39.878 Display dataframe with date_from using local time (no TZ specified)
2026.09.24 13:27:39.878 time open high low close tick_volume spread real_volume
2026.09.24 13:27:39.878 0 2025-01-10 05:00:00 1.03016 1.03031 1.02975 1.02983 698 0 0
2025.10.01 00:00 is 1736467200 (epoch time in seconds)
2025.10.01 05:00 is 1736485200 with my local timezone shift at that date. If you run this code from a different timezone, the first one will be the same, but the second one will differ.
So you get different data because you request different datetime, python/MQL5 API request UTC datetime. But the data MT5 returns are ALWAYS broker server time data.
I reported the documentation issue about datetime and timezone to MetaQuotes.
Where is the documentation wrong ? Each time it claims the following :
The confusion comes from how Python datetime is working, by default it will use the local timezone, the one of the computer where the python code is running, so to avoid returning different data depending where your code run, it's requested to set UTC timezone for each datetime parameter used in a python/MQL5 functions. So you need to use an UTC timezone datetime to finally receive data using the broker server timezone including DST.
An example to illustrate this :
2026.09.24 13:27:39.878 Display obtained 'UTC TZ' data 'as is'
2026.09.24 13:27:39.878 (1736467200, 1.03011, 1.03011, 1.0294, 1.02998, 288, 4, 0)
2026.09.24 13:27:39.878
2026.09.24 13:27:39.878 Display dataframe with date_from using UTC
2026.09.24 13:27:39.878 time open high low close tick_volume spread real_volume
2026.09.24 13:27:39.878 0 2025-01-10 1.03011 1.03011 1.0294 1.02998 288 4 0
2026.09.24 13:27:39.878 Display obtained 'local TZ' data 'as is'
2026.09.24 13:27:39.878 [(1736485200, 1.03016, 1.03031, 1.02975, 1.02983, 698, 0, 0)]
2026.09.24 13:27:39.878
2026.09.24 13:27:39.878 Display dataframe with date_from using local time (no TZ specified)
2026.09.24 13:27:39.878 time open high low close tick_volume spread real_volume
2026.09.24 13:27:39.878 0 2025-01-10 05:00:00 1.03016 1.03031 1.02975 1.02983 698 0 0
2025.10.01 00:00 is 1736467200 (epoch time in seconds)
2025.10.01 05:00 is 1736485200 with my local timezone shift at that date. If you run this code from a different timezone, the first one will be the same, but the second one will differ.
So you get different data because you request different datetime, python/MQL5 API request UTC datetime. But the data MT5 returns are ALWAYS broker server time data.
Hello,
I'm investigating a historical timestamp issue with EURUSD tick data from the MetaQuotes-Demo server using the MetaTrader 5 Python API.
I have approximately 44 million historical ticks covering November 2025 to October 2026.
During live testing on October 29, 2026, I observed the following:
-
Host UTC time: 22:40:50
-
Latest tick time_msc: 00:40:52 (when interpreted as UTC)
-
Difference: approximately +2 hours
-
A copy_ticks_range() query using a +2-hour shift successfully retrieved the exact reference tick, matching its timestamp, Bid and Ask.
However, this only establishes the observed behavior of the current API. It does not confirm the historical server timezone.
Could someone familiar with MetaQuotes-Demo clarify:
-
Does MetaQuotes-Demo use UTC+2 in winter and UTC+3 in summer?
-
Does its daylight saving time follow European or US transition dates?
-
Are historical time_msc values expressed in UTC or broker server time?
-
Were EURUSD trading and quoting sessions consistently Monday–Friday, 00:00–24:00 server time throughout 2025–2026?
I'm trying to establish the correct historical clock interpretation without modifying the original tick data.
Any official documentation or reliable technical explanation would be greatly appreciated.
Thank you!