mt5-web-client 1.0.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mt5_web_client-1.0.3/LICENSE +21 -0
- mt5_web_client-1.0.3/MANIFEST.in +1 -0
- mt5_web_client-1.0.3/PKG-INFO +422 -0
- mt5_web_client-1.0.3/README.md +377 -0
- mt5_web_client-1.0.3/mt5_web_client.egg-info/PKG-INFO +422 -0
- mt5_web_client-1.0.3/mt5_web_client.egg-info/SOURCES.txt +59 -0
- mt5_web_client-1.0.3/mt5_web_client.egg-info/dependency_links.txt +1 -0
- mt5_web_client-1.0.3/mt5_web_client.egg-info/requires.txt +23 -0
- mt5_web_client-1.0.3/mt5_web_client.egg-info/top_level.txt +1 -0
- mt5_web_client-1.0.3/pymt5/__init__.py +275 -0
- mt5_web_client-1.0.3/pymt5/_account.py +488 -0
- mt5_web_client-1.0.3/pymt5/_currency.py +301 -0
- mt5_web_client-1.0.3/pymt5/_dataframe.py +31 -0
- mt5_web_client-1.0.3/pymt5/_logging.py +39 -0
- mt5_web_client-1.0.3/pymt5/_market_data.py +629 -0
- mt5_web_client-1.0.3/pymt5/_metrics.py +39 -0
- mt5_web_client-1.0.3/pymt5/_order_helpers.py +525 -0
- mt5_web_client-1.0.3/pymt5/_order_manager.py +229 -0
- mt5_web_client-1.0.3/pymt5/_parsers.py +583 -0
- mt5_web_client-1.0.3/pymt5/_pool.py +116 -0
- mt5_web_client-1.0.3/pymt5/_push_handlers.py +498 -0
- mt5_web_client-1.0.3/pymt5/_rate_limiter.py +46 -0
- mt5_web_client-1.0.3/pymt5/_subscription.py +62 -0
- mt5_web_client-1.0.3/pymt5/_trading.py +722 -0
- mt5_web_client-1.0.3/pymt5/_validation.py +33 -0
- mt5_web_client-1.0.3/pymt5/client.py +612 -0
- mt5_web_client-1.0.3/pymt5/constants.py +290 -0
- mt5_web_client-1.0.3/pymt5/crypto.py +40 -0
- mt5_web_client-1.0.3/pymt5/events.py +77 -0
- mt5_web_client-1.0.3/pymt5/exceptions.py +89 -0
- mt5_web_client-1.0.3/pymt5/helpers.py +75 -0
- mt5_web_client-1.0.3/pymt5/protocol.py +309 -0
- mt5_web_client-1.0.3/pymt5/py.typed +0 -0
- mt5_web_client-1.0.3/pymt5/schemas.py +1076 -0
- mt5_web_client-1.0.3/pymt5/transport.py +273 -0
- mt5_web_client-1.0.3/pymt5/types.py +306 -0
- mt5_web_client-1.0.3/pyproject.toml +90 -0
- mt5_web_client-1.0.3/setup.cfg +4 -0
- mt5_web_client-1.0.3/tests/test_benchmarks.py +168 -0
- mt5_web_client-1.0.3/tests/test_client_async.py +1042 -0
- mt5_web_client-1.0.3/tests/test_client_features.py +1015 -0
- mt5_web_client-1.0.3/tests/test_client_lifecycle.py +931 -0
- mt5_web_client-1.0.3/tests/test_coverage_gaps.py +793 -0
- mt5_web_client-1.0.3/tests/test_fuzz.py +230 -0
- mt5_web_client-1.0.3/tests/test_helpers.py +194 -0
- mt5_web_client-1.0.3/tests/test_integration.py +150 -0
- mt5_web_client-1.0.3/tests/test_market_data_coverage.py +2226 -0
- mt5_web_client-1.0.3/tests/test_new_modules.py +476 -0
- mt5_web_client-1.0.3/tests/test_onboarding_commands.py +345 -0
- mt5_web_client-1.0.3/tests/test_package_version.py +29 -0
- mt5_web_client-1.0.3/tests/test_phase19.py +711 -0
- mt5_web_client-1.0.3/tests/test_phase20_21.py +576 -0
- mt5_web_client-1.0.3/tests/test_phase_15_16.py +971 -0
- mt5_web_client-1.0.3/tests/test_protocol_smoke.py +336 -0
- mt5_web_client-1.0.3/tests/test_push_handlers.py +1252 -0
- mt5_web_client-1.0.3/tests/test_release_tag.py +34 -0
- mt5_web_client-1.0.3/tests/test_remaining_coverage.py +1687 -0
- mt5_web_client-1.0.3/tests/test_trading_coverage.py +2310 -0
- mt5_web_client-1.0.3/tests/test_transport.py +224 -0
- mt5_web_client-1.0.3/tests/test_transport_lifecycle.py +892 -0
- mt5_web_client-1.0.3/tests/test_validation.py +204 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 cloudQuant
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
prune analysis
|
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mt5-web-client
|
|
3
|
+
Version: 1.0.3
|
|
4
|
+
Summary: Python client for MT5 Web Terminal via reverse-engineered WebSocket binary protocol
|
|
5
|
+
Author: cloudQuant
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/cloudQuant/pymt5
|
|
8
|
+
Project-URL: Documentation, https://pymt5.readthedocs.io
|
|
9
|
+
Project-URL: Repository, https://github.com/cloudQuant/pymt5
|
|
10
|
+
Project-URL: Issues, https://github.com/cloudQuant/pymt5/issues
|
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Office/Business :: Financial :: Investment
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Requires-Python: >=3.11
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Requires-Dist: websockets<16,>=13.0
|
|
26
|
+
Requires-Dist: cryptography<45,>=42.0.0
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: build>=1.0; extra == "dev"
|
|
29
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
30
|
+
Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
|
|
31
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
32
|
+
Requires-Dist: hypothesis>=6.0; extra == "dev"
|
|
33
|
+
Requires-Dist: mypy>=1.0; extra == "dev"
|
|
34
|
+
Requires-Dist: ruff>=0.1; extra == "dev"
|
|
35
|
+
Requires-Dist: twine>=5.0; extra == "dev"
|
|
36
|
+
Provides-Extra: docs
|
|
37
|
+
Requires-Dist: sphinx>=7.0; extra == "docs"
|
|
38
|
+
Requires-Dist: sphinx-rtd-theme>=2.0; extra == "docs"
|
|
39
|
+
Requires-Dist: sphinx-autodoc-typehints>=2.0; extra == "docs"
|
|
40
|
+
Provides-Extra: structlog
|
|
41
|
+
Requires-Dist: structlog>=24.0; extra == "structlog"
|
|
42
|
+
Provides-Extra: pandas
|
|
43
|
+
Requires-Dist: pandas>=2.0; extra == "pandas"
|
|
44
|
+
Dynamic: license-file
|
|
45
|
+
|
|
46
|
+
# pymt5
|
|
47
|
+
|
|
48
|
+
[](https://github.com/cloudQuant/pymt5/actions/workflows/ci.yml)
|
|
49
|
+
[](https://www.python.org)
|
|
50
|
+
[](https://opensource.org/licenses/MIT)
|
|
51
|
+
[](https://pymt5.readthedocs.io/en/latest/)
|
|
52
|
+
[](https://github.com/cloudQuant/pymt5)
|
|
53
|
+
|
|
54
|
+
Python client for the MT5 Web Terminal via reverse-engineered WebSocket binary protocol.
|
|
55
|
+
|
|
56
|
+
## Requirements
|
|
57
|
+
|
|
58
|
+
- **Python 3.11+** (3.11, 3.12, 3.13)
|
|
59
|
+
- **Platforms**: Linux, macOS, Windows
|
|
60
|
+
- **Dependencies**: `websockets`, `aiohttp`, `cryptography`
|
|
61
|
+
|
|
62
|
+
## Features
|
|
63
|
+
|
|
64
|
+
### Core Protocol
|
|
65
|
+
- WebSocket transport to `wss://web.metatrader.app/terminal`
|
|
66
|
+
- AES-CBC encryption with zero IV and PKCS7 padding
|
|
67
|
+
- Bootstrap handshake (cmd=0) with automatic key exchange
|
|
68
|
+
- Login (cmd=28) with UTF-16LE encoded fields
|
|
69
|
+
- `ping`, `logout`, `change_password`, `trader_params`
|
|
70
|
+
- `verify_code` (cmd=27) — two-factor authentication
|
|
71
|
+
- `request_opening_verification` / `submit_opening_verification` (cmd=27/40)
|
|
72
|
+
- `open_demo_account` (cmd=30) and `open_real_account` (cmd=39)
|
|
73
|
+
- `enable_otp` / `disable_otp` (cmd=43)
|
|
74
|
+
- `open_demo` (cmd=30) — legacy init-style wrapper kept for compatibility
|
|
75
|
+
- `send_notification` (cmd=42) — server notifications
|
|
76
|
+
|
|
77
|
+
### Account Data
|
|
78
|
+
- **`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
|
|
79
|
+
- `get_account_summary()` — `AccountInfo` dataclass (uses cmd=3 + positions)
|
|
80
|
+
- `get_positions_and_orders` (cmd=4) — open positions and pending orders
|
|
81
|
+
- `get_positions()` — convenience: open positions only
|
|
82
|
+
- `get_orders()` — convenience: pending orders only
|
|
83
|
+
- `get_trade_history` (cmd=5) — closed deals and historical orders
|
|
84
|
+
- `get_deals()` — convenience: closed deals only
|
|
85
|
+
|
|
86
|
+
### Market Data
|
|
87
|
+
- `get_symbols` (cmd=34, zlib compressed) — full symbol list with metadata
|
|
88
|
+
- **`get_symbol_groups` (cmd=9)** — category tree (Forex, Crypto, Indexes, etc.)
|
|
89
|
+
- `get_full_symbol_info` (cmd=18) — detailed contract specs (tick size, margins, volumes, bond face value/accrued interest, trade schedule, subscription flags)
|
|
90
|
+
- **`get_spreads` (cmd=20)** — spread data with proper schema parsing
|
|
91
|
+
- `get_rates` (cmd=11) — historical OHLCV bars (M1 to MN1), auto-detects extended format with `real_volume`
|
|
92
|
+
- `subscribe_ticks` (cmd=7) — real-time tick push (cmd=8) with callback
|
|
93
|
+
- `subscribe_symbols` — name-based tick subscription (resolves names via symbol cache)
|
|
94
|
+
- **`subscribe_book` (cmd=22)** — order book / depth-of-market subscription
|
|
95
|
+
- **`subscribe_book_by_name`** — name-based order book subscription
|
|
96
|
+
|
|
97
|
+
### Official MetaTrader5-style Helpers
|
|
98
|
+
- Session/account: `initialize`, `shutdown`, `account_info`, `terminal_info`, `version`
|
|
99
|
+
- Compatibility state: `last_error`
|
|
100
|
+
- Symbols/history: `symbols_total`, `symbols_get`, `symbol_info`, `positions_total`, `positions_get`, `orders_total`, `orders_get`, `history_orders_*`, `history_deals_*`
|
|
101
|
+
- Bars/trading: `copy_rates_range`, `copy_rates_from`, `copy_rates_from_pos`, `copy_ticks_from`, `copy_ticks_range`, `order_send`, `order_check`
|
|
102
|
+
- 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)
|
|
103
|
+
- DOM/cache helpers: `market_book_add`, `market_book_get`, `market_book_release`, `symbol_select`, `symbol_info_tick`
|
|
104
|
+
- `terminal_info` and `version` are best-effort Web Terminal views derived from `cmd=3` plus observed public build metadata
|
|
105
|
+
- `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
|
|
106
|
+
|
|
107
|
+
### Trading
|
|
108
|
+
- **Raw**: `trade_request` — full control over all trade fields, returns `TradeResult`
|
|
109
|
+
- **`TradeResult`** includes: `deal`, `order`, `volume`, `price`, `bid`, `ask`, `comment`, `request_id`
|
|
110
|
+
- **High-level helpers** (auto-resolve digits from symbol cache):
|
|
111
|
+
- `buy_market` / `sell_market` — market orders with optional SL/TP
|
|
112
|
+
- `buy_limit` / `sell_limit` — limit pending orders
|
|
113
|
+
- `buy_stop` / `sell_stop` — stop pending orders
|
|
114
|
+
- `buy_stop_limit` / `sell_stop_limit` — stop-limit pending orders
|
|
115
|
+
- `close_position` — close by opposite market order (auto-detects BUY/SELL direction)
|
|
116
|
+
- `close_position_by` — close by opposite position (hedge netting)
|
|
117
|
+
- `modify_position_sltp` — modify SL/TP of open position
|
|
118
|
+
- `modify_pending_order` — modify pending order price/SL/TP
|
|
119
|
+
- `cancel_pending_order` — remove a pending order
|
|
120
|
+
|
|
121
|
+
### Symbol Cache & Info
|
|
122
|
+
- `load_symbols()` — fetch and cache all symbols for fast name→id/digits lookup
|
|
123
|
+
- `get_symbol_info(name)` — lookup `SymbolInfo` by name
|
|
124
|
+
- `get_symbol_id(name)` — lookup symbol ID by name
|
|
125
|
+
- `symbol_names` — list all cached symbol names
|
|
126
|
+
|
|
127
|
+
### Miscellaneous Commands
|
|
128
|
+
- **`get_corporate_links` (cmd=44)** — broker links (support, education, social)
|
|
129
|
+
- `send_raw_command` — send any command with raw payload
|
|
130
|
+
- `send_bootstrap_command_52` — experimental wrapper for reserved bootstrap-only `cmd=52`
|
|
131
|
+
|
|
132
|
+
### Push Notifications
|
|
133
|
+
- `on_tick(callback)` — real-time tick pushes (cmd=8)
|
|
134
|
+
- `on_position_update(callback)` — position change pushes
|
|
135
|
+
- `on_order_update(callback)` — order change pushes
|
|
136
|
+
- `on_trade_update(callback)` — combined position+order push in single callback
|
|
137
|
+
- **`on_trade_transaction(callback)`** — order add/update/delete + balance updates (cmd=10)
|
|
138
|
+
- `on_symbol_update(callback)` — symbol change pushes (cmd=13)
|
|
139
|
+
- **`on_account_update(callback)`** — account balance/equity/margin pushes (cmd=14)
|
|
140
|
+
- `on_login_status(callback)` — login status pushes (cmd=15)
|
|
141
|
+
- **`on_symbol_details(callback)`** — extended quote data with options greeks (cmd=17)
|
|
142
|
+
- **`on_trade_result(callback)`** — async trade execution results (cmd=19)
|
|
143
|
+
- **`on_book_update(callback)`** — order book / DOM pushes (cmd=23)
|
|
144
|
+
|
|
145
|
+
### Reliability
|
|
146
|
+
- **Async context manager** (`async with MT5WebClient() as client:`)
|
|
147
|
+
- **Auto heartbeat** — periodic ping after login (configurable interval)
|
|
148
|
+
- **Auto reconnect** — optional reconnect on disconnect with exponential backoff
|
|
149
|
+
- **Disconnect callback** — `on_disconnect()` for custom handling
|
|
150
|
+
- **Python logging** — structured logging via `pymt5.client` and `pymt5.transport` loggers
|
|
151
|
+
|
|
152
|
+
### Constants & Enums
|
|
153
|
+
- `TradeResult` dataclass with `retcode`, `description`, `success`, `deal`, `order`, `volume`, `price` fields
|
|
154
|
+
- 33 MT5 return codes with human-readable descriptions
|
|
155
|
+
- Complete trade constants: `TRADE_ACTION_*` (including `CLOSE_BY`), `ORDER_TYPE_*` (including `STOP_LIMIT`), `ORDER_FILLING_*`, `ORDER_TIME_*`
|
|
156
|
+
- Position/deal enums: `POSITION_TYPE_*`, `DEAL_TYPE_*` (all 15 types), `DEAL_ENTRY_*`
|
|
157
|
+
- Order states: `ORDER_STATE_*` (all 7 states)
|
|
158
|
+
- Symbol trade modes: `SYMBOL_TRADE_MODE_*`
|
|
159
|
+
- 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`
|
|
160
|
+
|
|
161
|
+
### Tests
|
|
162
|
+
- 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
|
|
163
|
+
|
|
164
|
+
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.
|
|
165
|
+
|
|
166
|
+
## Install
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
pip install mt5-web-client
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Or install from source:
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
git clone https://github.com/cloudQuant/pymt5.git
|
|
176
|
+
cd pymt5
|
|
177
|
+
pip install -e .
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
For development (tests + type checking):
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
pip install -e ".[dev]"
|
|
184
|
+
make check
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Quick Start
|
|
188
|
+
|
|
189
|
+
```python
|
|
190
|
+
import asyncio
|
|
191
|
+
from pymt5 import MT5WebClient
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
async def main():
|
|
195
|
+
async with MT5WebClient(auto_reconnect=True) as client:
|
|
196
|
+
await client.login(login=12345678, password="your-password")
|
|
197
|
+
|
|
198
|
+
# Load symbol cache
|
|
199
|
+
await client.load_symbols()
|
|
200
|
+
print(f"Loaded {len(client.symbol_names)} symbols")
|
|
201
|
+
|
|
202
|
+
# Full account info (balance, equity, margin, leverage)
|
|
203
|
+
acct = await client.get_account()
|
|
204
|
+
print(f"Balance: {acct['balance']}, Currency: {acct['currency']}, Leverage: 1:{acct['leverage']}")
|
|
205
|
+
|
|
206
|
+
# Symbol groups
|
|
207
|
+
groups = await client.get_symbol_groups()
|
|
208
|
+
print(f"Groups: {groups}")
|
|
209
|
+
|
|
210
|
+
# Subscribe to ticks
|
|
211
|
+
def on_ticks(ticks):
|
|
212
|
+
for t in ticks:
|
|
213
|
+
print(f"TICK {t.get('symbol', t['symbol_id'])}: bid={t['bid']} ask={t['ask']}")
|
|
214
|
+
|
|
215
|
+
client.on_tick(on_ticks)
|
|
216
|
+
await client.subscribe_symbols(["EURUSD", "GBPUSD"])
|
|
217
|
+
|
|
218
|
+
# Register for all push notifications
|
|
219
|
+
client.on_trade_update(lambda d: print(f"Positions: {len(d['positions'])}"))
|
|
220
|
+
client.on_account_update(lambda d: print(f"Balance: {d.get('balance')}"))
|
|
221
|
+
client.on_trade_transaction(lambda d: print(f"Transaction: type={d.get('update_type')}"))
|
|
222
|
+
client.on_trade_result(lambda d: print(f"Trade result: {d.get('result', {})}"))
|
|
223
|
+
|
|
224
|
+
# Place a market buy
|
|
225
|
+
result = await client.buy_market("EURUSD", 0.01, sl=1.0800, tp=1.1200)
|
|
226
|
+
print(f"Trade: {result}")
|
|
227
|
+
|
|
228
|
+
await asyncio.sleep(10)
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
asyncio.run(main())
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## Trading Examples
|
|
235
|
+
|
|
236
|
+
```python
|
|
237
|
+
from pymt5 import (
|
|
238
|
+
MT5WebClient, ORDER_TYPE_BUY, ORDER_TYPE_SELL,
|
|
239
|
+
TRADE_RETCODE_DONE, ORDER_FILLING_IOC,
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
# Market orders
|
|
243
|
+
result = await client.buy_market("XAUUSD", 0.1, sl=2300.0, tp=2400.0)
|
|
244
|
+
result = await client.sell_market("EURUSD", 0.05, deviation=30)
|
|
245
|
+
|
|
246
|
+
# Pending orders
|
|
247
|
+
result = await client.buy_limit("EURUSD", 0.1, price=1.0800, sl=1.0750, tp=1.0900)
|
|
248
|
+
result = await client.sell_stop("GBPUSD", 0.1, price=1.2500)
|
|
249
|
+
|
|
250
|
+
# Stop-limit orders (trigger at price, then place limit at stop_limit_price)
|
|
251
|
+
result = await client.buy_stop_limit("EURUSD", 0.1, price=1.1000,
|
|
252
|
+
stop_limit_price=1.0950, sl=1.0900, tp=1.1100)
|
|
253
|
+
result = await client.sell_stop_limit("GBPUSD", 0.1, price=1.2400,
|
|
254
|
+
stop_limit_price=1.2450)
|
|
255
|
+
|
|
256
|
+
# Close position (auto-detects BUY/SELL direction)
|
|
257
|
+
result = await client.close_position("EURUSD", position_id=123456, volume=0.1)
|
|
258
|
+
|
|
259
|
+
# Close by opposite position (hedge netting)
|
|
260
|
+
result = await client.close_position_by("EURUSD", position_id=123456,
|
|
261
|
+
position_by=789012)
|
|
262
|
+
|
|
263
|
+
# Modify SL/TP
|
|
264
|
+
result = await client.modify_position_sltp("EURUSD", position_id=123456,
|
|
265
|
+
sl=1.0850, tp=1.0950)
|
|
266
|
+
|
|
267
|
+
# Cancel pending order
|
|
268
|
+
result = await client.cancel_pending_order(order=789012)
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
## Push Notifications
|
|
272
|
+
|
|
273
|
+
```python
|
|
274
|
+
# Combined position+order updates in one callback
|
|
275
|
+
def on_trade_change(data):
|
|
276
|
+
print(f"Positions: {len(data['positions'])}, Orders: {len(data['orders'])}")
|
|
277
|
+
client.on_trade_update(on_trade_change)
|
|
278
|
+
|
|
279
|
+
# Trade transaction (order add/update/delete, balance updates)
|
|
280
|
+
def on_transaction(data):
|
|
281
|
+
if data.get('update_type') == 2:
|
|
282
|
+
print(f"Balance update: {data['balance_info']}")
|
|
283
|
+
else:
|
|
284
|
+
print(f"Order transaction: type={data.get('transaction_type')}")
|
|
285
|
+
client.on_trade_transaction(on_transaction)
|
|
286
|
+
|
|
287
|
+
# Account balance/equity changes
|
|
288
|
+
client.on_account_update(lambda d: print(f"Balance: {d.get('balance')}"))
|
|
289
|
+
|
|
290
|
+
# Extended symbol data with options greeks
|
|
291
|
+
client.on_symbol_details(lambda d: print(f"Delta: {d[0].get('delta')}"))
|
|
292
|
+
|
|
293
|
+
# Async trade execution results
|
|
294
|
+
client.on_trade_result(lambda d: print(f"Retcode: {d.get('result', {}).get('retcode')}"))
|
|
295
|
+
|
|
296
|
+
# Order book (DOM) updates
|
|
297
|
+
client.on_book_update(lambda entries: print(f"Book: {len(entries)} symbols"))
|
|
298
|
+
|
|
299
|
+
# Login status changes (e.g. forced logout)
|
|
300
|
+
client.on_login_status(lambda r: print(f"Login status: code={r.code}"))
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
## Protocol Flow
|
|
304
|
+
|
|
305
|
+
1. `connect()` — opens WebSocket, sends bootstrap (cmd=0), receives new AES key
|
|
306
|
+
2. `login()` — sends credentials (cmd=28), receives session token, starts heartbeat
|
|
307
|
+
3. Data commands (get_account, get_symbols, get_rates, get_positions_and_orders, etc.)
|
|
308
|
+
4. `close()` — stops heartbeat, sends logout (cmd=2), closes WebSocket
|
|
309
|
+
|
|
310
|
+
**Important**: Do NOT call `init_session()` (cmd=29) after login — that command is for demo/real account creation, not session initialization.
|
|
311
|
+
|
|
312
|
+
## Logging
|
|
313
|
+
|
|
314
|
+
```python
|
|
315
|
+
import logging
|
|
316
|
+
logging.basicConfig(level=logging.DEBUG)
|
|
317
|
+
# Loggers: pymt5.client, pymt5.transport
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
## Examples
|
|
321
|
+
|
|
322
|
+
Run any example from the project root:
|
|
323
|
+
|
|
324
|
+
```bash
|
|
325
|
+
pip install -e .
|
|
326
|
+
python examples/01_connect_and_account.py
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
| Example | Description |
|
|
330
|
+
|---------|-------------|
|
|
331
|
+
| `01_connect_and_account.py` | Login, full account info (cmd=3), positions/orders/deals, ping |
|
|
332
|
+
| `02_market_data.py` | Symbol groups (cmd=9), symbol cache, spreads (cmd=20), OHLCV rates |
|
|
333
|
+
| `03_realtime_ticks.py` | Tick subscription, account/symbol details/login status push handlers |
|
|
334
|
+
| `04_trading.py` | Market/limit/stop orders, modify SL/TP, position close |
|
|
335
|
+
| `05_order_book.py` | Order book (DOM) subscription (cmd=22/23) |
|
|
336
|
+
| `06_all_push_notifications.py` | All 9 push notification types in one example |
|
|
337
|
+
| `07_all_order_types.py` | All 9 order types + modify + cancel + close + raw trade_request |
|
|
338
|
+
| `08_misc_features.py` | Corporate links, notifications, trader params, verify code, reconnect |
|
|
339
|
+
|
|
340
|
+
## Command Coverage
|
|
341
|
+
|
|
342
|
+
| CMD | Name | Status |
|
|
343
|
+
|-----|------|--------|
|
|
344
|
+
| 0 | Bootstrap | Implemented |
|
|
345
|
+
| 2 | Logout | Implemented |
|
|
346
|
+
| 3 | Get Account | **NEW** — balance, credit, currency, leverage, name |
|
|
347
|
+
| 4 | Get Positions/Orders | Implemented |
|
|
348
|
+
| 5 | Get Trade History | Implemented |
|
|
349
|
+
| 6 | Get Symbols | Implemented |
|
|
350
|
+
| 7 | Subscribe Ticks | Implemented |
|
|
351
|
+
| 8 | Tick Push | Implemented |
|
|
352
|
+
| 9 | Get Symbol Groups | **NEW** — Forex, Metals, Indexes, etc. |
|
|
353
|
+
| 10 | Trade Update Push | **NEW** — order add/update/delete + balance updates |
|
|
354
|
+
| 11 | Get Rates | Implemented |
|
|
355
|
+
| 12 | Trade Request | Implemented |
|
|
356
|
+
| 13 | Symbol Update Push | Implemented |
|
|
357
|
+
| 14 | Account Update Push | **NEW** — real-time balance/equity changes |
|
|
358
|
+
| 15 | Login Status Push | Implemented |
|
|
359
|
+
| 17 | Symbol Details Push | **NEW** — extended quotes with options greeks |
|
|
360
|
+
| 18 | Get Full Symbols | Implemented |
|
|
361
|
+
| 19 | Trade Result Push | **NEW** — async trade execution results |
|
|
362
|
+
| 20 | Get Spreads | **IMPROVED** — proper schema parsing |
|
|
363
|
+
| 22 | Subscribe Book | **NEW** — order book / DOM subscription |
|
|
364
|
+
| 23 | Book Push | **NEW** — order book push with bid/ask levels |
|
|
365
|
+
| 24 | Change Password | Implemented |
|
|
366
|
+
| 27 | Verify Code | Implemented |
|
|
367
|
+
| 28 | Login | Implemented |
|
|
368
|
+
| 29 | Init Session | Implemented |
|
|
369
|
+
| 30 | Open Demo | Implemented |
|
|
370
|
+
| 39 | Open Real Account | Implemented |
|
|
371
|
+
| 40 | Send Verification Codes | Implemented |
|
|
372
|
+
| 34 | Get Symbols (gzip) | Implemented |
|
|
373
|
+
| 41 | Trader Params | Implemented |
|
|
374
|
+
| 42 | Notify | Implemented |
|
|
375
|
+
| 43 | OTP Setup / Disable | Implemented |
|
|
376
|
+
| 44 | Get Corporate Links | **NEW** — broker links |
|
|
377
|
+
| 51 | Ping | Implemented |
|
|
378
|
+
| 52 | Reserved Bootstrap Command | **EXPERIMENTAL** — bootstrap-only helper with unknown business meaning |
|
|
379
|
+
|
|
380
|
+
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`.
|
|
381
|
+
|
|
382
|
+
## Documentation
|
|
383
|
+
|
|
384
|
+
Full API documentation is available at **[pymt5.readthedocs.io/en/latest](https://pymt5.readthedocs.io/en/latest/)**.
|
|
385
|
+
|
|
386
|
+
To build docs locally:
|
|
387
|
+
|
|
388
|
+
```bash
|
|
389
|
+
pip install -e ".[docs]"
|
|
390
|
+
cd docs && make html
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
## CI/CD
|
|
394
|
+
|
|
395
|
+
This project uses GitHub Actions for continuous integration, testing across:
|
|
396
|
+
|
|
397
|
+
| | Python 3.11 | Python 3.12 | Python 3.13 |
|
|
398
|
+
|---|---|---|---|
|
|
399
|
+
| **Linux** (ubuntu-latest) | ✅ | ✅ | ✅ |
|
|
400
|
+
| **macOS** (macos-latest) | ✅ | ✅ | ✅ |
|
|
401
|
+
| **Windows** (windows-latest) | ✅ | ✅ | ✅ |
|
|
402
|
+
|
|
403
|
+
The CI pipeline also runs mypy type checking and builds the Sphinx documentation.
|
|
404
|
+
For a local pre-push pass, run:
|
|
405
|
+
|
|
406
|
+
```bash
|
|
407
|
+
make check
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
## Notes
|
|
411
|
+
|
|
412
|
+
- 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)
|
|
413
|
+
- MetaQuotes may change the protocol at any time
|
|
414
|
+
- 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
|
|
415
|
+
- `get_account()` (cmd=3) returns balance, credit, currency, leverage, and name. Equity, margin, and profit are computed from positions
|
|
416
|
+
- The Symbol Details push (cmd=17) schema may produce approximate values — the exact byte layout for options greeks varies by server
|
|
417
|
+
- Order book (cmd=22/23) may not produce pushes on all servers — depends on broker configuration
|
|
418
|
+
- Some commands like `trader_params` (cmd=41) may cause the server to close the connection on rapid successive calls
|
|
419
|
+
|
|
420
|
+
## License
|
|
421
|
+
|
|
422
|
+
MIT License — see [LICENSE](LICENSE) for details.
|