Python
orderfill: async, typed, on httpx and websockets. Python 3.10+.
pip install orderfill
import asyncio, os
from orderfill import OrderFill
async def main():
async with OrderFill(token=os.environ["ORDERFILL_API_KEY"]) as client:
[account] = await client.accounts()
gold = client.account(account.id)
print(await gold.info())
await gold.place_order("XAUUSD", "buy", 0.1)
asyncio.run(main())
Everything is async. Results are frozen dataclasses with snake_case fields:
position.broker_symbol, summary.pending.
Accounts
connected = await client.connect("mt5", "477072059", password, "Exness-MT5Trial9")
if connected.notice:
print(connected.notice) # saved, but cannot connect yet
account = client.account(connected.account.id)
Trading
await account.place_order("XAUUSD", "buy", 0.1, stop_loss=2395)
await account.place_order("EURUSD", "buy", 0.1, kind="limit", price=1.07)
await account.check_order("XAUUSD", "buy", 0.1) # margin, without trading
await account.modify_position(ticket, take_profit=2440)
await account.close_position(ticket, volume=0.05) # part of it
await account.close_losing() # every loser
Each call that changes the account sends an idempotency key. Pass
idempotency_key="…" to use your own.
Reading and symbols
await account.quote("XAUUSD")
await account.candles("XAUUSD", "M1", count=100) # the latest 100
await account.candles("XAUUSD", "H1", from_="2026-09-01T00:00:00Z")
await account.margin_for("XAUUSD", "buy", 0.1)
await account.health()
await account.executions()
await account.symbols(all=True, q="gold")
await account.resolve_symbol("XAUUSD")
Streaming
from orderfill import OrderFillStream
stream = OrderFillStream(token=os.environ["ORDERFILL_API_KEY"])
stop = await stream.watch(account.id, "ticks", lambda quotes: print(quotes[0].bid), symbol="XAUUSD")
The listener can be a function or a coroutine function.
Errors
from orderfill import OrderFillError
try:
await account.place_order("NZDCAD", "buy", 0.1)
except OrderFillError as error:
print(error.code, error, error.hint, error.request_id)