Skip to content
01TX
Insights

Trading Infrastructure

Partial fills and MetaTrader: what the bridge has to decide

4 min read

The simple picture of a bridge is that a client sends an order, the bridge passes it to an LP, and the LP fills it. Mostly that's what happens. When it doesn't, you're usually looking at a partial fill, and the bridge has to make a decision that nobody wrote down in advance.

On the LP side a partial fill is routine. Over FIX you'll see an ExecutionReport with OrdStatus 1 (partially filled), with CumQty and LeavesQty telling you what's done and what's left. If the order went out as IOC (TimeInForce 3), the remainder is cancelled straight away. If it was FOK (4) there's no partial at all, it fills in full or not at all.

MT5 can represent a partial fill. One order can produce several deals, and the position is the sum of them. Whether you actually get one depends on the fill policy and execution mode set on the symbol (FOK, IOC or Return), so check what your server allows before assuming anything.

MT4 doesn't really have the idea. As far as its standard order model goes, a market order is there in full or it isn't. A bridge sitting in front of MT4 ends up rejecting anything the LP can't fill completely, splitting the order into more than one ticket, or filling the difference itself.

The options and what each one costs

Take what you got and cancel the rest. This is the simplest. The client ends up with a smaller position than they asked for, which MT5 can show honestly and MT4 can't.

Send the remainder to the next LP. The client gets their full size, but at two prices, so they need a sensible average, and the second leg might be worse or get rejected as well. The order also takes longer, and a slow order is one the price has moved on.

Fill the remainder yourself. That's quick and the client is happy, and now you hold risk you didn't plan to. Fine if it's deliberate, expensive if nobody noticed it was happening.

Reject the whole thing. Clean, and annoying for clients, especially on the pairs they trade most.

None of these is right everywhere. What matters is that it's a setting someone chose per symbol or per client group, and not whatever the code did on the day it was written.

Two cases that cause the real trouble

Late fills. The bridge waits on the LP, hits its own timeout, tells the client the order failed, and then the fill arrives. Now the bridge holds a position the client doesn't have. It has to keep tracking an order after it has given up on it, and have a rule for what to do when a fill shows up late. Otherwise you've got a hedge nobody asked for.

Fractions. Say the LP fills 1,500 units of a 10,000 unit order and the volume step on MT is 0.01 lots, which is 1,000 units. 1,500 units is 0.015 lots, which isn't a valid volume. Somebody gets 0.01 and 500 units of dust has to live somewhere. It's small, but it adds up in the position report and makes reconciliation noisy. Give the dust a named bucket and sweep it on purpose.

There probably isn't one policy that fits all flow. Small retail tickets and a large account want different defaults, so it's worth making this configurable early instead of bolting it on after the first complaint.

Building something that runs into these problems directly?