Small partially filled market orders

Hi,

Today, I have placed a very small buy order for 91.2 XRPUSDT (perp) at 2021-04-22 13:00:10 UTC.
I have subscribed to the user data stream and got back 3 partial fill messages (quantities of 17.9, 48.3, 53.6).
Given the liquidity of xrpusdt, I cannot believe that such a small market order is not immediately filled. Or do I misunderstand Binance’s definition of ‘market order’? - I would assume that a market order eats into the the order book until it is filled. I can imagine a partially filled market order if the order size is really huge so that the order book is completely depleted (which clearly cannot be the case in my example).

BTW: I have some more examples of small market orders getting only partially filled.
I can also provide more order details (ID) if necessary.

Thanks,
Robert

Hi Robert, getting partial fills for a small quantity market order can happen.

As you know trades happens very quickly, immediately after you place the buy market order, the best sell price quantity was lesser than yours, so you got partially filled, after this the next best price quantity might again be lesser than your “new” market order as many other traders are also involved and they’ve already filled their orders for the same price.

Hi aisling,

Thanks for your reply! If I understand you correctly, I would then get a partial fill message for each price level that my order depletes from the order book. Let’s say that when my buy order of 91.2 XRPUSDT hits the exchange the actual order book volume at the lowest price of 1.3286 was 17.9. So I would get a partial fill message of quantity 17.9 @ price 1.3286. Then we go to the next price level @ 1.3287, where there is a volume of 30.4 - so I get the next partial fill of quantity 30.4 @ 1.3287 (=48.3 cumulative quantity).

In this case, I would expect that the last fill prices of the partial fill messages in the user data stream (the “L” field) have different prices - like in my hypothetical example above. However, in my real example, my partial fill messages all have the same price 1.3286 - only the last fill message has a different price 1.3288.

Please find the messages below.
Thank you, aisling.

New order

{"e":"ORDER_TRADE_UPDATE","T":1619096410202,"E":1619096410206,"o":{"s":"XRPUSDT","c":"7277","S":"BUY","o":"MARKET","f":"GTC","q":"91.2","p":"0","ap":"0","sp":"0","x":"NEW","X":"NEW","i":12814899461,"l":"0","z":"0","L":"0","T":1619096410202,"t":0,"b":"0","a":"0","m":false,"R":false,"wt":"CONTRACT_PRICE","ot":"MARKET","ps":"BOTH","cp":false,"rp":"0","pP":false,"si":0,"ss":0}}

Partial fill 1:

{"e":"ORDER_TRADE_UPDATE","T":1619096410202,"E":1619096410207,"o":{"s":"XRPUSDT","c":"7277","S":"BUY","o":"MARKET","f":"GTC","q":"91.2","p":"0","ap":"1.32860","sp":"0","x":"TRADE","X":"PARTIALLY_FILLED","i":12814899461,"l":"17.9","z":"17.9","L":"1.3286","n":"0.00001511","N":"BNB","T":1619096410202,"t":329482146,"b":"0","a":"0","m":false,"R":false,"wt":"CONTRACT_PRICE","ot":"MARKET","ps":"BOTH","cp":false,"rp":"-0.32602063","pP":false,"si":0,"ss":0}}

Partial fill 2

{"e":"ORDER_TRADE_UPDATE","T":1619096410202,"E":1619096410207,"o":{"s":"XRPUSDT","c":"7277","S":"BUY","o":"MARKET","f":"GTC","q":"91.2","p":"0","ap":"1.32860","sp":"0","x":"TRADE","X":"PARTIALLY_FILLED","i":12814899461,"l":"30.4","z":"48.3","L":"1.3286","n":"0.00002566","N":"BNB","T":1619096410202,"t":329482147,"b":"0","a":"0","m":false,"R":false,"wt":"CONTRACT_PRICE","ot":"MARKET","ps":"BOTH","cp":false,"rp":"-0.55368867","pP":false,"si":0,"ss":0}}

Partial fill 3:

{"e":"ORDER_TRADE_UPDATE","T":1619096410202,"E":1619096410207,"o":{"s":"XRPUSDT","c":"7277","S":"BUY","o":"MARKET","f":"GTC","q":"91.2","p":"0","ap":"1.32860","sp":"0","x":"TRADE","X":"PARTIALLY_FILLED","i":12814899461,"l":"5.3","z":"53.6","L":"1.3286","n":"0.00000447","N":"BNB","T":1619096410202,"t":329482148,"b":"0","a":"0","m":false,"R":false,"wt":"CONTRACT_PRICE","ot":"MARKET","ps":"BOTH","cp":false,"rp":"-0.09653124","pP":false,"si":0,"ss":0}}

Fill:

{"e":"ORDER_TRADE_UPDATE","T":1619096410202,"E":1619096410207,"o":{"s":"XRPUSDT","c":"7277","S":"BUY","o":"MARKET","f":"GTC","q":"91.2","p":"0","ap":"1.32868","sp":"0","x":"TRADE","X":"FILLED", "i":12814899461,"l":"37.6","z":"91.2","L":"1.3288","n":"0.00003175","N":"BNB","T":1619096410202,"t":329482149,"b":"0","a":"0","m":false,"R":false,"wt":"CONTRACT_PRICE","ot":"MARKET","ps":"BOTH","cp":false,"rp":"-0.68866277","pP":false,"si":0,"ss":0}}

How do we code it so it allows for a partially filled order rather than let it sit there and potentially never hit the tp again?

If it’s a Market order it’ll always be fully filled, what you might be looking for is Limit order with timeInForce=IOC