DOCUMENTATION.md: Two-section guide covering the full project — plain-English trader guide (indicators, scoring, trade setups) and developer reference (architecture, data flow, every threshold/weight). mt5.md: Architecture plan for automated order execution via MT5 bridge (REST API on Windows, async client on Linux, risk-based lot sizing). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
7.5 KiB
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
MetaTrader5Python 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-Keyheader - 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)
MT5ExecutionClientclass withaiohttpexecute_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_idfor idempotency - Position sync: periodically calls
/api/positionsto stay in sync with MT5 - Graceful degradation: if bridge offline, logs warning, bot continues signal-only
Modified Files
4. config.py — Add MT5Config dataclass
@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, callmt5_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
- Demo account first —
MT5_SERVER=TIOMarkets-Demo enabled: Falsedefault — must explicitly opt-in viaMT5_ENABLED=true- Duplicate prevention — 3 layers: client-side tracking, bridge-side position check, idempotent
order_id - Circuit breaker —
max_daily_tradesstops execution if too many orders fire - Position limit —
max_open_positionscaps concurrent exposure - Risk-based sizing — lot size from
risk_pctof account balance, calculated on bridge with live tick values - 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):
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):
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
config.py— AddMT5Configmt5_bridge/mt5_bridge.py+requirements.txt— Windows bridge servermt5_client.py— Linux HTTP clienttelegram_bot.py— Wire execution + new commandsrequirements.txt— Addaiohttp
Verification
- Start bridge on Windows:
python mt5_bridge.py-> verifycurl /api/healthreturns MT5 connected - Test order via curl:
POST /api/orderwith demo credentials -> verify order appears in MT5 - Start bot on Linux with
MT5_ENABLED=true-> verify/mt5statuscommand works - Wait for actionable signal (or manually trigger scan) -> verify order placed + Telegram confirmation
- Verify duplicate prevention: same signal shouldn't place second order
- Kill bridge -> verify bot continues in signal-only mode without crashing
Windows Bridge Setup (one-time)
# 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)
MT5_ENABLED=true
MT5_BRIDGE_URL=http://<windows-ip>: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