Skip to content

Commit

Permalink
futues WS API
Browse files Browse the repository at this point in the history
  • Loading branch information
oliver-zehentleitner committed Nov 8, 2024
1 parent adea2bc commit 497ed6a
Show file tree
Hide file tree
Showing 14 changed files with 215 additions and 22 deletions.
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,14 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p

[How to upgrade to the latest version!](https://unicorn-binance-websocket-api.docs.lucit.tech/readme.html#installation-and-upgrade)

## 2.8.1.dev (development stage/unreleased/unstable)
## 2.9.0.dev (development stage/unreleased/unstable)

## 2.9.0
### Added
- Support for 'binance.com-futures' WebSocket API.
- Error handling if someone tries to use the WebSocket API Feature with an unsupported exchange.
### Fixed
- Type Error of returned value of `api.create_order()` and `api.create_test_order()`.

## 2.8.1
### Changed
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -290,8 +290,8 @@ Use the [UNICORN Binance REST API](https://www.lucit.tech/unicorn-binance-rest-a
| [Binance Margin Testnet](https://testnet.binance.vision/) | `binance.com-margin-testnet` | ![yes](https://raw.githubusercontent.com/lucit-systems-and-development/unicorn-binance-websocket-api/master/images/misc/ok-icon.png) | ![no](https://raw.githubusercontent.com/lucit-systems-and-development/unicorn-binance-websocket-api/master/images/misc/x-icon.png) |
| [Binance Isolated Margin](https://www.binance.com) | `binance.com-isolated_margin` | ![yes](https://raw.githubusercontent.com/lucit-systems-and-development/unicorn-binance-websocket-api/master/images/misc/ok-icon.png) | ![no](https://raw.githubusercontent.com/lucit-systems-and-development/unicorn-binance-websocket-api/master/images/misc/x-icon.png) |
| [Binance Isolated Margin Testnet](https://testnet.binance.vision/) | `binance.com-isolated_margin-testnet` | ![yes](https://raw.githubusercontent.com/lucit-systems-and-development/unicorn-binance-websocket-api/master/images/misc/ok-icon.png) | ![no](https://raw.githubusercontent.com/lucit-systems-and-development/unicorn-binance-websocket-api/master/images/misc/x-icon.png) |
| [Binance USD-M Futures](https://www.binance.com) | `binance.com-futures` | ![yes](https://raw.githubusercontent.com/lucit-systems-and-development/unicorn-binance-websocket-api/master/images/misc/ok-icon.png) | ![no](https://raw.githubusercontent.com/lucit-systems-and-development/unicorn-binance-websocket-api/master/images/misc/x-icon.png) |
| [Binance USD-M Futures Testnet](https://testnet.binancefuture.com) | `binance.com-futures-testnet` | ![yes](https://raw.githubusercontent.com/lucit-systems-and-development/unicorn-binance-websocket-api/master/images/misc/ok-icon.png) | ![no](https://raw.githubusercontent.com/lucit-systems-and-development/unicorn-binance-websocket-api/master/images/misc/x-icon.png) |
| [Binance USD-M Futures](https://www.binance.com) | `binance.com-futures` | ![yes](https://raw.githubusercontent.com/lucit-systems-and-development/unicorn-binance-websocket-api/master/images/misc/ok-icon.png) | ![yes](https://raw.githubusercontent.com/lucit-systems-and-development/unicorn-binance-websocket-api/master/images/misc/ok-icon.png) |
| [Binance USD-M Futures Testnet](https://testnet.binancefuture.com) | `binance.com-futures-testnet` | ![yes](https://raw.githubusercontent.com/lucit-systems-and-development/unicorn-binance-websocket-api/master/images/misc/ok-icon.png) | ![yes](https://raw.githubusercontent.com/lucit-systems-and-development/unicorn-binance-websocket-api/master/images/misc/ok-icon.png) |
| [Binance Coin-M Futures](https://www.binance.com) | `binance.com-coin_futures` | ![yes](https://raw.githubusercontent.com/lucit-systems-and-development/unicorn-binance-websocket-api/master/images/misc/ok-icon.png) | ![no](https://raw.githubusercontent.com/lucit-systems-and-development/unicorn-binance-websocket-api/master/images/misc/x-icon.png) |
| [Binance US](https://www.binance.us) | `binance.us` | ![yes](https://raw.githubusercontent.com/lucit-systems-and-development/unicorn-binance-websocket-api/master/images/misc/ok-icon.png) | ![no](https://raw.githubusercontent.com/lucit-systems-and-development/unicorn-binance-websocket-api/master/images/misc/x-icon.png) |
| [Binance TR](https://www.trbinance.com) | `trbinance.com` | ![yes](https://raw.githubusercontent.com/lucit-systems-and-development/unicorn-binance-websocket-api/master/images/misc/ok-icon.png) | ![no](https://raw.githubusercontent.com/lucit-systems-and-development/unicorn-binance-websocket-api/master/images/misc/x-icon.png) |
Expand Down
59 changes: 59 additions & 0 deletions binance_websocket_api_futures.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ¯\_(ツ)_/¯

from unicorn_binance_websocket_api import BinanceWebSocketApiManager
import asyncio
import logging
import os

api_key = ""
api_secret = ""


async def binance_stream(ubwa):
async def handle_socket_message(stream_id=None):
while ubwa.is_stop_request(stream_id=stream_id) is False:
data = await ubwa.get_stream_data_from_asyncio_queue(stream_id=stream_id)
print(f"received data:\r\n{data}\r\n")

api_stream = ubwa.create_stream(api=True, api_key=api_key, api_secret=api_secret,
stream_label="Bobs Websocket API",
process_asyncio_queue=handle_socket_message)
print(f"Start:")
ubwa.api.get_listen_key(stream_id=api_stream)
ubwa.api.get_server_time(stream_id=api_stream)
ubwa.api.get_account_status(stream_id=api_stream)
orig_client_order_id = ubwa.api.create_order(stream_id=api_stream, price=1.0, order_type="LIMIT",
quantity=15.0, side="SELL", symbol="BUSDUSDT")
ubwa.api.create_test_order(stream_id=api_stream, price=1.2, order_type="LIMIT",
quantity=12.0, side="SELL", symbol="BUSDUSDT")
ubwa.api.ping(stream_id=api_stream)
ubwa.api.get_exchange_info(stream_id=api_stream, symbols=['BUSDUSDT'])
ubwa.api.get_order_book(stream_id=api_stream, symbol="BUSDUSDT", limit=2)
ubwa.api.cancel_order(stream_id=api_stream, symbol="BUSDUSDT", orig_client_order_id=orig_client_order_id)
ubwa.api.get_open_orders(stream_id=api_stream, symbol="BUSDUSDT")
ubwa.api.get_open_orders(stream_id=api_stream)
ubwa.api.cancel_open_orders(stream_id=api_stream, symbol="BUSDUSDT")
ubwa.api.get_order(stream_id=api_stream, symbol="BUSDUSDT", orig_client_order_id=orig_client_order_id)

print(f"Finished! Waiting for responses:")
await asyncio.sleep(5)

print(f"Stopping!")
ubwa.stop_manager()

if __name__ == "__main__":
logging.basicConfig(level=logging.DEBUG,
filename=os.path.basename(__file__) + '.log',
format="{asctime} [{levelname:8}] {process} {thread} {module}: {message}",
style="{")

# To use this library you need a valid UNICORN Binance Suite License:
# https://shop.lucit.services
ubwa = BinanceWebSocketApiManager(exchange='binance.com-futures')
try:
asyncio.run(binance_stream(ubwa))
except KeyboardInterrupt:
print("\r\nGracefully stopping the websocket manager...")
ubwa.stop_manager()
2 changes: 1 addition & 1 deletion dev/test_websocket_api_orders.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# File: example_websocket_api.py
# File: binance_websocket_api_futures.py
#
# Part of ‘UNICORN Binance WebSocket API’
# Project website: https://www.lucit.tech/unicorn-binance-websocket-api.html
Expand Down
2 changes: 1 addition & 1 deletion dev/test_websocket_api_speed.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# File: example_websocket_api.py
# File: binance_websocket_api_futures.py
#
# Part of ‘UNICORN Binance WebSocket API’
# Project website: https://www.lucit.tech/unicorn-binance-websocket-api.html
Expand Down
2 changes: 1 addition & 1 deletion examples/_archive/example_websocket_api.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# File: example_websocket_api.py
# File: binance_websocket_api_futures.py
#
# Part of ‘UNICORN Binance WebSocket API’
# Project website: https://www.lucit.tech/unicorn-binance-websocket-api.html
Expand Down
30 changes: 30 additions & 0 deletions examples/binance_websocket_api_futures/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Binance WebSocket API
## Overview
A best practice example for websockets to Binance in Python.

## Prerequisites
Ensure you have Python 3.7+ installed on your system.

Before running the provided script, install the required Python packages:
```bash
pip install -r requirements.txt
```
## Get a UNICORN Binance Suite License
To run modules of the *UNICORN Binance Suite* you need a [valid license](https://shop.lucit.services)!

## Usage
### Running the Script:
```bash
python binance_chain_websocket_best_practice.py
```

### Graceful Shutdown:
The script is designed to handle a graceful shutdown upon receiving a KeyboardInterrupt (e.g., Ctrl+C) or encountering
an unexpected exception.

## Logging
The script employs logging to provide insights into its operation and to assist in troubleshooting. Logs are saved to a
file named after the script with a .log extension.

For further assistance or to report issues, please [contact our support team](https://www.lucit.tech/get-support.html)
or [visit our GitHub repository](https://github.com/LUCIT-Systems-and-Development/unicorn-binance-websocket-api).
1 change: 1 addition & 0 deletions examples/binance_websocket_api_futures/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
unicorn-binance-websocket-api
30 changes: 30 additions & 0 deletions examples/binance_websocket_api_spot/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Binance WebSocket API
## Overview
A best practice example for websockets to Binance in Python.

## Prerequisites
Ensure you have Python 3.7+ installed on your system.

Before running the provided script, install the required Python packages:
```bash
pip install -r requirements.txt
```
## Get a UNICORN Binance Suite License
To run modules of the *UNICORN Binance Suite* you need a [valid license](https://shop.lucit.services)!

## Usage
### Running the Script:
```bash
python binance_chain_websocket_best_practice.py
```

### Graceful Shutdown:
The script is designed to handle a graceful shutdown upon receiving a KeyboardInterrupt (e.g., Ctrl+C) or encountering
an unexpected exception.

## Logging
The script employs logging to provide insights into its operation and to assist in troubleshooting. Logs are saved to a
file named after the script with a .log extension.

For further assistance or to report issues, please [contact our support team](https://www.lucit.tech/get-support.html)
or [visit our GitHub repository](https://github.com/LUCIT-Systems-and-Development/unicorn-binance-websocket-api).
59 changes: 59 additions & 0 deletions examples/binance_websocket_api_spot/binance_websocket_api_spot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ¯\_(ツ)_/¯

from unicorn_binance_websocket_api import BinanceWebSocketApiManager
import asyncio
import logging
import os

api_key = ""
api_secret = ""


async def binance_stream(ubwa):
async def handle_socket_message(stream_id=None):
while ubwa.is_stop_request(stream_id=stream_id) is False:
data = await ubwa.get_stream_data_from_asyncio_queue(stream_id=stream_id)
print(f"received data:\r\n{data}\r\n")

api_stream = ubwa.create_stream(api=True, api_key=api_key, api_secret=api_secret,
stream_label="Bobs Websocket API",
process_asyncio_queue=handle_socket_message)
print(f"Start:")
ubwa.api.get_listen_key(stream_id=api_stream)
ubwa.api.get_server_time(stream_id=api_stream)
ubwa.api.get_account_status(stream_id=api_stream)
orig_client_order_id = ubwa.api.create_order(stream_id=api_stream, price=1.0, order_type="LIMIT",
quantity=15.0, side="SELL", symbol="BUSDUSDT")
ubwa.api.create_test_order(stream_id=api_stream, price=1.2, order_type="LIMIT",
quantity=12.0, side="SELL", symbol="BUSDUSDT")
ubwa.api.ping(stream_id=api_stream)
ubwa.api.get_exchange_info(stream_id=api_stream, symbols=['BUSDUSDT'])
ubwa.api.get_order_book(stream_id=api_stream, symbol="BUSDUSDT", limit=2)
ubwa.api.cancel_order(stream_id=api_stream, symbol="BUSDUSDT", orig_client_order_id=orig_client_order_id)
ubwa.api.get_open_orders(stream_id=api_stream, symbol="BUSDUSDT")
ubwa.api.get_open_orders(stream_id=api_stream)
ubwa.api.cancel_open_orders(stream_id=api_stream, symbol="BUSDUSDT")
ubwa.api.get_order(stream_id=api_stream, symbol="BUSDUSDT", orig_client_order_id=orig_client_order_id)

print(f"Finished! Waiting for responses:")
await asyncio.sleep(5)

print(f"Stopping!")
ubwa.stop_manager()

if __name__ == "__main__":
logging.basicConfig(level=logging.DEBUG,
filename=os.path.basename(__file__) + '.log',
format="{asctime} [{levelname:8}] {process} {thread} {module}: {message}",
style="{")

# To use this library you need a valid UNICORN Binance Suite License:
# https://shop.lucit.services
ubwa = BinanceWebSocketApiManager(exchange='binance.com')
try:
asyncio.run(binance_stream(ubwa))
except KeyboardInterrupt:
print("\r\nGracefully stopping the websocket manager...")
ubwa.stop_manager()
1 change: 1 addition & 0 deletions examples/binance_websocket_api_spot/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
unicorn-binance-websocket-api
11 changes: 6 additions & 5 deletions unicorn_binance_websocket_api/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ def create_order(self, iceberg_qty: float = None,
symbol: str = None,
time_in_force: Optional[Literal['GTC', 'IOC', 'FOK']] = "GTC",
test: bool = False,
trailing_delta: int = None) -> Union[int, bool]:
trailing_delta: int = None) -> Union[str, bool]:
"""
Create a new order.
Expand Down Expand Up @@ -546,7 +546,8 @@ def create_order(self, iceberg_qty: float = None,
:param trailing_delta: For more details on SPOT implementation on trailing stops, please refer to
`Trailing Stop FAQ <https://github.com/binance/binance-spot-api-docs/blob/master/faqs/trailing-stop-faq.md>`__
:type trailing_delta: int
:return: `False` or `orig_client_order_id`
:return: `False` (bool) or `orig_client_order_id` (str)
Message sent:
Expand Down Expand Up @@ -617,7 +618,7 @@ def create_order(self, iceberg_qty: float = None,
f"found!")
return False

new_client_order_id = new_client_order_id if new_client_order_id is not None else self.manager.get_request_id()
new_client_order_id = new_client_order_id if new_client_order_id is not None else str(self.manager.get_request_id())
params = {"apiKey": self.manager.stream_list[stream_id]['api_key'],
"newClientOrderId": new_client_order_id,
"quantity": quantity,
Expand Down Expand Up @@ -712,7 +713,7 @@ def create_test_order(self, iceberg_qty: float = None,
stream_label: str = None,
symbol: str = None,
time_in_force: Optional[Literal['GTC', 'IOC', 'FOK']] = "GTC",
trailing_delta: int = None) -> Union[int, bool]:
trailing_delta: int = None) -> Union[str, bool]:
"""
Test order placement.
Expand Down Expand Up @@ -814,7 +815,7 @@ def create_test_order(self, iceberg_qty: float = None,
`Trailing Stop FAQ <https://github.com/binance/binance-spot-api-docs/blob/master/faqs/trailing-stop-faq.md>`__
:type trailing_delta: int
:return: `False` or `orig_client_order_id`
:return: `False` (bool) or `orig_client_order_id` (str)
Message sent:
Expand Down
22 changes: 11 additions & 11 deletions unicorn_binance_websocket_api/connection_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,15 @@ class Exchanges(str, Enum):
CONNECTION_SETTINGS = {
Exchanges.BINANCE: (1024, "wss://stream.binance.com:9443/", "wss://ws-api.binance.com/ws-api/v3"),
Exchanges.BINANCE_TESTNET: (1024, "wss://testnet.binance.vision/", "wss://testnet.binance.vision/ws-api/v3"),
Exchanges.BINANCE_MARGIN: (1024, "wss://stream.binance.com:9443/", ""),
Exchanges.BINANCE_MARGIN_TESTNET: (1024, "wss://testnet.binance.vision/", ""),
Exchanges.BINANCE_ISOLATED_MARGIN: (1024, "wss://stream.binance.com:9443/", ""),
Exchanges.BINANCE_ISOLATED_MARGIN_TESTNET: (1024, "wss://testnet.binance.vision/", ""),
Exchanges.BINANCE_FUTURES: (200, "wss://fstream.binance.com/", ""),
Exchanges.BINANCE_FUTURES_TESTNET: (200, "wss://stream.binancefuture.com/", ""),
Exchanges.BINANCE_COIN_FUTURES: (200, "wss://dstream.binance.com/", ""),
Exchanges.BINANCE_US: (1024, "wss://stream.binance.us:9443/", ""),
Exchanges.TRBINANCE: (1024, "wss://stream-cloud.trbinance.com/", ""),
Exchanges.BINANCE_ORG: (1024, "wss://dex.binance.org/api/", ""),
Exchanges.BINANCE_ORG_TESTNET: (1024, "wss://testnet-dex.binance.org/api/", ""),
Exchanges.BINANCE_MARGIN: (1024, "wss://stream.binance.com:9443/", None),
Exchanges.BINANCE_MARGIN_TESTNET: (1024, "wss://testnet.binance.vision/", None),
Exchanges.BINANCE_ISOLATED_MARGIN: (1024, "wss://stream.binance.com:9443/", None),
Exchanges.BINANCE_ISOLATED_MARGIN_TESTNET: (1024, "wss://testnet.binance.vision/", None),
Exchanges.BINANCE_FUTURES: (200, "wss://fstream.binance.com/", "wss://ws-fapi.binance.com/ws-fapi/v1"),
Exchanges.BINANCE_FUTURES_TESTNET: (200, "wss://stream.binancefuture.com/", "wss://testnet.binancefuture.com/ws-fapi/v1"),
Exchanges.BINANCE_COIN_FUTURES: (200, "wss://dstream.binance.com/", None),
Exchanges.BINANCE_US: (1024, "wss://stream.binance.us:9443/", None),
Exchanges.TRBINANCE: (1024, "wss://stream-cloud.trbinance.com/", None),
Exchanges.BINANCE_ORG: (1024, "wss://dex.binance.org/api/", None),
Exchanges.BINANCE_ORG_TESTNET: (1024, "wss://testnet-dex.binance.org/api/", None),
}
5 changes: 5 additions & 0 deletions unicorn_binance_websocket_api/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -1920,6 +1920,11 @@ def create_websocket_uri(self, channels, markets, stream_id=None, symbols=None,
:return: str or False
"""
if api is not False:
if self.websocket_api_base_uri is None:
error_msg = (f"BinanceWebSocketApiManager() - The WebSocket API feature is not supported for exchange "
f"'{self.exchange}' - Missing a valid `websocket_api_base_uri`")
logger.critical(error_msg)
raise ValueError(error_msg)
logger.info("BinanceWebSocketApiManager.create_websocket_uri(" + str(channels) + ", " +
str(markets) + ", " + ", " + str(symbols) + ", " + str(api) + ") - Created websocket URI for "
"stream_id=" + str(stream_id) + " is " + self.websocket_api_base_uri)
Expand Down

0 comments on commit 497ed6a

Please sign in to comment.