Skip to content

Commit

Permalink
Merge pull request #3 from dalenguyen/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
Dale Nguyen authored Feb 27, 2021
2 parents 5e9f033 + 6307cd9 commit 2414b2f
Show file tree
Hide file tree
Showing 15 changed files with 258 additions and 28 deletions.
14 changes: 14 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Editor configuration, see http://editorconfig.org
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
max_line_length = 120

[*.md]
max_line_length = off
trim_trailing_whitespace = false
10 changes: 5 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ language: python

python:
- "3.7"
- "3.7-dev" # 3.7 development branch
- "3.8-dev" # 3.8 development branch
- "nightly" # nightly build
- "3.7-dev" # 3.7 development branch
- "3.8-dev" # 3.8 development branch
# - "nightly" # nightly build

install:
# - pip install -r requirements.txt
- pip install -r requirements.txt
- python setup.py install
- pip install coverage

script:
- nosetests --with-coverage --cover-package=stockai
- nosetests --with-coverage --cover-package=stockai
43 changes: 33 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

Python module to get stock data from Yahoo! Finance

*This is an ongoing project. If you have any requests or contributions, please create a [ticket](https://github.com/dalenguyen/stockai/issues)*
_This is an ongoing project. If you have any requests or contributions, please create a [ticket](https://github.com/dalenguyen/stockai/issues)_

## Install

Expand All @@ -15,6 +15,29 @@ From PyPI with pip
pip install stockai
```

## Development

Create a virtual environment

```
python3 -m venv venv
source env/bin/activate
pip3 install -r requirements.txt
```

For MacOS, you may need to use this command in order eto install ciso8601

```
ARCHFLAGS="-arch x86_64" pip install ciso8601
```

## Running Tests

```
python -m unittest tests/*
```

## Usage examples

```python
Expand All @@ -33,41 +56,41 @@ print(td.get_currency())
td.get_historical_prices('2019-01-01', '2019-01-05')

### The result is a dictionary with ['volumn', 'low', 'open', 'hight', 'close', 'date', 'adjclose']
{
'volume':[
{
'volume':[
3930300,
5407700,
5103400
],
'low':[
'low':[
67.12000274658203,
67.12000274658203,
67.66999816894531
],
'open':[
'open':[
67.51000213623047,
68.11000061035156,
68.0
],
'high':[
'high':[
68.43000030517578,
68.11000061035156,
68.1500015258789
],
'close':[
'close':[
68.25,
67.30000305175781,
67.9800033569336
],
'date':[
'date':[
'2019-01-02',
'2019-01-03',
'2019-01-04'
],
'adjclose':[
'adjclose':[
67.57575225830078,
66.63513946533203,
67.30841827392578
]
}
```
```
25 changes: 25 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Change log

> **Tags:**
>
> - :boom: [Breaking Change]
> - :eyeglasses: [Spec Compliancy]
> - :rocket: [New Feature]
> - :bug: [Bug Fix]
> - :memo: [Documentation]
> - :nail_care: [Polish]
---

## [1.0.0] - 2021-02-27

#### - :rocket: [New Feature]

- Restructured projects
- Added WealthSimple

## [0.0.4] - 2019-04-09

#### - :rocket: [New Feature]

- Retrieve stock price & data from Yahoo! Finance
3 changes: 3 additions & 0 deletions contributing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Contributing to StockAI

I would love for you to contribute to this project and help make it better than it is today. I will update the the detail later. For now, just a simple pull request will works.
36 changes: 36 additions & 0 deletions examples/wealthsimple.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import sys
sys.path.append('../stockai')

from stockai import WealthSimple

email: str = ''
password: str = ''

def prepare_credentails():
global email, password
print('Prepare credentials')
while not email:
email = str(input("Enter email: \n>>> "))
while not password:
password = str(input("Enter password: \n>>> "))

def init():
global username, password

ws = WealthSimple(email, password)

print('Get me...\n')
me = ws.get_me()
print(me)

print('Get accounts\n')
accounts = ws.get_accounts()
print(accounts)

print('Get security \n')
TSLA = ws.get_security('TSLA')
print(TSLA)

prepare_credentails()
init()

5 changes: 3 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
ciso8601==2.1.1
requests==2.21.0
ciso8601==2.1.3
requests==2.25.1
loguru==0.5.3
12 changes: 9 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,26 @@
with open("README.md", "r") as fh:
long_description = fh.read()

# Deploy to PyPI
#
# pip install twine
# python setup.py sdist bdist_wheel
# twine upload --skip-existing dist/*

setuptools.setup(
name="stockai",
version="0.0.4",
version="1.0.0",
author="Dale Nguyen",
author_email="[email protected]",
description="Get stock info from Yahoo! Finance",
long_description=long_description,
long_description_content_type="text/markdown",
url="https://github.com/dalenguyen/stockai",
packages=setuptools.find_packages(),
install_requires = [ 'ciso8601', 'requests', ],
install_requires = [ 'ciso8601', 'requests', 'loguru' ],
classifiers=[
"Programming Language :: Python :: 3",
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
"Operating System :: OS Independent",
],
)
)
5 changes: 3 additions & 2 deletions stockai/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
Stockai - get stock information from Yahoo! Finance
"""

__version__ = '0.0.4'
__version__ = '1.0.0'
__author__ = 'Dale Nguyen'
__name__ = 'stockai'

from .stock import Stock
from .yahoo.stock import Stock
from .wealthsimple.stock import WealthSimple
30 changes: 30 additions & 0 deletions stockai/wealthsimple/requests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import requests

class WSAPIRequest:
"""
Handle API requests for WealthSimple
"""

def __init__(self, session, WS_URL):
self.session = session
self.WS_URL = WS_URL

def request(self, method, endpoint, params=None):
url = self.WS_URL + endpoint

if method == 'POST':
return self.post(url, params)
elif method == 'GET':
return self.get(url, params)
else:
raise Exception('Invalid request method: {method}')

def post(self, url, params=None):
try:
return self.session.post(url, params)
except Exception as error:
print(error)

def get(self, url, payload=None):
auth = self.session.headers['Authorization']
return requests.get(url, headers = { 'Authorization': auth })
68 changes: 68 additions & 0 deletions stockai/wealthsimple/stock.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
from requests import Session
from .requests import WSAPIRequest
from loguru import logger

class WealthSimple():
BASE_DOMAIN = 'https://trade-service.wealthsimple.com/'

def __init__(self, email: str, password: str):
self.session = Session()
self.WSAPI = WSAPIRequest(self.session, self.BASE_DOMAIN)
self.login(email, password)

def login (self, email: str = None, password: str = None) -> None:
if email and password:
payload = { "email": email, "password": password, "timeoutMs": 2e4 }
response = self.WSAPI.request('POST', 'auth/login', payload)

# Check of OTP
if "x-wealthsimple-otp" in response.headers:
TFACode = ''
while not TFACode:
# Obtain user input and ensure it is not empty
TFACode = input('Enter 2FA code: ')
payload['otp'] = TFACode
response = self.WSAPI.request('POST', 'auth/login', payload)

if response.status_code == 401:
raise Exception('Invalid Login')

self.session.headers.update(
{"Authorization": response.headers["X-Access-Token"]}
)
self.session.headers.update(
{"refresh_token": response.headers["X-Refresh-Token"]}
)
else:
raise Exception('Missing login credentials')

def get_me(self):
logger.debug('get_me')
response = self.WSAPI.request('GET', 'me')
logger.debug(f'get_me {response.status_code}')

if response.status_code == 401:
raise Exception('Invalid Access Token')
else:
return response.json()

def get_accounts(self) -> list:
"""
Get Wealthsimple Trade Accounts
"""
response = self.WSAPI.request('GET', 'account/list')
response = response.json()
return response['results']

def get_security(self, id: str) -> dict:
"""
Get Security Info
"""
logger.debug('get_security')
response = self.WSAPI.request('GET', f'securities/{id}')
logger.debug(f"get_security {response.status_code}")

if response.status_code == 401:
raise Exception(f'Cannot get security {id}')
else:
return response.json()
2 changes: 1 addition & 1 deletion stockai/base.py → stockai/yahoo/base.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from requests import get
from .utils import timestamp_to_date
from ..utils import timestamp_to_date

class Base(object):
def __init__(self, symbol):
Expand Down
2 changes: 1 addition & 1 deletion stockai/stock.py → stockai/yahoo/stock.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from .base import Base
from .utils import date_to_timestamp
from ..utils import date_to_timestamp

class Stock(Base):
def __init__(self, symbol):
Expand Down
8 changes: 4 additions & 4 deletions tests/test.py → tests/stock.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,17 @@
class TestStock(TestCase):

def setUp(self):
self.td = Stock('TD.TO')
self.td = Stock('TD.TO')

def test_td_summary_profile(self):
self.assertEqual(self.td.get_summary_profile()['city'], 'Toronto')

def test_td_financial_data(self):
float(self.td.get_price())
self.assertEqual(self.td.get_currency(), 'CAD')
float(self.td.get_price())
self.assertEqual(self.td.get_currency(), 'CAD')

def test_td_historical_prices(self):
dict(self.td.get_historical_prices('2019-01-01', '2019-01-05'))

if __name__ == "__main__":
test_main()
test_main()
Loading

0 comments on commit 2414b2f

Please sign in to comment.