Skip to main content

tickerall

Official Python client for the TickerAll REST + WebSocket API.

Place trades, stream live market data, and manage broker sessions programmatically — without an MT4/MT5 terminal in the path. No Windows VM, no Wine, no MetaTrader5 terminal to babysit, no thread-safety workarounds.

pip install tickerall

Requires Python 3.9+. Depends only on httpx and websocket-client.

Why

The official MetaTrader5 Python package only runs on Windows, drives a local terminal over a single-threaded IPC channel, and falls over under concurrency. TickerAll hosts the broker connection for you and exposes it as a clean HTTP + WebSocket API, so your bot can run anywhere — Linux, macOS, a container, a Raspberry Pi — and stream ticks instead of polling.

MetaTrader5 (local terminal) tickerall
OS Windows only anywhere Python runs
Live ticks poll symbol_info_tick() per symbol push over WebSocket
Concurrency single-threaded IPC, not thread-safe stateless HTTP, thread-safe
Deploy a terminal per account to babysit pip install

Quickstart

from tickerall import Tickerall

client = Tickerall(api_key="cf_live_...")

# Connect a broker account → get a TickerAll account_id
session = client.sessions.start(
    broker="mt5",
    server="Exness-MT5Trial7",
    account=12345678,
    password="...",
)

# Place a market order
order = client.orders.place(
    session.account_id,
    type="market",
    symbol="BTCUSDm",
    side="BUY",
    volume=0.10,
    stop_loss=58000.0,
    take_profit=72000.0,
)
print(order.ticket, order.status)

client.sessions.end(session.account_id)

The client is a context manager too:

with Tickerall(api_key="cf_live_...") as client:
    ...

Mesh mode (advanced)

Mesh mode routes your broker traffic through a pool topology: you connect your accounts once against a mother endpoint, which warms them on a pool and hands back that pool's edge URL plus a short-lived grant. The SDK then sends all broker-data / trade / stream traffic to the edge (grant-authed) while roster and discovery stay on the mother — refreshing the grant, and following a pool migration, transparently. Opt in with mesh_mode=True; leaving it off is the normal direct connect, unchanged.

client = Tickerall(
    api_key="cf_live_...",           # authenticates you to the mother at discover time
    mesh_mode=True,
    mother_url="https://mesh.tickerall.com",
)

# Connect one or more accounts (they land on ONE pool together). Returns a
# stable account_ref per account — use it for every call and stream channel.
result = client.mesh.connect([
    {"broker": "mt5", "server": "Pepperstone-Demo", "account": 61542511, "password": "..."},
])
ref = result.accounts[0].account_ref

# From here the API is identical to direct mode — it just runs against the edge.
symbols = client.accounts.symbols(ref)
info    = client.accounts.account_info(ref)     # live balance/equity/…
stream  = client.stream.connect()
stream.subscribe_ticks(ref, ["BTCUSDm"])

The grant (1-hour TTL by default) is refreshed for you — proactively before it expires, and reactively when a grant is rejected (401), a pool migrates or dies (a persistent edge failure re-discovers onto a fresh pool), or the stream drops — so you never handle it. The account_ref is stable across refreshes and pool migrations, so subscriptions and queries keyed on it never need remapping. client.mesh.close() stops the background refresh.

Terminal type (MOBILE / WEB / CLIENT)

terminal_type picks which client the connection presents AS — "MOBILE" (the default), "WEB", or "CLIENT" (a desktop terminal). All expose the full surface (account, quotes, positions, history). The type sets the broker-assigned order origin (ENUM_DEAL_REASON): "MOBILE"DEAL_REASON_MOBILE, "WEB"DEAL_REASON_WEB, "CLIENT"DEAL_REASON_CLIENT — useful where a venue distinguishes desktop-placed orders (e.g. some prop firms).

"WEB" requires the broker's web-terminal URL (web_terminal_url) — web terminals are per-broker-domain, so the URL must be supplied. "MOBILE" and "CLIENT" take neither web field:

session = client.sessions.start(
    broker="mt5",
    server="YourBroker-Server",
    account=12345678,
    password="...",
    terminal_type="WEB",
    web_terminal_url="https://mt5.yourbroker.com",  # required for WEB
    # web_endpoint="wss://host/path",               # optional WS override (rare)
)

For a desktop-origin (DEAL_REASON_CLIENT) connection — no web URL needed:

session = client.sessions.start(
    broker="mt5",
    server="YourBroker-Server",
    account=12345678,
    password="...",
    terminal_type="CLIENT",
)

Streaming — push, not poll

The stream runs on its own background thread. Register callbacks and go; it heartbeats, reconnects with backoff, and re-subscribes automatically.

client = Tickerall(api_key="cf_live_...")
session = client.sessions.start(broker="mt5", server="Exness-MT5Trial7",
                                account=12345678, password="...")

stream = client.stream.connect()
stream.on("tick", lambda e: print(e.symbol, e.bid, e.ask, e.timestamp))
stream.on("position", lambda e: print(e.event, e.position.ticket, e.position.profit))
stream.subscribe_ticks(session.account_id, ["BTCUSDm", "ETHUSDm"])
stream.subscribe_positions(session.account_id)

# ... your app runs ...
stream.close()

Keep an in-memory tick cache fresh (zero polling)

A common pattern: let the WebSocket fill a dict so price reads are O(1) with no network call — strictly better than polling a terminal per symbol.

latest: dict[str, "TickEvent"] = {}
stream = client.stream.connect()
stream.on("tick", lambda e: latest.__setitem__(e.symbol, e))
stream.subscribe_ticks(session.account_id, ["BTCUSDm", "ETHUSDm", "XAUUSDm"])

# Anywhere in your app — instant, no IPC, no thread-safety dance:
tick = latest.get("BTCUSDm")

Market data & history

# Historical OHLC candles (coarser timeframes reach further back)
bars = client.candles.get(session.account_id, symbol="BTCUSDm", hours=24, timeframe="M5")
for c in bars:
    print(c.timestamp, c.open, c.high, c.low, c.close)

# Closed-trade history (recent broker window)
trades = client.history.get(session.account_id, symbol="BTCUSDm", limit=100)

# Tradeable symbols and their volume specs
symbols = client.accounts.symbols(session.account_id)
specs = client.accounts.symbol_specs(session.account_id)  # min / max / step per symbol

# Remove an account from your roster (disconnects it + drops it from your list
# and billing; broker account and open positions are untouched). Reversible —
# reconnect the same login with sessions.start to re-add it.
client.accounts.remove(session.account_id)

Positions

detail = client.accounts.get(session.account_id)
for p in detail.positions:
    print(p.ticket, p.symbol, p.side, p.volume, p.profit)

client.positions.modify(session.account_id, ticket=p.ticket, stop_loss=60000.0)
client.positions.close(session.account_id, ticket=p.ticket)          # full close
client.positions.close(session.account_id, ticket=p.ticket, volume=0.05)  # partial

Always-hot sessions & transparent re-arm

For connections that must stay up across restarts, use keep_alive. The credentials live in this process's memory only (never persisted); if the account goes cold (e.g. TickerAll restarted), the next call transparently re-supplies them and retries once.

session = client.sessions.keep_alive(broker="mt5", server="Exness-MT5Trial7",
                                     account=12345678, password="...")
# ... later, after an outage, this just works — the client re-arms under the hood:
client.accounts.get(session.account_id)

# Stop keeping it alive (drops the cached credentials):
client.sessions.stop_keep_alive(session.account_id)

Reliability — idempotency & queue-and-replay

State-changing calls (sessions.start, orders.place, positions.close, positions.modify) carry a stable Idempotency-Key, so a retried call can't double-execute. By default a transient connectivity failure (TickerallServiceUnavailableError, .transient == True) fails fast so you can re-decide with fresh prices:

from tickerall import TickerallServiceUnavailableError

try:
    client.orders.place(account_id, type="market", symbol="BTCUSDm", side="BUY", volume=0.1)
except TickerallServiceUnavailableError:
    ...  # momentary blip — safe to retry

For price-insensitive orders (pending orders, SL/TP edits) you can instead queue-and-replay until connectivity returns:

client.orders.place(
    account_id, type="limit", symbol="BTCUSDm", side="BUY", volume=0.1, price=60000.0,
    queue_if_reconnecting=True, queue_max_s=60.0,
)

Errors

All errors derive from TickerallApiError and carry .status, .code, .request_id, .details, and .transient:

Class When
TickerallAuthError 401 — bad/missing API key
TickerallForbiddenError 403 — plan limit / reserved resource
TickerallValidationError 400 / 422 — malformed request
TickerallNotFoundError 404 — account / position not found
TickerallBrokerError broker rejected or could not satisfy the request
TickerallServiceUnavailableError transient — TickerAll momentarily unreachable (safe to retry)

Using it from an async app

REST methods are synchronous and thread-safe, so call them from an event loop via asyncio.to_thread:

detail = await asyncio.to_thread(client.accounts.get, account_id)

The stream is already non-blocking (its own thread) — callbacks fire as events arrive.

License

MIT © Miguel Santos

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tickerall-0.2.1.tar.gz (33.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tickerall-0.2.1-py3-none-any.whl (41.1 kB view details)

Uploaded Python 3

File details

Details for the file tickerall-0.2.1.tar.gz.

File metadata

  • Download URL: tickerall-0.2.1.tar.gz
  • Upload date:
  • Size: 33.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.2

File hashes

Hashes for tickerall-0.2.1.tar.gz
Algorithm Hash digest
SHA256 8053578a850910bdfe6d24e5fc3905f9437db11e9c2d52d3189f48fc6edf975b
MD5 e9428dd4f593bdd29091a711ff3ebdca
BLAKE2b-256 63b2b6e1c0ca014b15ea1648b744366a475f6ae0f78657c79193134eb12f432b

See more details on using hashes here.

File details

Details for the file tickerall-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: tickerall-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 41.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.2

File hashes

Hashes for tickerall-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 e7e4514595fc66c3cd3d9c7b9c2ca0aeaafff553a9df5c828f9cd5d79bc0ce77
MD5 19dac6637a343b54aec7c847ce30c4f3
BLAKE2b-256 86c0813bcadcb1f6c1d89c215dfa0b2de66c8bc08bf5243b988d0df377b94935

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page