mt5.copy_rates_from() in MetaTrader5 Python: get bars back from a date

Copies a number of bars of one symbol and timeframe, ending at a date you give, into a numpy array. Returns None when the bars can't be read.

Signature

mt5.copy_rates_from(symbol, timeframe, date_from, count)

What it does

copy_rates_from() returns count bars that opened at or before date_from, oldest first. Use it for "the 500 hourly bars before this moment".

The result loads straight into pandas with pd.DataFrame(rates).

Parameters

ParameterWhat it is
symbolThe symbol name. Required.
timeframeA timeframe constant such as mt5.TIMEFRAME_M1, mt5.TIMEFRAME_H1 or mt5.TIMEFRAME_D1.
date_fromThe date to count back from. Dates can be datetime objects or seconds since 1970. Make datetime objects with tzinfo=timezone.utc so your own machine's time zone does not shift them, and remember the terminal reads them on the broker's clock.
countHow many bars to return.

What it returns

  • A numpy structured array, one row per bar, with the fields time, open, high, low, close, tick_volume, spread and real_volume. time is the bar's open time in seconds.
  • None on failure. Check mt5.last_error().

Example

from datetime import datetime, timezone
import pandas as pd
import MetaTrader5 as mt5

if not mt5.initialize():
    raise SystemExit(mt5.last_error())

until = datetime(2026, 10, 1, tzinfo=timezone.utc)
rates = mt5.copy_rates_from("EURUSD", mt5.TIMEFRAME_H1, until, 500)
if rates is None:
    raise SystemExit(mt5.last_error())

df = pd.DataFrame(rates)
df["time"] = pd.to_datetime(df["time"], unit="s")   # broker clock, not UTC
print(df.tail())
mt5.shutdown()

Common mistakes

  • Bar and tick times are the broker's server clock written as if it were UTC. On most servers that is two or three hours ahead of true UTC. Add the broker's offset before you compare them with real UTC times.
  • The terminal returns no more bars than its "Max. bars in chart" setting allows. Ask for more and you get fewer rows, with no error.
  • The first call for a symbol can return fewer bars while the terminal downloads history. Call again after a moment.

The same with Tickwire on Linux

The package needs a Windows terminal on the same machine. Tickwire runs the terminal for you and gives you a REST API, so the code below runs on Linux, macOS or a server.

Tickwire's candles route returns up to limit bars (1000 at most) that open at or before startTime, oldest first, as JSON. Each bar has a UTC time and a brokerTime, so there is no clock to guess. MT5 accounts have 21 timeframes, from 1m to 1mn; MT4 accounts have 9.

See Time zones for how the broker's offset is measured.

import os, requests

API = "https://api.tickwire.io"
h = {"auth-token": os.environ["TW_KEY"]}      # your Tickwire key
base = f"{API}/users/current/accounts/{os.environ['TW_ACCOUNT']}"

r = requests.get(f"{base}/historical-market-data/symbols/EURUSD/timeframes/1h/candles",
                 params={"startTime": "2026-10-01T00:00:00Z", "limit": 500}, headers=h)
bars = r.json()
print(bars[-1]["time"], bars[-1]["close"])

Related error codes

All MetaTrader5 Python functions

MT5 from Python, on any machine

One REST API for MT4 and MT5, with idempotent orders and an audit log. Read the MT5 Python API page or the quickstart.