Binance Order Filters
One of the issues that many traders come across is the limits on exchanges especially Binance.
If you have run across a Filter failure whether it be PRICE_FILTER, LOT_SIZE, MIN_NOTIONAL, MARKET_LOT_SIZE you know what I mean.
If you haven’t seen any of these before then you are bound to sooner or later! When you start running strategies and calculating percentages, or adding fees you will end up with some prices or quantities with greater precision than is allowed.
Another complication is that these filters can interact with each other, while you may satisfy the PRICE_FILTER you may not satisfy the MIN_NOTIONAL etc.
There are a number of other filters, for this post I’m going to focus on the filters related to the Spot market.
What do these terms mean
Lot - refers to the amount of the order, otherwise known as quantity
Notional - the value in the base asset calculated by price
* quantity
Base Asset - refers to the asset that is the quantity of a symbol. For the symbol BTCUSDT, BTC would be the base asset.
Quote Asset - refers to the asset that is the price of a symbol. For the symbol BTCUSDT, USDT would be the quote asset.
Symbol - a pair of assets that are traded on Binance
How to find filters
Let’s say we want to trade on BTCUSDT we will need to know the rules, but where are they?
They are found in the exchange info endpoint get_exchange_info
, this returns a list of symbols, the
python-binance client has a helper function get_symbol_info
if we are just interested in one symbol.
This returns
There’s a lot of information here, so let’s break it down.
baseAssetPrecision
and quoteAssetPrecision
are interesting as they describe the precision your balance
can be for the base and the quote asset.
This is generally a larger precision than what you can trade, you might have 1034.134894 USDT, but as you’ll see below you may end up with some small balance that are called dust.
Don’t despair though as Binance does have an option to convert dust to BNB.
PRICE_FILTER
Remember that price relates to the quote asset, and for BTCUSDT this is USDT. The price tell us how much we can buy or sell BTC for in USDT, well depending on the market.
I’ve pulled out the relevant information. So what does this tell us.
"minPrice": "0.01000000"
- we know the min price can be 0.01, if only!
"maxPrice": "1000000.00000000"
- we know the max price usable on the system is 1,000,000.00.
"tickSize": "0.01000000"
- tick size is the increment we can increase or decrease our price by.
MARKET_LOT_SIZE
The Market Lot Size filter defines rules around Market orders for a symbol.
Remember lot
relates to quantity and that’s the base asset, for BTCUSDT, BTC is the base asset.
This filter has a couple of values that are 0, which means this particular part of the filter does not apply.
"maxQty": "104.64146873"
- indicates the maximum quantity allowed for a market order
If minQty
was set then that would define the minimum quantity allowed.
stepSize
works similarly to the tickSize
of the PRICE_FILTER
filter and defines the intervals we can
increase or decrease the quantity by.
LOT_SIZE
The Lot Size filter defines the limits on the quantity for both Limit and Market orders for a symbol.
"minQty": "0.00000100"
- The minimum quantity of BTC we can place an order for
"maxQty": "9000.00000000"
- The maximum quantity of BTC we can place an order for
"stepSize": "0.00000100"
- The interval we can increase or decrease the quantity by
MIN_NOTIONAL
The Min Notional filter defines the minimum value calculated in the quote asset for a symbol.
For our symbol BTCUSDT the quote symbol is USDT, so the min notional values is in USDT.
From above, we know we can calculate the notional value as following.
How about Market orders you might ask, that doesn’t have a price, does this filter not apply?
Sorry to say, Market orders don’t always allow you a free pass for this filter.
"applyToMarket": true
if this is false then it doesn’t apply. As of writing if you do loop through all
the symbols and check the MIN_NOTIONAL filter then none of them have applyToMarket
as false. Even if they
did you are probably safer to just follow it.
Also note the "avgPriceMins": 5
part, what this is hinting to is that Binance calculates an average price
for each symbol and that is used to check this MIN_NOTIONAL filter for Market orders.
To find the average price for BTCUSDT, let’s modify the main
function of our code from above and run again
We see that the mins
value matches the symbol info response, and we now also have a price to use for
Market orders in our notional value calculation.
Ready to trade?
Now you know what they all mean you’re ready to trade? Or more confused about how to determine a price that will pass the filters?
Let’s say that you have been watching the BTCUSDT, all the squiggles align, the price is going to go up and you’re destined to make 3% profit.
We place a market order to get into the market fast, although let’s not use our own money just yet.
Luckily Binance offers a testnet to test out Spot trading. Head to testnet.binance.vision login with Github credentials and click on Generate HMAC_SHA256 Key, copy the API Key and API secret into the values below.
We don’t have a lot of USDT and we know the minimum quantity is 0.000001, so we start small.
Oh, we forgot about the notional value, it was only 0.000001 * 58425.57064095
which is 0.058
.
The min notional value is 10.0
, so our minimum is 10.0 / 58425.57064095 = 0.00017115
, lets be a bit more confident
now and set quantity = 0.001
and run our script.
Perfect now our order has been filled, and we can work out the price it filled at.
This gives us 58802.609
, great now we can work out where to place our Limit sell order.
Well that’s annoying, now we need to do a little bit more work.
We can see that is greater than our asset precision of 8 for a start, so let’s adjust the target_price.
Ok, we know what this means, we need to satisfy 2 decimal places.
Great now our limit order has finally been placed, and we can reap our profits.
Using helpers
The above code needs to know that our tickSize
of 0.01
means that we should round to 2 decimal places.
We have a helper function that can do this work for us called round_step_size
, this can be applied
to both price and quantity values.
The target_price is the same as above, and we have placed the limit order successfully.
Next Steps
Hopefully this has helped demystify some of the terminology that you will see when interacting with the exchange, and you now have some tools to handle price and quantity parameters when trading.
Register with Binance and switch over from the testnet and try out your strategies.