# MT5 Python: orders, filling modes, time zones and Linux

URL: https://fincodelabs.com/en/blog/metatrader-5-python · Publisher: Fincode (Fincode Yazılım ve Teknoloji A.Ş.), Istanbul, Turkey · Category: Stocks, forex and broker APIs · Published: 2026-11-06 · Updated: 2026-11-06

MT5 Python guide: version 5.0.6231 facts, why order_send returns 10030, a tested filling function, return codes, UTC or server time, Linux and VPS limits.

**Short answer:** The official **MT5 Python** package, MetaTrader5 5.0.6231 on PyPI (27 September 2026), is a 32-function connector to a MetaTrader 5 terminal on the same Windows machine, and PyPI lists Windows x64 wheels only. Read the symbol's execution and filling modes before `order_send`, because a filling type the symbol does not allow returns retcode 10030. Results are polled, not pushed, so check `positions_get` and `history_deals_get` before you resend anything.

The package was installed and inspected on Windows on 5 November 2026. No MetaTrader 5 terminal or broker account was available, so nothing here placed an order: live calls are labeled as not run, and the logic ran on synthetic data. Use a demo account first; this guide gives no strategy or settings.

For the wider map of MT5 routes, see [MT5 API](https://fincodelabs.com/en/blog/mt5-api); for chart alerts, see [TradingView to MT5](https://fincodelabs.com/en/blog/tradingview-to-mt5).

## Install MetaTrader 5 Python: what the MT5 Python API really is

Run `pip install MetaTrader5` on Windows with a terminal installed: the package only talks to that terminal, by what the MQL5 reference calls interprocessor communication.

**MetaTrader5 package, read and measured on 5 November 2026**

| Item | Value | Where it comes from |
| --- | --- | --- |
| Version | 5.0.6231, uploaded 27 September 2026; 11 of PyPI's 39 releases came in 2026 | PyPI |
| Wheels | 9, all `win_amd64`, CPython 3.6 to 3.14; no source distribution | PyPI |
| Functions | 32 in the reference; the module exposes the same 32 lowercase names | MQL5 reference, `dir()` |

`initialize()` starts the terminal if needed, with a default 60,000 ms timeout, per the reference. With no terminal on the test machine it returned `False` at once with `(-10003, 'IPC initialize failed, MetaTrader 5 x64 not found')`. Before that call, `positions_get()` returned `None` with `(-10004, 'No IPC connection')`, and `version()` returned `(0, 0, '')`, not the `None` its reference page gives for errors, so test its contents rather than its truth value.

Two terminal settings can stop orders when the code is right: the automated trading button and the option *Disable automatic trading through the external Python API*. MetaTrader 5's help says Python trading is disabled by default and must be enabled there (read 5 November 2026). `terminal_info()` reports them as `trade_allowed` and `tradeapi_disabled`.

## MT5 unsupported filling mode: why order_send returns 10030

Retcode 10030, *Invalid order filling type*, means the request's `type_filling` is not allowed for that symbol, and the reference's own `order_send` example can cause it.

That example hard-codes `ORDER_FILLING_RETURN`, which Order Properties disables under Market Execution; the reference's `symbol_info` sample shows an Instant Execution symbol (`trade_exemode=1`), where Return is allowed.

**Filling types by execution mode, MQL5 Order Properties, read 5 November 2026**

| `trade_exemode` | FOK | IOC | Return |
| --- | --- | --- | --- |
| Request (0), Instant (1) | Yes, whatever the symbol says | Yes, whatever the symbol says | Always |
| Market (2) | If set in the symbol | If set in the symbol | Disabled |
| Exchange (3) | If set in the symbol | If set in the symbol | Always |

Read `filling_mode` as bit flags: 1 for FOK, 2 for IOC. Package 5.0.6231 has no `SYMBOL_FILLING_FOK` or `SYMBOL_FILLING_IOC` names (`hasattr` returned `False`), so snippets that use them raise `AttributeError`. Do not confuse the flags with the order values: `ORDER_FILLING_FOK` is 0 and `ORDER_FILLING_IOC` is 1.

```python
import MetaTrader5 as mt5     # 5.0.6231; this test uses only its constants

FOK_FLAG, IOC_FLAG = 1, 2     # SYMBOL_FILLING_* values from the MQL5 reference

def pick_filling(exemode, flags):
    """Filling type for a market order, following the Order Properties table."""
    if flags & FOK_FLAG:      # FOK before IOC is a choice, not advice
        return mt5.ORDER_FILLING_FOK
    if flags & IOC_FLAG:
        return mt5.ORDER_FILLING_IOC
    if exemode == mt5.SYMBOL_TRADE_EXECUTION_MARKET:
        raise ValueError("Market Execution with no FOK or IOC flag: ask the broker")
    return mt5.ORDER_FILLING_RETURN

names = {mt5.ORDER_FILLING_FOK: "FOK", mt5.ORDER_FILLING_IOC: "IOC", mt5.ORDER_FILLING_RETURN: "RETURN"}
for mode in ("REQUEST", "INSTANT", "MARKET", "EXCHANGE"):
    row = []
    for flags in (0, 1, 2, 3):
        try:
            row.append(names[pick_filling(getattr(mt5, "SYMBOL_TRADE_EXECUTION_" + mode), flags)])
        except ValueError:
            row.append("error")
    print(f"{mode:9}", *row)

# Live use, demo first; not run here:
#   info = mt5.symbol_info(symbol)      # None: read last_error() and stop
#   request["type_filling"] = pick_filling(info.trade_exemode, info.filling_mode)
#   check = mt5.order_check(request)    # retcode 0 passes in the docs' sample
#   result = mt5.order_send(request)    # None: read last_error() and state before any resend
```

Output, using the package's constants:

```
REQUEST   RETURN FOK IOC FOK
INSTANT   RETURN FOK IOC FOK
MARKET    error FOK IOC FOK
EXCHANGE  RETURN FOK IOC FOK
```

> **Hypothetical example.** A symbol reports `trade_exemode=2` and `filling_mode=2`. By the documented rule, a request copied from the reference gets 10030, and `pick_filling` returns IOC. If only 0.04 of a 0.10 lot order can fill, IOC fills 0.04 and cancels the rest.

**The documents conflict here.** The `order_check` page says Return applies only to symbols with Market or Exchange execution, while Order Properties and Symbol Properties disable it under Market Execution. The function follows those two pages; a demo account settles it for your broker. For pending orders, the reference says to use Return whatever the execution mode.

## MT5 Python return codes and what to do with each

Check `result.retcode` after every send: an object back from `order_send` says nothing about success.

**Trade server return codes (MQL5 reference, read 5 November 2026); the last column is guidance, not official text**

| Code | Official description | What to do |
| ---: | --- | --- |
| 10009 | Request completed | Confirm fills with `history_deals_get`; do not resend |
| 10004 | Requote | Fresh price, limited tries |
| 10006 | Request rejected | Read `comment` and `retcode_external`; no blind resend |
| 10014 | Invalid volume in the request | Check `volume_min`, `volume_step`, `volume_max` |
| 10016 | Invalid stops in the request | Check `trade_stops_level` and the side of the price |
| 10018 | Market is closed | Your rules decide |
| 10019 | There is not enough money to complete the request | Use `order_check`; do not resend |
| 10027 | Autotrading disabled by client terminal | Fix the two settings above |
| 10030 | Invalid order filling type | Use `pick_filling` |

`order_send` can also return `None`: here it did, with -10004 without a terminal and -2 for a non-integer `action`. Call `last_error()` and read state before any resend. The package's undocumented helpers retry only on 10004 and 10021 (no quotes), up to 10 times.

## Orders are polled: reconcile with positions_get and history_deals_get

The package has no event callback, so a bot must read terminal state after each send and restart.

The `OrderSend` reference warns that a successful reply does not mean execution, since trades can happen after the response; an Expert Advisor hears of them in `OnTradeTransaction`, which has no Python counterpart.

```python
from types import SimpleNamespace as NS

def order_state(api, ticket, wanted):
    """Read one order's state; never resend while the answer is unknown."""
    if not ticket:                                     # no order ticket
        return "unknown: no ticket, do not resend"
    replies = []
    for call in (api.orders_get, api.history_orders_get, api.history_deals_get):
        reply = call(ticket=ticket)
        if reply is None and api.last_error()[0] < 0:  # check before the next call
            return "unknown: do not resend"
        replies.append(reply or ())
    working, ended, deals = replies
    filled = round(sum(d.volume for d in deals), 8)
    if filled >= wanted:
        return "filled"
    if working:
        return f"working, {filled} filled"
    return f"ended, {filled} of {wanted} filled" if ended else "unknown: read again later"

class Terminal:                           # synthetic; every call sets the error
    def __init__(self, deals=(), working=(), ended=(), broken=None):
        self.data, self.broken = {"deals": deals, "working": working, "ended": ended}, broken

    def _reply(self, key):
        self.err = (-10004, "No IPC connection") if key == self.broken else (1, "Success")
        return None if key == self.broken else self.data[key]

    history_deals_get = lambda self, ticket: self._reply("deals")
    orders_get = lambda self, ticket: self._reply("working")
    history_orders_get = lambda self, ticket: self._reply("ended")
    last_error = lambda self: self.err

part, order = NS(volume=0.04), (NS(ticket=555),)
print(order_state(Terminal(deals=(part, part, NS(volume=0.02)), ended=order), 555, 0.1))
print(order_state(Terminal(deals=(part,), working=order), 555, 0.1))
print(order_state(Terminal(deals=(part,), ended=order), 555, 0.1))
print(order_state(Terminal(ended=order, broken="deals"), 555, 0.1))
print(order_state(Terminal(), 555, 0.1))
print(order_state(Terminal(), 0, 0.1))
```

Output:

```
filled
working, 0.04 filled
ended, 0.04 of 0.1 filled
unknown: do not resend
unknown: read again later
unknown: no ticket, do not resend
```

`None` means an error, per the reference, so read `last_error()` before the next call can replace it. Deals are read last; read first, a fill between two calls gave "ended, 0 of 0.1 filled" in a mock, inviting a resend.

Bookkeeping depends on `account_info().margin_mode`, which your broker sets: 0 netting, 1 exchange, 2 hedging. Under hedging, which allows several positions per symbol, the [MqlTradeRequest page](https://www.mql5.com/en/docs/constants/structures/mqltraderequest) says to put the position ticket in a closing request. Limits belong in [trading bot risk management](https://fincodelabs.com/en/blog/trading-bot-risk-management), and the general order state model is in [broker API integration](https://fincodelabs.com/en/blog/broker-api-integration-fix-rest).

## MT5 Python lib timestamp and time zone: UTC or server time?

Build request datetimes in UTC as the reference says, then measure your broker's stamps, because the documents do not settle it.

The pages for `copy_rates_from` and `copy_ticks_from` say MetaTrader 5 stores tick and bar open times in UTC and that a naive `datetime` uses your local zone. The MQL5 reference describes `TimeCurrent()` as server time formed on the trade server. Which clock your broker's stamps follow could not be tested here.

```python
def clock_gap(tick_time, now_utc):
    """Whole hours between a tick stamp and real UTC; None if the tick looks stale."""
    seconds = tick_time - now_utc
    hours = round(seconds / 3600)
    return hours if abs(hours) <= 14 and abs(seconds - hours * 3600) <= 120 else None

now = 1_793_880_000                         # 5 November 2026 12:00 UTC, synthetic
print(clock_gap(now - 3, now))              # stamps are real UTC
print(clock_gap(now + 2 * 3600 - 3, now))   # stamps run two hours ahead
print(clock_gap(now - 25 * 60, now))        # last tick is 25 minutes old
print(clock_gap(now - 3600 - 30, now))      # an hour-old tick reads as -1
print(clock_gap(0, now))                    # zero stamp

# Live, on a demo while quoting; not run here:
#   tick = mt5.symbol_info_tick(symbol)     # None: read last_error()
#   clock_gap(tick.time, time.time())
```

Output on synthetic stamps:

```
0
2
None
-1
None
```

Run it on a demo just after the tick time changes, since a stale tick can land on a whole hour; repeat it around daylight-saving changes. MetaTrader 5's MCP [capabilities page](https://www.metatrader5.com/en/terminal/help/mcp_and_ai/capabilities) also lists a `get_time_information` tool for UTC, server time and the offset. A backtest loaded from these bars inherits the offset; [backtesting Python libraries](https://fincodelabs.com/en/blog/backtesting-python-libraries) covers what comes next.

## MetaTrader 5 Python on Linux and on a VPS

Windows is the documented answer: PyPI has no Linux or macOS wheel, and MetaQuotes' Linux page covers the terminal under Wine and says nothing about Python.

On 5 November 2026, `pip download MetaTrader5 --no-deps --only-binary=:all: --python-version 3.12` with `--platform manylinux2014_x86_64`, and with `macosx_11_0_arm64`, ended in `No matching distribution found`.

**Where the package can run, as of 5 November 2026**

| Setup | Status |
| --- | --- |
| Windows desktop or VPS, terminal logged in | Matches the wheels; not run here (no terminal or account) |
| Terminal under Wine on Linux | Documented by MetaQuotes for Ubuntu, Debian, Linux Mint and Fedora; terminal only |
| Windows Python inside Wine | Not documented, not tested here; treat as unsupported |
| Linux application calling a Windows worker | Ordinary design; you own the API and its security |
| MetaQuotes' built-in virtual hosting | Migration page covers Expert Advisors and indicators; scripts are not moved, DLL calls are forbidden, and Python is not mentioned |

On your own Windows VPS, keep the terminal logged in, call `initialize()` again after a disconnect and reconcile before sending. The module has no client object, so plan on one terminal per process, with `path` choosing it; that is an inference, not a documented limit. Keep the password out of source and logs.

## Where the MT5 Python documents and the package differ

Two more differences, besides the filling flags:

**MQL5 reference against package 5.0.6231, 5 November 2026**

| Topic | Documents | Package |
| --- | --- | --- |
| IPC error code | `RES_E_INTERNAL_FAIL_CONNECT` listed as -10003 | Constant is -10004, the value seen in the test above |
| Helpers | Not among the 32 functions | `Buy`, `Sell`, `Close` in `__init__.py`, deviation 10, no `type_filling` |

Symbol Properties says a request without a filling type gets Return, so by the documented rule those helpers fail with 10030 on Market Execution symbols; that was read from source, not run.

Leveraged forex carries high risk, and automated orders can lose money quickly. Rules depend on your country, account types and API access vary by broker, and no broker is recommended, ranked or linked with a referral here. For readers in Turkey, separate rules apply to leveraged FX with foreign firms: the [Capital Markets Board (SPK) said on 23 February 2023](https://spk.gov.tr/duyurular/basin-duyurulari/2023/izinsiz-kaldiracli-islemlere-iliskin-basin-duyurusu) that residents may trade leveraged FX only through firms it has authorized ([Law No. 6362](https://www.mevzuat.gov.tr/mevzuatmetin/1.5.6362.pdf) Articles 99(4) and 109(2)). For integration work in general, see [algorithmic trading](https://fincodelabs.com/en/services/algorithmic-trading); naming MetaTrader 5 here does not mean Fincode integrates it or has built on it.

## Frequently asked questions

### Does the MetaTrader5 Python package work on Linux or Mac?

Not officially: PyPI lists only Windows x64 wheels for 5.0.6231, and pip found nothing for Linux or macOS on 5 November 2026. MetaQuotes documents only the terminal under Wine.

### Why does mt5.initialize() return False?

Call mt5.last_error() to see why. With no terminal installed it returned (-10003, 'IPC initialize failed, MetaTrader 5 x64 not found') in a test on 5 November 2026; the documented codes also include authorization failures.

### How do I fix unsupported filling mode in MT5 Python?

Read symbol_info(symbol).filling_mode and trade_exemode, then set type_filling from them: FOK if flag 1 is set, IOC if flag 2 is set, and Return only where the execution mode allows it.

### Are MT5 Python timestamps in UTC?

The reference says so, but it could not be tested here without a terminal. Measure it on a demo by comparing a fresh tick's time with real UTC.

## Sources

- [PyPI: MetaTrader5 5.0.6231, files and metadata](https://pypi.org/project/MetaTrader5/)
- [MQL5 Reference: Python Integration (function list, interprocessor communication)](https://www.mql5.com/en/docs/python_metatrader5)
- [MQL5 Reference: initialize (terminal launch, 60,000 ms timeout)](https://www.mql5.com/en/docs/python_metatrader5/mt5initialize_py)
- [MQL5 Reference: order_send (example with ORDER_FILLING_RETURN)](https://www.mql5.com/en/docs/python_metatrader5/mt5ordersend_py)
- [MQL5 Reference: order_check (filling type table, retcode sample)](https://www.mql5.com/en/docs/python_metatrader5/mt5ordercheck_py)
- [MQL5 Reference: copy_rates_from (UTC note, timeframes)](https://www.mql5.com/en/docs/python_metatrader5/mt5copyratesfrom_py)
- [MQL5 Reference: Order Properties (filling policies by execution mode)](https://www.mql5.com/en/docs/constants/tradingconstants/orderproperties)
- [MQL5 Reference: Symbol Properties (SYMBOL_FILLING flags, default filling)](https://www.mql5.com/en/docs/constants/environment_state/marketinfoconstants)
- [MQL5 Reference: Trade Server Return Codes](https://www.mql5.com/en/docs/constants/errorswarnings/enum_trade_return_codes)
- [MQL5 Reference: OrderSend (a successful reply is not an execution)](https://www.mql5.com/en/docs/trading/ordersend)
- [MetaTrader 5 Help: How to install the platform on Linux](https://www.metatrader5.com/en/terminal/help/start_advanced/install_linux)
- [MetaTrader 5 Help: Platform settings (external Python API option)](https://www.metatrader5.com/en/terminal/help/startworking/settings)
- [MetaTrader 5 Help: Virtual hosting, migration features](https://www.metatrader5.com/en/terminal/help/virtual_hosting/virtual_hosting_migration)
- [SPK: Press notice on unauthorized leveraged trading, 23 February 2023 (Turkish)](https://spk.gov.tr/duyurular/basin-duyurulari/2023/izinsiz-kaldiracli-islemlere-iliskin-basin-duyurusu)
- [Capital Markets Law No. 6362, Articles 99 and 109 (Turkish, consolidated text)](https://www.mevzuat.gov.tr/mevzuatmetin/1.5.6362.pdf)

> This guide is general information about software and markets, not investment, legal or tax advice. Automated trading can lose money, past or backtested performance does not guarantee future results, and the rules that apply depend on your jurisdiction and your exchange's terms. Sources, checks and corrections: see the [editorial policy](https://fincodelabs.com/en/editorial-policy).

---

Published by Fincode (Fincode Yazılım ve Teknoloji A.Ş.), a software company in Istanbul, Turkey: https://fincodelabs.com/en/blog/metatrader-5-python

Cite as: Fincode, "MT5 Python: orders, filling modes, time zones and Linux", updated November 6, 2026, https://fincodelabs.com/en/blog/metatrader-5-python
