Skip to content

Repository files navigation

API2Trade Python SDK

Official Python SDK for the API2Trade Metatrader API.
A robust API for Metatrader that lets you control your trading accounts programmatically.
Build integrations, trading bots, and dashboards using this high-performance MT4 API and MT5 API — no MetaTrader terminal required.

PyPI versionPythonLicenseAPI StatusDocs


Features

FeatureDetail
Full API coverageAll 11 REST endpoints + WebSocket streaming
Typed modelsDataclass responses — no raw dict parsing
Auto-retryExponential back-off on requotes, timeouts, server busy
WebSocket streamingCallback and async-generator styles with auto-reconnect
Both auth modesAPI key (Single plan) + HTTP Basic Auth (Pro plans)
Exception hierarchySpecific exceptions for auth, 404, rate limit, broker rejection
P&L statisticsBuilt-in summary_stats() — win rate, profit factor, etc.
Paginated historyiter_all() generator — handles any account size
Context managerwith Api2TradeClient(...) as client: — auto-closes session
Env-var configAPI2TRADE_API_KEY and friends — 12-factor ready
Python 3.8 – 3.12Fully tested

Installation

# Core SDK (REST only)
pip install api2trade-sdk
# Core + WebSocket streaming
pip install "api2trade-sdk[streaming]"# Development (tests, streaming, dotenv)
pip install "api2trade-sdk[dev]"

No MetaTrader installation required. The SDK communicates directly with the API2Trade cloud bridge over standard HTTPS and WSS.


60-Second Quickstart

fromapi2trade_sdkimportApi2TradeClient, OrderTypeclient=Api2TradeClient(api_key="YOUR_API_KEY")
# 1. Register your MT4/MT5 accountaccount_id=client.accounts.register(
login="123456",
password="BrokerPass",
server="ICMarkets-Live01",
)
print(f"Account UUID: {account_id}") # save this!# 2. Check live balancesummary=client.accounts.summary(account_id)
print(f"Balance: {summary.balance}{summary.currency}")
print(f"Equity: {summary.equity}{summary.currency}")
# 3. Get a live quotequote=client.market.quote(account_id, "EURUSD")
print(quote) # Quote(EURUSD: bid=1.08500, ask=1.08510, spread=1.0 pips)# 4. Place a traderesult=client.orders.send(
account_id,
symbol="EURUSD",
order_type=OrderType.BUY_MARKET,
volume=0.01,
stop_loss=round(quote.ask-0.0020, 5),
take_profit=round(quote.ask+0.0040, 5),
)
print(f"Ticket: {result.ticket}") # ✅ OrderResult# 5. Close itclient.orders.close(account_id, ticket=result.ticket)

Authentication

Single Account Plan (€12/mo)

client=Api2TradeClient(api_key="YOUR_API_KEY")
# or via environment variable:# export API2TRADE_API_KEY=your_keyclient=Api2TradeClient()

Pro Plans (Basic Auth + dedicated URL)

client=Api2TradeClient(
pro_username="your_username",
pro_password="your_password",
base_url="https://your-dedicated-url.api2trade.com",
)

Find your API key at app.metatraderapi.dev → Settings.


Configuration via Environment Variables

# .env
API2TRADE_API_KEY=sk-...
API2TRADE_ACCOUNT_ID=a1b2c3d4-...
API2TRADE_BASE_URL=https://api.metatraderapi.dev # optional
API2TRADE_WS_URL=wss://api.metatraderapi.dev/stream # optional
fromdotenvimportload_dotenvload_dotenv()
client=Api2TradeClient() # reads API2TRADE_API_KEY automatically

API Reference

client.accounts

# Register MT4/MT5 account → returns UUID stringaccount_id=client.accounts.register(login, password, server)
# Check bridge connection statusstatus: ConnectStatus=client.accounts.check_connect(account_id)
# status.connected → bool# Live balance / equity / margins: AccountSummary=client.accounts.summary(account_id)
s.balance# floats.equity# floats.free_margin# floats.margin_level# float (%)s.currency# strs.is_margin_call_risk# True when margin_level < 150%# Remove account from bridgeclient.accounts.delete(account_id)

client.market

# Single symbol quoteq: Quote=client.market.quote(account_id, "EURUSD")
q.bid# floatq.ask# floatq.spread# float (price units)q.spread_pips# float (pip units)q.mid# float (midpoint)# Multiple symbols at oncequotes: list[Quote] =client.market.quotes(account_id, ["EURUSD", "GBPUSD", "XAUUSD"])

client.orders

fromapi2trade_sdkimportOrderType# Open a market or pending orderresult: OrderResult=client.orders.send(
account_id,
symbol="EURUSD",
order_type=OrderType.BUY_MARKET, # or SELL_MARKET, BUY_LIMIT, SELL_LIMIT, BUY_STOP, SELL_STOPvolume=0.01,
stop_loss=1.0800,
take_profit=1.1000,
comment="my-bot",
auto_retry=True, # retry on requote/timeout (default: True)max_retries=2,
)
result.ticket# int — MetaTrader ticket numberresult.success# bool — True when retcode == 0# Modify SL/TPclient.orders.modify(account_id, ticket=12345678, stop_loss=1.07, take_profit=1.11)
# Close position (partial or full)client.orders.close(account_id, ticket=12345678) # full closeclient.orders.close(account_id, ticket=12345678, volume=0.005) # partial close# Close ALL open positionsclient.orders.close_all(account_id)
# List open positionspositions: list[Position] =client.orders.positions(account_id)
forpinpositions:
print(p.ticket, p.symbol, p.order_type, p.volume, p.total_pnl)

client.history

fromdatetimeimportdatetime, timedelta, timezonenow=datetime.now(tz=timezone.utc)
date_from=now-timedelta(days=30)
# All closed trades in date rangehistory: list[OrderHistoryItem] =client.history.get(account_id, date_from, now)
# Single page (for large accounts)page: PaginatedHistory=client.history.get_page(account_id, date_from, now, page=1, page_size=50)
page.total# intpage.total_pages# intpage.has_next# bool# Iterate all pages as a generator (memory-efficient)fororderinclient.history.iter_all(account_id, date_from, now):
print(order.net_profit)
# Last N days shortcuthistory=client.history.last_n_days(account_id, days=7)
# Built-in statisticsstats=client.history.summary_stats(account_id, date_from, now)
print(stats["win_rate"]) # e.g. 0.6234print(stats["profit_factor"]) # e.g. 2.15print(stats["net_profit"]) # e.g. 934.50

WebSocket Streaming

importasynciofromapi2trade_sdkimportApi2TradeClientclient=Api2TradeClient(api_key="...")
# Style A: callback (runs forever, auto-reconnects)defon_tick(tick):
print(f"{tick.symbol}: {tick.bid:.5f} / {tick.ask:.5f} ({tick.spread_pips:.1f} pips)")
asyncio.run(client.stream(account_id, symbols=["EURUSD", "XAUUSD"], on_tick=on_tick))
# Style B: async generator (fine-grained control)asyncdefmain():
asyncfortickinclient.stream_iter(account_id, ["EURUSD"]):
print(tick)
iftick.ask>1.10:
breakasyncio.run(main())

Error Handling

fromapi2trade_sdk.exceptionsimport (
AuthenticationError, # HTTP 401 — invalid API keyAccountNotFoundError, # HTTP 404 — account not registeredRateLimitError, # HTTP 429 — too many requests (Single plan)BrokerRejectionError, # HTTP 200 but retcode != 0Api2TradeConnectionError, # Network error (timeout, DNS, etc.)Api2TradeError, # Base exception — catch-all
)
try:
result=client.orders.send(account_id, symbol="EURUSD",
order_type=0, volume=0.01)
exceptBrokerRejectionErrorase:
print(f"Broker rejected: retcode={e.retcode} retryable={e.is_retryable}")
# e.g. retcode=10019 → "Insufficient margin"exceptAuthenticationError:
print("Check your API key at app.metatraderapi.dev → Settings")
exceptRateLimitErrorase:
print(f"Rate limited. Retry after {e.retry_after}s")
exceptApi2TradeErrorase:
print(f"API error {e.status_code}: {e}")

OrderType Enum

fromapi2trade_sdkimportOrderTypeOrderType.BUY_MARKET# 0OrderType.SELL_MARKET# 1OrderType.BUY_LIMIT# 2OrderType.SELL_LIMIT# 3OrderType.BUY_STOP# 4OrderType.SELL_STOP# 5OrderType.BUY_MARKET.is_market() # TrueOrderType.BUY_LIMIT.is_pending() # True

RetCode Enum

fromapi2trade_sdkimportRetCodeRetCode.description(10019) # "Insufficient margin"RetCode.is_retryable(10004) # True (requote)RetCode.is_retryable(10019) # False (insufficient funds)

Running the Examples

cd examples/
cp ../.env.example .env
# Edit .env: add API2TRADE_API_KEY and broker credentials
python 01_connect_account.py # Register account → prints UUID
python 02_account_summary.py # Live balance table
python 03_place_trade.py # Open → list → modify → close
python 04_order_history.py # History + P&L stats
python 05_websocket_stream.py # Real-time ticks (requires websockets)
python 06_prop_firm_monitor.py # Drawdown monitor with auto close-out

Running Tests

pip install ".[dev]"
pytest tests/ -v

All tests use mocked HTTP — no real API calls or network required.


Project Structure

api2trade_sdk/
├── api2trade_sdk/
│ ├── __init__.py # Public API surface
│ ├── client.py # Api2TradeClient — main entry point
│ ├── http.py # HTTP transport (auth, retry, error mapping)
│ ├── streaming.py # WebSocket client (auto-reconnect)
│ ├── models.py # Typed dataclass response models
│ ├── enums.py # OrderType, RetCode
│ ├── exceptions.py # Exception hierarchy
│ └── resources/
│ ├── accounts.py # /RegisterAccount /CheckConnect /AccountSummary /DeleteAccount
│ ├── market.py # /GetQuote
│ ├── orders.py # /OrderSend /OrderModify /OrderClose /Positions
│ └── history.py # /OrderHistory /OrderHistoryPagination
├── examples/
│ ├── 01_connect_account.py
│ ├── 02_account_summary.py
│ ├── 03_place_trade.py
│ ├── 04_order_history.py
│ ├── 05_websocket_stream.py
│ └── 06_prop_firm_monitor.py
├── tests/
│ ├── test_models.py
│ ├── test_exceptions.py
│ └── test_resources.py
├── pyproject.toml
├── CHANGELOG.md
├── LICENSE
└── README.md

Supported Endpoints

EndpointMethodSDK method
/RegisterAccountPOSTclient.accounts.register()
/CheckConnectGETclient.accounts.check_connect()
/AccountSummaryGETclient.accounts.summary()
/DeleteAccountDELETEclient.accounts.delete()
/GetQuoteGETclient.market.quote()
/OrderSendPOSTclient.orders.send()
/OrderModifyPOSTclient.orders.modify()
/OrderClosePOSTclient.orders.close()
/PositionsGETclient.orders.positions()
/OrderHistoryGETclient.history.get()
/OrderHistoryPaginationGETclient.history.get_page() / iter_all()
wss://.../streamWSclient.stream() / stream_iter()

Support

ChannelLink
📧 Emailsupport@api2trade.com
💬 Telegramt.me/apisupport_en
📖 Docsdocs.metatraderapi.dev
🌐 Websiteapi2trade.com
🟢 Statusstatus.metatraderapi.dev

License

MIT — see LICENSE.


MetaTrader®, MT4®, and MT5® are trademarks of MetaQuotes Ltd. API2Trade is an independent service and is not affiliated with MetaQuotes Ltd.

About

Connect and control your MT4 & MT5 trading accounts via a single REST API + WebSocket layer. Live market data, trade execution, account management — without a running terminal or Expert Advisors.

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages