pythoncryptocurrencykucoin

Order failed: 200-{"msg":"Funds increment invalid.","code":"400100"}


I'm using the kucoin api to check what is my USDT balance and purchase its equivalent in Bitcoin using Python 3.12.3

Now if I understand correctly there might be two problems:

To solve these two problems, I leave a buffer of 0.01 USDT and I make sure that the trade amount is a multiple of the quote increment. You can see this in the below code:

from kucoin.client import Trade, User, Market

# Replace with your actual API credentials
api_key = 'my key'
api_secret = 'my secret'
api_passphrase = 'my passphrase'

# Initialize the KuCoin clients
trade_client = Trade(key=api_key, secret=api_secret, passphrase=api_passphrase)
user_client = User(key=api_key, secret=api_secret, passphrase=api_passphrase)
market_client = Market(key=api_key, secret=api_secret, passphrase=api_passphrase)

# Get account balances
account_balances = user_client.get_account_list()

# Find the USDT balance
usdt_balance = next((item for item in account_balances if item['currency'] == 'USDT' and item['type'] == 'trade'), None)

# Check if there is enough USDT balance
if usdt_balance and float(usdt_balance['balance']) > 0:
    total_usdt_amount = float(usdt_balance['balance'])
    buffer_amount = 0.01  # Leaving 0.01 USDT as buffer
    usdt_amount = total_usdt_amount - buffer_amount
    
    # Get the symbol info to find the quote increment and minimum size
    symbol_info = market_client.get_symbol_list()
    btc_usdt_info = next(item for item in symbol_info if item['symbol'] == 'BTC-USDT')
    quote_increment = float(btc_usdt_info['quoteIncrement'])
    quote_min_size = float(btc_usdt_info['quoteMinSize'])
    
    # Adjust USDT amount to be a multiple of quote_increment
    usdt_amount = (usdt_amount // quote_increment) * quote_increment

    if usdt_amount < quote_min_size:
        print(f"Order amount is too small, minimum required is {quote_min_size} USDT")
    else:
        # Create the market order to trade all USDT for BTC
        try:
            order = trade_client.create_market_order('BTC-USDT', 'buy', funds=str(usdt_amount))
            print(f"Order successful: Traded {usdt_amount} USDT for BTC")
        except Exception as e:
            print(f"Order failed: {e}")
else:
    print("Insufficient USDT balance or USDT balance not found")

Like you can see, I update the amount this way:

usdt_amount = (usdt_amount // quote_increment) * quote_increment

Which I thought it was correct, but probably I'm missing something because it gives me this error:

Order failed: 200-{"msg":"Funds increment invalid.","code":"400100"}

Solution

  • Canonical Answer

    Your problem likely stems from using floating point numbers, which are not precisely accurate, so instead of 19.99 you probably have 19.990000000000002, for example. That's what I got trying your solution in a python interpreter:

    >>> funds = 20
    >>> increment = float(0.01)
    >>> (funds // increment) * increment
    19.990000000000002
    

    You just need to round the number to the nearest hundreth, which you can do using round(), passing 2 as the second argument to round to 2 decimal places:

    >>> round((funds // increment) * increment, 2)
    19.99
    

    Case-Specific Answer

    Since the increment changes, you can't always use 2 as the second argument, but since quoteIncrement is given as a string from the API, you could just look at its length to determine what the argument should be. You don't need division at all this way:

    >>> funds = 20.00023230234234
    >>> quoteIncrement = "0.000001"
    >>> len(quoteIncrement) - 2  # subtract 2 for the initial `0.`
    6
    >>> round(funds, len(quoteIncrement) - 2)
    20.000232