This example will use
NOTE:
- This sample will attemp to create marker order (usually with lower fee), thus need to handle complex scenario like order would immediately match (maker order becomes taker order), order would not match after certain duration (price too high or too low) and order partially match.
- Binance REST API to query order status usually delay by 1 to 5 seconds, and could delay up to minutes during super peak session. Binance Websocket Stream is more reliable to get latest order status.
Setup
import asyncioimport binance_clientfrom unicorn_binance_websocket_api.unicorn_binance_websocket_api_manager import BinanceWebSocketApiManagerBINANCE_API_KEY = ...BINANCE_SECRET_KEY = ...running = Truefind_orders = {}
Helper functions
async def create_taker_order(binance, symbol, side): # try to place marker order order_id = None while not order_id: prices = await binance.get_price(symbol=symbol) price = float(prices['price']) # adjust price lower/higher to prevent immediate match if side == 'buy': price *= 0.9995 elif side == 'sell': price *= 1.0005 # buy BUSD 12 worth of BTC quantity = 12 / price price = f"{price:.2f}" quantity = f"{ quantity:.6f}" print('price', price, 'quantity', quantity) try: data = await binance.order_limit_maker(symbol=symbol, side=side, quantity=quantity, price=price) order_id = data['orderId'] print('order_id', order_id) except binance_client.BinanceException as e: if e.code == -2010 and e.msg == 'Order would immediately match and take.': await asyncio.sleep(1) else: raise e return order_id
async def check_order(binance, symbol, order_id): loop_count = 0 while True: # try to get order status status = None while not status: try: # check websocket order data data = find_orders.get(order_id) if data: print('order data from websocket') data = data[-1] # get the latest update if not data: # check order data via api print('order data from api') data = await binance.query_order(symbol=symbol, order_id=order_id) if data: status = data['status'] print('status', status) else: await asyncio.sleep(1) except binance_client.BinanceException as e: if e.code == -2013 and e.msg == 'Order does not exist.': await asyncio.sleep(1) else: raise e if status in ['FILLED', 'REJECTED', 'EXPIRED']: # 'CANCELED', 'PENDING_CANCEL', print('success', status) return True loop_count += 1 if loop_count > 10: if status in ['PARTIALLY_FILLED']: print('partial', status) return True data = await binance.cancel_order(symbol=symbol, order_id=order_id) status = data['status'] print('cancel', status) return False await asyncio.sleep(1)
Main
async def binance_websocket(): binance_websocket_api_manager = BinanceWebSocketApiManager() binance_websocket_api_manager.create_stream('arr', '!userData', api_key=BINANCE_API_KEY, stream_label="UnicornFy", output="UnicornFy") while running: if binance_websocket_api_manager.is_manager_stopping(): break oldest_stream_data_from_stream_buffer = binance_websocket_api_manager.pop_stream_data_from_stream_buffer() if oldest_stream_data_from_stream_buffer: stream = oldest_stream_data_from_stream_buffer if 'event_type' in stream: if stream['event_type'] == 'executionReport': order_id = stream['order_id'] orders = find_orders.get(order_id) if not orders: orders = [] find_orders[order_id] = orders # try to conver to query_order format orders.append({ 'clientOrderId': stream['client_order_id'], # 'cummulativeQuoteQty': 'executedQty': stream['last_executed_quantity'], 'icebergQty': stream['iceberg_quantity'], 'orderId': order_id, 'origQty': stream['order_quantity'], # 'origQuoteOrderQty': 'price': stream['order_price'], 'side': stream['side'], 'status': stream['current_order_status'], 'symbol': stream['symbol'], 'time': stream['order_creation_time'], 'updateTime': stream['transaction_time'], 'eventTime': stream['event_time'], 'source': 'userData' }) print('find_orders', len(find_orders)) else: print('event_type', stream['event_type']) else: await asyncio.sleep(1) binance_websocket_api_manager.stop_manager_with_all_streams() print('binance_websocket END')async def binance_order(): global running binance = binance_client.BinanceClientAsync(api_key=BINANCE_API_KEY, secret_key= BINANCE_SECRET_KEY) # binance_helper = binance_client.BinanceHelper(client=binance) symbol = 'BTCBUSD' side = 'buy' # wait binance_websocket start, else order data not received in time print('wait ...') await asyncio.sleep(5) try: result = False while not result: order_id = await create_taker_order(binance, symbol, side) result = await check_order(binance, symbol, order_id) print('result', result) except binance_client.BinanceException as e: print(e) await binance.close() running = False print('binance_order END')async def main(): tasks = [binance_websocket(), binance_order()] await asyncio.gather(*tasks)if __name__ == "__main__": asyncio.run(main())