MetaTrader 5 trading via REST API — get market data, place/modify/close orders, manage positions, pull history. Use when you need to interact with forex/crypto/stock markets through MT5.
REST API on top of MetaTrader 5 running inside a Windows VM. Talk to it with plain HTTP/JSON — no MT5 libraries, no Windows, no bullshit. Just curl and go.
For installation and setup, see references/setup.md.
The API should already be running. Set the base URL:
export MT5_API_URL=http://localhost:6542
Each terminal has its own port (configured in terminals.json). If running multiple terminals, set MT5_API_URL to the port for the terminal you want to talk to.
Verify: curl $MT5_API_URL/ping — should return {"status": "ok"}. If not, the API isn't up yet (may still be initializing — it retries in the background).
GET for reading, POST for creating, PUT for modifying, DELETE for closing/canceling. All bodies are JSON.
Every error response:
{"error": "description of what went wrong"}
Before placing any trade:
GET /account → trade_allowed must be trueGET /symbols/SYMBOL → trade_mode must be 4 (full trading)GET /symbols/SYMBOL → check trade_contract_size — 1 lot of EURUSD = 100,000 EUR, not 1 EURGET /terminal → connected must be truecurl $MT5_API_URL/ping
# {"status": "ok"}
curl $MT5_API_URL/error
# {"code": 1, "message": "Success"}
curl $MT5_API_URL/terminal
curl -X POST $MT5_API_URL/terminal/init
curl -X POST $MT5_API_URL/terminal/shutdown
Key fields on /terminal: connected, trade_allowed, build, company.
curl $MT5_API_URL/account
{
"login": 12345678,
"balance": 10000.0,
"equity": 10000.0,
"margin": 0.0,
"margin_free": 10000.0,
"margin_level": 0.0,
"leverage": 500,
"currency": "USD",
"trade_allowed": true,
"margin_so_call": 70.0,
"margin_so_so": 20.0
}
curl $MT5_API_URL/symbols
curl "$MT5_API_URL/symbols?group=*USD*"
curl $MT5_API_URL/symbols/EURUSD
curl $MT5_API_URL/symbols/EURUSD/tick
curl "$MT5_API_URL/symbols/EURUSD/rates?timeframe=H4&count=100"
curl "$MT5_API_URL/symbols/EURUSD/ticks?count=100"
Timeframes: M1 M2 M3 M4 M5 M6 M10 M12 M15 M20 M30 H1 H2 H3 H4 H6 H8 H12 D1 W1 MN1
Key symbol fields: bid, ask, digits, point, trade_contract_size, trade_tick_value, trade_tick_size, volume_min, volume_max, volume_step, spread, swap_long, swap_short, trade_stops_level, trade_mode.
# Place market order
curl -X POST $MT5_API_URL/orders \
-H 'Content-Type: application/json' \
-d '{"symbol": "EURUSD", "type": "BUY", "volume": 0.1, "sl": 1.08, "tp": 1.10}'
# List pending orders
curl $MT5_API_URL/orders
curl "$MT5_API_URL/orders?symbol=EURUSD"
curl $MT5_API_URL/orders/42094812
# Modify pending order
curl -X PUT $MT5_API_URL/orders/42094812 \
-H 'Content-Type: application/json' \
-d '{"price": 1.09, "sl": 1.07, "tp": 1.11}'
# Cancel pending order
curl -X DELETE $MT5_API_URL/orders/42094812
Order types: BUY, SELL, BUY_LIMIT, SELL_LIMIT, BUY_STOP, SELL_STOP, BUY_STOP_LIMIT, SELL_STOP_LIMIT
Fill policies: FOK, IOC (default), RETURN
Expiration: GTC (default), DAY, SPECIFIED, SPECIFIED_DAY
Required fields: symbol, type, volume. price auto-fills for market orders.
Trade result:
{
"retcode": 10009,
"deal": 40536203,
"order": 42094820,
"volume": 0.1,
"price": 1.0950,
"comment": "Request executed"
}
retcode 10009 = success. Anything else = something went wrong.
curl $MT5_API_URL/positions
curl "$MT5_API_URL/positions?symbol=EURUSD"
curl $MT5_API_URL/positions/42094820
# Update SL/TP
curl -X PUT $MT5_API_URL/positions/42094820 \
-H 'Content-Type: application/json' \
-d '{"sl": 1.085, "tp": 1.105}'
# Close full position
curl -X DELETE $MT5_API_URL/positions/42094820
# Partial close
curl -X DELETE $MT5_API_URL/positions/42094820 \
-H 'Content-Type: application/json' \
-d '{"volume": 0.05}'
Key position fields: ticket, type (0=buy, 1=sell), volume, price_open, price_current, sl, tp, profit, swap.
curl "$MT5_API_URL/history/orders?from=$(date -d '1 day ago' +%s)&to=$(date +%s)"
curl "$MT5_API_URL/history/deals?from=$(date -d '1 day ago' +%s)&to=$(date +%s)"
from and to are required, unix epoch seconds.
Deal fields: type (0=buy, 1=sell), entry (0=opening, 1=closing), profit (0 for entries, realized P&L for exits).
risk_amount = balance * risk_pct
sl_distance = ATR * multiplier
ticks_in_sl = sl_distance / trade_tick_size
risk_per_lot = ticks_in_sl * trade_tick_value
volume = risk_amount / risk_per_lot
Round down to nearest volume_step, clamp to [volume_min, volume_max]. Sanity check: volume * trade_contract_size * price should make sense relative to account balance.
retcode — 10009 = good, anything else = badGET /error to debug failed tradesdeviation on orders = max slippage in points (default 20, raise for volatile markets)type_filling matters — try FOK, IOC, RETURN if orders get rejectedtime is the open time, not close timetrade_stops_level = minimum SL/TP distance from current price in pointstrade_mode before placing ordersSearch for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer