Skip to content

Commit 8a1319e

Browse files
authored
Merge branch 'master' into master
2 parents 2ce45f7 + afefe8b commit 8a1319e

8 files changed

Lines changed: 1690 additions & 121 deletions

File tree

Endpoints.md

Lines changed: 778 additions & 0 deletions
Large diffs are not rendered by default.

README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ I would appreciate if you could try out the `feature/asyncio <https://github.com
2828
.. image:: https://img.shields.io/pypi/pyversions/python-binance.svg
2929
:target: https://pypi.python.org/pypi/python-binance
3030

31-
This is an unofficial Python wrapper for the `Binance exchange REST API v1/3 <https://github.com/binance-exchange/binance-official-api-docs>`_. I am in no way affiliated with Binance, use at your own risk.
31+
This is an unofficial Python wrapper for the `Binance exchange REST API v3 <https://github.com/binance/binance-spot-api-docs>`_. I am in no way affiliated with Binance, use at your own risk.
3232

3333
If you came here looking for the `Binance exchange <https://www.binance.com/?ref=10099792>`_ to purchase cryptocurrencies, then `go here <https://www.binance.com/?ref=10099792>`_. If you want to automate interactions with Binance stick around.
3434

binance/client.py

Lines changed: 639 additions & 92 deletions
Large diffs are not rendered by default.

binance/depthcache.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,3 +274,10 @@ def close(self, close_socket=False):
274274
self._bm.close()
275275
time.sleep(1)
276276
self._depth_cache = None
277+
278+
def get_symbol(self):
279+
"""Get the symbol
280+
281+
:return: symbol
282+
"""
283+
return self._symbol

binance/websockets.py

Lines changed: 155 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ def clientConnectionLost(self, connector, reason):
6464
class BinanceSocketManager(threading.Thread):
6565

6666
STREAM_URL = 'wss://stream.binance.com:9443/'
67+
FSTREAM_URL = 'wss://fstream.binance.com/'
6768

6869
WEBSOCKET_DEPTH_5 = '5'
6970
WEBSOCKET_DEPTH_10 = '10'
@@ -84,9 +85,10 @@ def __init__(self, client, user_timeout=DEFAULT_USER_TIMEOUT):
8485
self._conns = {}
8586
self._client = client
8687
self._user_timeout = user_timeout
87-
self._timers = {'user': None, 'margin': None}
88+
self._timers = {'user': None, 'margin': None}
8889
self._listen_keys = {'user': None, 'margin': None}
8990
self._account_callbacks = {'user': None, 'margin': None}
91+
# Isolated margin sockets will be opened under the 'symbol' name
9092

9193
def _start_socket(self, path, callback, prefix='ws/'):
9294
if path in self._conns:
@@ -102,6 +104,20 @@ def _start_socket(self, path, callback, prefix='ws/'):
102104
self._conns[path] = connectWS(factory, context_factory)
103105
return path
104106

107+
def _start_futures_socket(self, path, callback, prefix='stream?streams='):
108+
if path in self._conns:
109+
return False
110+
111+
factory_url = self.FSTREAM_URL + prefix + path
112+
factory = BinanceClientFactory(factory_url)
113+
factory.protocol = BinanceClientProtocol
114+
factory.callback = callback
115+
factory.reconnect = True
116+
context_factory = ssl.ClientContextFactory()
117+
118+
self._conns[path] = connectWS(factory, context_factory)
119+
return path
120+
105121
def start_depth_socket(self, symbol, callback, depth=None, interval=None):
106122
"""Start a websocket for symbol market depth returning either a diff or a partial book
107123
@@ -413,6 +429,99 @@ def start_ticker_socket(self, callback):
413429
"""
414430
return self._start_socket('!ticker@arr', callback)
415431

432+
def start_symbol_mark_price_socket(self, symbol, callback, fast=True):
433+
"""Start a websocket for a symbol's futures mark price
434+
https://binance-docs.github.io/apidocs/futures/en/#mark-price-stream
435+
:param symbol: required
436+
:type symbol: str
437+
:param callback: callback function to handle messages
438+
:type callback: function
439+
:returns: connection key string if successful, False otherwise
440+
Message Format
441+
.. code-block:: python
442+
{
443+
"e": "markPriceUpdate", // Event type
444+
"E": 1562305380000, // Event time
445+
"s": "BTCUSDT", // Symbol
446+
"p": "11185.87786614", // Mark price
447+
"r": "0.00030000", // Funding rate
448+
"T": 1562306400000 // Next funding time
449+
}
450+
"""
451+
stream_name = '@markPrice@1s' if fast else '@markPrice'
452+
return self._start_futures_socket(symbol.lower() + stream_name, callback)
453+
454+
def start_all_mark_price_socket(self, callback, fast=True):
455+
"""Start a websocket for all futures mark price data
456+
By default all symbols are included in an array.
457+
https://binance-docs.github.io/apidocs/futures/en/#mark-price-stream-for-all-market
458+
:param callback: callback function to handle messages
459+
:type callback: function
460+
:returns: connection key string if successful, False otherwise
461+
Message Format
462+
.. code-block:: python
463+
464+
[
465+
{
466+
"e": "markPriceUpdate", // Event type
467+
"E": 1562305380000, // Event time
468+
"s": "BTCUSDT", // Symbol
469+
"p": "11185.87786614", // Mark price
470+
"r": "0.00030000", // Funding rate
471+
"T": 1562306400000 // Next funding time
472+
}
473+
]
474+
"""
475+
stream_name = '!markPrice@arr@1s' if fast else '!markPrice@arr'
476+
return self._start_futures_socket(stream_name, callback)
477+
478+
def start_symbol_ticker_futures_socket(self, symbol, callback):
479+
"""Start a websocket for a symbol's ticker data
480+
By default all markets are included in an array.
481+
https://binance-docs.github.io/apidocs/futures/en/#individual-symbol-book-ticker-streams
482+
:param symbol: required
483+
:type symbol: str
484+
:param callback: callback function to handle messages
485+
:type callback: function
486+
:returns: connection key string if successful, False otherwise
487+
.. code-block:: python
488+
[
489+
{
490+
"u":400900217, // order book updateId
491+
"s":"BNBUSDT", // symbol
492+
"b":"25.35190000", // best bid price
493+
"B":"31.21000000", // best bid qty
494+
"a":"25.36520000", // best ask price
495+
"A":"40.66000000" // best ask qty
496+
}
497+
]
498+
"""
499+
return self._start_futures_socket(symbol.lower() + '@bookTicker', callback)
500+
501+
def start_all_ticker_futures_socket(self, callback):
502+
"""Start a websocket for all ticker data
503+
By default all markets are included in an array.
504+
https://binance-docs.github.io/apidocs/futures/en/#all-book-tickers-stream
505+
:param callback: callback function to handle messages
506+
:type callback: function
507+
:returns: connection key string if successful, False otherwise
508+
Message Format
509+
.. code-block:: python
510+
[
511+
{
512+
"u":400900217, // order book updateId
513+
"s":"BNBUSDT", // symbol
514+
"b":"25.35190000", // best bid price
515+
"B":"31.21000000", // best bid qty
516+
"a":"25.36520000", // best ask price
517+
"A":"40.66000000" // best ask qty
518+
}
519+
]
520+
"""
521+
522+
523+
return self._start_futures_socket('!bookTicker', callback)
524+
416525
def start_symbol_book_ticker_socket(self, symbol, callback):
417526
"""Start a websocket for the best bid or ask's price or quantity for a specified symbol.
418527
@@ -489,6 +598,7 @@ def start_user_socket(self, callback):
489598
"""Start a websocket for user data
490599
491600
https://github.com/binance-exchange/binance-official-api-docs/blob/master/user-data-stream.md
601+
https://binance-docs.github.io/apidocs/spot/en/#listen-key-spot
492602
493603
:param callback: callback function to handle messages
494604
:type callback: function
@@ -503,9 +613,9 @@ def start_user_socket(self, callback):
503613
return self._start_account_socket('user', user_listen_key, callback)
504614

505615
def start_margin_socket(self, callback):
506-
"""Start a websocket for margin data
616+
"""Start a websocket for cross-margin data
507617
508-
https://github.com/binance-exchange/binance-official-api-docs/blob/master/user-data-stream.md
618+
https://binance-docs.github.io/apidocs/spot/en/#listen-key-margin
509619
510620
:param callback: callback function to handle messages
511621
:type callback: function
@@ -519,6 +629,25 @@ def start_margin_socket(self, callback):
519629
# and start the socket with this specific key
520630
return self._start_account_socket('margin', margin_listen_key, callback)
521631

632+
def start_isolated_margin_socket(self, symbol, callback):
633+
"""Start a websocket for isolated margin data
634+
635+
https://binance-docs.github.io/apidocs/spot/en/#listen-key-isolated-margin
636+
637+
:param symbol: required - symbol for the isolated margin account
638+
:type symbol: str
639+
:param callback: callback function to handle messages
640+
:type callback: function
641+
642+
:returns: connection key string if successful, False otherwise
643+
644+
Message Format - see Binance API docs for all types
645+
"""
646+
# Get the isolated margin listen key
647+
isolated_margin_listen_key = self._client.isolated_margin_stream_get_listen_key(symbol)
648+
# and start the socket with this specific kek
649+
return self._start_account_socket(symbol, isolated_margin_listen_key, callback)
650+
522651
def _start_account_socket(self, socket_type, listen_key, callback):
523652
"""Starts one of user or margin socket"""
524653
self._check_account_socket_open(listen_key)
@@ -549,10 +678,15 @@ def _keepalive_account_socket(self, socket_type):
549678
if socket_type == 'user':
550679
listen_key_func = self._client.stream_get_listen_key
551680
callback = self._account_callbacks[socket_type]
552-
else:
681+
listen_key = listen_key_func()
682+
elif socket_type == 'margin': # cross-margin
553683
listen_key_func = self._client.margin_stream_get_listen_key
554684
callback = self._account_callbacks[socket_type]
555-
listen_key = listen_key_func()
685+
listen_key = listen_key_func()
686+
else: # isolated margin
687+
listen_key_func = self._client.isolated_margin_stream_get_listen_key
688+
callback = self._account_callbacks.get(socket_type, None)
689+
listen_key = listen_key_func(socket_type) # Passing symbol for islation margin
556690
if listen_key != self._listen_keys[socket_type]:
557691
self._start_account_socket(socket_type, listen_key, callback)
558692

@@ -572,18 +706,26 @@ def stop_socket(self, conn_key):
572706
self._conns[conn_key].disconnect()
573707
del(self._conns[conn_key])
574708

575-
# check if we have a user stream socket
576-
if len(conn_key) >= 60 and conn_key[:60] == self._listen_keys['user']:
577-
self._stop_account_socket('user')
709+
# OBSOLETE - removed when adding isolated margin. Loop over keys instead
710+
# # check if we have a user stream socket
711+
# if len(conn_key) >= 60 and conn_key[:60] == self._listen_keys['user']:
712+
# self._stop_account_socket('user')
713+
714+
# # or a margin stream socket
715+
# if len(conn_key) >= 60 and conn_key[:60] == self._listen_keys['margin']:
716+
# self._stop_account_socket('margin')
717+
718+
# NEW - Loop over keys in _listen_keys dictionary to find a match on
719+
# user, cross-margin and isolated margin:
720+
for key, value in self._listen_keys.items():
721+
if len(conn_key) >= 60 and conn_key[:60] == value:
722+
self._stop_account_socket(key)
578723

579-
# or a margin stream socket
580-
if len(conn_key) >= 60 and conn_key[:60] == self._listen_keys['margin']:
581-
self._stop_account_socket('margin')
582724

583725
def _stop_account_socket(self, socket_type):
584-
if not self._listen_keys[socket_type]:
726+
if not self._listen_keys.get(socket_type, None):
585727
return
586-
if self._timers[socket_type]:
728+
if self._timers.get(socket_type, None):
587729
self._timers[socket_type].cancel()
588730
self._timers[socket_type] = None
589731
self._listen_keys[socket_type] = None

docs/account.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Order Validation
99

1010
Binance has a number of rules around symbol pair orders with validation on minimum price, quantity and total order value.
1111

12-
Read more about their specifics in the `Filters <https://github.com/binance-exchange/binance-official-api-docs/blob/master/rest-api.md#filters>`_
12+
Read more about their specifics in the `Filters <https://github.com/binance/binance-spot-api-docs/blob/master/rest-api.md#filters>`_
1313
section of the official API.
1414

1515
It can be helpful to format the output using the following snippet

0 commit comments

Comments
 (0)