Skip to main content

pymt5

CI Python License: MIT Documentation Platform

Python client for the MT5 Web Terminal via reverse-engineered WebSocket binary protocol.

Requirements

  • Python 3.11+ (3.11, 3.12, 3.13)
  • Platforms: Linux, macOS, Windows
  • Dependencies: websockets, aiohttp, cryptography

Features

Core Protocol

  • WebSocket transport to wss://web.metatrader.app/terminal
  • AES-CBC encryption with zero IV and PKCS7 padding
  • Bootstrap handshake (cmd=0) with automatic key exchange
  • Login (cmd=28) with UTF-16LE encoded fields
  • ping, logout, change_password, trader_params
  • verify_code (cmd=27) — two-factor authentication
  • request_opening_verification / submit_opening_verification (cmd=27/40)
  • open_demo_account (cmd=30) and open_real_account (cmd=39)
  • enable_otp / disable_otp (cmd=43)
  • open_demo (cmd=30) — legacy init-style wrapper kept for compatibility
  • send_notification (cmd=42) — server notifications

Account Data

  • get_account (cmd=3) — account metadata and balance state: balance, credit, currency, leverage, account/server/company names, timezone, rights flags, trade settings, leverage rules, commission tables
  • get_account_summary() — AccountInfo dataclass (uses cmd=3 + positions)
  • get_positions_and_orders (cmd=4) — open positions and pending orders
  • get_positions() — convenience: open positions only
  • get_orders() — convenience: pending orders only
  • get_trade_history (cmd=5) — closed deals and historical orders
  • get_deals() — convenience: closed deals only

Market Data

  • get_symbols (cmd=34, zlib compressed) — full symbol list with metadata
  • get_symbol_groups (cmd=9) — category tree (Forex, Crypto, Indexes, etc.)
  • get_full_symbol_info (cmd=18) — detailed contract specs (tick size, margins, volumes, bond face value/accrued interest, trade schedule, subscription flags)
  • get_spreads (cmd=20) — spread data with proper schema parsing
  • get_rates (cmd=11) — historical OHLCV bars (M1 to MN1), auto-detects extended format with real_volume
  • subscribe_ticks (cmd=7) — real-time tick push (cmd=8) with callback
  • subscribe_symbols — name-based tick subscription (resolves names via symbol cache)
  • subscribe_book (cmd=22) — order book / depth-of-market subscription
  • subscribe_book_by_name — name-based order book subscription

Official MetaTrader5-style Helpers

  • Session/account: initialize, shutdown, account_info, terminal_info, version
  • Compatibility state: last_error
  • Symbols/history: symbols_total, symbols_get, symbol_info, positions_total, positions_get, orders_total, orders_get, history_orders_*, history_deals_*
  • Bars/trading: copy_rates_range, copy_rates_from, copy_rates_from_pos, copy_ticks_from, copy_ticks_range, order_send, order_check
  • Local formula helpers: order_calc_profit, order_calc_margin (best-effort for forex/CFD/futures/stock/bond modes that the current Web Terminal computes client-side)
  • DOM/cache helpers: market_book_add, market_book_get, market_book_release, symbol_select, symbol_info_tick
  • terminal_info and version are best-effort Web Terminal views derived from cmd=3 plus observed public build metadata
  • copy_ticks_* are cached views over observed cmd=8 pushes, and order_check is a local compatibility-layer pre-flight rather than a server RPC

Trading

  • Raw: trade_request — full control over all trade fields, returns TradeResult
  • TradeResult includes: deal, order, volume, price, bid, ask, comment, request_id
  • High-level helpers (auto-resolve digits from symbol cache):
    • buy_market / sell_market — market orders with optional SL/TP
    • buy_limit / sell_limit — limit pending orders
    • buy_stop / sell_stop — stop pending orders
    • buy_stop_limit / sell_stop_limit — stop-limit pending orders
    • close_position — close by opposite market order (auto-detects BUY/SELL direction)
    • close_position_by — close by opposite position (hedge netting)
    • modify_position_sltp — modify SL/TP of open position
    • modify_pending_order — modify pending order price/SL/TP
    • cancel_pending_order — remove a pending order

Symbol Cache & Info

  • load_symbols() — fetch and cache all symbols for fast name→id/digits lookup
  • get_symbol_info(name) — lookup SymbolInfo by name
  • get_symbol_id(name) — lookup symbol ID by name
  • symbol_names — list all cached symbol names

Miscellaneous Commands

  • get_corporate_links (cmd=44) — broker links (support, education, social)
  • send_raw_command — send any command with raw payload
  • send_bootstrap_command_52 — experimental wrapper for reserved bootstrap-only cmd=52

Push Notifications

  • on_tick(callback) — real-time tick pushes (cmd=8)
  • on_position_update(callback) — position change pushes
  • on_order_update(callback) — order change pushes
  • on_trade_update(callback) — combined position+order push in single callback
  • on_trade_transaction(callback) — order add/update/delete + balance updates (cmd=10)
  • on_symbol_update(callback) — symbol change pushes (cmd=13)
  • on_account_update(callback) — account balance/equity/margin pushes (cmd=14)
  • on_login_status(callback) — login status pushes (cmd=15)
  • on_symbol_details(callback) — extended quote data with options greeks (cmd=17)
  • on_trade_result(callback) — async trade execution results (cmd=19)
  • on_book_update(callback) — order book / DOM pushes (cmd=23)

Reliability

  • Async context manager (async with MT5WebClient() as client:)
  • Auto heartbeat — periodic ping after login (configurable interval)
  • Auto reconnect — optional reconnect on disconnect with exponential backoff
  • Disconnect callback — on_disconnect() for custom handling
  • Python logging — structured logging via pymt5.client and pymt5.transport loggers

Constants & Enums

  • TradeResult dataclass with retcode, description, success, deal, order, volume, price fields
  • 33 MT5 return codes with human-readable descriptions
  • Complete trade constants: TRADE_ACTION_* (including CLOSE_BY), ORDER_TYPE_* (including STOP_LIMIT), ORDER_FILLING_*, ORDER_TIME_*
  • Position/deal enums: POSITION_TYPE_*, DEAL_TYPE_* (all 15 types), DEAL_ENTRY_*
  • Order states: ORDER_STATE_* (all 7 states)
  • Symbol trade modes: SYMBOL_TRADE_MODE_*
  • Command IDs exported: CMD_GET_ACCOUNT, CMD_GET_SYMBOL_GROUPS, CMD_TRADE_UPDATE_PUSH, CMD_ACCOUNT_UPDATE_PUSH, CMD_SYMBOL_DETAILS_PUSH, CMD_TRADE_RESULT_PUSH, CMD_SUBSCRIBE_BOOK, CMD_BOOK_PUSH, CMD_GET_CORPORATE_LINKS

Tests

  • 206 offline unit tests: protocol, schemas, roundtrip parsing, trade constants, symbol cache, volume conversion, reconnect logic, compatibility helpers, onboarding/OTP flows, local formula logic, full symbol schema, push handler registration, and extended rate/tick parsing

Live-verified against MetaQuotes-Demo on 2026-03-16. The current official Web Terminal reports build 5687, built on 2026-03-15. Verified features include: 6,104 symbols, 6 symbol groups, account info, positions, 60 M1 bars, deals, orders, tick push, all 9 order types, order book subscription, corporate links, notifications, verify code, trader params, and the current onboarding / OTP flows.

Install

pip install mt5-web-client

Or install from source:

git clone https://github.com/cloudQuant/pymt5.git
cd pymt5
pip install -e .

For development (tests + type checking):

pip install -e ".[dev]"
make check

Quick Start

import asyncio
from pymt5 import MT5WebClient


async def main():
    async with MT5WebClient(auto_reconnect=True) as client:
        await client.login(login=12345678, password="your-password")

        # Load symbol cache
        await client.load_symbols()
        print(f"Loaded {len(client.symbol_names)} symbols")

        # Full account info (balance, equity, margin, leverage)
        acct = await client.get_account()
        print(f"Balance: {acct['balance']}, Currency: {acct['currency']}, Leverage: 1:{acct['leverage']}")

        # Symbol groups
        groups = await client.get_symbol_groups()
        print(f"Groups: {groups}")

        # Subscribe to ticks
        def on_ticks(ticks):
            for t in ticks:
                print(f"TICK {t.get('symbol', t['symbol_id'])}: bid={t['bid']} ask={t['ask']}")

        client.on_tick(on_ticks)
        await client.subscribe_symbols(["EURUSD", "GBPUSD"])

        # Register for all push notifications
        client.on_trade_update(lambda d: print(f"Positions: {len(d['positions'])}"))
        client.on_account_update(lambda d: print(f"Balance: {d.get('balance')}"))
        client.on_trade_transaction(lambda d: print(f"Transaction: type={d.get('update_type')}"))
        client.on_trade_result(lambda d: print(f"Trade result: {d.get('result', {})}"))

        # Place a market buy
        result = await client.buy_market("EURUSD", 0.01, sl=1.0800, tp=1.1200)
        print(f"Trade: {result}")

        await asyncio.sleep(10)


asyncio.run(main())

Trading Examples

from pymt5 import (
    MT5WebClient, ORDER_TYPE_BUY, ORDER_TYPE_SELL,
    TRADE_RETCODE_DONE, ORDER_FILLING_IOC,
)

# Market orders
result = await client.buy_market("XAUUSD", 0.1, sl=2300.0, tp=2400.0)
result = await client.sell_market("EURUSD", 0.05, deviation=30)

# Pending orders
result = await client.buy_limit("EURUSD", 0.1, price=1.0800, sl=1.0750, tp=1.0900)
result = await client.sell_stop("GBPUSD", 0.1, price=1.2500)

# Stop-limit orders (trigger at price, then place limit at stop_limit_price)
result = await client.buy_stop_limit("EURUSD", 0.1, price=1.1000,
                                      stop_limit_price=1.0950, sl=1.0900, tp=1.1100)
result = await client.sell_stop_limit("GBPUSD", 0.1, price=1.2400,
                                       stop_limit_price=1.2450)

# Close position (auto-detects BUY/SELL direction)
result = await client.close_position("EURUSD", position_id=123456, volume=0.1)

# Close by opposite position (hedge netting)
result = await client.close_position_by("EURUSD", position_id=123456,
                                         position_by=789012)

# Modify SL/TP
result = await client.modify_position_sltp("EURUSD", position_id=123456,
                                            sl=1.0850, tp=1.0950)

# Cancel pending order
result = await client.cancel_pending_order(order=789012)

Push Notifications

# Combined position+order updates in one callback
def on_trade_change(data):
    print(f"Positions: {len(data['positions'])}, Orders: {len(data['orders'])}")
client.on_trade_update(on_trade_change)

# Trade transaction (order add/update/delete, balance updates)
def on_transaction(data):
    if data.get('update_type') == 2:
        print(f"Balance update: {data['balance_info']}")
    else:
        print(f"Order transaction: type={data.get('transaction_type')}")
client.on_trade_transaction(on_transaction)

# Account balance/equity changes
client.on_account_update(lambda d: print(f"Balance: {d.get('balance')}"))

# Extended symbol data with options greeks
client.on_symbol_details(lambda d: print(f"Delta: {d[0].get('delta')}"))

# Async trade execution results
client.on_trade_result(lambda d: print(f"Retcode: {d.get('result', {}).get('retcode')}"))

# Order book (DOM) updates
client.on_book_update(lambda entries: print(f"Book: {len(entries)} symbols"))

# Login status changes (e.g. forced logout)
client.on_login_status(lambda r: print(f"Login status: code={r.code}"))

Protocol Flow

  1. connect() — opens WebSocket, sends bootstrap (cmd=0), receives new AES key
  2. login() — sends credentials (cmd=28), receives session token, starts heartbeat
  3. Data commands (get_account, get_symbols, get_rates, get_positions_and_orders, etc.)
  4. close() — stops heartbeat, sends logout (cmd=2), closes WebSocket

Important: Do NOT call init_session() (cmd=29) after login — that command is for demo/real account creation, not session initialization.

Logging

import logging
logging.basicConfig(level=logging.DEBUG)
# Loggers: pymt5.client, pymt5.transport

Examples

Run any example from the project root:

pip install -e .
python examples/01_connect_and_account.py
Example Description
01_connect_and_account.py Login, full account info (cmd=3), positions/orders/deals, ping
02_market_data.py Symbol groups (cmd=9), symbol cache, spreads (cmd=20), OHLCV rates
03_realtime_ticks.py Tick subscription, account/symbol details/login status push handlers
04_trading.py Market/limit/stop orders, modify SL/TP, position close
05_order_book.py Order book (DOM) subscription (cmd=22/23)
06_all_push_notifications.py All 9 push notification types in one example
07_all_order_types.py All 9 order types + modify + cancel + close + raw trade_request
08_misc_features.py Corporate links, notifications, trader params, verify code, reconnect

Command Coverage

CMD Name Status
0 Bootstrap Implemented
2 Logout Implemented
3 Get Account NEW — balance, credit, currency, leverage, name
4 Get Positions/Orders Implemented
5 Get Trade History Implemented
6 Get Symbols Implemented
7 Subscribe Ticks Implemented
8 Tick Push Implemented
9 Get Symbol Groups NEW — Forex, Metals, Indexes, etc.
10 Trade Update Push NEW — order add/update/delete + balance updates
11 Get Rates Implemented
12 Trade Request Implemented
13 Symbol Update Push Implemented
14 Account Update Push NEW — real-time balance/equity changes
15 Login Status Push Implemented
17 Symbol Details Push NEW — extended quotes with options greeks
18 Get Full Symbols Implemented
19 Trade Result Push NEW — async trade execution results
20 Get Spreads IMPROVED — proper schema parsing
22 Subscribe Book NEW — order book / DOM subscription
23 Book Push NEW — order book push with bid/ask levels
24 Change Password Implemented
27 Verify Code Implemented
28 Login Implemented
29 Init Session Implemented
30 Open Demo Implemented
39 Open Real Account Implemented
40 Send Verification Codes Implemented
34 Get Symbols (gzip) Implemented
41 Trader Params Implemented
42 Notify Implemented
43 OTP Setup / Disable Implemented
44 Get Corporate Links NEW — broker links
51 Ping Implemented
52 Reserved Bootstrap Command EXPERIMENTAL — bootstrap-only helper with unknown business meaning

Commands 21, 25, 33, 37, 50, 52, 100-112 are still accepted by the transport allowlist but have no direct usage in the current public Web Terminal JavaScript source. Live probing on 2026-03-16 showed that 21, 25, 33, 37, 50, 100-112 time out with an empty payload, while 52 only returns an empty ACK on a pristine bootstrap-only socket and causes the server to drop the connection after cmd=29 or cmd=28. Commands 39, 40, and 43 are now implemented in pymt5.

Documentation

Full API documentation is available at pymt5.readthedocs.io/en/latest.

To build docs locally:

pip install -e ".[docs]"
cd docs && make html

CI/CD

This project uses GitHub Actions for continuous integration, testing across:

Python 3.11 Python 3.12 Python 3.13
Linux (ubuntu-latest) ✅ ✅ ✅
macOS (macos-latest) ✅ ✅ ✅
Windows (windows-latest) ✅ ✅ ✅

The CI pipeline also runs mypy type checking and builds the Sphinx documentation. For a local pre-push pass, run:

make check

Notes

  • This package is experimental and tracks the MT5 Web Terminal protocol as observed in the public Web Terminal build 5687 (built on 2026-03-15)
  • MetaQuotes may change the protocol at any time
  • Volume encoding: MT5 uses integer volumes where volume = lots × 10^precision. The MetaQuotes demo server uses precision=8, so 1.0 lot = 100,000,000 and 0.01 lot = 1,000,000
  • get_account() (cmd=3) returns balance, credit, currency, leverage, and name. Equity, margin, and profit are computed from positions
  • The Symbol Details push (cmd=17) schema may produce approximate values — the exact byte layout for options greeks varies by server
  • Order book (cmd=22/23) may not produce pushes on all servers — depends on broker configuration
  • Some commands like trader_params (cmd=41) may cause the server to close the connection on rapid successive calls

License

MIT License — see LICENSE for details.

Metadata

Release files for mt5-web-client 1.0.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mt5-web-client 1.0.3
File Size Uploaded Provenance Actions
mt5_web_client-1.0.3.tar.gz 162.4 kB With provenance Details for mt5_web_client-1.0.3.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for mt5-web-client 1.0.3
File Interpreter ABI Platform Actions
mt5_web_client-1.0.3-py3-none-any.whl Python 3 none any Details for mt5_web_client-1.0.3-py3-none-any.whl

Total release size: 239.8 kB

Release files / mt5_web_client-1.0.3.tar.gz

Download URL mt5_web_client-1.0.3.tar.gz
Size 162.4 kB
Tags Source
SHA-256 checksum
How to use checksums
44f3e9edd300142a8e956f91a24ad60e6f07f27657d4cfbfaa5ffd0de743d36d
BLAKE2b-256 checksum
How to use checksums
f96e67a1d7941c9d3f2a756bafc0a2713ec32ccda4e085e78f985dffe8bd3dbe
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 13, 2026.

Transparency log

Release files / mt5_web_client-1.0.3-py3-none-any.whl

Download URL mt5_web_client-1.0.3-py3-none-any.whl
Size 77.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a0560cc636ddaad87c343322046cb3ed9b36225857a33fd5cc6ed80e1be48148
BLAKE2b-256 checksum
How to use checksums
6a456e836afcbf48dce99833c3ef76c0c3e075aab549f75928535a38cf60b3d2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 13, 2026.

Transparency log

Security for mt5-web-client 1.0.3

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for mt5_web_client-1.0.3.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 13, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

1.0.3 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page