ποΈ Architecture & Data Flow (PyMT5 + MT5)¶
A practical map of how our Python SDK, gRPC services, and the MT5 terminal talk to each other β with just enough humor to keep the margin level above 100%.
πΊοΈ Big Picture¶
βββββββββββββββββββββββββββββββββββββββββββββββββ
β MT5 Terminal β
β (broker login, quotes, trades) β
βββββββββββββββββββββββββββββββββββββββββββββββββ
β local/IPC
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββ
β mt5_term_api.* (gRPC server) β
β Services: MarketInfo, Trade... β
βββββββββββββββββββββββββββββββββββββββββββββββββ
β gRPC
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββ
β Python SDK (MetaRpcMT5) β
β MT5Account (package/MetaRpcMT5/...) β
β + generated pb2/pb2_grpc stubs β
βββββββββββββββββββββββββββββββββββββββββββββββββ
β async/await
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββ
β Your App / Examples β
β (docs, examples, services) β
βββββββββββββββββββββββββββββββββββββββββββββββββ
You write: highβlevel await acct.method(...)
calls.
SDK does: request building, metadata, deadlines, retries, unwraps .reply.data
.
Server does: talks to the real MT5 terminal and executes.
βοΈ Main Components (by folders)¶
π© SDK & gRPC contracts (client side)¶
package/MetaRpcMT5/mt5_account.py
β MT5Account wrappers (public API).package/MetaRpcMT5/mt5_term_api_*.py
β pb2 messages (requests/replies/enums).package/MetaRpcMT5/mt5_term_api_*_pb2_grpc.py
β stubs (client bindings).package/MetaRpcMT5/mrpc_mt5_error_pb2.py
β errors/retcodes mapping.
π§ App layer & helpers (optional services)¶
app/core/mt5_connect_helper.py
β connection bootstrap, metadata.app/core/mt5_service.py
β higherβlevel service orchestration.app/services/streams_service.py
β stream fanβout (ticks/trade events).app/services/trading_service.py
β trading flows (send/modify/close).app/services/history_service.py
β history pagination & caching.app/patches/*.py
β compatibility tweaks (symbol params, market info, etc.).
π Docs & Examples¶
docs/MT5Account/**
β method specs & overviews (what you read now).examples/quick_start_connect.py
β minimal bootstrap.examples/mt5_account_ex.py
β endβtoβend usage playground.
π Data Flow (Unary)¶
- Your call β `await acct.symbol_info_double(...)
- Wrapper builds
Request
, setsmetadata
, computestimeout
fromdeadline
. - Stub β
ServiceStub.Method(request, metadata, timeout)
. - Server performs the operation via MT5 terminal.
- Reply β SDK unwraps
reply.data
β you get clean*.Data
(or a primitive likefloat
).
from MetaRpcMT5 import mt5_term_api_account_information_pb2 as ai_pb2
value = await acct.account_info_double(ai_pb2.AccountInfoDoublePropertyType.ACCOUNT_EQUITY)
print(f"Equity: {value:.2f}")
π Data Flow (Streaming)¶
Streams keep a channel open and push events. Use cancellation_event and keep handlers nonβblocking.
import asyncio
stop = asyncio.Event()
async for ev in acct.on_trade(cancellation_event=stop):
queue.put_nowait(ev) # heavy work elsewhere
if should_stop(ev):
stop.set()
Common streams:
on_symbol_tick
β live ticks per symbol.on_trade
β highβlevel deltas (orders/positions/deals) + account snapshot.on_trade_transaction
β lowβlevel transaction + request + result.on_position_profit
β timed P/L frames for positions.on_positions_and_pending_orders_tickets
β IDsβonly snapshots for setβdiff.
Links: Subscriptions Overview
π§© RPC Domains & Where to Look¶
- Account Info β balance/equity/margins: Overview
- Orders Β· Positions Β· History β live & past trading objects: Overview
- Symbols & Market β symbol catalog, properties, sessions, DOM: Overview
- Trading Ops β send/modify/close, checks, margin calc: Overview
β¨ Highlights¶
- Wrappers return payloads (
*.Data
) already unwrapped from replies. - Deadlines become stub timeouts; pass them for predictable latency.
- Retries & reconnects handled in wrappers (
execute_with_reconnect(...)
). - UTC timestamps everywhere; convert once near UI.
- Serverβside sorting via enums; clientβside filtering for symbol lists is often cheaper.
π οΈ Developer Notes¶
- Prefer enums from pb2 (no βmagic numbersβ).
- For Market Book use the trio: market_book_add β market_book_get β market_book_release.
- Coldβstart: get a full snapshot once (OpenedOrders), then maintain via streams.
- Cheap change detection: IDsβonly stream β fetch details only on change.
π¦ Minimal Bootstrap (Example)¶
from MetaRpcMT5.mt5_account import MT5Account
from MetaRpcMT5 import mt5_term_api_account_helper_pb2 as ah_pb2
acct = MT5Account(...)
od = await acct.opened_orders(
ah_pb2.BMT5_ENUM_OPENED_ORDER_SORT_TYPE.BMT5_OPENED_ORDER_SORT_BY_OPEN_TIME_ASC
)
print(len(od.opened_orders), len(od.position_infos))
π§ͺ Debug & Troubleshooting¶
- Log transport issues with
app/utils/grpc_debug.py
. - Keep both retcode int and string (see
mrpc_mt5_error_pb2.py
). - If a stream "goes quiet", check that your handler isnβt blocking and the release was not called prematurely (DOM).