# MT5 Auto-Execution Integration Plan ## Context ForexBot2 generates trade signals with full setups (entry, SL, TP) but currently only displays them in Telegram. The user wants fully automatic order execution via MetaTrader 5. **Constraint:** MT5 runs on a separate Windows machine. The Python `MetaTrader5` package requires Windows (COM interface). The bot runs on Linux. A network bridge is needed. **Broker:** TIO Markets (demo first, live later via config change). **Execution mode:** Fully automatic for actionable signals (A+/A/B grades). ## Architecture: REST API Bridge ``` Linux (telegram_bot.py) Windows (mt5_bridge.py) ======================== ======================== Signal fires with TradeSetup FastAPI server running -> mt5_client.execute_trade() -> Wraps MetaTrader5 package POST /api/order ─────── HTTP ───────> -> mt5.order_send() <- {ticket: 12345} <──── HTTP ────── <- Returns ticket or error -> Telegram: "ORDER PLACED" -> Idempotency via order_id ``` **Why REST over WebSocket/file-sync:** Stateless, debuggable, retry-safe. For a bot placing 1-5 trades/day, HTTP latency (5-50ms LAN) is negligible. ## Files to Create/Modify ### New Files **1. `mt5_bridge/mt5_bridge.py`** — Windows-side FastAPI server (~200 lines) - Wraps `MetaTrader5` Python package - Endpoints: `/api/health`, `/api/account`, `/api/positions`, `/api/order` (POST), `/api/order/close` (POST) - Lot size calculation on bridge side (has access to `mt5.symbol_info()` for tick value, contract size, volume step) - Idempotency: stores `{order_id: ticket}` to prevent duplicate orders on retry - API key auth via `X-API-Key` header - MT5 credentials from env vars: `MT5_LOGIN`, `MT5_PASSWORD`, `MT5_SERVER`, `MT5_PATH` **2. `mt5_bridge/requirements.txt`** — Windows dependencies - `fastapi`, `uvicorn`, `MetaTrader5`, `pydantic` **3. `mt5_client.py`** — Linux-side async HTTP client (~150 lines) - `MT5ExecutionClient` class with `aiohttp` - `execute_trade(setup: TradeSetup, quality: str)` — sends order to bridge - Symbol mapping: `EURUSD=X` -> `EURUSD` (TIO Markets format, configurable) - Duplicate prevention: tracks open positions per symbol - Retry: 3 attempts, exponential backoff, same `order_id` for idempotency - Position sync: periodically calls `/api/positions` to stay in sync with MT5 - Graceful degradation: if bridge offline, logs warning, bot continues signal-only ### Modified Files **4. `config.py`** — Add `MT5Config` dataclass ```python @dataclass class MT5Config: enabled: bool = False bridge_url: str = "http://192.168.1.100:8080" bridge_api_key: str = "" risk_pct: float = 1.0 # % of balance risked per trade max_open_positions: int = 3 max_daily_trades: int = 10 # Circuit breaker magic_number: int = 234000 # Identifies ForexBot2 orders slippage_points: int = 20 # 2 pips for 5-digit brokers auto_execute_grades: List[str] # ["A+", "A", "B"] symbol_map: Dict[str, str] # Internal -> broker symbol ``` All overridable via env vars (`MT5_BRIDGE_URL`, `MT5_RISK_PCT`, etc.) **5. `telegram_bot.py`** — Wire execution into signal flow - In `_scan_timeframe()`: after sending Telegram messages, call `mt5_client.execute_trade()` for actionable signals - In `_handle_breach()`: same pattern after breach scan produces actionable signal - Add background task `_mt5_position_sync_loop()` for periodic position sync - Add Telegram commands: `/mt5status` (bridge health + account info), `/positions` (open trades) - Register new commands in `set_my_commands()` - Execution result messages sent to Telegram (ticket # on success, error on failure) **6. `requirements.txt`** — Add `aiohttp>=3.9` (async HTTP for Linux-side client) ## Safety Layers 1. **Demo account first** — `MT5_SERVER=TIOMarkets-Demo` 2. **`enabled: False` default** — must explicitly opt-in via `MT5_ENABLED=true` 3. **Duplicate prevention** — 3 layers: client-side tracking, bridge-side position check, idempotent `order_id` 4. **Circuit breaker** — `max_daily_trades` stops execution if too many orders fire 5. **Position limit** — `max_open_positions` caps concurrent exposure 6. **Risk-based sizing** — lot size from `risk_pct` of account balance, calculated on bridge with live tick values 7. **Graceful degradation** — bridge offline = signal-only mode, no crash ## Position Sizing (calculated on Windows bridge) ``` risk_amount = balance * (risk_pct / 100) tick_value = mt5.symbol_info(symbol).trade_tick_value tick_size = mt5.symbol_info(symbol).trade_tick_size sl_ticks = abs(entry - stop_loss) / tick_size lot_size = risk_amount / (sl_ticks * tick_value) lot_size = round_down(lot_size, volume_step) lot_size = clamp(lot_size, volume_min, volume_max) ``` Bridge side is best because it has real-time `tick_value` (varies with exchange rates for cross pairs). ## Symbol Mapping (TIO Markets) | Internal | MT5 Symbol | |----------|-----------| | `EURUSD=X` | `EURUSD` | | `USDJPY=X` | `USDJPY` | | `GBPUSD=X` | `GBPUSD` | | `XAU/USD` | `XAUUSD` | Configurable via `MT5_SYMBOL_MAP` env var (JSON) for broker variations. ## Integration Points ### In `_scan_timeframe()` (after line ~406): ```python mt5 = _get_mt5_client() if mt5: for report in actionable: if report.trade_setup and report.signal_quality in mt5.config.auto_execute_grades: result = await mt5.execute_trade(report.trade_setup, report.signal_quality) # Send execution confirmation/error to Telegram ``` ### In `_handle_breach()` (after line ~477): ```python if report.trade_setup and report.signal_quality in mt5.config.auto_execute_grades: mt5 = _get_mt5_client() if mt5: result = await mt5.execute_trade(report.trade_setup, report.signal_quality) # Send execution confirmation/error to Telegram ``` ## New Telegram Commands | Command | Description | |---------|-------------| | `/mt5status` | Bridge health, account balance/equity, open positions count | | `/positions` | List all open MT5 positions with P/L | ## Implementation Order 1. `config.py` — Add `MT5Config` 2. `mt5_bridge/mt5_bridge.py` + `requirements.txt` — Windows bridge server 3. `mt5_client.py` — Linux HTTP client 4. `telegram_bot.py` — Wire execution + new commands 5. `requirements.txt` — Add `aiohttp` ## Verification 1. Start bridge on Windows: `python mt5_bridge.py` -> verify `curl /api/health` returns MT5 connected 2. Test order via curl: `POST /api/order` with demo credentials -> verify order appears in MT5 3. Start bot on Linux with `MT5_ENABLED=true` -> verify `/mt5status` command works 4. Wait for actionable signal (or manually trigger scan) -> verify order placed + Telegram confirmation 5. Verify duplicate prevention: same signal shouldn't place second order 6. Kill bridge -> verify bot continues in signal-only mode without crashing ## Windows Bridge Setup (one-time) ```bash # On Windows machine: pip install fastapi uvicorn MetaTrader5 pydantic # Set environment variables: set MT5_LOGIN=12345678 set MT5_PASSWORD=your-password set MT5_SERVER=TIOMarkets-Demo set MT5_PATH=C:\Program Files\MetaTrader 5\terminal64.exe set BRIDGE_API_KEY=your-random-32-char-key set BRIDGE_PORT=8080 # Run: python mt5_bridge.py ``` ## Linux Bot Config (env vars) ```bash MT5_ENABLED=true MT5_BRIDGE_URL=http://:8080 MT5_BRIDGE_API_KEY=your-random-32-char-key MT5_RISK_PCT=1.0 MT5_MAX_OPEN_POSITIONS=3 MT5_AUTO_EXECUTE_GRADES=A+,A,B ```