Skip to main content

MFX Hub Python SDK

The typed Python client for the MFX Hub API: hosted trading terminals for your own broker accounts, with market data, execution, account state and a live event stream behind one signed REST and WebSocket API.

pip install mfx-sdk

Python 3.12 or later. Async first, with a thin synchronous client for scripts.

Your first quote and your first order

You need an API key (its id and the private key shown once when it is issued), the id of a farm your plan allows (client.farms.list() shows them and what each offers), and a broker account on a server MFX Hub supports. The documentation walks through each step, and the SDK reference lists every method.

import os
import anyio
import mfx

API = "https://api.mfxhub.com/v1"          # https://api.dev.mfxhub.com/v1 for development


async def main() -> None:
    async with mfx.MfxClient(API, os.environ["MFX_KEY_ID"], os.environ["MFX_PRIVATE_KEY"]) as client:
        # 1. A terminal for your broker account, on a farm your plan allows, asking only for what
        #    that farm offers.
        farm = await client.farms.get(os.environ["MFX_FARM_ID"])
        offers = {str(usage) for usage in farm.usages}
        terminal = await client.terminals.create(
            farm_id=farm.id,
            broker_id=os.environ["MFX_BROKER_ID"],
            server_id=os.environ["MFX_SERVER_ID"],
            streaming="quote_streaming" in offers,
            execution="order_execution" in offers,
            instruments=["EURUSD"],                # the broker's own symbol names
            idempotency_key="my-first-terminal",
        )
        await client.terminals.submit_credentials(
            terminal.id,
            login=int(os.environ["BROKER_LOGIN"]),
            password=mfx.Secret(os.environ["BROKER_PASSWORD"]),
            server=os.environ["BROKER_SERVER"],
            idempotency_key="my-first-credential",
        )
        while not mfx.is_usable(terminal := await client.terminals.get(terminal.id)):
            await anyio.sleep(5)

        # 2. A quote, always with its age.
        quote = await client.catalog.quote(os.environ["MFX_BROKER_ID"], "EURUSD")
        print(quote.bid, quote.ask, quote.age_s)

        # 3. An order. Execution never raises: every outcome is a result.
        placed = await client.execution.place_order(
            terminal.id, symbol="EURUSD", side="buy", volume="0.01",
            idempotency_key="my-first-order",
        )
        done = await client.execution.wait_for(placed.command_id)
        print(done.state, done.reason, done.exec_price)


anyio.run(main)

What to know

  • Every write takes an idempotency_key, and none defaults it. Retrying with the same key returns the original answer; a fresh key asks for a second terminal or a second order.
  • Execution methods never raise. A transport fault, a timeout, a rate limit and a broker rejection all come back as an ExecutionResult with a granular reason, the broker's own comment_raw, and retryable. A result in state UNKNOWN may already be a position: never re-send it under a new key; the platform reconciles it.
  • Prices, volumes and money are decimal strings, in both directions. Pass Decimal or str; a float is refused, because 0.07 * 3 is 0.21000000000000002.
  • Reads raise typed errors, mapped from the API's error.code: NotFoundError, RateLimitError with retry_after_s, UpstreamError (with DependencyUnavailableError and EdgeError beneath it), MaintenanceError with the window's ends_at, and the rest.
  • Credentials cannot be logged by accident. SigningKey and Secret render as *** in every repr, f-string, log line and traceback, and cannot be pickled.
  • Lists follow the cursor. There are no totals and no page numbers; list() methods iterate every page, page() methods return one.
  • The stream (client.stream()) carries market data, candles, order book, account state, results and events, with resumable sequence numbers on the channels that need them.

REST only

Every tenant operation in the API has a typed method here except these, which you call over HTTPS with the same request signing (mfx.signing). A test keeps this table equal to the API, so it cannot drift.

Operation Route
cancelTerminalOperation DELETE /terminals/{id}/operations/{operation_id}
createRedisPushConnector POST /connectors/redis-push
updateTerminal PATCH /terminals/{id}

openStream is the WebSocket, opened with client.stream().

How this package is built

src/mfx/_generated is generated from the published MFX Hub API description in spec/openapi.yaml and is never edited by hand; CI regenerates it and fails on any difference. The hand-written modules around it (mfx.terminals, mfx.execution, mfx.streaming and the rest) are what you import.

uv sync
uv run pytest
uv run python tools/generate.py      # after the API description changes

Support and security

Licence and trademarks

Licensed under the Apache License 2.0.

MFX Hub is an independent service and is not affiliated with, endorsed by or sponsored by MetaQuotes Ltd. MetaTrader is a trademark of MetaQuotes Ltd., used here only to say which trading platform MFX Hub's terminals are compatible with.

Metadata

Release files for mfx-sdk 0.9.15

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mfx-sdk 0.9.15
File Size Uploaded Provenance Actions
mfx_sdk-0.9.15.tar.gz 195.3 kB With provenance Details for mfx_sdk-0.9.15.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for mfx-sdk 0.9.15
File Interpreter ABI Platform Actions
mfx_sdk-0.9.15-py3-none-any.whl Python 3 none any Details for mfx_sdk-0.9.15-py3-none-any.whl

Total release size: 617.2 kB

Release files / mfx_sdk-0.9.15.tar.gz

Download URL mfx_sdk-0.9.15.tar.gz
Size 195.3 kB
Tags Source
SHA-256 checksum
How to use checksums
6875244e30fac88ac61d0ff1393da8ba8871aa82f4b27c8b07e7a2425276a293
BLAKE2b-256 checksum
How to use checksums
878573fe5fe2ebed7d762e6a4b0286ca87c2e32d303857d1b8490f6b4355ef61
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.

Transparency log

Release files / mfx_sdk-0.9.15-py3-none-any.whl

Download URL mfx_sdk-0.9.15-py3-none-any.whl
Size 421.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
efbc3c4cdaa8be3e75a337cf927fe9fe0c8995ea245b43d9651a5d2375ec4401
BLAKE2b-256 checksum
How to use checksums
c09cc4e992aa0f12b45cfc48d0640c8400d24eae47342ba4d58d28aed48c92a2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.

Transparency log

Security for mfx-sdk 0.9.15

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for mfx_sdk-0.9.15.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.9.15 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page