Giter VIP home page Giter VIP logo

qtrade's Introduction

from typing import List

class Borchmann:

    def __init__(self):
        self.username: str = "jborchma"
        self.name: str = "Jan Borchmann"
        self.location: str = "Toronto, ON"
        self.languages: List[str] = ["English", "German", "Spanish", "Python"]
        self.hobbies: List[str] = ["๐Ÿšฒ", "โšฝ๏ธ", "๐Ÿ’", "โœˆ๏ธ", "๐ŸŽธ", "๐Ÿบ"]
        self.workplace: str = "Shopify"
        self.job: str = "Data Scientist"

    def __str__(self):
        return self.name


if __name__ == "__main__":
    me = Borchmann()

qtrade's People

Contributors

ajhpark avatar jborchma avatar mmikitka avatar r-luo 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

Watchers

 avatar  avatar  avatar  avatar  avatar

qtrade's Issues

403 Client Error - get_historical_data

Firstly, thanks @jborchma for this library.

I am able to download data such as ticker information, account info etc, but when i try to download historical data i get the below error:

HTTPError: 403 Client Error: Forbidden for url: https://api02.iq.questrade.com/v1/markets/candles/36261155?startTime=2019-07-01T00%3A00%3A00-05%3A00&endTime=2019-07-02T00%3A00%3A00-05%3A00&interval=OneDay

Does this mean i do not have access to historical market data?

Anyone else get this issue?

Thanks

SSLCertVerificationError & MaxRetryError & SSLError

Hi Jan,

Recently, I have encountered errors related to SSLCertVerification and MaxRetry below, and I am not sure what went wrong from my side. Specifically, I get these errors when I call get_account_id method.


SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1131)

During handling of the above exception, another exception occurred:

MaxRetryError Traceback (most recent call last)
~\anaconda3\lib\site-packages\requests\adapters.py in send(self, request, stream, timeout, verify, cert, proxies)
438 if not chunked:
--> 439 resp = conn.urlopen(
440 method=request.method,

~\anaconda3\lib\site-packages\urllib3\connectionpool.py in urlopen(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, **response_kw)
754
--> 755 retries = retries.increment(
756 method, url, error=e, _pool=self, _stacktrace=sys.exc_info()[2]

~\anaconda3\lib\site-packages\urllib3\util\retry.py in increment(self, method, url, response, error, _pool, _stacktrace)
573 if new_retry.is_exhausted():
--> 574 raise MaxRetryError(_pool, url, error or ResponseError(cause))
575

MaxRetryError: HTTPSConnectionPool(host='api05.iq.questrade.com', port=443): Max retries exceeded with url: /v1/accounts (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1131)')))

During handling of the above exception, another exception occurred:

SSLError Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_9912/2462350887.py in
1 acctData = {}
----> 2 acctNums = qbot.get_account_id()
3 ACCOUNT_TYPE = ESHINHW_ACCOUNT_TYPE
4 for aNum in acctNums:
5 if aNum in ACCOUNT_TYPE:

~\Desktop\GitHub\questrade-portfolio-manager\utils\qtrade.py in get_account_id(self)
221 """
222 log.info("Getting account ID...")
--> 223 response: Dict[str, List[Dict[str, int]]] = self._send_message("get", "accounts")
224
225 account_id = []

~\Desktop\GitHub\questrade-portfolio-manager\utils\qtrade.py in _send_message(self, method, endpoint, params, data, json)
89 log.error("Access token not set...")
90 raise Exception("Access token not set...")
---> 91 resp = self.session.request(method, url, params=params, data=data, json=json, timeout=30)
92 resp.raise_for_status()
93 return resp.json()

~\anaconda3\lib\site-packages\requests\sessions.py in request(self, method, url, params, data, headers, cookies, files, auth, timeout, allow_redirects, proxies, hooks, stream, verify, cert, json)
540 }
541 send_kwargs.update(settings)
--> 542 resp = self.send(prep, **send_kwargs)
543
544 return resp

~\anaconda3\lib\site-packages\requests\sessions.py in send(self, request, **kwargs)
653
654 # Send the request
--> 655 r = adapter.send(request, **kwargs)
656
657 # Total elapsed time of the request (approximately)

~\anaconda3\lib\site-packages\requests\adapters.py in send(self, request, stream, timeout, verify, cert, proxies)
512 if isinstance(e.reason, _SSLError):
513 # This branch is for urllib3 v1.22 and later.
--> 514 raise SSLError(e, request=request)
515
516 raise ConnectionError(e, request=request)

SSLError: HTTPSConnectionPool(host='api05.iq.questrade.com', port=443): Max retries exceeded with url: /v1/accounts (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1131)')))

Is there anything I can change on my side to fix those errors, or is it a problem from the Questrade side?

Thanks!

Add more GH actions steps

It would be nice to automatically build the sphinx docs from GH actions when I add a new release. Also pushing the new release to pypi would be nice.

Going one step further, a push to master could automatically create the release (release message could be found from the last PR). But that's probably optional.

submit ordre

the submit_order is not working with me:
the http status code is 400 (bad request). Can you please give us an example ? I am using a partner app (Medved Trader)

get account balances

Hi,
When I try to call get_account_balances I get the following error: AttributeError: 'Questrade' object has no attribute 'get_account_balances'

In the questrade.py file I see the function is in there, not sure why Im not able to call it. Sorry If Im missing something, im new to python.

Thanks

Add tests

Like the title says, add testing.

  • utilities
  • qtrade class

Debugging a 400 bad request and clarifying the access code

Hello Jan. First, thanks for creating this package, and I look forward to using it.

I was not able to obtain an access token. Can you please clarify the initialization workflow and where the values are sourced from? I did the following:

  1. Created a Personal App at https://login.questrade.com/APIAccess/UserApps.aspx
  2. Clicked the "+ New device" link to create a new manually authorized device
  3. Clicked the "Generate token" link to create a new token (call it MY_TOKEN=1234567890ABCDEFG)
  4. Passed this token into qtrade.Questrade(access_code=MY_TOKEN)

I then get the following traceback

Traceback (most recent call last):
  File "./options.py", line 11, in <module>
    qtrade = Questrade(access_code=access_code)
  File "/app/qtrade/qtrade/questrade.py", line 38, in __init__
    self.get_access_token()
  File "/app/qtrade/qtrade/questrade.py", line 83, in get_access_token
    data.raise_for_status()
  File "/usr/local/lib/python3.7/site-packages/requests/models.py", line 940, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 400 Client Error: Bad Request for url: https://login.questrade.com/oauth2/token?grant_type=refresh_token&refresh_token=1234567890ABCDEFG

Expand pre-commit

I think it would make sense to include things like flake8, isort and the generic whitespace linters from pre-commit in the yaml-file.

Export L1

Add a method to connect to L1 streaming and show and eventually export to csv all the transaction

Add logging

As the title says: Add logging functionality.

Unclosed socket when doing testing with unittest

I'm getting the following warning when testing the API:
ResourceWarning: unclosed <ssl.SSLSocket fd=1104, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('192.168.5.66', 50373), raddr=('204.89.196.131', 443)>

The reason is that the Questrade class is missing a session closing statement. Please add the following:

class Questrade:
    ...
    def __del__(self):
        self.session.close()

Thank you,

"400 Client Error: Bad Request for url" when using "get_historical_data"

Environment: conda python==3.8 environment with qtrade and ipython installed

Issue:
'OneDay' works with get_historical_data:

uvxy = q.get_historical_data('UVXY', '2019-07-01', '2019-07-02', 'OneDay')

but changing 'OneDay' to 'OneHour' causes error:

>>> uvxy = q.get_historical_data('UVXY', '2019-07-01', '2019-07-02', 'OneHour')                                                 
---------------------------------------------------------------------------
HTTPError                                 Traceback (most recent call last)
<ipython-input-22-a0637f02abb7> in <module>
----> 1 uvxy = q.get_historical_data('UVXY', '2019-07-01', '2019-07-02', 'OneHour')

~/Documents/projects/qtrade/qtrade/questrade.py in get_historical_data(self, ticker, start_date, end_date, interval)
    448         )
    449 
--> 450         response = self._send_message(
    451             "get", "markets/candles/" + str(ids), params=payload
    452         )

~/Documents/projects/qtrade/qtrade/questrade.py in _send_message(self, method, endpoint, params, data, json)
     83             method, url, params=params, data=data, json=json, timeout=30
     84         )
---> 85         resp.raise_for_status()
     86         return resp.json()
     87 

~/anaconda3/envs/qtrade/lib/python3.8/site-packages/requests/models.py in raise_for_status(self)
    939 
    940         if http_error_msg:
--> 941             raise HTTPError(http_error_msg, response=self)
    942 
    943     def close(self):

HTTPError: 400 Client Error: Bad Request for url: https://api06.iq.questrade.com/v1/markets/candles/22992135?startTime=2019-07-01T00%3A00%3A00-05%3A00&endTime=2019-07-02T00%3A00%3A00-05%3A00&interval=OneHour

Extend readme

The readme should have a couple of more examples beyond just showing the token handling.

Add sphinx documentation

As the title says, add sphinx documentation and look into automatically deploying it to gh-pages using travis.

Suggestion: get account balance feature

Hi, I've enjoyed using your Questrade wrapper to perform analytic works on my accounts at Questrade. Just one suggestion, I hope there's a method which retrieves account balance data such as cash amount, total equity, and total market value by currencies. I figured in my own way to retrieve my balance data like below, but having this feature officially on your wrapper would be quite useful.

image

(^ Not sure if this is a safe and right way to get the data from API, but it works fine with me so far)

Thanks!

Make save yaml optional

I think it could be useful to add an option to not necessarily write out the token yaml every time when initiating.

Manage multiple accounts from different login IDs

Hello!

I am just wondering if qtrade can work with multiple accounts from different login IDs.

In my situation, I have no issue with using qtrade, but I want to manage other people's accounts with different API keys.

Based on my understanding, access_token.yml only works with one ID, and I have to delete and recreate it for new ID.

Is this correct and are there ways to access different accounts from different IDs?

Thanks,

I believe "refresh_access_token" stopped working today.

I hope it's not me; but it worked yesterday and today it never returns. Even though the token was not expired I got a new one; same result.
I'm not sure how I could provide more info about this.
Code:
from qtrade import Questrade
MyQtrade = Questrade(token_yaml="access_token.yml")
MyQtrade.refresh_access_token(from_yaml=True)
print(MyQtrade.ticker_information('IBM'))

I run each line in the interpreter and "refresh_access_token" does not return.
I stopped it with Ctrl-C and I got the following:
`

MyQtrade.refresh_access_token(from_yaml=True)
Traceback (most recent call last):
File "", line 1, in
File "C:\Users\Cat\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\qtrade\questrade.py", line 194, in refresh_access_token
data = requests.get(url)
File "C:\Users\Cat\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\requests\api.py", line 75, in get
return request('get', url, params=params, **kwargs)
File "C:\Users\Cat\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\requests\api.py", line 61, in request
return session.request(method=method, url=url, **kwargs)
File "C:\Users\Cat\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\requests\sessions.py", line 529, in request
resp = self.send(prep, **send_kwargs)
File "C:\Users\Cat\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\requests\sessions.py", line 645, in send
r = adapter.send(request, **kwargs)
File "C:\Users\Cat\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\requests\adapters.py", line 440, in send
resp = conn.urlopen(
File "C:\Users\Cat\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\urllib3\connectionpool.py", line 703, in urlopen
httplib_response = self._make_request(
File "C:\Users\Cat\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\urllib3\connectionpool.py", line 449, in _make_request
six.raise_from(e, None)
File "", line 3, in raise_from
File "C:\Users\Cat\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\urllib3\connectionpool.py", line 444, in _make_request
httplib_response = conn.getresponse()
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.1264.0_x64__qbz5n2kfra8p0\lib\http\client.py", line 1374, in getresponse
response.begin()
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.1264.0_x64__qbz5n2kfra8p0\lib\http\client.py", line 318, in begin
version, status, reason = self._read_status()
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.1264.0_x64__qbz5n2kfra8p0\lib\http\client.py", line 279, in _read_status
line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1")
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.1264.0_x64__qbz5n2kfra8p0\lib\socket.py", line 705, in readinto
return self._sock.recv_into(b)
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.1264.0_x64__qbz5n2kfra8p0\lib\ssl.py", line 1273, in recv_into
return self.read(nbytes, buffer)
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.1264.0_x64__qbz5n2kfra8p0\lib\ssl.py", line 1129, in read
return self._sslobj.read(len, buffer)
KeyboardInterrupt

`
Anything I'm doing wrong, or that I can do to fix this, please?

Add method to convert to pandas?

I'm assuming most of the usages for this package would be for analytics, do you want to include analytical utilities such as convert_to_pandas etc. in this package or do you think those should be separate?

Move to Github actions

I think with all the changes to Travis recently, it might be time to move to Github actions before running out of credits.

Improve token management

The token management could definitely be improved. Maybe it would work in conjunction with the requests.Session object. Definitely room for improvement.

Seems to be a problem with the link to refresh token

Maybe a url link needs to be updated in your functions. If I can update it myself I don't mind doing it, if you can tell me where it is in the code.ยธ

I simply coded:

from qtrade import Questrade
qtrade = Questrade(access_code='abc') #abc is my personnel token

The output is the error code:

raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 500 Server Error: Internal Server Error for url: https://login.questrade.com/oauth2/token?grant_type=refresh_token&refresh_token=MyqKC7-5ywmcBAPmPzjJfzjgToQYM3P90

Your help would be apprciated

Improve Error messages

Currently, the error messages are not very informative. Add much clearer error messages that actually tell the user what went wrong.

oauth2 token only works once

I believe QT made some changes in the last year and things might have been broken. So, these are my steps:

Basically, I have to create a new token for each run.

Am I doing something wrong?

json.decoder.JSONDecodeError: Expecting value: line 1 column 2 (char 1)

*** Error Output Below ***

File "/usr/local/Cellar/python/3.7.5/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/decoder.py", line 353, in raw_decode
  obj, end = self.scan_once(s, idx)

builtins.StopIteration: 1

During handling of the above exception, another exception occurred:

๏ฟผ File "/dowload_questrade_data/questrade/questrade_play.py", line 4, in <module>
  q = Questrade(refresh_token='<my token code>')
File "/usr/local/lib/python3.7/site-packages/questrade_api/questrade.py", line 22, in __init__
  self.auth = Auth(**auth_kwargs, config=self.config)
File "/usr/local/lib/python3.7/site-packages/questrade_api/auth.py", line 20, in __init__
  self.__refresh_token(kwargs['refresh_token'])
File "/usr/local/lib/python3.7/site-packages/questrade_api/auth.py", line 39, in __refresh_token
  token = json.loads(r.read().decode('utf-8'))
File "/usr/local/Cellar/python/3.7.5/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/__init__.py", line 348, in loads
  return _default_decoder.decode(s)
File "/usr/local/Cellar/python/3.7.5/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/decoder.py", line 337, in decode
  obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/usr/local/Cellar/python/3.7.5/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/decoder.py", line 355, in raw_decode
  raise JSONDecodeError("Expecting value", s, err.value) from None

json.decoder.JSONDecodeError: Expecting value: line 1 column 2 (char 1)

*** From 'decoder.py' ***

  def raw_decode(self, s, idx=0):
       """Decode a JSON document from ``s`` (a ``str`` beginning with
       a JSON document) and return a 2-tuple of the Python
       representation and the index in ``s`` where the document ended.

       This can be used to decode a JSON document from a string that may
       have extraneous data at the end.

       """
       try:
           obj, end = self.scan_once(s, idx)
       except StopIteration as err:
           raise JSONDecodeError("Expecting value", s, err.value) from None
       return obj, end

Issue with line 355: raise JSONDecodeError("Expecting value", s, err.value) from None

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.