feat: Linux (Arch+Wine) MT5 support with zero-step auto-connect
Make the bot connect to MetaTrader5 on Linux without manual setup or launching extra programs. - Add mt5linux rpyc bridge: MT5 terminal + Windows Python run under Wine, Linux client talks to it over a socket - scripts/mt5_bridge.sh: robust, idempotent launcher (up/down/status/restart/ login-gui/install-service) with .env loading, port health-checks and a systemd --user unit for auto-start on login - src/mt5_connector.py: auto-detect bridge backend (lazy, non-blocking import); auto-start the bridge via mt5_bridge.sh when the port is down so the bot self-connects; attach-mode initialize() first, then explicit login - Use configured SYMBOL instead of hardcoded XAUUSD in connector + news_agent (XM names spot gold 'GOLD') - scripts/test_mt5_bridge.py: connectivity smoke test - docs/MT5-ARCH-LINUX-SETUP.md: full setup, root-cause notes, troubleshooting Verified live: account 345454551 @ XMGlobal-MT5 10, balance read, GOLD M15 data + ticks streaming, trade_allowed=True.
This commit is contained in:
@@ -0,0 +1,151 @@
|
||||
# MT5 on Arch Linux (Wine + mt5linux bridge)
|
||||
|
||||
The `MetaTrader5` Python package is Windows-only. On Arch Linux we run the MT5
|
||||
terminal under **Wine** plus a **Windows Python** that exposes the MT5 API over
|
||||
an `rpyc` socket (`mt5linux`). The Linux-side bot connects to that socket.
|
||||
|
||||
```
|
||||
Linux Python (bot) --rpyc--> Wine Python (mt5linux server) --> MT5 terminal --> broker
|
||||
mt5linux client MetaTrader5 pkg terminal64.exe
|
||||
```
|
||||
|
||||
## One-time setup (already done on this machine)
|
||||
|
||||
- Wine: `wine-11.10 (Staging)` ✅
|
||||
- Headless display: `Xvfb` (pkg `xorg-server-xvfb`) ✅
|
||||
- MT5 terminal installed in Wine: `~/.wine/drive_c/Program Files/MetaTrader 5/terminal64.exe` ✅
|
||||
- Windows Python 3.9 in Wine: `~/.wine/drive_c/users/$USER/AppData/Local/Programs/Python/Python39/python.exe` ✅
|
||||
- Wine Python packages: `MetaTrader5`, `mt5linux`, `rpyc` ✅
|
||||
- Linux Python packages: `mt5linux`, `rpyc` ✅
|
||||
|
||||
To reproduce the Wine Python install:
|
||||
|
||||
```bash
|
||||
curl -sL -o /tmp/py39.exe https://www.python.org/ftp/python/3.9.13/python-3.9.13-amd64.exe
|
||||
DISPLAY=:1 WINEDEBUG=-all wine /tmp/py39.exe /quiet InstallAllUsers=0 PrependPath=1 Include_pip=1
|
||||
WINPY="$HOME/.wine/drive_c/users/$USER/AppData/Local/Programs/Python/Python39/python.exe"
|
||||
wine "$WINPY" -m pip install MetaTrader5 mt5linux
|
||||
```
|
||||
|
||||
## Configuration (`.env`)
|
||||
|
||||
```env
|
||||
MT5_LOGIN=...
|
||||
MT5_PASSWORD=...
|
||||
MT5_SERVER=... # exact broker server name (see terminal)
|
||||
MT5_BRIDGE_HOST=127.0.0.1
|
||||
MT5_BRIDGE_PORT=18812
|
||||
MT5_WIN_PATH=C:\Program Files\MetaTrader 5\terminal64.exe
|
||||
```
|
||||
|
||||
## Run (robust, one command)
|
||||
|
||||
```bash
|
||||
# Bring the whole bridge up (idempotent): Xvfb + rpyc server + verified login.
|
||||
# The terminal is auto-launched headless and logged in from .env credentials.
|
||||
scripts/mt5_bridge.sh up
|
||||
|
||||
# Other commands
|
||||
scripts/mt5_bridge.sh status # components + live login + trade_allowed
|
||||
scripts/mt5_bridge.sh restart
|
||||
scripts/mt5_bridge.sh down
|
||||
```
|
||||
|
||||
`up` is safe to re-run: it only starts what is missing and health-checks the
|
||||
rpyc port (no blind sleeps). Credentials and port are read from `.env`
|
||||
(`MT5_LOGIN/PASSWORD/SERVER`, `MT5_BRIDGE_PORT`, `MT5_WIN_PATH`).
|
||||
|
||||
### Auto-start on login (systemd --user)
|
||||
|
||||
```bash
|
||||
scripts/mt5_bridge.sh install-service
|
||||
systemctl --user enable --now mt5-bridge.service
|
||||
journalctl --user -u mt5-bridge -f # logs
|
||||
```
|
||||
|
||||
After this the bridge comes up automatically; you never repeat the manual
|
||||
steps. Then just run the bot:
|
||||
|
||||
```bash
|
||||
python main_live.py
|
||||
```
|
||||
|
||||
### First-time only
|
||||
|
||||
The account must be logged into the terminal once so the profile knows it.
|
||||
Normally `up` does this automatically via explicit login. If you ever get
|
||||
`LOGIN_FAIL (-6)`, do a one-time GUI login:
|
||||
|
||||
```bash
|
||||
scripts/mt5_bridge.sh login-gui # File -> Login to Trade Account
|
||||
```
|
||||
|
||||
The bot (`src/mt5_connector.py`) auto-detects the bridge: if the native
|
||||
`MetaTrader5` import fails but `mt5linux` is present, it connects lazily to
|
||||
`MT5_BRIDGE_HOST:MT5_BRIDGE_PORT` on the first `connect()` call, trying
|
||||
`initialize()` attach-mode first then explicit login.
|
||||
|
||||
### Zero-step auto-connect
|
||||
|
||||
You do **not** need to start anything by hand. When the bot calls `connect()`
|
||||
and the bridge port is closed, it auto-runs `scripts/mt5_bridge.sh up`
|
||||
(Xvfb + rpyc server + login) and waits for it to become ready. So on Linux:
|
||||
|
||||
```bash
|
||||
python main_live.py # bridge is started automatically if needed
|
||||
```
|
||||
|
||||
Disable autostart (e.g. when using the systemd service) with:
|
||||
|
||||
```bash
|
||||
export MT5_BRIDGE_AUTOSTART=0
|
||||
```
|
||||
|
||||
### Broker symbol note
|
||||
|
||||
XM Global names spot gold **`GOLD`** (not `XAUUSD`). `.env` sets `SYMBOL=GOLD`.
|
||||
The connector pre-selects whatever `SYMBOL` is configured.
|
||||
|
||||
## Root cause of the `-6 Authorization failed` we hit
|
||||
|
||||
Per the official mt5linux docs, the intended flow is:
|
||||
**(1) open MT5 and log in via the GUI → (2) start the server → (3) call
|
||||
`initialize()` with no credentials to attach to the running terminal.**
|
||||
|
||||
Our first attempt launched the terminal with `/portable` and passed
|
||||
`login/password/server` to `initialize()`. A fresh portable profile has **no
|
||||
saved account**, so the broker rejected the fresh login attempt with
|
||||
`(-6, 'Authorization failed')`. Confirmed: no `accounts.dat`/`servers.dat`
|
||||
account was present in the Wine prefix.
|
||||
|
||||
Fixes applied:
|
||||
- launcher no longer uses `/portable` (uses the persistent profile)
|
||||
- added `scripts/mt5_bridge.sh login_gui` for the one-time GUI login
|
||||
- the connector + test now try `initialize()` attach-mode first
|
||||
|
||||
> So the credentials were almost certainly fine — the terminal simply had never
|
||||
> logged into the account. Do the one-time `login_gui` step, then the bridge
|
||||
> attaches cleanly.
|
||||
|
||||
## QA status (verified)
|
||||
|
||||
- rpyc server starts and listens on `127.0.0.1:18812` ✅
|
||||
- Linux client connects through to the broker ✅
|
||||
- `mt5.initialize(...)` reaches the broker server ✅
|
||||
- `src/mt5_connector.py` imports without blocking; backend detected as `bridge` ✅
|
||||
|
||||
> NOTE: With the supplied XM credentials the broker returned
|
||||
> `(-6, 'Authorization failed')`. The transport works end-to-end — this is a
|
||||
> credential/server-name issue, not an infrastructure problem. Confirm in the
|
||||
> MT5 terminal:
|
||||
> - exact **server name** (XM has several, e.g. `XMGlobal-MT5`, `XMGlobal-MT5 2` … `10`)
|
||||
> - **login number** and **password** (investor vs master password)
|
||||
> - account is active and AlgoTrading is enabled
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- `Authorization failed (-6)` → wrong server name / login / password, or
|
||||
expired account. Log into the terminal GUI once to confirm the exact server.
|
||||
- Client `result expired` / timeout → the Wine MT5 terminal hung; run
|
||||
`scripts/mt5_bridge.sh restart`.
|
||||
- Port already in use → another server instance is running; `mt5_bridge.sh stop`.
|
||||
Reference in New Issue
Block a user