pdmt5
Low-level MetaTrader 5 wrapper and pandas/dict conversion package
Overview
pdmt5 is a Python package that provides a low-level wrapper around the MetaTrader 5 (MT5) API with pandas DataFrame and dictionary conversion helpers. It exposes raw MT5 API calls, converts results into pandas DataFrames and dicts, and provides canonical constant parsing for timeframes, tick copy flags, and order types.
High-level trading orchestration (market-order construction, margin-budget sizing, position lifecycle management, strategy or batch workflows) is out of scope. Those concerns belong in downstream applications or tools such as mt5cli.
See the architecture contract for the stable root API,
return shapes, lifecycle and error semantics, dependency direction, and the
full list of responsibilities deliberately left to mt5cli or downstream
applications.
Key Features
- Pandas Integration: DataFrame and dictionary helpers for easy analysis
- Type Safety: Full type hints with strict pyright checking and pydantic validation
- Comprehensive MT5 Coverage: Account info, market data, tick data, orders, positions, and more
- Canonical MT5 Constants: Shared parsing for timeframes, COPY_TICKS flags, and ORDER_TYPE values with official names, short aliases, or valid integers
- Context Manager Support: Clean initialization and cleanup with
withstatements;Mt5DataClientappliesMt5Configautomatically - Time Series Ready: OHLCV data with proper datetime indexing
- Robust Error Handling: Custom exceptions with detailed MT5 failure messages
- Direct Order Primitives:
order_check/order_sendwrappers with DataFrame/dict conversions
Requirements
- Operating System: Windows (required by MetaTrader5 API)
- Python: 3.11 or higher
- MetaTrader 5: Terminal must be installed
Installation
Using pip
pip install -U pdmt5 MetaTrader5
Using uv
git clone https://github.com/dceoy/pdmt5.git
cd pdmt5
uv sync
Quick Start
from datetime import datetime
from pdmt5 import Mt5DataClient, Mt5Config, parse_timeframe
# Configure connection
config = Mt5Config(
login=12345678, password="your_password", server="YourBroker-Server", timeout=60000
)
# Use as context manager
with Mt5DataClient(config=config) as client:
# Get account information as DataFrame
account_info = client.account_info_as_df()
print(account_info)
# Get OHLCV data as DataFrame
rates = client.copy_rates_from_as_df(
symbol="EURUSD",
timeframe=parse_timeframe("H1"),
date_from=datetime(2024, 1, 1),
count=100,
)
print(rates.head())
# Get current positions as DataFrame
positions = client.positions_get_as_df()
print(positions)
Core Components
Mt5Client
The base client wrapper for all MetaTrader5 operations with context manager support:
- Connection Management:
initialize()- Establish connection with MT5 terminal (with optional path, login, password, server, timeout)login()- Connect to trading account with credentialsshutdown()- Close MT5 terminal connection- Context manager support (
withstatement) for automatic initialization/cleanup (initialize only)
- Terminal Information:
version()- Get MT5 terminal version, build, and release datelast_error()- Get last error code and descriptionaccount_info()- Get current trading account informationterminal_info()- Get terminal status and settings
- Symbol Operations:
symbols_total()- Get total number of financial instrumentssymbols_get()- Get all symbols or filter by groupsymbol_info()- Get detailed data on specific symbolsymbol_info_tick()- Get last tick for symbolsymbol_select()- Show/hide symbol in MarketWatch
- Market Depth:
market_book_add()- Subscribe to Market Depth eventsmarket_book_get()- Get current Market Depth datamarket_book_release()- Unsubscribe from Market Depth
- Market Data:
copy_rates_from()- Get bars from specified datecopy_rates_from_pos()- Get bars from specified positioncopy_rates_range()- Get bars for date rangecopy_ticks_from()- Get ticks from specified datecopy_ticks_range()- Get ticks for date range
- Order Operations:
orders_total()- Get number of active ordersorders_get()- Get active orders with optional filtersorder_calc_margin()- Calculate required marginorder_calc_profit()- Calculate potential profitorder_check()- Check if order can be placedorder_send()- Send order to trade server
- Position Operations:
positions_total()- Get number of open positionspositions_get()- Get open positions with optional filters
- Trading History:
history_orders_total()- Get number of historical ordershistory_orders_get()- Get historical orders with filtershistory_deals_total()- Get number of historical dealshistory_deals_get()- Get historical deals with filters
Mt5DataClient
Extends Mt5Client with pandas DataFrame and dictionary conversions:
- Enhanced Connection:
initialize_and_login_mt5()- Combined initialization and login with retry logic- Configurable retry attempts via
retry_countparameter
- DataFrame/Dictionary Conversions: All methods have both
_as_dfand_as_dictvariants:version_as_dict/df()- MT5 version informationlast_error_as_dict/df()- Last error detailsaccount_info_as_dict/df()- Account informationterminal_info_as_dict/df()- Terminal informationsymbols_get_as_dicts/df()- Symbol list with optional group filtersymbol_info_as_dict/df()- Single symbol informationsymbol_info_tick_as_dict/df()- Last tick datamarket_book_get_as_dicts/df()- Market depth data
- OHLCV Data Methods:
copy_rates_from_as_dicts/df()- Historical bars from datecopy_rates_from_pos_as_dicts/df()- Historical bars from positioncopy_rates_range_as_dicts/df()- Historical bars for date range
- Tick Data Methods:
copy_ticks_from_as_dicts/df()- Historical ticks from datecopy_ticks_range_as_dicts/df()- Historical ticks for date range
- Trading Data Methods:
orders_get_as_dicts/df()- Active orders with filtersorder_check_as_dict/df()- Order validation resultsorder_send_as_dict/df()- Order execution resultspositions_get_as_dicts/df()- Open positions with filtershistory_orders_get_as_dicts/df()- Historical orders with date/ticket/position filtershistory_deals_get_as_dicts/df()- Historical deals with date/ticket/position filters
- Features:
- Automatic time conversion to datetime objects
- Optional DataFrame indexing with
index_keysparameter - Input validation for dates, counts, and positions
- Pydantic-based configuration via
Mt5Config
MT5 Constant Parsing
pdmt5 is the canonical source for parsing MT5 constants shared by CLI, HTTP API,
and other application layers. The constants module does not import
MetaTrader5, so it can be used for request validation and JSON schema
generation without a live terminal.
from pdmt5 import parse_copy_ticks, parse_order_type, parse_timeframe
from pdmt5.constants import (
list_copy_ticks_names,
list_copy_ticks_values,
list_order_type_names,
list_order_type_values,
list_timeframe_names,
list_timeframe_values,
)
parse_timeframe("TIMEFRAME_M1") # 1
parse_timeframe("M1") # 1
parse_copy_ticks("COPY_TICKS_ALL") # -1
parse_copy_ticks("ALL") # -1
parse_order_type("ORDER_TYPE_BUY") # 0
parse_order_type("BUY") # 0
# Integer values are accepted only when they belong to the requested family.
parse_timeframe(16385) # TIMEFRAME_H1
parse_order_type(16385) # raises ValueError
# Use these helpers to build Pydantic JSON schema enums.
timeframe_schema = {
"anyOf": [
{"type": "string", "enum": list_timeframe_names()},
{"type": "integer", "enum": list_timeframe_values()},
],
}
copy_ticks_schema = {
"anyOf": [
{"type": "string", "enum": list_copy_ticks_names()},
{"type": "integer", "enum": list_copy_ticks_values()},
],
}
order_type_schema = {
"anyOf": [
{"type": "string", "enum": list_order_type_names()},
{"type": "integer", "enum": list_order_type_values()},
],
}
Configuration
from pdmt5 import Mt5Config
config = Mt5Config(
login=12345678, # MT5 account number
password="password", # MT5 password
server="Broker-Server", # MT5 server name
timeout=60000, # Connection timeout in ms
)
Examples
Getting Historical Data
from datetime import datetime
from pdmt5 import Mt5DataClient, parse_timeframe
with Mt5DataClient(config=config) as client:
# Get last 1000 H1 bars for EURUSD as DataFrame
df = client.copy_rates_from_as_df(
symbol="EURUSD",
timeframe=parse_timeframe("TIMEFRAME_H1"),
date_from=datetime.now(),
count=1000,
)
# Data includes: time, open, high, low, close, tick_volume, spread, real_volume
print(df.columns)
print(df.describe())
Working with Tick Data
from datetime import datetime, timedelta
from pdmt5 import parse_copy_ticks
with Mt5DataClient(config=config) as client:
# Get ticks for the last hour as DataFrame
ticks = client.copy_ticks_from_as_df(
symbol="EURUSD",
date_from=datetime.now() - timedelta(hours=1),
count=10000,
flags=parse_copy_ticks("COPY_TICKS_ALL"),
)
# Tick data includes: time, bid, ask, last, volume, flags
print(ticks.head())
Analyzing Positions
with Mt5DataClient(config=config) as client:
# Get all open positions as DataFrame
positions = client.positions_get_as_df()
if not positions.empty:
# Calculate summary statistics
summary = positions.groupby("symbol").agg({
"volume": "sum",
"profit": "sum",
"price_open": "mean",
})
print(summary)
Order Check and Send
with Mt5DataClient(config=config) as client:
# Validate an order request without sending
request = {
"action": 1, # TRADE_ACTION_DEAL
"symbol": "EURUSD",
"volume": 0.1,
"type": 0, # ORDER_TYPE_BUY
"type_filling": 1,
"type_time": 0,
}
check = client.order_check_as_dict(request=request)
print(f"Check retcode: {check['retcode']}")
# Send the order to the trade server
result = client.order_send_as_dict(request=request)
print(f"Send retcode: {result['retcode']}")
Development
Setup Development Environment
# Clone repository
git clone https://github.com/dceoy/pdmt5.git
cd pdmt5
# Install with uv
uv sync
# Run tests
uv run pytest tests/ -v
# Run type checking
uv run pyright .
# Run linting
uv run ruff check --fix .
uv run ruff format .
Code Quality
This project maintains high code quality standards:
- Type Checking: Strict mode with pyright
- Linting: Comprehensive ruff configuration with 40+ rule categories
- Testing: pytest with 100% branch coverage enforcement
- Documentation: Google-style docstrings
Error Handling
The package provides detailed error information:
from pdmt5 import Mt5RuntimeError, parse_timeframe
try:
with Mt5DataClient(config=config) as client:
data = client.copy_rates_from(
"INVALID", parse_timeframe("H1"), datetime.now(), 100
)
except Mt5RuntimeError as e:
print(f"MT5 Error: {e}")
print("Inspect the exception message for the MT5 status details.")
Timestamps and Timezones
MT5 epoch timestamps (time, time_msc, time_setup, etc.) are labels on the
trade server's wall clock (typically UTC+2 or UTC+3), not true UTC. pdmt5
converts them to timezone-naive datetime64/Timestamp values that
preserve those labels:
- Converted datetimes are naive and represent server time. Do not treat
them as UTC; comparing them against
datetime.now(UTC)or persisting them with a UTC label introduces a 2–3 hour bias. date_from/date_toarguments (e.g. inhistory_deals_get,copy_rates_range,copy_ticks_range) are compared against server-labeled epochs by the MetaTrader5 API, so pass datetimes expressed in server time.- The official MQL5 docs call these epochs "UTC" because no timezone shift is
applied to them, and they recommend
tzinfo=timezone.utcso that the MetaTrader5 package does not shift naive datetimes by your local timezone. Both hold here: construct datetimes withtzinfo=timezone.utc, but choose wall-clock values that follow the trade server's clock. - To skip the conversion and work with the raw epochs, pass
skip_to_datetime=Trueto the*_as_dict/*_as_dfmethods.
Limitations
- Windows Only: Due to MetaTrader5 API requirements
- MT5 Terminal Required: The MetaTrader 5 terminal must be installed
- Single Thread: MT5 API is not thread-safe
- Server-Time Timestamps: Returned datetimes are timezone-naive server time, not UTC (see Timestamps and Timezones)
Contributing
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Ensure tests pass and coverage is maintained
- Submit a pull request
See CLAUDE.md for development guidelines.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Author
Daichi Narushima, Ph.D.
Acknowledgments
- MetaTrader 5 for providing the Python API
- The pandas community for the excellent data manipulation tools
Release files for pdmt5 1.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pdmt5-1.2.0.tar.gz | 24.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pdmt5-1.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 46.4 kB
Release files / pdmt5-1.2.0.tar.gz
| Download URL | pdmt5-1.2.0.tar.gz |
|---|---|
| Size | 24.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
972f500ee7e50032a14f83874baccbef69bf7377335011f72d0bbdd6e221edcd
|
|
BLAKE2b-256 checksum How to use checksums |
9b44410bdc4d567ddb49f5b8d0d366467c9cce5e1862ecfbbcd09734c8f34eac
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
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 Jul 10, 2026.
Transparency logRelease files / pdmt5-1.2.0-py3-none-any.whl
| Download URL | pdmt5-1.2.0-py3-none-any.whl |
|---|---|
| Size | 22.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ce355f24f4ec08ba5cc0148b5c529f73c671ea2e83b1d65248de1150369daeb7
|
|
BLAKE2b-256 checksum How to use checksums |
12ec88297de8aad400c922715cbdc15804dcf1ac5fbc0a3a0abeafc988c3c25d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
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 Jul 10, 2026.
Transparency log