Help with Time Zone Handling and Data Fetching in MT5

 

I’m reaching out for some clarification about how MT5 handles time zone offsets when fetching historical data.

Here’s the scenario:

  • My current local time in Budapest (UTC+2) is 10:34 AM.

  • The broker’s time zone is Cyprus (UTC+3), so it's 11:34 AM in Cyprus.

  • UTC time is currently 8:34 AM.

I assumed that if I wanted to fetch Bitcoin data up to 10:34 AM (Budapest time), I should use 11:34 AM (Cyprus time) as the broker’s time. So, I tried adding a 1-hour timedelta, but the results weren’t correct.

Here’s the Python code I used to fetch the data:

from_datetime = datetime.now() - timedelta(days=1)
to_datetime = datetime.now() + timedelta(hours=1)
rates = mt5.copy_rates_range("BITCOIN", mt5.TIMEFRAME_M1, from_datetime, to_datetime)
df = pd.DataFrame(rates)
df['datetime'] = pd.to_datetime(df['time'], unit='s')
df = df.set_index('datetime')
print(df.tail()[['open', 'high', 'low', 'close']])

Output:

                         open      high       low     close
datetime
2025-04-27 09:30:00  93921.11  93921.11  93888.23  93888.23
2025-04-27 09:31:00  93888.23  93888.23  93881.93  93881.93
2025-04-27 09:32:00  93881.93  93884.33  93868.94  93878.73
2025-04-27 09:33:00  93878.73  93878.73  93860.14  93870.84
2025-04-27 09:34:00  93870.84  93901.75  93870.84  93888.23

But the correct last (current) candle would be:

                         open      high       low     close
datetime
2025-04-27 11:34:00  94153.59  94153.59  94110.92  94110.92

I found this surprising so I played around with the timedeltas and found that when I add a 3-hour timedelta to the to_datetime , it works correctly, and I get the current candle values as expected:

# Adding 3 hours to the datetime
from_datetime = datetime.now() - timedelta(days=1)
to_datetime = datetime.now() + timedelta(hours=3)
rates = mt5.copy_rates_range("BITCOIN", mt5.TIMEFRAME_M1, from_datetime, to_datetime)
df = pd.DataFrame(rates)
df['datetime'] = pd.to_datetime(df['time'], unit='s')
df = df.set_index('datetime')
print(df.tail()[['open', 'high', 'low', 'close']])

Output (correct last candle):

                         open      high       low     close
datetime
2025-04-27 11:30:00  94119.91  94122.81  94071.34  94122.81
2025-04-27 11:31:00  94122.81  94158.12  94112.72  94115.91
2025-04-27 11:32:00  94115.91  94156.19  94108.53  94141.80
2025-04-27 11:33:00  94141.80  94180.38  94141.80  94153.59
2025-04-27 11:34:00  94153.59  94153.59  94110.92  94110.92

But here’s where I’m confused:
I understand that MT5 operates on UTC, but the data I get seems to be in Cyprus time (UTC+3), not UTC time: see the index, which clearly shows 11:34 AM as the last candle which is exactly 1 hour after my Budapest time of 10:34 AM. This makes me wonder why I need to add 3 hours to the to_datetime to align it correctly with the broker’s time, since I’m only 1 hour apart from the broker (Budapest is UTC+2, Cyprus is UTC+3).

Could you please help me understand:

  • Why do I need to add the 3-hour timedelta if I’m only 1 hour apart from the broker’s time zone?

  • Is MT5 returning the data in the broker’s local time (Cyprus time) rather than UTC, and if so, why does it seem like I need to adjust for a 3-hour difference?

---

Additional note:

Based on the documentation: https://www.mql5.com/en/docs/python_metatrader5/mt5copyratesfrom_py

"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."

So I should definitely input UTC time both to the `from_datetime` and the `to_datetime` values. This, again, seems to suggest to me that in my above scenario I need to input not 10:34 + 3:00 = 13:34 but 10:34 - 2:00 = 8:34 because that is the UTC time of my current local time of 10:34 AM. So even based on this, I don't understand where the 3 hour shift is coming from.

Documentation on MQL5: Date and Time / TimeLocal
Documentation on MQL5: Date and Time / TimeLocal
  • www.mql5.com
Returns the local time of a computer, where the client terminal is running. There are 2 variants of the function. Call without parameters Call with...
 
Levente Csibi:

I’m reaching out for some clarification about how MT5 handles time zone offsets when fetching historical data.

Here’s the scenario:

  • My current local time in Budapest (UTC+2) is 10:34 AM.

  • The broker’s time zone is Cyprus (UTC+3), so it's 11:34 AM in Cyprus.

  • UTC time is currently 8:34 AM.

I assumed that if I wanted to fetch Bitcoin data up to 10:34 AM (Budapest time), I should use 11:34 AM (Cyprus time) as the broker’s time. So, I tried adding a 1-hour timedelta, but the results weren’t correct.

Here’s the Python code I used to fetch the data:

Output:

But the correct last (current) candle would be:

I found this surprising so I played around with the timedeltas and found that when I add a 3-hour timedelta to the to_datetime , it works correctly, and I get the current candle values as expected:

Output (correct last candle):

But here’s where I’m confused:
I understand that MT5 operates on UTC, but the data I get seems to be in Cyprus time (UTC+3), not UTC time: see the index, which clearly shows 11:34 AM as the last candle which is exactly 1 hour after my Budapest time of 10:34 AM. This makes me wonder why I need to add 3 hours to the to_datetime to align it correctly with the broker’s time, since I’m only 1 hour apart from the broker (Budapest is UTC+2, Cyprus is UTC+3).

Could you please help me understand:

  • Why do I need to add the 3-hour timedelta if I’m only 1 hour apart from the broker’s time zone?

  • Is MT5 returning the data in the broker’s local time (Cyprus time) rather than UTC, and if so, why does it seem like I need to adjust for a 3-hour difference?

MT5 Time depends on time provided by broker. It may vary based on where broker is located. You can use TIMEGMT() function and adjust time by adding or substracting based on GMT Time which can be a little bit easier.
 

Hi Rajesh Kumar Nait,

Thanks for your swift reply.

I checked it: https://www.mql5.com/en/docs/dateandtime/timegmt but I am developing in Python using the Python MT5 API. Can you please confirm whether the referenced TimeGMT() method has an equivalent in the Python MT5 library? 

I couldn't find it, so I'm curious what workarounds I might have. 

Documentation on MQL5: Date and Time / TimeGMT
Documentation on MQL5: Date and Time / TimeGMT
  • www.mql5.com
Returns the GMT, which is calculated taking into account the DST switch by the local time on the computer where the client terminal is running...
 

Furthermore, I know that my broker is located in Cyprus, so the time there is well-known: UTC+3. 

Yet, I don't understand that if I want to fetch data till 10:34 AM according to my local time (UTC+2), why do I have to input 13:34 in the command, when the difference between me and my broker is supposedly only 1 hour? 

 
Levente Csibi #:

Hi Rajesh Kumar Nait,

Thanks for your swift reply.

I checked it: https://www.mql5.com/en/docs/dateandtime/timegmt but I am developing in Python using the Python MT5 API. Can you please confirm whether the referenced TimeGMT() method has an equivalent in the Python MT5 library? 

I couldn't find it, so I'm curious what workarounds I might have. 

I can not confirm or compile as i do not have python installed but you can try this

# Get the current server time
server_time = mt5.time()

# Convert to GMT (UTC timezone)
gmt_time = datetime.utcfromtimestamp(server_time).replace(tzinfo=timezone.utc)

print("Server Time (timestamp):", server_time)
print("Server Time (GMT):", gmt_time)


datetime.utcfromtimestamp() converts UNIX timestamp to UTC (GMT).

 
Levente Csibi #:

Furthermore, I know that my broker is located in Cyprus, so the time there is well-known: UTC+3. 

Yet, I don't understand that if I want to fetch data till 10:34 AM according to my local time (UTC+2), why do I have to input 13:34 in the command, when the difference between me and my broker is supposedly only 1 hour? 

when you query data from broker, your local time is not considered.  Base time = broker time. query time = broker time - offset. There is nothing with your local time in this case. I recommend to stick with Broker time if possible, If you try to match with your local time , you will get wrong daily candlestick data.
 

Sadly, this doesn't exist:

mt5.time()

--> `AttributeError: module 'MetaTrader5' has no attribute 'time'`


"when you query data from broker, your local time is not considered.  Base time = broker time. query time = broker time - offset. There is nothing with your local time in this case."

So if my local time is 10:34 AM and broker time is 11:34 AM, and offset between broker and UTC is -3 hours (UTC time being 8:34 AM), what should the query time be then? Empirically, I know it is 13:34 but based on what you said above, I still don't get the logic why this holds: query time = broker time - offset (when you mention offset, I presume you mean the broker-to-UTC offset of -3 hours)

 
Levente Csibi #:

Sadly, this doesn't exist:

--> `AttributeError: module 'MetaTrader5' has no attribute 'time'`


"when you query data from broker, your local time is not considered.  Base time = broker time. query time = broker time - offset. There is nothing with your local time in this case."

So if my local time is 10:34 AM and broker time is 11:34 AM, and offset between broker and UTC is -3 hours (UTC time being 8:34 AM), what should the query time be then? Empirically, I know it is 13:34 but based on what you said above, I still don't get the logic why this holds: query time = broker time - offset (when you mention offset, I presume you mean the broker-to-UTC offset of -3 hours)

If broker time is cyprus time and its providing candlesticks as per cyprus time, and if cyprus time is 2:00 pm and you want 1 hour data so you should query 1 pm as per broker time. It does not matter whatever local time you have as query of api should only be supported to broker time only
 
Levente Csibi #:

Sadly, this doesn't exist:

--> `AttributeError: module 'MetaTrader5' has no attribute 'time'`


use this to get TIMEGMT

from datetime import datetime, timezone
# Current GMT/UTC time
current_gmt = datetime.now(timezone.utc)
print("Current GMT:", current_gmt)
 
from datetime import datetime, timezone
# Current GMT/UTC time
current_gmt = datetime.now(timezone.utc)
print("Current GMT:", current_gmt)

Okay, but this won't be anything surprising, obviously it gives me the currnet GMT time which I knew perfectly already that it's exactly 2 hours less than my local time and is 3 hours less than the broker's local time. 


"If broker time is cyprus time and its providing candlesticks as per cyprus time, and if cyprus time is 2:00 pm and you want 1 hour data so you should query 1 pm as per broker time. It does not matter whatever local time you have as query of api should only be supported to broker time only"


But again, as I have written above, this won't work. If Cyprus time is 2:00 pm and I want the last 1 hour of data (meaning that I want the M1 level data from 1:00pm to 2:00pm in the broker's timezone), I would do this according to your instructions:


    symbol = "BITCOIN"
    timeframe = mt5.TIMEFRAME_M1
    from_datetime = datetime(2025, 4, 27, 13, 0, 0)
    to_datetime = datetime(2025, 4, 27, 14, 0, 0)

    mt5.initialize()

    rates = mt5.copy_rates_range(symbol, timeframe, from_datetime, to_datetime)
    df = pd.DataFrame(rates)
    df['datetime'] = pd.to_datetime(df['time'], unit='s')
    df = df.set_index('datetime')
    
    print(df[["open", "high", "low", "close"]])


This code will output the following dataframe:

                         open      high       low     close
datetime
2025-04-27 11:00:00  93980.58  93980.58  93980.58  93980.58
2025-04-27 11:01:00  93980.58  93980.58  93980.58  93980.58
2025-04-27 11:02:00  93980.58  93980.58  93966.39  93966.39
2025-04-27 11:03:00  93966.39  93966.39  93945.26  93952.90
2025-04-27 11:04:00  93952.90  93952.90  93938.20  93938.20
...                       ...       ...       ...       ...
2025-04-27 11:56:00  94122.91  94122.91  94122.91  94122.91
2025-04-27 11:57:00  94122.91  94122.91  94114.91  94114.91
2025-04-27 11:58:00  94114.91  94160.09  94114.91  94123.21
2025-04-27 11:59:00  94123.21  94123.21  94118.11  94118.11
2025-04-27 12:00:00  94118.11  94118.11  94070.84  94070.84

But what does it mean? I requested data from 13:00 to 14:00 and got indices from 11:00 to 12:00. So are the prices marked as 12:00 the midday prices according to 

  • UTC
  • broker time zone
  • or my own time zone?

Note: I actually know it is in the broker's time zone. So a closing price of 94070.84 at 12:00:00 on this dataframe means the closing price was 94070.84 at 11:00:00 in my timezone (GMT+2). But if it's true what you said above that the query time is always in the broker's time and my local time doesn't matter, then why do I have to query from 13:00 to 14:00 to fetch the broker-time data from 11:00 to 12:00?

So once again, why do I need to have this random `+timedelta(hours=3)` compared to my current local time if I want to fetch the current, actual candles?

    symbol = "BITCOIN"
    timeframe = mt5.TIMEFRAME_M1
    from_datetime = datetime.now() - timedelta(days=1)
    to_datetime = datetime.now() + timedelta(hours=3)   # add 3 hours for some ununderstandable reason ????????????

    mt5.initialize()

    rates = mt5.copy_rates_range(symbol, timeframe, from_datetime, to_datetime)
    df = pd.DataFrame(rates)
    df['datetime'] = pd.to_datetime(df['time'], unit='s')
    df = df.set_index('datetime')
    df.index = df.index - timedelta(hours=1)   # subtract 1 hr because broker is +1 hr compared to my local timezone
    
    print(df[["open", "high", "low", "close"]])
 

Documentaion says this under note.

"

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.

"