Python websocket client (SignalR) for getting live streaming data from Bittrex Exchange.
The library is mainly written in Python3 but should support Python2 with the same functionality, please report any issues.
I am not associated with Bittrex. Use the library at your own risk, I don't bear any responsibility if you end up losing your money.
As of 24 Nov 2017, there is still no official websocket documentation.
The code is licensed under the MIT license. Please consider the following message:
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
- bittrex-websocket
- Table of contents
- Testing needed
- What can I use it for?
- Motivation
- Road map
- Dependencies
- Installation
- Methods
- Message channels
- Sample usage
- Change log
- Support
It's a newly published library so please test it and report for any bugs. Much appreciated.
You can use it for various purposes, some examples include:
- maintaining live order book
- recording trade history
- analysing order flow
Use your imagination.
I am fairly new to Python and in my experience the best way to learn something is through actual practice. At the same time I am currently actively trading on Bittrex, hence the reason why I decided to build the Bittrex websocket client. I am publishing my code for a few reasons. Firstly, I want to make a contribution to the community, secondly the code needs lots of improvements and it would be great to work on it as a team, thirdly I haven't seen any other Python Bittrex websocket clients so far.
I have been largely motivated by the following projects and people:
-
Daniel Paquin: gdax-python - a websocket client for GDAX. The project really helped me around using threads and structuring the code.
-
David Parlevliet - saw his SignalR code initially which included Bittrex specific commands. Saved me a lot of time in researching.
-
Eric Somdahl: python-bittrex - great python bindings for Bittrex. Highly recommend it, I use it in conjuction with the websocket client.
On 11 Jan 2018 the names of the unsubscribe methods will change from:
unsubscribe_to_orderbook
unsubscribe_to_orderbook_update
unsubscribe_to_trades
unsubscribe_to_ticker_update
to
unsubscribe_from_orderbook
unsubscribe_from_orderbook_update
unsubscribe_from_trades
unsubscribe_from_ticker_update
- Test scripts
- Better documentation
- Code cleanup, optimization
- Better error handling
- Lots of stuff, waiting for suggestions
More user friendly subscription to the exchange channels.Pypi
To successfully install the package the following dependencies must be met:
- requests[security]
- g++, make, libffi-dev, openssl-dev
- signalr-client
- g++, make
I have added a Dockerfile for а quick setup. Please check the docker folder.
I am only adding this as a precaution, in most case you will not have to do anything at all as these are prepackaged with your python installation.
pip install bittrex-websocket
pip install git+https://github.com/slazarov/python-bittrex-websocket.git
def subscribe_to_orderbook(self, tickers, book_depth=10):
"""
Subscribe and maintain the live order book for a set of ticker(s).
:param tickers: A list of tickers you are interested in.
:type tickers: []
:param book_depth: The desired depth of the order book to be maintained.
:type book_depth: int
"""
def subscribe_to_orderbook_update(self, tickers):
"""
Subscribe to order book updates for a set of ticker(s).
:param tickers: A list of tickers you are interested in.
:type tickers: []
"""
def subscribe_to_trades(self, tickers):
"""
Subscribe and receive tick data(executed trades) for a set of ticker(s).
:param tickers: A list of tickers you are interested in.
:type tickers: []
"""
def subscribe_to_ticker_update(self, tickers):
"""
Subscribe and receive general data updates for a set of ticker(s). Example output:
{
'MarketName': 'BTC-ADA',
'High': 7.65e-06,
'Low': 4.78e-06,
'Volume': 1352355429.5288217,
'Last': 7.2e-06,
'BaseVolume': 7937.59243908,
'TimeStamp': '2017-11-28T15:02:17.7',
'Bid': 7.2e-06,
'Ask': 7.21e-06,
'OpenBuyOrders': 4452,
'OpenSellOrders': 3275,
'PrevDay': 5.02e-06,
'Created': '2017-09-29T07:01:58.873'
}
:param tickers: A list of tickers you are interested in.
:type tickers: []
"""
def unsubscribe_to_orderbook(self, tickers):
"""
Unsubscribe from real time order for specific set of ticker(s).
:param tickers: A list of tickers you are interested in.
:type tickers: []
"""
def unsubscribe_to_orderbook_update(self, tickers):
"""
Unsubscribe from order book updates for a set of ticker(s).
:param tickers: A list of tickers you are interested in.
:type tickers: []
"""
def unsubscribe_to_trades(self, tickers):
"""
Unsubscribe from receiving tick data(executed trades) for a set of ticker(s)
:param tickers: A list of tickers you are interested in.
:type tickers: []
"""
def unsubscribe_to_ticker_update(self, tickers):
"""
Unsubscribe from receiving general data updates for a set of ticker(s).
:param tickers: A list of tickers you are interested in.
:type tickers: []
"""
def get_order_book(self, ticker=None):
"""
Returns the most recently updated order book for the specific ticker.
If no ticker is specified, returns a dictionary with the order books of
all subscribed tickers.
:param ticker: The specific ticker you want the order book for.
:type ticker: str
"""
def get_order_book_sync_state(self, tickers=None):
"""
Returns the sync state of the order book for the specific ticker(s).
If no ticker is specified, returns the state for all tickers.
The sync states are:
Not initiated = 0
Invoked, not synced = 1
Received, not synced, not processing = 2
Received, synced, processing = 3
:param tickers: The specific ticker(s) and it's order book sync state you are interested in.
:type tickers: []
"""
def disconnect(self):
"""
Disconnects the connections and stops the websocket instance.
"""
The websocket clients starts a separate thread upon initialization with further subthreads for each connection (currently 20 tickers per connection). There are several methods which could be overwritten. Please check the actual code for further information and examples.
def on_open(self):
# Called before initiating the first websocket connection
# Use it when you want to add some opening logic.
def on_close(self):
# Called before closing the websocket instance.
# Use it when you want to add any closing logic.
def on_error(self, error):
# Error handler
def on_orderbook(self, msg):
# The main channel of subscribe_to_orderbook().
def on_orderbook_update(self, msg):
# The main channel of subscribe_to_orderbook_update().
def on_trades(self, msg):
# The main channel of subscribe_to_trades().
def on_ticker_update(self, msg):
# The main channel of subscribe_to_ticker_update().
To receive live data feed you must instantiate the websocket and use one of its subscribe methods. For the various subscription methods check above. Example:
# Tickers
tickers = ['ETH-ZEC'] # use lists
ws = MySocket()
ws.subscribe_to_orderbook(tickers)
# Do some stuff and trade for infinite profit
ws.disconnect()
# Tickers
tickers = ['BTC-ETH', 'BTC-NEO', 'BTC-ZEC', 'ETH-NEO', 'ETH-ZEC'] # use lists
ws = MySocket()
ws.subscribe_to_ticker_update(tickers)
# Do some stuff and trade for infinite profit
ws.disconnect()
Let's get some 'practical' examples. Check examples folder.
from __future__ import print_function
from time import sleep
from bittrex_websocket.websocket_client import BittrexSocket
def main():
class MySocket(BittrexSocket):
def on_open(self):
self.trade_history = {}
def on_trades(self, msg):
# Create entry for the ticker in the trade_history dict
if msg['ticker'] not in self.trade_history:
self.trade_history[msg['ticker']] = []
# Add history nounce
self.trade_history[msg['ticker']].append(msg)
# Ping
print('[Trades]: {}'.format(msg['ticker']))
ws = MySocket()
tickers = ['BTC-ETH', 'BTC-XMR']
ws.subscribe_to_trades(tickers)
while len(set(tickers) - set(ws.trade_history)) > 0:
sleep(1)
continue
else:
for ticker in ws.trade_history.keys():
print('Printing {} trade history.'.format(ticker))
for trade in ws.trade_history[ticker]:
print(trade)
ws.disconnect()
if __name__ == "__main__":
main()
from __future__ import print_function
from time import sleep
from bittrex_websocket.websocket_client import BittrexSocket
def main():
class MySocket(BittrexSocket):
def on_orderbook(self, msg):
print('[OrderBook]: {}'.format(msg['MarketName']))
ws = MySocket()
tickers = ['BTC-ETH', 'BTC-NEO', 'BTC-ZEC', 'ETH-NEO', 'ETH-ZEC']
ws.subscribe_to_orderbook(tickers)
while True:
i = 0
sync_states = ws.get_order_book_sync_state()
for state in sync_states.values():
if state == 3:
i += 1
if i == len(tickers):
print('We are fully synced. Hooray!')
for ticker in tickers:
ob = ws.get_order_book(ticker)
name = ob['MarketName']
quantity = str(ob['Buys'][0]['Quantity'])
price = str(ob['Buys'][0]['Rate'])
print('Ticker: ' + name + ', Bids depth 0: ' + quantity + '@' + price)
ws.disconnect()
break
else:
sleep(1)
if __name__ == "__main__":
main()
0.0.4 - Changed the behaviour of how on_ticker_update channel works: The message now contains a single ticker instead of a dictionary of all subscribed tickers.
0.0.3 - Removed left over code from initial release version that was throwing errors (had no effect on performance).
0.0.2 - Major improvements:
- Additional un/subscribe and order book sync state querying methods added.
- Better connection and thread management.
- Code optimisations
- Better code documentation
- Added additional connection URLs
0.0.1 - Initial release on github.
If you find this package helpful and would like to support it, you can do it through here:
Coin | Address |
---|---|
BTC | 18n4eKg8PB1USs5f95MK34JA4KmaV1YhT2 |
ETH | 0xf5a6431ac4acd8b1e5c8b56b9b45e04cdea20e6e |
LTC | LZT8o523jwa8ZmgMjPLNMJeVeBnLuAvRvc |
ZEC | t1dhA8QqVsXHR8jGp34a1EY8mM7bZ9FjhTW |