Broker API HubMenu

MT5 trade history to a spreadsheet with Python

Asked over and over on the MQL5 forum and answered in no single place. This is the whole job: the constraint that stops most people, the one call that does the work, and a script that writes a CSV.

Independent and unofficialLast reviewed

Risk warning: CFDs and spread bets are complex instruments and come with a high risk of losing money rapidly due to leverage. You can lose money on these products, and each provider publishes its own loss figure under FCA rules. You should consider whether you understand how they work and whether you can afford to take the high risk of losing your money. Automated and API trading can amplify losses through bugs, connectivity failures and runaway orders.

Carried over from an earlier version of this site. The links below are the sources it was written from, but its statements have not been re-read at source since the date shown, so check anything you rely on.

Remind me to do this again

One tap puts two reminders in your own calendar: every three months, and 6 April, the day after the UK tax year ends on 5 April. The file is built in this page and saved by your browser. There is no mailbox behind this site, no account to make and nothing to type, so nothing about you leaves this page.

The steps

  1. Install the packagepip install MetaTrader5 on a Windows machine with the terminal installed. The current release is 5.0.6231, published 27 Sep 2026.Step 1bashpip install MetaTrader5 SourcePyPI: MetaTrader5 release history checked 19 Sep 2026
  2. Understand the one call that mattersmt5.history_deals_get(date_from, date_to) returns the filled trades between two dates as a tuple of named tuples, or None on error, in which case mt5.last_error() says why. It also accepts group="*GBP*" to filter by symbol, ticket= for a single order, or position= for every deal belonging to one position. Deals, not orders, are what a spreadsheet of your trading should be built from.Our sourced reference page for history_deals_getSourceMQL5 docs: history_deals_get (Python) checked 18 Sep 2026
  3. Build the dates in UTCMetaTrader 5 works in UTC. Build date_from and date_to as timezone-aware UTC datetimes, or a run from a machine set to British Summer Time will silently miss an hour at each end of the range.SourceMQL5 docs: history_deals_get (Python) checked 18 Sep 2026
  4. Write the CSVEach deal exposes _asdict(), so csv.DictWriter can take the field names straight from the first row. The sample below saves the last 30 days of deals to deals.csv, which any spreadsheet will open. It only reads: it never calls order_send.SourceMQL5 docs: history_deals_get (Python) checked 18 Sep 2026
  5. Check the totals before you rely on itThe column names come from the deal named tuple and MetaQuotes does not document this export as a tax record. Reconcile the totals against your broker's own statement before you use it for anything that matters.SourceMQL5 docs: history_deals_get (Python) checked 18 Sep 2026
  6. If the call returns Nonehistory_deals_get returns None rather than raising. Print mt5.last_error() and look the code up: the negative codes are IPC, version, login and timeout failures with a page of their own.Every negative code mt5.last_error() returnsSourceMQL5 docs: last_error (Python) checked 19 Sep 2026

The script

Demo account only. It stops rather than run against a live account, it reads three values from the environment so no password is ever typed into the file, and it never calls order_send. Not yet run by us, so it carries no Tested badge.

# MetaTrader 5 Python: save your deals to CSV. DEMO ACCOUNT ONLY. Not yet run by us.
# Needs Windows with the MetaTrader 5 terminal installed, and: pip install MetaTrader5
# Set MT5_LOGIN, MT5_PASSWORD and MT5_SERVER as environment variables for a demo account.
import csv
import os
from datetime import datetime, timedelta, timezone
import MetaTrader5 as mt5

if not mt5.initialize(login=int(os.environ["MT5_LOGIN"]), password=os.environ["MT5_PASSWORD"], server=os.environ["MT5_SERVER"]):
    print("initialize() failed:", mt5.last_error())
    raise SystemExit(1)

try:
    acc = mt5.account_info()
    if acc is None or acc.trade_mode != mt5.ACCOUNT_TRADE_MODE_DEMO:
        raise SystemExit("Stopping: this sample runs on a demo account only.")

    # MetaTrader 5 times are UTC, so build the dates in UTC
    date_to = datetime.now(timezone.utc)
    date_from = date_to - timedelta(days=30)
    deals = mt5.history_deals_get(date_from, date_to)
    if deals is None:
        raise SystemExit(f"history_deals_get failed: {mt5.last_error()}")

    with open("deals.csv", "w", newline="") as f:
        writer = None
        for deal in deals:
            row = deal._asdict()
            if writer is None:
                writer = csv.DictWriter(f, fieldnames=list(row))
                writer.writeheader()
            writer.writerow(row)
    print(len(deals), "deals saved to deals.csv")
finally:
    mt5.shutdown()

Source: MQL5 docs: history_deals_get (Python) checked 18 Sep 2026

If you would rather not write code

The desktop terminal saves the same history as an HTML or PDF report with no Python at all, and that route works on any machine the terminal runs on.

Where to go next

Sections