hootnot / oanda-api-v20

OANDA REST-V20 API wrapper. Easy access to OANDA's REST v20 API with oandapyV20 package. Checkout the Jupyter notebooks!
MIT License
398 stars 107 forks source link

API Connection keeps closing #194

Closed essentiapip closed 1 year ago

essentiapip commented 1 year ago

Hello,

The API often returns this error:

"ConnectionResetError: [WinError 10054] An existing connection was forcibly closed by the remote host"

When I try to except it by re-connecting to the API:

except: API_CONNECTION = API(API_KEY, request_params={'timeout': 30})

It returns:

"ProtocolError: ('Connection aborted.', ConnectionResetError(10054, 'An existing connection was forcibly closed by the remote host', None, 10054, None))"

then it ends the program.

However, when I re-run the program / call the API again, it works just as expected. I have only just added the timeout parameter, but without it, the error still happens.

All calls are in the format of API_CONNECTION.request()

essentiapip commented 1 year ago

Here is the full error log:

Submit_Open_Buy_Order_Details = API_CONNECTION.request(orders.OrderDetails(accountID = ACCOUNT, orderID = Submit_Open_Buy_Order_ID))
Traceback (most recent call last):

  File ~\Anaconda3\lib\site-packages\urllib3\connectionpool.py:703 in urlopen
    httplib_response = self._make_request(

  File ~\Anaconda3\lib\site-packages\urllib3\connectionpool.py:449 in _make_request
    six.raise_from(e, None)

  File <string>:3 in raise_from

  File ~\Anaconda3\lib\site-packages\urllib3\connectionpool.py:444 in _make_request
    httplib_response = conn.getresponse()

  File ~\Anaconda3\lib\http\client.py:1377 in getresponse
    response.begin()

  File ~\Anaconda3\lib\http\client.py:320 in begin
    version, status, reason = self._read_status()

  File ~\Anaconda3\lib\http\client.py:281 in _read_status
    line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1")

  File ~\Anaconda3\lib\socket.py:704 in readinto
    return self._sock.recv_into(b)

  File ~\Anaconda3\lib\ssl.py:1241 in recv_into
    return self.read(nbytes, buffer)

  File ~\Anaconda3\lib\ssl.py:1099 in read
    return self._sslobj.read(len, buffer)

ConnectionResetError: [WinError 10054] An existing connection was forcibly closed by the remote host

During handling of the above exception, another exception occurred:

Traceback (most recent call last):

  File ~\Anaconda3\lib\site-packages\requests\adapters.py:440 in send
    resp = conn.urlopen(

  File ~\Anaconda3\lib\site-packages\urllib3\connectionpool.py:785 in urlopen
    retries = retries.increment(

  File ~\Anaconda3\lib\site-packages\urllib3\util\retry.py:550 in increment
    raise six.reraise(type(error), error, _stacktrace)

  File ~\Anaconda3\lib\site-packages\urllib3\packages\six.py:769 in reraise
    raise value.with_traceback(tb)

  File ~\Anaconda3\lib\site-packages\urllib3\connectionpool.py:703 in urlopen
    httplib_response = self._make_request(

  File ~\Anaconda3\lib\site-packages\urllib3\connectionpool.py:449 in _make_request
    six.raise_from(e, None)

  File <string>:3 in raise_from

  File ~\Anaconda3\lib\site-packages\urllib3\connectionpool.py:444 in _make_request
    httplib_response = conn.getresponse()

  File ~\Anaconda3\lib\http\client.py:1377 in getresponse
    response.begin()

  File ~\Anaconda3\lib\http\client.py:320 in begin
    version, status, reason = self._read_status()

  File ~\Anaconda3\lib\http\client.py:281 in _read_status
    line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1")

  File ~\Anaconda3\lib\socket.py:704 in readinto
    return self._sock.recv_into(b)

  File ~\Anaconda3\lib\ssl.py:1241 in recv_into
    return self.read(nbytes, buffer)

  File ~\Anaconda3\lib\ssl.py:1099 in read
    return self._sslobj.read(len, buffer)

ProtocolError: ('Connection aborted.', ConnectionResetError(10054, 'An existing connection was forcibly closed by the remote host', None, 10054, None))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):

  Input In [25] in <cell line: 1>
    Submit_Open_Buy_Order_Details = API_CONNECTION.request(orders.OrderDetails(accountID = ACCOUNT, orderID = Submit_Open_Buy_Order_ID))

  File ~\Anaconda3\lib\site-packages\oandapyV20\oandapyV20.py:337 in request
    response = self.__request(method, url,

  File ~\Anaconda3\lib\site-packages\oandapyV20\oandapyV20.py:266 in __request
    raise err

  File ~\Anaconda3\lib\site-packages\oandapyV20\oandapyV20.py:262 in __request
    response = func(url, stream=stream, headers=headers,

  File ~\Anaconda3\lib\site-packages\requests\sessions.py:542 in get
    return self.request('GET', url, **kwargs)

  File ~\Anaconda3\lib\site-packages\requests\sessions.py:529 in request
    resp = self.send(prep, **send_kwargs)

  File ~\Anaconda3\lib\site-packages\requests\sessions.py:645 in send
    r = adapter.send(request, **kwargs)

  File ~\Anaconda3\lib\site-packages\requests\adapters.py:501 in send
    raise ConnectionError(err, request=request)

ConnectionError: ('Connection aborted.', ConnectionResetError(10054, 'An existing connection was forcibly closed by the remote host', None, 10054, None))
hootnot commented 1 year ago

The error message seems pretty clear: ConnectionError, it also says 'forcibly closed'.

Since you did not show any code my guess is that you instantiate an API-client multiple times. OANDA has limits on several connection related things. Setting up connections in a certain time span is one of them.

The pattern is:

client = API(access_token=access_token)

r = orders.Order(...)

try:
    rv = client.request(r)
except Exception as err:
    print(err)
else:
    print(rv)

re-use the client. So, in case you place multiple orders:

client = API(access_token=access_token)

for instrument in [...]:
    r = orders.Order(...)
    try:
        rv = client.request(r)
    except Exception as err:
        print(err)
    else:
        print(rv)