Why am I getting 'Filter failure: LOT_SIZE' error in all my post requests?

Hello all. Firstly thank you so much for this forum. I had been wishing for a developer forum for Binance for a while now, and found this right now.

My issue had been posted here a lot of times but I still have some confusions about it so I’m posting here again.

The issue is I’m getting LOT_SIZE error when I’m trying to place a LIMIT order. And I can’t seem to wrap my head around two of the filter types: LOT_SIZE and MIN_NOTIONAL.

I’m working on a NodeJS/Express app and trying to place an order based on the “data” object below. The data has been fetched from “exchangeInfo” endpoint.

const data = {
symbol: ‘BNBBTC’,
type: ‘LIMIT’,
side: ‘BUY’,
price: ‘0.0095000’,
baseAsset: ‘BNB’,
baseAssetPrecision: 8,
quoteAsset: ‘BTC’,
quotePrecision: 8,
lotSizeFilter: {
filterType: ‘LOT_SIZE’,
minQty: ‘0.01000000’,
maxQty: ‘100000.00000000’,
stepSize: ‘0.01000000’
},
minNotionalFilter: {
filterType: ‘MIN_NOTIONAL’,
minNotional: ‘0.00010000’,
applyToMarket: true,
avgPriceMins: 5
}
}

This function help figure out the actual quantity of BNB to be bought. Here, I compared the minimum lot size needed with the actual quantity my BTC amount (20k sats for testing purposes) would get. This fumction takes in the amount to be spent (in BTC), price of the asset, minimum lot size of the asset and minimum notional value.

const quantityFunc = ( amount, price, lotSize, orderSize ) => {

// amount divided price gives the BNB amount I'll get.
let quantity = `${(amount / price).toFixed(8)}`;

if ( Number(quantity) < Number(lotSize) ) {
    console.log( `Error: Quantity Supplied: ${quantity}. Quantity Required: ${lotSize}` );
    return;
}

if ( Number(quantity) >= Number(lotSize) ) {
    return quantity;
}

}

This function executes the order with values taken from the object above as well as the value of the quantity from quantity function.

const orderExecutionFunc = async (pair, side, quantity, price) => {
const orderExecution = await bRest.testOrder({
“symbol”: pair,
“type”: “LIMIT”,
“side”: side,
“quantity”: quantity,
“timeInForce”: “FOK”,
“price”: price
});
return orderExecution;
};

const pair = data.pair;
const side = data.side;
const price = data.price;
const minLotSize = data.lotSizeFilter.minQty;
const minOrderSize = data.minNotionalFilter.minNotional;
const quantity = quantityFunc( 0.00020000, price, minLotSize, minOrderSize );

const executeOrder = await orderExecutionFunc(pair, side, quantity, price);

So is this how lot size is supposed to be compared with quantity? And should I compare MIN_NOTIONAL value with btc value on sell side or should I just compare both LOT_SIZE and MIN_NOTIONAL value in both sell and buy side? Please note that for testing purposes I’m using 20k sats as the initial value of my BTC.

Your help would be highly appreciated.

Let me explain the concept with the symbol BTCUSDT.

  1. BTC is the base asset. LOT_SIZE is measured by the amount of BTC, base asset.
  2. USDT is the quote asset. When you place an order with quoteOrderQty specified, the system will convert USDT to the corresponding quantity in BTC and check the LOT_SIZE.

So, with these concepts, I think it’s clear enough to answer the following questions.

  1. Say I have 100 USDT and I want to buy BTC. Typically while placing an order through Binance API, the quantity I have to put is the BTC amount (right?)… --> not necessary, you can put USDT (quoteOrderQty).

  2. In contrast, if I want to sell BTC for USDT, I have to put BTC amount as quantity (right?). So should I compare this BTC quantity with minQty or with the amount of USDT I’ll get? --> You only have to compare the BTC quantity with minQty.

  3. In the same way, MIN_NOTIONAL value’s quantity is the quantity of which asset? --> MIN_NOTIONAL = quantity * price, the unit here is USDT, the quote asset.

  4. Another issue I’m facing is with stepSize. I’m getting modulo value not equal to 0 all the time. What I did was, take the decimal places of minQty. Used that decimal places to round off the quantity value… --> stepSize defines the intervals. As your quantity = minQty + n * stepSize, (n is an integer.), it should be fine.

1 Like

That is a great explanation mate. Let me explain it to you based on what I understood. Correct me if I’m wrong.

LOT_SIZE is always measured by base asset

For the symbol BTCUSDT, it is always measured in BTC quantity, even if someone wants to buy BTC with USDT, the USDT will be first converted to BTC if he puts quoteOrderQty with his USDT amount, then checked to pass LOT_SIZE.

So if the symbol is ETHBTC, the base asset here is ETH. The LOT_SIZE will be measured by ETH amount, even if the user holds BTC amount and wants to buy ETH with BTC. But he needs to fill quoteOrderQty with his BTC amount.

Did I get it right thus far?

Moving on the points 1-4:

  1. Understood.
  2. Understood.
  3. In the same way, MIN_NOTIONAL value’s quantity is the quantity of which asset? --> MIN_NOTIONAL = quantity * price, the unit here is USDT, the quote asset.

The above is for the sell side. That is selling BTC for USDT, the unit is USDT. Therefore, MIN_NOTIONAL value is checked with USDT value. But for the buy side, is MIN_NOTIONAL value checked with BTC value as I’m buying BTC with USDT and therefore the unit is BTC?

  1. I’m not sure about this. I need to test this and understand the whole thing. But if you can, can you please tell me what “n” is here?

Bro, really sorry if I’m bothering you to a point where you are getting annoyed and want to bash my head to a wall. Its understandable. The questions I’m asking are just too absurd. But please bear with me for a while.

Why aren’t these filter controls used in trading presented in a separate API? We would get rid of tens of lines of calculation and control at once.

I think the explanation at LOT_SIZE and MIN_NOTIONAL on this page will be helpful for you. https://binance-docs.github.io/apidocs/spot/en/#filters
In brief, lot size defines the minimum quantity per trade and min notional specifies the minimum total payout (quantity * price) of the order.

Hey man, can’t thank you enough for your time.

There’s a big confusion I have and I hope you’ll help me clarify it. The minQty in LOT_SIZE is the quantity of which asset between BTCUSDT?

Say I have 100 USDT and I want to buy BTC. Typically while placing an order through Binance API, the quantity I have to put is the BTC amount (right?). So to get BTC quantity I have to divide 100 USDT with the current market price. So should I compare this BTC quantity with the minQty in LOT_SIZE?

In contrast, if I want to sell BTC for USDT, I have to put BTC amount as quantity (right?). So should I compare this BTC quantity with minQty or with the amount of USDT I’ll get?

In the same way, MIN_NOTIONAL value’s quantity is the quantity of which asset?

Another issue I’m facing is with stepSize. I’m getting modulo value not equal to 0 all the time. What I did was, take the decimal places of minQty. Used that decimal places to round off the quantity value. Then calculated (quantity - minQty) & stepSize. And it doesn’t equal to zero. Therefore, throws LOT_SIZE error.

I am really sorry for posting so many queries altogether. These things have been putting me into frustration because I couldn’t find any proper explanation. I hope you or someone here could help me clear out the confusion.

It’d be a big help.

Your understanding is correct.
For the rest of the points:
3. No matter you are selling or buying, the calculation is the same since you cannot find a symbol called “USDTBTC”. It’s always “BTCUSDT”.
4. n is a non-negative integer, e.g. 0, 1, 2, 3… Your quantity set per order should satisfy the condition
minQty < quantity = minQty + n * stepSize < maxQty

Mate, I have understood everything you said. But while I try to implement stepSize I get a weird error. And stepSize is the only issue right now.

So I’m trying to check stepSize for SOLBTC pair which has LOT_SIZE filter:

{
        filterType: "LOT_SIZE", 
        minQty: "0.10000000", 
        maxQty: "90000000.00000000", 
        stepSize: "0.10000000"
} 

and a base precision of 8.

So to execute a test order I do this:

const orderExecution = await bRest.testOrder({
        "symbol": "SOLBTC",
        "type": "LIMIT",
        "side": "BUY",
        "quantity": "0.3", // this is SOL amount I'm willing to buy
        "timeInForce": "GTC",
        "price": "0.000425"
 });

The order goes through perfectly. But I shouldn’t place an order without checking for stepSize, minQty or maxQty. So what I did was check this:

let quantity   = Number('0.3');
let minQty     = Number('0.10000000');
let stepSize   = Number('0.10000000');

if ( parseFloat((( quantity - minQty ) % stepSize ).toFixed(8) )  !== 0 ) {
    console.log('stepsize error...');
}

The quantity here is 0.3 which is a correct quantity value as the order goes through. But I still get that console statement. Isn’t that conditional supposed to be exactly zero if it is a correct quantity amount? What am I doing wrong?

This is a coding question, please avoid asking this here, thanks.

For your issue, please check on JavaScript Number’s characteristic. Floating point arithmetic is not always accurate. To demonstrate it, try printing out the result of quantity - minQty on console.

1 Like

Understood mate. I’ll try it out.

And thank you so much for all your help.

Finally the solution for this is the next:
If we have this:

 {
      'filterType': 'LOT_SIZE',
      'minQty': '0.01000000',
      'maxQty': '90000.00000000',
      'stepSize': '0.01000000'
},

that means that with a quantity of 0.011 will fail

in python to solve this do the next:

filters = info['filters']
minQty = float(list(filter(lambda x: x['filterType'] == 'LOT_SIZE', filters))[0]['minQty'])
precision = str(minQty)[::-1].find('.')
quantity = round(quantity, precision)

That will fix everything