Code Monkey home page Code Monkey logo

python-bittrex-websocket's Introduction

logo bittrex-websocket =====================

pypi-v2 pypi-pyversions2 pypi-l2 pypi-wheel2

What is bittrex-websocket? --------------------------Python Bittrex WebSocket (PBW) is the first unofficial Python wrapper for the Bittrex Websocket API. It provides users with a simple and easy to use interface to the Bittrex Exchange.

Users can use it to access real-time public data (e.g exchange status, summary ticks and order fills) and account-level data such as order and balance status. The goal of the package is to serve as a foundation block which users can use to build upon their applications. Examples usages can include maintaining live order books, recording trade history, analysing order flow and many more.

If you prefer asyncio, then take a look at my other library: bittrex-websocket-aio.


Documentation

http://python-bittrex-websocket-docs.readthedocs.io/en/latest/

Getting started/How-to

http://python-bittrex-websocket-docs.readthedocs.io/en/latest/howto.html

Methods

http://python-bittrex-websocket-docs.readthedocs.io/en/latest/methods.html

Changelog

http://python-bittrex-websocket-docs.readthedocs.io/en/latest/changelog.html#bittrex-websocket

I am constantly working on new features. Make sure you stay up to date by regularly checking the official docs!

Having an issue or a question? Found a bug or perhaps you want to contribute? Open an issue!

Quick Start

pip install bittrex-websocket
#!/usr/bin/python
# /examples/ticker_updates.py

# Sample script showing how subscribe_to_exchange_deltas() works.

# Overview:
# ---------
# 1) Creates a custom ticker_updates_container dict.
# 2) Subscribes to N tickers and starts receiving market data.
# 3) When information is received, checks if the ticker is
#    in ticker_updates_container and adds it if not.
# 4) Disconnects when it has data information for each ticker.

from bittrex_websocket.websocket_client import BittrexSocket
from time import sleep

def main():
    class MySocket(BittrexSocket):

        def on_public(self, msg):
            name = msg['M']
            if name not in ticker_updates_container:
                ticker_updates_container[name] = msg
                print('Just received market update for {}.'.format(name))

    # Create container
    ticker_updates_container = {}
    # Create the socket instance
    ws = MySocket()
    # Enable logging
    ws.enable_log()
    # Define tickers
    tickers = ['BTC-ETH', 'BTC-NEO', 'BTC-ZEC', 'ETH-NEO', 'ETH-ZEC']
    # Subscribe to ticker information
    for ticker in tickers:
        sleep(0.01)
        ws.subscribe_to_exchange_deltas([ticker])

    # Users can also subscribe without introducing delays during invoking but
    # it is the recommended way when you are subscribing to a large list of tickers.
    # ws.subscribe_to_exchange_deltas(tickers)

    while len(ticker_updates_container) < len(tickers):
        sleep(1)
    else:
        print('We have received updates for all tickers. Closing...')
        ws.disconnect()
        sleep(10)

if __name__ == "__main__":
    main()

Order book syncing

#!/usr/bin/python
# /examples/order_book.py

# Sample script showing how order book syncing works.

from __future__ import print_function
from time import sleep
from bittrex_websocket import OrderBook

def main():
    class MySocket(OrderBook):
        def on_ping(self, msg):
            print('Received order book update for {}'.format(msg))

    # Create the socket instance
    ws = MySocket()
    # Enable logging
    ws.enable_log()
    # Define tickers
    tickers = ['BTC-ETH']
    # Subscribe to order book updates
    ws.subscribe_to_orderbook(tickers)

    while True:
        sleep(10)
        book = ws.get_order_book('BTC-ETH')
        print(book[u'S'][0])
    else:
        pass

if __name__ == "__main__":
    main()

Disclaimer

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.

python-bittrex-websocket's People

Contributors

ericsomdahl avatar maxmax44 avatar slazarov avatar tingwai avatar zjhmale avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

python-bittrex-websocket's Issues

Wrong data in the order book list ( Solved )

Sometimes it is often wrong to take the orders at the end of the book, it usually stays between 5 seconds to 5 minutes. The limitation of 10 orders is by Bittrex or by the module?

{'MarketName': 'BTC-ZCL', 'Nounce': 4408, 'Buys':
[{'Quantity': 8.71577187, 'Rate': 0.00143},
{'Quantity': 128.0589916, 'Rate': 0.00142546},
{'Quantity': 396.69205873, 'Rate': 0.00142542},
{'Quantity': 150.57055717, 'Rate': 0.00142504},
{'Quantity': 140.62861093, 'Rate': 0.00142424},
{'Quantity': 2.0, 'Rate': 0.001424},
{'Quantity': 7.10991058, 'Rate': 0.00140298},
{'Quantity': 13.23308423, 'Rate': 0.00078}, <-- Error
{'Quantity': 1.93328652, 'Rate': 0.00077779}, <-- Error
{'Quantity': 2.0, 'Rate': 0.00077026}], <-- Error

Getting real-time non-stop ticker updates

Hi everyone!
I had a question on how to get real-time non-stop ticker updates using bittrex-websocket library.
Thanks to @slazarov I got this sample, may be useful for others:

`

    def main():
        class MySocket(BittrexSocket):
            def on_open(self):
                pass

            def on_ticker_update(self, msg):
                name = msg['MarketName']
                print('Just received ticker update for {}.'.format(name))
                print(msg)

        # Create the socket instance
        ws = MySocket()
        # Enable logging
        ws.enable_log()
        # Define tickers
        tickers = ['BTC-ETH', 'BTC-NEO']
        # Subscribe to ticker information
        ws.subscribe_to_ticker_update(tickers)

        while True:
            sleep(1)


    if __name__ == "__main__":
        main()

`

subscribe_to_orderbook() possible misbehaviour

When you call subscribe_to_orderbook() with multiple pair names, and the socket is not yet connected, every requested pair is processed in _subscribe_first_run(), which generates a connect event (and therefore a new thread and a new connection) for every pair that requires subscription. However if you call subscribe_to_orderbook() with a single pair, and then wait a little and request more subscriptions, the connect events will not be generated, i.e. if you request subscriptions in bulk before the socket is connected, the library will open a connection per every subscription required. Is this intentional?

Failed to connect

So i have been trying to use the examples but on every one of them i got this error:
``ConnectionError: HTTPSConnectionPool(host='socket-beta.bittrex.com', port=443): Max retries exceeded with url: /signalr/negotiate?connectionData=%5B%7B%22name%22%3A+%22coreHub%22%7D%5D&clientProtocol=1.5 (Caused by NewConnectionError('<urllib3.connection.VerifiedHTTPSConnection object at 0x05A56B70>: Failed to establish a new connection: [Errno 11001] getaddrinfo failed',))
`

`

How to get multiple websockets to work at once?

I finally got the websocket to work after checking the Getting real-time non-stop ticker updates #23 post, but now I have another problem. I need to have 1 websocket working on one function, and another on a different one with the first function calling the second at some point, like so:

def main():
    class MySocket(BittrexSocket):
        def __init__(self, url=None):
            super(MySocket, self).__init__(url)
            self.ticker_updates_container = {}        
            self.balances = {} #need this to work the same as ticker_updates_container

        def on_public(self, msg):           
            self.ticker_updates_container = msg
        
        def function1(self):   
            while True:                                 
                for i in self.ticker_updates_container['D']:    
                    dostuff
                    self.function2()
        def function2(self):
            while True:
                for i in balances:

    # Create the socket instance
    ws = MySocket()

    # Enable logging
    ws.enable_log()

    # Subscribe to ticker information   
    ws.subscribe_to_summary_deltas()  
    ws.authenticate(key, secret) #This is what I need for function2, on a while True loop
    time.sleep(10)
    ws.function1()

    while True:
        pass
    
      
if __name__ == "__main__":
    main()

But I don't know how to. In the example I use balances, it's the one on authenticate method, I think a better way to put it is that I don't understand how the msg get to on_public, and because of that I can't think of a way to add another websocket with something like

def on_balance(self, msg):    
    self.balance = msg

I tried both def on_private and def _on_private but it doesn't work.
I know this should be my problem but maybe a lot of people could use it like the other info post, sorry to bother you.

logging configuration is being overwritten

Hey,

I'm using your websocket implementation in my project,
I was logging everything to a file and I noticed that after I used your code, it started to display log messages in the terminal.

Your logging configuration is overwriting mine, I fixed the problem by commenting out line 25 in websocket_client.py.

logging.basicConfig(level=logging.DEBUG)

I don't know if there is a more elegant fix, I haven't had experience getting into logging at a deeper level.

Reconnect and subsciption not re-established

websocket works really well slazarov. I have a headless data collector and am testing different scenarios with latest version available form pip install. I have am subscribing to Trades for a single currently only to keep testing simple and when I remove the LAN connection the socket does not fully recover.

Early today reconnect would eventually defer to the Watchdog, but I have change versions and config since then - now the connection recovers when LAN restored, but the subscription is not re-established.

I cannot capture an exception and on_error is not called. I know you are working on Reconnect, is this something you are aware of?

Also - an Exception is thrown on LAN disconnect but it does not appear to be causing issues.
Websocket._exceptions.WebSocketConnectionsClosedException: Connection is already close.

This is thrown several times and is repeatable with a LAN disconnect during Trade subscription.

Duplicate logging

Hey,

First of all, I'm not entirely sure if it is intended or it's because of my setup.
I have enabled logging and it's writing logs as intended, however I have observed the following.

If I subscribe to both ticker updates and orderbook, it will start logging duplicate rows.
I'm guessing that, for any time a subscribe method is called for the first time, it will start a duplicate logging.

I have tested this and I have found these results:

Investigating subscribing to user deltas as well

I've been playing around with the possibility of creating a logged-in version of this where we'll also subscribe to 'SubscribeToUserDeltas'. Receiving order creations, executions and cancellations in (pseudo) real time.

I haven't been able to do this yet, not even in a very simple version where I log in with my browser and copy the .AspNet.ApplicationCookie generated and add it to the 'negotiate' request.

Does anyone have an idea what to investigate next? How does the signalr 'know' that it's allowed subscribe to my specific userdeltas?

Thanks in advance for any ideas,

JR
PS: I've also unsuccesfully tried the __cfduid cookie

subscribe_to_orderbook falling out of sync

I slightly modified your example that keeps a live orderbook so that it runs indefinitely and continually outputs the top 5 bids and asks for a ticker (tested on BTC-ETH) in the on_orderbook function

the orderbook falls out of sync regularly, usually either a couple of bids or asks are missing as compared to bittrex orderbook view through their website, these get rolled away as the price changes so at other times everything seems to be ok. The worst case I saw was when all top 5 bids shown by the websocket client were non existent on bittrex webpage

I tried it with just one symbol to make sure this is not just the scripts being overwhelmed but this happens no matter how many orderbook symbols i subscribed to

503 during socket handshake causes infinite loop

Hi,

Occasionally during initialization the issue #12 happens because the handshake returns a 503:

Traceback (most recent call last):
  File "/home/gryptobod/dev/.env/src/bittrex-websocket/bittrex_websocket/websocket_client.py", line 322, in _init_conn
ection                                                                                                               
    conn.start()
  File "/home/gryptobod/dev/.env/lib/python3.6/site-packages/signalr/_connection.py", line 50, in start
    listener = self.__transport.start()
  File "/home/gryptobod/dev/.env/lib/python3.6/site-packages/signalr/transports/_auto_transport.py", line 28, in start
    return self.__transport.start()
  File "/home/gryptobod/dev/.env/lib/python3.6/site-packages/signalr/transports/_ws_transport.py", line 38, in start
    enable_multithread=True)
  File "/home/gryptobod/dev/.env/lib/python3.6/site-packages/websocket/_core.py", line 490, in create_connection
    websock.connect(url, **options)
  File "/home/gryptobod/dev/.env/lib/python3.6/site-packages/websocket/_core.py", line 216, in connect
    self.handshake_response = handshake(self.sock, *addrs, **options)
  File "/home/gryptobod/dev/.env/lib/python3.6/site-packages/websocket/_handshake.py", line 69, in handshake
    status, resp = _get_resp_headers(sock)
  File "/home/gryptobod/dev/.env/lib/python3.6/site-packages/websocket/_handshake.py", line 135, in _get_resp_headers
    raise WebSocketBadStatusException("Handshake status %d", status)
websocket._exceptions.WebSocketBadStatusException: Handshake status 503

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.6/threading.py", line 916, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.6/threading.py", line 864, in run
    self._target(*self._args, **self._kwargs)
  File "/home/gryptobod/dev/.env/src/bittrex-websocket/bittrex_websocket/websocket_client.py", line 350, in _init_conn
ection                                                                                                               
    raise ImportWarning(MSG_ERROR_SOCKET_WEBSOCKETBADSTATUS)
ImportWarning: Please report error to https://github.com/slazarov/python-bittrex-websocket, Error:WebSocketBadStatusException                                                                                                              

In turn, this can cause an infinite loop in Ticker.set_book_depth(), because the while ticker not in self.list loops forever. As this is not a daemon thread, it will prevent normal process termination and confuse thread monitors (as is the case in my code).

A trivial solution would be:

                while ticker not in self.list:
                    sleep(0.5)
                    timeout += 0.5
                    if timeout > 40:
                        raise RuntimeError("Unable to set order book depth, timeout")

New Errors

My ticker list : ['BTC-ZCL', 'BTC-NEO', 'BTC-BCPT', 'BTC-ADA', 'BTC-ETH', 'BTC-ETC', 'BTC-OMG', 'BTC-LTC', 'BTC-RDD', 'BTC-XRP', 'BTC-XVG', 'BTC-BCC', 'BTC-XLM', 'BTC-BITB', 'BTC-SC', 'BTC-XMR', 'BTC-NBT', 'BTC-LSK', 'BTC-DOGE', 'BTC-MEME', 'ETH-NEO', 'ETH-ADA', 'ETH-OMG', 'ETH-XRP', 'ETH-WAX', 'USDT-BTC', 'USDT-NEO', 'USDT-ETH', 'USDT-LTC', 'USDT-ETC']

When I execute my code:

.
.
.
ion][OrderBook][USDT-ETH]: Order book snapshot requested.
2018-02-28 09:04:36 - bittrex_websocket.websocket_client - INFO - [Subscription][OrderBook][ETH-OMG]: Order book snapshot requested.
2018-02-28 09:04:36 - bittrex_websocket.websocket_client - INFO - [Subscription][OrderBook][USDT-NEO]: Order book snapshot requested.
2018-02-28 09:04:36 - bittrex_websocket.websocket_client - INFO - [Subscription][OrderBook][ETH-XRP]: Order book snapshot requested.
2018-02-28 09:04:36 - bittrex_websocket.websocket_client - INFO - [Subscription][OrderBook][USDT-LTC]: Order book snapshot requested.
2018-02-28 09:04:36 - bittrex_websocket.websocket_client - INFO - [Subscription][OrderBook][USDT-BTC]: Order book snapshot requested.
2018-02-28 09:04:36 - bittrex_websocket.websocket_client - INFO - [Subscription][OrderBook][ETH-NEO]: Order book snapshot requested.
ETH-NEO  is wrong
Traceback (most recent call last):
  File "/home/rightx2/.pyenv/versions/coin_trader_project/lib/python3.6/site-packages/bittrex_websocket/websocket_client.py", line 989, in _transfer_backorder_queue2
    e = q.get(False)
AttributeError: 'NoneType' object has no attribute 'get'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/rightx2/.pyenv/versions/coin_trader_project/lib/python3.6/site-packages/gevent/greenlet.py", line 537, in run
    result = self._run(*self.args, **self.kwargs)
  File "/home/rightx2/.pyenv/versions/coin_trader_project/lib/python3.6/site-packages/signalr/_connection.py", line 53, in wrapped_listener
    listener()
  File "/home/rightx2/.pyenv/versions/coin_trader_project/lib/python3.6/site-packages/signalr/transports/_ws_transport.py", line 43, in _receive
    self._handle_notification(notification)
  File "/home/rightx2/.pyenv/versions/coin_trader_project/lib/python3.6/site-packages/signalr/transports/_transport.py", line 50, in _handle_notification
    self._connection.received.fire(**data)
  File "/home/rightx2/.pyenv/versions/coin_trader_project/lib/python3.6/site-packages/signalr/events/_events.py", line 15, in fire
    handler(*args, **kwargs)
  File "/home/rightx2/.pyenv/versions/coin_trader_project/lib/python3.6/site-packages/bittrex_websocket/websocket_client.py", line 1016, in _on_debug
    self._is_orderbook_snapshot(kwargs)
  File "/home/rightx2/.pyenv/versions/coin_trader_project/lib/python3.6/site-packages/bittrex_websocket/websocket_client.py", line 949, in _is_orderbook_snapshot
    if self._transfer_backorder_queue2(ticker, msg['R']):
  File "/home/rightx2/.pyenv/versions/coin_trader_project/lib/python3.6/site-packages/bittrex_websocket/websocket_client.py", line 996, in _transfer_backorder_queue2
    raise NotImplementedError('Please report error to '
NotImplementedError: Please report error to https://github.com/slazarov/python-bittrex-websocket, Error:_transfer_backorder_queue:AttributeError
Wed Feb 28 09:04:36 2018 <Greenlet at 0x7f81cae8bf20: wrapped_listener> failed with NotImplementedError

2018-02-28 09:04:36 - bittrex_websocket.websocket_client - INFO - [Connection][f41ebe46fee04fe2b975e32bc6174dc9]:Trying to establish connection to Bittrex through https://socket.bittrex.com/signalr.
2018-02-28 09:04:42 - bittrex_websocket.websocket_client - INFO - [Connection][f41ebe46fee04fe2b975e32bc6174dc9]:Connection to Bittrex established successfully through https://socket.bittrex.com/signalr
.
.
.

I added code for debuging in the library (line number 995):

 982     def _transfer_backorder_queue2(self, ticker, snapshot):
 983         confirmed = False
 984         sub = self.tickers.list[ticker][SUB_TYPE_ORDERBOOK]
 985         q = sub['InternalQueue']
 986         q2 = queue.Queue()
 987         while True:
 988             try:
 989                 e = q.get(False)
 990                 q2.put(e)
 991             except queue.Empty:
 992                 sub['InternalQueue'] = q2
 993                 return confirmed
 994             except AttributeError:
 995                 print(ticker, " is wrong")
 996                 raise NotImplementedError('Please report error to '
 997                                           'https://github.com/slazarov/python-bittrex-websocket, '
 998                                           'Error:_transfer_backorder_queue:AttributeError')
 999             else:
1000                 if self._confirm_order_book(snapshot, e):
1001                     confirmed = True
1002                 q.task_done()

If you see the error log again, there is a log, "ETH-NEO is wrong".

Why does this happen?

I still used 0.0.6.4 but it occured 0.0.7.0, too !

(Only difference is whether program STOP or not due to the error. )

Connecting and trying to get all tickers update is not working

When using a list of ticker I get tickers update, when using a list to [None], the ticker update method is never being called. I'm using the sample that comes with bittrex websocket.

2018-01-09 17:03:22 - bittrex_websocket.websocket_client - INFO - [Connection][5f8bbaec22ee4c17bcbc40bdd7f8ad8e]: Trying to establish connection to Bittrex through https://socket-stage.bittrex.com/signalr. 2018-01-09 17:03:29 - bittrex_websocket.websocket_client - INFO - [Connection][5f8bbaec22ee4c17bcbc40bdd7f8ad8e]: Connection to Bittrex established successfully through https://socket-stage.bittrex.com/signalr. 2018-01-09 17:03:29 - bittrex_websocket._auxiliary - INFO - [Subscription][TickerUpdate][None]: Enabled.

waiting 5 seconds per every update?

I want to get every ticker_update data but it always take some delays about 5 seconds.
below is that I tried basic example and printed in on_ticker_update(self, msg) def.

[BTC-XRP] 0.00013021 / 2018-01-15T11:38:46.023
[BTC-XRP] 0.00013021 / 2018-01-15T11:38:51.63
[BTC-XRP] 0.00013014 / 2018-01-15T11:38:56.003
[BTC-XRP] 0.00013014 / 2018-01-15T11:39:01.347
[BTC-XRP] 0.00013009 / 2018-01-15T11:39:06.673
[BTC-XRP] 0.00013017 / 2018-01-15T11:39:16.92
[BTC-XRP] 0.00013017 / 2018-01-15T11:39:21.76
[BTC-XRP] 0.00013021 / 2018-01-15T11:39:26.34
[BTC-XRP] 0.00013021 / 2018-01-15T11:39:31.697

is there a way to get real time ticker_update msg ?

Check if already subscribed to channel

Hey,

I am writing an app that will send orders and using your library, will dynamically subscribe to the market ticker / orderbook. Right now every time I send an order, it calls a subscribe method for the given market.

But if I send multiple orders for the same market, I call the subscribe method multiple times. From the logs I see that you are handling it this like this:
"OrderBook subscription is already enabled for BTC-XRP. Ignoring..."

I was curious if there was a way to check if the given market orderbook / ticker is already subscribed to, so I don't make unnecesarry calls. :)

Connection timed out

I'm trying to save the data from the ticker but after half a day i get a timeout.
My guess is:
It's always reconnecting? Instead of just staying at on subscription?
I used the sample script provided in the examples and modified it to run constantly...

requests.exceptions.ConnectionError: HTTPSConnectionPool(host='socket-beta.bittrex.com', port=443): Max retries exceeded with url: /signal
r/negotiate?connectionData=%5B%7B%22name%22%3A+%22coreHub%22%7D%5D&clientProtocol=1.5 (Caused by NewConnectionError('<urllib3.connection.V
erifiedHTTPSConnection object at 0x7f4bf6434128>: Failed to establish a new connection: [Errno 110] Connection timed out',))

websocket._exceptions.WebSocketConnectionClosedException: Connection is already closed?

I run bittrex-websocket==0.0.6.3 version on my Linux Ubuntu 16.04 desktop.

I run a code which gets about 40 symbol's order book and tick.

It works well at first time but after 1hour 30mins later, it raise exception like below :

.
.

2018-02-11 22:08:22 - bittrex_websocket.websocket_client - INFO - [Subscription][OrderBook][ETH-POWR]: Order book snapshot requested.
2018-02-11 22:08:22 - bittrex_websocket.websocket_client - INFO - [Subscription][OrderBook][ETH-POWR]: Order book snapshot received.
2018-02-11 22:08:23 - bittrex_websocket.websocket_client - INFO - [Subscription][OrderBook][ETH-BTG]: Order book snapshot requested.
2018-02-11 22:08:23 - bittrex_websocket.websocket_client - INFO - [Subscription][OrderBook][ETH-BTG]: Order book snapshot received.
2018-02-11 22:08:24 - bittrex_websocket.websocket_client - INFO - [Subscription][OrderBook][USDT-BTC]: Order book snapshot requested.
2018-02-11 22:08:24 - bittrex_websocket.websocket_client - INFO - [Subscription][OrderBook][USDT-BTC]: Order book snapshot received.
2018-02-11 22:08:25 - bittrex_websocket.websocket_client - INFO - [Subscription][OrderBook][USDT-XRP]: Order book snapshot requested.
2018-02-11 22:08:25 - bittrex_websocket.websocket_client - INFO - [Subscription][OrderBook][USDT-XRP]: Order book snapshot received.
2018-02-11 22:08:27 - bittrex_websocket.websocket_client - INFO - [Subscription][OrderBook][USDT-ETH]: Order book snapshot requested.
2018-02-11 22:08:27 - bittrex_websocket.websocket_client - INFO - [Subscription][OrderBook][USDT-ETH]: Order book snapshot received.
2018-02-11 22:08:29 - bittrex_websocket.websocket_client - INFO - [Subscription][OrderBook][USDT-ADA]: Order book snapshot requested.
2018-02-11 22:08:29 - bittrex_websocket.websocket_client - INFO - [Subscription][OrderBook][USDT-ADA]: Order book snapshot received.
2018-02-11 22:08:33 - bittrex_websocket.websocket_client - INFO - [Subscription][OrderBook][USDT-NEO]: Order book snapshot requested.
2018-02-11 22:08:33 - bittrex_websocket.websocket_client - INFO - [Subscription][OrderBook][USDT-NEO]: Order book snapshot received.
2018-02-11 22:08:34 - bittrex_websocket.websocket_client - INFO - [Subscription][OrderBook][USDT-ETC]: Order book snapshot requested.
2018-02-11 22:08:34 - bittrex_websocket.websocket_client - INFO - [Subscription][OrderBook][USDT-ETC]: Order book snapshot received.
2018-02-11 22:08:39 - bittrex_websocket.websocket_client - INFO - [Subscription][OrderBook][USDT-LTC]: Order book snapshot requested.
2018-02-11 22:08:39 - bittrex_websocket.websocket_client - INFO - [Subscription][OrderBook][USDT-LTC]: Order book snapshot received.
2018-02-11 22:08:40 - bittrex_websocket.websocket_client - INFO - [Subscription][OrderBook][USDT-BCC]: Order book snapshot requested.
2018-02-11 22:08:40 - bittrex_websocket.websocket_client - INFO - [Subscription][OrderBook][USDT-BCC]: Order book snapshot received.
2018-02-11 22:08:53 - bittrex_websocket.websocket_client - INFO - [Subscription][OrderBook][USDT-XVG]: Order book snapshot requested.
2018-02-11 22:08:53 - bittrex_websocket.websocket_client - INFO - [Subscription][OrderBook][USDT-XVG]: Order book snapshot received.
2018-02-11 22:08:59 - bittrex_websocket.websocket_client - INFO - [Subscription][OrderBook][USDT-BTG]: Order book snapshot requested.
2018-02-11 22:08:59 - bittrex_websocket.websocket_client - INFO - [Subscription][OrderBook][USDT-BTG]: Order book snapshot received.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][BTC-XRP]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][BTC-BCC]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][BTC-ETC]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][BTC-NBT]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][BTC-ADA]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][BTC-NEO]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][BTC-ETH]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][BTC-XLM]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][BTC-LSK]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][BTC-SC]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][BTC-LTC]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][BTC-XVG]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][BTC-ZEC]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][BTC-QTUM]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][BTC-EMC2]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][ETH-XRP]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][ETH-BCC]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][ETH-NEO]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][ETH-ETC]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][ETH-ADA]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][ETH-OMG]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][ETH-XMR]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][ETH-QTUM]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][ETH-LTC]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][ETH-XLM]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][ETH-SC]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][ETH-ZEC]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][ETH-REP]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][ETH-POWR]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][ETH-BTG]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][USDT-BTC]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][USDT-XRP]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][USDT-ETH]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][USDT-ADA]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][USDT-NEO]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][USDT-ETC]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][USDT-LTC]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][USDT-BCC]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][USDT-XVG]: Enabled.
2018-02-11 22:09:00 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][USDT-BTG]: Enabled.
2018-02-11 23:35:13 - bittrex_websocket.websocket_client - INFO - [Connection][f432396b8e0a4dfe9a564e3fb2ce1f6d]:Trying to establish connection to Bittrex through https://socket-stage.bittrex.com/signalr.
2018-02-11 23:35:19 - bittrex_websocket.websocket_client - INFO - [Connection][d3bd524542784b67b49f8785e5f6c72b]:Trying to establish connection to Bittrex through https://socket-stage.bittrex.com/signalr.
2018-02-11 23:35:20 - bittrex_websocket.websocket_client - INFO - [Connection][f432396b8e0a4dfe9a564e3fb2ce1f6d]:Connection to Bittrex established successfully through https://socket-stage.bittrex.com/signalr
2018-02-11 23:35:26 - bittrex_websocket.websocket_client - INFO - [Connection][d3bd524542784b67b49f8785e5f6c72b]:Connection to Bittrex established successfully through https://socket-stage.bittrex.com/signalr
Traceback (most recent call last):
  File "/home/rightx2/.pyenv/versions/coin_trader_project/lib/python3.6/site-packages/gevent/greenlet.py", line 536, in run
    result = self._run(*self.args, **self.kwargs)
Traceback (most recent call last):
  File "/home/rightx2/.pyenv/versions/coin_trader_project/lib/python3.6/site-packages/signalr/_connection.py", line 53, in wrapped_listener
    listener()
  File "/home/rightx2/.pyenv/versions/coin_trader_project/lib/python3.6/site-packages/gevent/greenlet.py", line 536, in run
    result = self._run(*self.args, **self.kwargs)
  File "/home/rightx2/.pyenv/versions/coin_trader_project/lib/python3.6/site-packages/signalr/_connection.py", line 53, in wrapped_listener
    listener()
  File "/home/rightx2/.pyenv/versions/coin_trader_project/lib/python3.6/site-packages/signalr/transports/_ws_transport.py", line 42, in _receive
    for notification in self.ws:
  File "/home/rightx2/.pyenv/versions/coin_trader_project/lib/python3.6/site-packages/websocket/_core.py", line 107, in __iter__
    yield self.recv()
  File "/home/rightx2/.pyenv/versions/coin_trader_project/lib/python3.6/site-packages/websocket/_core.py", line 296, in recv
    opcode, data = self.recv_data()
  File "/home/rightx2/.pyenv/versions/coin_trader_project/lib/python3.6/site-packages/websocket/_core.py", line 313, in recv_data
    opcode, frame = self.recv_data_frame(control_frame)
  File "/home/rightx2/.pyenv/versions/coin_trader_project/lib/python3.6/site-packages/websocket/_core.py", line 326, in recv_data_frame
    frame = self.recv_frame()
  File "/home/rightx2/.pyenv/versions/coin_trader_project/lib/python3.6/site-packages/websocket/_core.py", line 360, in recv_frame
    return self.frame_buffer.recv_frame()
  File "/home/rightx2/.pyenv/versions/coin_trader_project/lib/python3.6/site-packages/websocket/_abnf.py", line 340, in recv_frame
    self.recv_header()
  File "/home/rightx2/.pyenv/versions/coin_trader_project/lib/python3.6/site-packages/websocket/_abnf.py", line 288, in recv_header
    header = self.recv_strict(2)
  File "/home/rightx2/.pyenv/versions/coin_trader_project/lib/python3.6/site-packages/websocket/_abnf.py", line 375, in recv_strict
    bytes_ = self.recv(min(16384, shortage))
  File "/home/rightx2/.pyenv/versions/coin_trader_project/lib/python3.6/site-packages/websocket/_core.py", line 430, in _recv
    return recv(self.sock, bufsize)
  File "/home/rightx2/.pyenv/versions/coin_trader_project/lib/python3.6/site-packages/websocket/_socket.py", line 94, in recv
    "Connection is already closed.")
websocket._exceptions.WebSocketConnectionClosedException: Connection is already closed.
  File "/home/rightx2/.pyenv/versions/coin_trader_project/lib/python3.6/site-packages/signalr/transports/_ws_transport.py", line 42, in _receive
    for notification in self.ws:
Mon Feb 12 00:00:48 2018 <Greenlet at 0x7fe16d5b33d8: wrapped_listener> failed with WebSocketConnectionClosedException

  File "/home/rightx2/.pyenv/versions/coin_trader_project/lib/python3.6/site-packages/websocket/_core.py", line 107, in __iter__
    yield self.recv()
2018-02-12 00:00:48 - bittrex_websocket.websocket_client - INFO - [Connection][f432396b8e0a4dfe9a564e3fb2ce1f6d]:Trying to establish connection to Bittrex through https://socket-stage.bittrex.com/signalr.
  File "/home/rightx2/.pyenv/versions/coin_trader_project/lib/python3.6/site-packages/websocket/_core.py", line 296, in recv
    opcode, data = self.recv_data()
  File "/home/rightx2/.pyenv/versions/coin_trader_project/lib/python3.6/site-packages/websocket/_core.py", line 313, in recv_data
    opcode, frame = self.recv_data_frame(control_frame)
  File "/home/rightx2/.pyenv/versions/coin_trader_project/lib/python3.6/site-packages/websocket/_core.py", line 326, in recv_data_frame
    frame = self.recv_frame()
  File "/home/rightx2/.pyenv/versions/coin_trader_project/lib/python3.6/site-packages/websocket/_core.py", line 360, in recv_frame
    return self.frame_buffer.recv_frame()
  File "/home/rightx2/.pyenv/versions/coin_trader_project/lib/python3.6/site-packages/websocket/_abnf.py", line 340, in recv_frame
    self.recv_header()
  File "/home/rightx2/.pyenv/versions/coin_trader_project/lib/python3.6/site-packages/websocket/_abnf.py", line 288, in recv_header
    header = self.recv_strict(2)
  File "/home/rightx2/.pyenv/versions/coin_trader_project/lib/python3.6/site-packages/websocket/_abnf.py", line 375, in recv_strict
    bytes_ = self.recv(min(16384, shortage))
  File "/home/rightx2/.pyenv/versions/coin_trader_project/lib/python3.6/site-packages/websocket/_core.py", line 430, in _recv
    return recv(self.sock, bufsize)
  File "/home/rightx2/.pyenv/versions/coin_trader_project/lib/python3.6/site-packages/websocket/_socket.py", line 94, in recv
    "Connection is already closed.")
websocket._exceptions.WebSocketConnectionClosedException: Connection is already closed.
Mon Feb 12 00:00:48 2018 <Greenlet at 0x7fe16d5b3898: wrapped_listener> failed with WebSocketConnectionClosedException

As you can see the log, there is nothing wrong with my code(all logs are related with related library, not my code).

And also def on_error(self, error): doesn't called, even once.

I don't know why this happend.

If you need a more infos, please tell me.

Thanks

installation issue (windows)

I just tried to install your module, but got this error:

https://pastebin.com/AfhzciMg

PS C:> pip3.4 install bittrex-websocket
Collecting bittrex-websocket
Using cached bittrex_websocket-0.0.7.0-py2.py3-none-any.whl
Requirement already satisfied: websocket-client>=0.47.0 in c:\python34\lib\site-packages (from bittrex-websocket)
Requirement already satisfied: cfscrape>=1.9.4 in c:\python34\lib\site-packages (from bittrex-websocket)
Collecting gevent>=1.3a1 (from bittrex-websocket)
Using cached gevent-1.3a2-cp34-cp34m-win32.whl
Requirement already satisfied: signalr-client==0.0.7 in c:\python34\lib\site-packages (from bittrex-websocket)
Collecting wsaccel>=0.6.2 (from bittrex-websocket)
Using cached wsaccel-0.6.2.tar.gz
Requirement already satisfied: requests[security]==2.18.4 in c:\python34\lib\site-packages (from bittrex-websocket)
Requirement already satisfied: Events==0.3 in c:\python34\lib\site-packages (from bittrex-websocket)
Requirement already satisfied: six in c:\python34\lib\site-packages (from websocket-client>=0.47.0->bittrex-websocket)
Requirement already satisfied: PyExecJS>=1.4.0 in c:\python34\lib\site-packages (from cfscrape>=1.9.4->bittrex-websocket
)
Collecting greenlet>=0.4.13; platform_python_implementation == "CPython" (from gevent>=1.3a1->bittrex-websocket)
Using cached greenlet-0.4.13-cp34-cp34m-win32.whl
Requirement already satisfied: sseclient in c:\python34\lib\site-packages (from signalr-client==0.0.7->bittrex-websocket
)
Requirement already satisfied: urllib3<1.23,>=1.21.1 in c:\python34\lib\site-packages (from requests[security]==2.18.4->
bittrex-websocket)
Requirement already satisfied: chardet<3.1.0,>=3.0.2 in c:\python34\lib\site-packages (from requests[security]==2.18.4->
bittrex-websocket)
Requirement already satisfied: certifi>=2017.4.17 in c:\python34\lib\site-packages (from requests[security]==2.18.4->bit
trex-websocket)
Requirement already satisfied: idna<2.7,>=2.5 in c:\python34\lib\site-packages (from requests[security]==2.18.4->bittrex
-websocket)
Requirement already satisfied: cryptography>=1.3.4; extra == "security" in c:\python34\lib\site-packages (from requests[
security]==2.18.4->bittrex-websocket)
Requirement already satisfied: pyOpenSSL>=0.14; extra == "security" in c:\python34\lib\site-packages (from requests[secu
rity]==2.18.4->bittrex-websocket)
Requirement already satisfied: cffi>=1.7; platform_python_implementation != "PyPy" in c:\python34\lib\site-packages (fro
m cryptography>=1.3.4; extra == "security"->requests[security]==2.18.4->bittrex-websocket)
Requirement already satisfied: asn1crypto>=0.21.0 in c:\python34\lib\site-packages (from cryptography>=1.3.4; extra == "
security"->requests[security]==2.18.4->bittrex-websocket)
Requirement already satisfied: pycparser in c:\python34\lib\site-packages (from cffi>=1.7; platform_python_implementatio
n != "PyPy"->cryptography>=1.3.4; extra == "security"->requests[security]==2.18.4->bittrex-websocket)
Building wheels for collected packages: wsaccel
Running setup.py bdist_wheel for wsaccel ... error
Complete output from command c:\python34\python.exe -u -c "import setuptools, tokenize;file='C:\Users\SERPEN1\
AppData\Local\Temp\pip-build-zr6bilna\wsaccel\setup.py';f=getattr(tokenize, 'open', open)(file);code=f.read().r
eplace('\r\n', '\n');f.close();exec(compile(code, file, 'exec'))" bdist_wheel -d C:\Users\SERPEN
1\AppData\Local\Tem
p\tmp47k6x4depip-wheel- --python-tag cp34:
running bdist_wheel
running build
running build_py
creating build
creating build\lib.win32-3.4
creating build\lib.win32-3.4\wsaccel
copying wsaccel_init_.py -> build\lib.win32-3.4\wsaccel
running build_ext
building 'wsaccel.utf8validator' extension
error: INCLUDE environment variable is empty


Failed building wheel for wsaccel
Running setup.py clean for wsaccel
Failed to build wsaccel
Installing collected packages: greenlet, gevent, wsaccel, bittrex-websocket
Found existing installation: greenlet 0.4.12
Uninstalling greenlet-0.4.12:
Successfully uninstalled greenlet-0.4.12
Found existing installation: gevent 1.2.2
Uninstalling gevent-1.2.2:
Successfully uninstalled gevent-1.2.2
Running setup.py install for wsaccel ... error
Complete output from command c:\python34\python.exe -u -c "import setuptools, tokenize;file='C:\Users\SERPEN1
\AppData\Local\Temp\pip-build-zr6bilna\wsaccel\setup.py';f=getattr(tokenize, 'open', open)(file);code=f.read()
.replace('\r\n', '\n');f.close();exec(compile(code, file, 'exec'))" install --record C:\Users\SERPEN
1\AppData\Local
\Temp\pip-egg59y1n-record\install-record.txt --single-version-externally-managed --compile:
running install
running build
running build_py
creating build
creating build\lib.win32-3.4
creating build\lib.win32-3.4\wsaccel
copying wsaccel_init_.py -> build\lib.win32-3.4\wsaccel
running build_ext
building 'wsaccel.utf8validator' extension
error: INCLUDE environment variable is empty

----------------------------------------

Command "c:\python34\python.exe -u -c "import setuptools, tokenize;file='C:\Users\SERPEN1\AppData\Local\Temp\
pip-build-zr6bilna\wsaccel\setup.py';f=getattr(tokenize, 'open', open)(file);code=f.read().replace('\r\n', '\n');f
.close();exec(compile(code, file, 'exec'))" install --record C:\Users\SERPEN
1\AppData\Local\Temp\pip-egg59y1n-recor
d\install-record.txt --single-version-externally-managed --compile" failed with error code 1 in C:\Users\SERPEN~1\AppDat
a\Local\Temp\pip-build-zr6bilna\wsaccel\

Snapshot for orderbook updates

First, thanks for sharing @slazarov.

When subscribing to orderbook updates with subscribe_to_orderbook_update(), there is no snapshot syncing performed. A reasonable behaviour would be that the first update includes all levels.

I have hacked around this (at the expense of subscribe_to_orderbook()), but wouldn't mind contributing with a pull request with a more sustainable solution. Currently, the snapshot is quite heavily tied in with SUB_TYPE_ORDERBOOK, even though the overlap between the two subscriptions types seem to be quite large. How do you feel about consolidating the two types and having a variable (e.g. self.tickers.list[ticker][SUB_TYPE_ORDERBOOK]['IsDifferential']) indicate if only changed levels should be passed to the callback function?

On a sidenote, I can't figure out where in the code the client tells Bittrex which tickers are of interest. Do they simply publish updates for all tickers, leaving the client to filter out tickers of no interest?

Getting gevent.hub.LoopExit exception when trying to combine python-bittrex-websocket with flask multi-threaded

Hi,
First of all thanks for your work on your library.

I'm trying to combine it with flask in order to build a web application connecting to bittrex with python backend and HTML/CSS/JS frontend.

I'm first creating a BittrexSocket with your library, then I'm running flask using "threaded = True" to handle multiple requests to the web server at the same time. However, when requesting an url (simply http://127.0.0.1:5000/, without any routing), I'm getting the following exception:

gevent.hub.LoopExit: ('This operation would block forever', <Hub at 0x2c8d1a01c28 select pending=0 ref=0>)

If I remove the "threaded = True", the exception is not raised anymore. So I think that your library may be touching some shared data also used by flask, in a wrong way. But I'm a newbie to python multi-threaded programming so I can't be sure.

Here is a gist with combining the exemple ticker_updates.py with flask and producing the error: https://gist.github.com/Celeborn2BeAlive/30afcd35f18db4c60484eabcfdcb101e

And a stacktrace for the error:
Exception happened during processing of request from ('127.0.0.1', 51029)
Traceback (most recent call last):
File "c:\Anaconda3\lib\socketserver.py", line 639, in process_request_thread
self.finish_request(request, client_address)
File "c:\Anaconda3\lib\socketserver.py", line 361, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "c:\Anaconda3\lib\socketserver.py", line 696, in init
self.handle()
File "c:\Anaconda3\lib\site-packages\werkzeug\serving.py", line 232, in handle
rv = BaseHTTPRequestHandler.handle(self)
File "c:\Anaconda3\lib\http\server.py", line 418, in handle
self.handle_one_request()
File "c:\Anaconda3\lib\site-packages\werkzeug\serving.py", line 263, in handle_one_request
self.raw_requestline = self.rfile.readline()
File "c:\Anaconda3\lib\socket.py", line 586, in readinto
return self._sock.recv_into(b)
File "c:\Anaconda3\lib\site-packages\gevent_socket3.py", line 384, in recv_into
self._wait(self._read_event)
File "c:\Anaconda3\lib\site-packages\gevent_socket3.py", line 156, in _wait
self.hub.wait(watcher)
File "c:\Anaconda3\lib\site-packages\gevent\hub.py", line 651, in wait
result = waiter.get()
File "c:\Anaconda3\lib\site-packages\gevent\hub.py", line 898, in get
return self.hub.switch()
File "c:\Anaconda3\lib\site-packages\gevent\hub.py", line 630, in switch
return RawGreenlet.switch(self)
gevent.hub.LoopExit: ('This operation would block forever', <Hub at 0x283e3f62b90 select pending=0 ref=0>)

socket.gaierror: [Errno -2] Name or service not known

I've pulled the latest code and reinstalled -- getting this error (and a cascade of errors after that). It happens after running for a while, I'm inserting some debug statements in to see where it happens so I can try and catch it.

I am running cfscrape 1.9.1 in python3

If you can shed any light on why or where to look I'll continue testing.

Here's the error log:

Exception in thread Thread-4:
Traceback (most recent call last):
  File "/usr/local/lib/python3.5/dist-packages/urllib3-1.22-py3.5.egg/urllib3/connection.py", line 141, in _new_conn
    (self.host, self.port), self.timeout, **extra_kw)
  File "/usr/local/lib/python3.5/dist-packages/urllib3-1.22-py3.5.egg/urllib3/util/connection.py", line 60, in create_connection
    for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
  File "/usr/local/lib/python3.5/dist-packages/gevent/_socketcommon.py", line 288, in getaddrinfo
    return get_hub().resolver.getaddrinfo(host, port, family, type, proto, flags)
  File "/usr/local/lib/python3.5/dist-packages/gevent/resolver_thread.py", line 65, in getaddrinfo
    return self.pool.apply(_socket.getaddrinfo, args, kwargs)
  File "/usr/local/lib/python3.5/dist-packages/gevent/pool.py", line 325, in apply
    return self.spawn(func, *args, **kwds).get()
  File "/usr/local/lib/python3.5/dist-packages/gevent/event.py", line 385, in get
    return self.get(block=False)
  File "/usr/local/lib/python3.5/dist-packages/gevent/event.py", line 375, in get
    return self._raise_exception()
  File "/usr/local/lib/python3.5/dist-packages/gevent/event.py", line 355, in _raise_exception
    reraise(*self.exc_info)
  File "/usr/local/lib/python3.5/dist-packages/gevent/_compat.py", line 33, in reraise
    raise value.with_traceback(tb)
  File "/usr/local/lib/python3.5/dist-packages/gevent/threadpool.py", line 211, in _worker
    value = func(*args, **kwargs)
socket.gaierror: [Errno -2] Name or service not known

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.5/dist-packages/urllib3-1.22-py3.5.egg/urllib3/connectionpool.py", line 601, in urlopen
    chunked=chunked)
  File "/usr/local/lib/python3.5/dist-packages/urllib3-1.22-py3.5.egg/urllib3/connectionpool.py", line 346, in _make_request
    self._validate_conn(conn)
  File "/usr/local/lib/python3.5/dist-packages/urllib3-1.22-py3.5.egg/urllib3/connectionpool.py", line 850, in _validate_conn
    conn.connect()
  File "/usr/local/lib/python3.5/dist-packages/urllib3-1.22-py3.5.egg/urllib3/connection.py", line 284, in connect
    conn = self._new_conn()
  File "/usr/local/lib/python3.5/dist-packages/urllib3-1.22-py3.5.egg/urllib3/connection.py", line 150, in _new_conn
    self, "Failed to establish a new connection: %s" % e)
urllib3.exceptions.NewConnectionError: <urllib3.connection.VerifiedHTTPSConnection object at 0x7fd4003df780>: Failed to establish a new connection: [Errno -2] Name or servi
ce not known

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.5/dist-packages/requests-2.18.4-py3.5.egg/requests/adapters.py", line 440, in send
    timeout=timeout
  File "/usr/local/lib/python3.5/dist-packages/urllib3-1.22-py3.5.egg/urllib3/connectionpool.py", line 639, in urlopen
    _stacktrace=sys.exc_info()[2])
  File "/usr/local/lib/python3.5/dist-packages/urllib3-1.22-py3.5.egg/urllib3/util/retry.py", line 388, in increment
    raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='socket-beta.bittrex.com', port=443): Max retries exceeded with url: /signalr/negotiate?connectionData=%5B%7B%22name%22%3A+%22coreHub%22%7D%5D&clientProtocol=1.5 (Caused by NewConnectionError('<urllib3.connection.VerifiedHTTPSConnection object at 0x7fd4003df780>: Failed to establish a new connection: [Errno -2] Name or service not known',))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.5/threading.py", line 914, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.5/threading.py", line 862, in run
    self._target(*self._args, **self._kwargs)
  File "/usr/local/lib/python3.5/dist-packages/bittrex_websocket-0.0.5-py3.5.egg/bittrex_websocket/websocket_client.py", line 287, in _init_connection
    conn.start()
  File "/usr/local/lib/python3.5/dist-packages/signalr/_connection.py", line 47, in start
    negotiate_data = self.__transport.negotiate()
  File "/usr/local/lib/python3.5/dist-packages/signalr/transports/_auto_transport.py", line 16, in negotiate
    negotiate_data = Transport.negotiate(self)
  File "/usr/local/lib/python3.5/dist-packages/signalr/transports/_transport.py", line 26, in negotiate
    negotiate = self._session.get(url)
  File "/usr/local/lib/python3.5/dist-packages/requests-2.18.4-py3.5.egg/requests/sessions.py", line 521, in get
    return self.request('GET', url, **kwargs)
  File "/usr/local/lib/python3.5/dist-packages/cfscrape-1.9.0-py3.5.egg/cfscrape/__init__.py", line 39, in request
    resp = super(CloudflareScraper, self).request(method, url, *args, **kwargs)
  File "/usr/local/lib/python3.5/dist-packages/requests-2.18.4-py3.5.egg/requests/sessions.py", line 508, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/local/lib/python3.5/dist-packages/requests-2.18.4-py3.5.egg/requests/sessions.py", line 618, in send
    r = adapter.send(request, **kwargs)
  File "/usr/local/lib/python3.5/dist-packages/requests-2.18.4-py3.5.egg/requests/adapters.py", line 508, in send
    raise ConnectionError(e, request=request)
requests.exceptions.ConnectionError: HTTPSConnectionPool(host='socket-beta.bittrex.com', port=443): Max retries exceeded with url: /signalr/negotiate?connectionData=%5B%7B%22name%22%3A+%22coreHub%22%7D%5D&clientProtocol=1.5 (Caused by NewConnectionError('<urllib3.connection.VerifiedHTTPSConnection object at 0x7fd4003df780>: Failed to establish a new connection: [Errno -2] Name or service not known',))


Traceback (most recent call last):
  File "/usr/local/lib/python3.5/dist-packages/gevent/greenlet.py", line 536, in run
    result = self._run(*self.args, **self.kwargs)
  File "/usr/local/lib/python3.5/dist-packages/signalr/_connection.py", line 53, in wrapped_listener
    listener()
  File "/usr/local/lib/python3.5/dist-packages/signalr/transports/_ws_transport.py", line 42, in _receive
    for notification in self.ws:
  File "/usr/local/lib/python3.5/dist-packages/websocket/_core.py", line 105, in __iter__
    yield self.recv()
  File "/usr/local/lib/python3.5/dist-packages/websocket/_core.py", line 293, in recv
    opcode, data = self.recv_data()
  File "/usr/local/lib/python3.5/dist-packages/websocket/_core.py", line 310, in recv_data
    opcode, frame = self.recv_data_frame(control_frame)
  File "/usr/local/lib/python3.5/dist-packages/websocket/_core.py", line 323, in recv_data_frame
    frame = self.recv_frame()
  File "/usr/local/lib/python3.5/dist-packages/websocket/_core.py", line 357, in recv_frame
    return self.frame_buffer.recv_frame()
  File "/usr/local/lib/python3.5/dist-packages/websocket/_abnf.py", line 340, in recv_frame
    self.recv_header()
  File "/usr/local/lib/python3.5/dist-packages/websocket/_abnf.py", line 288, in recv_header
    header = self.recv_strict(2)
  File "/usr/local/lib/python3.5/dist-packages/websocket/_abnf.py", line 375, in recv_strict
    bytes_ = self.recv(min(16384, shortage))
  File "/usr/local/lib/python3.5/dist-packages/websocket/_core.py", line 427, in _recv
    return recv(self.sock, bufsize)
  File "/usr/local/lib/python3.5/dist-packages/websocket/_socket.py", line 93, in recv
    "Connection is already closed.")
websocket._exceptions.WebSocketConnectionClosedException: Connection is already closed.
Mon Dec 25 19:27:46 2017 <Greenlet at 0x7fd40068df20: wrapped_listener> failed with WebSocketConnectionClosedException

'NoneType' object has no attribute 'callback'

Since v0.0.6.3 I keep having this error published out so reporting as requested. I've included my log & script.

'NoneType' object has no attribute 'callback'
Got this exception from _on_tick_update. This is bug testing. Please report to https://github.com/slazarov/python-bittrex-websocket with this message
2018-02-24 10:16:06 - bittrex_websocket.websocket_client - INFO - [Connection][6a532f19f19041a3bb5f9ad680950737]:Connection to Bittrex established successfully through https://socket-stage.bittrex.com/signalr
2018-02-24 10:16:06 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][BTC-XVC]: Enabled.
2018-02-24 10:16:06 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][BTC-MEME]: Enabled.
2018-02-24 10:16:06 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][BTC-STEEM]: Enabled.
2018-02-24 10:16:06 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][BTC-2GIVE]: Enabled.
2018-02-24 10:16:06 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][BTC-LSK]: Enabled.
2018-02-24 10:16:06 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][BTC-PDC]: Enabled.
2018-02-24 10:16:06 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][BTC-BRK]: Enabled.
2018-02-24 10:16:06 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][BTC-WAVES]: Enabled.
2018-02-24 10:16:06 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][BTC-LBC]: Enabled.
2018-02-24 10:16:06 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][BTC-SBD]: Enabled.
2018-02-24 10:16:06 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][BTC-BRX]: Enabled.
2018-02-24 10:16:06 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][BTC-ETC]: Enabled.
2018-02-24 10:16:06 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][ETH-ETC]: Enabled.
2018-02-24 10:16:06 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][BTC-STRAT]: Enabled.
2018-02-24 10:16:06 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][BTC-UNB]: Enabled.
2018-02-24 10:16:06 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][BTC-SYNX]: Enabled.
2018-02-24 10:16:06 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][BTC-EBST]: Enabled.
2018-02-24 10:16:06 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][BTC-VRM]: Enabled.
2018-02-24 10:16:06 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][BTC-SEQ]: Enabled.
2018-02-24 10:16:06 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][BTC-REP]: Enabled.
2018-02-24 10:16:06 - bittrex_websocket.websocket_client - INFO - [Connection][350f35bf2d82479697716a6926932e46]:Trying to establish connection to Bittrex through https://socket-stage.bittrex.com/signalr.
from __future__ import print_function
from time import sleep
from bittrex_websocket.websocket_client import BittrexSocket
import os
import json
import redis
from bittrex.bittrex import Bittrex

def main():
  class SocketHandler(BittrexSocket):
    def on_open(self):
      self.redis = redis.Redis.from_url(os.environ['REDIS_URL'])

    def on_trades(self, msg):
      # print('[Trades]: {}'.format(msg['ticker']))

      for trade in msg['trades']:
        trade_json = {
          'exchange': 'bittrex',
          'base': msg['ticker'].split('-')[0].lower(),
          'quote': msg['ticker'].split('-')[1].lower(),
          'kind': trade['OrderType'].lower(),
          'quantity': trade['Quantity'],
          'price': trade['Rate'],
          'timestamp': trade['TimeStamp'],
        }

        print(json.dumps(trade_json))

        self.redis.publish('bittrex:trade:' + msg['ticker'].lower(), json.dumps(trade_json))

      # print('')

    def on_ticker_update(self, msg):
      price = {
        'base': msg['MarketName'].split('-')[0].lower(),
        'quote': msg['MarketName'].split('-')[1].lower(),
        'price': msg['Last'],
      }

      print(json.dumps(price))

      self.redis.publish('bittrex:price:' + price['base'] + '-' + price['quote'], price['price'])
      self.redis.set('bittrex:price:' + price['base'] + '-' + price['quote'], price['price'])

      # print('')

  # Define tickers
  bittrex = Bittrex(None, None)
  tickers = list(map(lambda market: market['MarketName'], bittrex.get_markets()['result']))

  print(tickers)

  # Create the socket instance
  ws = SocketHandler()

  # Enable logging
  ws.enable_log()

  # Subscribe to trade fills
  ws.subscribe_to_trades(tickers)
  ws.subscribe_to_ticker_update(tickers)

  while True:
    sleep(1)

if __name__ == "__main__":
  main()

Websocket failing to connect

Good Morning,

The websocket connection has recently been failing in my script. Is it due to upgrades on the server side or I need to upgrade one of the modules I am using.

Here is the list of the modules in my pip3:

asn1crypto (0.22.0)
bittrex-websocket (0.0.6.2.2)
certifi (2017.4.17)
cffi (1.11.4)
cfscrape (1.9.2)
chardet (3.0.4)
command-not-found (0.3)
cryptography (2.1.4)
distro-info (0.17)
Events (0.3)
gevent (1.3a1)
greenlet (0.4.12)
httplib2 (0.9.2)
idna (2.5)
keyring (10.4.0)
keyrings.alt (2.2)
language-selector (0.1)
numpy (1.14.0)
pip (9.0.1)
pycparser (2.18)
pycrypto (2.6.1)
PyExecJS (1.5.1)
pygobject (3.24.1)
pyOpenSSL (17.5.0)
python-apt (1.4.0b3)
python-bittrex (0.3.0)
python-debian (0.1.30)
pyxdg (0.25)
PyYAML (3.12)
requests (2.7.0)
SecretStorage (2.3.1)
setuptools (36.2.7)
signalr-client (0.0.7)
six (1.10.0)
sseclient (0.0.18)
ssh-import-id (5.7)
systemd-python (234)
ufw (0.35)
unattended-upgrades (0.1)
urllib3 (1.21.1)
websocket-client (0.46.0)
wheel (0.29.0)

Cheers

Doesn't do anything after "Establishing connection to Bittrex"

PS C:\Python27\Lib\site-packages> python -m bittrex_websocket.websocket_client.py
2018-04-21 12:23:39 - bittrex_websocket.websocket_client - INFO - Establishing connection to Bittrex.

The code I ran is the example you did, I pasted it in websocket_client.py

class MySocket(BittrexSocket):
        def __init__(self):
            super(MySocket, self).__init__()
            self.ticker_updates_container = {}

        def on_public(self, msg):
            name = msg['M']
            if name not in self.ticker_updates_container:
                self.ticker_updates_container[name] = msg
                print ('Just received market update for {}.'.format(name))

ws = MySocket()

# Enable logging
ws.enable_log()

# Define tickers
tickers = ['BTC-ETH', 'BTC-NEO', 'BTC-ZEC', 'ETH-NEO', 'ETH-ZEC']

# Subscribe to ticker information
for ticker in tickers:
    sleep(0.01)
    ws.subscribe_to_exchange_deltas([ticker])

while len(ws.ticker_updates_container) < len(tickers):
        sleep(1)
else:
    print ('We have received updates for all tickers. Closing...')
    ws.disconnect()
    sleep(10)

As I mentioned in the title, it doesn't do anything after that message. Am I missing something or do I got a problem?

Before this problem I was getting some stuff with:
"Exception in thread SocketConnection (most likely raised during interpreter shutdown):" idk if it's important or not.
Appreciate the help.

ImportError: No module named 'bittrex_websocket'

So I installed everything with:

sudo apt-get install python-setuptools python-dev build-essential libssl-dev libffi-dev
sudo easy_install pip
pip install git+https://github.com/slazarov/python-bittrex-websocket.git

Then when I try to execute:

python /usr/local/lib/python2.7/dist-packages/bittrex_websocket/examples/ticker_updates.py

I get the following error:

Traceback (most recent call last):
  File "ticker_updates.py", line 18, in <module>
    from bittrex_websocket.websocket_client import BittrexSocket
ImportError: No module named bittrex_websocket.websocket_client

What did I miss?

Logging both to file and stdout

Hey,

I have enabled logging and set a file to be logged there.
I noticed that this will log both to the file and stdout.

Would it be possible to log only to the file?

huge memory leak right after reconnect

The code just like in example
only with subscribe_to_exchange_deltas

Output

2018-05-06 18:55:35 - bittrex_websocket.websocket_client - ERROR - Connection is already closed..
2018-05-06 18:55:35 - bittrex_websocket.websocket_client - ERROR - Initiating reconnection procedure
2018-05-06 18:55:35 - bittrex_websocket.websocket_client - INFO - Establishing connection to Bittrex through https://beta.bittrex.com/signalr.
2018-05-06 18:55:39 - bittrex_websocket.websocket_client - INFO - Successfully subscribed to [QueryExchangeState] for [BTC-ZCL].
2018-05-06 18:55:39 - bittrex_websocket.websocket_client - INFO - Successfully subscribed to [SubscribeToExchangeDeltas] for [BTC-ZCL].
2018-05-06 18:55:39 - bittrex_websocket.websocket_client - INFO - Successfully subscribed to [QueryExchangeState] for [BTC-RDD].
2018-05-06 18:55:39 - bittrex_websocket.websocket_client - INFO - Successfully subscribed to [SubscribeToExchangeDeltas] for [BTC-RDD].
2018-05-06 18:55:39 - bittrex_websocket.websocket_client - INFO - Successfully subscribed to [QueryExchangeState] for [BTC-TRX].
2018-05-06 18:55:39 - bittrex_websocket.websocket_client - INFO - Successfully subscribed to [SubscribeToExchangeDeltas] for [BTC-TRX].
2018-05-06 18:56:20.775091 15593
2018-05-06 18:57:20.835102 15659
2018-05-06 18:58:21.108694 15691
2018-05-06 18:59:30.381624 15736
2018-05-06 19:00:06 - bittrex_websocket.websocket_client - ERROR - Undocumented error message received with code -1 and payload: 32. Report to https://github.com/slazarov/python-bittrex-websocket
2018-05-06 19:00:06 - bittrex_websocket.websocket_client - ERROR - Initiating reconnection procedure
2018-05-06 19:00:06 - bittrex_websocket.websocket_client - INFO - Establishing connection to Bittrex through https://beta.bittrex.com/signalr.

After first reconnect app starts to eat all available memory and swap.

It works fine, but when compiling I'm not able to make it run ( pyinstaller )

2018-03-13 09:51:55 - bittrex_websocket.websocket_client - INFO - [Connection]

[161b25740b7045d28881129964a45742]:Trying to establish connection to Bittrex through https://socket-stage.bittrex.com/signalr.
Exception in thread Thread-1:
Traceback (most recent call last):
File "threading.py", line 916, in _bootstrap_inner
File "threading.py", line 864, in run
File "site-packages\bittrex_websocket\websocket_client.py", line 327, in _init_connection
File "site-packages\bittrex_websocket_signalr.py", line 17, in start
File "site-packages\signalr\transports_auto_transport.py", line 28, in start
File "site-packages\signalr\transports_ws_transport.py", line 38, in start
File "site-packages\websocket_core.py", line 494, in create_connection
File "site-packages\websocket_core.py", line 217, in connect
File "site-packages\websocket_http.py", line 76, in connect
File "site-packages\websocket_http.py", line 191, in _ssl_socket
File "site-packages\websocket_http.py", line 144, in _wrap_sni_socket
TypeError: cafile, capath and cadata cannot be all omitted

2018-03-13 09:52:15 - bittrex_websocket.websocket_client - ERROR - Failed to subscribe [OrderBook][['BTC-ETH', 'BTC-NEO', 'BTC-ZEC', 'ETH-NEO', 'ETH-ZEC']] from connection 161b25740b7045d28881129964a45742 after 20 seconds. The connection is probably down

Incomplete?

Hi :)

Why do all the interesting functions have "raise NotImplementedError" ?
So in fact this project is not functional yet? Or where can I find "subscribe_to_orderbook" and other functions?

In addition:
I struggle with this "conn.wait()" command... It seems this is blocking, but without it nothing works.
So how can I start the WS connection and still continue the script simultanously?

on_orderbook_update call twice

when i use subscribe_to_orderbook and subscribe_to_orderbook_update on same tickers at the same time, i will receive two same nounce on_orderbook_update from different thread. i think you can handle it in the module

Orderbook Update Types

Orderbook updates seem to have types of 1, 2 or 3. Does anyone know what these types signify? Are updates sent when orders are closed or cancelled? Thanks,

David

What is the meaning of `Type` in data getting from `subscribe_to_orderbook_update()`?

I got,

{'asks': [],
 'bids': [{'Quantity': 6.66416248, 'Rate': 0.10008401, 'Type': 0},
          {'Quantity': 0.0, 'Rate': 0.10006604, 'Type': 1},
          {'Quantity': 0.0, 'Rate': 0.10000279, 'Type': 1},
          {'Quantity': 184.98650139, 'Rate': 0.09997183, 'Type': 0}],
 'nounce': 25473,
 'ticker': 'BTC-ETH',
 'timestamp': 1518162631.0817032}

Want to know about the meaning of Type in the data.

Where can I check the meaning of each field?

RecursionError: maximum recursion depth exceeded while calling a Python object [py36]

  • Python version: Python 3.6.4 downloaded from python.org
  • Operating System: macOS 10.13.3 (17D102)

Description:

I'm tryng to send a POST inside of a websocket. So, I got this error:

Traceback (most recent call last):
  File "apps/core/order_book.py", line 84, in <module>
    thing()
  File "apps/core/order_book.py", line 69, in thing
    dp.bot.send_message(chat_id="-287763810", text="We are the champions!")
  File "/Users/victorhvs/Workspace/victorhvs/calltraderbot/env/lib/python3.6/site-packages/telegram/bot.py", line 60, in decorator
    result = func(self, *args, **kwargs)
  File "/Users/victorhvs/Workspace/victorhvs/calltraderbot/env/lib/python3.6/site-packages/telegram/bot.py", line 85, in decorator
    result = self._request.post(url, data, timeout=kwargs.get('timeout'))
  File "/Users/victorhvs/Workspace/victorhvs/calltraderbot/env/lib/python3.6/site-packages/telegram/utils/request.py", line 273, in post
    **urlopen_kwargs)
  File "/Users/victorhvs/Workspace/victorhvs/calltraderbot/env/lib/python3.6/site-packages/telegram/utils/request.py", line 190, in _request_wrapper
    resp = self._con_pool.request(*args, **kwargs)
  File "/Users/victorhvs/Workspace/victorhvs/calltraderbot/env/lib/python3.6/site-packages/telegram/vendor/ptb_urllib3/urllib3/request.py", line 70, in request
    **urlopen_kw)
  File "/Users/victorhvs/Workspace/victorhvs/calltraderbot/env/lib/python3.6/site-packages/telegram/vendor/ptb_urllib3/urllib3/request.py", line 148, in request_encode_body
    return self.urlopen(method, url, **extra_kw)
  File "/Users/victorhvs/Workspace/victorhvs/calltraderbot/env/lib/python3.6/site-packages/telegram/vendor/ptb_urllib3/urllib3/poolmanager.py", line 244, in urlopen
    response = conn.urlopen(method, u.request_uri, **kw)
  File "/Users/victorhvs/Workspace/victorhvs/calltraderbot/env/lib/python3.6/site-packages/telegram/vendor/ptb_urllib3/urllib3/connectionpool.py", line 617, in urlopen
    chunked=chunked)
  File "/Users/victorhvs/Workspace/victorhvs/calltraderbot/env/lib/python3.6/site-packages/telegram/vendor/ptb_urllib3/urllib3/connectionpool.py", line 360, in _make_request
    self._validate_conn(conn)
  File "/Users/victorhvs/Workspace/victorhvs/calltraderbot/env/lib/python3.6/site-packages/telegram/vendor/ptb_urllib3/urllib3/connectionpool.py", line 857, in _validate_conn
    super(HTTPSConnectionPool, self)._validate_conn(conn)
  File "/Users/victorhvs/Workspace/victorhvs/calltraderbot/env/lib/python3.6/site-packages/telegram/vendor/ptb_urllib3/urllib3/connectionpool.py", line 289, in _validate_conn
    conn.connect()
  File "/Users/victorhvs/Workspace/victorhvs/calltraderbot/env/lib/python3.6/site-packages/telegram/vendor/ptb_urllib3/urllib3/connection.py", line 314, in connect
    cert_reqs=resolve_cert_reqs(self.cert_reqs),
  File "/Users/victorhvs/Workspace/victorhvs/calltraderbot/env/lib/python3.6/site-packages/telegram/vendor/ptb_urllib3/urllib3/util/ssl_.py", line 264, in create_urllib3_context
    context.options |= options
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/ssl.py", line 465, in options
    super(SSLContext, SSLContext).options.__set__(self, value)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/ssl.py", line 465, in options
    super(SSLContext, SSLContext).options.__set__(self, value)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/ssl.py", line 465, in options
    super(SSLContext, SSLContext).options.__set__(self, value)
  [Previous line repeated 321 more times]
RecursionError: maximum recursion depth exceeded while calling a Python object

What I've run:

import logging

from telegram.ext import (Updater)
from time import sleep
from bittrex_websocket.websocket_client import BittrexSocket

updater = Updater("XXX", request_kwargs={'read_timeout': 6, 'connect_timeout': 7})
dp = updater.dispatcher

def thing():
    class MySocket(BittrexSocket):
        pass

    # Create the socket instance
    ws = MySocket()
    # Enable logging
    ws.enable_log()
    # Define tickers
    tickers = ['BTC-ETH', 'BTC-LTC', 'BTC-ZEC', 'ETH-NEO', 'ETH-ZEC']
    # Subscribe to live order book
    ws.subscribe_to_orderbook(tickers)

    while True:
        i = 0
        sleep(1)
        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:
                dp.bot.send_message(chat_id="237810", text="We are the champions!")
        
        else:
            sleep(1)

thing()

I got error with this peace:

dp.bot.send_message(chat_id="-287763810", text="We are the champions!")

But using outside of the websocket I dont get erros.

Entire library not working because cloudflare issue

Hello,

Thank you so much for writing this library, it has been immensely useful! Starting very recently, I started getting this issue pasted below. I ran the system on two different machines with different ip's and also tried to update the cfscrape library. The issue is fatal, causing the entire library to not work.

Please let me know what you think the best fix is:

Traceback (most recent call last): File "/usr/lib/python3.5/threading.py", line 914, in _bootstrap_inner self.run() File "/home/ubuntu/gerald/bittrex-ws/bittrex_websocket/bittrex.py", line 200, in run self.conn.start() File "/home/ubuntu/gerald/bittrex-ws/bittrex_websocket/_signalr.py", line 15, in start negotiate_data = self.__transport.negotiate() File "/home/ubuntu/gerald/bittrex-ws/env/lib/python3.5/site-packages/signalr/transports/_auto_transport.py", line 16, in negotiate negotiate_data = Transport.negotiate(self) File "/home/ubuntu/gerald/bittrex-ws/env/lib/python3.5/site-packages/signalr/transports/_transport.py", line 26, in negotiate negotiate = self._session.get(url) File "/home/ubuntu/gerald/bittrex-ws/env/lib/python3.5/site-packages/requests/sessions.py", line 521, in get return self.request('GET', url, **kwargs) File "/home/ubuntu/gerald/bittrex-ws/env/lib/python3.5/site-packages/cfscrape/__init__.py", line 66, in request resp = self.solve_cf_challenge(resp, **kwargs) File "/home/ubuntu/gerald/bittrex-ws/env/lib/python3.5/site-packages/cfscrape/__init__.py", line 97, in solve_cf_challenge params["jschl_answer"] = str(self.solve_challenge(body) + len(domain)) File "/home/ubuntu/gerald/bittrex-ws/env/lib/python3.5/site-packages/cfscrape/__init__.py", line 127, in solve_challenge raise ValueError("Error parsing Cloudflare IUAM Javascript challenge. %s" % BUG_REPORT) ValueError: Error parsing Cloudflare IUAM Javascript challenge. Cloudflare may have changed their technique, or there may be a bug in the script.

Random exception

I got today this exception - I am monitoring all pairs. I accept the fact, that the connection may fail randomly, as Bittrex websocket is not to reliable... but these pairs stopped to be monitored. The exception is probably not caught and the thread exits. Do you have some idea how to fix this?

The workaround here that comes to my mind is to monitor all files if the last trade is not too old -> probably connection down. But then I have to restart other pairs as well as you are using max_tickers_per_conn for one connection and it is not possible to restart just one chunk.

Catching this exception would help me a lot.

2018-01-27 16:35:17 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][USDT-NXT]: Enabled.
2018-01-27 16:35:17 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][USDT-OMG]: Enabled.
2018-01-27 16:35:17 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][USDT-XMR]: Enabled.
2018-01-27 16:35:17 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][USDT-XRP]: Enabled.
2018-01-27 16:35:17 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][USDT-XVG]: Enabled.
2018-01-27 16:35:17 - bittrex_websocket._auxiliary - INFO - [Subscription][Trades][USDT-ZEC]: Enabled.
Traceback (most recent call last):
  File "C:\Python27\lib\site-packages\gevent\hub.py", line 866, in switch
Traceback (most recent call last):
  File "C:\Python27\lib\site-packages\gevent\greenlet.py", line 536, in run
    result = self._run(*self.args, **self.kwargs)
  File "C:\Python27\lib\site-packages\signalr\_connection.py", line 53, in wrapped_listener
    listener()
  File "C:\Python27\lib\site-packages\signalr\transports\_ws_transport.py", line 42, in _receive
    for notification in self.ws:
  File "C:\Python27\lib\site-packages\websocket\_core.py", line 107, in __iter__
    switch(value)
  File "C:\Python27\lib\site-packages\gevent\greenlet.py", line 538, in run
    self._report_error(sys.exc_info())
  File "C:\Python27\lib\site-packages\gevent\greenlet.py", line 520, in _report_error
    yield self.recv()
  File "C:\Python27\lib\site-packages\websocket\_core.py", line 296, in recv
    self._exc_info = exc_info[0], exc_info[1], dump_traceback(exc_info[2])
    opcode, data = self.recv_data()
  File "C:\Python27\lib\site-packages\websocket\_core.py", line 313, in recv_data
  File "C:\Python27\lib\site-packages\gevent\_tblib.py", line 370, in g
    opcode, frame = self.recv_data_frame(control_frame)
  File "C:\Python27\lib\site-packages\websocket\_core.py", line 326, in recv_data_frame
    frame = self.recv_frame()
  File "C:\Python27\lib\site-packages\websocket\_core.py", line 360, in recv_frame
    return self.frame_buffer.recv_frame()
  File "C:\Python27\lib\site-packages\websocket\_abnf.py", line 340, in recv_frame
    self.recv_header()
  File "C:\Python27\lib\site-packages\websocket\_abnf.py", line 288, in recv_header
    header = self.recv_strict(2)
  File "C:\Python27\lib\site-packages\websocket\_abnf.py", line 375, in recv_strict
    return f(a)
  File "C:\Python27\lib\site-packages\gevent\_tblib.py", line 425, in dump_traceback
    bytes_ = self.recv(min(16384, shortage))
  File "C:\Python27\lib\site-packages\websocket\_core.py", line 430, in _recv
    return dumps(tb)
TypeError: 'NoneType' object is not callable
Sat Jan 27 16:39:01 2018    return recv(self.sock, bufsize)
   File "C:\Python27\lib\site-packages\websocket\_socket.py", line 94, in recv
<built-in method switch of Greenlet object at 0x0000000008F23DF0> failed with TypeError

    "Connection is already closed.")
WebSocketConnectionClosedException: Connection is already closed.
Sat Jan 27 16:39:01 2018 <Greenlet at 0x90300e0L: wrapped_listener> failed with WebSocketConnectionClosedException

Example `ticker_updates.py` fails on Python 3

When I download and run this example, it first complains that ticker_updates_container is not an attribute of ws. I assume this means on_open() is not running on time before the while loop starts running. Therefore, I overrode the __init__ for MySocket as follows:

def __init__(self):
    super().__init__()
    self.ticker_updates_container = {}

Even then, I get this error later:

$ python ticker_updates.py
2018-02-20 18:21:36 - bittrex_websocket.websocket_client - INFO - [Connection][009cd9f08d954f7d91d5d59f15c8b583]:Trying to establish connection to Bittrex through https://socket-stage.bittrex.com/signalr.
2018-02-20 18:21:41 - bittrex_websocket.websocket_client - ERROR - [Connection][009cd9f08d954f7d91d5d59f15c8b583]:Timeout for url https://socket-stage.bittrex.com/signalr. Please check your internet connection is on.
2018-02-20 18:21:41 - bittrex_websocket.websocket_client - INFO - [Connection][009cd9f08d954f7d91d5d59f15c8b583]:Trying to establish connection to Bittrex through https://socket.bittrex.com/signalr.
2018-02-20 18:21:47 - bittrex_websocket.websocket_client - ERROR - [Connection][009cd9f08d954f7d91d5d59f15c8b583]:Timeout for url https://socket.bittrex.com/signalr. Please check your internet connection is on.
2018-02-20 18:21:47 - bittrex_websocket.websocket_client - ERROR - [Connection][009cd9f08d954f7d91d5d59f15c8b583]:Failed to establish connection through supplied URLS. Leaving to watchdog...
2018-02-20 18:21:56 - bittrex_websocket.websocket_client - ERROR - Failed to subscribe [TickerUpdate][['BTC-ETH', 'BTC-NEO', 'BTC-ZEC', 'ETH-NEO', 'ETH-ZEC']] from connection 009cd9f08d954f7d91d5d59f15c8b583 after 20 seconds. The connection is probably down.

I know the Node library node.bittrex.api uses the WebSocket URL wss://socket.bittrex.com/signalr and that library works for me.

Could it be an issue with the URL? If so, can I change the URL through options without changing BittrexSocket?

ImportError: cannot import name 'create_connection'

When I tried to import bittrex_websocket on my jupyter-notebook, I got an ImportError.
This error is telling me there is no create_connection module from websocket.

import bittrex_websocket
---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
<ipython-input-17-535727247b22> in <module>()
----> 1 import bittrex_websocket

~/.conda/envs/py3/lib/python3.6/site-packages/bittrex_websocket/__init__.py in <module>()
----> 1 from bittrex_websocket.order_book import OrderBook
      2 from bittrex_websocket.websocket_client import BittrexSocket

~/.conda/envs/py3/lib/python3.6/site-packages/bittrex_websocket/order_book.py in <module>()
     16 from requests import get
     17 
---> 18 from bittrex_websocket.websocket_client import BittrexSocket
     19 
     20 

~/.conda/envs/py3/lib/python3.6/site-packages/bittrex_websocket/websocket_client.py in <module>()
     10 import cfscrape
     11 from requests import Session
---> 12 from signalr import Connection
     13 
     14 

~/.conda/envs/py3/lib/python3.6/site-packages/signalr/__init__.py in <module>()
      4 monkey.patch_ssl()
      5 
----> 6 from ._connection import Connection
      7 
      8 __version__ = '0.0.7'

~/.conda/envs/py3/lib/python3.6/site-packages/signalr/_connection.py in <module>()
      3 from signalr.events import EventHook
      4 from signalr.hubs import Hub
----> 5 from signalr.transports import AutoTransport
      6 
      7 

~/.conda/envs/py3/lib/python3.6/site-packages/signalr/transports/__init__.py in <module>()
----> 1 from ._auto_transport import AutoTransport

~/.conda/envs/py3/lib/python3.6/site-packages/signalr/transports/_auto_transport.py in <module>()
      1 from ._transport import Transport
      2 from ._sse_transport import ServerSentEventsTransport
----> 3 from ._ws_transport import WebSocketsTransport
      4 
      5 

~/.conda/envs/py3/lib/python3.6/site-packages/signalr/transports/_ws_transport.py in <module>()
      9     from urllib.parse import urlparse, urlunparse
     10 
---> 11 from websocket import create_connection
     12 from ._transport import Transport
     13 

ImportError: cannot import name 'create_connection'

But, when I tried to import it on ipython console, it worked!

Why is it not working on jupyter notebook?

Running Example receive 503 error

2017-12-23 11:31:02 - bittrex_websocket.websocket_client - INFO - Trying to establish connection to Bittrex through https://socket-stage.bittrex.com/signalr.
Exception in thread Thread-2:
Traceback (most recent call last):
  File "C:\Program Files\Python36\Lib\threading.py", line 916, in _bootstrap_inner
    self.run()
  File "C:\Program Files\Python36\Lib\threading.py", line 864, in run
    self._target(*self._args, **self._kwargs)
  File "D:\Documents\auto_bittrex\python-bittrex-websocket\bittrex_websocket\websocket_client.py", line 287, in _init_connection
    conn.start()
  File "D:\Documents\auto_bittrex\venv\lib\site-packages\signalr\_connection.py", line 50, in start
    listener = self.__transport.start()
  File "D:\Documents\auto_bittrex\venv\lib\site-packages\signalr\transports\_auto_transport.py", line 28, in start
    return self.__transport.start()
  File "D:\Documents\auto_bittrex\venv\lib\site-packages\signalr\transports\_ws_transport.py", line 38, in start
    enable_multithread=True)
  File "D:\Documents\auto_bittrex\venv\lib\site-packages\websocket\_core.py", line 487, in create_connection
    websock.connect(url, **options)
  File "D:\Documents\auto_bittrex\venv\lib\site-packages\websocket\_core.py", line 214, in connect
    self.handshake_response = handshake(self.sock, *addrs, **options)
  File "D:\Documents\auto_bittrex\venv\lib\site-packages\websocket\_handshake.py", line 69, in handshake
    status, resp = _get_resp_headers(sock)
  File "D:\Documents\auto_bittrex\venv\lib\site-packages\websocket\_handshake.py", line 129, in _get_resp_headers
    raise WebSocketBadStatusException("Handshake status %d", status)
websocket._exceptions.WebSocketBadStatusException: Handshake status 503

2017-12-23 11:31:23 - bittrex_websocket.websocket_client - INFO - Failed to subscribe [Trades][['BTC-ETH', 'BTC-XMR']] from connection b00ffeefc6bc4bce8b93e63b18e107e0 after 20 seconds. The connection is probably down.

maybe the problem of url?

Version 0.0.6.x topic

I haven't been active for the past 2/3 weeks so leaving a note here to highlight how reconnection will be implemented in v0.0.6.

The experimental implementation will work in the following way:

  • a watchdog thread will monitor subscriptions and check if their respective connections are active.
  • if the connection is inactive, the watchdog will send an unsubscribe method followed by subscribe method
  • a connection is marked as inactive upon exception in def _init_connection(self, conn_obj)

This implementation works on the base that connections are established independently of subscriptions. When an exception is reached in def _init_connection(self, conn_obj), the script will try to reconnect with the extra URL. If this fails, the thread that holds the connection will die. However, since the watchdog is in a separate thread, it will detect that the connection is inactive and will try to establish a new one and the whole thing begins again.

As always, I am open to recommendations.

[Update] 22/Jan/18
Due to changes in the how the code is organised as of 0.0.6.x you might get an error message when you declare a variable in on_open and then try to access it immediately. E.g:

Traceback (most recent call last):
File "python-bittrex-websocket/bittrex_websocket/examples/ticker_updates.py", line 49, in
2018-01-22 07:49:39 - bittrex_websocket.websocket_client - INFO - [Connection][da64c763df6e411c9663004a1baefec6]:Trying to establish connection to Bittrex through https://socket-stage.bittrex.com/signalr.
main()
File "python-bittrex-websocket/bittrex_websocket/examples/ticker_updates.py", line 41, in main
while len(ws.ticker_updates_container) < len(tickers):
AttributeError: 'MySocket' object has no attribute 'ticker_updates_container'

Quick workaround before I fix it is to introduce some delay after subscribing but before your logic, e.g time.sleep(5).

[Update] 21/Jan/18
Version 0.0.6.2

  • Every 5400s (1hr30) the script will force reconnection.
  • Every reconnection (including the above) will be done with a fresh cookie
  • Upon reconnection the script will check if the connection has been running for more than 600s (10mins). If it has been running for less it will use the backup url.

The timeouts (5400 and 10) are not final and are subject to results.

[Update] 14/Jan/18
I've been experimenting for the past few days and I have found that Bittrex has an embedded auto-reconnection. Meaning that if the connection drops and is reconnected through the same session either through cfscrape or requests, the invokes persist at a server level and sync with the client. Thought I have to note that I haven't tried to unsubscribe an invoke and apply a different session to it.

Anyways 0.0.6 is getting closer and thanks for the wait!

Stan

HTTP requests needs to use cookie and agent from cfscrape

Example

I wrote the Bittrex API again to include the handling of cloudflare cookies. Using the cookie from cf gives the status of a non bot and this gives the opportunity to use features which aren't possible otherwise.

My proposal is, that the websocket api class provides a parameter for a class instance which contains cookie and http agent. In the case the parameter is None, the API uses the internal instance from cfscrape. I will write a gist for the proposed class

Multiple updates for 'all tickers' in the _on_ticker_update function

I guess that the 'for' cycle on the line 1010 (websocket_client.py) will better start after 'else' on the line 1013, so the code will be:
if 'Deltas' in msg: if self.tickers.get_sub_state(ALL_TICKERS, SUB_TYPE_TICKERUPDATE) is SUB_STATE_ON: self.updateSummaryState.on_change(msg['Deltas']) else: for update in msg['Deltas']: try: ticker = update['MarketName']

Then we won't multiply msg for all tickers.

I get the following error ( Solved )

2018-03-06 14:34:23 - bittrex_websocket.websocket_client - INFO - [Connection][5ba904306a12492f9346af0e8dca15f9]:Trying to establish connection to Bittrex through https://socket-stage.bittrex.com/signalr.

2018-03-06 14:34:28 - bittrex_websocket.websocket_client - ERROR - [Connection][5ba904306a12492f9346af0e8dca15f9]:Timeout for url https://socket-stage.bittrex.com/signalr. Please check your internet connection is on.

2018-03-06 14:34:28 - bittrex_websocket.websocket_client - INFO - [Connection][5ba904306a12492f9346af0e8dca15f9]:Trying to establish connection to Bittrex through https://socket.bittrex.com/signalr.

2018-03-06 14:34:33 - bittrex_websocket.websocket_client - ERROR - [Connection][5ba904306a12492f9346af0e8dca15f9]:Timeout for url https://socket.bittrex.com/signalr. Please check your internet connection is on.

2018-03-06 14:34:33 - bittrex_websocket.websocket_client - ERROR - [Connection][5ba904306a12492f9346af0e8dca15f9]:Failed to establish connection through supplied URLS. Leaving to watchdog...

2018-03-06 14:34:43 - bittrex_websocket.websocket_client - ERROR - Failed to subscribe [OrderBook][['BTC-ETH']] from connection 5ba904306a12492f9346af0e8dca15f9 after 20 seconds. The connection is probably down.

Traceback (most recent call last):

File "F:\eclipse\eclipse-workspace\Web_Socket_Python\docker\example.py", line 57, in
main()

File "F:\eclipse\eclipse-workspace\Web_Socket_Python\docker\example.py", line 34, in main
ws.subscribe_to_orderbook(tickers)

File "F:\eclipse\eclipse-workspace\Web_Socket_Python\bittrex_websocket\websocket_client.py", line 742, in subscribe_to_orderbook
self.tickers.set_book_depth(tickers, book_depth)

File "F:\eclipse\eclipse-workspace\Web_Socket_Python\bittrex_websocket_auxiliary.py", line 153, in set_book_depth
raise RuntimeError("Unable to set order book depth, timeout")

RuntimeError: Unable to set order book depth, timeout

Error at running in a docker container

I have simple code to watch ticker & order book:

from time import sleep
from datetime import datetime

from bittrex_websocket.websocket_client import BittrexSocket


class MySocket(BittrexSocket):
    def on_orderbook(self, msg):
        print(f'on_orderbook at {self.now}')

    def on_orderbook_update(self, msg):
        print(f'on_orderbook_update at {self.now}')

    def on_ticker_update(self, msg):
        print(f'on_ticker_update at {self.now}')

    @property
    def now(self):
        return datetime.now().strftime('%M:%S')


if __name__ == "__main__":
    ws = MySocket()
    ws.enable_log()

    ws.subscribe_to_orderbook(['USDT-ETH'], 30)
    ws.subscribe_to_ticker_update(['USDT-ETH'])

    while True:
        try:
            sleep(1)
        except KeyboardInterrupt:
            ws.disconnect()

I try to running it at docker (Python 3.6.0):

version: '2'
services:
  collector:
    build: './back/.'
    restart: 'always'
    command: 'python bittrex-collector.py'
    working_dir: '/app/'
    volumes:
      - './back:/app'

I have the errors when (docker-compose up):

Creating trusttrade_redis_1     ... done
Creating trusttrade_redis_1     ...
Creating trusttrade_collector_1 ... done
Attaching to trusttrade_collector_1
collector_1  | 2018-03-20 13:30:15 - bittrex_websocket.websocket_client - INFO - [Connection][22980b5d6c4b42e8863abc6029fea332]:Trying to establish connection to Bittrex through https://socket-stage.bittrex.com/signalr.
collector_1  | 2018-03-20 13:30:20 - bittrex_websocket.websocket_client - ERROR - [Connection][22980b5d6c4b42e8863abc6029fea332]:Timeout for url https://socket-stage.bittrex.com/signalr. Please check your internet connection is on.
collector_1  | 2018-03-20 13:30:20 - bittrex_websocket.websocket_client - INFO - [Connection][22980b5d6c4b42e8863abc6029fea332]:Trying to establish connection to Bittrex through https://socket.bittrex.com/signalr.
collector_1  | 2018-03-20 13:30:25 - bittrex_websocket.websocket_client - ERROR - [Connection][22980b5d6c4b42e8863abc6029fea332]:Timeout for url https://socket.bittrex.com/signalr. Please check your internet connection is on.
collector_1  | 2018-03-20 13:30:25 - bittrex_websocket.websocket_client - ERROR - [Connection][22980b5d6c4b42e8863abc6029fea332]:Failed to establish connection through supplied URLS. Leaving to watchdog...
collector_1  | 2018-03-20 13:30:35 - bittrex_websocket.websocket_client - ERROR - Failed to subscribe [OrderBook][['USDT-ETH']] from connection 22980b5d6c4b42e8863abc6029fea332 after 20 seconds. The connection is probably down.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.