thanks for taking the time to check out my issue. I'm struggling to place orders using python-binance, specifically a perpetual futures market order. I don't believe this is a duplicate on here but there have been several queries around the same error code on python-binance (as well as other packages so I don't believe it's a python-binance issue, it's an issue with my understanding), unfortunately, none seem to have a successful resolution.
https://github.com/sammchardy/python-binance/issues/57
https://github.com/sammchardy/python-binance/issues/184
The error code intimates that the precision is over the maximum allowed for that symbol. As far as I'm aware (or at least for the instruments I'm interested in) the baseAssetPrecision is always 8. However, each instrument also has a tickSize which varies.
from binance.client import Client
from binance.enums import *
from binance.exceptions import BinanceAPIException, BinanceOrderException
from decimal import Decimal
api_key = 'YOURAPIKEY'
api_secret = 'YOURAPISECRET'
client = Client(api_key, api_secret)
#tick_size = {'BTCUSDT': 6, 'ETHUSDT': 5, 'XRPUSDT': 1, 'LINKUSDT': 2}
trade_size = 10 # The trade size we want in USDT
sym = 'BTCUSDT' # the symbol we want to place a market order on
tick_size = 6 # the tick_size as per binance API docs
price = 19000 # Just making this up for now to exemplify, this is fetched within the script
trade_quantity = trade_size / price # Work out how much BTC to order
trade_quantity_str = "{:0.0{}f}".format(trade_quantity, tick_size)
#print(trade_quantity_str)
#0.000526
#PLACING THE ORDER
client.futures_create_order(symbol=sym, side='BUY', type='MARKET', quantity=trade_quantity)
Results in...
BinanceAPIException: APIError(code=-1111): Precision is over the maximum defined for this asset.
I have also tried including Decimal but to no avail.
This has been the bane of my life for the last 2 days, any help would be gladly appreciated. If I've not included details that could help, please let me know.
EDIT: I have an unsatisfactory solution to this which is to manually check the allowed position sizes via binance. In doing so I discovered that the required precision is vastly different to what is returned when requesting symbol info via the API.
For example, when requesting info:
sym = 'BTCUSDT'
info = client.get_symbol_info(sym)
print(info)
it returns (at the time of writing):
{'symbol': 'BTCUSDT', 'status': 'TRADING', 'baseAsset': 'BTC', 'baseAssetPrecision': 8, 'quoteAsset': 'USDT', 'quotePrecision': 8, 'quoteAssetPrecision': 8, 'baseCommissionPrecision': 8, 'quoteCommissionPrecision': 8, 'orderTypes': ['LIMIT', 'LIMIT_MAKER', 'MARKET', 'STOP_LOSS_LIMIT', 'TAKE_PROFIT_LIMIT'], 'icebergAllowed': True, 'ocoAllowed': True, 'quoteOrderQtyMarketAllowed': True, 'isSpotTradingAllowed': True, 'isMarginTradingAllowed': True, 'filters': [{'filterType': 'PRICE_FILTER', 'minPrice': '0.01000000', 'maxPrice': '1000000.00000000', 'tickSize': '0.01000000'}, {'filterType': 'PERCENT_PRICE', 'multiplierUp': '5', 'multiplierDown': '0.2', 'avgPriceMins': 5}, {'filterType': 'LOT_SIZE', 'minQty': '0.00000100', 'maxQty': '9000.00000000', 'stepSize': '0.00000100'}, {'filterType': 'MIN_NOTIONAL', 'minNotional': '10.00000000', 'applyToMarket': True, 'avgPriceMins': 5}, {'filterType': 'ICEBERG_PARTS', 'limit': 10}, {'filterType': 'MARKET_LOT_SIZE', 'minQty': '0.00000000', 'maxQty': '247.36508140', 'stepSize': '0.00000000'}, {'filterType': 'MAX_NUM_ORDERS', 'maxNumOrders': 200}, {'filterType': 'MAX_NUM_ALGO_ORDERS', 'maxNumAlgoOrders': 5}], 'permissions': ['SPOT', 'MARGIN']}
However, by checking on binance manually, I can see that it only allows trades up to three decimal places... I can't see how this could be arrived at by using the returned info above.
***** EDIT 2 ******
Thanks to the responses below I've put together a solution which works well enough for what I need
from binance.client import Client
from binance.enums import *
from binance.exceptions import BinanceAPIException, BinanceOrderException
from decimal import Decimal
api_key = 'YOURAPIKEY'
api_secret = 'YOURAPISECRET'
client = Client(api_key, api_secret)
info = client.futures_exchange_info() # request info on all futures symbols
for item in info['symbols']:
symbols_n_precision[item['symbol']] = item['quantityPrecision'] # not really necessary but here we are...
# Example $100 of BTCUSDT
trade_size_in_dollars = 100
symbol = "BTCUSDT"
price = 55000 # For example
order_amount = trade_size_in_dollars / price # size of order in BTC
precision = symbols_n_precision[symbol] # the binance-required level of precision
precise_order_amount = "{:0.0{}f}".format(order_amount, precision) # string of precise order amount that can be used when creating order
Thanks for the help everyone!
Instead use hardcode precision, you can call api to retrieve the stepSize:
symbol_info = client.get_symbol_info('BTCUSDT')
step_size = 0.0
for f in symbol_info['filters']:
if f['filterType'] == 'LOT_SIZE':
step_size = float(f['stepSize'])
precision = int(round(-math.log(stepSize, 10), 0))
quantity = float(round(quantity, precision))
client.futures_create_order(symbol=sym, side='BUY', type='MARKET', quantity=quantity)