slazarov / python-bittrex-websocket

Python websocket for Bittrex (non async).
http://python-bittrex-websocket-docs.readthedocs.io/en/latest/index.html
MIT License
103 stars 38 forks source link

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

Closed VictorHVS closed 6 years ago

VictorHVS commented 6 years ago

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.

slazarov commented 6 years ago

Hi, the error is related to this RuntimeWarning: Monkey-patching ssl after ssl has already been imported may lead to errors, including RecursionError on Python 3.6. Please monkey-patch earlier.

I am trying to fix it. For the time being, can you try Python3.5 and report back?

slazarov commented 6 years ago

You can also try this fork of SignalR which has replaced gevent: https://github.com/PawelTroka/signalr-client-threads

VictorHVS commented 6 years ago

@slazarov I'm trying, but it looks like it's offline ... Although on the bittrex website the orderbook is loading correctly. Where can I see the status of the websocket?

Traceback (most recent call last):
  File "manage.py", line 22, in <module>
    execute_from_command_line(sys.argv)
  File "/Users/victorhvs/Workspace/victorhvs/calltraderbot/env/lib/python3.5/site-packages/django/core/management/__init__.py", line 363, in execute_from_command_line
    utility.execute()
  File "/Users/victorhvs/Workspace/victorhvs/calltraderbot/env/lib/python3.5/site-packages/django/core/management/__init__.py", line 355, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/Users/victorhvs/Workspace/victorhvs/calltraderbot/env/lib/python3.5/site-packages/django/core/management/base.py", line 283, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/Users/victorhvs/Workspace/victorhvs/calltraderbot/env/lib/python3.5/site-packages/django/core/management/base.py", line 330, in execute
    output = self.handle(*args, **options)
  File "/Users/victorhvs/Workspace/victorhvs/calltraderbot/core/management/commands/order_book.py", line 75, in handle
    main()
  File "/Users/victorhvs/Workspace/victorhvs/calltraderbot/core/management/commands/order_book.py", line 48, in main
    ws.subscribe_to_orderbook(tickers)
  File "/Users/victorhvs/Workspace/victorhvs/calltraderbot/env/lib/python3.5/site-packages/bittrex_websocket/websocket_client.py", line 742, in subscribe_to_orderbook
    self.tickers.set_book_depth(tickers, book_depth)
  File "/Users/victorhvs/Workspace/victorhvs/calltraderbot/env/lib/python3.5/site-packages/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
slazarov commented 6 years ago

Is nodejs installed, also are the examples or the dockerfile running fine?

VictorHVS commented 6 years ago

it is true 👍. I had uninstalled. But now with the py35 it worked! When the bug is fixed I go back to using py36. Ty.

rightx2 commented 6 years ago

It doesn't work for me in Python 3.5.2 environment. Error is /home/rightx2/.pyenv/versions/coin_trader_project/lib/python3.5/site-packages/gevent/monkey.py:543: MonkeyPatchWarning: Monkey-patching ssl after ssl has already been imported may lead to errors, including RecursionError on Python 3.6. Please monkey-patch earlier. See https://github.com/gevent/gevent/issues/1016

VictorHVS commented 6 years ago

@rightx2 if this help you...

My Python is 3.5.4

When I type pip freeze:

bittrex-websocket==0.0.7.0
certifi==2018.1.18
cffi==1.11.5
cfscrape==1.9.4
chardet==3.0.4
cryptography==2.2
Django==1.11
Events==0.3
future==0.16.0
gevent==1.3a2
greenlet==0.4.13
idna==2.6
nodejs==0.1.1
optional-django==0.1.0
psycopg2==2.7.4
psycopg2-binary==2.7.4
pycparser==2.18
PyExecJS==1.5.1
pyOpenSSL==17.5.0
python-bittrex==0.3.0
python-decouple==3.0
python-telegram-bot==10.0.1
pytz==2018.3
raven==6.6.0
requests==2.18.4
signalr-client==0.0.7
six==1.11.0
sseclient==0.0.19
urllib3==1.22
websocket-client==0.47.0
wsaccel==0.6.2
rightx2 commented 6 years ago
{'Django==1.11',
 'cryptography==2.2',
 'future==0.16.0',
 'nodejs==0.1.1',
 'optional-django==0.1.0',
 'psycopg2==2.7.4',
 'python-bittrex==0.3.0',
 'python-decouple==3.0',
 'python-telegram-bot==10.0.1',
 'raven==6.6.0'}

These are result of set(your pip result) - set(my pip result). Anything that I missed?

slazarov commented 6 years ago

Can you import bittrex-websocket at the top?

slazarov commented 6 years ago

Please do: pip install git+https://github.com/slazarov/python-bittrex-websocket.git@0.0.7.1 and check for recursion errors.

Also it's advisable to uninstall the signalr client before that.

rightx2 commented 6 years ago

@slazarov

It(0.0.7.1) works well now. It even works well after 1 hour later reconnection

Btw, have some questions about data.

  1. tick I got data like below on on_trade():

    
    {
    'ticker': 'BTC-SC', 
    'timestamp': 1522053373.1464992, 
    'nounce': 10201, 
    'trades': [
        {'Quantity': 20574.47059849, 'OrderType': 'SELL', 'TimeStamp': c, 'Rate': 1.8e-06}, 
        {'Quantity': 307.11000277, 'OrderType': 'SELL', 'TimeStamp': '2018-03-26T08:36:13.053', 'Rate': 1.8e-06}, 
        {'Quantity': 27717.49370833, 'OrderType': 'SELL', 'TimeStamp': '2018-03-26T08:36:13.053', 'Rate': 1.8e-06}, 
        {'Quantity': 2908.01175, 'OrderType': 'SELL', 'TimeStamp': '2018-03-26T08:36:13.053', 'Rate': 1.8e-06}, 
    
        {'Quantity': 7381.17761152, 'OrderType': 'SELL', 'TimeStamp': '2018-03-26T08:36:13.037', 'Rate': 1.8e-06}, 
        {'Quantity': 5000.0, 'OrderType': 'SELL', 'TimeStamp': '2018-03-26T08:36:13.037', 'Rate': 1.8e-06}, 
        {'Quantity': 1000.0, 'OrderType': 'SELL', 'TimeStamp': '2018-03-26T08:36:13.037', 'Rate': 1.8e-06}, 
        {'Quantity': 38152.95941497, 'OrderType': 'SELL', 'TimeStamp': '2018-03-26T08:36:13.037', 'Rate': 1.8e-06}
    ]
    }

As you can see here, they can be separated as two groups by `timestamp`('2018-03-26T08:36:13.053', '2018-03-26T08:36:13.037')
What I wonder is that, are those sort of "1 taker, N makers, at price X" transactions? 
(In this case, since OrderType is `SELL`, it can be think of the one wanting to sell make transaction happened?) 
If not, What's the difference between `msg` with multiple `trade` list and single `trade`?

2. Orderbook 
The orderbook data has `timestamp` field.  Is that the time where data of orderbook changed or the time that I received the data(event time)?
slazarov commented 6 years ago

Hi, thanks for waiting for my reply.

  1. tick - I don't think thats the case. In your example, say:

{'Quantity': 20574.47059849, 'OrderType': 'SELL', 'TimeStamp': c, 'Rate': 1.8e-06}, This was a sell order (liquidity in) put by somebody on order book; and someone bought it (liquidity out). There are multiple trade entries because they occurred at relatively the same timestamp (in this case second).

  1. Orderbook - the time that you received it, I have placed it in the code.
rightx2 commented 6 years ago

Then, what is the meaning of ticks occurring different time sent in the same list(trade)?

I mean above data can be sent like below? but why isn't it?

{
    'ticker': 'BTC-SC', 
    'timestamp': 1522053373.1464992, 
    'nounce': 10201, 
    'trades': [
        {'Quantity': 20574.47059849, 'OrderType': 'SELL', 'TimeStamp': '2018-03-26T08:36:13.053, 'Rate': 1.8e-06}, 
        {'Quantity': 307.11000277, 'OrderType': 'SELL', 'TimeStamp': '2018-03-26T08:36:13.053', 'Rate': 1.8e-06}, 
        {'Quantity': 27717.49370833, 'OrderType': 'SELL', 'TimeStamp': '2018-03-26T08:36:13.053', 'Rate': 1.8e-06}, 
        {'Quantity': 2908.01175, 'OrderType': 'SELL', 'TimeStamp': '2018-03-26T08:36:13.053', 'Rate': 1.8e-06}, 
    ]
}

{
    'ticker': 'BTC-SC', 
    'timestamp': 1522053373.1564992,   # with different timestamp
    'nounce': 10202,   # with different nounce
    'trades': [
        {'Quantity': 7381.17761152, 'OrderType': 'SELL', 'TimeStamp': '2018-03-26T08:36:13.037', 'Rate': 1.8e-06}, 
        {'Quantity': 5000.0, 'OrderType': 'SELL', 'TimeStamp': '2018-03-26T08:36:13.037', 'Rate': 1.8e-06}, 
        {'Quantity': 1000.0, 'OrderType': 'SELL', 'TimeStamp': '2018-03-26T08:36:13.037', 'Rate': 1.8e-06}, 
        {'Quantity': 38152.95941497, 'OrderType': 'SELL', 'TimeStamp': '2018-03-26T08:36:13.037', 'Rate': 1.8e-06}
    ]
}
slazarov commented 6 years ago

Here is how it works. When you receive data from Bittrex it comes with a nounce number. From what I am observing from the data you put, Bittrex doesn’t care about microseconds and instead aggregates all trades that occurred within the same second together. If you are wondering which fill in the list is the most recent, my best guess is the first one.

The only additional modification I do to the input data is to timestamp it so that you know at what time you received it. Don’t be mistaken, there is certainly a latency and you are getting the data with a delay.

slazarov commented 6 years ago

Closing this issue, gevent is no longer used.