Skip to content
This repository has been archived by the owner on Oct 13, 2023. It is now read-only.

huge memory leak right after reconnect #61

Open
gzivdo opened this issue May 6, 2018 · 62 comments
Open

huge memory leak right after reconnect #61

gzivdo opened this issue May 6, 2018 · 62 comments
Labels

Comments

@gzivdo
Copy link

gzivdo commented May 6, 2018

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.

@slazarov
Copy link
Owner

slazarov commented May 6, 2018

Error 32 should refer to socket.error: [Errno 32] Broken pipe and is due to connection drop. If your connection is working fine, then I suspect that the error is coming from Bittrex's side since recently they have been pushing constant updates in order to get the main endpoint stable. Note that we are using the beta endpoint currently in order to avoid bypassing cloudflare. You can try:

ws = MySocket(url='https://socket.bittrex.com/signalr')

Just make sure you have installed cfscrape and node.js.

The reconnection memory leak is due to the fact that the client tries to reconnect and since it's denied immediately it goes into an infinite loop which causes high CPU usage. This is on my side and I will implement a fix. I am thinking of maximum connection retries solution.

@slazarov slazarov added the bug label May 6, 2018
@gzivdo
Copy link
Author

gzivdo commented May 6, 2018

cpu usage not high at all, but memory usage rising quite fast.

@slazarov
Copy link
Owner

slazarov commented May 6, 2018

Doesn't change the fact.

Also when posting make sure you specify what Python version you are using and also provide the code you are executing. In this case you said you are using the example but you are also invoking QueryExchangeState and I have no idea whether you are executing it in a loop.

@gzivdo
Copy link
Author

gzivdo commented May 6, 2018

Python 2.7.x

from bittrex_websocket.websocket_client import BittrexSocket
import cPickle, time, datetime

tickers = {
    'ZCL':  (35, 5),
    'RDD': (20000, 2000),
    'TRX': (5000, 2000),
}


class BittrexSocket1(BittrexSocket):
        def __init__(self, tickers, url=None):
            super(BittrexSocket1, self).__init__(url)
            self.tickers = tickers
            self.cnt = 0
            for ticker in self.tickers:
                time.sleep(0.01)
                self.last[ticker] = time.time()
                self.query_exchange_state(['BTC-'+ticker])
                self.subscribe_to_exchange_deltas(['BTC-'+ticker])


        def on_public(self, msg):
            ticker = msg['M'].split('-')[-1]
            self.cnt += 1
            return

def main():
    ws = BittrexSocket1(tickers)
    ws.enable_log()
    try:
        while True:
            sleep(60)
            print datetime.datetime.now(), ws.cnt
    except KeyboardInterrupt:
        pass
    print 'exiting'
    ws.disconnect()
    sleep(10)

if __name__ == "__main__":
    main()

@slazarov
Copy link
Owner

slazarov commented May 6, 2018

I will test it now.

1.) How often does the issue happens?

2.) Is there any pattern in the average time between starting the code and the occurrence of the error? E.g every 10mins or so.

@gzivdo
Copy link
Author

gzivdo commented May 6, 2018

No, it happens just after network error. Sometimes its 2h, sometimes 6-8h

@slazarov
Copy link
Owner

slazarov commented May 6, 2018

I see, I will work on a fix and will push it to github in due time.
Thank you for reporting the bug.

@hamkline
Copy link

capture
I'm having issues with reconnection too. Mine lasts quite a bit, but at least once a day it breaks. I'm running on a server with 1GB RAM only though.
I don't run connections on a loop, it happens once and then I call a function to take care of the data + rest requests from the same library you use.
Also, I don't have the other errors, but I think I got a different one last time even though it was from reconnection also.
I can take a print next time if it helps. (python 3)

@slazarov
Copy link
Owner

Its a temporary fix but do the following: update to the latest version from github and replace line 140-143:

            elif invoke == BittrexMethods.GET_AUTH_CONTENT:
                self.connection.corehub.server.invoke(invoke, payload[0])
                self.invokes.append({'invoke': invoke, 'ticker': payload[0]})
                logger.info('Retrieving authentication challenge.')

with

            elif invoke == BittrexMethods.GET_AUTH_CONTENT:
                self.connection.corehub.server.invoke(invoke, self.credentials['api_key'])
                self.invokes.append({'invoke': invoke, 'ticker': self.credentials['api_key']})
                logger.info('Retrieving authentication challenge.')

@ayy1337
Copy link

ayy1337 commented May 13, 2018

screenshot_2018-05-13_12-17-40
I'm also having troubles on reconnection.. Seems like it blew through by VPS' available memory and was killed by linux oom-killer.

@ayy1337
Copy link

ayy1337 commented May 13, 2018

Also, I notice that you have in the websocket_client.py put a variable 'self.threads = []', but when a thread dies or is finished it is not removed from this list, preventing it from being garbage collected (as there are still references to it)
Honestly I can't even tell why the list is there at all, since it doesn't seem to be accessed anywhere..

@ayy1337
Copy link

ayy1337 commented May 13, 2018

screenshot_2018-05-13_13-32-39
Managed to catch it in htop. What are all these threads doing?

@slazarov
Copy link
Owner

slazarov commented May 13, 2018

Hi, self.threads = [] is a leftover from v<1.0, so thanks for noticing it. I am aware of what might be causing the thread spam and will fix in due time. As always thanks for raising an issue but next time provide additional information such as the whole log, code snippet, python version and a few word explanation since its difficult to debug from a picture.

Is node.js installed together with cfscrape?

@slazarov
Copy link
Owner

Update the package to v1.0.4 through:
pip install git+https://github.com/slazarov/python-bittrex-websocket.git@1.0.4

Theoretically this should fix it, waiting for your feedback after testing.

@hamkline
Copy link

Is v1.0.4 only difference in the code you mentioned for me above? Because I still got the error with that.
If not let me know and I'll test with the new code and provide feedback.

Just in case I'll post it here.
capture
It's funny that it only shows those few lines, so if it was trying to reconnect a lot, in a loop or something, it should have more output, right?

@slazarov
Copy link
Owner

As I said I can’t comment on pictures without any code.

v1.0.4 is different than the code I posted, you can check the commits.

@hamkline
Copy link

As I said, I subscribe and then stick to a function with a while True that handles the data forever, just like in your example with the __init__ having this: self.ticker_updates_container = {} which haves msg value every time on_update.

I'll test v1.0.4 and provide feedback.

@ayy1337
Copy link

ayy1337 commented May 13, 2018

As requested, here is a pastebin with full code, is pretty basic honestly.. https://pastebin.com/a5UvBZqU
And here is a pastebin with the full output from running the above code: https://pastebin.com/LSN9QDMc

Python version was 3.5, don't believe node.js is installed no. Cfscrape is installed.
(this is re: your first reply, I will update to 1.0.4 and do further testing)

@slazarov
Copy link
Owner

slazarov commented May 13, 2018 via email

@ayy1337
Copy link

ayy1337 commented May 13, 2018

screenshot_2018-05-14_02-04-47
My bad, it appears to have had node.js I was just ignorant of the appropriate command (i was trying 'node' and 'npm')

Edit: I will update to 1.0.4 now and do further testing, haven't done so yet
Edit2: Have updated to new version, will post again with logs and whatnot when test completes

@ayy1337
Copy link

ayy1337 commented May 14, 2018

Okay so I updated and ran the same script again with the new version, have the output from my tests.
This paste I disconnected the network connection manually for 60 seconds and reconnected it. https://pastebin.com/V0bZHpY9

For the second test I let it run until it ran into an issue on its own, https://pastebin.com/F9y0hLhm

In neither case did it successfully reconnect after the error

@hamkline
Copy link

hamkline commented May 14, 2018

I got that too, here's a print just in case it helps:
capture
It was in the same function I mentioned earlier, it's the one that handles self.ticker_updates_container and nothing more. Again, same place under a while True loop that other errors occurred.
My program didn't really end with killed this time though, probably the socket disconnected and it kept handling the same data on self.ticker_updates_container till I woke up.

@slazarov
Copy link
Owner

Hi, the reason for the error is that exceptions in Python2 have a 'message' attribute whereas exceptions in Python3 have 'args' instead. This is fixed. Do:

pip install git+https://github.com/slazarov/python-bittrex-websocket.git@1.0.5

@ayy1337 I have added TimeoutError as a new exception in the reconnection logic. I reckon the exception is from urllib3.exceptions import TimeoutError is the correct one. Please do your tests and update me.

As a whole, I have disabled the auto-reconnection for unknown errors since I prefer to add them when they appear and after I've become acquainted with them.

@ayy1337
Copy link

ayy1337 commented May 15, 2018

For printing exception info I usually use (in 3.5 etc.) "{} {}".format(type(e).__name__, e)
You don't need .args or .message
Edit: This works on python 2.7 as well..
screenshot_2018-05-15_11-31-14

P.s. the url git+https://github.com/slazarov/python-bittrex-websocket.git@1.0.5 doesn't actually work since the update wasn't tagged with a version on git.
screenshot_2018-05-15_10-43-08

@slazarov
Copy link
Owner

Hi @ayy1337, thanks for the suggestion. Also my bad, I pushed directly to the master so you can update through:
pip install git+https://github.com/slazarov/python-bittrex-websocket.git

@ayy1337
Copy link

ayy1337 commented May 17, 2018

screenshot_2018-05-17_17-11-13
Okay so running the tests again on version 1.0.5, this first pic is from just letting it run until it ran into troubles; the reconnect seems to have worked this time without blowing up the memory which is good, though it failed to resubscribe to the account deltas

screenshot_2018-05-17_17-14-25
This second pic is by forcibly disconnecting the internet connection, again for around 60 seconds before reconnecting.

@slazarov
Copy link
Owner

Can you paste the contents of websocket_client.py/_handle_subscribe method?

@slazarov
Copy link
Owner

I wasn't sure which package was raising the TimeoutError. Initially I thought it was urllib3.exceptions but probably it's the one from the built-ins. I have pushed the commit to v.1.0.6.

@ayy1337
Copy link

ayy1337 commented May 19, 2018

Can you paste the contents of websocket_client.py/_handle_subscribe method?

Sure (1.0.5)
screenshot_2018-05-19_12-02-35

@slazarov
Copy link
Owner

Were you getting any data between 00:20 and 12:20?

@ayy1337
Copy link

ayy1337 commented May 20, 2018

Hmm I didn't notice that actually.. appears to be a gap, possibly it didn't succeed in subscribing to summarylitedeltas?

@ayy1337
Copy link

ayy1337 commented May 20, 2018

screenshot_2018-05-20_16-32-37
So, this is basically just conjecture on my part, but is it possible that it was trying to join a running thread here, and because it had no timeout, it simply blocked for 12 hrs waiting for the thread to die? Think it might be a possibility because the last thing it printed before the gap in the log is "Initiating reconnection procedure"

@slazarov
Copy link
Owner

Yes, that's what I am investigating currently. It seems SOCKET_CONNECTION_THREAD failed to quit somewhere in _signalr.py/start(self).

@slazarov
Copy link
Owner

slazarov commented May 20, 2018

I've made some changes to ensure SOCKET_CONNECTION_THREAD quits. Theoretically, this should ensure c2.Authenticate doesn't fail. I have also put some error traps to see if the Authenticate gets corrupted somewhere.

pip install git+https://github.com/slazarov/python-bittrex-websocket.git@1.0.6.1

Changes:
699175b
715cdd8

@ayy1337
Copy link

ayy1337 commented May 20, 2018

Okay, will rerun the test (natural reconnect) with the new version

@ayy1337
Copy link

ayy1337 commented May 20, 2018

screenshot_2018-05-21_01-29-41
Captured two reconnection events, both appear to have worked as intended. I will keep running the script for a while though

@ayy1337
Copy link

ayy1337 commented May 21, 2018

screenshot_2018-05-21_14-59-17
Two more, looks like reconnecting is working fine now

@gzivdo
Copy link
Author

gzivdo commented May 21, 2018

TimeoutError absent in python 2.x, its not built-in.
Also i have this error:

2018-05-21 20:46:23 - bittrex_websocket.websocket_client - INFO - Successfully subscribed to [QueryExchangeState] for [BTC-ZCL].
2018-05-21 20:46:23 - bittrex_websocket.websocket_client - INFO - Successfully subscribed to [SubscribeToExchangeDeltas] for [BTC-ZCL].
No handlers could be found for logger "websocket"
2018-05-21 20:46:24 - bittrex_websocket.websocket_client - ERROR - 
Unhandled Exception = <type 'exceptions.AttributeError'>, Message = <'NoneType' object has no attribute 'split'>.

@slazarov
Copy link
Owner

slazarov commented May 21, 2018 via email

@slazarov
Copy link
Owner

slazarov commented May 22, 2018 via email

@gzivdo
Copy link
Author

gzivdo commented May 22, 2018

Exception in thread SocketConnectionThread:
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 801, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.7/threading.py", line 754, in run
    self.__target(*self.__args, **self.__kwargs)
  File "build/bdist.linux-x86_64/egg/bittrex_websocket/websocket_client.py", line 159, in _connection_handler
    except TimeoutError as e:
NameError: global name 'TimeoutError' is not defined

And then if i comment timeouterror code i get:

No handlers could be found for logger "websocket"
2018-05-22 08:47:24 - bittrex_websocket.websocket_client - ERROR - 
Unhandled Exception = <type 'exceptions.AttributeError'>, Message = <'NoneType' object has no attribute 'split'>.
Auto-reconnection is disabled for unhandled exceptions.
Report to https://github.com/slazarov/python-bittrex-websocket.

And nothing happening after.

@hamkline
Copy link

1
2
v1.0.6 - py3
The 2 pictures are from the same situation, just had to cut them in 2.

@gzivdo
Copy link
Author

gzivdo commented Jun 1, 2018

Still no fix? With py2.x just not work at all now.

@slazarov
Copy link
Owner

slazarov commented Jun 1, 2018

I’ve been away for the past 2 weeks, will look into it in the weekend.

@slazarov
Copy link
Owner

slazarov commented Jun 2, 2018

Do a:
pip install git+https://github.com/slazarov/python-bittrex-websocket.git@1.0.6.1

It should fix the TimeoutError. Regarding:
Unhandled Exception = <type 'exceptions.AttributeError'>, Message = <'NoneType' object has no attribute 'split'>.

Are you sure that this is not part of your code? Can you repost again your code.

@gzivdo
Copy link
Author

gzivdo commented Jun 2, 2018

yes, sorry.

@gzivdo
Copy link
Author

gzivdo commented Jun 2, 2018

The error bacause beta api returns with QueryExchangeState 'M' not None, but https://socket.bittrex.com/signalr returns None. Will use beta for now.

@slazarov
Copy link
Owner

slazarov commented Jun 2, 2018 via email

@gzivdo
Copy link
Author

gzivdo commented Jun 2, 2018

What if i will subscribe for few tickers, how your workaround will handle that?

@slazarov
Copy link
Owner

slazarov commented Jun 2, 2018 via email

@gzivdo
Copy link
Author

gzivdo commented Jun 3, 2018

Now after connection dropped i have:

2018-06-03 10:08:46 - bittrex_websocket.websocket_client - INFO - Successfully subscribed to [QueryExchangeState] for [BTC-TRX].
2018-06-03 10:08:46 - bittrex_websocket.websocket_client - INFO - Successfully subscribed to [SubscribeToExchangeDeltas] for [BTC-TRX].
2018-06-03 17:43:29 - bittrex_websocket.websocket_client - ERROR - Exception = <class 'websocket._exceptions.WebSocketConnectionClosedException'>, Message = <Connection is already closed.>.
2018-06-03 17:43:29 - bittrex_websocket.websocket_client - DEBUG - Initiating reconnection procedure
2018-06-03 17:43:29 - bittrex_websocket.websocket_client - DEBUG - Previous reconnection failed. Retrying in 5 seconds. Reconnection attempt 1.
2018-06-03 17:43:29 - bittrex_websocket.websocket_client - DEBUG - Last reconnection was more than 60 seconds ago. Resetting retry counter.
2018-06-03 17:43:29 - bittrex_websocket.websocket_client - INFO - Establishing connection to Bittrex through https://beta.bittrex.com/signalr.
2018-06-03 17:43:29 - bittrex_websocket.websocket_client - INFO - cfscrape detected, will try to bypass Cloudflare if enabled.
2018-06-03 17:43:39 - bittrex_websocket.websocket_client - ERROR - Connection timeout after 10 seconds. Sending a reconnection signal.
2018-06-03 17:43:39 - bittrex_websocket.websocket_client - DEBUG - Initiating reconnection procedure

And the app not react on ctrl+c
Can I catch dropped connection and just quit the app in that case somehow?

@slazarov
Copy link
Owner

slazarov commented Jun 3, 2018

Is it stuck on reconnection or what? Seems like you are unable to reconnect at all.

@gzivdo
Copy link
Author

gzivdo commented Jun 3, 2018

Dont know, but there was no data after that last message and I cant stop it by ctrl+c

@slazarov
Copy link
Owner

slazarov commented Jun 3, 2018

You are also connecting to the beta endpoint, I can’t guarantee that it is stable.

@gzivdo
Copy link
Author

gzivdo commented Jun 3, 2018

I know, but the bug still in the lib. It still cant reconnect and even cant stop the app after retry.

@slazarov
Copy link
Owner

slazarov commented Jun 3, 2018

Is this the full log? Anything after?
2018-06-03 17:43:39 - bittrex_websocket.websocket_client - DEBUG - Initiating reconnection procedure

Firstly, if the library is unable to reconnect after a drop it will keep on trying every 10 seconds. E.g here is an example of when I have disabled my connection and then reenabled it:

2018-06-03 18:19:38 - bittrex_websocket.websocket_client - ERROR - Exception = <class 'websocket._exceptions.WebSocketConnectionClosedException'>, Message = <Connection is already closed.>.
2018-06-03 18:19:38 - bittrex_websocket.websocket_client - DEBUG - Initiating reconnection procedure.
2018-06-03 18:19:38 - bittrex_websocket.websocket_client - DEBUG - Previous reconnection failed. Retrying in 5 seconds. Reconnection attempt 1.
2018-06-03 18:19:38 - bittrex_websocket.websocket_client - INFO - Establishing connection to Bittrex through https://socket.bittrex.com/signalr.
2018-06-03 18:19:38 - bittrex_websocket.websocket_client - INFO - cfscrape detected, will try to bypass Cloudflare if enabled.
2018-06-03 18:19:48 - bittrex_websocket.websocket_client - ERROR - Connection timeout after 10 seconds. Sending a reconnection signal.
2018-06-03 18:19:48 - bittrex_websocket.websocket_client - DEBUG - Initiating reconnection procedure.
2018-06-03 18:19:48 - bittrex_websocket.websocket_client - DEBUG - Previous reconnection failed. Retrying in 5 seconds. Reconnection attempt 2.
2018-06-03 18:19:53 - bittrex_websocket.websocket_client - INFO - Establishing connection to Bittrex through https://socket.bittrex.com/signalr.
2018-06-03 18:19:53 - bittrex_websocket.websocket_client - INFO - cfscrape detected, will try to bypass Cloudflare if enabled.
2018-06-03 18:20:03 - bittrex_websocket.websocket_client - ERROR - Connection timeout after 10 seconds. Sending a reconnection signal.
2018-06-03 18:20:03 - bittrex_websocket.websocket_client - DEBUG - Initiating reconnection procedure.
2018-06-03 18:20:03 - bittrex_websocket.websocket_client - DEBUG - Previous reconnection failed. Retrying in 5 seconds. Reconnection attempt 3.
2018-06-03 18:20:08 - bittrex_websocket.websocket_client - INFO - Establishing connection to Bittrex through https://socket.bittrex.com/signalr.
2018-06-03 18:20:08 - bittrex_websocket.websocket_client - INFO - cfscrape detected, will try to bypass Cloudflare if enabled.
2018-06-03 18:20:09 - bittrex_websocket.websocket_client - INFO - Successfully subscribed to [SubscribeToExchangeDeltas] for [BTC-ETH].
2018-06-03 18:20:09 - bittrex_websocket.websocket_client - INFO - Successfully subscribed to [SubscribeToExchangeDeltas] for [BTC-NEO].
2018-06-03 18:20:09 - bittrex_websocket.websocket_client - INFO - Successfully subscribed to [SubscribeToExchangeDeltas] for [BTC-ZEC].
2018-06-03 18:20:09 - bittrex_websocket.websocket_client - INFO - Successfully subscribed to [SubscribeToExchangeDeltas] for [ETH-NEO].
2018-06-03 18:20:09 - bittrex_websocket.websocket_client - INFO - Successfully subscribed to [SubscribeToExchangeDeltas] for [ETH-ZEC].
2018-06-03 18:20:09 - bittrex_websocket.websocket_client - INFO - Retrieving authentication challenge.
2018-06-03 18:20:09 - bittrex_websocket.websocket_client - INFO - Challenge retrieved. Sending authentication. Awaiting messages...

Secondly , in your initial code you are handling KeyboardInterrupt, are you sure thats the reason you can't do CTRL+C?

Thirdly, as I mentioned, don't use the beta endpoint.

Finally, the last time you posted your script was 28 days, I guess it has changed by now. Even though, I am trying to help you, I have no idea and I can't guess what you are executing. I need to be able to replicate your issue precisely.

@gzivdo
Copy link
Author

gzivdo commented Jun 3, 2018

Yes i am handle Keyboardinterrupt:

    except KeyboardInterrupt:
        exiting = True
        b_ws.disconnect()
        time.sleep(2)
        break
    except:
        traceback.print_exc()
        time.sleep(5)

Will try to run for a while original 'test' code. Possibly the reason in that i use python 2.7.

@slazarov
Copy link
Owner

slazarov commented Jun 3, 2018

@gzivdo here is an infinite loop test code:

#!/usr/bin/python
# -*- coding: utf-8 -*-

from __future__ import print_function
from time import sleep
from bittrex_websocket import BittrexSocket, BittrexMethods


def main():
    class MySocket(BittrexSocket):

        def on_public(self, msg):
            # Create entry for the ticker in the trade_history dict
            if msg['invoke_type'] == BittrexMethods.SUBSCRIBE_TO_EXCHANGE_DELTAS:
                if msg['M'] not in trade_history:
                    trade_history[msg['M']] = []
                # Add history nounce
                trade_history[msg['M']].append(msg)
                # Ping
                print('[Trades]: {}'.format(msg['M']))

    # Create container
    trade_history = {}
    # 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 trade fills
    ws.subscribe_to_exchange_deltas(tickers)
    ws.subscribe_to_summary_lite_deltas()
    ws.authenticate('test your api key', 'test your api secret')
    while True:
        sleep(1)


if __name__ == "__main__":
    main()

@slazarov
Copy link
Owner

Still having the issue?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

4 participants