From 7afa86dc2d4e331581ebd00a66d1bca02f1c6296 Mon Sep 17 00:00:00 2001 From: Justin Date: Wed, 24 Feb 2021 23:21:02 -0600 Subject: [PATCH 01/72] start of Docker and docker-compose support --- .dockerignore | 7 +++++++ Dockerfile | 29 +++++++++++++++++++++++++++++ docker-compose.yaml | 9 +++++++++ 3 files changed, 45 insertions(+) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 docker-compose.yaml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000000..4f223a0c1d1 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +.git + +.dockerignore +.env* +.gitignore +docker-compose.yaml +Dockerfile* diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000000..d639cd25e5c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,29 @@ +FROM python:3.6.13-slim-buster + +RUN apt-get update && apt-get -y install --no-install-recommends \ +ca-certificates \ +wget \ +curl \ +telnet \ +net-tools \ +iputils-ping \ +dnsutils \ +git \ +gnupg \ +unzip \ +bzip2 && \ +apt-get clean && \ +rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +RUN mkdir -p /home/gamestonkterminal +WORKDIR /home/gamestonkterminal + +COPY . . + +RUN pip install -r requirements.txt +RUN pip install git+https://github.com/DidierRLopes/TimeSeriesCrossValidation + +RUN chown -R python /home/gamestonkterminal +USER python + +CMD ["python", "gameston_terminal.py"] diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 00000000000..486a9ad7038 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,9 @@ +version: '3.8' +services: + gamestonkterminal: + build: + context: . + image: gamestonkterminal:dev + dns: + - 1.1.1.1 + - 8.8.8.8 From 52c836ebfc6901c63a906d3a6d59679fe6b2b911 Mon Sep 17 00:00:00 2001 From: Justin Date: Wed, 24 Feb 2021 23:25:53 -0600 Subject: [PATCH 02/72] missing k --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index d639cd25e5c..6403a96ca21 100644 --- a/Dockerfile +++ b/Dockerfile @@ -26,4 +26,4 @@ RUN pip install git+https://github.com/DidierRLopes/TimeSeriesCrossValidation RUN chown -R python /home/gamestonkterminal USER python -CMD ["python", "gameston_terminal.py"] +CMD ["python", "gamestonk_terminal.py"] From 8830782066ab0be244b9402b2ce3956b804fe9dd Mon Sep 17 00:00:00 2001 From: Justin Date: Wed, 24 Feb 2021 23:29:51 -0600 Subject: [PATCH 03/72] added INSTALL_ON_LINUX=1 and still pip install fails --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 6403a96ca21..b6b26240c28 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,7 +20,7 @@ WORKDIR /home/gamestonkterminal COPY . . -RUN pip install -r requirements.txt +RUN INSTALL_ON_LINUX=1 && pip install -r requirements.txt RUN pip install git+https://github.com/DidierRLopes/TimeSeriesCrossValidation RUN chown -R python /home/gamestonkterminal From 54520a295d97218685ab91b3e09981462f89f453 Mon Sep 17 00:00:00 2001 From: Justin Date: Wed, 24 Feb 2021 23:37:48 -0600 Subject: [PATCH 04/72] create python user in Dockerfile --- Dockerfile | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index b6b26240c28..840aca6328c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,15 +15,18 @@ bzip2 && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* -RUN mkdir -p /home/gamestonkterminal -WORKDIR /home/gamestonkterminal +RUN useradd --create-home --shell /bin/bash python +USER python + +RUN mkdir -p /home/python/gamestonkterminal +WORKDIR /home/python/gamestonkterminal COPY . . -RUN INSTALL_ON_LINUX=1 && pip install -r requirements.txt +RUN INSTALL_ON_LINUX=1 pip install -r requirements.txt RUN pip install git+https://github.com/DidierRLopes/TimeSeriesCrossValidation RUN chown -R python /home/gamestonkterminal -USER python + CMD ["python", "gamestonk_terminal.py"] From 070c193a8b91880463457d8258d63c836d6f0613 Mon Sep 17 00:00:00 2001 From: Justin Date: Wed, 24 Feb 2021 23:48:25 -0600 Subject: [PATCH 05/72] fixes and remove using CloudFlare DNS in docker-compose.yaml --- Dockerfile | 7 +------ docker-compose.yaml | 3 --- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/Dockerfile b/Dockerfile index 840aca6328c..d89d2fe736b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,16 +17,11 @@ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* RUN useradd --create-home --shell /bin/bash python USER python - -RUN mkdir -p /home/python/gamestonkterminal -WORKDIR /home/python/gamestonkterminal +WORKDIR /home/python COPY . . RUN INSTALL_ON_LINUX=1 pip install -r requirements.txt RUN pip install git+https://github.com/DidierRLopes/TimeSeriesCrossValidation -RUN chown -R python /home/gamestonkterminal - - CMD ["python", "gamestonk_terminal.py"] diff --git a/docker-compose.yaml b/docker-compose.yaml index 486a9ad7038..bdbcb4a134e 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -4,6 +4,3 @@ services: build: context: . image: gamestonkterminal:dev - dns: - - 1.1.1.1 - - 8.8.8.8 From fe1063b9aadf3da5022c5ba9d5ace2dc965199d0 Mon Sep 17 00:00:00 2001 From: Justin Date: Thu, 25 Feb 2021 00:00:28 -0600 Subject: [PATCH 06/72] fix permissions --- Dockerfile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Dockerfile b/Dockerfile index d89d2fe736b..cf981dae7ea 100644 --- a/Dockerfile +++ b/Dockerfile @@ -24,4 +24,9 @@ COPY . . RUN INSTALL_ON_LINUX=1 pip install -r requirements.txt RUN pip install git+https://github.com/DidierRLopes/TimeSeriesCrossValidation +# is there a better way to do this? +USER root +RUN chown -R python /home/python + +USER python CMD ["python", "gamestonk_terminal.py"] From 30e79c2c9e784c75d924783b07509d1f4cc1c7ff Mon Sep 17 00:00:00 2001 From: Justin Date: Thu, 25 Feb 2021 00:07:43 -0600 Subject: [PATCH 07/72] permissions --- Dockerfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index cf981dae7ea..147fb8d9df6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -24,9 +24,9 @@ COPY . . RUN INSTALL_ON_LINUX=1 pip install -r requirements.txt RUN pip install git+https://github.com/DidierRLopes/TimeSeriesCrossValidation -# is there a better way to do this? +# is there a better way to do this? The chown is quite slow! USER root -RUN chown -R python /home/python - +RUN chown -R python:python /home/python USER python + CMD ["python", "gamestonk_terminal.py"] From a7afb60d516bc86a1d6b53d0ac083dffe271aefc Mon Sep 17 00:00:00 2001 From: Justin Date: Thu, 25 Feb 2021 01:51:36 -0600 Subject: [PATCH 08/72] requirements.txt fun. not --- Dockerfile | 2 ++ requirements.txt | 4 +--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 147fb8d9df6..427b37036e4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,8 @@ FROM python:3.6.13-slim-buster RUN apt-get update && apt-get -y install --no-install-recommends \ +gcc \ +make \ ca-certificates \ wget \ curl \ diff --git a/requirements.txt b/requirements.txt index a4a54419592..c2c3f140e7a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -78,7 +78,6 @@ PyMeeus==0.4.2 pyparsing==2.4.7 PySocks==1.7.1 python-dateutil==2.8.1 -python-Levenshtein==0.12.2 pytrends==4.7.3 pytz==2019.3 Quandl==3.6.0 @@ -88,7 +87,7 @@ requests-oauthlib==1.3.0 rsa==4.7.2 sacremoses==0.0.43 scikit-learn==0.24.1 -scipy==1.6.1 +scipy==1.4.1 segtok==1.5.10 sentencepiece==0.1.91 six==1.15.0 @@ -129,4 +128,3 @@ tensorflow==2.4.1 zipp==3.4.0 lunarcalendar fbprophet -levenshtein From f81af24199b841a054fc2f1d5c66e46333638e31 Mon Sep 17 00:00:00 2001 From: Justin Date: Thu, 25 Feb 2021 02:10:07 -0600 Subject: [PATCH 09/72] correct permissions using chmod trip in COPY. --- Dockerfile | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/Dockerfile b/Dockerfile index 427b37036e4..0523fd22e3c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,8 +2,8 @@ FROM python:3.6.13-slim-buster RUN apt-get update && apt-get -y install --no-install-recommends \ gcc \ +g++ \ make \ -ca-certificates \ wget \ curl \ telnet \ @@ -21,14 +21,9 @@ RUN useradd --create-home --shell /bin/bash python USER python WORKDIR /home/python -COPY . . +COPY --chown=python:python . . RUN INSTALL_ON_LINUX=1 pip install -r requirements.txt RUN pip install git+https://github.com/DidierRLopes/TimeSeriesCrossValidation -# is there a better way to do this? The chown is quite slow! -USER root -RUN chown -R python:python /home/python -USER python - CMD ["python", "gamestonk_terminal.py"] From 2522df0ed028162f5258443792182a9618894123 Mon Sep 17 00:00:00 2001 From: Justin Date: Thu, 25 Feb 2021 02:31:08 -0600 Subject: [PATCH 10/72] Mount local into container for development --- Dockerfile | 2 +- docker-compose.yaml | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 0523fd22e3c..3d1e2b4bd40 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,6 +14,7 @@ git \ gnupg \ unzip \ bzip2 && \ +apt-get -y autoremove && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* @@ -24,6 +25,5 @@ WORKDIR /home/python COPY --chown=python:python . . RUN INSTALL_ON_LINUX=1 pip install -r requirements.txt -RUN pip install git+https://github.com/DidierRLopes/TimeSeriesCrossValidation CMD ["python", "gamestonk_terminal.py"] diff --git a/docker-compose.yaml b/docker-compose.yaml index bdbcb4a134e..67ab223c65a 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -4,3 +4,5 @@ services: build: context: . image: gamestonkterminal:dev + volumes: + - .:/home/python From d3a4b90bde5838659c2c24613ac84f2a035fd637 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sat, 27 Feb 2021 14:57:46 +0100 Subject: [PATCH 11/72] GitHub Action to lint Python code --- .github/workflows/lint_python.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 .github/workflows/lint_python.yml diff --git a/.github/workflows/lint_python.yml b/.github/workflows/lint_python.yml new file mode 100644 index 00000000000..0fba0e0678c --- /dev/null +++ b/.github/workflows/lint_python.yml @@ -0,0 +1,19 @@ +name: lint_python +on: [pull_request, push] +jobs: + lint_python: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + - run: pip install bandit black codespell flake8 isort mypy pytest pyupgrade + - run: bandit -r . || true + - run: black --check . || true + - run: codespell --quiet-level=2 || true # --ignore-words-list="" --skip="" + - run: flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics + - run: isort --check-only --profile black . || true + - run: pip install -r requirements.txt || true + - run: mypy --ignore-missing-imports . || true + - run: pytest . || true + - run: pytest --doctest-modules . || true + - run: shopt -s globstar && pyupgrade --py36-plus **/*.py || true From d7e613fc78b76f95c326f15cb89109d6b0fb9e67 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sat, 27 Feb 2021 15:00:28 +0100 Subject: [PATCH 12/72] Use ==/!= to compare constant literals (str, bytes, int, float, tuple) --- prediction_techniques/neural_networks.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/prediction_techniques/neural_networks.py b/prediction_techniques/neural_networks.py index ff1c24f6fa7..1929843ad23 100644 --- a/prediction_techniques/neural_networks.py +++ b/prediction_techniques/neural_networks.py @@ -27,7 +27,7 @@ def build_neural_network_model(Recurrent_Neural_Network, n_inputs, n_days): for idx_layer, d_layer in enumerate(Recurrent_Neural_Network): # Recurrent Neural Network - if str(*d_layer) is 'SimpleRNN': + if str(*d_layer) == 'SimpleRNN': # Is this the input layer? If so, define input_shape if idx_layer == 0: model.add(SimpleRNN(**d_layer['SimpleRNN'], input_shape=(n_inputs, 1))) @@ -38,7 +38,7 @@ def build_neural_network_model(Recurrent_Neural_Network, n_inputs, n_days): model.add(SimpleRNN(**d_layer['SimpleRNN'])) # Long-Short Term-Memory - elif str(*d_layer) is 'LSTM': + elif str(*d_layer) == 'LSTM': # Is this the input layer? If so, define input_shape if idx_layer == 0: model.add(LSTM(**d_layer['LSTM'], input_shape=(n_inputs, 1))) @@ -49,7 +49,7 @@ def build_neural_network_model(Recurrent_Neural_Network, n_inputs, n_days): model.add(LSTM(**d_layer['LSTM'])) # Dense (Simple Neuron) - elif str(*d_layer) is 'Dense': + elif str(*d_layer) == 'Dense': # Is this the input layer? If so, define input_shape if idx_layer == 0: model.add(Dense(**d_layer['Dense'], input_dim=n_inputs)) From 39f0ae4b85b333b3ac82b73570eaf8e3a027f5d6 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sat, 27 Feb 2021 15:02:15 +0100 Subject: [PATCH 13/72] Use ==/!= to compare constant literals (str, bytes, int, float, tuple) --- discovery/short_interest_api.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/discovery/short_interest_api.py b/discovery/short_interest_api.py index 901fc555723..351eec49bb4 100644 --- a/discovery/short_interest_api.py +++ b/discovery/short_interest_api.py @@ -43,7 +43,7 @@ def high_short_interest(l_args): l_stock_info = list() for elem in a_high_short_interested_stocks: - if elem is '': + if elem == '': continue l_stock_info.append(elem) @@ -92,7 +92,7 @@ def low_float(l_args): l_stock_info = list() for elem in a_low_float_stocks: - if elem is '': + if elem == '': continue l_stock_info.append(elem) @@ -103,4 +103,4 @@ def low_float(l_args): pd.set_option('display.max_colwidth', -1) print(df_low_float.head(n=ns_parser.n_num).to_string(index=False)) - print("") \ No newline at end of file + print("") From 6e1914fe893431a53c292e12d11f93b34a20a6e7 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sat, 27 Feb 2021 15:07:38 +0100 Subject: [PATCH 14/72] Update neural_networks.py --- prediction_techniques/neural_networks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prediction_techniques/neural_networks.py b/prediction_techniques/neural_networks.py index 1929843ad23..38f7da13f85 100644 --- a/prediction_techniques/neural_networks.py +++ b/prediction_techniques/neural_networks.py @@ -60,7 +60,7 @@ def build_neural_network_model(Recurrent_Neural_Network, n_inputs, n_days): model.add(Dense(**d_layer['Dense'])) # Dropout (Regularization) - elif str(*d_layer) is 'Dropout': + elif str(*d_layer) == 'Dropout': model.add(Dropout(**d_layer['Dropout'])) else: From 0b7b354300f942174b312e3a836936dc99465bd7 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sat, 27 Feb 2021 15:16:22 +0100 Subject: [PATCH 15/72] Update lint_python.yml --- .github/workflows/lint_python.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint_python.yml b/.github/workflows/lint_python.yml index 0fba0e0678c..7f810f4f6c5 100644 --- a/.github/workflows/lint_python.yml +++ b/.github/workflows/lint_python.yml @@ -12,7 +12,7 @@ jobs: - run: codespell --quiet-level=2 || true # --ignore-words-list="" --skip="" - run: flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics - run: isort --check-only --profile black . || true - - run: pip install -r requirements.txt || true + - run: pip install -r requirements.txt - run: mypy --ignore-missing-imports . || true - run: pytest . || true - run: pytest --doctest-modules . || true From c26ccc57b90a1cc287c88d93223ea96ab1290c1e Mon Sep 17 00:00:00 2001 From: sigaloid <69441971+sigaloid@users.noreply.github.com> Date: Sat, 27 Feb 2021 16:58:47 +0000 Subject: [PATCH 16/72] Create bug_report.md --- .github/ISSUE_TEMPLATE/bug_report.md | 32 ++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000000..8909c8e97fb --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,32 @@ +--- +name: Bug report +about: Create a report to help us improve +title: "[Bug]" +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps and commands to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + - Browser [e.g. chrome, safari] + - Version [e.g. 22] + +**Additional context** +Add any other context about the problem here. From 15fb585bdce8a9ae508507f2054085dfae9d9f73 Mon Sep 17 00:00:00 2001 From: sigaloid <69441971+sigaloid@users.noreply.github.com> Date: Sat, 27 Feb 2021 16:59:15 +0000 Subject: [PATCH 17/72] Create feature_request.md --- .github/ISSUE_TEMPLATE/feature_request.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000000..9e8ab6a673f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: "[FR]" +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. From 79106c5efeace97e96523159e6082f41bd1578cf Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sat, 27 Feb 2021 21:19:13 +0100 Subject: [PATCH 18/72] codespell --ignore-words-list="mape" --quiet-level=2 --- .github/workflows/lint_python.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint_python.yml b/.github/workflows/lint_python.yml index 7f810f4f6c5..1354fefee97 100644 --- a/.github/workflows/lint_python.yml +++ b/.github/workflows/lint_python.yml @@ -9,7 +9,7 @@ jobs: - run: pip install bandit black codespell flake8 isort mypy pytest pyupgrade - run: bandit -r . || true - run: black --check . || true - - run: codespell --quiet-level=2 || true # --ignore-words-list="" --skip="" + - run: codespell --ignore-words-list="mape" --quiet-level=2 || true # --skip="" - run: flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics - run: isort --check-only --profile black . || true - run: pip install -r requirements.txt From 58ae580aa53ca66f3153c429ff38c849c0fed34e Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sat, 27 Feb 2021 21:22:02 +0100 Subject: [PATCH 19/72] Fix typos discovered by codespell --- sentiment/reddit_api.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sentiment/reddit_api.py b/sentiment/reddit_api.py index 6ef651a33ec..61132119b40 100644 --- a/sentiment/reddit_api.py +++ b/sentiment/reddit_api.py @@ -104,7 +104,7 @@ def watchlist(l_args): d_watchlist_tickers[key] = 1 l_watchlist_links.append(f"https://www.reddit.com{submission.permalink}") - # delte below, not necessary I reckon. Probably just link? + # delete below, not necessary I reckon. Probably just link? # Refactor data s_datetime = datetime.utcfromtimestamp(submission.created_utc).strftime("%d/%m/%Y %H:%M:%S") @@ -361,7 +361,7 @@ def spac_community(l_args): d_watchlist_tickers[key] = 1 l_watchlist_links.append(f"https://www.reddit.com{submission.permalink}") - # delte below, not necessary I reckon. Probably just link? + # delete below, not necessary I reckon. Probably just link? # Refactor data s_datetime = datetime.utcfromtimestamp(submission.created_utc).strftime("%d/%m/%Y %H:%M:%S") @@ -497,7 +497,7 @@ def spac(l_args): d_watchlist_tickers[key] = 1 l_watchlist_links.append(f"https://www.reddit.com{submission.permalink}") - # delte below, not necessary I reckon. Probably just link? + # delete below, not necessary I reckon. Probably just link? # Refactor data s_datetime = datetime.utcfromtimestamp(submission.created_utc).strftime("%d/%m/%Y %H:%M:%S") @@ -642,4 +642,4 @@ def wsb_community(l_args): break print("") except: - print("") \ No newline at end of file + print("") From b1ab52c34f6cd1dff506fb0cc985f7216acd11d9 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sat, 27 Feb 2021 21:24:09 +0100 Subject: [PATCH 20/72] Fix typos discovered by codespell --- fundamental_analysis/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fundamental_analysis/README.md b/fundamental_analysis/README.md index 2501ab3ad88..f5cdc6046e7 100644 --- a/fundamental_analysis/README.md +++ b/fundamental_analysis/README.md @@ -178,7 +178,7 @@ Prints a complete balance sheet statement over time. This can be either quarterl ``` usage: cash [-n N_NUM] [-q] ``` -Prints a complete cash flow statement over time. This can be either quarterly or annually. The following fields are expected: Accepted date, Accounts payables, Accounts receivables, Acquisitions net, Capital expenditure, Cash at beginning of period, Cash at end of period, Change in working capital, Common stock issued, Common stock repurchased, Debt repayment, Deferred income tax, Depreciation and amortization, Dividends paid, Effect of forex changes on cash, Filling date, Final link, Free cash flow, Inventory, Investments in property plant and equipment, Link, Net cash provided by operating activities, Net cash used for investing activites, Net cash used provided by financing activities, Net change in cash, Net income, Operating cash flow, Other financing activites, Other investing activites, Other non cash items, Other working capital, Period, Purchases of investments, Sales maturities of investments, Stock based compensation. [Source: Alpha Vantage] +Prints a complete cash flow statement over time. This can be either quarterly or annually. The following fields are expected: Accepted date, Accounts payables, Accounts receivables, Acquisitions net, Capital expenditure, Cash at beginning of period, Cash at end of period, Change in working capital, Common stock issued, Common stock repurchased, Debt repayment, Deferred income tax, Depreciation and amortization, Dividends paid, Effect of forex changes on cash, Filling date, Final link, Free cash flow, Inventory, Investments in property plant and equipment, Link, Net cash provided by operating activities, Net cash used for investing activities, Net cash used provided by financing activities, Net change in cash, Net income, Operating cash flow, Other financing activities, Other investing activities, Other non cash items, Other working capital, Period, Purchases of investments, Sales maturities of investments, Stock based compensation. [Source: Alpha Vantage] * n : Number of latest years/quarters. Default 1. * q : Quarter fundamental data flag. Default False. @@ -241,7 +241,7 @@ Prints a complete balance sheet statement over time. This can be either quarterl ``` usage: cashf [-n N_NUM] [-q] ``` -Prints a complete cash flow statement over time. This can be either quarterly or annually. The following fields are expected: Accepted date, Accounts payables, Accounts receivables, Acquisitions net, Capital expenditure, Cash at beginning of period, Cash at end of period, Change in working capital, Common stock issued, Common stock repurchased, Debt repayment, Deferred income tax, Depreciation and amortization, Dividends paid, Effect of forex changes on cash, Filling date, Final link, Free cash flow, Inventory, Investments in property plant and equipment, Link, Net cash provided by operating activities, Net cash used for investing activites, Net cash used provided by financing activities, Net change in cash, Net income, Operating cash flow, Other financing activites, Other investing activites, Other non cash items, Other working capital, Period, Purchases of investments, Sales maturities of investments, Stock based compensation. [Source: Financial Modeling Prep] +Prints a complete cash flow statement over time. This can be either quarterly or annually. The following fields are expected: Accepted date, Accounts payables, Accounts receivables, Acquisitions net, Capital expenditure, Cash at beginning of period, Cash at end of period, Change in working capital, Common stock issued, Common stock repurchased, Debt repayment, Deferred income tax, Depreciation and amortization, Dividends paid, Effect of forex changes on cash, Filling date, Final link, Free cash flow, Inventory, Investments in property plant and equipment, Link, Net cash provided by operating activities, Net cash used for investing activities, Net cash used provided by financing activities, Net change in cash, Net income, Operating cash flow, Other financing activities, Other investing activities, Other non cash items, Other working capital, Period, Purchases of investments, Sales maturities of investments, Stock based compensation. [Source: Financial Modeling Prep] * n : Number of latest years/quarters. Default 1. * q : Quarter fundamental data flag. Default False. From a2a3945a49f9489b390cdf97dda34e06b6254b1a Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sat, 27 Feb 2021 21:26:41 +0100 Subject: [PATCH 21/72] Fix typos discovered by codespell --- fundamental_analysis/alpha_vantage_api.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fundamental_analysis/alpha_vantage_api.py b/fundamental_analysis/alpha_vantage_api.py index 87a9b1288f8..8de17800192 100644 --- a/fundamental_analysis/alpha_vantage_api.py +++ b/fundamental_analysis/alpha_vantage_api.py @@ -247,9 +247,9 @@ def cash_flow(l_args, s_ticker): Debt repayment, Deferred income tax, Depreciation and amortization, Dividends paid, Effect of forex changes on cash, Filling date, Final link, Free cash flow, Inventory, Investments in property plant and equipment, Link, Net cash provided by operating activities, - Net cash used for investing activites, Net cash used provided by financing activities, Net - change in cash, Net income, Operating cash flow, Other financing activites, Other investing - activites, Other non cash items, Other working capital, Period, Purchases of investments, + Net cash used for investing activities, Net cash used provided by financing activities, Net + change in cash, Net income, Operating cash flow, Other financing activities, Other investing + activities, Other non cash items, Other working capital, Period, Purchases of investments, Sales maturities of investments, Stock based compensation. [Source: Alpha Vantage]""") parser.add_argument('-n', "--num", action="store", dest="n_num", type=check_positive, default=1, @@ -329,7 +329,7 @@ def earnings(l_args, s_ticker): "estimatedEPS":"Estimated EPS", "reportedDate":"Reported Date", "surprise":"Surprise", - "surprisePercentage":"Suprise Percentage"}) + "surprisePercentage":"Surprise Percentage"}) else: df_fa = pd.DataFrame(df_fa['annualEarnings'][0]) df_fa = df_fa.rename(columns={"fiscalDateEnding":"Fiscal Date Ending", From a4846aaaf44db87a9e492f126904b43d2612425f Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sat, 27 Feb 2021 21:27:47 +0100 Subject: [PATCH 22/72] Fix typos discovered by codespell --- fundamental_analysis/financial_modeling_prep_api.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fundamental_analysis/financial_modeling_prep_api.py b/fundamental_analysis/financial_modeling_prep_api.py index f9e9e684296..7ff1558b585 100644 --- a/fundamental_analysis/financial_modeling_prep_api.py +++ b/fundamental_analysis/financial_modeling_prep_api.py @@ -286,9 +286,9 @@ def cash_flow(l_args, s_ticker): Debt repayment, Deferred income tax, Depreciation and amortization, Dividends paid, Effect of forex changes on cash, Filling date, Final link, Free cash flow, Inventory, Investments in property plant and equipment, Link, Net cash provided by operating activities, - Net cash used for investing activites, Net cash used provided by financing activities, Net - change in cash, Net income, Operating cash flow, Other financing activites, Other investing - activites, Other non cash items, Other working capital, Period, Purchases of investments, + Net cash used for investing activities, Net cash used provided by financing activities, Net + change in cash, Net income, Operating cash flow, Other financing activities, Other investing + activities, Other non cash items, Other working capital, Period, Purchases of investments, Sales maturities of investments, Stock based compensation. [Source: Financial Modeling Prep]""") parser.add_argument('-n', "--num", action="store", dest="n_num", type=check_positive, default=1, @@ -509,4 +509,4 @@ def financial_statement_growth(l_args, s_ticker): except: print("") return - \ No newline at end of file + From 7089673ded8728403a4b2eec3fa68e621ecb6a3b Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sat, 27 Feb 2021 21:28:49 +0100 Subject: [PATCH 23/72] Make codespell a mandatory test --- .github/workflows/lint_python.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint_python.yml b/.github/workflows/lint_python.yml index 1354fefee97..318f5a74e0e 100644 --- a/.github/workflows/lint_python.yml +++ b/.github/workflows/lint_python.yml @@ -9,7 +9,7 @@ jobs: - run: pip install bandit black codespell flake8 isort mypy pytest pyupgrade - run: bandit -r . || true - run: black --check . || true - - run: codespell --ignore-words-list="mape" --quiet-level=2 || true # --skip="" + - run: codespell --ignore-words-list="mape" --quiet-level=2 # --skip="" - run: flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics - run: isort --check-only --profile black . || true - run: pip install -r requirements.txt From 794467443c3f9a22b2c8445619ad34aa64df907b Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sat, 27 Feb 2021 21:37:43 +0100 Subject: [PATCH 24/72] pip install -r requirements.txt || true --- .github/workflows/lint_python.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint_python.yml b/.github/workflows/lint_python.yml index 318f5a74e0e..5d7ca7652a3 100644 --- a/.github/workflows/lint_python.yml +++ b/.github/workflows/lint_python.yml @@ -12,7 +12,7 @@ jobs: - run: codespell --ignore-words-list="mape" --quiet-level=2 # --skip="" - run: flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics - run: isort --check-only --profile black . || true - - run: pip install -r requirements.txt + - run: pip install -r requirements.txt || true - run: mypy --ignore-missing-imports . || true - run: pytest . || true - run: pytest --doctest-modules . || true From 9e79817bd51ecc43c50c44d4888c0e3b96d29cd3 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sun, 28 Feb 2021 08:09:18 +0100 Subject: [PATCH 25/72] Update lint_python.yml --- .github/workflows/lint_python.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/lint_python.yml b/.github/workflows/lint_python.yml index 5d7ca7652a3..e72ec894a9b 100644 --- a/.github/workflows/lint_python.yml +++ b/.github/workflows/lint_python.yml @@ -6,7 +6,7 @@ jobs: steps: - uses: actions/checkout@v2 - uses: actions/setup-python@v2 - - run: pip install bandit black codespell flake8 isort mypy pytest pyupgrade + - run: pip install bandit black codespell flake8 isort mypy pytest pyupgrade safety - run: bandit -r . || true - run: black --check . || true - run: codespell --ignore-words-list="mape" --quiet-level=2 # --skip="" @@ -17,3 +17,4 @@ jobs: - run: pytest . || true - run: pytest --doctest-modules . || true - run: shopt -s globstar && pyupgrade --py36-plus **/*.py || true + - run: safety check || true From 9b0d92b89ca32abef0e4b467843ee1b98c0e71f0 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sun, 28 Feb 2021 08:12:04 +0100 Subject: [PATCH 26/72] Make safety check a mandatory test --- .github/workflows/lint_python.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint_python.yml b/.github/workflows/lint_python.yml index e72ec894a9b..3365e5f3f6b 100644 --- a/.github/workflows/lint_python.yml +++ b/.github/workflows/lint_python.yml @@ -17,4 +17,4 @@ jobs: - run: pytest . || true - run: pytest --doctest-modules . || true - run: shopt -s globstar && pyupgrade --py36-plus **/*.py || true - - run: safety check || true + - run: safety check From 32be931e69a642d1a9499194a59c2c2041988ca8 Mon Sep 17 00:00:00 2001 From: Didier Lopes Date: Sun, 28 Feb 2021 15:53:58 +0000 Subject: [PATCH 27/72] #27 Attempt to use poetry for package management --- .dockerignore | 2 +- Dockerfile | 6 +- poetry.lock | 2806 ++++++++++++++++++++++++++++++++++++++++++++++++ pyproject.toml | 37 + 4 files changed, 2849 insertions(+), 2 deletions(-) create mode 100644 poetry.lock create mode 100644 pyproject.toml diff --git a/.dockerignore b/.dockerignore index 4f223a0c1d1..2097259688f 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,5 +1,5 @@ .git - +.* .dockerignore .env* .gitignore diff --git a/Dockerfile b/Dockerfile index 3d1e2b4bd40..cec864b683a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -22,8 +22,12 @@ RUN useradd --create-home --shell /bin/bash python USER python WORKDIR /home/python +ENV PATH="/home/python/.local/bin:${PATH}" + COPY --chown=python:python . . -RUN INSTALL_ON_LINUX=1 pip install -r requirements.txt +#RUN INSTALL_ON_LINUX=1 pip install -r requirements.txt +RUN pip install "poetry==1.1.4" +RUN poetry export -f requirements.txt | pip install -r /dev/stdin CMD ["python", "gamestonk_terminal.py"] diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 00000000000..25f56de7e4d --- /dev/null +++ b/poetry.lock @@ -0,0 +1,2806 @@ +[[package]] +name = "absl-py" +version = "0.11.0" +description = "Abseil Python Common Libraries, see https://github.com/abseil/abseil-py." +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +six = "*" + +[[package]] +name = "aiohttp" +version = "3.7.4" +description = "Async http client/server framework (asyncio)" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +async-timeout = ">=3.0,<4.0" +attrs = ">=17.3.0" +chardet = ">=2.0,<4.0" +idna-ssl = {version = ">=1.0", markers = "python_version < \"3.7\""} +multidict = ">=4.5,<7.0" +typing-extensions = ">=3.6.5" +yarl = ">=1.0,<2.0" + +[package.extras] +speedups = ["aiodns", "brotlipy", "cchardet"] + +[[package]] +name = "alpha-vantage" +version = "2.3.1" +description = "Python module to get stock data from the Alpha Vantage Api" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +aiohttp = "*" +requests = "*" + +[[package]] +name = "astunparse" +version = "1.6.3" +description = "An AST unparser for Python" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +six = ">=1.6.1,<2.0" + +[[package]] +name = "async-timeout" +version = "3.0.1" +description = "Timeout context manager for asyncio programs" +category = "main" +optional = false +python-versions = ">=3.5.3" + +[[package]] +name = "attrs" +version = "20.3.0" +description = "Classes Without Boilerplate" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[package.extras] +dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "furo", "sphinx", "pre-commit"] +docs = ["furo", "sphinx", "zope.interface"] +tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"] +tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six"] + +[[package]] +name = "beautifulsoup4" +version = "4.9.3" +description = "Screen-scraping library" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +soupsieve = {version = ">1.2", markers = "python_version >= \"3.0\""} + +[package.extras] +html5lib = ["html5lib"] +lxml = ["lxml"] + +[[package]] +name = "bpemb" +version = "0.3.2" +description = "Byte-pair embeddings in 275 languages" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +gensim = "*" +numpy = "*" +requests = "*" +sentencepiece = "*" +tqdm = "*" + +[[package]] +name = "bs4" +version = "0.0.1" +description = "Dummy package for Beautiful Soup" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +beautifulsoup4 = "*" + +[[package]] +name = "cachetools" +version = "4.2.1" +description = "Extensible memoizing collections and decorators" +category = "main" +optional = false +python-versions = "~=3.5" + +[[package]] +name = "certifi" +version = "2020.12.5" +description = "Python package for providing Mozilla's CA Bundle." +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "chardet" +version = "3.0.4" +description = "Universal encoding detector for Python 2 and 3" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "click" +version = "7.1.2" +description = "Composable command line interface toolkit" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[[package]] +name = "cloudpickle" +version = "1.6.0" +description = "Extended pickling support for Python objects" +category = "main" +optional = false +python-versions = ">=3.5" + +[[package]] +name = "cmdstanpy" +version = "0.4.0" +description = "Python interface to CmdStan" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +numpy = "*" +pandas = "*" + +[package.extras] +docs = ["sphinx", "sphinx-gallery", "sphinx-rtd-theme", "numpydoc", "matplotlib"] +tests = ["pytest", "pytest-cov"] + +[[package]] +name = "convertdate" +version = "2.3.1" +description = "Converts between Gregorian dates and other calendar systems.Calendars included: Baha'i, French Republican, Hebrew, Indian Civil, Islamic, ISO, Julian, Mayan and Persian." +category = "main" +optional = false +python-versions = ">=3.5" + +[package.dependencies] +pymeeus = ">=0.3.6,<0.3.8 || >0.3.8,<=1" +pytz = ">=2014.10" + +[package.extras] +docs = ["sphinx", "sphinx-rtd-theme"] +test = ["coverage"] + +[[package]] +name = "cssselect" +version = "1.1.0" +description = "cssselect parses CSS3 Selectors and translates them to XPath 1.0" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[[package]] +name = "cycler" +version = "0.10.0" +description = "Composable style cycles" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +six = "*" + +[[package]] +name = "cython" +version = "0.29.17" +description = "The Cython compiler for writing C extensions for the Python language." +category = "main" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" + +[[package]] +name = "dataclasses" +version = "0.8" +description = "A backport of the dataclasses module for Python 3.6" +category = "main" +optional = false +python-versions = ">=3.6, <3.7" + +[[package]] +name = "decorator" +version = "4.4.2" +description = "Decorators for Humans" +category = "main" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*" + +[[package]] +name = "deprecated" +version = "1.2.11" +description = "Python @deprecated decorator to deprecate old python classes, functions or methods." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[package.dependencies] +wrapt = ">=1.10,<2" + +[package.extras] +dev = ["tox", "bump2version (<1)", "sphinx (<2)", "importlib-metadata (<3)", "importlib-resources (<4)", "configparser (<5)", "sphinxcontrib-websupport (<2)", "zipp (<2)", "PyTest (<5)", "PyTest-Cov (<2.6)", "pytest", "pytest-cov"] + +[[package]] +name = "ephem" +version = "3.7.7.1" +description = "Compute positions of the planets and stars" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "fbprophet" +version = "0.6" +description = "Automatic Forecasting Procedure" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +cmdstanpy = "0.4" +convertdate = ">=2.1.2" +Cython = ">=0.22" +holidays = ">=0.9.5" +LunarCalendar = ">=0.0.9" +matplotlib = ">=2.0.0" +numpy = ">=1.10.0" +pandas = ">=0.23.4" +pystan = ">=2.14" +python-dateutil = ">=2.8.0" +setuptools-git = ">=1.2" + +[[package]] +name = "filelock" +version = "3.0.12" +description = "A platform independent file lock." +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "finviz" +version = "1.3.4" +description = "Unofficial API for finviz.com" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +aiohttp = "*" +cssselect = "*" +lxml = "*" +requests = "*" +urllib3 = "*" +user_agent = "*" + +[[package]] +name = "flair" +version = "0.7" +description = "A very simple framework for state-of-the-art NLP" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +bpemb = ">=0.3.2" +deprecated = ">=1.2.4" +ftfy = "*" +gdown = "*" +gensim = ">=3.4.0,<=3.8.3" +hyperopt = ">=0.1.1" +janome = "*" +konoha = ">=4.0.0,<5.0.0" +langdetect = "*" +lxml = "*" +matplotlib = ">=2.2.3" +mpld3 = "0.3" +python-dateutil = ">=2.6.1" +regex = "*" +scikit-learn = ">=0.21.3" +segtok = ">=1.5.7" +sentencepiece = "<=0.1.91" +sqlitedict = ">=1.6.0" +tabulate = "*" +torch = ">=1.1.0" +tqdm = ">=4.26.0" +transformers = ">=3.5.0,<=3.5.1" + +[[package]] +name = "flatbuffers" +version = "1.12" +description = "The FlatBuffers serialization format for Python" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "ftfy" +version = "5.9" +description = "Fixes some problems with Unicode text after the fact" +category = "main" +optional = false +python-versions = ">=3.5" + +[package.dependencies] +wcwidth = "*" + +[[package]] +name = "fundamentalanalysis" +version = "0.2.6" +description = "Fully-fledged Fundamental Analysis package capable of collecting 20 years of Company Profiles, Financial Statements, Ratios and Stock Data of 13.000+ companies." +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "future" +version = "0.18.2" +description = "Clean single-source support for Python 3 and 2" +category = "main" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" + +[[package]] +name = "gast" +version = "0.3.3" +description = "Python AST that abstracts the underlying Python version" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[[package]] +name = "gdown" +version = "3.12.2" +description = "Google Drive direct download of big files." +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +filelock = "*" +requests = {version = "*", extras = ["socks"]} +six = "*" +tqdm = "*" + +[[package]] +name = "gensim" +version = "3.8.2" +description = "Python framework for fast Vector Space Modelling" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +numpy = ">=1.11.3" +scipy = ">=1.0.0" +six = ">=1.5.0" +smart-open = ">=1.8.1" + +[package.extras] +distributed = ["Pyro4 (>=4.27)"] +docs = ["pytest", "pytest-rerunfailures", "mock", "cython", "testfixtures", "Morfessor (==2.0.2a4)", "python-Levenshtein (>=0.10.2)", "visdom (>0.1.8.7)", "scikit-learn", "Pyro4 (>=4.27)", "sphinx", "sphinxcontrib-napoleon", "plotly", "pattern (<=2.6)", "sphinxcontrib.programoutput"] +test = ["pytest", "pytest-rerunfailures", "mock", "cython", "testfixtures", "Morfessor (==2.0.2a4)", "python-Levenshtein (>=0.10.2)", "visdom (>0.1.8.7)", "scikit-learn"] +test-win = ["pytest", "pytest-rerunfailures", "mock", "cython", "testfixtures", "Morfessor (==2.0.2a4)", "python-Levenshtein (>=0.10.2)", "visdom (>0.1.8.7)", "scikit-learn"] + +[[package]] +name = "google-auth" +version = "1.27.0" +description = "Google Authentication Library" +category = "main" +optional = false +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*" + +[package.dependencies] +cachetools = ">=2.0.0,<5.0" +pyasn1-modules = ">=0.2.1" +rsa = {version = ">=3.1.4,<5", markers = "python_version >= \"3.6\""} +six = ">=1.9.0" + +[package.extras] +aiohttp = ["aiohttp (>=3.6.2,<4.0.0dev)"] +pyopenssl = ["pyopenssl (>=20.0.0)"] + +[[package]] +name = "google-auth-oauthlib" +version = "0.4.2" +description = "Google Authentication Library" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +google-auth = "*" +requests-oauthlib = ">=0.7.0" + +[package.extras] +tool = ["click"] + +[[package]] +name = "google-pasta" +version = "0.2.0" +description = "pasta is an AST-based Python refactoring library" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +six = "*" + +[[package]] +name = "grpcio" +version = "1.32.0" +description = "HTTP/2-based RPC framework" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +six = ">=1.5.2" + +[package.extras] +protobuf = ["grpcio-tools (>=1.32.0)"] + +[[package]] +name = "h5py" +version = "2.10.0" +description = "Read and write HDF5 files from Python" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +numpy = ">=1.7" +six = "*" + +[[package]] +name = "hijri-converter" +version = "2.1.1" +description = "Accurate Hijri-Gregorian date converter based on the Umm al-Qura calendar" +category = "main" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "holidays" +version = "0.10.5.2" +description = "Generate and work with holidays in Python" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +convertdate = ">=2.3.0" +hijri_converter = "*" +korean_lunar_calendar = "*" +python-dateutil = "*" +six = "*" + +[[package]] +name = "hyperopt" +version = "0.2.5" +description = "Distributed Asynchronous Hyperparameter Optimization" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +cloudpickle = "*" +future = "*" +networkx = ">=2.2" +numpy = "*" +scipy = "*" +six = "*" +tqdm = "*" + +[package.extras] +atpe = ["lightgbm", "scikit-learn"] +mongotrials = ["pymongo"] +sparktrials = ["pyspark"] +dev = ["black", "pre-commit", "nose", "pytest"] + +[[package]] +name = "idna" +version = "2.10" +description = "Internationalized Domain Names in Applications (IDNA)" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[[package]] +name = "idna-ssl" +version = "1.1.0" +description = "Patch ssl.match_hostname for Unicode(idna) domains support" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +idna = ">=2.0" + +[[package]] +name = "importlib-metadata" +version = "3.7.0" +description = "Read metadata from Python packages" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} +zipp = ">=0.5" + +[package.extras] +docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] +testing = ["pytest (>=3.5,!=3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-cov", "pytest-enabler", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"] + +[[package]] +name = "inflection" +version = "0.5.1" +description = "A port of Ruby on Rails inflector to Python" +category = "main" +optional = false +python-versions = ">=3.5" + +[[package]] +name = "iso8601" +version = "0.1.14" +description = "Simple module to parse ISO 8601 dates" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "janome" +version = "0.4.1" +description = "Japanese morphological analysis engine." +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "joblib" +version = "1.0.1" +description = "Lightweight pipelining with Python functions" +category = "main" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "keras-preprocessing" +version = "1.1.2" +description = "Easy data preprocessing and data augmentation for deep learning models" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +numpy = ">=1.9.1" +six = ">=1.9.0" + +[package.extras] +image = ["scipy (>=0.14)", "Pillow (>=5.2.0)"] +pep8 = ["flake8"] +tests = ["pandas", "pillow", "tensorflow", "keras", "pytest", "pytest-xdist", "pytest-cov"] + +[[package]] +name = "kiwisolver" +version = "1.3.1" +description = "A fast implementation of the Cassowary constraint solver" +category = "main" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "konoha" +version = "4.6.2" +description = "A tiny sentence/word tokenizer for Japanese text written in Python" +category = "main" +optional = false +python-versions = ">=3.6.1,<4.0.0" + +[package.dependencies] +overrides = "3.0.0" + +[package.extras] +janome = ["janome (>=0.3.10,<0.4.0)"] +all = ["janome (>=0.3.10,<0.4.0)", "natto-py (>=0.9.0,<0.10.0)", "kytea (>=0.1.4,<0.2.0)", "sentencepiece (>=0.1.85,<0.2.0)", "sudachipy (==0.4.9)", "boto3 (>=1.11.0,<2.0.0)", "fastapi (>=0.54.1,<0.55.0)", "uvicorn (>=0.11.5,<0.12.0)", "sudachidict-core (>=20200330,<20200331)", "nagisa (>=0.2.7,<0.3.0)"] +all_with_integrations = ["janome (>=0.3.10,<0.4.0)", "natto-py (>=0.9.0,<0.10.0)", "kytea (>=0.1.4,<0.2.0)", "sentencepiece (>=0.1.85,<0.2.0)", "sudachipy (==0.4.9)", "boto3 (>=1.11.0,<2.0.0)", "allennlp (>=1.0.0,<2.0.0)", "fastapi (>=0.54.1,<0.55.0)", "uvicorn (>=0.11.5,<0.12.0)", "sudachidict-core (>=20200330,<20200331)", "nagisa (>=0.2.7,<0.3.0)"] +mecab = ["natto-py (>=0.9.0,<0.10.0)"] +kytea = ["kytea (>=0.1.4,<0.2.0)"] +sentencepiece = ["sentencepiece (>=0.1.85,<0.2.0)"] +sudachi = ["sudachipy (==0.4.9)", "sudachidict-core (>=20200330,<20200331)"] +remote = ["boto3 (>=1.11.0,<2.0.0)"] +allennlp = ["allennlp (>=1.0.0,<2.0.0)"] +server = ["fastapi (>=0.54.1,<0.55.0)", "uvicorn (>=0.11.5,<0.12.0)"] +docs = ["sphinx (>=3.1.1,<4.0.0)", "sphinx_rtd_theme (>=0.4.3,<0.5.0)"] +nagisa = ["nagisa (>=0.2.7,<0.3.0)"] + +[[package]] +name = "korean-lunar-calendar" +version = "0.2.1" +description = "Korean Lunar Calendar" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "langdetect" +version = "1.0.8" +description = "Language detection library ported from Google's language-detection." +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +six = "*" + +[[package]] +name = "lunarcalendar" +version = "0.0.9" +description = "A lunar calendar converter, including a number of lunar and solar holidays, mainly from China." +category = "main" +optional = false +python-versions = ">=2.7, <4" + +[package.dependencies] +ephem = ">=3.7.5.3" +python-dateutil = ">=2.6.1" +pytz = "*" + +[[package]] +name = "lxml" +version = "4.6.2" +description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*" + +[package.extras] +cssselect = ["cssselect (>=0.7)"] +html5 = ["html5lib"] +htmlsoup = ["beautifulsoup4"] +source = ["Cython (>=0.29.7)"] + +[[package]] +name = "markdown" +version = "3.3.4" +description = "Python implementation of Markdown." +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} + +[package.extras] +testing = ["coverage", "pyyaml"] + +[[package]] +name = "matplotlib" +version = "3.3.3" +description = "Python plotting package" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +cycler = ">=0.10" +kiwisolver = ">=1.0.1" +numpy = ">=1.15" +pillow = ">=6.2.0" +pyparsing = ">=2.0.3,<2.0.4 || >2.0.4,<2.1.2 || >2.1.2,<2.1.6 || >2.1.6" +python-dateutil = ">=2.1" + +[[package]] +name = "more-itertools" +version = "8.7.0" +description = "More routines for operating on iterables, beyond itertools" +category = "main" +optional = false +python-versions = ">=3.5" + +[[package]] +name = "mpld3" +version = "0.3" +description = "D3 Viewer for Matplotlib" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "multidict" +version = "5.1.0" +description = "multidict implementation" +category = "main" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "multitasking" +version = "0.0.9" +description = "Non-blocking Python methods using decorators" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "networkx" +version = "2.5" +description = "Python package for creating and manipulating graphs and networks" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +decorator = ">=4.3.0" + +[package.extras] +all = ["numpy", "scipy", "pandas", "matplotlib", "pygraphviz", "pydot", "pyyaml", "lxml", "pytest"] +gdal = ["gdal"] +lxml = ["lxml"] +matplotlib = ["matplotlib"] +numpy = ["numpy"] +pandas = ["pandas"] +pydot = ["pydot"] +pygraphviz = ["pygraphviz"] +pytest = ["pytest"] +pyyaml = ["pyyaml"] +scipy = ["scipy"] + +[[package]] +name = "numpy" +version = "1.19.5" +description = "NumPy is the fundamental package for array computing with Python." +category = "main" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "oauthlib" +version = "3.1.0" +description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[package.extras] +rsa = ["cryptography"] +signals = ["blinker"] +signedtoken = ["cryptography", "pyjwt (>=1.0.0)"] + +[[package]] +name = "opt-einsum" +version = "3.3.0" +description = "Optimizing numpys einsum function" +category = "main" +optional = false +python-versions = ">=3.5" + +[package.dependencies] +numpy = ">=1.7" + +[package.extras] +docs = ["sphinx (==1.2.3)", "sphinxcontrib-napoleon", "sphinx-rtd-theme", "numpydoc"] +tests = ["pytest", "pytest-cov", "pytest-pep8"] + +[[package]] +name = "overrides" +version = "3.0.0" +description = "A decorator to automatically detect mismatch when overriding a method." +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "packaging" +version = "20.9" +description = "Core utilities for Python packages" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[package.dependencies] +pyparsing = ">=2.0.2" + +[[package]] +name = "pandas" +version = "1.1.5" +description = "Powerful data structures for data analysis, time series, and statistics" +category = "main" +optional = false +python-versions = ">=3.6.1" + +[package.dependencies] +numpy = ">=1.15.4" +python-dateutil = ">=2.7.3" +pytz = ">=2017.2" + +[package.extras] +test = ["pytest (>=4.0.2)", "pytest-xdist", "hypothesis (>=3.58)"] + +[[package]] +name = "pandas-ta" +version = "0.2.23b" +description = "An easy to use Python 3 Pandas Extension with 115+ Technical Analysis Indicators. Can be called from a Pandas DataFrame or standalone like TA-Lib. Correlation tested with TA-Lib." +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +pandas = "*" + +[package.extras] +dev = ["ta-lib", "jupyterlab", "sklearn", "statsmodels"] +test = ["ta-lib"] + +[[package]] +name = "patsy" +version = "0.5.1" +description = "A Python package for describing statistical models and for building design matrices." +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +numpy = ">=1.4" +six = "*" + +[[package]] +name = "pillow" +version = "8.1.0" +description = "Python Imaging Library (Fork)" +category = "main" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "plotly" +version = "4.14.3" +description = "An open-source, interactive data visualization library for Python" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +retrying = ">=1.3.3" +six = "*" + +[[package]] +name = "pmdarima" +version = "1.8.0" +description = "Python's forecast::auto.arima equivalent" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +Cython = ">=0.29,<0.29.18" +joblib = ">=0.11" +numpy = ">=1.17.3" +pandas = ">=0.19" +scikit-learn = ">=0.22" +scipy = ">=1.3.2" +statsmodels = ">=0.11,<0.12.0 || >0.12.0" +urllib3 = "*" + +[[package]] +name = "praw" +version = "7.1.4" +description = "PRAW, an acronym for `Python Reddit API Wrapper`, is a python package that allows for simple access to reddit's API." +category = "main" +optional = false +python-versions = "~=3.6" + +[package.dependencies] +prawcore = ">=1.5.0,<2.0" +update-checker = ">=0.18" +websocket-client = ">=0.54.0" + +[package.extras] +ci = ["coveralls"] +dev = ["packaging", "pre-commit", "black", "flake8", "flynt", "isort", "pydocstyle", "sphinx (<3.0)", "sphinx-rtd-theme", "betamax (>=0.8,<0.9)", "betamax-matchers (>=0.3.0,<0.5)", "pytest (>=2.7.3)"] +lint = ["black", "flake8", "flynt", "isort", "pydocstyle", "sphinx (<3.0)", "sphinx-rtd-theme"] +readthedocs = ["sphinx (<3.0)"] +test = ["betamax (>=0.8,<0.9)", "betamax-matchers (>=0.3.0,<0.5)", "pytest (>=2.7.3)"] + +[[package]] +name = "prawcore" +version = "1.5.0" +description = "Low-level communication layer for PRAW 4+." +category = "main" +optional = false +python-versions = ">=3.5" + +[package.dependencies] +requests = ">=2.6.0,<3.0" + +[package.extras] +ci = ["coveralls"] +dev = ["black", "flake8", "pre-commit", "pydocstyle", "betamax (>=0.8,<0.9)", "betamax-matchers (>=0.4.0,<0.5)", "betamax-serializers (>=0.2.0,<0.3)", "mock (>=0.8)", "pytest", "testfixtures (>4.13.2,<7)"] +lint = ["black", "flake8", "pre-commit", "pydocstyle"] +test = ["betamax (>=0.8,<0.9)", "betamax-matchers (>=0.4.0,<0.5)", "betamax-serializers (>=0.2.0,<0.3)", "mock (>=0.8)", "pytest", "testfixtures (>4.13.2,<7)"] + +[[package]] +name = "prettytable" +version = "2.0.0" +description = "A simple Python library for easily displaying tabular data in a visually appealing ASCII table format" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +wcwidth = "*" + +[package.extras] +tests = ["pytest", "pytest-cov"] + +[[package]] +name = "protobuf" +version = "3.15.3" +description = "Protocol Buffers" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +six = ">=1.9" + +[[package]] +name = "psaw" +version = "0.0.12" +description = "Pushshift.io API Wrapper for reddit.com public comment/submission search" +category = "main" +optional = false +python-versions = ">=3" + +[package.dependencies] +Click = "*" +requests = "*" + +[[package]] +name = "pyasn1" +version = "0.4.8" +description = "ASN.1 types and codecs" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "pyasn1-modules" +version = "0.2.8" +description = "A collection of ASN.1-based protocols modules." +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +pyasn1 = ">=0.4.6,<0.5.0" + +[[package]] +name = "pymeeus" +version = "0.4.2" +description = "Python implementation of Jean Meeus astronomical routines" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "pyparsing" +version = "2.4.7" +description = "Python parsing module" +category = "main" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" + +[[package]] +name = "pysocks" +version = "1.7.1" +description = "A Python SOCKS client module. See https://github.com/Anorov/PySocks for more information." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[[package]] +name = "pystan" +version = "2.19.1.1" +description = "Python interface to Stan, a package for Bayesian inference" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +Cython = ">=0.22,<0.25.1 || >0.25.1" +numpy = ">=1.7" + +[[package]] +name = "python-dateutil" +version = "2.8.1" +description = "Extensions to the standard Python datetime module" +category = "main" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "pytrends" +version = "4.7.3" +description = "Pseudo API for Google Trends" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +lxml = "*" +pandas = ">=0.25" +requests = "*" + +[[package]] +name = "pytz" +version = "2021.1" +description = "World timezone definitions, modern and historical" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "quandl" +version = "3.6.0" +description = "Package for quandl API access" +category = "main" +optional = false +python-versions = ">= 3.5" + +[package.dependencies] +inflection = ">=0.3.1" +more-itertools = "*" +numpy = ">=1.8" +pandas = ">=0.14" +python-dateutil = "*" +requests = ">=2.7.0" +six = "*" + +[[package]] +name = "rapidfuzz" +version = "1.1.1" +description = "rapid fuzzy string matching" +category = "main" +optional = false +python-versions = ">=2.7" + +[[package]] +name = "regex" +version = "2020.11.13" +description = "Alternative regular expression module, to replace re." +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "requests" +version = "2.25.1" +description = "Python HTTP for Humans." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[package.dependencies] +certifi = ">=2017.4.17" +chardet = ">=3.0.2,<5" +idna = ">=2.5,<3" +PySocks = {version = ">=1.5.6,<1.5.7 || >1.5.7", optional = true, markers = "extra == \"socks\""} +urllib3 = ">=1.21.1,<1.27" + +[package.extras] +security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"] +socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"] + +[[package]] +name = "requests-oauthlib" +version = "1.3.0" +description = "OAuthlib authentication support for Requests." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[package.dependencies] +oauthlib = ">=3.0.0" +requests = ">=2.0.0" + +[package.extras] +rsa = ["oauthlib[signedtoken] (>=3.0.0)"] + +[[package]] +name = "retrying" +version = "1.3.3" +description = "Retrying" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +six = ">=1.7.0" + +[[package]] +name = "rsa" +version = "4.7.2" +description = "Pure-Python RSA implementation" +category = "main" +optional = false +python-versions = ">=3.5, <4" + +[package.dependencies] +pyasn1 = ">=0.1.3" + +[[package]] +name = "sacremoses" +version = "0.0.43" +description = "SacreMoses" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +click = "*" +joblib = "*" +regex = "*" +six = "*" +tqdm = "*" + +[[package]] +name = "scikit-learn" +version = "0.24.1" +description = "A set of python modules for machine learning and data mining" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +joblib = ">=0.11" +numpy = ">=1.13.3" +scipy = ">=0.19.1" +threadpoolctl = ">=2.0.0" + +[package.extras] +benchmark = ["matplotlib (>=2.1.1)", "pandas (>=0.25.0)", "memory-profiler (>=0.57.0)"] +docs = ["matplotlib (>=2.1.1)", "scikit-image (>=0.13)", "pandas (>=0.25.0)", "seaborn (>=0.9.0)", "memory-profiler (>=0.57.0)", "sphinx (>=3.2.0)", "sphinx-gallery (>=0.7.0)", "numpydoc (>=1.0.0)", "Pillow (>=7.1.2)", "sphinx-prompt (>=1.3.0)"] +examples = ["matplotlib (>=2.1.1)", "scikit-image (>=0.13)", "pandas (>=0.25.0)", "seaborn (>=0.9.0)"] +tests = ["matplotlib (>=2.1.1)", "scikit-image (>=0.13)", "pandas (>=0.25.0)", "pytest (>=5.0.1)", "pytest-cov (>=2.9.0)", "flake8 (>=3.8.2)", "mypy (>=0.770)", "pyamg (>=4.0.0)"] + +[[package]] +name = "scipy" +version = "1.5.4" +description = "SciPy: Scientific Library for Python" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +numpy = ">=1.14.5" + +[[package]] +name = "segtok" +version = "1.5.10" +description = "sentence segmentation and word tokenization tools" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +regex = "*" + +[[package]] +name = "sentencepiece" +version = "0.1.91" +description = "SentencePiece python wrapper" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "setuptools-git" +version = "1.2" +description = "Setuptools revision control system plugin for Git" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "six" +version = "1.15.0" +description = "Python 2 and 3 compatibility utilities" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" + +[[package]] +name = "smart-open" +version = "4.2.0" +description = "Utils for streaming large files (S3, HDFS, GCS, Azure Blob Storage, gzip, bz2...)" +category = "main" +optional = false +python-versions = ">=3.6.*" + +[package.extras] +all = ["boto3", "google-cloud-storage", "azure-storage-blob", "azure-common", "azure-core", "requests"] +azure = ["azure-storage-blob", "azure-common", "azure-core"] +gcp = ["google-cloud-storage"] +http = ["requests"] +s3 = ["boto3"] +test = ["boto3", "google-cloud-storage", "azure-storage-blob", "azure-common", "azure-core", "requests", "mock", "moto[server] (==1.3.14)", "pathlib2", "responses", "boto3", "paramiko", "parameterizedtestcase", "pytest", "pytest-rerunfailures"] +webhdfs = ["requests"] + +[[package]] +name = "soupsieve" +version = "2.2" +description = "A modern CSS selector implementation for Beautiful Soup." +category = "main" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "sqlitedict" +version = "1.7.0" +description = "Persistent dict in Python, backed up by sqlite3 and pickle, multithread-safe." +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "statsmodels" +version = "0.12.2" +description = "Statistical computations and models for Python" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +numpy = ">=1.15" +pandas = ">=0.21" +patsy = ">=0.5" +scipy = ">=1.1" + +[package.extras] +build = ["cython (>=0.29)"] +develop = ["cython (>=0.29)"] +docs = ["sphinx", "nbconvert", "jupyter-client", "ipykernel", "matplotlib", "nbformat", "numpydoc", "pandas-datareader"] + +[[package]] +name = "tabulate" +version = "0.8.9" +description = "Pretty-print tabular data" +category = "main" +optional = false +python-versions = "*" + +[package.extras] +widechars = ["wcwidth"] + +[[package]] +name = "tensorboard" +version = "2.4.1" +description = "TensorBoard lets you watch Tensors Flow" +category = "main" +optional = false +python-versions = ">= 2.7, != 3.0.*, != 3.1.*" + +[package.dependencies] +absl-py = ">=0.4" +google-auth = ">=1.6.3,<2" +google-auth-oauthlib = ">=0.4.1,<0.5" +grpcio = ">=1.24.3" +markdown = ">=2.6.8" +numpy = ">=1.12.0" +protobuf = ">=3.6.0" +requests = ">=2.21.0,<3" +six = ">=1.10.0" +tensorboard-plugin-wit = ">=1.6.0" +werkzeug = ">=0.11.15" + +[[package]] +name = "tensorboard-plugin-wit" +version = "1.8.0" +description = "What-If Tool TensorBoard plugin." +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "tensorflow" +version = "2.4.1" +description = "TensorFlow is an open source machine learning framework for everyone." +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +absl-py = ">=0.10,<1.0" +astunparse = ">=1.6.3,<1.7.0" +flatbuffers = ">=1.12.0,<1.13.0" +gast = "0.3.3" +google-pasta = ">=0.2,<1.0" +grpcio = ">=1.32.0,<1.33.0" +h5py = ">=2.10.0,<2.11.0" +keras-preprocessing = ">=1.1.2,<1.2.0" +numpy = ">=1.19.2,<1.20.0" +opt-einsum = ">=3.3.0,<3.4.0" +protobuf = ">=3.9.2" +six = ">=1.15.0,<1.16.0" +tensorboard = ">=2.4,<3.0" +tensorflow-estimator = ">=2.4.0,<2.5.0" +termcolor = ">=1.1.0,<1.2.0" +typing-extensions = ">=3.7.4,<3.8.0" +wrapt = ">=1.12.1,<1.13.0" + +[[package]] +name = "tensorflow-estimator" +version = "2.4.0" +description = "TensorFlow Estimator." +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "termcolor" +version = "1.1.0" +description = "ANSII Color formatting for output in terminal." +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "threadpoolctl" +version = "2.1.0" +description = "threadpoolctl" +category = "main" +optional = false +python-versions = ">=3.5" + +[[package]] +name = "TimeSeriesCrossValidation" +version = "0.4" +description = "" +category = "main" +optional = false +python-versions = "*" +develop = false + +[package.dependencies] +numpy = "*" + +[package.source] +type = "git" +url = "https://github.com/DidierRLopes/TimeSeriesCrossValidation.git" +reference = "master" +resolved_reference = "1e29d393204abb3bde23ff3f15258ed85d3b263e" + +[[package]] +name = "tokenizers" +version = "0.9.3" +description = "Fast and Customizable Tokenizers" +category = "main" +optional = false +python-versions = "*" + +[package.extras] +testing = ["pytest"] + +[[package]] +name = "torch" +version = "1.7.1" +description = "Tensors and Dynamic neural networks in Python with strong GPU acceleration" +category = "main" +optional = false +python-versions = ">=3.6.2" + +[package.dependencies] +dataclasses = {version = "*", markers = "python_version < \"3.7\""} +numpy = "*" +typing-extensions = "*" + +[[package]] +name = "tqdm" +version = "4.58.0" +description = "Fast, Extensible Progress Meter" +category = "main" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" + +[package.extras] +dev = ["py-make (>=0.1.0)", "twine", "wheel"] +telegram = ["requests"] + +[[package]] +name = "transformers" +version = "3.5.1" +description = "State-of-the-art Natural Language Processing for TensorFlow 2.0 and PyTorch" +category = "main" +optional = false +python-versions = ">=3.6.0" + +[package.dependencies] +dataclasses = {version = "*", markers = "python_version < \"3.7\""} +filelock = "*" +numpy = "*" +packaging = "*" +protobuf = "*" +regex = "!=2019.12.17" +requests = "*" +sacremoses = "*" +sentencepiece = "0.1.91" +tokenizers = "0.9.3" +tqdm = ">=4.27" + +[package.extras] +all = ["tensorflow (>=2.0)", "onnxconverter-common", "keras2onnx", "torch (>=1.0)", "jaxlib (==0.1.55)", "jax (>=0.2.0)", "flax (==0.2.2)", "sentencepiece (==0.1.91)", "tokenizers (==0.9.2)"] +dev = ["tensorflow (>=2.0)", "onnxconverter-common", "keras2onnx", "torch (>=1.0)", "jaxlib (==0.1.55)", "jax (>=0.2.0)", "flax (==0.2.2)", "sentencepiece (==0.1.91)", "tokenizers (==0.9.2)", "pytest", "pytest-xdist", "timeout-decorator", "parameterized", "psutil", "faiss-cpu", "datasets", "black (>=20.8b1)", "isort (>=5.5.4)", "flake8 (>=3.8.3)", "fugashi (>=1.0)", "ipadic (>=1.0.0,<2.0)", "unidic-lite (>=1.0.7)", "unidic (>=1.0.2)", "recommonmark", "sphinx (==3.2.1)", "sphinx-markdown-tables", "sphinx-rtd-theme (==0.4.3)", "sphinx-copybutton", "scikit-learn"] +docs = ["recommonmark", "sphinx (==3.2.1)", "sphinx-markdown-tables", "sphinx-rtd-theme (==0.4.3)", "sphinx-copybutton"] +flax = ["jaxlib (==0.1.55)", "jax (>=0.2.0)", "flax (==0.2.2)"] +ja = ["fugashi (>=1.0)", "ipadic (>=1.0.0,<2.0)", "unidic-lite (>=1.0.7)", "unidic (>=1.0.2)"] +onnxruntime = ["onnxruntime (>=1.4.0)", "onnxruntime-tools (>=1.4.2)"] +quality = ["black (>=20.8b1)", "isort (>=5.5.4)", "flake8 (>=3.8.3)"] +retrieval = ["faiss-cpu", "datasets"] +sentencepiece = ["sentencepiece (==0.1.91)"] +serving = ["pydantic", "uvicorn", "fastapi", "starlette"] +sklearn = ["scikit-learn"] +testing = ["pytest", "pytest-xdist", "timeout-decorator", "parameterized", "psutil", "faiss-cpu", "datasets"] +tf = ["tensorflow (>=2.0)", "onnxconverter-common", "keras2onnx"] +tf-cpu = ["tensorflow-cpu (>=2.0)", "onnxconverter-common", "keras2onnx"] +tokenizers = ["tokenizers (==0.9.2)"] +torch = ["torch (>=1.0)"] + +[[package]] +name = "typing-extensions" +version = "3.7.4.3" +description = "Backported and Experimental Type Hints for Python 3.5+" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "update-checker" +version = "0.18.0" +description = "A python module that will check for package updates." +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +requests = ">=2.3.0" + +[package.extras] +dev = ["black", "flake8", "pytest (>=2.7.3)"] +lint = ["black", "flake8"] +test = ["pytest (>=2.7.3)"] + +[[package]] +name = "urllib3" +version = "1.26.3" +description = "HTTP library with thread-safe connection pooling, file post, and more." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" + +[package.extras] +brotli = ["brotlipy (>=0.6.0)"] +secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] +socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] + +[[package]] +name = "user-agent" +version = "0.1.9" +description = "User-Agent generator" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +six = "*" + +[[package]] +name = "wcwidth" +version = "0.2.5" +description = "Measures the displayed width of unicode strings in a terminal" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "websocket-client" +version = "0.57.0" +description = "WebSocket client for Python. hybi13 is supported." +category = "main" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[package.dependencies] +six = "*" + +[[package]] +name = "werkzeug" +version = "1.0.1" +description = "The comprehensive WSGI web application library." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[package.extras] +dev = ["pytest", "pytest-timeout", "coverage", "tox", "sphinx", "pallets-sphinx-themes", "sphinx-issues"] +watchdog = ["watchdog"] + +[[package]] +name = "wrapt" +version = "1.12.1" +description = "Module for decorators, wrappers and monkey patching." +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "yarl" +version = "1.6.3" +description = "Yet another URL library" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +idna = ">=2.0" +multidict = ">=4.0" +typing-extensions = {version = ">=3.7.4", markers = "python_version < \"3.8\""} + +[[package]] +name = "yfinance" +version = "0.1.55" +description = "Yahoo! Finance market data downloader" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +lxml = ">=4.5.1" +multitasking = ">=0.0.7" +numpy = ">=1.15" +pandas = ">=0.24" +requests = ">=2.20" + +[[package]] +name = "zipp" +version = "3.4.0" +description = "Backport of pathlib-compatible object wrapper for zip files" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.extras] +docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"] +testing = ["pytest (>=3.5,!=3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-cov", "jaraco.test (>=3.2.0)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"] + +[metadata] +lock-version = "1.1" +python-versions = "3.6.13" +content-hash = "93086c15c0e3a2cb06ea26b57f4af5e3b20128492e916eefba79c8d7f28350b4" + +[metadata.files] +absl-py = [ + {file = "absl-py-0.11.0.tar.gz", hash = "sha256:673cccb88d810e5627d0c1c818158485d106f65a583880e2f730c997399bcfa7"}, + {file = "absl_py-0.11.0-py3-none-any.whl", hash = "sha256:b3d9eb5119ff6e0a0125f6dabf2f9fae02f8acae7be70576002fac27235611c5"}, +] +aiohttp = [ + {file = "aiohttp-3.7.4-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:6c8200abc9dc5f27203986100579fc19ccad7a832c07d2bc151ce4ff17190076"}, + {file = "aiohttp-3.7.4-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:dd7936f2a6daa861143e376b3a1fb56e9b802f4980923594edd9ca5670974895"}, + {file = "aiohttp-3.7.4-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:bc3d14bf71a3fb94e5acf5bbf67331ab335467129af6416a437bd6024e4f743d"}, + {file = "aiohttp-3.7.4-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:8ec1a38074f68d66ccb467ed9a673a726bb397142c273f90d4ba954666e87d54"}, + {file = "aiohttp-3.7.4-cp36-cp36m-manylinux2014_ppc64le.whl", hash = "sha256:b84ad94868e1e6a5e30d30ec419956042815dfaea1b1df1cef623e4564c374d9"}, + {file = "aiohttp-3.7.4-cp36-cp36m-manylinux2014_s390x.whl", hash = "sha256:d5d102e945ecca93bcd9801a7bb2fa703e37ad188a2f81b1e65e4abe4b51b00c"}, + {file = "aiohttp-3.7.4-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:c2a80fd9a8d7e41b4e38ea9fe149deed0d6aaede255c497e66b8213274d6d61b"}, + {file = "aiohttp-3.7.4-cp36-cp36m-win32.whl", hash = "sha256:481d4b96969fbfdcc3ff35eea5305d8565a8300410d3d269ccac69e7256b1329"}, + {file = "aiohttp-3.7.4-cp36-cp36m-win_amd64.whl", hash = "sha256:16d0683ef8a6d803207f02b899c928223eb219111bd52420ef3d7a8aa76227b6"}, + {file = "aiohttp-3.7.4-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:eab51036cac2da8a50d7ff0ea30be47750547c9aa1aa2cf1a1b710a1827e7dbe"}, + {file = "aiohttp-3.7.4-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:feb24ff1226beeb056e247cf2e24bba5232519efb5645121c4aea5b6ad74c1f2"}, + {file = "aiohttp-3.7.4-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:119feb2bd551e58d83d1b38bfa4cb921af8ddedec9fad7183132db334c3133e0"}, + {file = "aiohttp-3.7.4-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:6ca56bdfaf825f4439e9e3673775e1032d8b6ea63b8953d3812c71bd6a8b81de"}, + {file = "aiohttp-3.7.4-cp37-cp37m-manylinux2014_ppc64le.whl", hash = "sha256:5563ad7fde451b1986d42b9bb9140e2599ecf4f8e42241f6da0d3d624b776f40"}, + {file = "aiohttp-3.7.4-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:62bc216eafac3204877241569209d9ba6226185aa6d561c19159f2e1cbb6abfb"}, + {file = "aiohttp-3.7.4-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:f4496d8d04da2e98cc9133e238ccebf6a13ef39a93da2e87146c8c8ac9768242"}, + {file = "aiohttp-3.7.4-cp37-cp37m-win32.whl", hash = "sha256:2ffea7904e70350da429568113ae422c88d2234ae776519549513c8f217f58a9"}, + {file = "aiohttp-3.7.4-cp37-cp37m-win_amd64.whl", hash = "sha256:5e91e927003d1ed9283dee9abcb989334fc8e72cf89ebe94dc3e07e3ff0b11e9"}, + {file = "aiohttp-3.7.4-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:4c1bdbfdd231a20eee3e56bd0ac1cd88c4ff41b64ab679ed65b75c9c74b6c5c2"}, + {file = "aiohttp-3.7.4-cp38-cp38-manylinux1_i686.whl", hash = "sha256:71680321a8a7176a58dfbc230789790639db78dad61a6e120b39f314f43f1907"}, + {file = "aiohttp-3.7.4-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:7dbd087ff2f4046b9b37ba28ed73f15fd0bc9f4fdc8ef6781913da7f808d9536"}, + {file = "aiohttp-3.7.4-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:dee68ec462ff10c1d836c0ea2642116aba6151c6880b688e56b4c0246770f297"}, + {file = "aiohttp-3.7.4-cp38-cp38-manylinux2014_ppc64le.whl", hash = "sha256:99c5a5bf7135607959441b7d720d96c8e5c46a1f96e9d6d4c9498be8d5f24212"}, + {file = "aiohttp-3.7.4-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:5dde6d24bacac480be03f4f864e9a67faac5032e28841b00533cd168ab39cad9"}, + {file = "aiohttp-3.7.4-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:418597633b5cd9639e514b1d748f358832c08cd5d9ef0870026535bd5eaefdd0"}, + {file = "aiohttp-3.7.4-cp38-cp38-win32.whl", hash = "sha256:e76e78863a4eaec3aee5722d85d04dcbd9844bc6cd3bfa6aa880ff46ad16bfcb"}, + {file = "aiohttp-3.7.4-cp38-cp38-win_amd64.whl", hash = "sha256:950b7ef08b2afdab2488ee2edaff92a03ca500a48f1e1aaa5900e73d6cf992bc"}, + {file = "aiohttp-3.7.4-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:2eb3efe243e0f4ecbb654b08444ae6ffab37ac0ef8f69d3a2ffb958905379daf"}, + {file = "aiohttp-3.7.4-cp39-cp39-manylinux1_i686.whl", hash = "sha256:822bd4fd21abaa7b28d65fc9871ecabaddc42767884a626317ef5b75c20e8a2d"}, + {file = "aiohttp-3.7.4-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:58c62152c4c8731a3152e7e650b29ace18304d086cb5552d317a54ff2749d32a"}, + {file = "aiohttp-3.7.4-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:7c7820099e8b3171e54e7eedc33e9450afe7cd08172632d32128bd527f8cb77d"}, + {file = "aiohttp-3.7.4-cp39-cp39-manylinux2014_ppc64le.whl", hash = "sha256:5b50e0b9460100fe05d7472264d1975f21ac007b35dcd6fd50279b72925a27f4"}, + {file = "aiohttp-3.7.4-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:c44d3c82a933c6cbc21039326767e778eface44fca55c65719921c4b9661a3f7"}, + {file = "aiohttp-3.7.4-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:cc31e906be1cc121ee201adbdf844522ea3349600dd0a40366611ca18cd40e81"}, + {file = "aiohttp-3.7.4-cp39-cp39-win32.whl", hash = "sha256:fbd3b5e18d34683decc00d9a360179ac1e7a320a5fee10ab8053ffd6deab76e0"}, + {file = "aiohttp-3.7.4-cp39-cp39-win_amd64.whl", hash = "sha256:40bd1b101b71a18a528ffce812cc14ff77d4a2a1272dfb8b11b200967489ef3e"}, + {file = "aiohttp-3.7.4.tar.gz", hash = "sha256:5d84ecc73141d0a0d61ece0742bb7ff5751b0657dab8405f899d3ceb104cc7de"}, +] +alpha-vantage = [ + {file = "alpha_vantage-2.3.1-py3-none-any.whl", hash = "sha256:5d05355febe6f0fafc4bd11dc6ce3504a02d9d3c105d60202539855c0f608661"}, + {file = "alpha_vantage-2.3.1.tar.gz", hash = "sha256:0ce76908c3e2a22f9bbdacead90195ec3a4fa41ef8ae7c69a4a2fc99459bfbec"}, +] +astunparse = [ + {file = "astunparse-1.6.3-py2.py3-none-any.whl", hash = "sha256:c2652417f2c8b5bb325c885ae329bdf3f86424075c4fd1a128674bc6fba4b8e8"}, + {file = "astunparse-1.6.3.tar.gz", hash = "sha256:5ad93a8456f0d084c3456d059fd9a92cce667963232cbf763eac3bc5b7940872"}, +] +async-timeout = [ + {file = "async-timeout-3.0.1.tar.gz", hash = "sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f"}, + {file = "async_timeout-3.0.1-py3-none-any.whl", hash = "sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3"}, +] +attrs = [ + {file = "attrs-20.3.0-py2.py3-none-any.whl", hash = "sha256:31b2eced602aa8423c2aea9c76a724617ed67cf9513173fd3a4f03e3a929c7e6"}, + {file = "attrs-20.3.0.tar.gz", hash = "sha256:832aa3cde19744e49938b91fea06d69ecb9e649c93ba974535d08ad92164f700"}, +] +beautifulsoup4 = [ + {file = "beautifulsoup4-4.9.3-py2-none-any.whl", hash = "sha256:4c98143716ef1cb40bf7f39a8e3eec8f8b009509e74904ba3a7b315431577e35"}, + {file = "beautifulsoup4-4.9.3-py3-none-any.whl", hash = "sha256:fff47e031e34ec82bf17e00da8f592fe7de69aeea38be00523c04623c04fb666"}, + {file = "beautifulsoup4-4.9.3.tar.gz", hash = "sha256:84729e322ad1d5b4d25f805bfa05b902dd96450f43842c4e99067d5e1369eb25"}, +] +bpemb = [ + {file = "bpemb-0.3.2-py3-none-any.whl", hash = "sha256:2a84d0ef963221d01a41b2a4c5d26ef2978992d6558e7289bbe58f7fd03a6446"}, + {file = "bpemb-0.3.2.tar.gz", hash = "sha256:7ef2564f656ec48c4621f555c4431c4ec71900f3c45c8d2203f9c78446e8391c"}, +] +bs4 = [ + {file = "bs4-0.0.1.tar.gz", hash = "sha256:36ecea1fd7cc5c0c6e4a1ff075df26d50da647b75376626cc186e2212886dd3a"}, +] +cachetools = [ + {file = "cachetools-4.2.1-py3-none-any.whl", hash = "sha256:1d9d5f567be80f7c07d765e21b814326d78c61eb0c3a637dffc0e5d1796cb2e2"}, + {file = "cachetools-4.2.1.tar.gz", hash = "sha256:f469e29e7aa4cff64d8de4aad95ce76de8ea1125a16c68e0d93f65c3c3dc92e9"}, +] +certifi = [ + {file = "certifi-2020.12.5-py2.py3-none-any.whl", hash = "sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830"}, + {file = "certifi-2020.12.5.tar.gz", hash = "sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c"}, +] +chardet = [ + {file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"}, + {file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"}, +] +click = [ + {file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"}, + {file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"}, +] +cloudpickle = [ + {file = "cloudpickle-1.6.0-py3-none-any.whl", hash = "sha256:3a32d0eb0bc6f4d0c57fbc4f3e3780f7a81e6fee0fa935072884d58ae8e1cc7c"}, + {file = "cloudpickle-1.6.0.tar.gz", hash = "sha256:9bc994f9e9447593bd0a45371f0e7ac7333710fcf64a4eb9834bf149f4ef2f32"}, +] +cmdstanpy = [ + {file = "cmdstanpy-0.4.0-py3-none-any.whl", hash = "sha256:3ac2ec8f6ce331ca5b2db5a8ac5f0f34a83571dbb9a2a7d9b9cf7b04ad696cd5"}, + {file = "cmdstanpy-0.4.0.tar.gz", hash = "sha256:5604d20136785b05883eda20a2e8c1a1f47600b148abf68deb12dda6ccd8951f"}, +] +convertdate = [ + {file = "convertdate-2.3.1-py3-none-any.whl", hash = "sha256:ede4b0bfbef002de8e31b9d8c03dc619a210915ce453e7a4826ac8808110fcff"}, + {file = "convertdate-2.3.1.tar.gz", hash = "sha256:4eabe5cab9f7890c6bddab2133502de9d116ad81f2fcf16c4858fef2b737e328"}, +] +cssselect = [ + {file = "cssselect-1.1.0-py2.py3-none-any.whl", hash = "sha256:f612ee47b749c877ebae5bb77035d8f4202c6ad0f0fc1271b3c18ad6c4468ecf"}, + {file = "cssselect-1.1.0.tar.gz", hash = "sha256:f95f8dedd925fd8f54edb3d2dfb44c190d9d18512377d3c1e2388d16126879bc"}, +] +cycler = [ + {file = "cycler-0.10.0-py2.py3-none-any.whl", hash = "sha256:1d8a5ae1ff6c5cf9b93e8811e581232ad8920aeec647c37316ceac982b08cb2d"}, + {file = "cycler-0.10.0.tar.gz", hash = "sha256:cd7b2d1018258d7247a71425e9f26463dfb444d411c39569972f4ce586b0c9d8"}, +] +cython = [ + {file = "Cython-0.29.17-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:8ef49cafea89d99ffc2cf37af2f0f2b7d219080574f14a422f701bcaa85c7167"}, + {file = "Cython-0.29.17-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:4f35752adfd4855d39e38bf08eb6d02f7aa88b1bb420ab86e6d2e37ccd7c88c2"}, + {file = "Cython-0.29.17-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:00faa77500ca2f865fd7f3126f86e77de3ec0d855dd6cf92fc85b57ebed11655"}, + {file = "Cython-0.29.17-cp27-cp27m-win32.whl", hash = "sha256:fce2e7f500b1456f96d5b8ceefba243cae7018ad8b3f791e62c20a0f0fbba71c"}, + {file = "Cython-0.29.17-cp27-cp27m-win_amd64.whl", hash = "sha256:b19a1aa98192d44d7254613a1f9c382ef381deb79289f2ff446d1447d19085aa"}, + {file = "Cython-0.29.17-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:785d6e88a3bb10ce6425d23f0a740a21b0bfc9e8d371fea7edba0eaa0ec57d96"}, + {file = "Cython-0.29.17-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ea75bbc076d4a5605d04c72c8c7a933f51473b0bcecd79295256b9ecd75cca49"}, + {file = "Cython-0.29.17-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:5c501742a92cbcef8f3c21d1dcba9c073b37f1218af3586957901730ac6b6665"}, + {file = "Cython-0.29.17-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:179ad5569dc101e3e0d9d04305f9a5e03fbf8acf9d93fb543340f8c1a8fb054b"}, + {file = "Cython-0.29.17-cp34-cp34m-win32.whl", hash = "sha256:c78fd0bdf5915f4df730298e6cc7197e4c6aa5285d7c37491366a38125b3e0ab"}, + {file = "Cython-0.29.17-cp34-cp34m-win_amd64.whl", hash = "sha256:4e8d351ee840a4e491f8f0a64da19923ada0ce09d2d818bce0ae6ce1b6837aeb"}, + {file = "Cython-0.29.17-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:c56f658ab6f387619a3668cd78cf2d3459324d9ea3cb39cce4d72ef5bce8f318"}, + {file = "Cython-0.29.17-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:a5ebd8fe5a3d97924bd89d449914d1c5b6d084f4b124a4eb28e4412d09fb0f20"}, + {file = "Cython-0.29.17-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:7cec6bd82fd92f85790908fdc7a43a8a5442606e6d771d5b32a1ab8a39ad1a65"}, + {file = "Cython-0.29.17-cp35-cp35m-win32.whl", hash = "sha256:96d18413a33aa5ce51a5554615ba01e3fdb26126d8678459330d052f0bdf60ec"}, + {file = "Cython-0.29.17-cp35-cp35m-win_amd64.whl", hash = "sha256:86ae455b1dd7041b4b8a15499fe72f3d3f990f78a794deb799ee2ef7db389ca0"}, + {file = "Cython-0.29.17-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b6f7d2cf2f6b246fd04696d6d346489628f94f72a4988682ea0591b632370a1f"}, + {file = "Cython-0.29.17-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:7d597733ad0e7fc545df39100ee3b24290ce35586466dee4fa6018d4b8815d72"}, + {file = "Cython-0.29.17-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:3950ae725472ae47bfb41c6bfdb3869a8ac27b5f30405f599a51398512afa224"}, + {file = "Cython-0.29.17-cp36-cp36m-win32.whl", hash = "sha256:809896928abce18e7c91a28b2705473ca4f15b9a53f433495845a882e15c09d8"}, + {file = "Cython-0.29.17-cp36-cp36m-win_amd64.whl", hash = "sha256:14e218a93d4f2e43e0063a5a0f7f26fe1783d5d20700216c5c4ff092c4553488"}, + {file = "Cython-0.29.17-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:f7b20838f2534ad0d231c4c6e09acbdd40fb995a9671bb05839f7879093ec5e3"}, + {file = "Cython-0.29.17-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:719eddf050a1c8b0abbd74b0c388523cf618c3d9fe3bf20a350f4eafa43776e6"}, + {file = "Cython-0.29.17-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:2a98c9f852b266f0b9a147da4b6699cf6da24b817375f74d51986312373689ab"}, + {file = "Cython-0.29.17-cp37-cp37m-win32.whl", hash = "sha256:4dbb58f963f6283b31b4ddac44e4f684527b06923efdec72ecb54e70ee91c766"}, + {file = "Cython-0.29.17-cp37-cp37m-win_amd64.whl", hash = "sha256:788192badd3b1ebb1a72a5c6cc2a07b692ca4c1c1fe4431fdd3c0e439e2c0a6d"}, + {file = "Cython-0.29.17-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e146b4b4ed4937a40e9e5c27b264adfce4ae4b7640d46eeffd3eef123b0170a2"}, + {file = "Cython-0.29.17-cp38-cp38-manylinux1_i686.whl", hash = "sha256:dcfee6312cf8f4f4839bae22f323a0e885c4237e2187202ab12def8a5460ca4c"}, + {file = "Cython-0.29.17-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:c68f3015cbb0f5bc402829bad0a6b907889413f2e28cc0873dc1443de0f1a808"}, + {file = "Cython-0.29.17-cp38-cp38-win32.whl", hash = "sha256:7c8ac5bc9726ccb1a1cce1af4ceb7589228db6c57ada3bfcd461075abe3a6a7b"}, + {file = "Cython-0.29.17-cp38-cp38-win_amd64.whl", hash = "sha256:8135cc7de72805833a118e7c8a255daddd35875d17ea21f6c356200b0fa4b732"}, + {file = "Cython-0.29.17-py2.py3-none-any.whl", hash = "sha256:20cdf3f918c46355128d7c7cb041872ba2863cc11313972c6e390bd3dad968ba"}, + {file = "Cython-0.29.17.tar.gz", hash = "sha256:6361588cb1d82875bcfbad83d7dd66c442099759f895cf547995f00601f9caf2"}, +] +dataclasses = [ + {file = "dataclasses-0.8-py3-none-any.whl", hash = "sha256:0201d89fa866f68c8ebd9d08ee6ff50c0b255f8ec63a71c16fda7af82bb887bf"}, + {file = "dataclasses-0.8.tar.gz", hash = "sha256:8479067f342acf957dc82ec415d355ab5edb7e7646b90dc6e2fd1d96ad084c97"}, +] +decorator = [ + {file = "decorator-4.4.2-py2.py3-none-any.whl", hash = "sha256:41fa54c2a0cc4ba648be4fd43cff00aedf5b9465c9bf18d64325bc225f08f760"}, + {file = "decorator-4.4.2.tar.gz", hash = "sha256:e3a62f0520172440ca0dcc823749319382e377f37f140a0b99ef45fecb84bfe7"}, +] +deprecated = [ + {file = "Deprecated-1.2.11-py2.py3-none-any.whl", hash = "sha256:924b6921f822b64ec54f49be6700a126bab0640cfafca78f22c9d429ed590560"}, + {file = "Deprecated-1.2.11.tar.gz", hash = "sha256:471ec32b2755172046e28102cd46c481f21c6036a0ec027521eba8521aa4ef35"}, +] +ephem = [ + {file = "ephem-3.7.7.1-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:0a6d6ed003383f702695094399728052981c567d423b25aa7163b3fd40de3d5a"}, + {file = "ephem-3.7.7.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:e73b9997d7b844fabff988d7f66c3bad4e76ec8975ec9c60ec988037bb5c04b1"}, + {file = "ephem-3.7.7.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:7619297a1103f6b3dac0c609bfa7c31e17678fb1a02653347ec030487e412031"}, + {file = "ephem-3.7.7.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:37fd1abbebb821381d2865064a6fa9484ffdcd2161cf92193da8d42da79aa7db"}, + {file = "ephem-3.7.7.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:ff4e1584cc232d8bc4aea405346eeb8a24b0fbe84c6331d4edb5d4456d19f1c3"}, + {file = "ephem-3.7.7.1-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:c6081a9791e9de6511cddbeb9529bd5550fdb6f9e2a8dc9c2ec85911d67c6d11"}, + {file = "ephem-3.7.7.1-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:7f781d73e49caf7989c503a948471f1c8c1f738a450d557413999fb732f4dba3"}, + {file = "ephem-3.7.7.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:f0959882bf73c8fe1cb801f42b0989e0ecb9d84b99eb8b8f70d61d16767a1e8a"}, + {file = "ephem-3.7.7.1-cp35-cp35m-win32.whl", hash = "sha256:2bcd953cced045e4232bcb71d60f6ba237f7944c880e83e74cc959449b192dee"}, + {file = "ephem-3.7.7.1-cp35-cp35m-win_amd64.whl", hash = "sha256:fd0b922387df1ad8721f2fafd5dca51ce7105238f968e1532a177b781b8cae0e"}, + {file = "ephem-3.7.7.1-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:e10c2c8afbb9e927d46d9bf3562441da2173ff196790a75ad0e5c5ee920d5922"}, + {file = "ephem-3.7.7.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:8d586d970c42d62b1fc757a1c7c10679416a43e9e4a77391a05907159ce346f8"}, + {file = "ephem-3.7.7.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:1a8ea6a045ff669011f8ecdeffadfc5eaa519fb56ab8dd40508910e9db5ec7b0"}, + {file = "ephem-3.7.7.1-cp36-cp36m-win32.whl", hash = "sha256:72fdb72c813fc9780726aa732eb2193bbe1663549265ca5a746899215ecfbffd"}, + {file = "ephem-3.7.7.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f5af029f8814aa8617e73b2ddcad2bd1c682ca13c31ee3b6f5825dd5cb43e777"}, + {file = "ephem-3.7.7.1-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:e61c68f1c7d304a130bb6b88c1fca6600bbc1a1df6ca9a109b6eba4c6cbd3376"}, + {file = "ephem-3.7.7.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:31e2a17ca6f8d6bd44832574fea5461938ba034e52bf551e15e1a4c8f8c6c4fb"}, + {file = "ephem-3.7.7.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:1ff5abefa230d5ab40846f1cb27d4f5583d46044fecf10e17bfb559bdc766a47"}, + {file = "ephem-3.7.7.1-cp37-cp37m-win32.whl", hash = "sha256:71ea3935c658ee184575fd4cc2aa3e7fd6d6bac4a1ccff9ee5549cee67ff0385"}, + {file = "ephem-3.7.7.1-cp37-cp37m-win_amd64.whl", hash = "sha256:34fd228105b89fefd20608420861a75a184db1edeaf0056cf2f85d2a2f768aee"}, + {file = "ephem-3.7.7.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:189fcaeacb44dc5a1684ad489542f126d99d4a85e87d2fe73864c902f0bc2c71"}, + {file = "ephem-3.7.7.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:a5ddf46ced515e4b81dfd22e6408fd06a329c31c6abb10af48d392641c490b0e"}, + {file = "ephem-3.7.7.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:3530bee3eb7458d86d4c399f51f5b73ad7ea0441f0b2fb03de41d623789935af"}, + {file = "ephem-3.7.7.1-cp38-cp38-win32.whl", hash = "sha256:33ad1a71b204aff123250b04e0ff2d5c3b8e9c6c814bf2c675d7752ce5896c02"}, + {file = "ephem-3.7.7.1-cp38-cp38-win_amd64.whl", hash = "sha256:4bc5140cc7218a53ee6d949110f6ed413b8e3165294100515cd0fb29aa8e3637"}, + {file = "ephem-3.7.7.1.tar.gz", hash = "sha256:36b51a8dc7cfdeb456dd6b8ab811accab8341b2d562ee3c6f4c86f6d3dbb984e"}, +] +fbprophet = [ + {file = "fbprophet-0.6.tar.gz", hash = "sha256:de7eaa16500e4dba69a0706906775cbe96668a6fe48354ee2fff820d9e6a899b"}, +] +filelock = [ + {file = "filelock-3.0.12-py3-none-any.whl", hash = "sha256:929b7d63ec5b7d6b71b0fa5ac14e030b3f70b75747cef1b10da9b879fef15836"}, + {file = "filelock-3.0.12.tar.gz", hash = "sha256:18d82244ee114f543149c66a6e0c14e9c4f8a1044b5cdaadd0f82159d6a6ff59"}, +] +finviz = [ + {file = "finviz-1.3.4.tar.gz", hash = "sha256:3e850019c1b239dbaa6a75e982b513805182c205f6e957db48425a5f41fbd788"}, +] +flair = [ + {file = "flair-0.7-py3-none-any.whl", hash = "sha256:42c7e8074f67eeac722d68f4d5a9ad602377a76f5c4a2a190b916645b9be6ff2"}, + {file = "flair-0.7.tar.gz", hash = "sha256:50cfe5382b41ba88d9cd7096fb82d21d7f938b167fc7de2c8365bf53f3576ef4"}, +] +flatbuffers = [ + {file = "flatbuffers-1.12-py2.py3-none-any.whl", hash = "sha256:9e9ef47fa92625c4721036e7c4124182668dc6021d9e7c73704edd395648deb9"}, + {file = "flatbuffers-1.12.tar.gz", hash = "sha256:63bb9a722d5e373701913e226135b28a6f6ac200d5cc7b4d919fa38d73b44610"}, +] +ftfy = [ + {file = "ftfy-5.9.tar.gz", hash = "sha256:8c4fb2863c0b82eae2ab3cf353d9ade268dfbde863d322f78d6a9fd5cefb31e9"}, +] +fundamentalanalysis = [ + {file = "FundamentalAnalysis-0.2.6.tar.gz", hash = "sha256:0033d51784ae6c75a7347942ec3114bfb9d5db494e5fbd67eb693c6ed6fee4fa"}, +] +future = [ + {file = "future-0.18.2.tar.gz", hash = "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"}, +] +gast = [ + {file = "gast-0.3.3-py2.py3-none-any.whl", hash = "sha256:8f46f5be57ae6889a4e16e2ca113b1703ef17f2b0abceb83793eaba9e1351a45"}, + {file = "gast-0.3.3.tar.gz", hash = "sha256:b881ef288a49aa81440d2c5eb8aeefd4c2bb8993d5f50edae7413a85bfdb3b57"}, +] +gdown = [ + {file = "gdown-3.12.2.tar.gz", hash = "sha256:4b3a1301e57bfd8dce939bf25ef8fbb4b23967fd0f878eede328bdcc41386bac"}, +] +gensim = [ + {file = "gensim-3.8.2-cp35-cp35m-macosx_10_7_intel.whl", hash = "sha256:ae3b493154073d059242fd4929cec050db77995b34621d3c9c7a622689cae341"}, + {file = "gensim-3.8.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:9d4407d0d866afa97c8a2c9d04ad0a6b996fe02f1f96144c0f929608bcdbff78"}, + {file = "gensim-3.8.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:27806c022289a76dbce29cd0e00090abb4a0ae117ff714ca0b963bd13de52d5b"}, + {file = "gensim-3.8.2-cp35-cp35m-win32.whl", hash = "sha256:3d1c1a94688c4b6107a261b0af0f43f13edef7263716348ffff790d207f4a629"}, + {file = "gensim-3.8.2-cp35-cp35m-win_amd64.whl", hash = "sha256:446476a017105a549a0eafba6e8ebb50d973775f1cf7fc1d23ba04e2c5056be4"}, + {file = "gensim-3.8.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:1da1daed1d405c38541f4830981385fc4ae9ccb05cf01d4f49e184c4c0ccfe85"}, + {file = "gensim-3.8.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:806ea08d463931f4e44b2380bedf16325562bb047615de0e4bb95216074315d9"}, + {file = "gensim-3.8.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:c32506dd2d112ef33721e862009f0d7aa1d83a9d8f006faedc532a4fa4c201fa"}, + {file = "gensim-3.8.2-cp36-cp36m-win32.whl", hash = "sha256:5be9320d09babf386909be1c799ebcef5fc3b8d1ba595635768e83bd753cbb52"}, + {file = "gensim-3.8.2-cp36-cp36m-win_amd64.whl", hash = "sha256:0254577e162ae7fc99b7d47cdad121e2b120cb06fb4fdf88c2c7c67b0ac2af89"}, + {file = "gensim-3.8.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b0d0c4750adeb169744e5e6b60eb3425bc47b2e19ca77ae2aeae26ca03d6c6c8"}, + {file = "gensim-3.8.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:77bfbc0a424611f50d87e38ee92c514870f4a9eb2eb92efd9478d66f14a3dacc"}, + {file = "gensim-3.8.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:7ddac73e8ad42f4522fb12a3b3c85192e28c67bb54dbc36ba7d53be8a7f8fed5"}, + {file = "gensim-3.8.2-cp37-cp37m-win32.whl", hash = "sha256:c8ae97aac860c57ffa444425a76566e1cf1d120daa2b3af6a748c2fe9edf48a5"}, + {file = "gensim-3.8.2-cp37-cp37m-win_amd64.whl", hash = "sha256:5a7227c03a9ab48d80e306104a295f518e4049f21e29a51f41702bda247d5478"}, + {file = "gensim-3.8.2.tar.gz", hash = "sha256:46e3065e82e11d2c50c682aa17729292734a8388cb7301f0e3204052d2df2ff5"}, + {file = "gensim-3.8.2.win-amd64-py3.5.exe", hash = "sha256:48c6653dcc1a168209108d7658cae3b9b8aa05b212252bb5a696d6ba9b1da09c"}, + {file = "gensim-3.8.2.win-amd64-py3.6.exe", hash = "sha256:db22e1f6bfd093dc8c143e75ce4eb21a5c96568822d2447d952ae65c5be8240b"}, + {file = "gensim-3.8.2.win-amd64-py3.7.exe", hash = "sha256:5a114d3c1339255496c0be7b20fa0b5740fb2ccde0b56f4631e48fefe4be7c06"}, + {file = "gensim-3.8.2.win32-py3.5.exe", hash = "sha256:8a96813bab1043544c8d20806663c649195dcf13270ed6f336748ceb4ab90bd6"}, + {file = "gensim-3.8.2.win32-py3.6.exe", hash = "sha256:a9f0a27126126e466db0faccfe506559d50d0346c12d4b4d8d796d60bb8776a8"}, + {file = "gensim-3.8.2.win32-py3.7.exe", hash = "sha256:3234cbd52c0a4d548f385393040277fab03593358fee5673533e7ee6ed2f406c"}, +] +google-auth = [ + {file = "google-auth-1.27.0.tar.gz", hash = "sha256:da5218cbf33b8461d7661d6b4ad91c12c0107e2767904d5e3ae6408031d5463e"}, + {file = "google_auth-1.27.0-py2.py3-none-any.whl", hash = "sha256:d3640ea61ee025d5af00e3ffd82ba0a06dd99724adaf50bdd52f49daf29f3f65"}, +] +google-auth-oauthlib = [ + {file = "google-auth-oauthlib-0.4.2.tar.gz", hash = "sha256:65b65bc39ad8cab15039b35e5898455d3d66296d0584d96fe0e79d67d04c51d9"}, + {file = "google_auth_oauthlib-0.4.2-py2.py3-none-any.whl", hash = "sha256:d4d98c831ea21d574699978827490a41b94f05d565c617fe1b420e88f1fc8d8d"}, +] +google-pasta = [ + {file = "google-pasta-0.2.0.tar.gz", hash = "sha256:c9f2c8dfc8f96d0d5808299920721be30c9eec37f2389f28904f454565c8a16e"}, + {file = "google_pasta-0.2.0-py2-none-any.whl", hash = "sha256:4612951da876b1a10fe3960d7226f0c7682cf901e16ac06e473b267a5afa8954"}, + {file = "google_pasta-0.2.0-py3-none-any.whl", hash = "sha256:b32482794a366b5366a32c92a9a9201b107821889935a02b3e51f6b432ea84ed"}, +] +grpcio = [ + {file = "grpcio-1.32.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3afb058b6929eba07dba9ae6c5b555aa1d88cb140187d78cc510bd72d0329f28"}, + {file = "grpcio-1.32.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:a8004b34f600a8a51785e46859cd88f3386ef67cccd1cfc7598e3d317608c643"}, + {file = "grpcio-1.32.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:e6786f6f7be0937614577edcab886ddce91b7c1ea972a07ef9972e9f9ecbbb78"}, + {file = "grpcio-1.32.0-cp27-cp27m-win32.whl", hash = "sha256:e467af6bb8f5843f5a441e124b43474715cfb3981264e7cd227343e826dcc3ce"}, + {file = "grpcio-1.32.0-cp27-cp27m-win_amd64.whl", hash = "sha256:1376a60f9bfce781b39973f100b5f67e657b5be479f2fd8a7d2a408fc61c085c"}, + {file = "grpcio-1.32.0-cp27-cp27mu-linux_armv7l.whl", hash = "sha256:ce617e1c4a39131f8527964ac9e700eb199484937d7a0b3e52655a3ba50d5fb9"}, + {file = "grpcio-1.32.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:99bac0e2c820bf446662365df65841f0c2a55b0e2c419db86eaf5d162ddae73e"}, + {file = "grpcio-1.32.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:6d869a3e8e62562b48214de95e9231c97c53caa7172802236cd5d60140d7cddd"}, + {file = "grpcio-1.32.0-cp35-cp35m-linux_armv7l.whl", hash = "sha256:182c64ade34c341398bf71ec0975613970feb175090760ab4f51d1e9a5424f05"}, + {file = "grpcio-1.32.0-cp35-cp35m-macosx_10_7_intel.whl", hash = "sha256:9c0d8f2346c842088b8cbe3e14985b36e5191a34bf79279ba321a4bf69bd88b7"}, + {file = "grpcio-1.32.0-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:4775bc35af9cd3b5033700388deac2e1d611fa45f4a8dcb93667d94cb25f0444"}, + {file = "grpcio-1.32.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:be98e3198ec765d0a1e27f69d760f69374ded8a33b953dcfe790127731f7e690"}, + {file = "grpcio-1.32.0-cp35-cp35m-manylinux2014_i686.whl", hash = "sha256:378fe80ec5d9353548eb2a8a43ea03747a80f2e387c4f177f2b3ff6c7d898753"}, + {file = "grpcio-1.32.0-cp35-cp35m-manylinux2014_x86_64.whl", hash = "sha256:f7d508691301027033215d3662dab7e178f54d5cca2329f26a71ae175d94b83f"}, + {file = "grpcio-1.32.0-cp35-cp35m-win32.whl", hash = "sha256:25959a651420dd4a6fd7d3e8dee53f4f5fd8c56336a64963428e78b276389a59"}, + {file = "grpcio-1.32.0-cp35-cp35m-win_amd64.whl", hash = "sha256:ac7028d363d2395f3d755166d0161556a3f99500a5b44890421ccfaaf2aaeb08"}, + {file = "grpcio-1.32.0-cp36-cp36m-linux_armv7l.whl", hash = "sha256:c31e8a219650ddae1cd02f5a169e1bffe66a429a8255d3ab29e9363c73003b62"}, + {file = "grpcio-1.32.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e28e4c0d4231beda5dee94808e3a224d85cbaba3cfad05f2192e6f4ec5318053"}, + {file = "grpcio-1.32.0-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f03dfefa9075dd1c6c5cc27b1285c521434643b09338d8b29e1d6a27b386aa82"}, + {file = "grpcio-1.32.0-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:c4966d746dccb639ef93f13560acbe9630681c07f2b320b7ec03fe2c8f0a1f15"}, + {file = "grpcio-1.32.0-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:ec10d5f680b8e95a06f1367d73c5ddcc0ed04a3f38d6e4c9346988fb0cea2ffa"}, + {file = "grpcio-1.32.0-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:28677f057e2ef11501860a7bc15de12091d40b95dd0fddab3c37ff1542e6b216"}, + {file = "grpcio-1.32.0-cp36-cp36m-win32.whl", hash = "sha256:0f3f09269ffd3fded430cd89ba2397eabbf7e47be93983b25c187cdfebb302a7"}, + {file = "grpcio-1.32.0-cp36-cp36m-win_amd64.whl", hash = "sha256:4396b1d0f388ae875eaf6dc05cdcb612c950fd9355bc34d38b90aaa0665a0d4b"}, + {file = "grpcio-1.32.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:1ada89326a364a299527c7962e5c362dbae58c67b283fe8383c4d952b26565d5"}, + {file = "grpcio-1.32.0-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:1d384a61f96a1fc6d5d3e0b62b0a859abc8d4c3f6d16daba51ebf253a3e7df5d"}, + {file = "grpcio-1.32.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:e811ce5c387256609d56559d944a974cc6934a8eea8c76e7c86ec388dc06192d"}, + {file = "grpcio-1.32.0-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:07b430fa68e5eecd78e2ad529ab80f6a234b55fc1b675fe47335ccbf64c6c6c8"}, + {file = "grpcio-1.32.0-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:0e3edd8cdb71809d2455b9dbff66b4dd3d36c321e64bfa047da5afdfb0db332b"}, + {file = "grpcio-1.32.0-cp37-cp37m-win32.whl", hash = "sha256:6f7947dad606c509d067e5b91a92b250aa0530162ab99e4737090f6b17eb12c4"}, + {file = "grpcio-1.32.0-cp37-cp37m-win_amd64.whl", hash = "sha256:7cda998b7b551503beefc38db9be18c878cfb1596e1418647687575cdefa9273"}, + {file = "grpcio-1.32.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c58825a3d8634cd634d8f869afddd4d5742bdb59d594aea4cea17b8f39269a55"}, + {file = "grpcio-1.32.0-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:ef9bd7fdfc0a063b4ed0efcab7906df5cae9bbcf79d05c583daa2eba56752b00"}, + {file = "grpcio-1.32.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:1ce6f5ff4f4a548c502d5237a071fa617115df58ea4b7bd41dac77c1ab126e9c"}, + {file = "grpcio-1.32.0-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:f12900be4c3fd2145ba94ab0d80b7c3d71c9e6414cfee2f31b1c20188b5c281f"}, + {file = "grpcio-1.32.0-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:f53f2dfc8ff9a58a993e414a016c8b21af333955ae83960454ad91798d467c7b"}, + {file = "grpcio-1.32.0-cp38-cp38-win32.whl", hash = "sha256:5bddf9d53c8df70061916c3bfd2f468ccf26c348bb0fb6211531d895ed5e4c72"}, + {file = "grpcio-1.32.0-cp38-cp38-win_amd64.whl", hash = "sha256:14c0f017bfebbc18139551111ac58ecbde11f4bc375b73a53af38927d60308b6"}, + {file = "grpcio-1.32.0.tar.gz", hash = "sha256:01d3046fe980be25796d368f8fc5ff34b7cf5e1444f3789a017a7fe794465639"}, +] +h5py = [ + {file = "h5py-2.10.0-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:ecf4d0b56ee394a0984de15bceeb97cbe1fe485f1ac205121293fc44dcf3f31f"}, + {file = "h5py-2.10.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:86868dc07b9cc8cb7627372a2e6636cdc7a53b7e2854ad020c9e9d8a4d3fd0f5"}, + {file = "h5py-2.10.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:aac4b57097ac29089f179bbc2a6e14102dd210618e94d77ee4831c65f82f17c0"}, + {file = "h5py-2.10.0-cp27-cp27m-win32.whl", hash = "sha256:7be5754a159236e95bd196419485343e2b5875e806fe68919e087b6351f40a70"}, + {file = "h5py-2.10.0-cp27-cp27m-win_amd64.whl", hash = "sha256:13c87efa24768a5e24e360a40e0bc4c49bcb7ce1bb13a3a7f9902cec302ccd36"}, + {file = "h5py-2.10.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:79b23f47c6524d61f899254f5cd5e486e19868f1823298bc0c29d345c2447172"}, + {file = "h5py-2.10.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:cbf28ae4b5af0f05aa6e7551cee304f1d317dbed1eb7ac1d827cee2f1ef97a99"}, + {file = "h5py-2.10.0-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:c0d4b04bbf96c47b6d360cd06939e72def512b20a18a8547fa4af810258355d5"}, + {file = "h5py-2.10.0-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:549ad124df27c056b2e255ea1c44d30fb7a17d17676d03096ad5cd85edb32dc1"}, + {file = "h5py-2.10.0-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:a5f82cd4938ff8761d9760af3274acf55afc3c91c649c50ab18fcff5510a14a5"}, + {file = "h5py-2.10.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:3dad1730b6470fad853ef56d755d06bb916ee68a3d8272b3bab0c1ddf83bb99e"}, + {file = "h5py-2.10.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:063947eaed5f271679ed4ffa36bb96f57bc14f44dd4336a827d9a02702e6ce6b"}, + {file = "h5py-2.10.0-cp35-cp35m-win32.whl", hash = "sha256:c54a2c0dd4957776ace7f95879d81582298c5daf89e77fb8bee7378f132951de"}, + {file = "h5py-2.10.0-cp35-cp35m-win_amd64.whl", hash = "sha256:6998be619c695910cb0effe5eb15d3a511d3d1a5d217d4bd0bebad1151ec2262"}, + {file = "h5py-2.10.0-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:ff7d241f866b718e4584fa95f520cb19405220c501bd3a53ee11871ba5166ea2"}, + {file = "h5py-2.10.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:54817b696e87eb9e403e42643305f142cd8b940fe9b3b490bbf98c3b8a894cf4"}, + {file = "h5py-2.10.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:d3c59549f90a891691991c17f8e58c8544060fdf3ccdea267100fa5f561ff62f"}, + {file = "h5py-2.10.0-cp36-cp36m-win32.whl", hash = "sha256:d7ae7a0576b06cb8e8a1c265a8bc4b73d05fdee6429bffc9a26a6eb531e79d72"}, + {file = "h5py-2.10.0-cp36-cp36m-win_amd64.whl", hash = "sha256:bffbc48331b4a801d2f4b7dac8a72609f0b10e6e516e5c480a3e3241e091c878"}, + {file = "h5py-2.10.0-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:51ae56894c6c93159086ffa2c94b5b3388c0400548ab26555c143e7cfa05b8e5"}, + {file = "h5py-2.10.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:16ead3c57141101e3296ebeed79c9c143c32bdd0e82a61a2fc67e8e6d493e9d1"}, + {file = "h5py-2.10.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:f0e25bb91e7a02efccb50aba6591d3fe2c725479e34769802fcdd4076abfa917"}, + {file = "h5py-2.10.0-cp37-cp37m-win32.whl", hash = "sha256:f23951a53d18398ef1344c186fb04b26163ca6ce449ebd23404b153fd111ded9"}, + {file = "h5py-2.10.0-cp37-cp37m-win_amd64.whl", hash = "sha256:8bb1d2de101f39743f91512a9750fb6c351c032e5cd3204b4487383e34da7f75"}, + {file = "h5py-2.10.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:64f74da4a1dd0d2042e7d04cf8294e04ddad686f8eba9bb79e517ae582f6668d"}, + {file = "h5py-2.10.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:d35f7a3a6cefec82bfdad2785e78359a0e6a5fbb3f605dd5623ce88082ccd681"}, + {file = "h5py-2.10.0-cp38-cp38-win32.whl", hash = "sha256:6ef7ab1089e3ef53ca099038f3c0a94d03e3560e6aff0e9d6c64c55fb13fc681"}, + {file = "h5py-2.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:769e141512b54dee14ec76ed354fcacfc7d97fea5a7646b709f7400cf1838630"}, + {file = "h5py-2.10.0.tar.gz", hash = "sha256:84412798925dc870ffd7107f045d7659e60f5d46d1c70c700375248bf6bf512d"}, +] +hijri-converter = [ + {file = "hijri-converter-2.1.1.tar.gz", hash = "sha256:969e9b1e844c854b752243f697b14884c5d9112195889d3d8aa07d61af37fb21"}, + {file = "hijri_converter-2.1.1-py3-none-any.whl", hash = "sha256:7e121c2bda9d2ff022cd5aa9bf66c34efc4032f3f777b485b17541fe4c09b26d"}, +] +holidays = [ + {file = "holidays-0.10.5.2-py3.7.egg", hash = "sha256:c704931e2e133ff1d591595d5f84cf6c9fd0e1230ea65e270e845769b27a5058"}, + {file = "holidays-0.10.5.2-py3.8.egg", hash = "sha256:ae132b50000461744403c1f1acfebe2805d4500e6dcc56abd1ab8fb541b305e4"}, + {file = "holidays-0.10.5.2-py3.9.egg", hash = "sha256:8656d10bcb7991c685714b743fc63516e96f82feea8c6af8d39c43c1f1c4e870"}, + {file = "holidays-0.10.5.2.tar.gz", hash = "sha256:ed17186d785928723efecebe4ab2d03358abe8ef3f7fa939a39d3392d6c2903c"}, +] +hyperopt = [ + {file = "hyperopt-0.2.5-py2.py3-none-any.whl", hash = "sha256:dc5c7cceaf33c125b727cf92709e70035d94dd507831dae66406ac762a18a253"}, + {file = "hyperopt-0.2.5.tar.gz", hash = "sha256:bc6047d50f956ae64eebcb34b1fd40f186a93e214957f20e87af2f10195295cc"}, +] +idna = [ + {file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"}, + {file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"}, +] +idna-ssl = [ + {file = "idna-ssl-1.1.0.tar.gz", hash = "sha256:a933e3bb13da54383f9e8f35dc4f9cb9eb9b3b78c6b36f311254d6d0d92c6c7c"}, +] +importlib-metadata = [ + {file = "importlib_metadata-3.7.0-py3-none-any.whl", hash = "sha256:c6af5dbf1126cd959c4a8d8efd61d4d3c83bddb0459a17e554284a077574b614"}, + {file = "importlib_metadata-3.7.0.tar.gz", hash = "sha256:24499ffde1b80be08284100393955842be4a59c7c16bbf2738aad0e464a8e0aa"}, +] +inflection = [ + {file = "inflection-0.5.1-py2.py3-none-any.whl", hash = "sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2"}, + {file = "inflection-0.5.1.tar.gz", hash = "sha256:1a29730d366e996aaacffb2f1f1cb9593dc38e2ddd30c91250c6dde09ea9b417"}, +] +iso8601 = [ + {file = "iso8601-0.1.14-py2.py3-none-any.whl", hash = "sha256:e7e1122f064d626e17d47cd5106bed2c620cb38fe464999e0ddae2b6d2de6004"}, + {file = "iso8601-0.1.14.tar.gz", hash = "sha256:8aafd56fa0290496c5edbb13c311f78fa3a241f0853540da09d9363eae3ebd79"}, +] +janome = [ + {file = "Janome-0.4.1-py2.py3-none-any.whl", hash = "sha256:a650e2684e80af72f869eff17566f31dd4444f5443c4771dca1ada60cea5c251"}, + {file = "Janome-0.4.1.tar.gz", hash = "sha256:6c2c38d894014d57cb3151265c11146506ead3b3bc290898adc33711711612de"}, +] +joblib = [ + {file = "joblib-1.0.1-py3-none-any.whl", hash = "sha256:feeb1ec69c4d45129954f1b7034954241eedfd6ba39b5e9e4b6883be3332d5e5"}, + {file = "joblib-1.0.1.tar.gz", hash = "sha256:9c17567692206d2f3fb9ecf5e991084254fe631665c450b443761c4186a613f7"}, +] +keras-preprocessing = [ + {file = "Keras_Preprocessing-1.1.2-py2.py3-none-any.whl", hash = "sha256:7b82029b130ff61cc99b55f3bd27427df4838576838c5b2f65940e4fcec99a7b"}, + {file = "Keras_Preprocessing-1.1.2.tar.gz", hash = "sha256:add82567c50c8bc648c14195bf544a5ce7c1f76761536956c3d2978970179ef3"}, +] +kiwisolver = [ + {file = "kiwisolver-1.3.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:fd34fbbfbc40628200730bc1febe30631347103fc8d3d4fa012c21ab9c11eca9"}, + {file = "kiwisolver-1.3.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:d3155d828dec1d43283bd24d3d3e0d9c7c350cdfcc0bd06c0ad1209c1bbc36d0"}, + {file = "kiwisolver-1.3.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:5a7a7dbff17e66fac9142ae2ecafb719393aaee6a3768c9de2fd425c63b53e21"}, + {file = "kiwisolver-1.3.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:f8d6f8db88049a699817fd9178782867bf22283e3813064302ac59f61d95be05"}, + {file = "kiwisolver-1.3.1-cp36-cp36m-manylinux2014_ppc64le.whl", hash = "sha256:5f6ccd3dd0b9739edcf407514016108e2280769c73a85b9e59aa390046dbf08b"}, + {file = "kiwisolver-1.3.1-cp36-cp36m-win32.whl", hash = "sha256:225e2e18f271e0ed8157d7f4518ffbf99b9450fca398d561eb5c4a87d0986dd9"}, + {file = "kiwisolver-1.3.1-cp36-cp36m-win_amd64.whl", hash = "sha256:cf8b574c7b9aa060c62116d4181f3a1a4e821b2ec5cbfe3775809474113748d4"}, + {file = "kiwisolver-1.3.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:232c9e11fd7ac3a470d65cd67e4359eee155ec57e822e5220322d7b2ac84fbf0"}, + {file = "kiwisolver-1.3.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:b38694dcdac990a743aa654037ff1188c7a9801ac3ccc548d3341014bc5ca278"}, + {file = "kiwisolver-1.3.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ca3820eb7f7faf7f0aa88de0e54681bddcb46e485beb844fcecbcd1c8bd01689"}, + {file = "kiwisolver-1.3.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:c8fd0f1ae9d92b42854b2979024d7597685ce4ada367172ed7c09edf2cef9cb8"}, + {file = "kiwisolver-1.3.1-cp37-cp37m-manylinux2014_ppc64le.whl", hash = "sha256:1e1bc12fb773a7b2ffdeb8380609f4f8064777877b2225dec3da711b421fda31"}, + {file = "kiwisolver-1.3.1-cp37-cp37m-win32.whl", hash = "sha256:72c99e39d005b793fb7d3d4e660aed6b6281b502e8c1eaf8ee8346023c8e03bc"}, + {file = "kiwisolver-1.3.1-cp37-cp37m-win_amd64.whl", hash = "sha256:8be8d84b7d4f2ba4ffff3665bcd0211318aa632395a1a41553250484a871d454"}, + {file = "kiwisolver-1.3.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:31dfd2ac56edc0ff9ac295193eeaea1c0c923c0355bf948fbd99ed6018010b72"}, + {file = "kiwisolver-1.3.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:563c649cfdef27d081c84e72a03b48ea9408c16657500c312575ae9d9f7bc1c3"}, + {file = "kiwisolver-1.3.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:78751b33595f7f9511952e7e60ce858c6d64db2e062afb325985ddbd34b5c131"}, + {file = "kiwisolver-1.3.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:a357fd4f15ee49b4a98b44ec23a34a95f1e00292a139d6015c11f55774ef10de"}, + {file = "kiwisolver-1.3.1-cp38-cp38-manylinux2014_ppc64le.whl", hash = "sha256:5989db3b3b34b76c09253deeaf7fbc2707616f130e166996606c284395da3f18"}, + {file = "kiwisolver-1.3.1-cp38-cp38-win32.whl", hash = "sha256:c08e95114951dc2090c4a630c2385bef681cacf12636fb0241accdc6b303fd81"}, + {file = "kiwisolver-1.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:44a62e24d9b01ba94ae7a4a6c3fb215dc4af1dde817e7498d901e229aaf50e4e"}, + {file = "kiwisolver-1.3.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:50af681a36b2a1dee1d3c169ade9fdc59207d3c31e522519181e12f1b3ba7000"}, + {file = "kiwisolver-1.3.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:a53d27d0c2a0ebd07e395e56a1fbdf75ffedc4a05943daf472af163413ce9598"}, + {file = "kiwisolver-1.3.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:834ee27348c4aefc20b479335fd422a2c69db55f7d9ab61721ac8cd83eb78882"}, + {file = "kiwisolver-1.3.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:5c3e6455341008a054cccee8c5d24481bcfe1acdbc9add30aa95798e95c65621"}, + {file = "kiwisolver-1.3.1-cp39-cp39-manylinux2014_ppc64le.whl", hash = "sha256:acef3d59d47dd85ecf909c359d0fd2c81ed33bdff70216d3956b463e12c38a54"}, + {file = "kiwisolver-1.3.1-cp39-cp39-win32.whl", hash = "sha256:c5518d51a0735b1e6cee1fdce66359f8d2b59c3ca85dc2b0813a8aa86818a030"}, + {file = "kiwisolver-1.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:b9edd0110a77fc321ab090aaa1cfcaba1d8499850a12848b81be2222eab648f6"}, + {file = "kiwisolver-1.3.1-pp36-pypy36_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0cd53f403202159b44528498de18f9285b04482bab2a6fc3f5dd8dbb9352e30d"}, + {file = "kiwisolver-1.3.1-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:33449715e0101e4d34f64990352bce4095c8bf13bed1b390773fc0a7295967b3"}, + {file = "kiwisolver-1.3.1-pp36-pypy36_pp73-win32.whl", hash = "sha256:401a2e9afa8588589775fe34fc22d918ae839aaaf0c0e96441c0fdbce6d8ebe6"}, + {file = "kiwisolver-1.3.1.tar.gz", hash = "sha256:950a199911a8d94683a6b10321f9345d5a3a8433ec58b217ace979e18f16e248"}, +] +konoha = [ + {file = "konoha-4.6.2-py3-none-any.whl", hash = "sha256:2e7fd97680085f26fcec1992a6e2b76870d3b88ff5ad7eceda4b4fc691fe10e8"}, + {file = "konoha-4.6.2.tar.gz", hash = "sha256:c5feb806be40d66a557d70440d156accb0d55851d002ce808f6e29f3d3b93de0"}, +] +korean-lunar-calendar = [ + {file = "korean_lunar_calendar-0.2.1-py3-none-any.whl", hash = "sha256:a619ea88610129019267467b85cc9faf0fab6e1694b2e782d1aeb610cdd382d5"}, + {file = "korean_lunar_calendar-0.2.1.tar.gz", hash = "sha256:12ce54b1392ed45a82dc6cea85ee5f7e33630556e82488f57e37a22482c8275d"}, +] +langdetect = [ + {file = "langdetect-1.0.8-py2-none-any.whl", hash = "sha256:f37495e63607865e47deed08d78f7f8e58172658216ff954b2f14671bcd87740"}, + {file = "langdetect-1.0.8.tar.gz", hash = "sha256:363795ea005f1243c958e953245dac5d814fabdc025c9afa91588c5fa6b2fa83"}, +] +lunarcalendar = [ + {file = "LunarCalendar-0.0.9-py2.py3-none-any.whl", hash = "sha256:5ef25883d73898b37edb54da9e0f04215aaa68b897fd12e9d4b79756ff91c8cb"}, + {file = "LunarCalendar-0.0.9.tar.gz", hash = "sha256:681142f22fc353c3abca4b25699e3d1aa7083ad1c268dce36ba297eca04bed5a"}, +] +lxml = [ + {file = "lxml-4.6.2-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a9d6bc8642e2c67db33f1247a77c53476f3a166e09067c0474facb045756087f"}, + {file = "lxml-4.6.2-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:791394449e98243839fa822a637177dd42a95f4883ad3dec2a0ce6ac99fb0a9d"}, + {file = "lxml-4.6.2-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:68a5d77e440df94011214b7db907ec8f19e439507a70c958f750c18d88f995d2"}, + {file = "lxml-4.6.2-cp27-cp27m-win32.whl", hash = "sha256:fc37870d6716b137e80d19241d0e2cff7a7643b925dfa49b4c8ebd1295eb506e"}, + {file = "lxml-4.6.2-cp27-cp27m-win_amd64.whl", hash = "sha256:69a63f83e88138ab7642d8f61418cf3180a4d8cd13995df87725cb8b893e950e"}, + {file = "lxml-4.6.2-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:42ebca24ba2a21065fb546f3e6bd0c58c3fe9ac298f3a320147029a4850f51a2"}, + {file = "lxml-4.6.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:f83d281bb2a6217cd806f4cf0ddded436790e66f393e124dfe9731f6b3fb9afe"}, + {file = "lxml-4.6.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:535f067002b0fd1a4e5296a8f1bf88193080ff992a195e66964ef2a6cfec5388"}, + {file = "lxml-4.6.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:366cb750140f221523fa062d641393092813b81e15d0e25d9f7c6025f910ee80"}, + {file = "lxml-4.6.2-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:97db258793d193c7b62d4e2586c6ed98d51086e93f9a3af2b2034af01450a74b"}, + {file = "lxml-4.6.2-cp35-cp35m-win32.whl", hash = "sha256:648914abafe67f11be7d93c1a546068f8eff3c5fa938e1f94509e4a5d682b2d8"}, + {file = "lxml-4.6.2-cp35-cp35m-win_amd64.whl", hash = "sha256:4e751e77006da34643ab782e4a5cc21ea7b755551db202bc4d3a423b307db780"}, + {file = "lxml-4.6.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:681d75e1a38a69f1e64ab82fe4b1ed3fd758717bed735fb9aeaa124143f051af"}, + {file = "lxml-4.6.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:127f76864468d6630e1b453d3ffbbd04b024c674f55cf0a30dc2595137892d37"}, + {file = "lxml-4.6.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4fb85c447e288df535b17ebdebf0ec1cf3a3f1a8eba7e79169f4f37af43c6b98"}, + {file = "lxml-4.6.2-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:5be4a2e212bb6aa045e37f7d48e3e1e4b6fd259882ed5a00786f82e8c37ce77d"}, + {file = "lxml-4.6.2-cp36-cp36m-win32.whl", hash = "sha256:8c88b599e226994ad4db29d93bc149aa1aff3dc3a4355dd5757569ba78632bdf"}, + {file = "lxml-4.6.2-cp36-cp36m-win_amd64.whl", hash = "sha256:6e4183800f16f3679076dfa8abf2db3083919d7e30764a069fb66b2b9eff9939"}, + {file = "lxml-4.6.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d8d3d4713f0c28bdc6c806a278d998546e8efc3498949e3ace6e117462ac0a5e"}, + {file = "lxml-4.6.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:8246f30ca34dc712ab07e51dc34fea883c00b7ccb0e614651e49da2c49a30711"}, + {file = "lxml-4.6.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:923963e989ffbceaa210ac37afc9b906acebe945d2723e9679b643513837b089"}, + {file = "lxml-4.6.2-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:1471cee35eba321827d7d53d104e7b8c593ea3ad376aa2df89533ce8e1b24a01"}, + {file = "lxml-4.6.2-cp37-cp37m-win32.whl", hash = "sha256:2363c35637d2d9d6f26f60a208819e7eafc4305ce39dc1d5005eccc4593331c2"}, + {file = "lxml-4.6.2-cp37-cp37m-win_amd64.whl", hash = "sha256:f4822c0660c3754f1a41a655e37cb4dbbc9be3d35b125a37fab6f82d47674ebc"}, + {file = "lxml-4.6.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0448576c148c129594d890265b1a83b9cd76fd1f0a6a04620753d9a6bcfd0a4d"}, + {file = "lxml-4.6.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:60a20bfc3bd234d54d49c388950195d23a5583d4108e1a1d47c9eef8d8c042b3"}, + {file = "lxml-4.6.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:2e5cc908fe43fe1aa299e58046ad66981131a66aea3129aac7770c37f590a644"}, + {file = "lxml-4.6.2-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:50c348995b47b5a4e330362cf39fc503b4a43b14a91c34c83b955e1805c8e308"}, + {file = "lxml-4.6.2-cp38-cp38-win32.whl", hash = "sha256:94d55bd03d8671686e3f012577d9caa5421a07286dd351dfef64791cf7c6c505"}, + {file = "lxml-4.6.2-cp38-cp38-win_amd64.whl", hash = "sha256:7a7669ff50f41225ca5d6ee0a1ec8413f3a0d8aa2b109f86d540887b7ec0d72a"}, + {file = "lxml-4.6.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e0bfe9bb028974a481410432dbe1b182e8191d5d40382e5b8ff39cdd2e5c5931"}, + {file = "lxml-4.6.2-cp39-cp39-manylinux1_i686.whl", hash = "sha256:6fd8d5903c2e53f49e99359b063df27fdf7acb89a52b6a12494208bf61345a03"}, + {file = "lxml-4.6.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:7e9eac1e526386df7c70ef253b792a0a12dd86d833b1d329e038c7a235dfceb5"}, + {file = "lxml-4.6.2-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:7ee8af0b9f7de635c61cdd5b8534b76c52cd03536f29f51151b377f76e214a1a"}, + {file = "lxml-4.6.2-cp39-cp39-win32.whl", hash = "sha256:2e6fd1b8acd005bd71e6c94f30c055594bbd0aa02ef51a22bbfa961ab63b2d75"}, + {file = "lxml-4.6.2-cp39-cp39-win_amd64.whl", hash = "sha256:535332fe9d00c3cd455bd3dd7d4bacab86e2d564bdf7606079160fa6251caacf"}, + {file = "lxml-4.6.2.tar.gz", hash = "sha256:cd11c7e8d21af997ee8079037fff88f16fda188a9776eb4b81c7e4c9c0a7d7fc"}, +] +markdown = [ + {file = "Markdown-3.3.4-py3-none-any.whl", hash = "sha256:96c3ba1261de2f7547b46a00ea8463832c921d3f9d6aba3f255a6f71386db20c"}, + {file = "Markdown-3.3.4.tar.gz", hash = "sha256:31b5b491868dcc87d6c24b7e3d19a0d730d59d3e46f4eea6430a321bed387a49"}, +] +matplotlib = [ + {file = "matplotlib-3.3.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b2a5e1f637a92bb6f3526cc54cc8af0401112e81ce5cba6368a1b7908f9e18bc"}, + {file = "matplotlib-3.3.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:c586ac1d64432f92857c3cf4478cfb0ece1ae18b740593f8a39f2f0b27c7fda5"}, + {file = "matplotlib-3.3.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:9b03722c89a43a61d4d148acfc89ec5bb54cd0fd1539df25b10eb9c5fa6c393a"}, + {file = "matplotlib-3.3.3-cp36-cp36m-win32.whl", hash = "sha256:2c2c5041608cb75c39cbd0ed05256f8a563e144234a524c59d091abbfa7a868f"}, + {file = "matplotlib-3.3.3-cp36-cp36m-win_amd64.whl", hash = "sha256:c092fc4673260b1446b8578015321081d5db73b94533fe4bf9b69f44e948d174"}, + {file = "matplotlib-3.3.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:27c9393fada62bd0ad7c730562a0fecbd3d5aaa8d9ed80ba7d3ebb8abc4f0453"}, + {file = "matplotlib-3.3.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:b8ba2a1dbb4660cb469fe8e1febb5119506059e675180c51396e1723ff9b79d9"}, + {file = "matplotlib-3.3.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:0caa687fce6174fef9b27d45f8cc57cbc572e04e98c81db8e628b12b563d59a2"}, + {file = "matplotlib-3.3.3-cp37-cp37m-win32.whl", hash = "sha256:b7b09c61a91b742cb5460b72efd1fe26ef83c1c704f666e0af0df156b046aada"}, + {file = "matplotlib-3.3.3-cp37-cp37m-win_amd64.whl", hash = "sha256:6ffd2d80d76df2e5f9f0c0140b5af97e3b87dd29852dcdb103ec177d853ec06b"}, + {file = "matplotlib-3.3.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5111d6d47a0f5b8f3e10af7a79d5e7eb7e73a22825391834734274c4f312a8a0"}, + {file = "matplotlib-3.3.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:a4fe54eab2c7129add75154823e6543b10261f9b65b2abe692d68743a4999f8c"}, + {file = "matplotlib-3.3.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:83e6c895d93fdf93eeff1a21ee96778ba65ef258e5d284160f7c628fee40c38f"}, + {file = "matplotlib-3.3.3-cp38-cp38-win32.whl", hash = "sha256:b26c472847911f5a7eb49e1c888c31c77c4ddf8023c1545e0e8e0367ba74fb15"}, + {file = "matplotlib-3.3.3-cp38-cp38-win_amd64.whl", hash = "sha256:09225edca87a79815822eb7d3be63a83ebd4d9d98d5aa3a15a94f4eee2435954"}, + {file = "matplotlib-3.3.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:eb6b6700ea454bb88333d98601e74928e06f9669c1ea231b4c4c666c1d7701b4"}, + {file = "matplotlib-3.3.3-cp39-cp39-manylinux1_i686.whl", hash = "sha256:2d31aff0c8184b05006ad756b9a4dc2a0805e94d28f3abc3187e881b6673b302"}, + {file = "matplotlib-3.3.3-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:d082f77b4ed876ae94a9373f0db96bf8768a7cca6c58fc3038f94e30ffde1880"}, + {file = "matplotlib-3.3.3-cp39-cp39-win32.whl", hash = "sha256:e71cdd402047e657c1662073e9361106c6981e9621ab8c249388dfc3ec1de07b"}, + {file = "matplotlib-3.3.3-cp39-cp39-win_amd64.whl", hash = "sha256:756ee498b9ba35460e4cbbd73f09018e906daa8537fff61da5b5bf8d5e9de5c7"}, + {file = "matplotlib-3.3.3-pp36-pypy36_pp73-macosx_10_9_x86_64.whl", hash = "sha256:7ad44f2c74c50567c694ee91c6fa16d67e7c8af6f22c656b80469ad927688457"}, + {file = "matplotlib-3.3.3-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:3a4c3e9be63adf8e9b305aa58fb3ec40ecc61fd0f8fd3328ce55bc30e7a2aeb0"}, + {file = "matplotlib-3.3.3-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:746897fbd72bd462b888c74ed35d812ca76006b04f717cd44698cdfc99aca70d"}, + {file = "matplotlib-3.3.3-pp37-pypy37_pp73-manylinux2010_x86_64.whl", hash = "sha256:5ed3d3342698c2b1f3651f8ea6c099b0f196d16ee00e33dc3a6fee8cb01d530a"}, + {file = "matplotlib-3.3.3.tar.gz", hash = "sha256:b1b60c6476c4cfe9e5cf8ab0d3127476fd3d5f05de0f343a452badaad0e4bdec"}, +] +more-itertools = [ + {file = "more-itertools-8.7.0.tar.gz", hash = "sha256:c5d6da9ca3ff65220c3bfd2a8db06d698f05d4d2b9be57e1deb2be5a45019713"}, + {file = "more_itertools-8.7.0-py3-none-any.whl", hash = "sha256:5652a9ac72209ed7df8d9c15daf4e1aa0e3d2ccd3c87f8265a0673cd9cbc9ced"}, +] +mpld3 = [ + {file = "mpld3-0.3.tar.gz", hash = "sha256:4d455884a211bf99b37ecc760759435c7bb6a5955de47d8daf4967e301878ab7"}, +] +multidict = [ + {file = "multidict-5.1.0-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:b7993704f1a4b204e71debe6095150d43b2ee6150fa4f44d6d966ec356a8d61f"}, + {file = "multidict-5.1.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:9dd6e9b1a913d096ac95d0399bd737e00f2af1e1594a787e00f7975778c8b2bf"}, + {file = "multidict-5.1.0-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:f21756997ad8ef815d8ef3d34edd98804ab5ea337feedcd62fb52d22bf531281"}, + {file = "multidict-5.1.0-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:1ab820665e67373de5802acae069a6a05567ae234ddb129f31d290fc3d1aa56d"}, + {file = "multidict-5.1.0-cp36-cp36m-manylinux2014_ppc64le.whl", hash = "sha256:9436dc58c123f07b230383083855593550c4d301d2532045a17ccf6eca505f6d"}, + {file = "multidict-5.1.0-cp36-cp36m-manylinux2014_s390x.whl", hash = "sha256:830f57206cc96ed0ccf68304141fec9481a096c4d2e2831f311bde1c404401da"}, + {file = "multidict-5.1.0-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:2e68965192c4ea61fff1b81c14ff712fc7dc15d2bd120602e4a3494ea6584224"}, + {file = "multidict-5.1.0-cp36-cp36m-win32.whl", hash = "sha256:2f1a132f1c88724674271d636e6b7351477c27722f2ed789f719f9e3545a3d26"}, + {file = "multidict-5.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:3a4f32116f8f72ecf2a29dabfb27b23ab7cdc0ba807e8459e59a93a9be9506f6"}, + {file = "multidict-5.1.0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:46c73e09ad374a6d876c599f2328161bcd95e280f84d2060cf57991dec5cfe76"}, + {file = "multidict-5.1.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:018132dbd8688c7a69ad89c4a3f39ea2f9f33302ebe567a879da8f4ca73f0d0a"}, + {file = "multidict-5.1.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:4b186eb7d6ae7c06eb4392411189469e6a820da81447f46c0072a41c748ab73f"}, + {file = "multidict-5.1.0-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:3a041b76d13706b7fff23b9fc83117c7b8fe8d5fe9e6be45eee72b9baa75f348"}, + {file = "multidict-5.1.0-cp37-cp37m-manylinux2014_ppc64le.whl", hash = "sha256:051012ccee979b2b06be928a6150d237aec75dd6bf2d1eeeb190baf2b05abc93"}, + {file = "multidict-5.1.0-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:6a4d5ce640e37b0efcc8441caeea8f43a06addace2335bd11151bc02d2ee31f9"}, + {file = "multidict-5.1.0-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:5cf3443199b83ed9e955f511b5b241fd3ae004e3cb81c58ec10f4fe47c7dce37"}, + {file = "multidict-5.1.0-cp37-cp37m-win32.whl", hash = "sha256:f200755768dc19c6f4e2b672421e0ebb3dd54c38d5a4f262b872d8cfcc9e93b5"}, + {file = "multidict-5.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:05c20b68e512166fddba59a918773ba002fdd77800cad9f55b59790030bab632"}, + {file = "multidict-5.1.0-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:54fd1e83a184e19c598d5e70ba508196fd0bbdd676ce159feb412a4a6664f952"}, + {file = "multidict-5.1.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:0e3c84e6c67eba89c2dbcee08504ba8644ab4284863452450520dad8f1e89b79"}, + {file = "multidict-5.1.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:dc862056f76443a0db4509116c5cd480fe1b6a2d45512a653f9a855cc0517456"}, + {file = "multidict-5.1.0-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:0e929169f9c090dae0646a011c8b058e5e5fb391466016b39d21745b48817fd7"}, + {file = "multidict-5.1.0-cp38-cp38-manylinux2014_ppc64le.whl", hash = "sha256:d81eddcb12d608cc08081fa88d046c78afb1bf8107e6feab5d43503fea74a635"}, + {file = "multidict-5.1.0-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:585fd452dd7782130d112f7ddf3473ffdd521414674c33876187e101b588738a"}, + {file = "multidict-5.1.0-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:37e5438e1c78931df5d3c0c78ae049092877e5e9c02dd1ff5abb9cf27a5914ea"}, + {file = "multidict-5.1.0-cp38-cp38-win32.whl", hash = "sha256:07b42215124aedecc6083f1ce6b7e5ec5b50047afa701f3442054373a6deb656"}, + {file = "multidict-5.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:929006d3c2d923788ba153ad0de8ed2e5ed39fdbe8e7be21e2f22ed06c6783d3"}, + {file = "multidict-5.1.0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:b797515be8743b771aa868f83563f789bbd4b236659ba52243b735d80b29ed93"}, + {file = "multidict-5.1.0-cp39-cp39-manylinux1_i686.whl", hash = "sha256:d5c65bdf4484872c4af3150aeebe101ba560dcfb34488d9a8ff8dbcd21079647"}, + {file = "multidict-5.1.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:b47a43177a5e65b771b80db71e7be76c0ba23cc8aa73eeeb089ed5219cdbe27d"}, + {file = "multidict-5.1.0-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:806068d4f86cb06af37cd65821554f98240a19ce646d3cd24e1c33587f313eb8"}, + {file = "multidict-5.1.0-cp39-cp39-manylinux2014_ppc64le.whl", hash = "sha256:46dd362c2f045095c920162e9307de5ffd0a1bfbba0a6e990b344366f55a30c1"}, + {file = "multidict-5.1.0-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:ace010325c787c378afd7f7c1ac66b26313b3344628652eacd149bdd23c68841"}, + {file = "multidict-5.1.0-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:ecc771ab628ea281517e24fd2c52e8f31c41e66652d07599ad8818abaad38cda"}, + {file = "multidict-5.1.0-cp39-cp39-win32.whl", hash = "sha256:fc13a9524bc18b6fb6e0dbec3533ba0496bbed167c56d0aabefd965584557d80"}, + {file = "multidict-5.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:7df80d07818b385f3129180369079bd6934cf70469f99daaebfac89dca288359"}, + {file = "multidict-5.1.0.tar.gz", hash = "sha256:25b4e5f22d3a37ddf3effc0710ba692cfc792c2b9edfb9c05aefe823256e84d5"}, +] +multitasking = [ + {file = "multitasking-0.0.9.tar.gz", hash = "sha256:b59d99f709d2e17d60ccaa2be09771b6e9ed9391c63f083c0701e724f624d2e0"}, +] +networkx = [ + {file = "networkx-2.5-py3-none-any.whl", hash = "sha256:8c5812e9f798d37c50570d15c4a69d5710a18d77bafc903ee9c5fba7454c616c"}, + {file = "networkx-2.5.tar.gz", hash = "sha256:7978955423fbc9639c10498878be59caf99b44dc304c2286162fd24b458c1602"}, +] +numpy = [ + {file = "numpy-1.19.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:cc6bd4fd593cb261332568485e20a0712883cf631f6f5e8e86a52caa8b2b50ff"}, + {file = "numpy-1.19.5-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:aeb9ed923be74e659984e321f609b9ba54a48354bfd168d21a2b072ed1e833ea"}, + {file = "numpy-1.19.5-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:8b5e972b43c8fc27d56550b4120fe6257fdc15f9301914380b27f74856299fea"}, + {file = "numpy-1.19.5-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:43d4c81d5ffdff6bae58d66a3cd7f54a7acd9a0e7b18d97abb255defc09e3140"}, + {file = "numpy-1.19.5-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:a4646724fba402aa7504cd48b4b50e783296b5e10a524c7a6da62e4a8ac9698d"}, + {file = "numpy-1.19.5-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:2e55195bc1c6b705bfd8ad6f288b38b11b1af32f3c8289d6c50d47f950c12e76"}, + {file = "numpy-1.19.5-cp36-cp36m-win32.whl", hash = "sha256:39b70c19ec771805081578cc936bbe95336798b7edf4732ed102e7a43ec5c07a"}, + {file = "numpy-1.19.5-cp36-cp36m-win_amd64.whl", hash = "sha256:dbd18bcf4889b720ba13a27ec2f2aac1981bd41203b3a3b27ba7a33f88ae4827"}, + {file = "numpy-1.19.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:603aa0706be710eea8884af807b1b3bc9fb2e49b9f4da439e76000f3b3c6ff0f"}, + {file = "numpy-1.19.5-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:cae865b1cae1ec2663d8ea56ef6ff185bad091a5e33ebbadd98de2cfa3fa668f"}, + {file = "numpy-1.19.5-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:36674959eed6957e61f11c912f71e78857a8d0604171dfd9ce9ad5cbf41c511c"}, + {file = "numpy-1.19.5-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:06fab248a088e439402141ea04f0fffb203723148f6ee791e9c75b3e9e82f080"}, + {file = "numpy-1.19.5-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6149a185cece5ee78d1d196938b2a8f9d09f5a5ebfbba66969302a778d5ddd1d"}, + {file = "numpy-1.19.5-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:50a4a0ad0111cc1b71fa32dedd05fa239f7fb5a43a40663269bb5dc7877cfd28"}, + {file = "numpy-1.19.5-cp37-cp37m-win32.whl", hash = "sha256:d051ec1c64b85ecc69531e1137bb9751c6830772ee5c1c426dbcfe98ef5788d7"}, + {file = "numpy-1.19.5-cp37-cp37m-win_amd64.whl", hash = "sha256:a12ff4c8ddfee61f90a1633a4c4afd3f7bcb32b11c52026c92a12e1325922d0d"}, + {file = "numpy-1.19.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cf2402002d3d9f91c8b01e66fbb436a4ed01c6498fffed0e4c7566da1d40ee1e"}, + {file = "numpy-1.19.5-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1ded4fce9cfaaf24e7a0ab51b7a87be9038ea1ace7f34b841fe3b6894c721d1c"}, + {file = "numpy-1.19.5-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:012426a41bc9ab63bb158635aecccc7610e3eff5d31d1eb43bc099debc979d94"}, + {file = "numpy-1.19.5-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:759e4095edc3c1b3ac031f34d9459fa781777a93ccc633a472a5468587a190ff"}, + {file = "numpy-1.19.5-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:a9d17f2be3b427fbb2bce61e596cf555d6f8a56c222bd2ca148baeeb5e5c783c"}, + {file = "numpy-1.19.5-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:99abf4f353c3d1a0c7a5f27699482c987cf663b1eac20db59b8c7b061eabd7fc"}, + {file = "numpy-1.19.5-cp38-cp38-win32.whl", hash = "sha256:384ec0463d1c2671170901994aeb6dce126de0a95ccc3976c43b0038a37329c2"}, + {file = "numpy-1.19.5-cp38-cp38-win_amd64.whl", hash = "sha256:811daee36a58dc79cf3d8bdd4a490e4277d0e4b7d103a001a4e73ddb48e7e6aa"}, + {file = "numpy-1.19.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c843b3f50d1ab7361ca4f0b3639bf691569493a56808a0b0c54a051d260b7dbd"}, + {file = "numpy-1.19.5-cp39-cp39-manylinux1_i686.whl", hash = "sha256:d6631f2e867676b13026e2846180e2c13c1e11289d67da08d71cacb2cd93d4aa"}, + {file = "numpy-1.19.5-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:7fb43004bce0ca31d8f13a6eb5e943fa73371381e53f7074ed21a4cb786c32f8"}, + {file = "numpy-1.19.5-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:2ea52bd92ab9f768cc64a4c3ef8f4b2580a17af0a5436f6126b08efbd1838371"}, + {file = "numpy-1.19.5-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:400580cbd3cff6ffa6293df2278c75aef2d58d8d93d3c5614cd67981dae68ceb"}, + {file = "numpy-1.19.5-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:df609c82f18c5b9f6cb97271f03315ff0dbe481a2a02e56aeb1b1a985ce38e60"}, + {file = "numpy-1.19.5-cp39-cp39-win32.whl", hash = "sha256:ab83f24d5c52d60dbc8cd0528759532736b56db58adaa7b5f1f76ad551416a1e"}, + {file = "numpy-1.19.5-cp39-cp39-win_amd64.whl", hash = "sha256:0eef32ca3132a48e43f6a0f5a82cb508f22ce5a3d6f67a8329c81c8e226d3f6e"}, + {file = "numpy-1.19.5-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:a0d53e51a6cb6f0d9082decb7a4cb6dfb33055308c4c44f53103c073f649af73"}, + {file = "numpy-1.19.5.zip", hash = "sha256:a76f502430dd98d7546e1ea2250a7360c065a5fdea52b2dffe8ae7180909b6f4"}, +] +oauthlib = [ + {file = "oauthlib-3.1.0-py2.py3-none-any.whl", hash = "sha256:df884cd6cbe20e32633f1db1072e9356f53638e4361bef4e8b03c9127c9328ea"}, + {file = "oauthlib-3.1.0.tar.gz", hash = "sha256:bee41cc35fcca6e988463cacc3bcb8a96224f470ca547e697b604cc697b2f889"}, +] +opt-einsum = [ + {file = "opt_einsum-3.3.0-py3-none-any.whl", hash = "sha256:2455e59e3947d3c275477df7f5205b30635e266fe6dc300e3d9f9646bfcea147"}, + {file = "opt_einsum-3.3.0.tar.gz", hash = "sha256:59f6475f77bbc37dcf7cd748519c0ec60722e91e63ca114e68821c0c54a46549"}, +] +overrides = [ + {file = "overrides-3.0.0.tar.gz", hash = "sha256:7dafd6efc15c809f0d812515bc1e8f64ffe28583d20e9046f95a2c010b4b6cdf"}, +] +packaging = [ + {file = "packaging-20.9-py2.py3-none-any.whl", hash = "sha256:67714da7f7bc052e064859c05c595155bd1ee9f69f76557e21f051443c20947a"}, + {file = "packaging-20.9.tar.gz", hash = "sha256:5b327ac1320dc863dca72f4514ecc086f31186744b84a230374cc1fd776feae5"}, +] +pandas = [ + {file = "pandas-1.1.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:bf23a3b54d128b50f4f9d4675b3c1857a688cc6731a32f931837d72effb2698d"}, + {file = "pandas-1.1.5-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:5a780260afc88268a9d3ac3511d8f494fdcf637eece62fb9eb656a63d53eb7ca"}, + {file = "pandas-1.1.5-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:b61080750d19a0122469ab59b087380721d6b72a4e7d962e4d7e63e0c4504814"}, + {file = "pandas-1.1.5-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:0de3ddb414d30798cbf56e642d82cac30a80223ad6fe484d66c0ce01a84d6f2f"}, + {file = "pandas-1.1.5-cp36-cp36m-win32.whl", hash = "sha256:70865f96bb38fec46f7ebd66d4b5cfd0aa6b842073f298d621385ae3898d28b5"}, + {file = "pandas-1.1.5-cp36-cp36m-win_amd64.whl", hash = "sha256:19a2148a1d02791352e9fa637899a78e371a3516ac6da5c4edc718f60cbae648"}, + {file = "pandas-1.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:26fa92d3ac743a149a31b21d6f4337b0594b6302ea5575b37af9ca9611e8981a"}, + {file = "pandas-1.1.5-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:c16d59c15d946111d2716856dd5479221c9e4f2f5c7bc2d617f39d870031e086"}, + {file = "pandas-1.1.5-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:3be7a7a0ca71a2640e81d9276f526bca63505850add10206d0da2e8a0a325dae"}, + {file = "pandas-1.1.5-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:573fba5b05bf2c69271a32e52399c8de599e4a15ab7cec47d3b9c904125ab788"}, + {file = "pandas-1.1.5-cp37-cp37m-win32.whl", hash = "sha256:21b5a2b033380adbdd36b3116faaf9a4663e375325831dac1b519a44f9e439bb"}, + {file = "pandas-1.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:24c7f8d4aee71bfa6401faeba367dd654f696a77151a8a28bc2013f7ced4af98"}, + {file = "pandas-1.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2860a97cbb25444ffc0088b457da0a79dc79f9c601238a3e0644312fcc14bf11"}, + {file = "pandas-1.1.5-cp38-cp38-manylinux1_i686.whl", hash = "sha256:5008374ebb990dad9ed48b0f5d0038124c73748f5384cc8c46904dace27082d9"}, + {file = "pandas-1.1.5-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:2c2f7c670ea4e60318e4b7e474d56447cf0c7d83b3c2a5405a0dbb2600b9c48e"}, + {file = "pandas-1.1.5-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:0a643bae4283a37732ddfcecab3f62dd082996021b980f580903f4e8e01b3c5b"}, + {file = "pandas-1.1.5-cp38-cp38-win32.whl", hash = "sha256:5447ea7af4005b0daf695a316a423b96374c9c73ffbd4533209c5ddc369e644b"}, + {file = "pandas-1.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:4c62e94d5d49db116bef1bd5c2486723a292d79409fc9abd51adf9e05329101d"}, + {file = "pandas-1.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:731568be71fba1e13cae212c362f3d2ca8932e83cb1b85e3f1b4dd77d019254a"}, + {file = "pandas-1.1.5-cp39-cp39-manylinux1_i686.whl", hash = "sha256:c61c043aafb69329d0f961b19faa30b1dab709dd34c9388143fc55680059e55a"}, + {file = "pandas-1.1.5-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:2b1c6cd28a0dfda75c7b5957363333f01d370936e4c6276b7b8e696dd500582a"}, + {file = "pandas-1.1.5-cp39-cp39-win32.whl", hash = "sha256:c94ff2780a1fd89f190390130d6d36173ca59fcfb3fe0ff596f9a56518191ccb"}, + {file = "pandas-1.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:edda9bacc3843dfbeebaf7a701763e68e741b08fccb889c003b0a52f0ee95782"}, + {file = "pandas-1.1.5.tar.gz", hash = "sha256:f10fc41ee3c75a474d3bdf68d396f10782d013d7f67db99c0efbfd0acb99701b"}, +] +pandas-ta = [ + {file = "pandas_ta-0.2.23b.tar.gz", hash = "sha256:73d5c5f9de2edd322abc961f4c47f9c5b2a1e3915223042bc10f1dbc0c29bb02"}, +] +patsy = [ + {file = "patsy-0.5.1-py2.py3-none-any.whl", hash = "sha256:5465be1c0e670c3a965355ec09e9a502bf2c4cbe4875e8528b0221190a8a5d40"}, + {file = "patsy-0.5.1.tar.gz", hash = "sha256:f115cec4201e1465cd58b9866b0b0e7b941caafec129869057405bfe5b5e3991"}, +] +pillow = [ + {file = "Pillow-8.1.0-cp36-cp36m-macosx_10_10_x86_64.whl", hash = "sha256:d355502dce85ade85a2511b40b4c61a128902f246504f7de29bbeec1ae27933a"}, + {file = "Pillow-8.1.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:93a473b53cc6e0b3ce6bf51b1b95b7b1e7e6084be3a07e40f79b42e83503fbf2"}, + {file = "Pillow-8.1.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:2353834b2c49b95e1313fb34edf18fca4d57446675d05298bb694bca4b194174"}, + {file = "Pillow-8.1.0-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:1d208e670abfeb41b6143537a681299ef86e92d2a3dac299d3cd6830d5c7bded"}, + {file = "Pillow-8.1.0-cp36-cp36m-win32.whl", hash = "sha256:dd9eef866c70d2cbbea1ae58134eaffda0d4bfea403025f4db6859724b18ab3d"}, + {file = "Pillow-8.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:b09e10ec453de97f9a23a5aa5e30b334195e8d2ddd1ce76cc32e52ba63c8b31d"}, + {file = "Pillow-8.1.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:b02a0b9f332086657852b1f7cb380f6a42403a6d9c42a4c34a561aa4530d5234"}, + {file = "Pillow-8.1.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:ca20739e303254287138234485579b28cb0d524401f83d5129b5ff9d606cb0a8"}, + {file = "Pillow-8.1.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:604815c55fd92e735f9738f65dabf4edc3e79f88541c221d292faec1904a4b17"}, + {file = "Pillow-8.1.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:cf6e33d92b1526190a1de904df21663c46a456758c0424e4f947ae9aa6088bf7"}, + {file = "Pillow-8.1.0-cp37-cp37m-win32.whl", hash = "sha256:47c0d93ee9c8b181f353dbead6530b26980fe4f5485aa18be8f1fd3c3cbc685e"}, + {file = "Pillow-8.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:96d4dc103d1a0fa6d47c6c55a47de5f5dafd5ef0114fa10c85a1fd8e0216284b"}, + {file = "Pillow-8.1.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:7916cbc94f1c6b1301ac04510d0881b9e9feb20ae34094d3615a8a7c3db0dcc0"}, + {file = "Pillow-8.1.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:3de6b2ee4f78c6b3d89d184ade5d8fa68af0848f9b6b6da2b9ab7943ec46971a"}, + {file = "Pillow-8.1.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:cdbbe7dff4a677fb555a54f9bc0450f2a21a93c5ba2b44e09e54fcb72d2bd13d"}, + {file = "Pillow-8.1.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:f50e7a98b0453f39000619d845be8b06e611e56ee6e8186f7f60c3b1e2f0feae"}, + {file = "Pillow-8.1.0-cp38-cp38-win32.whl", hash = "sha256:cb192176b477d49b0a327b2a5a4979552b7a58cd42037034316b8018ac3ebb59"}, + {file = "Pillow-8.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:6c5275bd82711cd3dcd0af8ce0bb99113ae8911fc2952805f1d012de7d600a4c"}, + {file = "Pillow-8.1.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:165c88bc9d8dba670110c689e3cc5c71dbe4bfb984ffa7cbebf1fac9554071d6"}, + {file = "Pillow-8.1.0-cp39-cp39-manylinux1_i686.whl", hash = "sha256:5e2fe3bb2363b862671eba632537cd3a823847db4d98be95690b7e382f3d6378"}, + {file = "Pillow-8.1.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:7612520e5e1a371d77e1d1ca3a3ee6227eef00d0a9cddb4ef7ecb0b7396eddf7"}, + {file = "Pillow-8.1.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:d673c4990acd016229a5c1c4ee8a9e6d8f481b27ade5fc3d95938697fa443ce0"}, + {file = "Pillow-8.1.0-cp39-cp39-win32.whl", hash = "sha256:dc577f4cfdda354db3ae37a572428a90ffdbe4e51eda7849bf442fb803f09c9b"}, + {file = "Pillow-8.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:22d070ca2e60c99929ef274cfced04294d2368193e935c5d6febfd8b601bf865"}, + {file = "Pillow-8.1.0-pp36-pypy36_pp73-macosx_10_10_x86_64.whl", hash = "sha256:a3d3e086474ef12ef13d42e5f9b7bbf09d39cf6bd4940f982263d6954b13f6a9"}, + {file = "Pillow-8.1.0-pp36-pypy36_pp73-manylinux2010_i686.whl", hash = "sha256:731ca5aabe9085160cf68b2dbef95fc1991015bc0a3a6ea46a371ab88f3d0913"}, + {file = "Pillow-8.1.0-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:bba80df38cfc17f490ec651c73bb37cd896bc2400cfba27d078c2135223c1206"}, + {file = "Pillow-8.1.0-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:c3d911614b008e8a576b8e5303e3db29224b455d3d66d1b2848ba6ca83f9ece9"}, + {file = "Pillow-8.1.0-pp37-pypy37_pp73-manylinux2010_i686.whl", hash = "sha256:39725acf2d2e9c17356e6835dccebe7a697db55f25a09207e38b835d5e1bc032"}, + {file = "Pillow-8.1.0-pp37-pypy37_pp73-manylinux2010_x86_64.whl", hash = "sha256:81c3fa9a75d9f1afafdb916d5995633f319db09bd773cb56b8e39f1e98d90820"}, + {file = "Pillow-8.1.0-pp37-pypy37_pp73-win32.whl", hash = "sha256:b6f00ad5ebe846cc91763b1d0c6d30a8042e02b2316e27b05de04fa6ec831ec5"}, + {file = "Pillow-8.1.0.tar.gz", hash = "sha256:887668e792b7edbfb1d3c9d8b5d8c859269a0f0eba4dda562adb95500f60dbba"}, +] +plotly = [ + {file = "plotly-4.14.3-py2.py3-none-any.whl", hash = "sha256:d68fc15fcb49f88db27ab3e0c87110943e65fee02a47f33a8590f541b3042461"}, + {file = "plotly-4.14.3.tar.gz", hash = "sha256:7d8aaeed392e82fb8e0e48899f2d3d957b12327f9d38cdd5802bc574a8a39d91"}, +] +pmdarima = [ + {file = "pmdarima-1.8.0-cp36-cp36m-macosx_10_15_x86_64.whl", hash = "sha256:0377023997c4424586d4f5d207a455a3fbba6f5fda41d89eb135a5f697375dcd"}, + {file = "pmdarima-1.8.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:5fbd363bbfe6dd4f35c1825f53ae07e63d3ca1995ac3e87bef0359c1670c464b"}, + {file = "pmdarima-1.8.0-cp36-cp36m-win32.whl", hash = "sha256:01a96b4c014646c2bfe57cbecf2f75ccd99e417badfa9c28fd1c0f3506ad0eb1"}, + {file = "pmdarima-1.8.0-cp36-cp36m-win_amd64.whl", hash = "sha256:582ad6644a9eebde47739aa1152ccc812b530b2ce4fd32d1685442ac0c57396d"}, + {file = "pmdarima-1.8.0-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:f9c13f124a4f2996c544463cd651a668a65c5c390f85e25a76110c4836fa4182"}, + {file = "pmdarima-1.8.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:d39e4251ffdc78f90b4dac2ba5c5a2222eea43a7548f35cdccd10b044d042eb2"}, + {file = "pmdarima-1.8.0-cp37-cp37m-win32.whl", hash = "sha256:f02aae7f79dfe2e7605db586d4b5683d5ef2587efaf1273a2b8a37966733a892"}, + {file = "pmdarima-1.8.0-cp37-cp37m-win_amd64.whl", hash = "sha256:524b51f9cc3997ec2ffc66b30c3a97dc6e14e7fad72905a2c8830360d30d45cf"}, + {file = "pmdarima-1.8.0-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:0e4dc0fe42fbfce7822b5f0e56e46b7fb89f2d6ce4eb7da5fa4fefff6983a841"}, + {file = "pmdarima-1.8.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:fa4110707e7cfbd9966ce3ef856db4d8f916d34aa668fb9281e424e9a98c22d8"}, + {file = "pmdarima-1.8.0-cp38-cp38-win32.whl", hash = "sha256:3df67baa9ac64cbdf96ba0b4a4bc24507bce02b93411afeb857e26abd2385a56"}, + {file = "pmdarima-1.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:394d220f65ed3a26cb4554323e7c4c6b88922fe283f912255844fbe14dff5b32"}, + {file = "pmdarima-1.8.0.tar.gz", hash = "sha256:65f22f49ebc2271934a2bb346a6667b19094300eeaebf93a3674577c5440a6bc"}, +] +praw = [ + {file = "praw-7.1.4-py3-none-any.whl", hash = "sha256:068a01c19834e1f748a8c220c6aa62ae9f0f8e211504ab8ef19883d09bed3430"}, + {file = "praw-7.1.4.tar.gz", hash = "sha256:87166a77ec31a1d9686ccdac97b5b72ba277ce436976eb3baf467c593f15bb26"}, +] +prawcore = [ + {file = "prawcore-1.5.0-py3-none-any.whl", hash = "sha256:672d8a2faa12b44307874b2acfdd27f9cbaa5fa37bada4b34e36277224e6d8ed"}, + {file = "prawcore-1.5.0.tar.gz", hash = "sha256:1f1eafc8a65d671f9892354f73142014fbb5d3a9ee621568c662d0a354e0578b"}, +] +prettytable = [ + {file = "prettytable-2.0.0-py3-none-any.whl", hash = "sha256:5dc7fcaca227f48deacd86958ae9d7b8c31a186fcb354bbb066763f20adf3eb9"}, + {file = "prettytable-2.0.0.tar.gz", hash = "sha256:e37acd91976fe6119172771520e58d1742c8479703489321dc1d9c85e7259922"}, +] +protobuf = [ + {file = "protobuf-3.15.3-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:822341974a28d895f0b39df13b3e2f27577498c1d85b5e876ff1d53fbdf2ef97"}, + {file = "protobuf-3.15.3-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:31460706eb7c3bcc3c153877e580b78efa624b9626bd084fb882f20681ffa81a"}, + {file = "protobuf-3.15.3-cp35-cp35m-macosx_10_9_intel.whl", hash = "sha256:405fbe27eeccd90b07e7cc20f2bcce477a86027435016aef71f15473dede92b5"}, + {file = "protobuf-3.15.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:a98195be29b2622961896893a6e92a4e0812e4e367078ac20f0c7982e51ff7ea"}, + {file = "protobuf-3.15.3-cp35-cp35m-win32.whl", hash = "sha256:7141c37a5af565908c3da10575c517c59a8e67591c507cf36f2655590200ddfc"}, + {file = "protobuf-3.15.3-cp35-cp35m-win_amd64.whl", hash = "sha256:ffc556af23c7e1278b43719999dd215619f73f8d42f40275c55a1de09938214f"}, + {file = "protobuf-3.15.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9aa4c216e48236c6af4e71f64afc0c13c12401d3067a323b9fe543bb676bac3"}, + {file = "protobuf-3.15.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0c678e11b7b6d6e5baa9710f44de01d48bc81b7db617ad5283a76f1f4c73df99"}, + {file = "protobuf-3.15.3-cp36-cp36m-win32.whl", hash = "sha256:1fe832e1a5c51c71c2d6e949e597f3c47ef39c817264086293e4037941ab9bd7"}, + {file = "protobuf-3.15.3-cp36-cp36m-win_amd64.whl", hash = "sha256:8a8157ff82760105cf435dbb8f4e7042a39c6d92f673fba8c2c815432b3f1063"}, + {file = "protobuf-3.15.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:970b9f648fc12d28ce6f1f10575bbf063e828e1fd8d95339602cad2312a4fefa"}, + {file = "protobuf-3.15.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:492beef9386706f84f683489fe18d1a7d8be5f4ab050782b3a484de1d1b01a69"}, + {file = "protobuf-3.15.3-cp37-cp37m-win32.whl", hash = "sha256:af760e4fe6f30e1af3d5dac6767444ff61ef621ac857b3405b8f3cd29f16ac55"}, + {file = "protobuf-3.15.3-cp37-cp37m-win_amd64.whl", hash = "sha256:21911af1fc692e7ca6a73c0fab3912a5d792ed7603350dbabd34a9722cbfe4d5"}, + {file = "protobuf-3.15.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a3e18453d91040dad1985d1ea8a237fb7522a84fcefc17b452f756833b066d71"}, + {file = "protobuf-3.15.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:d7761bd18fc3d197e50459c37abb95b64cd614e7b9014239a1e7c952433e380b"}, + {file = "protobuf-3.15.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6f52c66f361de32096ba88c73ad0ff53585dafc569d8bf11968412175ddf297c"}, + {file = "protobuf-3.15.3-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:3bbaed8e63cd62533a80adfa51f91b34bf7da29ac0335412dbebd21dac2d68b9"}, + {file = "protobuf-3.15.3-py2.py3-none-any.whl", hash = "sha256:ad8e808b572e6ee38131e7b58d94aa5c438e3a3469d055e8989ea73a8e2308c0"}, + {file = "protobuf-3.15.3.tar.gz", hash = "sha256:f3348af83391cdb842030e774d9bb01565ed4c62c93554cd1c69723411ec5e9d"}, +] +psaw = [ + {file = "psaw-0.0.12-py3-none-any.whl", hash = "sha256:cfbfdf1953ee5f31ca9d4ec6d471873ace960da9fbc7234b9d19a059d5cfa2d6"}, +] +pyasn1 = [ + {file = "pyasn1-0.4.8-py2.4.egg", hash = "sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3"}, + {file = "pyasn1-0.4.8-py2.5.egg", hash = "sha256:0458773cfe65b153891ac249bcf1b5f8f320b7c2ce462151f8fa74de8934becf"}, + {file = "pyasn1-0.4.8-py2.6.egg", hash = "sha256:5c9414dcfede6e441f7e8f81b43b34e834731003427e5b09e4e00e3172a10f00"}, + {file = "pyasn1-0.4.8-py2.7.egg", hash = "sha256:6e7545f1a61025a4e58bb336952c5061697da694db1cae97b116e9c46abcf7c8"}, + {file = "pyasn1-0.4.8-py2.py3-none-any.whl", hash = "sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d"}, + {file = "pyasn1-0.4.8-py3.1.egg", hash = "sha256:78fa6da68ed2727915c4767bb386ab32cdba863caa7dbe473eaae45f9959da86"}, + {file = "pyasn1-0.4.8-py3.2.egg", hash = "sha256:08c3c53b75eaa48d71cf8c710312316392ed40899cb34710d092e96745a358b7"}, + {file = "pyasn1-0.4.8-py3.3.egg", hash = "sha256:03840c999ba71680a131cfaee6fab142e1ed9bbd9c693e285cc6aca0d555e576"}, + {file = "pyasn1-0.4.8-py3.4.egg", hash = "sha256:7ab8a544af125fb704feadb008c99a88805126fb525280b2270bb25cc1d78a12"}, + {file = "pyasn1-0.4.8-py3.5.egg", hash = "sha256:e89bf84b5437b532b0803ba5c9a5e054d21fec423a89952a74f87fa2c9b7bce2"}, + {file = "pyasn1-0.4.8-py3.6.egg", hash = "sha256:014c0e9976956a08139dc0712ae195324a75e142284d5f87f1a87ee1b068a359"}, + {file = "pyasn1-0.4.8-py3.7.egg", hash = "sha256:99fcc3c8d804d1bc6d9a099921e39d827026409a58f2a720dcdb89374ea0c776"}, + {file = "pyasn1-0.4.8.tar.gz", hash = "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba"}, +] +pyasn1-modules = [ + {file = "pyasn1-modules-0.2.8.tar.gz", hash = "sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e"}, + {file = "pyasn1_modules-0.2.8-py2.4.egg", hash = "sha256:0fe1b68d1e486a1ed5473f1302bd991c1611d319bba158e98b106ff86e1d7199"}, + {file = "pyasn1_modules-0.2.8-py2.5.egg", hash = "sha256:fe0644d9ab041506b62782e92b06b8c68cca799e1a9636ec398675459e031405"}, + {file = "pyasn1_modules-0.2.8-py2.6.egg", hash = "sha256:a99324196732f53093a84c4369c996713eb8c89d360a496b599fb1a9c47fc3eb"}, + {file = "pyasn1_modules-0.2.8-py2.7.egg", hash = "sha256:0845a5582f6a02bb3e1bde9ecfc4bfcae6ec3210dd270522fee602365430c3f8"}, + {file = "pyasn1_modules-0.2.8-py2.py3-none-any.whl", hash = "sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74"}, + {file = "pyasn1_modules-0.2.8-py3.1.egg", hash = "sha256:f39edd8c4ecaa4556e989147ebf219227e2cd2e8a43c7e7fcb1f1c18c5fd6a3d"}, + {file = "pyasn1_modules-0.2.8-py3.2.egg", hash = "sha256:b80486a6c77252ea3a3e9b1e360bc9cf28eaac41263d173c032581ad2f20fe45"}, + {file = "pyasn1_modules-0.2.8-py3.3.egg", hash = "sha256:65cebbaffc913f4fe9e4808735c95ea22d7a7775646ab690518c056784bc21b4"}, + {file = "pyasn1_modules-0.2.8-py3.4.egg", hash = "sha256:15b7c67fabc7fc240d87fb9aabf999cf82311a6d6fb2c70d00d3d0604878c811"}, + {file = "pyasn1_modules-0.2.8-py3.5.egg", hash = "sha256:426edb7a5e8879f1ec54a1864f16b882c2837bfd06eee62f2c982315ee2473ed"}, + {file = "pyasn1_modules-0.2.8-py3.6.egg", hash = "sha256:cbac4bc38d117f2a49aeedec4407d23e8866ea4ac27ff2cf7fb3e5b570df19e0"}, + {file = "pyasn1_modules-0.2.8-py3.7.egg", hash = "sha256:c29a5e5cc7a3f05926aff34e097e84f8589cd790ce0ed41b67aed6857b26aafd"}, +] +pymeeus = [ + {file = "PyMeeus-0.4.2.tar.gz", hash = "sha256:6b7b3b86e4a8c9065fcf3b2ebb3f1e122d1a819de1a98461c3f873feab550291"}, +] +pyparsing = [ + {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"}, + {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"}, +] +pysocks = [ + {file = "PySocks-1.7.1-py27-none-any.whl", hash = "sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299"}, + {file = "PySocks-1.7.1-py3-none-any.whl", hash = "sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5"}, + {file = "PySocks-1.7.1.tar.gz", hash = "sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0"}, +] +pystan = [ + {file = "pystan-2.19.1.1-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:4a0820df5fcd13c7a4cae75d59809adee72d1135a604dc2b5f068d4ac8ca349e"}, + {file = "pystan-2.19.1.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:2baa4106ddc7fb90712bd0e5ab8693ce130b001c6166839247511326edc6d0ba"}, + {file = "pystan-2.19.1.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:6c4bbbb0a59144135d9821f2b9c308bfdf70aa61befdc7dc435f4c86bfb4457e"}, + {file = "pystan-2.19.1.1-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:1127522641533a6ccb7684d4008d06c092cbe6f3ee7d44679a87937ee39093ab"}, + {file = "pystan-2.19.1.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:43fdd98561f0cba0637f1fa343ed7d5adc885d04a655ab6302dbfd08f016105d"}, + {file = "pystan-2.19.1.1-cp35-cp35m-win32.whl", hash = "sha256:e6580cec2f5ed1bdb44eab83d54fe87b11e673ed65d6c2064d8d9f76265ce049"}, + {file = "pystan-2.19.1.1-cp35-cp35m-win_amd64.whl", hash = "sha256:c87bd98db2b5c67fa08177de04c98b46d1fcd68ae53dbe55ffc5187868068002"}, + {file = "pystan-2.19.1.1-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:e9fbbf10dfc0ef8e7343ee4a3e17fd5c214fb12fc42615673e14908949b410e4"}, + {file = "pystan-2.19.1.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:5020ac3ca3a840f428f090fc5fe75412e2a7948ac7e3de59f4bbfd7a4539c0ef"}, + {file = "pystan-2.19.1.1-cp36-cp36m-win32.whl", hash = "sha256:61340356889547e29e2e6db7ef28f821b91e73fee80a888e81a794a24a249987"}, + {file = "pystan-2.19.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:bc1193f52bc6c6419dd753bcb0b6958b24fe588dc3da3c7f70bd23dcbda6ec2a"}, + {file = "pystan-2.19.1.1-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:5b67008f5780c7cf0f3fbad5bc54bc9919efc9655d63e0314dc013e85c7a0f14"}, + {file = "pystan-2.19.1.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:2b44502aaa8866e0bcc81df1537e7e08b74aaf4cc9d4bf43e7c8b168f3568ca6"}, + {file = "pystan-2.19.1.1-cp37-cp37m-win32.whl", hash = "sha256:b2ef9031dfbd65757828e2441cb9a76c9217fb5bb93817fee2550722e7a785b3"}, + {file = "pystan-2.19.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:3622520b2e55d2ce70a3027d9910b6197a8bc2ef59e01967be9c4e607a48a9c1"}, + {file = "pystan-2.19.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:837a62976b32e4fd2bd48fee3b419c651e19747280e440d5934bea3822b22115"}, + {file = "pystan-2.19.1.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:e8e0924c318a0ea67260167a74f040078a4ce0d3fd4a7d566aa76f7752a85fab"}, + {file = "pystan-2.19.1.1-cp38-cp38-win32.whl", hash = "sha256:f16c399da3d9d72e9661b131c23d51a59c789416598885714813fcb552234c83"}, + {file = "pystan-2.19.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:9d8c2ae05d1dca854a55b2ae9276af5866e473fb8264d03d5267abadb3c602da"}, + {file = "pystan-2.19.1.1.tar.gz", hash = "sha256:fa8bad8dbc0da22bbe6f36af56c9abbfcf10f92df8ce627d59a36bd8d25eb038"}, +] +python-dateutil = [ + {file = "python-dateutil-2.8.1.tar.gz", hash = "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"}, + {file = "python_dateutil-2.8.1-py2.py3-none-any.whl", hash = "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a"}, +] +pytrends = [ + {file = "pytrends-4.7.3-py3-none-any.whl", hash = "sha256:88d92e398b9408c79fd92946ddc2b03fa622301233bc49f16804042eb2897328"}, + {file = "pytrends-4.7.3.tar.gz", hash = "sha256:8ccb06c57c31fa157b978a0d810de7718ee46583d28cf818250d45f36abd2faa"}, +] +pytz = [ + {file = "pytz-2021.1-py2.py3-none-any.whl", hash = "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"}, + {file = "pytz-2021.1.tar.gz", hash = "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da"}, +] +quandl = [ + {file = "Quandl-3.6.0-py2.py3-none-any.whl", hash = "sha256:4f7034a3ddb386ade242748e4ec64044ca5ab4165fbaef291057af576cf38fb3"}, + {file = "Quandl-3.6.0.tar.gz", hash = "sha256:c131ebdc5a21c34bfbaf01627b430b2e210330a15ecf5f64824d3ce567802302"}, +] +rapidfuzz = [ + {file = "rapidfuzz-1.1.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:b491e68620a31d5059ae83a7d6955142d3b68b6852b0da8dacf1f05742ec848f"}, + {file = "rapidfuzz-1.1.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:8c08b696e1d7edc897bd15df549c312276403741271a3e7d779653b757c3bc85"}, + {file = "rapidfuzz-1.1.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:a6633fe5ed0361f4145d01ae8fde8564609f178614bb3341d96a71a9c0b051b0"}, + {file = "rapidfuzz-1.1.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:c58e5d2a94c09220d03fcac7cf5e5c98ffc76ab0343d12238ae8a140cbccdc7a"}, + {file = "rapidfuzz-1.1.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:753924c78fd6d754e4640832eebf662e8696ac9c1be9bddf2a530e5d72f6d065"}, + {file = "rapidfuzz-1.1.1-cp27-cp27m-win32.whl", hash = "sha256:d708287eb74f6b432e27ddd0b08a83f76b7b64d818e5066483833067048b06cf"}, + {file = "rapidfuzz-1.1.1-cp27-cp27m-win_amd64.whl", hash = "sha256:15c9ac1279ce9103dfe377b1a51f0548f6cc08c7d58d6bc45e9f224e5ab310d0"}, + {file = "rapidfuzz-1.1.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:86056bf87b177e3a4e899bf50ee21da0ac72c27a9e6c5b75b816fa775c3199fe"}, + {file = "rapidfuzz-1.1.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:4947c60f073d0970ba8ca7456dd94e610672d79886689363f6175fc9d68cceee"}, + {file = "rapidfuzz-1.1.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:9e3a0daea2bcfda554897586afde99807bacb44672613a4c52f9a87388627e70"}, + {file = "rapidfuzz-1.1.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:8921f620a995cba93d3cf97a4386abd7633ee78bdbb5cfda4c5a08057edcffad"}, + {file = "rapidfuzz-1.1.1-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:a795b393dc537aafbfbbc936eec0a6189ae7dc42afe459a62b0be41e30fbd5d8"}, + {file = "rapidfuzz-1.1.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:d79ace11b1b81f87e6c303ce06b2c0b841938df9694ef6873b94b085cb43827e"}, + {file = "rapidfuzz-1.1.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:611751f2164bc2a14f008b6ac45a7d0fd14d145934ddd9a6ece786560deb0148"}, + {file = "rapidfuzz-1.1.1-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:822adafbc76c2cf2f0966fd9c20683d46b6cf5a09b6020526fb1ab0cc6b3db73"}, + {file = "rapidfuzz-1.1.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:f1f10d7118890f14be78e6b01fca1903e6c621c5f7f9c4ad9224440f96f2e8bd"}, + {file = "rapidfuzz-1.1.1-cp35-cp35m-win32.whl", hash = "sha256:932bf1316d15e5cc79f32406d8c96a06749494df4b7c1fdc620b482370a38958"}, + {file = "rapidfuzz-1.1.1-cp35-cp35m-win_amd64.whl", hash = "sha256:31bb95bc8c3425f81f161f07b00a50c67a1d16eac3f4fb5e3bd0fdcdd8b9334f"}, + {file = "rapidfuzz-1.1.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:4cd9aa9e10b3f47bd64bbdac5a13168725dffbfcf24f1b79d602c1a139823e1e"}, + {file = "rapidfuzz-1.1.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:e028da2c1f2032700412f1812509356d19eb776da67921f8564a9863ae870029"}, + {file = "rapidfuzz-1.1.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:f19aab9a50e5380c5092d3ebfdb3d1d8a778dadde2ceb32ef9c8bfdbda6f0f72"}, + {file = "rapidfuzz-1.1.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:e0b316d949f04dfc1953cec35e9caed5cb54d6deb421d6634336c1f000e8d141"}, + {file = "rapidfuzz-1.1.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fa1ace30c431073218d7717fa747c2298dbbf269faf42cae1471ec49b62c62f5"}, + {file = "rapidfuzz-1.1.1-cp36-cp36m-win32.whl", hash = "sha256:90d6b1c78fb9b51efe5a9a042977339435c8c007e36c8d81ddc21098ff5b9fc2"}, + {file = "rapidfuzz-1.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:c0309d9c19b0ff7f7420022323237a04f717d9ac6867d90ff9daaa55cf6d8535"}, + {file = "rapidfuzz-1.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:41dc6326d445d8e7afff53f1194ea3a2a7342d578efdc29748fb33eb479c97f6"}, + {file = "rapidfuzz-1.1.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:bbb9a6802231851b6e582c5a7e633e17a333ef3ba5d2da626f43d75c9ce1a96c"}, + {file = "rapidfuzz-1.1.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:3a1039ca6136d957aa30b9743f3f627ef0662a26e8d5f722815866d1cdfb396b"}, + {file = "rapidfuzz-1.1.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:04c4a27b1bd475d36e9003380220a862163a079184043c27e7443c9aded09c86"}, + {file = "rapidfuzz-1.1.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:e43d057b5277bdcf2519c30ca9eb8aa52e047f3e92dcbc45c4600a5f760c148e"}, + {file = "rapidfuzz-1.1.1-cp37-cp37m-win32.whl", hash = "sha256:c9c1cde7a546e55d1530ec06840af3781ee3d05e7e21fe0f68203869c2a8bef4"}, + {file = "rapidfuzz-1.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:52512ba8940c9fac1eb9c18771ca0cf20ec9d61b48960b8e0f149ae64e73042e"}, + {file = "rapidfuzz-1.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0dbd7d197d1a590c2671cbc7f67ba6979548deb1827c45963bc48deddc509207"}, + {file = "rapidfuzz-1.1.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:bd423368637bd6b56e4e89356ad52bb4501100ba2d5e49ccf08c1f476068e234"}, + {file = "rapidfuzz-1.1.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:8789b6105168796d7478304a8886e2d735fe63ff60f3641da6d3dedb292fda9d"}, + {file = "rapidfuzz-1.1.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:1d858ec78a99ea8e32d86925166434788522f5020ade02648c85bb3fc3f4f6de"}, + {file = "rapidfuzz-1.1.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:3724934e8037befd18901bf7f26cc9e041c3cdfae222e54fe6e6afd6e4cb0e26"}, + {file = "rapidfuzz-1.1.1-cp38-cp38-win32.whl", hash = "sha256:94f73da4a5c783b1743530fd1c85e2311e749f9f7e557360f1d2a87d6a444f94"}, + {file = "rapidfuzz-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:3e6f6c9757823aab42d6216800eb942f31d100a22a07ec666058ccb224ede5ab"}, + {file = "rapidfuzz-1.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8548e2a9462cccfd26529eed6f9a891f48e55c800c08cb8ed2c8c612dcc5ff09"}, + {file = "rapidfuzz-1.1.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:fadbf1ccfdcbba169db24704325421f8389a954cc717512bfa33f2cd3ffc67f7"}, + {file = "rapidfuzz-1.1.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:6a6447d9612cc7ba0dfc93e5d4a92a1d8022bf4f693fe36dfd4a79326e91c151"}, + {file = "rapidfuzz-1.1.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:b01988ceb5fa891828485d3861d629716b6fe28d7d632e643c0fd8a847612c54"}, + {file = "rapidfuzz-1.1.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:74196c59e16a141e61161bd902f7cddab73571ee89951f1fd6acba6a7cc8a131"}, + {file = "rapidfuzz-1.1.1-cp39-cp39-win32.whl", hash = "sha256:2b657bb9cc69d5729d1f0799f13ca9632fccba1a588bef78012bdd51f07b7ee8"}, + {file = "rapidfuzz-1.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:79bdac4250d1dd33ec7abaa4b5a047d96f21a3f8c5f736f47371ad17c2fa10ac"}, + {file = "rapidfuzz-1.1.1-pp27-pypy_73-macosx_10_9_x86_64.whl", hash = "sha256:f7821472adb6e416479a7e1d6ed1dbe69627fc0fc648903a7b58fe84cb8b177f"}, + {file = "rapidfuzz-1.1.1-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:f4f46633dfdac0a25fe53893f8f42213fa22636f70f1c77912d190cd5b9b5fa0"}, + {file = "rapidfuzz-1.1.1-pp27-pypy_73-win32.whl", hash = "sha256:8ecd71bb161953daf7524f095d9484791c984bfc93b8f9ea06b16ef4143dee4a"}, + {file = "rapidfuzz-1.1.1-pp36-pypy36_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0d08a0bb5a6cd164d899a8f17fece7f5e54e040ccbe17dd38d56603b1ee3319a"}, + {file = "rapidfuzz-1.1.1-pp36-pypy36_pp73-manylinux1_x86_64.whl", hash = "sha256:3f885029755fcaea0449d3bb7cbbc551b24e1e9441fdc273472d81c02f30ae7f"}, + {file = "rapidfuzz-1.1.1-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:85ed82af38aaed64e34adcbdeb629d2e514f306ca8539e92906028a792228113"}, + {file = "rapidfuzz-1.1.1-pp36-pypy36_pp73-win32.whl", hash = "sha256:06edb5a49b487499857b575028182c3f75361c6c22950661c598d36cc584af3c"}, + {file = "rapidfuzz-1.1.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a6cf3263dec303acc034b74b4060492fea898f05855947b024e9aade5ecc264e"}, + {file = "rapidfuzz-1.1.1-pp37-pypy37_pp73-manylinux1_x86_64.whl", hash = "sha256:e6fb951b8d9bde314f024a27b36494fc04a97d7393ab0777e74f9526a7f28da4"}, + {file = "rapidfuzz-1.1.1-pp37-pypy37_pp73-manylinux2010_x86_64.whl", hash = "sha256:f50359da4303c903269e88c00db8ad6cd6f62480cdba2aae3697519a70dcbbec"}, + {file = "rapidfuzz-1.1.1-pp37-pypy37_pp73-win32.whl", hash = "sha256:164ad3790d361d5264972c4cfec97f1ff3ea9a7b451208e84ca873f4a88bda06"}, + {file = "rapidfuzz-1.1.1.tar.gz", hash = "sha256:5ad59cfc2c9f6a214c814de8b9e94309f82943a902f7acea307d9d5be2b0cccb"}, +] +regex = [ + {file = "regex-2020.11.13-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:8b882a78c320478b12ff024e81dc7d43c1462aa4a3341c754ee65d857a521f85"}, + {file = "regex-2020.11.13-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:a63f1a07932c9686d2d416fb295ec2c01ab246e89b4d58e5fa468089cab44b70"}, + {file = "regex-2020.11.13-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:6e4b08c6f8daca7d8f07c8d24e4331ae7953333dbd09c648ed6ebd24db5a10ee"}, + {file = "regex-2020.11.13-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:bba349276b126947b014e50ab3316c027cac1495992f10e5682dc677b3dfa0c5"}, + {file = "regex-2020.11.13-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:56e01daca75eae420bce184edd8bb341c8eebb19dd3bce7266332258f9fb9dd7"}, + {file = "regex-2020.11.13-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:6a8ce43923c518c24a2579fda49f093f1397dad5d18346211e46f134fc624e31"}, + {file = "regex-2020.11.13-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:1ab79fcb02b930de09c76d024d279686ec5d532eb814fd0ed1e0051eb8bd2daa"}, + {file = "regex-2020.11.13-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:9801c4c1d9ae6a70aeb2128e5b4b68c45d4f0af0d1535500884d644fa9b768c6"}, + {file = "regex-2020.11.13-cp36-cp36m-win32.whl", hash = "sha256:49cae022fa13f09be91b2c880e58e14b6da5d10639ed45ca69b85faf039f7a4e"}, + {file = "regex-2020.11.13-cp36-cp36m-win_amd64.whl", hash = "sha256:749078d1eb89484db5f34b4012092ad14b327944ee7f1c4f74d6279a6e4d1884"}, + {file = "regex-2020.11.13-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b2f4007bff007c96a173e24dcda236e5e83bde4358a557f9ccf5e014439eae4b"}, + {file = "regex-2020.11.13-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:38c8fd190db64f513fe4e1baa59fed086ae71fa45083b6936b52d34df8f86a88"}, + {file = "regex-2020.11.13-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:5862975b45d451b6db51c2e654990c1820523a5b07100fc6903e9c86575202a0"}, + {file = "regex-2020.11.13-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:262c6825b309e6485ec2493ffc7e62a13cf13fb2a8b6d212f72bd53ad34118f1"}, + {file = "regex-2020.11.13-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:bafb01b4688833e099d79e7efd23f99172f501a15c44f21ea2118681473fdba0"}, + {file = "regex-2020.11.13-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:e32f5f3d1b1c663af7f9c4c1e72e6ffe9a78c03a31e149259f531e0fed826512"}, + {file = "regex-2020.11.13-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:3bddc701bdd1efa0d5264d2649588cbfda549b2899dc8d50417e47a82e1387ba"}, + {file = "regex-2020.11.13-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:02951b7dacb123d8ea6da44fe45ddd084aa6777d4b2454fa0da61d569c6fa538"}, + {file = "regex-2020.11.13-cp37-cp37m-win32.whl", hash = "sha256:0d08e71e70c0237883d0bef12cad5145b84c3705e9c6a588b2a9c7080e5af2a4"}, + {file = "regex-2020.11.13-cp37-cp37m-win_amd64.whl", hash = "sha256:1fa7ee9c2a0e30405e21031d07d7ba8617bc590d391adfc2b7f1e8b99f46f444"}, + {file = "regex-2020.11.13-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:baf378ba6151f6e272824b86a774326f692bc2ef4cc5ce8d5bc76e38c813a55f"}, + {file = "regex-2020.11.13-cp38-cp38-manylinux1_i686.whl", hash = "sha256:e3faaf10a0d1e8e23a9b51d1900b72e1635c2d5b0e1bea1c18022486a8e2e52d"}, + {file = "regex-2020.11.13-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:2a11a3e90bd9901d70a5b31d7dd85114755a581a5da3fc996abfefa48aee78af"}, + {file = "regex-2020.11.13-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:d1ebb090a426db66dd80df8ca85adc4abfcbad8a7c2e9a5ec7513ede522e0a8f"}, + {file = "regex-2020.11.13-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:b2b1a5ddae3677d89b686e5c625fc5547c6e492bd755b520de5332773a8af06b"}, + {file = "regex-2020.11.13-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:2c99e97d388cd0a8d30f7c514d67887d8021541b875baf09791a3baad48bb4f8"}, + {file = "regex-2020.11.13-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:c084582d4215593f2f1d28b65d2a2f3aceff8342aa85afd7be23a9cad74a0de5"}, + {file = "regex-2020.11.13-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:a3d748383762e56337c39ab35c6ed4deb88df5326f97a38946ddd19028ecce6b"}, + {file = "regex-2020.11.13-cp38-cp38-win32.whl", hash = "sha256:7913bd25f4ab274ba37bc97ad0e21c31004224ccb02765ad984eef43e04acc6c"}, + {file = "regex-2020.11.13-cp38-cp38-win_amd64.whl", hash = "sha256:6c54ce4b5d61a7129bad5c5dc279e222afd00e721bf92f9ef09e4fae28755683"}, + {file = "regex-2020.11.13-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1862a9d9194fae76a7aaf0150d5f2a8ec1da89e8b55890b1786b8f88a0f619dc"}, + {file = "regex-2020.11.13-cp39-cp39-manylinux1_i686.whl", hash = "sha256:4902e6aa086cbb224241adbc2f06235927d5cdacffb2425c73e6570e8d862364"}, + {file = "regex-2020.11.13-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:7a25fcbeae08f96a754b45bdc050e1fb94b95cab046bf56b016c25e9ab127b3e"}, + {file = "regex-2020.11.13-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:d2d8ce12b7c12c87e41123997ebaf1a5767a5be3ec545f64675388970f415e2e"}, + {file = "regex-2020.11.13-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:f7d29a6fc4760300f86ae329e3b6ca28ea9c20823df123a2ea8693e967b29917"}, + {file = "regex-2020.11.13-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:717881211f46de3ab130b58ec0908267961fadc06e44f974466d1887f865bd5b"}, + {file = "regex-2020.11.13-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:3128e30d83f2e70b0bed9b2a34e92707d0877e460b402faca908c6667092ada9"}, + {file = "regex-2020.11.13-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:8f6a2229e8ad946e36815f2a03386bb8353d4bde368fdf8ca5f0cb97264d3b5c"}, + {file = "regex-2020.11.13-cp39-cp39-win32.whl", hash = "sha256:f8f295db00ef5f8bae530fc39af0b40486ca6068733fb860b42115052206466f"}, + {file = "regex-2020.11.13-cp39-cp39-win_amd64.whl", hash = "sha256:a15f64ae3a027b64496a71ab1f722355e570c3fac5ba2801cafce846bf5af01d"}, + {file = "regex-2020.11.13.tar.gz", hash = "sha256:83d6b356e116ca119db8e7c6fc2983289d87b27b3fac238cfe5dca529d884562"}, +] +requests = [ + {file = "requests-2.25.1-py2.py3-none-any.whl", hash = "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e"}, + {file = "requests-2.25.1.tar.gz", hash = "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804"}, +] +requests-oauthlib = [ + {file = "requests-oauthlib-1.3.0.tar.gz", hash = "sha256:b4261601a71fd721a8bd6d7aa1cc1d6a8a93b4a9f5e96626f8e4d91e8beeaa6a"}, + {file = "requests_oauthlib-1.3.0-py2.py3-none-any.whl", hash = "sha256:7f71572defaecd16372f9006f33c2ec8c077c3cfa6f5911a9a90202beb513f3d"}, + {file = "requests_oauthlib-1.3.0-py3.7.egg", hash = "sha256:fa6c47b933f01060936d87ae9327fead68768b69c6c9ea2109c48be30f2d4dbc"}, +] +retrying = [ + {file = "retrying-1.3.3.tar.gz", hash = "sha256:08c039560a6da2fe4f2c426d0766e284d3b736e355f8dd24b37367b0bb41973b"}, +] +rsa = [ + {file = "rsa-4.7.2-py3-none-any.whl", hash = "sha256:78f9a9bf4e7be0c5ded4583326e7461e3a3c5aae24073648b4bdfa797d78c9d2"}, + {file = "rsa-4.7.2.tar.gz", hash = "sha256:9d689e6ca1b3038bc82bf8d23e944b6b6037bc02301a574935b2dd946e0353b9"}, +] +sacremoses = [ + {file = "sacremoses-0.0.43.tar.gz", hash = "sha256:123c1bf2664351fb05e16f87d3786dbe44a050cfd7b85161c09ad9a63a8e2948"}, +] +scikit-learn = [ + {file = "scikit-learn-0.24.1.tar.gz", hash = "sha256:a0334a1802e64d656022c3bfab56a73fbd6bf4b1298343f3688af2151810bbdf"}, + {file = "scikit_learn-0.24.1-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:9bed8a1ef133c8e2f13966a542cb8125eac7f4b67dcd234197c827ba9c7dd3e0"}, + {file = "scikit_learn-0.24.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:a36e159a0521e13bbe15ca8c8d038b3a1dd4c7dad18d276d76992e03b92cf643"}, + {file = "scikit_learn-0.24.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:c658432d8a20e95398f6bb95ff9731ce9dfa343fdf21eea7ec6a7edfacd4b4d9"}, + {file = "scikit_learn-0.24.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:9dfa564ef27e8e674aa1cc74378416d580ac4ede1136c13dd555a87996e13422"}, + {file = "scikit_learn-0.24.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:9c6097b6a9b2bafc5e0f31f659e6ab5e131383209c30c9e978c5b8abdac5ed2a"}, + {file = "scikit_learn-0.24.1-cp36-cp36m-win32.whl", hash = "sha256:7b04691eb2f41d2c68dbda8d1bd3cb4ef421bdc43aaa56aeb6c762224552dfb6"}, + {file = "scikit_learn-0.24.1-cp36-cp36m-win_amd64.whl", hash = "sha256:1adf483e91007a87171d7ce58c34b058eb5dab01b5fee6052f15841778a8ecd8"}, + {file = "scikit_learn-0.24.1-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:ddb52d088889f5596bc4d1de981f2eca106b58243b6679e4782f3ba5096fd645"}, + {file = "scikit_learn-0.24.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:a29460499c1e62b7a830bb57ca42e615375a6ab1bcad053cd25b493588348ea8"}, + {file = "scikit_learn-0.24.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:0567a2d29ad08af98653300c623bd8477b448fe66ced7198bef4ed195925f082"}, + {file = "scikit_learn-0.24.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:99349d77f54e11f962d608d94dfda08f0c9e5720d97132233ebdf35be2858b2d"}, + {file = "scikit_learn-0.24.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:83b21ff053b1ff1c018a2d24db6dd3ea339b1acfbaa4d9c881731f43748d8b3b"}, + {file = "scikit_learn-0.24.1-cp37-cp37m-win32.whl", hash = "sha256:c3deb3b19dd9806acf00cf0d400e84562c227723013c33abefbbc3cf906596e9"}, + {file = "scikit_learn-0.24.1-cp37-cp37m-win_amd64.whl", hash = "sha256:d54dbaadeb1425b7d6a66bf44bee2bb2b899fe3e8850b8e94cfb9c904dcb46d0"}, + {file = "scikit_learn-0.24.1-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:3c4f07f47c04e81b134424d53c3f5e16dfd7f494e44fd7584ba9ce9de2c5e6c1"}, + {file = "scikit_learn-0.24.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:c13ebac42236b1c46397162471ea1c46af68413000e28b9309f8c05722c65a09"}, + {file = "scikit_learn-0.24.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:4ddd2b6f7449a5d539ff754fa92d75da22de261fd8fdcfb3596799fadf255101"}, + {file = "scikit_learn-0.24.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:826b92bf45b8ad80444814e5f4ac032156dd481e48d7da33d611f8fe96d5f08b"}, + {file = "scikit_learn-0.24.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:259ec35201e82e2db1ae2496f229e63f46d7f1695ae68eef9350b00dc74ba52f"}, + {file = "scikit_learn-0.24.1-cp38-cp38-win32.whl", hash = "sha256:8772b99d683be8f67fcc04789032f1b949022a0e6880ee7b75a7ec97dbbb5d0b"}, + {file = "scikit_learn-0.24.1-cp38-cp38-win_amd64.whl", hash = "sha256:ed9d65594948678827f4ff0e7ae23344e2f2b4cabbca057ccaed3118fdc392ca"}, + {file = "scikit_learn-0.24.1-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:8aa1b3ac46b80eaa552b637eeadbbce3be5931e4b5002b964698e33a1b589e1e"}, + {file = "scikit_learn-0.24.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:c7f4eb77504ac586d8ac1bde1b0c04b504487210f95297235311a0ab7edd7e38"}, + {file = "scikit_learn-0.24.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:087dfede39efb06ab30618f9ab55a0397f29c38d63cd0ab88d12b500b7d65fd7"}, + {file = "scikit_learn-0.24.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:895dbf2030aa7337649e36a83a007df3c9811396b4e2fa672a851160f36ce90c"}, + {file = "scikit_learn-0.24.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:9a24d1ccec2a34d4cd3f2a1f86409f3f5954cc23d4d2270ba0d03cf018aa4780"}, + {file = "scikit_learn-0.24.1-cp39-cp39-win32.whl", hash = "sha256:fab31f48282ebf54dd69f6663cd2d9800096bad1bb67bbc9c9ac84eb77b41972"}, + {file = "scikit_learn-0.24.1-cp39-cp39-win_amd64.whl", hash = "sha256:4562dcf4793e61c5d0f89836d07bc37521c3a1889da8f651e2c326463c4bd697"}, +] +scipy = [ + {file = "scipy-1.5.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:4f12d13ffbc16e988fa40809cbbd7a8b45bc05ff6ea0ba8e3e41f6f4db3a9e47"}, + {file = "scipy-1.5.4-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:a254b98dbcc744c723a838c03b74a8a34c0558c9ac5c86d5561703362231107d"}, + {file = "scipy-1.5.4-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:368c0f69f93186309e1b4beb8e26d51dd6f5010b79264c0f1e9ca00cd92ea8c9"}, + {file = "scipy-1.5.4-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:4598cf03136067000855d6b44d7a1f4f46994164bcd450fb2c3d481afc25dd06"}, + {file = "scipy-1.5.4-cp36-cp36m-win32.whl", hash = "sha256:e98d49a5717369d8241d6cf33ecb0ca72deee392414118198a8e5b4c35c56340"}, + {file = "scipy-1.5.4-cp36-cp36m-win_amd64.whl", hash = "sha256:65923bc3809524e46fb7eb4d6346552cbb6a1ffc41be748535aa502a2e3d3389"}, + {file = "scipy-1.5.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:9ad4fcddcbf5dc67619379782e6aeef41218a79e17979aaed01ed099876c0e62"}, + {file = "scipy-1.5.4-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:f87b39f4d69cf7d7529d7b1098cb712033b17ea7714aed831b95628f483fd012"}, + {file = "scipy-1.5.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:25b241034215247481f53355e05f9e25462682b13bd9191359075682adcd9554"}, + {file = "scipy-1.5.4-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:fa789583fc94a7689b45834453fec095245c7e69c58561dc159b5d5277057e4c"}, + {file = "scipy-1.5.4-cp37-cp37m-win32.whl", hash = "sha256:d6d25c41a009e3c6b7e757338948d0076ee1dd1770d1c09ec131f11946883c54"}, + {file = "scipy-1.5.4-cp37-cp37m-win_amd64.whl", hash = "sha256:2c872de0c69ed20fb1a9b9cf6f77298b04a26f0b8720a5457be08be254366c6e"}, + {file = "scipy-1.5.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e360cb2299028d0b0d0f65a5c5e51fc16a335f1603aa2357c25766c8dab56938"}, + {file = "scipy-1.5.4-cp38-cp38-manylinux1_i686.whl", hash = "sha256:3397c129b479846d7eaa18f999369a24322d008fac0782e7828fa567358c36ce"}, + {file = "scipy-1.5.4-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:168c45c0c32e23f613db7c9e4e780bc61982d71dcd406ead746c7c7c2f2004ce"}, + {file = "scipy-1.5.4-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:213bc59191da2f479984ad4ec39406bf949a99aba70e9237b916ce7547b6ef42"}, + {file = "scipy-1.5.4-cp38-cp38-win32.whl", hash = "sha256:634568a3018bc16a83cda28d4f7aed0d803dd5618facb36e977e53b2df868443"}, + {file = "scipy-1.5.4-cp38-cp38-win_amd64.whl", hash = "sha256:b03c4338d6d3d299e8ca494194c0ae4f611548da59e3c038813f1a43976cb437"}, + {file = "scipy-1.5.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3d5db5d815370c28d938cf9b0809dade4acf7aba57eaf7ef733bfedc9b2474c4"}, + {file = "scipy-1.5.4-cp39-cp39-manylinux1_i686.whl", hash = "sha256:6b0ceb23560f46dd236a8ad4378fc40bad1783e997604ba845e131d6c680963e"}, + {file = "scipy-1.5.4-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:ed572470af2438b526ea574ff8f05e7f39b44ac37f712105e57fc4d53a6fb660"}, + {file = "scipy-1.5.4-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:8c8d6ca19c8497344b810b0b0344f8375af5f6bb9c98bd42e33f747417ab3f57"}, + {file = "scipy-1.5.4-cp39-cp39-win32.whl", hash = "sha256:d84cadd7d7998433334c99fa55bcba0d8b4aeff0edb123b2a1dfcface538e474"}, + {file = "scipy-1.5.4-cp39-cp39-win_amd64.whl", hash = "sha256:cc1f78ebc982cd0602c9a7615d878396bec94908db67d4ecddca864d049112f2"}, + {file = "scipy-1.5.4.tar.gz", hash = "sha256:4a453d5e5689de62e5d38edf40af3f17560bfd63c9c5bd228c18c1f99afa155b"}, +] +segtok = [ + {file = "segtok-1.5.10.tar.gz", hash = "sha256:2ed6525e840a669ec7ba3be61353a4f660264aecfc726834dbe4b01eb4ef7804"}, +] +sentencepiece = [ + {file = "sentencepiece-0.1.91-cp27-cp27m-macosx_10_6_x86_64.whl", hash = "sha256:f2f109514b28326d5c6d69b43ba6b08e6fedf8fc77416b9a9c16be55c9ac138d"}, + {file = "sentencepiece-0.1.91-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:b3643634e043fd7a5914d51d7dc60003dad0af976b8496df0406a487b0b83a8e"}, + {file = "sentencepiece-0.1.91-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:21a2e9f476f0c3e45da1e5da00b7ec5241bbddb524bd7b1b3d61b1bcbc05efa6"}, + {file = "sentencepiece-0.1.91-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:30224b1f77af9cef79ffe3a40ed0e536be44df75c066f771e9e769b48379bd98"}, + {file = "sentencepiece-0.1.91-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:679fcdd01e01d990950a46a814210445f2202260d092d3b69f9826739d8aed2b"}, + {file = "sentencepiece-0.1.91-cp35-cp35m-macosx_10_6_x86_64.whl", hash = "sha256:123ac26429025b3153f8bae53d044e9dd29539e888dcb9f39a4982e6daf9dbe9"}, + {file = "sentencepiece-0.1.91-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:53f4a91c8a6b55a75caad70d9f34bf331a576e9708c549729b06412c857aacb9"}, + {file = "sentencepiece-0.1.91-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:f1c0cf36fcff4a3ea8925babc3ed7f5f3d58628e062b24f9fad92c400bc9210c"}, + {file = "sentencepiece-0.1.91-cp36-cp36m-macosx_10_6_x86_64.whl", hash = "sha256:c0b01bb8ab3b62aba76d6b0851a1d0fcf5df5ef5616f114ea85917d8ab5f59db"}, + {file = "sentencepiece-0.1.91-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:70b4164c98dba43246a068c848fab5ac9966b5bcd731ee4cb9bcf6ae976389a4"}, + {file = "sentencepiece-0.1.91-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:b858805ac3c6d92e5454a89476b1f9e0505e1511276cd258d5a70776c70374f1"}, + {file = "sentencepiece-0.1.91-cp36-cp36m-win32.whl", hash = "sha256:8bbb9173168d53165ba00172a5db7734e4826c30e6ffc4b3f8a6098713f6111d"}, + {file = "sentencepiece-0.1.91-cp36-cp36m-win_amd64.whl", hash = "sha256:51c25d504beeef4c697b8f55e2baf7c6b31733a190ff9b983a6db57faa59d3d8"}, + {file = "sentencepiece-0.1.91-cp37-cp37m-macosx_10_6_x86_64.whl", hash = "sha256:a04218f1b93b5669f3cee1dc8d6c397428e2f6af8843a20ddb2b629f6a86e632"}, + {file = "sentencepiece-0.1.91-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:7fcda06cab76136346dd279268664c65f0b66bb2147ceb97e2cec25b426e8210"}, + {file = "sentencepiece-0.1.91-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:3b4175a9d883a3b27436d51cb82794e3a62d0955bb36cc96d5d7932095c13135"}, + {file = "sentencepiece-0.1.91-cp37-cp37m-win32.whl", hash = "sha256:f0b383de68604195fe806072e7c8837eb5156455dfdb18fd26a9a94df3f57d42"}, + {file = "sentencepiece-0.1.91-cp37-cp37m-win_amd64.whl", hash = "sha256:82d819eb1e997b39424d7422aa885d2ef514f754dd2935a4f4fcfdedeee955c6"}, + {file = "sentencepiece-0.1.91-cp38-cp38-macosx_10_6_x86_64.whl", hash = "sha256:f331fd58f438d5d5476d189e9a4944c84f7e4b027533809292b9c119b58e43b8"}, + {file = "sentencepiece-0.1.91-cp38-cp38-manylinux1_i686.whl", hash = "sha256:79ad2f82b412859c516b569fb89b5e5c0ceba74d71c8d4b99cc8a2c734f3c79d"}, + {file = "sentencepiece-0.1.91-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:796726d680d6c26f0f4ff213a0f6b1ef790b02071268adf5f449739c1c903f93"}, + {file = "sentencepiece-0.1.91-cp38-cp38-win32.whl", hash = "sha256:9bdff324279359598a516de8413fd2c62bc3c9c8f569f4431829599fbe57e417"}, + {file = "sentencepiece-0.1.91-cp38-cp38-win_amd64.whl", hash = "sha256:c2a004470d388272d6c17ca160ef73d6ea1ffcddc345771d817ece5c85d85dcb"}, + {file = "sentencepiece-0.1.91.tar.gz", hash = "sha256:f9700cf607ea064d9fad34c751fbf49953dcc56fe68c54b277481aa0aec5c18f"}, +] +setuptools-git = [ + {file = "setuptools-git-1.2.tar.gz", hash = "sha256:ff64136da01aabba76ae88b050e7197918d8b2139ccbf6144e14d472b9c40445"}, + {file = "setuptools_git-1.2-py2.py3-none-any.whl", hash = "sha256:e7764dccce7d97b4b5a330d7b966aac6f9ac026385743fd6cedad553f2494cfa"}, +] +six = [ + {file = "six-1.15.0-py2.py3-none-any.whl", hash = "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"}, + {file = "six-1.15.0.tar.gz", hash = "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259"}, +] +smart-open = [ + {file = "smart_open-4.2.0.tar.gz", hash = "sha256:d9f5a0f173ccb9bbae528db5a3804f57145815774f77ef755b9b0f3b4b2a9dcb"}, +] +soupsieve = [ + {file = "soupsieve-2.2-py3-none-any.whl", hash = "sha256:d3a5ea5b350423f47d07639f74475afedad48cf41c0ad7a82ca13a3928af34f6"}, + {file = "soupsieve-2.2.tar.gz", hash = "sha256:407fa1e8eb3458d1b5614df51d9651a1180ea5fedf07feb46e45d7e25e6d6cdd"}, +] +sqlitedict = [ + {file = "sqlitedict-1.7.0.tar.gz", hash = "sha256:2affcc301aacd4da7511692601ecbde392294205af418498f7d6d3ec0dbcad56"}, +] +statsmodels = [ + {file = "statsmodels-0.12.2-cp36-cp36m-macosx_10_15_x86_64.whl", hash = "sha256:c1d98ce2072f5e772cbf91d05475490368da5d3ee4a3150062330c7b83221ceb"}, + {file = "statsmodels-0.12.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:4184487e9c281acad3d0bda19445c69db292f0dbb18f25ebf56a7966a0a28eef"}, + {file = "statsmodels-0.12.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:37e107fa11299090ed90f93c7172162b850c28fd09999937b971926813e887c5"}, + {file = "statsmodels-0.12.2-cp36-none-win32.whl", hash = "sha256:5d3e7333e1c5b234797ed57c3d1533371374c1e1e7e7ed54d27805611f96e2d5"}, + {file = "statsmodels-0.12.2-cp36-none-win_amd64.whl", hash = "sha256:aaf3c75fd22cb9dcf9c1b28f8ae87521310870f4dd8a6a4f1010f1e46d992377"}, + {file = "statsmodels-0.12.2-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:c48b7cbb37a651bb1cd23614abc10f447845ad3c3a713bf74e2aad20cfc94ae7"}, + {file = "statsmodels-0.12.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:a3bd3922463dda8ad33e5e5075d2080e9e012aeb2032b5cdaeea9b79c2472000"}, + {file = "statsmodels-0.12.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:43de84bc08c8b9f778502aed7a476d6e68674e6878718e533b07d569cf0927a9"}, + {file = "statsmodels-0.12.2-cp37-none-win32.whl", hash = "sha256:0197855aa1d40c42532d6a75b4ca72e30826a50d90ec3047a404f9702d8b814f"}, + {file = "statsmodels-0.12.2-cp37-none-win_amd64.whl", hash = "sha256:93273aa1c31caf59bcce9790ca4c3f54fdc45a37c61084d06f1ba4fbe56e7752"}, + {file = "statsmodels-0.12.2-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:3e94306d4c07e332532ea4911d1f1d1f661c79aa73f22c5bb22e6dd47b40d562"}, + {file = "statsmodels-0.12.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:f3a7622f3d0ce2fc204f43b74de4e03e42775609705bf94d656b730482ca935a"}, + {file = "statsmodels-0.12.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:587deb788e7f8f3f866d28e812cf5c082b4d4a2d3f5beea94d0e9699ea71ef22"}, + {file = "statsmodels-0.12.2-cp38-none-win32.whl", hash = "sha256:cbbdf6f708c9a1f1fad5cdea5e4342d6fdb37e42e92288c2cf906b99976ffe15"}, + {file = "statsmodels-0.12.2-cp38-none-win_amd64.whl", hash = "sha256:1fa720e895112a1b04b27002218b0ea7f10dd1d9cffd1c018c88bbfb82520f57"}, + {file = "statsmodels-0.12.2-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:c3782ce846a52862ac72f89d22b6b1ca13d877bc593872309228a6f05d934321"}, + {file = "statsmodels-0.12.2-cp39-cp39-manylinux1_i686.whl", hash = "sha256:8f93cb3f7d87c1fc7e51b3b239371c25a17a0a8e782467fdf4788cfef600724a"}, + {file = "statsmodels-0.12.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f61f33f64760a22100b6b146217823f73cfedd251c9bdbd58453ca94e63326c7"}, + {file = "statsmodels-0.12.2-cp39-none-win32.whl", hash = "sha256:3aab85174444f1bcad1e9218a3d3db08f0f86eeb97985236ca8605a0a39ce305"}, + {file = "statsmodels-0.12.2-cp39-none-win_amd64.whl", hash = "sha256:94d3632d56c13eebebaefb52bd4b43144ad5a131337b57842f46db826fa7d2d3"}, + {file = "statsmodels-0.12.2.tar.gz", hash = "sha256:8ad7a7ae7cdd929095684118e3b05836c0ccb08b6a01fe984159475d174a1b10"}, +] +tabulate = [ + {file = "tabulate-0.8.9-py3-none-any.whl", hash = "sha256:d7c013fe7abbc5e491394e10fa845f8f32fe54f8dc60c6622c6cf482d25d47e4"}, + {file = "tabulate-0.8.9.tar.gz", hash = "sha256:eb1d13f25760052e8931f2ef80aaf6045a6cceb47514db8beab24cded16f13a7"}, +] +tensorboard = [ + {file = "tensorboard-2.4.1-py3-none-any.whl", hash = "sha256:7b8c53c396069b618f6f276ec94fc45d17e3282d668979216e5d30be472115e4"}, +] +tensorboard-plugin-wit = [ + {file = "tensorboard_plugin_wit-1.8.0-py3-none-any.whl", hash = "sha256:2a80d1c551d741e99b2f197bb915d8a133e24adb8da1732b840041860f91183a"}, +] +tensorflow = [ + {file = "tensorflow-2.4.1-cp36-cp36m-macosx_10_11_x86_64.whl", hash = "sha256:e1f2799cc86861680d8515167f103e2207a8cab92a4afe5471e4839330591f08"}, + {file = "tensorflow-2.4.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:55368ba0bedb513ba0e36a2543a588b5276e9b2ca99fa3232a9a176601a7bab5"}, + {file = "tensorflow-2.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:0e427b1350be6dbe572f971947c5596fdbb152081f227808d8becd894bf40282"}, + {file = "tensorflow-2.4.1-cp37-cp37m-macosx_10_11_x86_64.whl", hash = "sha256:36d5acd60aac48e34bd545d0ce1fb8b3fceebff6b8782436defd0f71c12203bd"}, + {file = "tensorflow-2.4.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:22723b8e1fa83b34f56c349b16a57aaff913b404451fcf70981f2b1d6e0c64fc"}, + {file = "tensorflow-2.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:2357112319303da1b5459a621fd0503c2b2cd97b6c33c4903abd46b3c3e380e2"}, + {file = "tensorflow-2.4.1-cp38-cp38-macosx_10_11_x86_64.whl", hash = "sha256:4a04081647b89a8fb602895b29ffc559e3c20aac8bde1d4c5ecd2a65adce5d35"}, + {file = "tensorflow-2.4.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:efa9daa4b3701a4e439b24b74c1e4b66844aee8ae5263fb3cc12281ac9cc9f67"}, + {file = "tensorflow-2.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:eedcf578afde5e6e69c75d796bed41093451cd1ab54afb438760e40fb74a09de"}, +] +tensorflow-estimator = [ + {file = "tensorflow_estimator-2.4.0-py2.py3-none-any.whl", hash = "sha256:5b7b7bf2debe19a8794adacc43e8ba6459daa4efaf54d3302623994a359b17f0"}, +] +termcolor = [ + {file = "termcolor-1.1.0.tar.gz", hash = "sha256:1d6d69ce66211143803fbc56652b41d73b4a400a2891d7bf7a1cdf4c02de613b"}, +] +threadpoolctl = [ + {file = "threadpoolctl-2.1.0-py3-none-any.whl", hash = "sha256:38b74ca20ff3bb42caca8b00055111d74159ee95c4370882bbff2b93d24da725"}, + {file = "threadpoolctl-2.1.0.tar.gz", hash = "sha256:ddc57c96a38beb63db45d6c159b5ab07b6bced12c45a1f07b2b92f272aebfa6b"}, +] +TimeSeriesCrossValidation = [] +tokenizers = [ + {file = "tokenizers-0.9.3-cp35-cp35m-macosx_10_11_x86_64.whl", hash = "sha256:ea1db6a8ebdf29f0487212c35357574c70f72c7c311406603fabeaa44cc94a12"}, + {file = "tokenizers-0.9.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:be639a8933206dfd6e1cab26683ce020c03c6a3757d4a1dd5c8854d2bbed09ae"}, + {file = "tokenizers-0.9.3-cp35-cp35m-win32.whl", hash = "sha256:5b35be31ca999f9fb4732d947fa629104a29af3633e73cf8311cb69948f80165"}, + {file = "tokenizers-0.9.3-cp35-cp35m-win_amd64.whl", hash = "sha256:e2d709d028fe87dc305c767acca2da0425029fa0ae2135a2139ead7de62bc276"}, + {file = "tokenizers-0.9.3-cp36-cp36m-macosx_10_11_x86_64.whl", hash = "sha256:f71161ed25ab649e9291139f7ce6a28cd520de5de9246e2907a19a6f329b9105"}, + {file = "tokenizers-0.9.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:219dafb24d26a10bd4162372901ac886254e1c6bf6510dde85df282469231eaf"}, + {file = "tokenizers-0.9.3-cp36-cp36m-win32.whl", hash = "sha256:424d8ab61b0b0afadf4d88beded036cb801e3a4ddba6804621568cefd5ddb317"}, + {file = "tokenizers-0.9.3-cp36-cp36m-win_amd64.whl", hash = "sha256:ef6208dfdd2536566d0eee06a03da1a74b9c9246ef5c4a213d5afd00f51d0976"}, + {file = "tokenizers-0.9.3-cp37-cp37m-macosx_10_11_x86_64.whl", hash = "sha256:0f30e6a9ea56cc8d999b17142f121ddb24b005b9fce936e7df47cdff1f55edcc"}, + {file = "tokenizers-0.9.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:2d875e019e39bce56c35a126ef4338345d97bf5e53730c68d0f7128a05c3d6c0"}, + {file = "tokenizers-0.9.3-cp37-cp37m-win32.whl", hash = "sha256:b9c5c304bfdba4e703f8828bf4c57d3d65b3c77d2732f5ec81044abe8287f2de"}, + {file = "tokenizers-0.9.3-cp37-cp37m-win_amd64.whl", hash = "sha256:3f199b1042d56837b5764c212874510f8eab7702d7486fdb626432465717e4f7"}, + {file = "tokenizers-0.9.3-cp38-cp38-macosx_10_11_x86_64.whl", hash = "sha256:a8c197a0d8f8b91cc220315e1617b942d992ae70bade504838b70e49bf5e4454"}, + {file = "tokenizers-0.9.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:27ec3543e6e5701586804b1536cf687d44f8167871bd84ab01e5700cbfa969ec"}, + {file = "tokenizers-0.9.3-cp38-cp38-win32.whl", hash = "sha256:e76f84123695ccfaef734912369edbcb8ed71723196987ffd086e07d00c9d73a"}, + {file = "tokenizers-0.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:3100ed9051558a3b2a9c2b7dda6880328a7c4c0736be72d279b0029339d55789"}, + {file = "tokenizers-0.9.3.tar.gz", hash = "sha256:bacaeb3621055aba9b5158a21dc8b5d80f65724ff47f414f9d06f1e087668d61"}, +] +torch = [ + {file = "torch-1.7.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:422e64e98d0e100c360993819d0307e5d56e9517b26135808ad68984d577d75a"}, + {file = "torch-1.7.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f0aaf657145533824b15f2fd8fde8f8c67fe6c6281088ef588091f03fad90243"}, + {file = "torch-1.7.1-cp36-none-macosx_10_9_x86_64.whl", hash = "sha256:af464a6f4314a875035e0c4c2b07517599704b214634f4ed3ad2e748c5ef291f"}, + {file = "torch-1.7.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:5d76c255a41484c1d41a9ff570b9c9f36cb85df9428aa15a58ae16ac7cfc2ea6"}, + {file = "torch-1.7.1-cp37-cp37m-win_amd64.whl", hash = "sha256:d241c3f1c4d563e4ba86f84769c23e12606db167ee6f674eedff6d02901462e3"}, + {file = "torch-1.7.1-cp37-none-macosx_10_9_x86_64.whl", hash = "sha256:de84b4166e3f7335eb868b51d3bbd909ec33828af27290b4171bce832a55be3c"}, + {file = "torch-1.7.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:dd2fc6880c95e836960d86efbbc7f63d3287f2e1893c51d31f96dbfe02f0d73e"}, + {file = "torch-1.7.1-cp38-cp38-win_amd64.whl", hash = "sha256:e000b94be3aa58ad7f61e7d07cf379ea9366cf6c6874e68bd58ad0bdc537b3a7"}, + {file = "torch-1.7.1-cp38-none-macosx_10_9_x86_64.whl", hash = "sha256:2e49cac969976be63117004ee00d0a3e3dd4ea662ad77383f671b8992825de1a"}, + {file = "torch-1.7.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:a3793dcceb12b1e2281290cca1277c5ce86ddfd5bf044f654285a4d69057aea7"}, + {file = "torch-1.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:6652a767a0572ae0feb74ad128758e507afd3b8396b6e7f147e438ba8d4c6f63"}, + {file = "torch-1.7.1-cp39-none-macosx_10_9_x86_64.whl", hash = "sha256:38d67f4fb189a92a977b2c0a38e4f6dd413e0bf55aa6d40004696df7e40a71ff"}, +] +tqdm = [ + {file = "tqdm-4.58.0-py2.py3-none-any.whl", hash = "sha256:2c44efa73b8914dba7807aefd09653ac63c22b5b4ea34f7a80973f418f1a3089"}, + {file = "tqdm-4.58.0.tar.gz", hash = "sha256:c23ac707e8e8aabb825e4d91f8e17247f9cc14b0d64dd9e97be0781e9e525bba"}, +] +transformers = [ + {file = "transformers-3.5.1-py3-none-any.whl", hash = "sha256:cefb06c8892e0ce2de1bfc782d2c49af020960ebada8340317306ff606190341"}, + {file = "transformers-3.5.1.tar.gz", hash = "sha256:0d637c6cecc13b12f33f9e79bf5757c85f433c851e3ae7845ff20b6c49f41441"}, +] +typing-extensions = [ + {file = "typing_extensions-3.7.4.3-py2-none-any.whl", hash = "sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f"}, + {file = "typing_extensions-3.7.4.3-py3-none-any.whl", hash = "sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918"}, + {file = "typing_extensions-3.7.4.3.tar.gz", hash = "sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c"}, +] +update-checker = [ + {file = "update_checker-0.18.0-py3-none-any.whl", hash = "sha256:cbba64760a36fe2640d80d85306e8fe82b6816659190993b7bdabadee4d4bbfd"}, + {file = "update_checker-0.18.0.tar.gz", hash = "sha256:6a2d45bb4ac585884a6b03f9eade9161cedd9e8111545141e9aa9058932acb13"}, +] +urllib3 = [ + {file = "urllib3-1.26.3-py2.py3-none-any.whl", hash = "sha256:1b465e494e3e0d8939b50680403e3aedaa2bc434b7d5af64dfd3c958d7f5ae80"}, + {file = "urllib3-1.26.3.tar.gz", hash = "sha256:de3eedaad74a2683334e282005cd8d7f22f4d55fa690a2a1020a416cb0a47e73"}, +] +user-agent = [ + {file = "user_agent-0.1.9.tar.gz", hash = "sha256:8f1ad46cc4aef9f99515ea1c74bb8cacc43e23074c335b2ba2db7735ebe9c0d5"}, +] +wcwidth = [ + {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, + {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"}, +] +websocket-client = [ + {file = "websocket_client-0.57.0-py2.py3-none-any.whl", hash = "sha256:0fc45c961324d79c781bab301359d5a1b00b13ad1b10415a4780229ef71a5549"}, + {file = "websocket_client-0.57.0.tar.gz", hash = "sha256:d735b91d6d1692a6a181f2a8c9e0238e5f6373356f561bb9dc4c7af36f452010"}, +] +werkzeug = [ + {file = "Werkzeug-1.0.1-py2.py3-none-any.whl", hash = "sha256:2de2a5db0baeae7b2d2664949077c2ac63fbd16d98da0ff71837f7d1dea3fd43"}, + {file = "Werkzeug-1.0.1.tar.gz", hash = "sha256:6c80b1e5ad3665290ea39320b91e1be1e0d5f60652b964a3070216de83d2e47c"}, +] +wrapt = [ + {file = "wrapt-1.12.1.tar.gz", hash = "sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7"}, +] +yarl = [ + {file = "yarl-1.6.3-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:0355a701b3998dcd832d0dc47cc5dedf3874f966ac7f870e0f3a6788d802d434"}, + {file = "yarl-1.6.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:bafb450deef6861815ed579c7a6113a879a6ef58aed4c3a4be54400ae8871478"}, + {file = "yarl-1.6.3-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:547f7665ad50fa8563150ed079f8e805e63dd85def6674c97efd78eed6c224a6"}, + {file = "yarl-1.6.3-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:63f90b20ca654b3ecc7a8d62c03ffa46999595f0167d6450fa8383bab252987e"}, + {file = "yarl-1.6.3-cp36-cp36m-manylinux2014_ppc64le.whl", hash = "sha256:97b5bdc450d63c3ba30a127d018b866ea94e65655efaf889ebeabc20f7d12406"}, + {file = "yarl-1.6.3-cp36-cp36m-manylinux2014_s390x.whl", hash = "sha256:d8d07d102f17b68966e2de0e07bfd6e139c7c02ef06d3a0f8d2f0f055e13bb76"}, + {file = "yarl-1.6.3-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:15263c3b0b47968c1d90daa89f21fcc889bb4b1aac5555580d74565de6836366"}, + {file = "yarl-1.6.3-cp36-cp36m-win32.whl", hash = "sha256:b5dfc9a40c198334f4f3f55880ecf910adebdcb2a0b9a9c23c9345faa9185721"}, + {file = "yarl-1.6.3-cp36-cp36m-win_amd64.whl", hash = "sha256:b2e9a456c121e26d13c29251f8267541bd75e6a1ccf9e859179701c36a078643"}, + {file = "yarl-1.6.3-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:ce3beb46a72d9f2190f9e1027886bfc513702d748047b548b05dab7dfb584d2e"}, + {file = "yarl-1.6.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:2ce4c621d21326a4a5500c25031e102af589edb50c09b321049e388b3934eec3"}, + {file = "yarl-1.6.3-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:d26608cf178efb8faa5ff0f2d2e77c208f471c5a3709e577a7b3fd0445703ac8"}, + {file = "yarl-1.6.3-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:4c5bcfc3ed226bf6419f7a33982fb4b8ec2e45785a0561eb99274ebbf09fdd6a"}, + {file = "yarl-1.6.3-cp37-cp37m-manylinux2014_ppc64le.whl", hash = "sha256:4736eaee5626db8d9cda9eb5282028cc834e2aeb194e0d8b50217d707e98bb5c"}, + {file = "yarl-1.6.3-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:68dc568889b1c13f1e4745c96b931cc94fdd0defe92a72c2b8ce01091b22e35f"}, + {file = "yarl-1.6.3-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:7356644cbed76119d0b6bd32ffba704d30d747e0c217109d7979a7bc36c4d970"}, + {file = "yarl-1.6.3-cp37-cp37m-win32.whl", hash = "sha256:00d7ad91b6583602eb9c1d085a2cf281ada267e9a197e8b7cae487dadbfa293e"}, + {file = "yarl-1.6.3-cp37-cp37m-win_amd64.whl", hash = "sha256:69ee97c71fee1f63d04c945f56d5d726483c4762845400a6795a3b75d56b6c50"}, + {file = "yarl-1.6.3-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:e46fba844f4895b36f4c398c5af062a9808d1f26b2999c58909517384d5deda2"}, + {file = "yarl-1.6.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:31ede6e8c4329fb81c86706ba8f6bf661a924b53ba191b27aa5fcee5714d18ec"}, + {file = "yarl-1.6.3-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:fcbb48a93e8699eae920f8d92f7160c03567b421bc17362a9ffbbd706a816f71"}, + {file = "yarl-1.6.3-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:72a660bdd24497e3e84f5519e57a9ee9220b6f3ac4d45056961bf22838ce20cc"}, + {file = "yarl-1.6.3-cp38-cp38-manylinux2014_ppc64le.whl", hash = "sha256:324ba3d3c6fee56e2e0b0d09bf5c73824b9f08234339d2b788af65e60040c959"}, + {file = "yarl-1.6.3-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:e6b5460dc5ad42ad2b36cca524491dfcaffbfd9c8df50508bddc354e787b8dc2"}, + {file = "yarl-1.6.3-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:6d6283d8e0631b617edf0fd726353cb76630b83a089a40933043894e7f6721e2"}, + {file = "yarl-1.6.3-cp38-cp38-win32.whl", hash = "sha256:9ede61b0854e267fd565e7527e2f2eb3ef8858b301319be0604177690e1a3896"}, + {file = "yarl-1.6.3-cp38-cp38-win_amd64.whl", hash = "sha256:f0b059678fd549c66b89bed03efcabb009075bd131c248ecdf087bdb6faba24a"}, + {file = "yarl-1.6.3-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:329412812ecfc94a57cd37c9d547579510a9e83c516bc069470db5f75684629e"}, + {file = "yarl-1.6.3-cp39-cp39-manylinux1_i686.whl", hash = "sha256:c49ff66d479d38ab863c50f7bb27dee97c6627c5fe60697de15529da9c3de724"}, + {file = "yarl-1.6.3-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f040bcc6725c821a4c0665f3aa96a4d0805a7aaf2caf266d256b8ed71b9f041c"}, + {file = "yarl-1.6.3-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:d5c32c82990e4ac4d8150fd7652b972216b204de4e83a122546dce571c1bdf25"}, + {file = "yarl-1.6.3-cp39-cp39-manylinux2014_ppc64le.whl", hash = "sha256:d597767fcd2c3dc49d6eea360c458b65643d1e4dbed91361cf5e36e53c1f8c96"}, + {file = "yarl-1.6.3-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:8aa3decd5e0e852dc68335abf5478a518b41bf2ab2f330fe44916399efedfae0"}, + {file = "yarl-1.6.3-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:73494d5b71099ae8cb8754f1df131c11d433b387efab7b51849e7e1e851f07a4"}, + {file = "yarl-1.6.3-cp39-cp39-win32.whl", hash = "sha256:5b883e458058f8d6099e4420f0cc2567989032b5f34b271c0827de9f1079a424"}, + {file = "yarl-1.6.3-cp39-cp39-win_amd64.whl", hash = "sha256:4953fb0b4fdb7e08b2f3b3be80a00d28c5c8a2056bb066169de00e6501b986b6"}, + {file = "yarl-1.6.3.tar.gz", hash = "sha256:8a9066529240171b68893d60dca86a763eae2139dd42f42106b03cf4b426bf10"}, +] +yfinance = [ + {file = "yfinance-0.1.55.tar.gz", hash = "sha256:65d39bccf16bef35f6a08bf0df33650c0515b5ce8ea3c53924601f5fe00590cb"}, +] +zipp = [ + {file = "zipp-3.4.0-py3-none-any.whl", hash = "sha256:102c24ef8f171fd729d46599845e95c7ab894a4cf45f5de11a44cc7444fb1108"}, + {file = "zipp-3.4.0.tar.gz", hash = "sha256:ed5eee1974372595f9e416cc7bbeeb12335201d8081ca8a0743c954d4446e5cb"}, +] diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000000..88f04bc9bd2 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,37 @@ +[tool.poetry] +name = "GamestonkTerminal" +version = "0.1.0" +description = "" +authors = ["Didier Rodrigues Lopes"] + +[tool.poetry.dependencies] +python = "3.6.13" +fbprophet = "0.6" +pandas = "1.1.5" +iso8601 = "0.1.14" +FundamentalAnalysis = "0.2.6" +requests = "2.25.1" +alpha-vantage = "2.3.1" +finviz = "1.3.4" +bs4 = "0.0.1" +rapidfuzz = "1.1.1" +yfinance = "0.1.55" +pandas-ta = "0.2.23b0" +dataclasses = "0.8" +prettytable = "2.0.0" +psaw = "0.0.12" +praw = "7.1.4" +Quandl = "3.6.0" +flair = "0.7" +pytrends = "4.7.3" +TimeSeriesCrossValidation = { git = "https://github.com/DidierRLopes/TimeSeriesCrossValidation.git", branch = "master" } +pmdarima = "1.8.0" +tensorflow = "2.4.1" +matplotlib = "3.3.3" +plotly = "4.14.3" + +[tool.poetry.dev-dependencies] + +[build-system] +requires = ["poetry-core>=1.0.0"] +build-backend = "poetry.core.masonry.api" From c2ed0e3acf7a8ba40641bc153f6a6c5a1b587af2 Mon Sep 17 00:00:00 2001 From: Didier Lopes Date: Sun, 28 Feb 2021 15:55:15 +0000 Subject: [PATCH 28/72] Improve requirements to necessary packages only --- requirements.txt | 231 +++++++++++++++++++++++------------------------ 1 file changed, 115 insertions(+), 116 deletions(-) diff --git a/requirements.txt b/requirements.txt index c2c3f140e7a..3545df2ed43 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,130 +1,129 @@ -absl-py==0.11.0 -aiohttp==3.7.3 +absl-py==0.11.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.2.0" +aiohttp==3.7.4; python_version >= "3.6" alpha-vantage==2.3.1 -appscript==1.1.2 astunparse==1.6.3 -async-timeout==3.0.1 -attrs==20.3.0 +async-timeout==3.0.1; python_full_version >= "3.5.3" and python_version >= "3.6" +attrs==20.3.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" beautifulsoup4==4.9.3 -bpemb==0.3.2 -cachetools==4.2.1 -certifi==2020.12.5 -chardet==3.0.4 -click==7.1.2 -cloudpickle==1.6.0 -config==0.5.0.post0 -convertdate==2.3.1 -cssselect==1.1.0 -cycler==0.10.0 -Cython==0.29.17 -decorator==4.4.2 -Deprecated==1.2.11 -filelock==3.0.12 +bpemb==0.3.2; python_version >= "3.6" +bs4==0.0.1 +cachetools==4.2.1; python_version >= "3.5" and python_version < "4.0" and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0") +certifi==2020.12.5; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" +chardet==3.0.4; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" +click==7.1.2; python_full_version >= "3.6.0" and python_version >= "3.6" +cloudpickle==1.6.0; python_version >= "3.6" +cmdstanpy==0.4.0 +convertdate==2.3.1; python_version >= "3.5" +cssselect==1.1.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" +cycler==0.10.0; python_version >= "3.6" +cython==0.29.17; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.6" +dataclasses==0.8; python_version >= "3.6" and python_version < "3.7" +decorator==4.4.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.2.0" and python_version >= "3.6" +deprecated==1.2.11; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" +ephem==3.7.7.1; python_version >= "2.7" and python_version < "4" +fbprophet==0.6 +filelock==3.0.12; python_full_version >= "3.6.0" and python_version >= "3.6" finviz==1.3.4 -flair==0.7 +flair==0.7; python_version >= "3.6" flatbuffers==1.12 -ftfy==5.9 -FundamentalAnalysis==0.2.6 -future==0.18.2 -fuzzywuzzy==0.18.0 -gast==0.3.3 -gdown==3.12.2 -gensim==3.8.3 -google-auth==1.27.0 -google-auth-oauthlib==0.4.2 +ftfy==5.9; python_version >= "3.6" +fundamentalanalysis==0.2.6 +future==0.18.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.6" +gast==0.3.3; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" +gdown==3.12.2; python_version >= "3.6" +gensim==3.8.2; python_version >= "3.6" +google-auth-oauthlib==0.4.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.2.0" and python_version >= "3.6" +google-auth==1.27.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" google-pasta==0.2.0 -grpcio==1.32.0 +grpcio==1.32.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.2.0" h5py==2.10.0 -hijri-converter==2.1.1 +hijri-converter==2.1.1; python_version >= "3.6" holidays==0.10.5.2 -hyperopt==0.2.5 -idna==2.10 -importlib-metadata==3.7.0 -inflection==0.5.1 +hyperopt==0.2.5; python_version >= "3.6" +idna-ssl==1.1.0; python_version < "3.7" and python_version >= "3.6" +idna==2.10; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "3.7" or python_version < "3.7" and python_version >= "3.6" and python_full_version >= "3.5.0" +importlib-metadata==3.7.0; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "3.8" or python_full_version >= "3.2.0" and python_version >= "3.6" and python_version < "3.8" +inflection==0.5.1; python_version >= "3.5" iso8601==0.1.14 -Janome==0.4.1 -joblib==1.0.1 -Keras-Preprocessing==1.1.2 -kiwisolver==1.3.1 -konoha==4.6.2 +janome==0.4.1; python_version >= "3.6" +joblib==1.0.1; python_full_version >= "3.6.0" and python_version >= "3.6" +keras-preprocessing==1.1.2 +kiwisolver==1.3.1; python_version >= "3.6" +konoha==4.6.2; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.6" korean-lunar-calendar==0.2.1 -langdetect==1.0.8 -lxml==4.6.2 -Markdown==3.3.4 -matplotlib==3.1.1 -more-itertools==8.7.0 -mpld3==0.3 -multidict==5.1.0 +langdetect==1.0.8; python_version >= "3.6" +lunarcalendar==0.0.9; python_version >= "2.7" and python_version < "4" +lxml==4.6.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" +markdown==3.3.4; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.2.0" and python_version >= "3.6" +matplotlib==3.3.3; python_version >= "3.6" +more-itertools==8.7.0; python_version >= "3.5" +mpld3==0.3; python_version >= "3.6" +multidict==5.1.0; python_version >= "3.6" multitasking==0.0.9 -networkx==2.5 -numpy==1.19.2 -oauthlib==3.1.0 -opt-einsum==3.3.0 -overrides==3.0.0 -packaging==20.9 -pandas==1.1.5 -pandas-ta==0.2.23b0 -patsy==0.5.1 -pmdarima==1.8.0 -praw==7.1.4 -prawcore==1.5.0 -prettytable==2.0.0 -protobuf==3.15.2 -psaw==0.0.12 -psutil==5.8.0 -pyasn1==0.4.8 -pyasn1-modules==0.2.8 -PyMeeus==0.4.2 -pyparsing==2.4.7 -PySocks==1.7.1 -python-dateutil==2.8.1 +networkx==2.5; python_version >= "3.6" +numpy==1.19.5; python_version >= "3.6" and python_full_version >= "3.6.2" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.2.0" and python_version >= "3.6") +oauthlib==3.1.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" +opt-einsum==3.3.0; python_version >= "3.5" +overrides==3.0.0; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.6" +packaging==20.9; python_full_version >= "3.6.0" and python_version >= "3.6" +pandas-ta==0.2.23b +pandas==1.1.5; python_full_version >= "3.6.1" +patsy==0.5.1; python_version >= "3.6" +pillow==8.1.0; python_version >= "3.6" +plotly==4.14.3 +pmdarima==1.8.0; python_version >= "3.6" +praw==7.1.4; python_version >= "3.6" and python_version < "4.0" +prawcore==1.5.0; python_version >= "3.6" and python_version < "4.0" +prettytable==2.0.0; python_version >= "3.6" +protobuf==3.15.3; python_full_version >= "3.6.0" and python_version >= "3.6" and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.2.0") +psaw==0.0.12; python_version >= "3" +pyasn1-modules==0.2.8; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" +pyasn1==0.4.8; python_version >= "3.5" and python_full_version < "3.0.0" and python_version < "4" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6") or python_version >= "3.5" and python_version < "4" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6") and python_full_version >= "3.6.0" +pymeeus==0.4.2; python_version >= "3.5" +pyparsing==2.4.7; python_full_version >= "3.6.0" and python_version >= "3.6" +pysocks==1.7.1; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" +pystan==2.19.1.1 +python-dateutil==2.8.1; python_full_version >= "3.6.1" and python_version >= "3.5" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.6") and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.3.0") and (python_version >= "2.7" and python_full_version < "3.0.0" and python_version < "4" or python_version >= "2.7" and python_version < "4" and python_full_version >= "3.3.0") pytrends==4.7.3 -pytz==2019.3 -Quandl==3.6.0 -regex==2020.11.13 -requests==2.25.1 -requests-oauthlib==1.3.0 -rsa==4.7.2 -sacremoses==0.0.43 -scikit-learn==0.24.1 -scipy==1.4.1 -segtok==1.5.10 -sentencepiece==0.1.91 -six==1.15.0 -smart-open==4.2.0 -soupsieve==2.2 -sqlitedict==1.7.0 -statsmodels==0.12.2 -tabulate==0.8.9 -tensorboard==2.4.1 -tensorboard-plugin-wit==1.8.0 -tensorflow==2.4.1 +pytz==2021.1; python_full_version >= "3.6.1" and python_version >= "3.5" and python_version < "4" +quandl==3.6.0; python_version >= "3.5" +rapidfuzz==1.1.1; python_version >= "2.7" +regex==2020.11.13; python_full_version >= "3.6.0" and python_version >= "3.6" +requests-oauthlib==1.3.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" +requests==2.25.1; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.5.0") +retrying==1.3.3 +rsa==4.7.2; python_version >= "3.5" and python_version < "4" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6") +sacremoses==0.0.43; python_full_version >= "3.6.0" and python_version >= "3.6" +scikit-learn==0.24.1; python_version >= "3.6" +scipy==1.5.4; python_version >= "3.6" +segtok==1.5.10; python_version >= "3.6" +sentencepiece==0.1.91; python_full_version >= "3.6.0" and python_version >= "3.6" +setuptools-git==1.2 +six==1.15.0; python_full_version >= "3.6.0" and python_version >= "3.6" and python_version < "4.0" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.6") and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0") +smart-open==4.2.0; python_version >= "3.6" +soupsieve==2.2; python_version >= "3.6" +sqlitedict==1.7.0; python_version >= "3.6" +statsmodels==0.12.2; python_version >= "3.6" +tabulate==0.8.9; python_version >= "3.6" +tensorboard-plugin-wit==1.8.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.2.0" +tensorboard==2.4.1; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.2.0" tensorflow-estimator==2.4.0 -termcolor==1.1.0 -threadpoolctl==2.1.0 -TimeSeriesCrossValidation @ git+https://github.com/DidierRLopes/TimeSeriesCrossValidation@1e29d393204abb3bde23ff3f15258ed85d3b263e -tokenizers==0.9.3 -torch==1.7.1 -tqdm==4.57.0 -transformers==3.5.1 -typing-extensions==3.7.4.3 -update-checker==0.18.0 -urllib3==1.26.3 -user-agent==0.1.9 -wcwidth==0.2.5 -websocket-client==0.57.0 -Werkzeug==1.0.1 -wrapt==1.12.1 -XlsxWriter==1.2.7 -xlwings==0.16.4 -yahoo-fin==0.8.4 -yarl==1.6.3 -yfinance==0.1.55 -beautifulsoup4==4.9.3 -FundamentalAnalysis==0.2.6 -python_dateutil==2.8.1 -scikit_learn==0.24.1 tensorflow==2.4.1 -zipp==3.4.0 -lunarcalendar -fbprophet +termcolor==1.1.0 +threadpoolctl==2.1.0; python_version >= "3.6" +timeseriescrossvalidation @ git+https://github.com/DidierRLopes/TimeSeriesCrossValidation.git@master +tokenizers==0.9.3; python_full_version >= "3.6.0" and python_version >= "3.6" +torch==1.7.1; python_full_version >= "3.6.2" and python_version >= "3.6" +tqdm==4.58.0; python_full_version >= "3.6.0" and python_version >= "3.6" +transformers==3.5.1; python_full_version >= "3.6.0" and python_version >= "3.6" +typing-extensions==3.7.4.3; python_full_version >= "3.6.2" and python_version >= "3.6" and python_version < "3.8" and (python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "3.8" or python_full_version >= "3.2.0" and python_version >= "3.6" and python_version < "3.8") +update-checker==0.18.0; python_version >= "3.6" and python_version < "4.0" +urllib3==1.26.3; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version < "4" and python_version >= "3.6" +user-agent==0.1.9 +wcwidth==0.2.5; python_version >= "3.6" +websocket-client==0.57.0; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.6" and python_version < "4.0" and python_full_version >= "3.4.0" +werkzeug==1.0.1; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" +wrapt==1.12.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" +yarl==1.6.3; python_version >= "3.6" +yfinance==0.1.55 +zipp==3.4.0; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "3.8" or python_full_version >= "3.2.0" and python_version >= "3.6" and python_version < "3.8" From e7a51638e06652972b6e8941a30773261704434d Mon Sep 17 00:00:00 2001 From: Didier Lopes Date: Sun, 28 Feb 2021 15:56:11 +0000 Subject: [PATCH 29/72] #36 replace fuzzywuzzy by rapidfuzz, avoid merge conflicts --- due_diligence/business_insider_api.py | 2 +- fundamental_analysis/business_insider_api.py | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/due_diligence/business_insider_api.py b/due_diligence/business_insider_api.py index 204cd22a19e..ed370ac832c 100644 --- a/due_diligence/business_insider_api.py +++ b/due_diligence/business_insider_api.py @@ -8,7 +8,7 @@ import json import config_terminal as cfg from datetime import datetime import argparse -from fuzzywuzzy import fuzz +from rapidfuzz import fuzz import matplotlib.pyplot as plt from pandas.plotting import register_matplotlib_converters register_matplotlib_converters() diff --git a/fundamental_analysis/business_insider_api.py b/fundamental_analysis/business_insider_api.py index 967f9e9d8a0..5c3cfc9402a 100644 --- a/fundamental_analysis/business_insider_api.py +++ b/fundamental_analysis/business_insider_api.py @@ -6,15 +6,15 @@ import json import config_terminal as cfg from datetime import datetime import argparse -from fuzzywuzzy import fuzz +from rapidfuzz import fuzz # ---------------------------------------------------- MANAGEMENT ---------------------------------------------------- def management(l_args, s_ticker): - parser = argparse.ArgumentParser(prog='mgmt', - description="""Print management team. Namely: Name, Title, Information from google and + parser = argparse.ArgumentParser(prog='mgmt', + description="""Print management team. Namely: Name, Title, Information from google and (potentially) Insider Activity page. [Source: Business Insider]""") - + try: (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) @@ -33,7 +33,7 @@ def management(l_args, s_ticker): l_names = list() for s_name in text_soup_market_business_insider.findAll('td', {'class': 'table__td table--allow-wrap'}): l_names.append(s_name.text.strip()) - + df_management = pd.DataFrame({'Name': l_names[-len(l_titles):], 'Title':l_titles}, columns=['Name','Title']) df_management['Info'] = '-' @@ -57,7 +57,7 @@ def management(l_args, s_ticker): if df_management['Insider Activity'][ind] not in '-': print(f"{df_management['Insider Activity'][ind]}") print("") - + except: print("") return From f7e6709cbd9dd8f83f9a645c1e6c2d47112c3d68 Mon Sep 17 00:00:00 2001 From: Sabuj Pattanayek Date: Sun, 28 Feb 2021 09:48:18 -0800 Subject: [PATCH 30/72] it can load btcusd, add crypto It seems you can load -t btcusd -s 2017-10-01 so mention crypto in the readme. Also you don't need an alpha vantage key to get the daily OHLC values (for now at least) so also mention that below the key section --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7008d704dc4..b8783be6fed 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ## About -Gamestonk Terminal is an awesome stock market terminal that has been developed for fun, while I saw my GME shares tanking. But hey, I like the stock 💎🙌. +Gamestonk Terminal is an awesome stock and crypto market terminal that has been developed for fun, while I saw my GME shares tanking. But hey, I like the stock 💎🙌. The implementation (in python) allows to easily add more commands, and expand on their configuration. @@ -235,6 +235,8 @@ When these are obtained, don't forget to update [config_terminal.py](/config_ter * GT_API_TWITTER_SECRET_KEY * GT_API_TWITTER_BEARER_TOKEN. +Note that it is not necessary to have a valid Alpha Vantage key to get daily OHLC values. + ## Disclaimer "A few things I am not. I am not a cat. I am not an institutional investor, nor am I a hedge fund. I do not have clients and I do not provide personalized investment advice for fees or commissions." DFV From 0000718b512a3db89c6196a31ec2935c025975a6 Mon Sep 17 00:00:00 2001 From: Levi Blaney Date: Sun, 28 Feb 2021 13:21:32 -0500 Subject: [PATCH 31/72] setup poetry to work with python 3.6.8 --- poetry.lock | 10 +++++----- pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index 25f56de7e4d..367880b0032 100644 --- a/poetry.lock +++ b/poetry.lock @@ -402,9 +402,9 @@ smart-open = ">=1.8.1" [package.extras] distributed = ["Pyro4 (>=4.27)"] -docs = ["pytest", "pytest-rerunfailures", "mock", "cython", "testfixtures", "Morfessor (==2.0.2a4)", "python-Levenshtein (>=0.10.2)", "visdom (>0.1.8.7)", "scikit-learn", "Pyro4 (>=4.27)", "sphinx", "sphinxcontrib-napoleon", "plotly", "pattern (<=2.6)", "sphinxcontrib.programoutput"] -test = ["pytest", "pytest-rerunfailures", "mock", "cython", "testfixtures", "Morfessor (==2.0.2a4)", "python-Levenshtein (>=0.10.2)", "visdom (>0.1.8.7)", "scikit-learn"] -test-win = ["pytest", "pytest-rerunfailures", "mock", "cython", "testfixtures", "Morfessor (==2.0.2a4)", "python-Levenshtein (>=0.10.2)", "visdom (>0.1.8.7)", "scikit-learn"] +docs = ["pytest", "pytest-rerunfailures", "mock", "cython", "testfixtures", "Morfessor (==2.0.2a4)", "python-Levenshtein (>=0.10.2)", "visdom (>=0.1.8,!=0.1.8.7)", "scikit-learn", "Pyro4 (>=4.27)", "sphinx", "sphinxcontrib-napoleon", "plotly", "pattern (<=2.6)", "sphinxcontrib.programoutput"] +test = ["pytest", "pytest-rerunfailures", "mock", "cython", "testfixtures", "Morfessor (==2.0.2a4)", "python-Levenshtein (>=0.10.2)", "visdom (>=0.1.8,!=0.1.8.7)", "scikit-learn"] +test-win = ["pytest", "pytest-rerunfailures", "mock", "cython", "testfixtures", "Morfessor (==2.0.2a4)", "python-Levenshtein (>=0.10.2)", "visdom (>=0.1.8,!=0.1.8.7)", "scikit-learn"] [[package]] name = "google-auth" @@ -1603,8 +1603,8 @@ testing = ["pytest (>=3.5,!=3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake [metadata] lock-version = "1.1" -python-versions = "3.6.13" -content-hash = "93086c15c0e3a2cb06ea26b57f4af5e3b20128492e916eefba79c8d7f28350b4" +python-versions = "~3.6.8" +content-hash = "8eb522fff7107ad0fc1c444f5932434da119093b35e283e6a43e7b6bb8fb8b17" [metadata.files] absl-py = [ diff --git a/pyproject.toml b/pyproject.toml index 88f04bc9bd2..a486e8a20ca 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ description = "" authors = ["Didier Rodrigues Lopes"] [tool.poetry.dependencies] -python = "3.6.13" +python = "~3.6.8" fbprophet = "0.6" pandas = "1.1.5" iso8601 = "0.1.14" From b7de368dfd7c9772e17bebdc0b3ec70987484fb6 Mon Sep 17 00:00:00 2001 From: Levi Blaney Date: Sun, 28 Feb 2021 13:22:12 -0500 Subject: [PATCH 32/72] change docker to use poetry --- Dockerfile | 2 +- docker-compose.yaml | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index cec864b683a..e5af3d19646 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,6 +28,6 @@ COPY --chown=python:python . . #RUN INSTALL_ON_LINUX=1 pip install -r requirements.txt RUN pip install "poetry==1.1.4" -RUN poetry export -f requirements.txt | pip install -r /dev/stdin +RUN poetry export --without-hashes -f requirements.txt | pip install -r /dev/stdin CMD ["python", "gamestonk_terminal.py"] diff --git a/docker-compose.yaml b/docker-compose.yaml index 67ab223c65a..bdbcb4a134e 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -4,5 +4,3 @@ services: build: context: . image: gamestonkterminal:dev - volumes: - - .:/home/python From 0bfcaa6667698e486c11eaa8a14200f9db047920 Mon Sep 17 00:00:00 2001 From: sigaloid <69441971+sigaloid@users.noreply.github.com> Date: Mon, 1 Mar 2021 01:18:13 +0000 Subject: [PATCH 33/72] Update README.md --- README.md | 291 +++++++++++++++++++++++++++--------------------------- 1 file changed, 148 insertions(+), 143 deletions(-) diff --git a/README.md b/README.md index 7008d704dc4..4bafac20a9e 100644 --- a/README.md +++ b/README.md @@ -28,14 +28,17 @@ Feel free to request features, I'll be happy to work on them on my spare time. The main menu allows the following commands: ``` load -t S_TICKER [-s S_START_DATE] [-i {1,5,15,30,60}] -clear -view -t S_TICKER [-s S_START_DATE] [-i {1,5,15,30,60}] [--type N_TYPE] ``` -With their functions being: * Load stock ticker to perform analysis on * -s : The starting date (format YYYY-MM-DD) of the stock * -i : Intraday stock minutes +``` +clear +``` * Clear previously loaded stock ticker. +``` +view -t S_TICKER [-s S_START_DATE] [-i {1,5,15,30,60}] [--type N_TYPE] +``` * Visualise historical data of a stock. An alpha_vantage key is necessary. * -s : The starting date (format YYYY-MM-DD) of the stock * -i : Intraday stock minutes @@ -46,168 +49,171 @@ With their functions being: Note: Until a ticker is loaded, the menu will only show *disc* and *sen* menu, as the others require a ticker being provided. ### [Discover Stocks](discovery/README.md) -``` -map S&P500 index stocks map [Finviz] -sectors show sectors performance [Alpha Vantage] -gainers show latest top gainers [Yahoo Finance] -orders orders by Fidelity Customers [Fidelity] -up_earnings upcoming earnings release dates [Seeking Alpha] -high_short show top high short interest stocks of over 20% ratio [www.highshortinterest.com] -low_float show low float stocks under 10M shares float [www.lowfloat.com] -simply_wallst Simply Wall St. research data [Simply Wall St.] -spachero great website for SPACs research [SpacHero] -uwhales good website for SPACs research [UnusualWhales] -``` +Command|Explanation +---|--- +`map` |S&P500 index stocks map ([Finviz](https://finviz.com)) +`sectors` |show sectors performance ([Alpha Vantage](www.alphavantage.co)) +`gainers` |show latest top gainers ([Yahoo Finance](https://finance.yahoo.com/)) +`orders` |orders by Fidelity Customers ([Fidelity](https://www.fidelity.com/)) +`up_earnings` |upcoming earnings release dates ([Seeking Alpha](https://seekingalpha.com/)) +`high_short` |show top high short interest stocks of over 20% ratio ([High Short Interest](https://www.highshortinterest.com/)) +`low_float` |show low float stocks under 10M shares float ([Low Float](https://www.lowfloat.com/)) +`simply_wallst` |Simply Wall St. research data ([Simply Wall St.](https://simplywall.st/about)) +`spachero` |great website for SPACs research ([SpacHero](https://www.spachero.com/)) +`uwhales` |good website for SPACs research ([UnusualWhales](https://unusualwhales.com/)) + ### [Market Sentiment](sentiment/README.md) -``` -Reddit: -wsb show what WSB gang is up to in subreddit wallstreetbets -watchlist show other users watchlist -popular show popular tickers -spac_c show other users spacs announcements from subreddit SPACs community -spac show other users spacs announcements from other subs - -Stocktwits: -bullbear estimate quick sentiment from last 30 messages on board -messages output up to the 30 last messages on the board -trending trending stocks -stalker stalk stocktwits user's last messages - -Twitter: -infer infer about stock's sentiment from latest tweets -sentiment in-depth sentiment prediction from tweets over time - -Google: -mentions interest over time based on stock's mentions -regions regions that show highest interest in stock -queries top related queries with this stock -rise top rising related queries with stock -``` +Command|Explanation +----|---- +Reddit:| +`wsb` |show what WSB gang is up to in subreddit wallstreetbets +`watchlist` |show other users watchlist +`popular` |show popular tickers +`spac_c` |show other users spacs announcements from subreddit SPACs community +`spac` |show other users spacs announcements from other subs +Stocktwits:| +`bullbear` |estimate quick sentiment from last 30 messages on board +`messages` |output up to the 30 last messages on the board +`trending` |trending stocks +`stalker` |stalk stocktwits user's last message +Twitter:| +`infer` |infer about stock's sentiment from latest tweets +`sentiment` |in-depth sentiment prediction from tweets over time +Google:| +`mentions` |interest over time based on stock's mentions +`regions` |regions that show highest interest in stock +`queries` |top related queries with this stock +`rise` |top rising related queries with stock ### Research Web pages -``` -macroaxis www.macroaxis.com -yahoo www.finance.yahoo.com -finviz www.finviz.com -marketwatch www.marketwatch.com -fool www.fool.com -businessinsider www.markets.businessinsider.com -fmp www.financialmodelingprep.com -fidelity www.eresearch.fidelity.com -tradingview www.tradingview.com -marketchameleon www.marketchameleon.com -stockrow www.stockrow.com -barchart www.barchart.com -grufity www.grufity.com -fintel www.fintel.com -zacks www.zacks.com -macrotrends www.macrotrends.net -newsfilter www.newsfilter.io +Command|Website +----|---- +`macroaxis` |www.macroaxis.com +`yahoo` |www.finance.yahoo.com +`finviz` |www.finviz.com +`marketwatch` |www.marketwatch.com +`fool` |www.fool.com +`businessinsider` |www.markets.businessinsider.com +`fmp` |www.financialmodelingprep.com +`fidelity` |www.eresearch.fidelity.com +`tradingview` |www.tradingview.com +`marketchameleon` |www.marketchameleon.com +`stockrow` |www.stockrow.com +`barchart` |www.barchart.com +`grufity` |www.grufity.com +`fintel` |www.fintel.com +`zacks` |www.zacks.com +`macrotrends` |www.macrotrends.net +`newsfilter` |www.newsfilter.io +`resources` |www.tradinganalysisresources.com -resources www.tradinganalysisresources.com -``` ### [Fundamental Analysis](fundamental_analysis/README.md) -``` -Daily Stock: BB (from 2020-06-04) -screener screen info about the company [Finviz] -mgmt management team of the company [Business Insider] +Command|Explanation +----- | --------- +`screener` |screen info about the company ([Finviz](https://finviz.com/)) +`mgmt` |management team of the company ([Business Insider](https://www.businessinsider.com/)) +Market Watch API | +`income` |income statement of the company +`assets` |assets of the company +`liabilities` |liabilities and shareholders equity of the company +`operating` |cash flow operating activities of the company +`investing` |cash flow investing activities of the company +`financing` |cash flow financing activities of the company +Yahoo Finance API | +`info` |information scope of the company +`shrs` |shareholders of the company +`sust` |sustainability values of the company +`cal` |calendar earnings and estimates of the company +Alpha Vantage API | +`overview` |overview of the company +`income` |income statements of the company +`balance` |balance sheet of the company +`cash` |cash flow of the company +`earnings` |earnings dates and reported EPS +Financial Modeling Prep API | +`profile` |profile of the company +`quote` |quote of the company +`enterprise` |enterprise value of the company over time +`dcf` |discounted cash flow of the company over time +`inc` |income statements of the company +`bal` |balance sheet of the company +`cashf` |cash flow of the company +`metrics` |key metrics of the company +`ratios` |financial ratios of the company +`growth` |financial statement growth of the company -Market Watch API -income income statement of the company -assets assets of the company -liabilities liabilities and shareholders equity of the company -operating cash flow operating activities of the company -investing cash flow investing activities of the company -financing cash flow financing activities of the company - -Yahoo Finance API -info information scope of the company -shrs shareholders of the company -sust sustainability values of the company -cal calendar earnings and estimates of the company - -Alpha Vantage API -overview overview of the company -income income statements of the company -balance balance sheet of the company -cash cash flow of the company -earnings earnings dates and reported EPS - -Financial Modeling Prep API -profile profile of the company -quote quote of the company -enterprise enterprise value of the company over time -dcf discounted cash flow of the company over time -inc income statements of the company -bal balance sheet of the company -cashf cash flow of the company -metrics key metrics of the company -ratios financial ratios of the company -growth financial statement growth of the company -``` ### [Technical Analysis](technical_analysis/README.md) -``` -overlap: -ema exponential moving average -sma simple moving average -vwap volume weighted average price -momentum: -cci commodity channel index -macd moving average convergence/divergence -rsi relative strength index -stoch stochastic oscillator +Command | Explanation +------ | ------ +overlap: | +`ema` | exponential moving average ([source 1](https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average), [source 2](https://www.investopedia.com/terms/e/ema.asp)) +`sma` |simple moving average ([source 1](https://en.wikipedia.org/wiki/Moving_average#Simple_moving_average_(boxcar_filter)), [source 2](https://www.investopedia.com/terms/s/sma.asp)) +`vwap` |volume weighted average price ([source 1](https://en.wikipedia.org/wiki/Volume-weighted_average_price), [source 2](https://www.investopedia.com/terms/v/vwap.asp)) +momentum: | +`cci` |commodity channel index ([source 1](https://en.wikipedia.org/wiki/Commodity_channel_index), [source 2](https://www.investopedia.com/terms/c/commoditychannelindex.asp)) +`macd` |moving average convergence/divergence ([source 1](https://en.wikipedia.org/wiki/MACD), [source 2](https://www.investopedia.com/terms/m/macd.asp)) +`rsi` |relative strength index ([source 1](https://en.wikipedia.org/wiki/Relative_strength_index), [source 2](https://www.investopedia.com/terms/r/rsi.asp)) +`stoch` |stochastic oscillator ([source 1](https://en.wikipedia.org/wiki/Stochastic_oscillator), [source 2](https://www.investopedia.com/terms/s/stochasticoscillator.asp)) trend: -adx average directional movement index -aroon aroon indicator -volatility: -bbands bollinger bands -volume: -ad chaikin accumulation/distribution line values -obv on balance volume -``` +`adx` |average directional movement index ([source 1](https://en.wikipedia.org/wiki/Average_directional_movement_index), [source 2](https://www.investopedia.com/terms/a/adx.asp)) +`aroon` |aroon indicator ([source 1](https://www.investopedia.com/terms/a/aroon.asp)) +volatility: | +`bbands` |bollinger bands ([source 1](https://en.wikipedia.org/wiki/Bollinger_Bands), [source 2](https://www.investopedia.com/terms/b/bollingerbands.asp)) +volume: | +`ad` |chaikin accumulation/distribution line values ([source 1](https://en.wikipedia.org/wiki/Accumulation/distribution_index), [source 2](https://www.investopedia.com/terms/a/accumulationdistribution.asp)) +`obv` |on balance volume ([source 1](https://en.wikipedia.org/wiki/On-balance_volume), [source 2](https://www.investopedia.com/terms/o/onbalancevolume.asp)) ### [Due Diligence](due_diligence/README.md) -``` -news latest news of the company [Finviz] -red gets due diligence from another user's post [Reddit] -analyst analyst prices and ratings of the company [Finviz] -rating rating of the company from strong sell to strong buy [FMP] -pt price targets over time [Business Insider] -est quarter and year analysts earnings estimates [Business Insider] -ins insider activity over time [Business Insider] -insider insider trading of the company [Finviz] -sec SEC filings [Market Watch] -short short interest [Quandl] -warnings company warnings according to Sean Seah book [Market Watch] -``` +Command|Explanation +------ | -------- +`news` |latest news of the company ([Finviz](https://finviz.com/)) +`red` |gets due diligence from another user's post ([Reddit](https://reddit.com)) +`analyst` |analyst prices and ratings of the company ([Finviz](https://finviz.com/)) +`rating` |rating of the company from strong sell to strong buy [FMP] +`pt` |price targets over time ([Business Insider](https://www.businessinsider.com/)) +`est` |quarter and year analysts earnings estimates ([Business Insider](https://www.businessinsider.com/)) +`ins` |insider activity over time ([Business Insider](https://www.businessinsider.com/)) +`insider` |insider trading of the company ([Finviz](https://finviz.com/)) +`sec` |SEC filings ([MarketWatch](https://www.marketwatch.com/)) +`short` |short interest ([Quandl](https://www.quandl.com/)) +`warnings` |company warnings according to Sean Seah book ([MarketWatch](https://www.marketwatch.com/)) + ### [Prediction Techniques](prediction_techniques/README.md) -``` -sma simple moving average -knn k-Nearest Neighbors -linear linear regression (polynomial 1) -quadratic quadratic regression (polynomial 2) -cubic cubic regression (polynomial 3) -regression regression (other polynomial) -arima autoregressive integrated moving average -prophet Facebook's prophet prediction -mlp MultiLayer Perceptron -rnn Recurrent Neural Network -lstm Long-Short Term Memory -``` +Command|Algorithm +------ | ---------- +`sma` |simple moving average ([source 1](https://en.wikipedia.org/wiki/Moving_average#Simple_moving_average), [source 2](https://www.investopedia.com/terms/s/sma.asp)) +`knn` |k-Nearest Neighbors ([source 1](https://en.wikipedia.org/wiki/K-nearest_neighbors_algorithm)) +`linear` |linear regression (polynomial 1) ([source 1](https://en.wikipedia.org/wiki/Linear_regression), [source 2](https://www.investopedia.com/terms/r/regression.asp)) +`quadratic` |quadratic regression (polynomial 2) ([source 1](https://en.wikipedia.org/wiki/Polynomial_regression), [source 2](https://www.investopedia.com/terms/r/regression.asp)) +`cubic` |cubic regression (polynomial 3) ([source 1](https://en.wikipedia.org/wiki/Polynomial_regression), [source 2](https://www.investopedia.com/terms/r/regression.asp)) +`regression` |regression (other polynomial) ([source 1](https://en.wikipedia.org/wiki/Polynomial_regression), [source 2](https://www.investopedia.com/terms/r/regression.asp)) +`arima` |autoregressive integrated moving average ([source 1](https://en.wikipedia.org/wiki/Autoregressive_integrated_moving_average), [source 2](https://www.investopedia.com/terms/a/autoregressive-integrated-moving-average-arima.asp)) +`prophet` |Facebook's prophet prediction] ([source 1](https://facebook.github.io/prophet/)) +`mlp` |MultiLayer Perceptron ([source 1](https://en.wikipedia.org/wiki/Multilayer_perceptron)) +`rnn` |Recurrent Neural Network ([source 1](https://en.wikipedia.org/wiki/Recurrent_neural_network)) +`lstm` |Long Short-Term Memory ([source 1](https://en.wikipedia.org/wiki/Long_short-term_memory)) + ## Install This project was written and tested with Python 3.6.8. -In order to install all libraries used by this repository, you must run +In order to install, you must run: ``` -pip install -r requirements.txt +git clone https://github.com/DidierRLopes/GamestonkTerminal +cd GamestonkTerminal/ +pip3 install -r requirements.txt ``` +Then run: +``` +python3 gamestonk_terminal.py +``` + Note: The libraries specified in the [requirements.txt](/requirements.txt) file have been tested and work for the purpose of this project, however, these may be older versions. Hence, it is recommended for the user to set up a virtual python environment prior to installing these. This allows to keep dependencies required by different projects in separate places. @@ -244,4 +250,3 @@ When these are obtained, don't forget to update [config_terminal.py](/config_ter If you like this project, and would like me to maintain it and keep adding features, feel free to buy me a coffee! Buy Me A Coffee - From eec11b1009ccef22eb35916e94455d82c64840d0 Mon Sep 17 00:00:00 2001 From: sigaloid <69441971+sigaloid@users.noreply.github.com> Date: Mon, 1 Mar 2021 01:29:03 +0000 Subject: [PATCH 34/72] Some fixes --- README.md | 86 +++++++++++++++++++++++++++---------------------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index 4bafac20a9e..be65472747a 100644 --- a/README.md +++ b/README.md @@ -49,38 +49,38 @@ view -t S_TICKER [-s S_START_DATE] [-i {1,5,15,30,60}] [--type N_TYPE] Note: Until a ticker is loaded, the menu will only show *disc* and *sen* menu, as the others require a ticker being provided. ### [Discover Stocks](discovery/README.md) -Command|Explanation ----|--- -`map` |S&P500 index stocks map ([Finviz](https://finviz.com)) -`sectors` |show sectors performance ([Alpha Vantage](www.alphavantage.co)) -`gainers` |show latest top gainers ([Yahoo Finance](https://finance.yahoo.com/)) -`orders` |orders by Fidelity Customers ([Fidelity](https://www.fidelity.com/)) -`up_earnings` |upcoming earnings release dates ([Seeking Alpha](https://seekingalpha.com/)) -`high_short` |show top high short interest stocks of over 20% ratio ([High Short Interest](https://www.highshortinterest.com/)) -`low_float` |show low float stocks under 10M shares float ([Low Float](https://www.lowfloat.com/)) -`simply_wallst` |Simply Wall St. research data ([Simply Wall St.](https://simplywall.st/about)) -`spachero` |great website for SPACs research ([SpacHero](https://www.spachero.com/)) -`uwhales` |good website for SPACs research ([UnusualWhales](https://unusualwhales.com/)) +Command|Description|Source +---|---|--- +`map` |S&P500 index stocks map |[Finviz](https://finviz.com) +`sectors` |show sectors performance |[Alpha Vantage](www.alphavantage.co) +`gainers` |show latest top gainers |[Yahoo Finance](https://finance.yahoo.com/) +`orders` |orders by Fidelity Customers |[Fidelity](https://www.fidelity.com/) +`up_earnings` |upcoming earnings release dates |[Seeking Alpha](https://seekingalpha.com/) +`high_short` |show top high short interest stocks of over 20% ratio |[High Short Interest](https://www.highshortinterest.com/) +`low_float` |show low float stocks under 10M shares float |[Low Float](https://www.lowfloat.com/) +`simply_wallst` |Simply Wall St. research data |[Simply Wall St.](https://simplywall.st/about) +`spachero` |great website for SPACs research |[SpacHero](https://www.spachero.com/) +`uwhales` |good website for SPACs research |[UnusualWhales](https://unusualwhales.com/) ### [Market Sentiment](sentiment/README.md) -Command|Explanation +Command|Description ----|---- -Reddit:| +[Reddit](https://reddit.com):| `wsb` |show what WSB gang is up to in subreddit wallstreetbets `watchlist` |show other users watchlist `popular` |show popular tickers `spac_c` |show other users spacs announcements from subreddit SPACs community `spac` |show other users spacs announcements from other subs -Stocktwits:| +[Stocktwits](https://stocktwits.com/):| `bullbear` |estimate quick sentiment from last 30 messages on board `messages` |output up to the 30 last messages on the board `trending` |trending stocks `stalker` |stalk stocktwits user's last message -Twitter:| +[Twitter](https://twitter.com/):| `infer` |infer about stock's sentiment from latest tweets `sentiment` |in-depth sentiment prediction from tweets over time -Google:| +[Google](https://google.com/):| `mentions` |interest over time based on stock's mentions `regions` |regions that show highest interest in stock `queries` |top related queries with this stock @@ -111,7 +111,7 @@ Command|Website ### [Fundamental Analysis](fundamental_analysis/README.md) -Command|Explanation +Command|Description ----- | --------- `screener` |screen info about the company ([Finviz](https://finviz.com/)) `mgmt` |management team of the company ([Business Insider](https://www.businessinsider.com/)) @@ -147,25 +147,25 @@ Financial Modeling Prep API | ### [Technical Analysis](technical_analysis/README.md) -Command | Explanation ------- | ------ +Command | Description | Wikipedia | Investopedia +------ | ------ | ------ | ----- overlap: | -`ema` | exponential moving average ([source 1](https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average), [source 2](https://www.investopedia.com/terms/e/ema.asp)) -`sma` |simple moving average ([source 1](https://en.wikipedia.org/wiki/Moving_average#Simple_moving_average_(boxcar_filter)), [source 2](https://www.investopedia.com/terms/s/sma.asp)) -`vwap` |volume weighted average price ([source 1](https://en.wikipedia.org/wiki/Volume-weighted_average_price), [source 2](https://www.investopedia.com/terms/v/vwap.asp)) +`ema` | exponential moving average | [Link](https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average) | [Link](https://www.investopedia.com/terms/e/ema.asp) +`sma` |simple moving average | [Link](https://en.wikipedia.org/wiki/Moving_average#Simple_moving_average_(boxcar_filter))| [Link](https://www.investopedia.com/terms/s/sma.asp) +`vwap` |volume weighted average price | [Link](https://en.wikipedia.org/wiki/Volume-weighted_average_price)| [Link](https://www.investopedia.com/terms/v/vwap.asp) momentum: | -`cci` |commodity channel index ([source 1](https://en.wikipedia.org/wiki/Commodity_channel_index), [source 2](https://www.investopedia.com/terms/c/commoditychannelindex.asp)) -`macd` |moving average convergence/divergence ([source 1](https://en.wikipedia.org/wiki/MACD), [source 2](https://www.investopedia.com/terms/m/macd.asp)) -`rsi` |relative strength index ([source 1](https://en.wikipedia.org/wiki/Relative_strength_index), [source 2](https://www.investopedia.com/terms/r/rsi.asp)) -`stoch` |stochastic oscillator ([source 1](https://en.wikipedia.org/wiki/Stochastic_oscillator), [source 2](https://www.investopedia.com/terms/s/stochasticoscillator.asp)) +`cci` |commodity channel index | [Link](https://en.wikipedia.org/wiki/Commodity_channel_index)| [Link](https://www.investopedia.com/terms/c/commoditychannelindex.asp) +`macd` |moving average convergence/divergence | [Link](https://en.wikipedia.org/wiki/MACD)| [Link](https://www.investopedia.com/terms/m/macd.asp) +`rsi` |relative strength index | [Link](https://en.wikipedia.org/wiki/Relative_strength_index)| [Link](https://www.investopedia.com/terms/r/rsi.asp) +`stoch` |stochastic oscillator | [Link](https://en.wikipedia.org/wiki/Stochastic_oscillator)| [Link](https://www.investopedia.com/terms/s/stochasticoscillator.asp) trend: -`adx` |average directional movement index ([source 1](https://en.wikipedia.org/wiki/Average_directional_movement_index), [source 2](https://www.investopedia.com/terms/a/adx.asp)) -`aroon` |aroon indicator ([source 1](https://www.investopedia.com/terms/a/aroon.asp)) +`adx` |average directional movement index | [Link](https://en.wikipedia.org/wiki/Average_directional_movement_index)| [Link](https://www.investopedia.com/terms/a/adx.asp) +`aroon` |aroon indicator | [Link](https://www.investopedia.com/terms/a/aroon.asp) volatility: | -`bbands` |bollinger bands ([source 1](https://en.wikipedia.org/wiki/Bollinger_Bands), [source 2](https://www.investopedia.com/terms/b/bollingerbands.asp)) +`bbands` |bollinger bands | [Link](https://en.wikipedia.org/wiki/Bollinger_Bands)| [Link](https://www.investopedia.com/terms/b/bollingerbands.asp) volume: | -`ad` |chaikin accumulation/distribution line values ([source 1](https://en.wikipedia.org/wiki/Accumulation/distribution_index), [source 2](https://www.investopedia.com/terms/a/accumulationdistribution.asp)) -`obv` |on balance volume ([source 1](https://en.wikipedia.org/wiki/On-balance_volume), [source 2](https://www.investopedia.com/terms/o/onbalancevolume.asp)) +`ad` |chaikin accumulation/distribution line values | [Link](https://en.wikipedia.org/wiki/Accumulation/distribution_index)| [Link](https://www.investopedia.com/terms/a/accumulationdistribution.asp) +`obv` |on balance volume | [Link](https://en.wikipedia.org/wiki/On-balance_volume)| [Link](https://www.investopedia.com/terms/o/onbalancevolume.asp) ### [Due Diligence](due_diligence/README.md) Command|Explanation @@ -186,17 +186,17 @@ Command|Explanation ### [Prediction Techniques](prediction_techniques/README.md) Command|Algorithm ------ | ---------- -`sma` |simple moving average ([source 1](https://en.wikipedia.org/wiki/Moving_average#Simple_moving_average), [source 2](https://www.investopedia.com/terms/s/sma.asp)) -`knn` |k-Nearest Neighbors ([source 1](https://en.wikipedia.org/wiki/K-nearest_neighbors_algorithm)) -`linear` |linear regression (polynomial 1) ([source 1](https://en.wikipedia.org/wiki/Linear_regression), [source 2](https://www.investopedia.com/terms/r/regression.asp)) -`quadratic` |quadratic regression (polynomial 2) ([source 1](https://en.wikipedia.org/wiki/Polynomial_regression), [source 2](https://www.investopedia.com/terms/r/regression.asp)) -`cubic` |cubic regression (polynomial 3) ([source 1](https://en.wikipedia.org/wiki/Polynomial_regression), [source 2](https://www.investopedia.com/terms/r/regression.asp)) -`regression` |regression (other polynomial) ([source 1](https://en.wikipedia.org/wiki/Polynomial_regression), [source 2](https://www.investopedia.com/terms/r/regression.asp)) -`arima` |autoregressive integrated moving average ([source 1](https://en.wikipedia.org/wiki/Autoregressive_integrated_moving_average), [source 2](https://www.investopedia.com/terms/a/autoregressive-integrated-moving-average-arima.asp)) -`prophet` |Facebook's prophet prediction] ([source 1](https://facebook.github.io/prophet/)) -`mlp` |MultiLayer Perceptron ([source 1](https://en.wikipedia.org/wiki/Multilayer_perceptron)) -`rnn` |Recurrent Neural Network ([source 1](https://en.wikipedia.org/wiki/Recurrent_neural_network)) -`lstm` |Long Short-Term Memory ([source 1](https://en.wikipedia.org/wiki/Long_short-term_memory)) +`sma` |simple moving average | [Link](https://en.wikipedia.org/wiki/Moving_average#Simple_moving_average)| [Link](https://www.investopedia.com/terms/s/sma.asp) +`knn` |k-Nearest Neighbors | [Link](https://en.wikipedia.org/wiki/K-nearest_neighbors_algorithm)) +`linear` |linear regression (polynomial 1) | [Link](https://en.wikipedia.org/wiki/Linear_regression)| [Link](https://www.investopedia.com/terms/r/regression.asp) +`quadratic` |quadratic regression (polynomial 2) | [Link](https://en.wikipedia.org/wiki/Polynomial_regression)| [Link](https://www.investopedia.com/terms/r/regression.asp) +`cubic` |cubic regression (polynomial 3) | [Link](https://en.wikipedia.org/wiki/Polynomial_regression)| [Link](https://www.investopedia.com/terms/r/regression.asp) +`regression` |regression (other polynomial) | [Link](https://en.wikipedia.org/wiki/Polynomial_regression)| [Link](https://www.investopedia.com/terms/r/regression.asp) +`arima` |autoregressive integrated moving average | [Link](https://en.wikipedia.org/wiki/Autoregressive_integrated_moving_average)| [Link](https://www.investopedia.com/terms/a/autoregressive-integrated-moving-average-arima.asp) +`prophet` |Facebook's prophet prediction] | [Link](https://facebook.github.io/prophet/)) +`mlp` |MultiLayer Perceptron | [Link](https://en.wikipedia.org/wiki/Multilayer_perceptron)) +`rnn` |Recurrent Neural Network | [Link](https://en.wikipedia.org/wiki/Recurrent_neural_network)) +`lstm` |Long Short-Term Memory | [Link](https://en.wikipedia.org/wiki/Long_short-term_memory)) ## Install From 5a9c5042b967ab04cd1c495f8fc225ee2e9d13b7 Mon Sep 17 00:00:00 2001 From: sigaloid <69441971+sigaloid@users.noreply.github.com> Date: Mon, 1 Mar 2021 01:43:21 +0000 Subject: [PATCH 35/72] Further changes todo: need source for `rating of the company from strong sell to strong buy [FMP]` pandas-ta lib links --- README.md | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index be65472747a..a9d51d16e97 100644 --- a/README.md +++ b/README.md @@ -114,26 +114,26 @@ Command|Website Command|Description ----- | --------- `screener` |screen info about the company ([Finviz](https://finviz.com/)) -`mgmt` |management team of the company ([Business Insider](https://www.businessinsider.com/)) -Market Watch API | +`mgmt` |management team of the company ([Business Insider](https://markets.businessinsider.com/)) +[Market Watch API](https://markets.businessinsider.com/) | `income` |income statement of the company `assets` |assets of the company `liabilities` |liabilities and shareholders equity of the company `operating` |cash flow operating activities of the company `investing` |cash flow investing activities of the company `financing` |cash flow financing activities of the company -Yahoo Finance API | +[Yahoo Finance API](https://finance.yahoo.com/) | `info` |information scope of the company `shrs` |shareholders of the company `sust` |sustainability values of the company `cal` |calendar earnings and estimates of the company -Alpha Vantage API | +[Alpha Vantage API](https://www.alphavantage.co/) | `overview` |overview of the company `income` |income statements of the company `balance` |balance sheet of the company `cash` |cash flow of the company `earnings` |earnings dates and reported EPS -Financial Modeling Prep API | +[Financial Modeling Prep API](https://financialmodelingprep.com/) | `profile` |profile of the company `quote` |quote of the company `enterprise` |enterprise value of the company over time @@ -168,35 +168,35 @@ volume: | `obv` |on balance volume | [Link](https://en.wikipedia.org/wiki/On-balance_volume)| [Link](https://www.investopedia.com/terms/o/onbalancevolume.asp) ### [Due Diligence](due_diligence/README.md) -Command|Explanation ------- | -------- -`news` |latest news of the company ([Finviz](https://finviz.com/)) -`red` |gets due diligence from another user's post ([Reddit](https://reddit.com)) -`analyst` |analyst prices and ratings of the company ([Finviz](https://finviz.com/)) +Command|Explanation|Source +------ | --------|---- +`news` |latest news of the company |[Finviz](https://finviz.com/) +`red` |gets due diligence from another user's post |[Reddit](https://reddit.com) +`analyst` |analyst prices and ratings of the company |[Finviz](https://finviz.com/) `rating` |rating of the company from strong sell to strong buy [FMP] -`pt` |price targets over time ([Business Insider](https://www.businessinsider.com/)) -`est` |quarter and year analysts earnings estimates ([Business Insider](https://www.businessinsider.com/)) -`ins` |insider activity over time ([Business Insider](https://www.businessinsider.com/)) -`insider` |insider trading of the company ([Finviz](https://finviz.com/)) -`sec` |SEC filings ([MarketWatch](https://www.marketwatch.com/)) -`short` |short interest ([Quandl](https://www.quandl.com/)) -`warnings` |company warnings according to Sean Seah book ([MarketWatch](https://www.marketwatch.com/)) +`pt` |price targets over time |[Business Insider](https://www.businessinsider.com/) +`est` |quarter and year analysts earnings estimates |[Business Insider](https://www.businessinsider.com/) +`ins` |insider activity over time |[Business Insider](https://www.businessinsider.com/) +`insider` |insider trading of the company |[Finviz](https://finviz.com/) +`sec` |SEC filings |[MarketWatch](https://www.marketwatch.com/) +`short` |short interest |[Quandl](https://www.quandl.com/) +`warnings` |company warnings according to Sean Seah book |[MarketWatch](https://www.marketwatch.com/) ### [Prediction Techniques](prediction_techniques/README.md) -Command|Algorithm ------- | ---------- +Command|Technique|Wikipedia|Investopedia +------ | ------------|---|---- `sma` |simple moving average | [Link](https://en.wikipedia.org/wiki/Moving_average#Simple_moving_average)| [Link](https://www.investopedia.com/terms/s/sma.asp) -`knn` |k-Nearest Neighbors | [Link](https://en.wikipedia.org/wiki/K-nearest_neighbors_algorithm)) +`knn` |k-Nearest Neighbors | [Link](https://en.wikipedia.org/wiki/K-nearest_neighbors_algorithm) `linear` |linear regression (polynomial 1) | [Link](https://en.wikipedia.org/wiki/Linear_regression)| [Link](https://www.investopedia.com/terms/r/regression.asp) `quadratic` |quadratic regression (polynomial 2) | [Link](https://en.wikipedia.org/wiki/Polynomial_regression)| [Link](https://www.investopedia.com/terms/r/regression.asp) `cubic` |cubic regression (polynomial 3) | [Link](https://en.wikipedia.org/wiki/Polynomial_regression)| [Link](https://www.investopedia.com/terms/r/regression.asp) `regression` |regression (other polynomial) | [Link](https://en.wikipedia.org/wiki/Polynomial_regression)| [Link](https://www.investopedia.com/terms/r/regression.asp) `arima` |autoregressive integrated moving average | [Link](https://en.wikipedia.org/wiki/Autoregressive_integrated_moving_average)| [Link](https://www.investopedia.com/terms/a/autoregressive-integrated-moving-average-arima.asp) -`prophet` |Facebook's prophet prediction] | [Link](https://facebook.github.io/prophet/)) -`mlp` |MultiLayer Perceptron | [Link](https://en.wikipedia.org/wiki/Multilayer_perceptron)) -`rnn` |Recurrent Neural Network | [Link](https://en.wikipedia.org/wiki/Recurrent_neural_network)) -`lstm` |Long Short-Term Memory | [Link](https://en.wikipedia.org/wiki/Long_short-term_memory)) +`prophet` |Facebook's prophet prediction ([Link](https://facebook.github.io/prophet/))| +`mlp` |MultiLayer Perceptron | [Link](https://en.wikipedia.org/wiki/Multilayer_perceptron) +`rnn` |Recurrent Neural Network | [Link](https://en.wikipedia.org/wiki/Recurrent_neural_network) +`lstm` |Long Short-Term Memory | [Link](https://en.wikipedia.org/wiki/Long_short-term_memory) ## Install From 090b950c5588dfc589458dd63286e3f819e792b1 Mon Sep 17 00:00:00 2001 From: sigaloid <69441971+sigaloid@users.noreply.github.com> Date: Mon, 1 Mar 2021 01:48:59 +0000 Subject: [PATCH 36/72] FMP --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a9d51d16e97..a2136df071e 100644 --- a/README.md +++ b/README.md @@ -173,7 +173,7 @@ Command|Explanation|Source `news` |latest news of the company |[Finviz](https://finviz.com/) `red` |gets due diligence from another user's post |[Reddit](https://reddit.com) `analyst` |analyst prices and ratings of the company |[Finviz](https://finviz.com/) -`rating` |rating of the company from strong sell to strong buy [FMP] +`rating` |rating of the company from strong sell to strong buy | [FMP](https://financialmodelingprep.com/) `pt` |price targets over time |[Business Insider](https://www.businessinsider.com/) `est` |quarter and year analysts earnings estimates |[Business Insider](https://www.businessinsider.com/) `ins` |insider activity over time |[Business Insider](https://www.businessinsider.com/) From 96227baffbf71b8478763f231db98d32a2f54998 Mon Sep 17 00:00:00 2001 From: Ben Kulbertis Date: Mon, 1 Mar 2021 00:15:27 -0700 Subject: [PATCH 37/72] Fixed undefined timeseries var --- gamestonk_terminal.py | 1 + 1 file changed, 1 insertion(+) diff --git a/gamestonk_terminal.py b/gamestonk_terminal.py index a2f4f17d4c9..171d0b3890d 100644 --- a/gamestonk_terminal.py +++ b/gamestonk_terminal.py @@ -310,6 +310,7 @@ def main(): b_quit = pm.pred_menu(df_stock, s_ticker, s_start, s_interval) # If stock data is intradaily, we need to get data again as prediction techniques work on daily adjusted data else: + ts = TimeSeries(key=cfg.API_KEY_ALPHAVANTAGE, output_format='pandas') df_stock_pred, _ = ts.get_daily_adjusted(symbol=s_ticker, outputsize='full') df_stock_pred = df_stock_pred.sort_index(ascending=True) df_stock_pred = df_stock_pred[s_start:] From 0b9f948d77cdafcc42216c1625de7b2392f3a94f Mon Sep 17 00:00:00 2001 From: Levi Blaney Date: Mon, 1 Mar 2021 02:23:01 -0500 Subject: [PATCH 38/72] add pytest to poetry dev packages --- poetry.lock | 106 ++++++++++++++++++++++++++++++++++++++++++++++++- pyproject.toml | 1 + 2 files changed, 106 insertions(+), 1 deletion(-) diff --git a/poetry.lock b/poetry.lock index 367880b0032..2cbf6318680 100644 --- a/poetry.lock +++ b/poetry.lock @@ -60,6 +60,14 @@ category = "main" optional = false python-versions = ">=3.5.3" +[[package]] +name = "atomicwrites" +version = "1.4.0" +description = "Atomic file writes." +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + [[package]] name = "attrs" version = "20.3.0" @@ -171,6 +179,14 @@ pandas = "*" docs = ["sphinx", "sphinx-gallery", "sphinx-rtd-theme", "numpydoc", "matplotlib"] tests = ["pytest", "pytest-cov"] +[[package]] +name = "colorama" +version = "0.4.4" +description = "Cross-platform colored terminal text." +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + [[package]] name = "convertdate" version = "2.3.1" @@ -565,6 +581,14 @@ category = "main" optional = false python-versions = ">=3.5" +[[package]] +name = "iniconfig" +version = "1.1.1" +description = "iniconfig: brain-dead simple config-ini parsing" +category = "dev" +optional = false +python-versions = "*" + [[package]] name = "iso8601" version = "0.1.14" @@ -889,6 +913,20 @@ python-versions = "*" retrying = ">=1.3.3" six = "*" +[[package]] +name = "pluggy" +version = "0.13.1" +description = "plugin and hook calling mechanisms for python" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[package.dependencies] +importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} + +[package.extras] +dev = ["pre-commit", "tox"] + [[package]] name = "pmdarima" version = "1.8.0" @@ -981,6 +1019,14 @@ python-versions = ">=3" Click = "*" requests = "*" +[[package]] +name = "py" +version = "1.10.0" +description = "library with cross-python path, ini-parsing, io, code, log facilities" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + [[package]] name = "pyasn1" version = "0.4.8" @@ -1036,6 +1082,28 @@ python-versions = "*" Cython = ">=0.22,<0.25.1 || >0.25.1" numpy = ">=1.7" +[[package]] +name = "pytest" +version = "6.2.2" +description = "pytest: simple powerful testing with Python" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} +attrs = ">=19.2.0" +colorama = {version = "*", markers = "sys_platform == \"win32\""} +importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=0.12,<1.0.0a1" +py = ">=1.8.2" +toml = "*" + +[package.extras] +testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] + [[package]] name = "python-dateutil" version = "2.8.1" @@ -1410,6 +1478,14 @@ python-versions = "*" [package.extras] testing = ["pytest"] +[[package]] +name = "toml" +version = "0.10.2" +description = "Python Library for Tom's Obvious, Minimal Language" +category = "dev" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" + [[package]] name = "torch" version = "1.7.1" @@ -1604,7 +1680,7 @@ testing = ["pytest (>=3.5,!=3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake [metadata] lock-version = "1.1" python-versions = "~3.6.8" -content-hash = "8eb522fff7107ad0fc1c444f5932434da119093b35e283e6a43e7b6bb8fb8b17" +content-hash = "9b8e2cfb34868968b4cc4708f501d76036aaef0bb0ee642cf25a40d29c6cc830" [metadata.files] absl-py = [ @@ -1662,6 +1738,10 @@ async-timeout = [ {file = "async-timeout-3.0.1.tar.gz", hash = "sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f"}, {file = "async_timeout-3.0.1-py3-none-any.whl", hash = "sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3"}, ] +atomicwrites = [ + {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, + {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, +] attrs = [ {file = "attrs-20.3.0-py2.py3-none-any.whl", hash = "sha256:31b2eced602aa8423c2aea9c76a724617ed67cf9513173fd3a4f03e3a929c7e6"}, {file = "attrs-20.3.0.tar.gz", hash = "sha256:832aa3cde19744e49938b91fea06d69ecb9e649c93ba974535d08ad92164f700"}, @@ -1702,6 +1782,10 @@ cmdstanpy = [ {file = "cmdstanpy-0.4.0-py3-none-any.whl", hash = "sha256:3ac2ec8f6ce331ca5b2db5a8ac5f0f34a83571dbb9a2a7d9b9cf7b04ad696cd5"}, {file = "cmdstanpy-0.4.0.tar.gz", hash = "sha256:5604d20136785b05883eda20a2e8c1a1f47600b148abf68deb12dda6ccd8951f"}, ] +colorama = [ + {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, + {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, +] convertdate = [ {file = "convertdate-2.3.1-py3-none-any.whl", hash = "sha256:ede4b0bfbef002de8e31b9d8c03dc619a210915ce453e7a4826ac8808110fcff"}, {file = "convertdate-2.3.1.tar.gz", hash = "sha256:4eabe5cab9f7890c6bddab2133502de9d116ad81f2fcf16c4858fef2b737e328"}, @@ -1961,6 +2045,10 @@ inflection = [ {file = "inflection-0.5.1-py2.py3-none-any.whl", hash = "sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2"}, {file = "inflection-0.5.1.tar.gz", hash = "sha256:1a29730d366e996aaacffb2f1f1cb9593dc38e2ddd30c91250c6dde09ea9b417"}, ] +iniconfig = [ + {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, + {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, +] iso8601 = [ {file = "iso8601-0.1.14-py2.py3-none-any.whl", hash = "sha256:e7e1122f064d626e17d47cd5106bed2c620cb38fe464999e0ddae2b6d2de6004"}, {file = "iso8601-0.1.14.tar.gz", hash = "sha256:8aafd56fa0290496c5edbb13c311f78fa3a241f0853540da09d9363eae3ebd79"}, @@ -2272,6 +2360,10 @@ plotly = [ {file = "plotly-4.14.3-py2.py3-none-any.whl", hash = "sha256:d68fc15fcb49f88db27ab3e0c87110943e65fee02a47f33a8590f541b3042461"}, {file = "plotly-4.14.3.tar.gz", hash = "sha256:7d8aaeed392e82fb8e0e48899f2d3d957b12327f9d38cdd5802bc574a8a39d91"}, ] +pluggy = [ + {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"}, + {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"}, +] pmdarima = [ {file = "pmdarima-1.8.0-cp36-cp36m-macosx_10_15_x86_64.whl", hash = "sha256:0377023997c4424586d4f5d207a455a3fbba6f5fda41d89eb135a5f697375dcd"}, {file = "pmdarima-1.8.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:5fbd363bbfe6dd4f35c1825f53ae07e63d3ca1995ac3e87bef0359c1670c464b"}, @@ -2324,6 +2416,10 @@ protobuf = [ psaw = [ {file = "psaw-0.0.12-py3-none-any.whl", hash = "sha256:cfbfdf1953ee5f31ca9d4ec6d471873ace960da9fbc7234b9d19a059d5cfa2d6"}, ] +py = [ + {file = "py-1.10.0-py2.py3-none-any.whl", hash = "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a"}, + {file = "py-1.10.0.tar.gz", hash = "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3"}, +] pyasn1 = [ {file = "pyasn1-0.4.8-py2.4.egg", hash = "sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3"}, {file = "pyasn1-0.4.8-py2.5.egg", hash = "sha256:0458773cfe65b153891ac249bcf1b5f8f320b7c2ce462151f8fa74de8934becf"}, @@ -2388,6 +2484,10 @@ pystan = [ {file = "pystan-2.19.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:9d8c2ae05d1dca854a55b2ae9276af5866e473fb8264d03d5267abadb3c602da"}, {file = "pystan-2.19.1.1.tar.gz", hash = "sha256:fa8bad8dbc0da22bbe6f36af56c9abbfcf10f92df8ce627d59a36bd8d25eb038"}, ] +pytest = [ + {file = "pytest-6.2.2-py3-none-any.whl", hash = "sha256:b574b57423e818210672e07ca1fa90aaf194a4f63f3ab909a2c67ebb22913839"}, + {file = "pytest-6.2.2.tar.gz", hash = "sha256:9d1edf9e7d0b84d72ea3dbcdfd22b35fb543a5e8f2a60092dd578936bf63d7f9"}, +] python-dateutil = [ {file = "python-dateutil-2.8.1.tar.gz", hash = "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"}, {file = "python_dateutil-2.8.1-py2.py3-none-any.whl", hash = "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a"}, @@ -2705,6 +2805,10 @@ tokenizers = [ {file = "tokenizers-0.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:3100ed9051558a3b2a9c2b7dda6880328a7c4c0736be72d279b0029339d55789"}, {file = "tokenizers-0.9.3.tar.gz", hash = "sha256:bacaeb3621055aba9b5158a21dc8b5d80f65724ff47f414f9d06f1e087668d61"}, ] +toml = [ + {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, + {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, +] torch = [ {file = "torch-1.7.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:422e64e98d0e100c360993819d0307e5d56e9517b26135808ad68984d577d75a"}, {file = "torch-1.7.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f0aaf657145533824b15f2fd8fde8f8c67fe6c6281088ef588091f03fad90243"}, diff --git a/pyproject.toml b/pyproject.toml index a486e8a20ca..7a4e5d0993a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,6 +31,7 @@ matplotlib = "3.3.3" plotly = "4.14.3" [tool.poetry.dev-dependencies] +pytest = "^6.2.2" [build-system] requires = ["poetry-core>=1.0.0"] From 76d94b9dff97a98b9da54dcd00e6dfa84a476379 Mon Sep 17 00:00:00 2001 From: Levi Blaney Date: Mon, 1 Mar 2021 02:24:01 -0500 Subject: [PATCH 39/72] add test for load --- tests/__init__.py | 0 tests/conftest.py | 2 ++ tests/test_gamestonk_terminal.py | 21 +++++++++++++++++++++ 3 files changed, 23 insertions(+) create mode 100644 tests/__init__.py create mode 100644 tests/conftest.py create mode 100644 tests/test_gamestonk_terminal.py diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 00000000000..ca073aeb742 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,2 @@ +def pytest_configure(config): + config.addinivalue_line("markers", "e2e: mark as end-to-end test.") \ No newline at end of file diff --git a/tests/test_gamestonk_terminal.py b/tests/test_gamestonk_terminal.py new file mode 100644 index 00000000000..d45d4ffdfe8 --- /dev/null +++ b/tests/test_gamestonk_terminal.py @@ -0,0 +1,21 @@ +from unittest.mock import patch + +import pandas as pd +import pytest + +from gamestonk_terminal import load + +@pytest.mark.e2e +def test_load_command(): + + test_stock = 'TSLA' + test_start = '2020-06-04' + + with patch('sys.stdout.write') as mock_out: + result = load(['-t', test_stock, '-s', test_start], '', '', '', '') + + args = mock_out.call_args_list[0][0] + + assert result[0] == test_stock + assert test_stock in args[0] + assert test_start in args[0] From fc6e1104311818011de7b80ee74e199ccf45be60 Mon Sep 17 00:00:00 2001 From: Levi Blaney Date: Mon, 1 Mar 2021 03:29:43 -0500 Subject: [PATCH 40/72] add neural network test --- .../test_neural_networks.py | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 tests/test_prediction_techniques/test_neural_networks.py diff --git a/tests/test_prediction_techniques/test_neural_networks.py b/tests/test_prediction_techniques/test_neural_networks.py new file mode 100644 index 00000000000..a7daaef098d --- /dev/null +++ b/tests/test_prediction_techniques/test_neural_networks.py @@ -0,0 +1,25 @@ +from unittest.mock import patch + +import pytest + +from prediction_techniques.neural_networks import mlp +from gamestonk_terminal import load + + +@pytest.fixture +def stock(): + + def load_stock(name, start='2020-06-04'): + return load(['-t', name, '-s', start], '', '', '', '') + + return load_stock + + +@pytest.mark.e2e +def test_mlp(stock): + + with patch('sys.stdout.write') as mock_out: + tesla = stock('TSLA') + mlp([], tesla[0], tesla[2], tesla[3]) + + mock_out.assert_any_call('Predicted share price:') From e206a001af2a2833899e7d601524abc585ee1f30 Mon Sep 17 00:00:00 2001 From: Levi Blaney Date: Mon, 1 Mar 2021 03:32:05 -0500 Subject: [PATCH 41/72] add github workflow to run tests --- .github/workflows/test.yml | 42 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 00000000000..55ef1c04486 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,42 @@ +name: Tests +on: push +jobs: + tests: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ['3.6.8'] + name: Python ${{ matrix.python-version }} + steps: + - name: Checkout Code + uses: actions/checkout@v2 + + - name: Setup Python ${{ matrix.python-version }} + uses: actions/setup-python@v1 + with: + python-version: ${{ matrix.python-version }} + architecture: x64 + + - name: Install Poetry + uses: snok/install-poetry@v1.1.1 + with: + virtualenvs-create: true + virtualenvs-in-project: true + + - name: Load cached venv + id: cached-poetry-dependencies + uses: actions/cache@v2 + with: + path: .venv + key: venv-${{ runner.os }}-${{ hashFiles('**/poetry.lock') }} + + - name: Install dependencies + if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true' + run: poetry install --no-interaction --no-root + + - name: Run tests + env: + MPLBACKEND: Agg + run: | + source .venv/bin/activate + pytest tests/ From 75927141171f31157e5896aeea2760be94fa5cc1 Mon Sep 17 00:00:00 2001 From: Levi Blaney Date: Mon, 1 Mar 2021 03:36:01 -0500 Subject: [PATCH 42/72] change python to 3.6.13 --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 55ef1c04486..1bfc6c42242 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -5,7 +5,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ['3.6.8'] + python-version: ['3.6.13'] name: Python ${{ matrix.python-version }} steps: - name: Checkout Code From 0c83480e2edabf850d09cb40505a43b37a97e38b Mon Sep 17 00:00:00 2001 From: Levi Blaney Date: Mon, 1 Mar 2021 10:03:50 -0500 Subject: [PATCH 43/72] update depedencies to increase compatibility --- poetry.lock | 92 ++++++++++++++++++++++++------------------------ pyproject.toml | 45 ++++++++++++----------- requirements.txt | 12 +++---- 3 files changed, 74 insertions(+), 75 deletions(-) diff --git a/poetry.lock b/poetry.lock index 2cbf6318680..aad6887f6cd 100644 --- a/poetry.lock +++ b/poetry.lock @@ -725,7 +725,7 @@ testing = ["coverage", "pyyaml"] [[package]] name = "matplotlib" -version = "3.3.3" +version = "3.3.4" description = "Python plotting package" category = "main" optional = false @@ -868,8 +868,8 @@ test = ["pytest (>=4.0.2)", "pytest-xdist", "hypothesis (>=3.58)"] [[package]] name = "pandas-ta" -version = "0.2.23b" -description = "An easy to use Python 3 Pandas Extension with 115+ Technical Analysis Indicators. Can be called from a Pandas DataFrame or standalone like TA-Lib. Correlation tested with TA-Lib." +version = "0.2.45b" +description = "An easy to use Python 3 Pandas Extension with 130+ Technical Analysis Indicators. Can be called from a Pandas DataFrame or standalone like TA-Lib. Correlation tested with TA-Lib." category = "main" optional = false python-versions = "*" @@ -947,39 +947,39 @@ urllib3 = "*" [[package]] name = "praw" -version = "7.1.4" +version = "7.2.0" description = "PRAW, an acronym for `Python Reddit API Wrapper`, is a python package that allows for simple access to reddit's API." category = "main" optional = false python-versions = "~=3.6" [package.dependencies] -prawcore = ">=1.5.0,<2.0" +prawcore = ">=2,<3" update-checker = ">=0.18" websocket-client = ">=0.54.0" [package.extras] ci = ["coveralls"] -dev = ["packaging", "pre-commit", "black", "flake8", "flynt", "isort", "pydocstyle", "sphinx (<3.0)", "sphinx-rtd-theme", "betamax (>=0.8,<0.9)", "betamax-matchers (>=0.3.0,<0.5)", "pytest (>=2.7.3)"] -lint = ["black", "flake8", "flynt", "isort", "pydocstyle", "sphinx (<3.0)", "sphinx-rtd-theme"] -readthedocs = ["sphinx (<3.0)"] +dev = ["packaging", "pre-commit", "black", "flake8", "flynt", "isort", "pydocstyle", "sphinx", "sphinx-rtd-theme", "betamax (>=0.8,<0.9)", "betamax-matchers (>=0.3.0,<0.5)", "pytest (>=2.7.3)"] +lint = ["black", "flake8", "flynt", "isort", "pydocstyle", "sphinx", "sphinx-rtd-theme"] +readthedocs = ["sphinx"] test = ["betamax (>=0.8,<0.9)", "betamax-matchers (>=0.3.0,<0.5)", "pytest (>=2.7.3)"] [[package]] name = "prawcore" -version = "1.5.0" +version = "2.0.0" description = "Low-level communication layer for PRAW 4+." category = "main" optional = false -python-versions = ">=3.5" +python-versions = "~=3.6" [package.dependencies] requests = ">=2.6.0,<3.0" [package.extras] ci = ["coveralls"] -dev = ["black", "flake8", "pre-commit", "pydocstyle", "betamax (>=0.8,<0.9)", "betamax-matchers (>=0.4.0,<0.5)", "betamax-serializers (>=0.2.0,<0.3)", "mock (>=0.8)", "pytest", "testfixtures (>4.13.2,<7)"] -lint = ["black", "flake8", "pre-commit", "pydocstyle"] +dev = ["black", "flake8", "pre-commit", "pydocstyle", "flynt", "betamax (>=0.8,<0.9)", "betamax-matchers (>=0.4.0,<0.5)", "betamax-serializers (>=0.2.0,<0.3)", "mock (>=0.8)", "pytest", "testfixtures (>4.13.2,<7)"] +lint = ["black", "flake8", "pre-commit", "pydocstyle", "flynt"] test = ["betamax (>=0.8,<0.9)", "betamax-matchers (>=0.4.0,<0.5)", "betamax-serializers (>=0.2.0,<0.3)", "mock (>=0.8)", "pytest", "testfixtures (>4.13.2,<7)"] [[package]] @@ -1048,7 +1048,7 @@ pyasn1 = ">=0.4.6,<0.5.0" [[package]] name = "pymeeus" -version = "0.4.2" +version = "0.4.3" description = "Python implementation of Jean Meeus astronomical routines" category = "main" optional = false @@ -1679,8 +1679,8 @@ testing = ["pytest (>=3.5,!=3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake [metadata] lock-version = "1.1" -python-versions = "~3.6.8" -content-hash = "9b8e2cfb34868968b4cc4708f501d76036aaef0bb0ee642cf25a40d29c6cc830" +python-versions = "^3.6.8" +content-hash = "02a3e4a9429708ed386254d585c0564fea6f1bfc5473b25f34197aaeae5564be" [metadata.files] absl-py = [ @@ -2159,31 +2159,31 @@ markdown = [ {file = "Markdown-3.3.4.tar.gz", hash = "sha256:31b5b491868dcc87d6c24b7e3d19a0d730d59d3e46f4eea6430a321bed387a49"}, ] matplotlib = [ - {file = "matplotlib-3.3.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b2a5e1f637a92bb6f3526cc54cc8af0401112e81ce5cba6368a1b7908f9e18bc"}, - {file = "matplotlib-3.3.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:c586ac1d64432f92857c3cf4478cfb0ece1ae18b740593f8a39f2f0b27c7fda5"}, - {file = "matplotlib-3.3.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:9b03722c89a43a61d4d148acfc89ec5bb54cd0fd1539df25b10eb9c5fa6c393a"}, - {file = "matplotlib-3.3.3-cp36-cp36m-win32.whl", hash = "sha256:2c2c5041608cb75c39cbd0ed05256f8a563e144234a524c59d091abbfa7a868f"}, - {file = "matplotlib-3.3.3-cp36-cp36m-win_amd64.whl", hash = "sha256:c092fc4673260b1446b8578015321081d5db73b94533fe4bf9b69f44e948d174"}, - {file = "matplotlib-3.3.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:27c9393fada62bd0ad7c730562a0fecbd3d5aaa8d9ed80ba7d3ebb8abc4f0453"}, - {file = "matplotlib-3.3.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:b8ba2a1dbb4660cb469fe8e1febb5119506059e675180c51396e1723ff9b79d9"}, - {file = "matplotlib-3.3.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:0caa687fce6174fef9b27d45f8cc57cbc572e04e98c81db8e628b12b563d59a2"}, - {file = "matplotlib-3.3.3-cp37-cp37m-win32.whl", hash = "sha256:b7b09c61a91b742cb5460b72efd1fe26ef83c1c704f666e0af0df156b046aada"}, - {file = "matplotlib-3.3.3-cp37-cp37m-win_amd64.whl", hash = "sha256:6ffd2d80d76df2e5f9f0c0140b5af97e3b87dd29852dcdb103ec177d853ec06b"}, - {file = "matplotlib-3.3.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5111d6d47a0f5b8f3e10af7a79d5e7eb7e73a22825391834734274c4f312a8a0"}, - {file = "matplotlib-3.3.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:a4fe54eab2c7129add75154823e6543b10261f9b65b2abe692d68743a4999f8c"}, - {file = "matplotlib-3.3.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:83e6c895d93fdf93eeff1a21ee96778ba65ef258e5d284160f7c628fee40c38f"}, - {file = "matplotlib-3.3.3-cp38-cp38-win32.whl", hash = "sha256:b26c472847911f5a7eb49e1c888c31c77c4ddf8023c1545e0e8e0367ba74fb15"}, - {file = "matplotlib-3.3.3-cp38-cp38-win_amd64.whl", hash = "sha256:09225edca87a79815822eb7d3be63a83ebd4d9d98d5aa3a15a94f4eee2435954"}, - {file = "matplotlib-3.3.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:eb6b6700ea454bb88333d98601e74928e06f9669c1ea231b4c4c666c1d7701b4"}, - {file = "matplotlib-3.3.3-cp39-cp39-manylinux1_i686.whl", hash = "sha256:2d31aff0c8184b05006ad756b9a4dc2a0805e94d28f3abc3187e881b6673b302"}, - {file = "matplotlib-3.3.3-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:d082f77b4ed876ae94a9373f0db96bf8768a7cca6c58fc3038f94e30ffde1880"}, - {file = "matplotlib-3.3.3-cp39-cp39-win32.whl", hash = "sha256:e71cdd402047e657c1662073e9361106c6981e9621ab8c249388dfc3ec1de07b"}, - {file = "matplotlib-3.3.3-cp39-cp39-win_amd64.whl", hash = "sha256:756ee498b9ba35460e4cbbd73f09018e906daa8537fff61da5b5bf8d5e9de5c7"}, - {file = "matplotlib-3.3.3-pp36-pypy36_pp73-macosx_10_9_x86_64.whl", hash = "sha256:7ad44f2c74c50567c694ee91c6fa16d67e7c8af6f22c656b80469ad927688457"}, - {file = "matplotlib-3.3.3-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:3a4c3e9be63adf8e9b305aa58fb3ec40ecc61fd0f8fd3328ce55bc30e7a2aeb0"}, - {file = "matplotlib-3.3.3-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:746897fbd72bd462b888c74ed35d812ca76006b04f717cd44698cdfc99aca70d"}, - {file = "matplotlib-3.3.3-pp37-pypy37_pp73-manylinux2010_x86_64.whl", hash = "sha256:5ed3d3342698c2b1f3651f8ea6c099b0f196d16ee00e33dc3a6fee8cb01d530a"}, - {file = "matplotlib-3.3.3.tar.gz", hash = "sha256:b1b60c6476c4cfe9e5cf8ab0d3127476fd3d5f05de0f343a452badaad0e4bdec"}, + {file = "matplotlib-3.3.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:672960dd114e342b7c610bf32fb99d14227f29919894388b41553217457ba7ef"}, + {file = "matplotlib-3.3.4-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:7c155437ae4fd366e2700e2716564d1787700687443de46bcb895fe0f84b761d"}, + {file = "matplotlib-3.3.4-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:a17f0a10604fac7627ec82820439e7db611722e80c408a726cd00d8c974c2fb3"}, + {file = "matplotlib-3.3.4-cp36-cp36m-win32.whl", hash = "sha256:215e2a30a2090221a9481db58b770ce56b8ef46f13224ae33afe221b14b24dc1"}, + {file = "matplotlib-3.3.4-cp36-cp36m-win_amd64.whl", hash = "sha256:348e6032f666ffd151b323342f9278b16b95d4a75dfacae84a11d2829a7816ae"}, + {file = "matplotlib-3.3.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:94bdd1d55c20e764d8aea9d471d2ae7a7b2c84445e0fa463f02e20f9730783e1"}, + {file = "matplotlib-3.3.4-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:a1acb72f095f1d58ecc2538ed1b8bca0b57df313b13db36ed34b8cdf1868e674"}, + {file = "matplotlib-3.3.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:46b1a60a04e6d884f0250d5cc8dc7bd21a9a96c584a7acdaab44698a44710bab"}, + {file = "matplotlib-3.3.4-cp37-cp37m-win32.whl", hash = "sha256:ed4a9e6dcacba56b17a0a9ac22ae2c72a35b7f0ef0693aa68574f0b2df607a89"}, + {file = "matplotlib-3.3.4-cp37-cp37m-win_amd64.whl", hash = "sha256:c24c05f645aef776e8b8931cb81e0f1632d229b42b6d216e30836e2e145a2b40"}, + {file = "matplotlib-3.3.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7310e353a4a35477c7f032409966920197d7df3e757c7624fd842f3eeb307d3d"}, + {file = "matplotlib-3.3.4-cp38-cp38-manylinux1_i686.whl", hash = "sha256:451cc89cb33d6652c509fc6b588dc51c41d7246afdcc29b8624e256b7663ed1f"}, + {file = "matplotlib-3.3.4-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:3d2eb9c1cc254d0ffa90bc96fde4b6005d09c2228f99dfd493a4219c1af99644"}, + {file = "matplotlib-3.3.4-cp38-cp38-win32.whl", hash = "sha256:e15fa23d844d54e7b3b7243afd53b7567ee71c721f592deb0727ee85e668f96a"}, + {file = "matplotlib-3.3.4-cp38-cp38-win_amd64.whl", hash = "sha256:1de0bb6cbfe460725f0e97b88daa8643bcf9571c18ba90bb8e41432aaeca91d6"}, + {file = "matplotlib-3.3.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f44149a0ef5b4991aaef12a93b8e8d66d6412e762745fea1faa61d98524e0ba9"}, + {file = "matplotlib-3.3.4-cp39-cp39-manylinux1_i686.whl", hash = "sha256:746a1df55749629e26af7f977ea426817ca9370ad1569436608dc48d1069b87c"}, + {file = "matplotlib-3.3.4-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:5f571b92a536206f7958f7cb2d367ff6c9a1fa8229dc35020006e4cdd1ca0acd"}, + {file = "matplotlib-3.3.4-cp39-cp39-win32.whl", hash = "sha256:9265ae0fb35e29f9b8cc86c2ab0a2e3dcddc4dd9de4b85bf26c0f63fe5c1c2ca"}, + {file = "matplotlib-3.3.4-cp39-cp39-win_amd64.whl", hash = "sha256:9a79e5dd7bb797aa611048f5b70588b23c5be05b63eefd8a0d152ac77c4243db"}, + {file = "matplotlib-3.3.4-pp36-pypy36_pp73-macosx_10_9_x86_64.whl", hash = "sha256:1e850163579a8936eede29fad41e202b25923a0a8d5ffd08ce50fc0a97dcdc93"}, + {file = "matplotlib-3.3.4-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:d738acfdfb65da34c91acbdb56abed46803db39af259b7f194dc96920360dbe4"}, + {file = "matplotlib-3.3.4-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:aa49571d8030ad0b9ac39708ee77bd2a22f87815e12bdee52ecaffece9313ed8"}, + {file = "matplotlib-3.3.4-pp37-pypy37_pp73-manylinux2010_x86_64.whl", hash = "sha256:cf3a7e54eff792f0815dbbe9b85df2f13d739289c93d346925554f71d484be78"}, + {file = "matplotlib-3.3.4.tar.gz", hash = "sha256:3e477db76c22929e4c6876c44f88d790aacdf3c3f8f3a90cb1975c0bf37825b0"}, ] more-itertools = [ {file = "more-itertools-8.7.0.tar.gz", hash = "sha256:c5d6da9ca3ff65220c3bfd2a8db06d698f05d4d2b9be57e1deb2be5a45019713"}, @@ -2316,7 +2316,7 @@ pandas = [ {file = "pandas-1.1.5.tar.gz", hash = "sha256:f10fc41ee3c75a474d3bdf68d396f10782d013d7f67db99c0efbfd0acb99701b"}, ] pandas-ta = [ - {file = "pandas_ta-0.2.23b.tar.gz", hash = "sha256:73d5c5f9de2edd322abc961f4c47f9c5b2a1e3915223042bc10f1dbc0c29bb02"}, + {file = "pandas_ta-0.2.45b.tar.gz", hash = "sha256:2adde7d3ecec5d96b032b6d80491fb2c9b7952626a3c2cf01fe7ca78f35ebe38"}, ] patsy = [ {file = "patsy-0.5.1-py2.py3-none-any.whl", hash = "sha256:5465be1c0e670c3a965355ec09e9a502bf2c4cbe4875e8528b0221190a8a5d40"}, @@ -2380,12 +2380,12 @@ pmdarima = [ {file = "pmdarima-1.8.0.tar.gz", hash = "sha256:65f22f49ebc2271934a2bb346a6667b19094300eeaebf93a3674577c5440a6bc"}, ] praw = [ - {file = "praw-7.1.4-py3-none-any.whl", hash = "sha256:068a01c19834e1f748a8c220c6aa62ae9f0f8e211504ab8ef19883d09bed3430"}, - {file = "praw-7.1.4.tar.gz", hash = "sha256:87166a77ec31a1d9686ccdac97b5b72ba277ce436976eb3baf467c593f15bb26"}, + {file = "praw-7.2.0-py3-none-any.whl", hash = "sha256:f8e9f1854368a833d09208ca6f0318220d488a0c6660ff5c38391e55f50f0aa9"}, + {file = "praw-7.2.0.tar.gz", hash = "sha256:434600bb77264dc5f8f7635eb0541a6c992b87e1d9e9f6e3f40fe98e2c508152"}, ] prawcore = [ - {file = "prawcore-1.5.0-py3-none-any.whl", hash = "sha256:672d8a2faa12b44307874b2acfdd27f9cbaa5fa37bada4b34e36277224e6d8ed"}, - {file = "prawcore-1.5.0.tar.gz", hash = "sha256:1f1eafc8a65d671f9892354f73142014fbb5d3a9ee621568c662d0a354e0578b"}, + {file = "prawcore-2.0.0-py3-none-any.whl", hash = "sha256:2353c0de28a01ccd39615f3ba0975d0781e4b51d2913f0965903dd98ebdd9a75"}, + {file = "prawcore-2.0.0.tar.gz", hash = "sha256:b498d9b6f54991005e727d5235c8f49ea5ba0c9a6d793fb743b40fa089cd36d1"}, ] prettytable = [ {file = "prettytable-2.0.0-py3-none-any.whl", hash = "sha256:5dc7fcaca227f48deacd86958ae9d7b8c31a186fcb354bbb066763f20adf3eb9"}, @@ -2451,7 +2451,7 @@ pyasn1-modules = [ {file = "pyasn1_modules-0.2.8-py3.7.egg", hash = "sha256:c29a5e5cc7a3f05926aff34e097e84f8589cd790ce0ed41b67aed6857b26aafd"}, ] pymeeus = [ - {file = "PyMeeus-0.4.2.tar.gz", hash = "sha256:6b7b3b86e4a8c9065fcf3b2ebb3f1e122d1a819de1a98461c3f873feab550291"}, + {file = "PyMeeus-0.4.3.tar.gz", hash = "sha256:d4a48f102d938740e047bd00c972aa8b3256c02d296f4a5070690133fcb86e5d"}, ] pyparsing = [ {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"}, diff --git a/pyproject.toml b/pyproject.toml index 7a4e5d0993a..dc084d2ae96 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,30 +5,29 @@ description = "" authors = ["Didier Rodrigues Lopes"] [tool.poetry.dependencies] -python = "~3.6.8" -fbprophet = "0.6" -pandas = "1.1.5" -iso8601 = "0.1.14" -FundamentalAnalysis = "0.2.6" -requests = "2.25.1" -alpha-vantage = "2.3.1" -finviz = "1.3.4" -bs4 = "0.0.1" -rapidfuzz = "1.1.1" -yfinance = "0.1.55" -pandas-ta = "0.2.23b0" -dataclasses = "0.8" -prettytable = "2.0.0" -psaw = "0.0.12" -praw = "7.1.4" -Quandl = "3.6.0" -flair = "0.7" -pytrends = "4.7.3" +python = "^3.6.8" +fbprophet = "^0.6" +pandas = "^1.1.5" +iso8601 = "^0.1.14" +FundamentalAnalysis = "^0.2.6" +requests = "^2.25.1" +alpha-vantage = "^2.3.1" +finviz = "^1.3.4" +bs4 = "^0.0.1" +rapidfuzz = "^1.1.1" +yfinance = "^0.1.55" +pandas-ta = "^0.2.23b0" +prettytable = "^2.0.0" +psaw = "^0.0.12" +praw = "^7.1.4" +Quandl = "^3.6.0" +flair = "^0.7" +pytrends = "^4.7.3" TimeSeriesCrossValidation = { git = "https://github.com/DidierRLopes/TimeSeriesCrossValidation.git", branch = "master" } -pmdarima = "1.8.0" -tensorflow = "2.4.1" -matplotlib = "3.3.3" -plotly = "4.14.3" +pmdarima = "^1.8.0" +tensorflow = "^2.4.1" +matplotlib = "^3.3.3" +plotly = "^4.14.3" [tool.poetry.dev-dependencies] pytest = "^6.2.2" diff --git a/requirements.txt b/requirements.txt index 3545df2ed43..e9c73f22e57 100644 --- a/requirements.txt +++ b/requirements.txt @@ -17,7 +17,7 @@ convertdate==2.3.1; python_version >= "3.5" cssselect==1.1.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" cycler==0.10.0; python_version >= "3.6" cython==0.29.17; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.6" -dataclasses==0.8; python_version >= "3.6" and python_version < "3.7" +dataclasses==0.8; python_version >= "3.6" and python_version < "3.7" and python_full_version >= "3.6.2" decorator==4.4.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.2.0" and python_version >= "3.6" deprecated==1.2.11; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" ephem==3.7.7.1; python_version >= "2.7" and python_version < "4" @@ -55,7 +55,7 @@ langdetect==1.0.8; python_version >= "3.6" lunarcalendar==0.0.9; python_version >= "2.7" and python_version < "4" lxml==4.6.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" markdown==3.3.4; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.2.0" and python_version >= "3.6" -matplotlib==3.3.3; python_version >= "3.6" +matplotlib==3.3.4; python_version >= "3.6" more-itertools==8.7.0; python_version >= "3.5" mpld3==0.3; python_version >= "3.6" multidict==5.1.0; python_version >= "3.6" @@ -66,20 +66,20 @@ oauthlib==3.1.0; python_version >= "3.6" and python_full_version < "3.0.0" or py opt-einsum==3.3.0; python_version >= "3.5" overrides==3.0.0; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.6" packaging==20.9; python_full_version >= "3.6.0" and python_version >= "3.6" -pandas-ta==0.2.23b +pandas-ta==0.2.45b pandas==1.1.5; python_full_version >= "3.6.1" patsy==0.5.1; python_version >= "3.6" pillow==8.1.0; python_version >= "3.6" plotly==4.14.3 pmdarima==1.8.0; python_version >= "3.6" -praw==7.1.4; python_version >= "3.6" and python_version < "4.0" -prawcore==1.5.0; python_version >= "3.6" and python_version < "4.0" +praw==7.2.0; python_version >= "3.6" and python_version < "4.0" +prawcore==2.0.0; python_version >= "3.6" and python_version < "4.0" prettytable==2.0.0; python_version >= "3.6" protobuf==3.15.3; python_full_version >= "3.6.0" and python_version >= "3.6" and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.2.0") psaw==0.0.12; python_version >= "3" pyasn1-modules==0.2.8; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" pyasn1==0.4.8; python_version >= "3.5" and python_full_version < "3.0.0" and python_version < "4" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6") or python_version >= "3.5" and python_version < "4" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6") and python_full_version >= "3.6.0" -pymeeus==0.4.2; python_version >= "3.5" +pymeeus==0.4.3; python_version >= "3.5" pyparsing==2.4.7; python_full_version >= "3.6.0" and python_version >= "3.6" pysocks==1.7.1; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" pystan==2.19.1.1 From 9c125f62be0f7ce7b466e760394305da137ee0d0 Mon Sep 17 00:00:00 2001 From: Levi Blaney Date: Mon, 1 Mar 2021 10:04:12 -0500 Subject: [PATCH 44/72] add pythons 3.7 and 3.8 to test workflow --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1bfc6c42242..0eed218e168 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -5,7 +5,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ['3.6.13'] + python-version: ['3.6.8', '3.7', '3.8'] name: Python ${{ matrix.python-version }} steps: - name: Checkout Code From 2cd6a7e3edda3093ac42cdcf32212f29baeabf3c Mon Sep 17 00:00:00 2001 From: Levi Blaney Date: Mon, 1 Mar 2021 10:05:36 -0500 Subject: [PATCH 45/72] set python back to 3.6.13 --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0eed218e168..baf34dd5a3b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -5,7 +5,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ['3.6.8', '3.7', '3.8'] + python-version: ['3.6.13', '3.7', '3.8'] name: Python ${{ matrix.python-version }} steps: - name: Checkout Code From 534432cf12007640903cfb9fef3cd6850d78fac4 Mon Sep 17 00:00:00 2001 From: Ben Kulbertis Date: Mon, 1 Mar 2021 17:53:13 -0700 Subject: [PATCH 46/72] Add try/except --- gamestonk_terminal.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/gamestonk_terminal.py b/gamestonk_terminal.py index 171d0b3890d..ebcc0e53d05 100644 --- a/gamestonk_terminal.py +++ b/gamestonk_terminal.py @@ -310,8 +310,12 @@ def main(): b_quit = pm.pred_menu(df_stock, s_ticker, s_start, s_interval) # If stock data is intradaily, we need to get data again as prediction techniques work on daily adjusted data else: - ts = TimeSeries(key=cfg.API_KEY_ALPHAVANTAGE, output_format='pandas') - df_stock_pred, _ = ts.get_daily_adjusted(symbol=s_ticker, outputsize='full') + try: + ts = TimeSeries(key=cfg.API_KEY_ALPHAVANTAGE, output_format='pandas') + df_stock_pred, _ = ts.get_daily_adjusted(symbol=s_ticker, outputsize='full') + except: + print("Either the ticker or the API_KEY are invalids. Try again!") + return df_stock_pred = df_stock_pred.sort_index(ascending=True) df_stock_pred = df_stock_pred[s_start:] b_quit = pm.pred_menu(df_stock_pred, s_ticker, s_start, s_interval="1440min") From 75011a8da71f4972d2cac7aa6d9df84a58055eda Mon Sep 17 00:00:00 2001 From: sigaloid <69441971+sigaloid@users.noreply.github.com> Date: Tue, 2 Mar 2021 03:42:43 +0000 Subject: [PATCH 47/72] Update README.md --- README.md | 62 +++++++++++++++++++++++++++---------------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index a2136df071e..599be25376c 100644 --- a/README.md +++ b/README.md @@ -66,21 +66,21 @@ Command|Description|Source ### [Market Sentiment](sentiment/README.md) Command|Description ----|---- -[Reddit](https://reddit.com):| +[Reddit](https://reddit.com)| `wsb` |show what WSB gang is up to in subreddit wallstreetbets `watchlist` |show other users watchlist `popular` |show popular tickers `spac_c` |show other users spacs announcements from subreddit SPACs community `spac` |show other users spacs announcements from other subs -[Stocktwits](https://stocktwits.com/):| +[Stocktwits](https://stocktwits.com/)| `bullbear` |estimate quick sentiment from last 30 messages on board `messages` |output up to the 30 last messages on the board `trending` |trending stocks `stalker` |stalk stocktwits user's last message -[Twitter](https://twitter.com/):| +[Twitter](https://twitter.com/)| `infer` |infer about stock's sentiment from latest tweets `sentiment` |in-depth sentiment prediction from tweets over time -[Google](https://google.com/):| +[Google](https://google.com/)| `mentions` |interest over time based on stock's mentions `regions` |regions that show highest interest in stock `queries` |top related queries with this stock @@ -147,25 +147,25 @@ Command|Description ### [Technical Analysis](technical_analysis/README.md) -Command | Description | Wikipedia | Investopedia ------- | ------ | ------ | ----- +Command | Description | Sources +------ | ------ | ------ overlap: | -`ema` | exponential moving average | [Link](https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average) | [Link](https://www.investopedia.com/terms/e/ema.asp) -`sma` |simple moving average | [Link](https://en.wikipedia.org/wiki/Moving_average#Simple_moving_average_(boxcar_filter))| [Link](https://www.investopedia.com/terms/s/sma.asp) -`vwap` |volume weighted average price | [Link](https://en.wikipedia.org/wiki/Volume-weighted_average_price)| [Link](https://www.investopedia.com/terms/v/vwap.asp) +`ema` | exponential moving average | [Wikipedia](https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average), [Investopedia](https://www.investopedia.com/terms/e/ema.asp) +`sma` |simple moving average | [Wikipedia](https://en.wikipedia.org/wiki/Moving_average#Simple_moving_average_(boxcar_filter)), [Investopedia](https://www.investopedia.com/terms/s/sma.asp) +`vwap` |volume weighted average price | [Wikipedia](https://en.wikipedia.org/wiki/Volume-weighted_average_price), [Investopedia](https://www.investopedia.com/terms/v/vwap.asp) momentum: | -`cci` |commodity channel index | [Link](https://en.wikipedia.org/wiki/Commodity_channel_index)| [Link](https://www.investopedia.com/terms/c/commoditychannelindex.asp) -`macd` |moving average convergence/divergence | [Link](https://en.wikipedia.org/wiki/MACD)| [Link](https://www.investopedia.com/terms/m/macd.asp) -`rsi` |relative strength index | [Link](https://en.wikipedia.org/wiki/Relative_strength_index)| [Link](https://www.investopedia.com/terms/r/rsi.asp) -`stoch` |stochastic oscillator | [Link](https://en.wikipedia.org/wiki/Stochastic_oscillator)| [Link](https://www.investopedia.com/terms/s/stochasticoscillator.asp) +`cci` |commodity channel index | [Wikipedia](https://en.wikipedia.org/wiki/Commodity_channel_index), [Investopedia](https://www.investopedia.com/terms/c/commoditychannelindex.asp) +`macd` |moving average convergence/divergence | [Wikipedia](https://en.wikipedia.org/wiki/MACD), [Investopedia](https://www.investopedia.com/terms/m/macd.asp) +`rsi` |relative strength index | [Wikipedia](https://en.wikipedia.org/wiki/Relative_strength_index), [Investopedia](https://www.investopedia.com/terms/r/rsi.asp) +`stoch` |stochastic oscillator | [Wikipedia](https://en.wikipedia.org/wiki/Stochastic_oscillator), [Investopedia](https://www.investopedia.com/terms/s/stochasticoscillator.asp) trend: -`adx` |average directional movement index | [Link](https://en.wikipedia.org/wiki/Average_directional_movement_index)| [Link](https://www.investopedia.com/terms/a/adx.asp) -`aroon` |aroon indicator | [Link](https://www.investopedia.com/terms/a/aroon.asp) +`adx` |average directional movement index | [Wikipedia](https://en.wikipedia.org/wiki/Average_directional_movement_index), [Investopedia](https://www.investopedia.com/terms/a/adx.asp) +`aroon` |aroon indicator | [Investopedia](https://www.investopedia.com/terms/a/aroon.asp) volatility: | -`bbands` |bollinger bands | [Link](https://en.wikipedia.org/wiki/Bollinger_Bands)| [Link](https://www.investopedia.com/terms/b/bollingerbands.asp) +`bbands` |bollinger bands | [Wikipedia](https://en.wikipedia.org/wiki/Bollinger_Bands), [Investopedia](https://www.investopedia.com/terms/b/bollingerbands.asp) volume: | -`ad` |chaikin accumulation/distribution line values | [Link](https://en.wikipedia.org/wiki/Accumulation/distribution_index)| [Link](https://www.investopedia.com/terms/a/accumulationdistribution.asp) -`obv` |on balance volume | [Link](https://en.wikipedia.org/wiki/On-balance_volume)| [Link](https://www.investopedia.com/terms/o/onbalancevolume.asp) +`ad` |chaikin accumulation/distribution line values | [Wikipedia](https://en.wikipedia.org/wiki/Accumulation/distribution_index), [Investopedia](https://www.investopedia.com/terms/a/accumulationdistribution.asp) +`obv` |on balance volume | [Wikipedia](https://en.wikipedia.org/wiki/On-balance_volume), [Investopedia](https://www.investopedia.com/terms/o/onbalancevolume.asp) ### [Due Diligence](due_diligence/README.md) Command|Explanation|Source @@ -184,19 +184,19 @@ Command|Explanation|Source ### [Prediction Techniques](prediction_techniques/README.md) -Command|Technique|Wikipedia|Investopedia ------- | ------------|---|---- -`sma` |simple moving average | [Link](https://en.wikipedia.org/wiki/Moving_average#Simple_moving_average)| [Link](https://www.investopedia.com/terms/s/sma.asp) -`knn` |k-Nearest Neighbors | [Link](https://en.wikipedia.org/wiki/K-nearest_neighbors_algorithm) -`linear` |linear regression (polynomial 1) | [Link](https://en.wikipedia.org/wiki/Linear_regression)| [Link](https://www.investopedia.com/terms/r/regression.asp) -`quadratic` |quadratic regression (polynomial 2) | [Link](https://en.wikipedia.org/wiki/Polynomial_regression)| [Link](https://www.investopedia.com/terms/r/regression.asp) -`cubic` |cubic regression (polynomial 3) | [Link](https://en.wikipedia.org/wiki/Polynomial_regression)| [Link](https://www.investopedia.com/terms/r/regression.asp) -`regression` |regression (other polynomial) | [Link](https://en.wikipedia.org/wiki/Polynomial_regression)| [Link](https://www.investopedia.com/terms/r/regression.asp) -`arima` |autoregressive integrated moving average | [Link](https://en.wikipedia.org/wiki/Autoregressive_integrated_moving_average)| [Link](https://www.investopedia.com/terms/a/autoregressive-integrated-moving-average-arima.asp) -`prophet` |Facebook's prophet prediction ([Link](https://facebook.github.io/prophet/))| -`mlp` |MultiLayer Perceptron | [Link](https://en.wikipedia.org/wiki/Multilayer_perceptron) -`rnn` |Recurrent Neural Network | [Link](https://en.wikipedia.org/wiki/Recurrent_neural_network) -`lstm` |Long Short-Term Memory | [Link](https://en.wikipedia.org/wiki/Long_short-term_memory) +Command|Technique|Sources +------ | ------------|--- +`sma` |simple moving average | [Wikipedia](https://en.wikipedia.org/wiki/Moving_average#Simple_moving_average), [Investopedia](https://www.investopedia.com/terms/s/sma.asp) +`knn` |k-Nearest Neighbors | [Wikipedia](https://en.wikipedia.org/wiki/K-nearest_neighbors_algorithm) +`linear` |linear regression (polynomial 1) | [Wikipedia](https://en.wikipedia.org/wiki/Linear_regression), [Investopedia](https://www.investopedia.com/terms/r/regression.asp) +`quadratic` |quadratic regression (polynomial 2) | [Wikipedia](https://en.wikipedia.org/wiki/Polynomial_regression), [Investopedia](https://www.investopedia.com/terms/r/regression.asp) +`cubic` |cubic regression (polynomial 3) | [Wikipedia](https://en.wikipedia.org/wiki/Polynomial_regression), [Investopedia](https://www.investopedia.com/terms/r/regression.asp) +`regression` |regression (other polynomial) | [Wikipedia](https://en.wikipedia.org/wiki/Polynomial_regression), [Investopedia](https://www.investopedia.com/terms/r/regression.asp) +`arima` |autoregressive integrated moving average | [Wikipedia](https://en.wikipedia.org/wiki/Autoregressive_integrated_moving_average), [Investopedia](https://www.investopedia.com/terms/a/autoregressive-integrated-moving-average-arima.asp) +`prophet` |Facebook's prophet prediction | [Link](https://facebook.github.io/prophet/) +`mlp` |MultiLayer Perceptron | [Wikipedia](https://en.wikipedia.org/wiki/Multilayer_perceptron) +`rnn` |Recurrent Neural Network | [Wikipedia](https://en.wikipedia.org/wiki/Recurrent_neural_network) +`lstm` |Long Short-Term Memory | [Wikipedia](https://en.wikipedia.org/wiki/Long_short-term_memory) ## Install From b306135f9fca1d562b522080b6440b7d815da9b3 Mon Sep 17 00:00:00 2001 From: sigaloid <69441971+sigaloid@users.noreply.github.com> Date: Tue, 2 Mar 2021 03:43:02 +0000 Subject: [PATCH 48/72] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 599be25376c..58cfd7ce6d7 100644 --- a/README.md +++ b/README.md @@ -211,7 +211,7 @@ pip3 install -r requirements.txt ``` Then run: ``` -python3 gamestonk_terminal.py +python gamestonk_terminal.py ``` Note: The libraries specified in the [requirements.txt](/requirements.txt) file have been tested and work for the purpose of this project, however, these may be older versions. Hence, it is recommended for the user to set up a virtual python environment prior to installing these. This allows to keep dependencies required by different projects in separate places. From 8f3c8dc42500d27e88180547ea6806c52e015018 Mon Sep 17 00:00:00 2001 From: sigaloid <69441971+sigaloid@users.noreply.github.com> Date: Tue, 2 Mar 2021 03:44:23 +0000 Subject: [PATCH 49/72] pip3->pip --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 58cfd7ce6d7..afbdcc77917 100644 --- a/README.md +++ b/README.md @@ -207,7 +207,7 @@ In order to install, you must run: ``` git clone https://github.com/DidierRLopes/GamestonkTerminal cd GamestonkTerminal/ -pip3 install -r requirements.txt +pip install -r requirements.txt ``` Then run: ``` From b7835545d808ff14f7aa3b340131f5f16c13dae9 Mon Sep 17 00:00:00 2001 From: didier Date: Tue, 2 Mar 2021 22:12:51 +0000 Subject: [PATCH 50/72] Modify pystan to 2.18 on requirements.txt for fbprophet to build --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index e9c73f22e57..1fa6cca3943 100644 --- a/requirements.txt +++ b/requirements.txt @@ -82,7 +82,7 @@ pyasn1==0.4.8; python_version >= "3.5" and python_full_version < "3.0.0" and pyt pymeeus==0.4.3; python_version >= "3.5" pyparsing==2.4.7; python_full_version >= "3.6.0" and python_version >= "3.6" pysocks==1.7.1; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" -pystan==2.19.1.1 +pystan==2.18 python-dateutil==2.8.1; python_full_version >= "3.6.1" and python_version >= "3.5" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.6") and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.3.0") and (python_version >= "2.7" and python_full_version < "3.0.0" and python_version < "4" or python_version >= "2.7" and python_version < "4" and python_full_version >= "3.3.0") pytrends==4.7.3 pytz==2021.1; python_full_version >= "3.6.1" and python_version >= "3.5" and python_version < "4" From 0f2c1fac699a200bc061e535f25ec903f942799b Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Tue, 2 Mar 2021 22:48:32 +0000 Subject: [PATCH 51/72] Add pandas-ta hyperlinks to README --- README.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 26a11e4ad41..fd03363fcbb 100644 --- a/README.md +++ b/README.md @@ -149,21 +149,21 @@ Command|Description ### [Technical Analysis](technical_analysis/README.md) Command | Description | Sources ------ | ------ | ------ -overlap: | +[overlap](https://github.com/twopirllc/pandas-ta/tree/master/pandas_ta/overlap) | `ema` | exponential moving average | [Wikipedia](https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average), [Investopedia](https://www.investopedia.com/terms/e/ema.asp) `sma` |simple moving average | [Wikipedia](https://en.wikipedia.org/wiki/Moving_average#Simple_moving_average_(boxcar_filter)), [Investopedia](https://www.investopedia.com/terms/s/sma.asp) `vwap` |volume weighted average price | [Wikipedia](https://en.wikipedia.org/wiki/Volume-weighted_average_price), [Investopedia](https://www.investopedia.com/terms/v/vwap.asp) -momentum: | +[momentum](https://github.com/twopirllc/pandas-ta/tree/master/pandas_ta/momentum) | `cci` |commodity channel index | [Wikipedia](https://en.wikipedia.org/wiki/Commodity_channel_index), [Investopedia](https://www.investopedia.com/terms/c/commoditychannelindex.asp) `macd` |moving average convergence/divergence | [Wikipedia](https://en.wikipedia.org/wiki/MACD), [Investopedia](https://www.investopedia.com/terms/m/macd.asp) `rsi` |relative strength index | [Wikipedia](https://en.wikipedia.org/wiki/Relative_strength_index), [Investopedia](https://www.investopedia.com/terms/r/rsi.asp) `stoch` |stochastic oscillator | [Wikipedia](https://en.wikipedia.org/wiki/Stochastic_oscillator), [Investopedia](https://www.investopedia.com/terms/s/stochasticoscillator.asp) -trend: +[trend](https://github.com/twopirllc/pandas-ta/tree/master/pandas_ta/trend) | `adx` |average directional movement index | [Wikipedia](https://en.wikipedia.org/wiki/Average_directional_movement_index), [Investopedia](https://www.investopedia.com/terms/a/adx.asp) `aroon` |aroon indicator | [Investopedia](https://www.investopedia.com/terms/a/aroon.asp) -volatility: | +[volatility](https://github.com/twopirllc/pandas-ta/tree/master/pandas_ta/volatility) | `bbands` |bollinger bands | [Wikipedia](https://en.wikipedia.org/wiki/Bollinger_Bands), [Investopedia](https://www.investopedia.com/terms/b/bollingerbands.asp) -volume: | +[volume](https://github.com/twopirllc/pandas-ta/tree/master/pandas_ta/volume) | `ad` |chaikin accumulation/distribution line values | [Wikipedia](https://en.wikipedia.org/wiki/Accumulation/distribution_index), [Investopedia](https://www.investopedia.com/terms/a/accumulationdistribution.asp) `obv` |on balance volume | [Wikipedia](https://en.wikipedia.org/wiki/On-balance_volume), [Investopedia](https://www.investopedia.com/terms/o/onbalancevolume.asp) @@ -193,10 +193,12 @@ Command|Technique|Sources `cubic` |cubic regression (polynomial 3) | [Wikipedia](https://en.wikipedia.org/wiki/Polynomial_regression), [Investopedia](https://www.investopedia.com/terms/r/regression.asp) `regression` |regression (other polynomial) | [Wikipedia](https://en.wikipedia.org/wiki/Polynomial_regression), [Investopedia](https://www.investopedia.com/terms/r/regression.asp) `arima` |autoregressive integrated moving average | [Wikipedia](https://en.wikipedia.org/wiki/Autoregressive_integrated_moving_average), [Investopedia](https://www.investopedia.com/terms/a/autoregressive-integrated-moving-average-arima.asp) -`prophet` |Facebook's prophet prediction | [Link](https://facebook.github.io/prophet/) +`prophet` |Facebook's prophet prediction | [Details](https://facebook.github.io/prophet/) `mlp` |MultiLayer Perceptron | [Wikipedia](https://en.wikipedia.org/wiki/Multilayer_perceptron) `rnn` |Recurrent Neural Network | [Wikipedia](https://en.wikipedia.org/wiki/Recurrent_neural_network) -`lstm` |Long Short-Term Memory | [Wikipedia](https://en.wikipedia.org/wiki/Long_short-term_memory) +`lstm` |Long Short-Term Memory | [Wikipedia](https://en.wikipedia.org/wiki/Long_short-term_memory), [Details](https://colah.github.io/posts/2015-08-Understanding-LSTMs/) + + ## Install From ddcede918fb2fca868367d1721e85e4f67562bf5 Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Tue, 2 Mar 2021 22:56:08 +0000 Subject: [PATCH 52/72] Update bug_report.md --- .github/ISSUE_TEMPLATE/bug_report.md | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 8909c8e97fb..73b47b27ba4 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -2,31 +2,22 @@ name: Bug report about: Create a report to help us improve title: "[Bug]" -labels: '' +labels: 'bug' assignees: '' - --- **Describe the bug** A clear and concise description of what the bug is. **To Reproduce** -Steps and commands to reproduce the behavior: -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error - -**Expected behavior** -A clear and concise description of what you expected to happen. +Steps(from the start) and commands to reproduce the behavior **Screenshots** If applicable, add screenshots to help explain your problem. **Desktop (please complete the following information):** - - OS: [e.g. iOS] - - Browser [e.g. chrome, safari] - - Version [e.g. 22] + - OS: [e.g. Mac Sierra] + - Python version [e.g. 3.6.8] **Additional context** -Add any other context about the problem here. +Add any other information that you think could be useful for us. From 06146c0c981d241b2fba8c62d2f8ff64f914640d Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Tue, 2 Mar 2021 23:01:55 +0000 Subject: [PATCH 53/72] Update feature_request.md --- .github/ISSUE_TEMPLATE/feature_request.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 9e8ab6a673f..34e85b37947 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -2,19 +2,19 @@ name: Feature request about: Suggest an idea for this project title: "[FR]" -labels: '' +labels: 'new feature' assignees: '' --- -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] +**What's the problem of not having this feature?** +A clear description of what you are lacking, or why you need this additional feature. -**Describe the solution you'd like** -A clear and concise description of what you want to happen. +**Describe the solution you would like** +A description of what you think would be the best solution for this. From user inputs, to an output. **Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. +If there are other alternatives (worth considering) to your solution, list them here. -**Additional context** -Add any other context or screenshots about the feature request here. +**Additional information** +Add any other information or screenshots about the feature request here. From 878f82ffe9ec3aaa2ccfb1c07de3e6bb360dfb65 Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Tue, 2 Mar 2021 23:09:23 +0000 Subject: [PATCH 54/72] Create enhancement.md --- .github/ISSUE_TEMPLATE/enhancement.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/enhancement.md diff --git a/.github/ISSUE_TEMPLATE/enhancement.md b/.github/ISSUE_TEMPLATE/enhancement.md new file mode 100644 index 00000000000..f568e1ff2e6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/enhancement.md @@ -0,0 +1,20 @@ +--- +name: Improvement +about: Improve something on this project +title: "[IMPROVE]" +labels: 'enhancement' +assignees: '' + +--- + +**What's the feature that should be improved?** +A description of what's the feature you want improved, and a bit of context (why is that). + +**Describe how you would like the feature improved** +A description of what the current feature is vs what it would be after your suggestion. + +**Possibly describe the ideal way to improve this** +If you have thought about how you would do it, add it here. + +**Additional information** +Add any other information or screenshots about the feature improvement. From 04073787b0642f4eb11d92ddd1bbf793f1a9e833 Mon Sep 17 00:00:00 2001 From: Levi Blaney Date: Wed, 3 Mar 2021 02:13:07 -0500 Subject: [PATCH 55/72] change Test action so it runs on every PR --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index baf34dd5a3b..53508333d29 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,5 +1,5 @@ name: Tests -on: push +on: [pull_request, push] jobs: tests: runs-on: ubuntu-latest From 6d1ad0a8df0c15b2de5c6171eed7cc180afc1e0b Mon Sep 17 00:00:00 2001 From: Levi Blaney Date: Wed, 3 Mar 2021 02:13:40 -0500 Subject: [PATCH 56/72] change tests to run on windows and mac. --- .github/workflows/test.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 53508333d29..62ddc1cf2f8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -2,10 +2,12 @@ name: Tests on: [pull_request, push] jobs: tests: - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} strategy: + fail-fast: false matrix: python-version: ['3.6.13', '3.7', '3.8'] + os: [ubuntu-latest, macos-latest, windows-latest] name: Python ${{ matrix.python-version }} steps: - name: Checkout Code From 29a4f8952fbd3748ad09584bdcf794d28fabe229 Mon Sep 17 00:00:00 2001 From: Levi Blaney Date: Wed, 3 Mar 2021 02:37:24 -0500 Subject: [PATCH 57/72] fix windows test --- .github/workflows/test.yml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 62ddc1cf2f8..93b204eeecb 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -3,12 +3,15 @@ on: [pull_request, push] jobs: tests: runs-on: ${{ matrix.os }} + defaults: + run: + shell: bash strategy: fail-fast: false matrix: - python-version: ['3.6.13', '3.7', '3.8'] + python-version: ['3.6', '3.7', '3.8'] os: [ubuntu-latest, macos-latest, windows-latest] - name: Python ${{ matrix.python-version }} + name: ${{ matrix.os}} Python ${{ matrix.python-version }} steps: - name: Checkout Code uses: actions/checkout@v2 @@ -36,9 +39,12 @@ jobs: if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true' run: poetry install --no-interaction --no-root + - name: Install Package + run: poetry install --no-interaction + - name: Run tests env: MPLBACKEND: Agg run: | - source .venv/bin/activate + source $VENV pytest tests/ From 6f20d6cf0d637851ee02d9233c5f0272b6295820 Mon Sep 17 00:00:00 2001 From: Levi Blaney Date: Wed, 3 Mar 2021 04:07:35 -0500 Subject: [PATCH 58/72] refactored github actions --- .github/workflows/lint_python.yml | 20 -------- .github/workflows/test.yml | 82 ++++++++++++++++++++++++++++--- 2 files changed, 76 insertions(+), 26 deletions(-) delete mode 100644 .github/workflows/lint_python.yml diff --git a/.github/workflows/lint_python.yml b/.github/workflows/lint_python.yml deleted file mode 100644 index 3365e5f3f6b..00000000000 --- a/.github/workflows/lint_python.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: lint_python -on: [pull_request, push] -jobs: - lint_python: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 - - run: pip install bandit black codespell flake8 isort mypy pytest pyupgrade safety - - run: bandit -r . || true - - run: black --check . || true - - run: codespell --ignore-words-list="mape" --quiet-level=2 # --skip="" - - run: flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics - - run: isort --check-only --profile black . || true - - run: pip install -r requirements.txt || true - - run: mypy --ignore-missing-imports . || true - - run: pytest . || true - - run: pytest --doctest-modules . || true - - run: shopt -s globstar && pyupgrade --py36-plus **/*.py || true - - run: safety check diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 93b204eeecb..9af512b8f14 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,17 +1,87 @@ name: Tests on: [pull_request, push] jobs: + linting: + name: Linting + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v2 + + - name: Setup Python 3.8 + uses: actions/setup-python@v1 + with: + python-version: "3.8" + architecture: x64 + + - uses: actions/cache@v2 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-lint + restore-keys: ${{ runner.os }}-lint + + - run: pip install bandit black codespell flake8 isort mypy pyupgrade safety + - run: bandit -r . || true + - run: black --check . || true + - run: codespell --ignore-words-list="mape" --quiet-level=2 # --skip="" + - run: flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics + - run: isort --check-only --profile black . || true + - run: pip install -r requirements.txt || true + - run: mypy --ignore-missing-imports . || true + - run: shopt -s globstar && pyupgrade --py36-plus **/*.py || true + - run: safety check + test: + name: ubuntu-latest - Python 3.8 + needs: linting + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v2 + + - name: Setup Python 3.8 + uses: actions/setup-python@v1 + with: + python-version: "3.8" + architecture: x64 + + - name: Install Poetry + uses: snok/install-poetry@v1.1.1 + with: + virtualenvs-create: true + virtualenvs-in-project: true + + - name: Load cached venv + id: cached-poetry-dependencies + uses: actions/cache@v2 + with: + path: .venv + key: venv-${{ runner.os }}-${{ hashFiles('**/poetry.lock') }} + + - name: Install dependencies + if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true' + run: poetry install --no-interaction --no-root + + - name: Install Package + run: poetry install --no-interaction + + - name: Run tests + env: + MPLBACKEND: Agg + run: | + source $VENV + pytest tests/ tests: + needs: test runs-on: ${{ matrix.os }} - defaults: - run: - shell: bash strategy: - fail-fast: false + fail-fast: true matrix: python-version: ['3.6', '3.7', '3.8'] - os: [ubuntu-latest, macos-latest, windows-latest] - name: ${{ matrix.os}} Python ${{ matrix.python-version }} + os: [ubuntu-latest, macos-latest] + exclude: + - os: ubuntu-latest + python-version: '3.8' + name: ${{ matrix.os}} - Python ${{ matrix.python-version }} steps: - name: Checkout Code uses: actions/checkout@v2 From 3b4cf432487d9f4eb73231b7e4455ee78514cd51 Mon Sep 17 00:00:00 2001 From: Levi Blaney Date: Wed, 3 Mar 2021 04:09:24 -0500 Subject: [PATCH 59/72] fix yaml format --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9af512b8f14..3260ac31c77 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,7 +1,7 @@ name: Tests on: [pull_request, push] jobs: - linting: + linting: name: Linting runs-on: ubuntu-latest steps: From d0ef5223d90cc7c410ac52f53b2db32289764a5b Mon Sep 17 00:00:00 2001 From: Levi Blaney Date: Wed, 3 Mar 2021 04:10:24 -0500 Subject: [PATCH 60/72] fix matrix exclude --- .github/workflows/test.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3260ac31c77..7373d0c32d5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -78,9 +78,9 @@ jobs: matrix: python-version: ['3.6', '3.7', '3.8'] os: [ubuntu-latest, macos-latest] - exclude: - - os: ubuntu-latest - python-version: '3.8' + exclude: + - os: ubuntu-latest + python-version: '3.8' name: ${{ matrix.os}} - Python ${{ matrix.python-version }} steps: - name: Checkout Code From 1ed531b7cad576578a7708066f8df2e140caafa8 Mon Sep 17 00:00:00 2001 From: Levi Blaney Date: Wed, 3 Mar 2021 04:14:23 -0500 Subject: [PATCH 61/72] remove package install from linting --- .github/workflows/test.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7373d0c32d5..831a0a6cda5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -17,8 +17,8 @@ jobs: - uses: actions/cache@v2 with: path: ~/.cache/pip - key: ${{ runner.os }}-lint - restore-keys: ${{ runner.os }}-lint + key: ${{ runner.os }}-linting + restore-keys: ${{ runner.os }}-linting - run: pip install bandit black codespell flake8 isort mypy pyupgrade safety - run: bandit -r . || true @@ -26,7 +26,6 @@ jobs: - run: codespell --ignore-words-list="mape" --quiet-level=2 # --skip="" - run: flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics - run: isort --check-only --profile black . || true - - run: pip install -r requirements.txt || true - run: mypy --ignore-missing-imports . || true - run: shopt -s globstar && pyupgrade --py36-plus **/*.py || true - run: safety check From 4b12fe6a05a4fc745d1ab0749611a0c0bb45c3cb Mon Sep 17 00:00:00 2001 From: Levi Date: Wed, 3 Mar 2021 19:01:12 +0530 Subject: [PATCH 62/72] Update .github/workflows/test.yml Co-authored-by: Christian Clauss --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 831a0a6cda5..698039aff9a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -9,7 +9,7 @@ jobs: uses: actions/checkout@v2 - name: Setup Python 3.8 - uses: actions/setup-python@v1 + uses: actions/setup-python@v2 with: python-version: "3.8" architecture: x64 From 598a9ab18f40cdc2703ad74158ebf3cdb0767e96 Mon Sep 17 00:00:00 2001 From: Levi Date: Wed, 3 Mar 2021 19:35:31 +0530 Subject: [PATCH 63/72] Apply suggestions from code review Co-authored-by: Christian Clauss --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 698039aff9a..49dcf5a5c68 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -38,7 +38,7 @@ jobs: uses: actions/checkout@v2 - name: Setup Python 3.8 - uses: actions/setup-python@v1 + uses: actions/setup-python@v2 with: python-version: "3.8" architecture: x64 From 00221d88d998e687a1aee4b6d3702e47d86951fd Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Thu, 25 Feb 2021 10:15:16 +0200 Subject: [PATCH 64/72] Clean up imports --- discovery/alpha_vantage_api.py | 8 ++++--- discovery/disc_menu.py | 12 +++++----- discovery/fidelity_api.py | 8 ++++--- discovery/seeking_alpha_api.py | 6 +++-- discovery/short_interest_api.py | 8 +++---- discovery/yahoo_finance_api.py | 6 ++--- due_diligence/business_insider_api.py | 19 ++++++++------- due_diligence/dd_menu.py | 18 ++++----------- due_diligence/financial_modeling_prep_api.py | 11 ++++----- due_diligence/finviz_api.py | 7 ++++-- due_diligence/market_watch_api.py | 8 ++++--- due_diligence/quandl_api.py | 11 +++++---- due_diligence/reddit_api.py | 16 +++++-------- fundamental_analysis/alpha_vantage_api.py | 9 ++++---- fundamental_analysis/business_insider_api.py | 11 ++++----- fundamental_analysis/fa_menu.py | 14 ++--------- .../financial_modeling_prep_api.py | 13 +++++++---- fundamental_analysis/finviz_api.py | 4 ++-- fundamental_analysis/market_watch_api.py | 6 ++--- fundamental_analysis/yahoo_finance_api.py | 7 +++--- gamestonk_terminal.py | 22 ++++++++++-------- helper_funcs.py | 23 ++++++++----------- prediction_techniques/arima.py | 7 ++++-- prediction_techniques/fbprophet.py | 8 +++---- prediction_techniques/knn.py | 8 ++++--- prediction_techniques/neural_networks.py | 11 +++++---- prediction_techniques/pred_menu.py | 11 ++++----- prediction_techniques/regression.py | 8 ++++--- prediction_techniques/sma.py | 9 +++++--- res_menu.py | 1 - sentiment/google_api.py | 10 ++++---- sentiment/reddit_api.py | 21 ++++++++--------- sentiment/sen_menu.py | 6 ++--- sentiment/stocktwits_api.py | 5 +++- sentiment/twitter_api.py | 10 ++++---- technical_analysis/momentum.py | 6 +++-- technical_analysis/overlap.py | 6 +++-- technical_analysis/ta_menu.py | 13 ++--------- technical_analysis/trend.py | 6 +++-- technical_analysis/volatility.py | 6 +++-- technical_analysis/volume.py | 6 +++-- 41 files changed, 201 insertions(+), 204 deletions(-) diff --git a/discovery/alpha_vantage_api.py b/discovery/alpha_vantage_api.py index a5cff863e03..ef0dfb25f0f 100644 --- a/discovery/alpha_vantage_api.py +++ b/discovery/alpha_vantage_api.py @@ -1,8 +1,10 @@ import argparse -from alpha_vantage.sectorperformance import SectorPerformances -import config_terminal as cfg -import pandas as pd + import matplotlib.pyplot as plt +from alpha_vantage.sectorperformance import SectorPerformances + +import config_terminal as cfg + # ---------------------------------------------------- SECTORS ---------------------------------------------------- def sectors(l_args): diff --git a/discovery/disc_menu.py b/discovery/disc_menu.py index e46c894dd6e..5e2c0e64d03 100644 --- a/discovery/disc_menu.py +++ b/discovery/disc_menu.py @@ -1,14 +1,14 @@ -import config_terminal as cfg import argparse + from discovery import alpha_vantage_api -from discovery import yahoo_finance_api -from discovery import finviz_api -from discovery import short_interest_api -from discovery import seeking_alpha_api from discovery import fidelity_api +from discovery import finviz_api +from discovery import seeking_alpha_api +from discovery import short_interest_api from discovery import simply_wallst_api from discovery import spachero_api from discovery import unusual_whales_api +from discovery import yahoo_finance_api # ----------------------------------------------------------------------------------------------------------------------- @@ -111,4 +111,4 @@ def disc_menu(): # ------------------------------------------------------------------------------------------------------------ else: - print("Command not recognized!") \ No newline at end of file + print("Command not recognized!") diff --git a/discovery/fidelity_api.py b/discovery/fidelity_api.py index 5307e2e96d5..d469c55cf6d 100644 --- a/discovery/fidelity_api.py +++ b/discovery/fidelity_api.py @@ -1,10 +1,12 @@ import argparse -from bs4 import BeautifulSoup -import requests + import pandas as pd -import re +import requests +from bs4 import BeautifulSoup + from helper_funcs import * + # ---------------------------------------------------- ORDERS ---------------------------------------------------- def orders(l_args): parser = argparse.ArgumentParser(prog='orders', diff --git a/discovery/seeking_alpha_api.py b/discovery/seeking_alpha_api.py index 34c4c8cc591..1d38cf33518 100644 --- a/discovery/seeking_alpha_api.py +++ b/discovery/seeking_alpha_api.py @@ -1,7 +1,9 @@ import argparse -from bs4 import BeautifulSoup -import requests + import pandas as pd +import requests +from bs4 import BeautifulSoup + from helper_funcs import * diff --git a/discovery/short_interest_api.py b/discovery/short_interest_api.py index 351eec49bb4..247df24b6bb 100644 --- a/discovery/short_interest_api.py +++ b/discovery/short_interest_api.py @@ -1,9 +1,9 @@ import argparse -import webbrowser -from bs4 import BeautifulSoup -import requests + import pandas as pd -import re +import requests +from bs4 import BeautifulSoup + from helper_funcs import * diff --git a/discovery/yahoo_finance_api.py b/discovery/yahoo_finance_api.py index b234eab9ae4..d0eeaf6b788 100644 --- a/discovery/yahoo_finance_api.py +++ b/discovery/yahoo_finance_api.py @@ -1,8 +1,8 @@ import argparse -from alpha_vantage.sectorperformance import SectorPerformances -from alpha_vantage.timeseries import TimeSeries -import config_terminal as cfg + import pandas as pd + + #from helper_funcs import * diff --git a/due_diligence/business_insider_api.py b/due_diligence/business_insider_api.py index ed370ac832c..c323a95cb05 100644 --- a/due_diligence/business_insider_api.py +++ b/due_diligence/business_insider_api.py @@ -1,16 +1,15 @@ -from bs4 import BeautifulSoup -from alpha_vantage.timeseries import TimeSeries -from helper_funcs import * -import requests -import pandas as pd -import re -import json -import config_terminal as cfg -from datetime import datetime import argparse -from rapidfuzz import fuzz +import json +import re + import matplotlib.pyplot as plt +import pandas as pd +import requests +from bs4 import BeautifulSoup from pandas.plotting import register_matplotlib_converters + +from helper_funcs import check_positive + register_matplotlib_converters() diff --git a/due_diligence/dd_menu.py b/due_diligence/dd_menu.py index 193817b787c..118faec9b5c 100644 --- a/due_diligence/dd_menu.py +++ b/due_diligence/dd_menu.py @@ -1,21 +1,11 @@ -import FundamentalAnalysis as fa -from alpha_vantage.fundamentaldata import FundamentalData -import config_terminal as cfg import argparse -import datetime -from datetime import datetime -from helper_funcs import * -import pandas as pd -import json -import requests -from pandas.io.json import json_normalize +from due_diligence import business_insider_api as bi_api +from due_diligence import financial_modeling_prep_api as fmp_api from due_diligence import finviz_api as fvz_api from due_diligence import market_watch_api as mw_api -from due_diligence import reddit_api as r_api from due_diligence import quandl_api as q_api -from due_diligence import financial_modeling_prep_api as fmp_api -from due_diligence import business_insider_api as bi_api +from due_diligence import reddit_api as r_api # ----------------------------------------------------------------------------------------------------------------------- @@ -128,4 +118,4 @@ def dd_menu(df_stock, s_ticker, s_start, s_interval): q_api.short_interest(l_args, s_ticker, s_start) else: - print("Command not recognized!") \ No newline at end of file + print("Command not recognized!") diff --git a/due_diligence/financial_modeling_prep_api.py b/due_diligence/financial_modeling_prep_api.py index 9f47e18cecd..936202a7594 100644 --- a/due_diligence/financial_modeling_prep_api.py +++ b/due_diligence/financial_modeling_prep_api.py @@ -1,10 +1,9 @@ -import FundamentalAnalysis as fa # Financial Modeling Prep -import config_terminal as cfg import argparse -import datetime -from datetime import datetime -from helper_funcs import * -import pandas as pd + +import FundamentalAnalysis as fa # Financial Modeling Prep + +import config_terminal as cfg + # ---------------------------------------------------- RATING ---------------------------------------------------- def rating(l_args, s_ticker): diff --git a/due_diligence/finviz_api.py b/due_diligence/finviz_api.py index 542c2860e16..64a80d3fd7f 100644 --- a/due_diligence/finviz_api.py +++ b/due_diligence/finviz_api.py @@ -1,8 +1,11 @@ -import finviz import argparse -from helper_funcs import * + +import finviz import pandas as pd +from helper_funcs import * + + # ---------------------------------------------------- INSIDER ---------------------------------------------------- def insider(l_args, s_ticker): parser = argparse.ArgumentParser(prog='insider', diff --git a/due_diligence/market_watch_api.py b/due_diligence/market_watch_api.py index 9489c29276b..54e5bdc6b03 100644 --- a/due_diligence/market_watch_api.py +++ b/due_diligence/market_watch_api.py @@ -1,8 +1,10 @@ import argparse -import pandas as pd -from bs4 import BeautifulSoup -import requests + import numpy as np +import pandas as pd +import requests +from bs4 import BeautifulSoup + from helper_funcs import * diff --git a/due_diligence/quandl_api.py b/due_diligence/quandl_api.py index 62606b1d4f6..a4e9c557ecb 100644 --- a/due_diligence/quandl_api.py +++ b/due_diligence/quandl_api.py @@ -1,13 +1,14 @@ -import quandl -from datetime import datetime -import config_terminal as cfg import argparse -from matplotlib import pyplot as plt -import numpy as np + import matplotlib.ticker as ticker import pandas as pd +import quandl +from matplotlib import pyplot as plt + +import config_terminal as cfg from helper_funcs import * + # -------------------------------------------------------- SHORT_INTEREST -------------------------------------------------------- def short_interest(l_args, s_ticker, s_start): parser = argparse.ArgumentParser(prog='short', diff --git a/due_diligence/reddit_api.py b/due_diligence/reddit_api.py index cdd685914d0..1f589ba58da 100644 --- a/due_diligence/reddit_api.py +++ b/due_diligence/reddit_api.py @@ -1,16 +1,12 @@ import argparse -from prettytable import PrettyTable -from datetime import datetime, timedelta -import pandas as pd -from psaw import PushshiftAPI + import praw -from datetime import datetime -from pytz import timezone -from holidays import US as holidaysUS -from helper_funcs import * -import re -import finviz +from prettytable import PrettyTable +from psaw import PushshiftAPI + import config_terminal as cfg +from helper_funcs import * + # ------------------------------------------------------------------------------------------------------------------- def due_diligence(l_args, s_ticker): diff --git a/fundamental_analysis/alpha_vantage_api.py b/fundamental_analysis/alpha_vantage_api.py index 8de17800192..08e3968586e 100644 --- a/fundamental_analysis/alpha_vantage_api.py +++ b/fundamental_analysis/alpha_vantage_api.py @@ -1,12 +1,13 @@ -from alpha_vantage.fundamentaldata import FundamentalData -import config_terminal as cfg import argparse -from helper_funcs import * + import pandas as pd -import json import requests +from alpha_vantage.fundamentaldata import FundamentalData from pandas.io.json import json_normalize +import config_terminal as cfg +from helper_funcs import * + # ---------------------------------------------------- OVERVIEW ---------------------------------------------------- def overview(l_args, s_ticker): diff --git a/fundamental_analysis/business_insider_api.py b/fundamental_analysis/business_insider_api.py index 5c3cfc9402a..b9e43e25376 100644 --- a/fundamental_analysis/business_insider_api.py +++ b/fundamental_analysis/business_insider_api.py @@ -1,13 +1,10 @@ -from bs4 import BeautifulSoup -import requests -import pandas as pd -import re -import json -import config_terminal as cfg -from datetime import datetime import argparse from rapidfuzz import fuzz +import pandas as pd +import requests +from bs4 import BeautifulSoup + # ---------------------------------------------------- MANAGEMENT ---------------------------------------------------- def management(l_args, s_ticker): diff --git a/fundamental_analysis/fa_menu.py b/fundamental_analysis/fa_menu.py index 850a30e2879..5eb1f18a78e 100644 --- a/fundamental_analysis/fa_menu.py +++ b/fundamental_analysis/fa_menu.py @@ -1,20 +1,10 @@ -import FundamentalAnalysis as fa -from alpha_vantage.fundamentaldata import FundamentalData -import config_terminal as cfg import argparse -import datetime -from datetime import datetime -from helper_funcs import * -import pandas as pd -import json -import requests -from pandas.io.json import json_normalize from fundamental_analysis import alpha_vantage_api as av_api +from fundamental_analysis import business_insider_api as bi_api from fundamental_analysis import financial_modeling_prep_api as fmp_api from fundamental_analysis import finviz_api as fvz_api from fundamental_analysis import market_watch_api as mw_api -from fundamental_analysis import business_insider_api as bi_api from fundamental_analysis import yahoo_finance_api as yf_api @@ -232,4 +222,4 @@ def fa_menu(s_ticker, s_start, s_interval): fmp_api.financial_statement_growth(l_args, s_ticker) else: - print("Command not recognized!") \ No newline at end of file + print("Command not recognized!") diff --git a/fundamental_analysis/financial_modeling_prep_api.py b/fundamental_analysis/financial_modeling_prep_api.py index 7ff1558b585..5badf276bb2 100644 --- a/fundamental_analysis/financial_modeling_prep_api.py +++ b/fundamental_analysis/financial_modeling_prep_api.py @@ -1,11 +1,11 @@ -import FundamentalAnalysis as fa # Financial Modeling Prep -import config_terminal as cfg -import argparse import datetime -from datetime import datetime -from helper_funcs import * + +import FundamentalAnalysis as fa # Financial Modeling Prep import pandas as pd +import config_terminal as cfg +from helper_funcs import * + # ---------------------------------------------------- PROFILE ---------------------------------------------------- def profile(l_args, s_ticker): @@ -509,4 +509,7 @@ def financial_statement_growth(l_args, s_ticker): except: print("") return +<<<<<<< HEAD +======= +>>>>>>> 63fc66c... Clean up imports diff --git a/fundamental_analysis/finviz_api.py b/fundamental_analysis/finviz_api.py index f604acf73bc..10110ba25e9 100644 --- a/fundamental_analysis/finviz_api.py +++ b/fundamental_analysis/finviz_api.py @@ -1,6 +1,6 @@ -import finviz import argparse -from helper_funcs import * + +import finviz import pandas as pd diff --git a/fundamental_analysis/market_watch_api.py b/fundamental_analysis/market_watch_api.py index 65b90d5656f..d4beebea557 100644 --- a/fundamental_analysis/market_watch_api.py +++ b/fundamental_analysis/market_watch_api.py @@ -1,9 +1,9 @@ import argparse + import pandas as pd -from bs4 import BeautifulSoup import requests -import numpy as np -from helper_funcs import * +from bs4 import BeautifulSoup + # ---------------------------------------------------- INCOME ---------------------------------------------------- def income(l_args, s_ticker): diff --git a/fundamental_analysis/yahoo_finance_api.py b/fundamental_analysis/yahoo_finance_api.py index 1cb18cf2558..fbf1e7115e0 100644 --- a/fundamental_analysis/yahoo_finance_api.py +++ b/fundamental_analysis/yahoo_finance_api.py @@ -1,7 +1,8 @@ -import yfinance as yf -import pandas as pd -import config_terminal as cfg import argparse + +import pandas as pd +import yfinance as yf + from helper_funcs import * diff --git a/gamestonk_terminal.py b/gamestonk_terminal.py index a2f4f17d4c9..17795911db9 100644 --- a/gamestonk_terminal.py +++ b/gamestonk_terminal.py @@ -2,17 +2,21 @@ """ import argparse + import pandas as pd -from helper_funcs import * -from fundamental_analysis import fa_menu as fam -from technical_analysis import ta_menu as tam -from due_diligence import dd_menu as ddm -from discovery import disc_menu as dm -from sentiment import sen_menu as sm -from prediction_techniques import pred_menu as pm -import res_menu as rm -import config_terminal as cfg from alpha_vantage.timeseries import TimeSeries + +import config_terminal as cfg +import res_menu as rm +from discovery import disc_menu as dm +from due_diligence import dd_menu as ddm +from fundamental_analysis import fa_menu as fam +from helper_funcs import * +from prediction_techniques import pred_menu as pm +from sentiment import sen_menu as sm +from technical_analysis import ta_menu as tam + + #import warnings #warnings.simplefilter("always") diff --git a/helper_funcs.py b/helper_funcs.py index 661534b51b4..867daaabe57 100644 --- a/helper_funcs.py +++ b/helper_funcs.py @@ -1,18 +1,13 @@ - -from pytz import timezone -from holidays import US as holidaysUS -from datetime import datetime, time as Time -import re -import numpy as np -import sys -import iso8601 -import matplotlib -import matplotlib.pyplot as plt -from datetime import timedelta -from pytz import timezone -from holidays import US as holidaysUS -from datetime import datetime, timedelta, time as Time import argparse +import re +import sys +from datetime import datetime, timedelta, time as Time + +import iso8601 +import matplotlib.pyplot as plt +from holidays import US as holidaysUS +from pytz import timezone + # ----------------------------------------------------------------------------------------------------------------------- def check_non_negative(value): diff --git a/prediction_techniques/arima.py b/prediction_techniques/arima.py index 0cdcf998f5e..338dd09844f 100644 --- a/prediction_techniques/arima.py +++ b/prediction_techniques/arima.py @@ -1,8 +1,11 @@ import argparse -from helper_funcs import * -import pandas as pd + import matplotlib.pyplot as plt +import pandas as pd from pandas.plotting import register_matplotlib_converters + +from helper_funcs import * + register_matplotlib_converters() import pmdarima from statsmodels.tsa.arima.model import ARIMA diff --git a/prediction_techniques/fbprophet.py b/prediction_techniques/fbprophet.py index fcef2998afa..efe4798c0a4 100644 --- a/prediction_techniques/fbprophet.py +++ b/prediction_techniques/fbprophet.py @@ -1,12 +1,10 @@ import argparse -import numpy as np -import pandas as pd + import matplotlib.pyplot as plt +import pandas as pd from pandas.plotting import register_matplotlib_converters + register_matplotlib_converters() -import datetime -from datetime import datetime -from alpha_vantage.timeseries import TimeSeries from helper_funcs import * from fbprophet import Prophet import warnings diff --git a/prediction_techniques/knn.py b/prediction_techniques/knn.py index d3690d6cdb8..8ca411e7e55 100644 --- a/prediction_techniques/knn.py +++ b/prediction_techniques/knn.py @@ -1,9 +1,11 @@ import argparse -import numpy as np -from helper_funcs import * -import pandas as pd + import matplotlib.pyplot as plt +import pandas as pd from pandas.plotting import register_matplotlib_converters + +from helper_funcs import * + register_matplotlib_converters() from sklearn import neighbors from TimeSeriesCrossValidation import splitTrain diff --git a/prediction_techniques/neural_networks.py b/prediction_techniques/neural_networks.py index 38f7da13f85..6518f2e5463 100644 --- a/prediction_techniques/neural_networks.py +++ b/prediction_techniques/neural_networks.py @@ -1,16 +1,19 @@ import argparse -from helper_funcs import * -import pandas as pd -import numpy as np + import matplotlib.pyplot as plt +import numpy as np +import pandas as pd from pandas.plotting import register_matplotlib_converters + +from helper_funcs import * + register_matplotlib_converters() from TimeSeriesCrossValidation import splitTrain from sklearn.preprocessing import MinMaxScaler, StandardScaler from tensorflow.keras.models import Sequential -from tensorflow.keras.layers import LSTM, SimpleRNN, Dense, Dropout, Activation, RepeatVector, TimeDistributed +from tensorflow.keras.layers import LSTM, SimpleRNN, Dense, Dropout import config_neural_network_models as cfg_nn_models diff --git a/prediction_techniques/pred_menu.py b/prediction_techniques/pred_menu.py index b04defbed93..718adfb7e7d 100644 --- a/prediction_techniques/pred_menu.py +++ b/prediction_techniques/pred_menu.py @@ -1,12 +1,9 @@ -import config_terminal as cfg import argparse -import datetime -from datetime import datetime -from helper_funcs import * -import config_terminal as cfg -import pandas as pd -import matplotlib.pyplot as plt from pandas.plotting import register_matplotlib_converters +import argparse + +from pandas.plotting import register_matplotlib_converters + register_matplotlib_converters() from prediction_techniques import sma diff --git a/prediction_techniques/regression.py b/prediction_techniques/regression.py index c9b15530170..7a760078c53 100644 --- a/prediction_techniques/regression.py +++ b/prediction_techniques/regression.py @@ -1,9 +1,11 @@ import argparse -import numpy as np -from helper_funcs import * -import pandas as pd + import matplotlib.pyplot as plt +import pandas as pd from pandas.plotting import register_matplotlib_converters + +from helper_funcs import * + register_matplotlib_converters() from TimeSeriesCrossValidation import splitTrain from sklearn import linear_model diff --git a/prediction_techniques/sma.py b/prediction_techniques/sma.py index eecad082aff..cb6a56f34b3 100644 --- a/prediction_techniques/sma.py +++ b/prediction_techniques/sma.py @@ -1,9 +1,12 @@ import argparse -import numpy as np -from helper_funcs import * -import pandas as pd + import matplotlib.pyplot as plt +import numpy as np +import pandas as pd from pandas.plotting import register_matplotlib_converters + +from helper_funcs import * + register_matplotlib_converters() # ----------------------------------------------------- SMA ----------------------------------------------------- diff --git a/res_menu.py b/res_menu.py index ecad894fbe6..e103c05347b 100644 --- a/res_menu.py +++ b/res_menu.py @@ -1,4 +1,3 @@ -import config_terminal as cfg import argparse import webbrowser diff --git a/sentiment/google_api.py b/sentiment/google_api.py index 37e2db7b001..32e5543a863 100644 --- a/sentiment/google_api.py +++ b/sentiment/google_api.py @@ -1,10 +1,10 @@ -import pandas as pd -from pytrends.request import TrendReq -from datetime import datetime -import matplotlib.pyplot as plt -from helper_funcs import * import argparse +import matplotlib.pyplot as plt +from pytrends.request import TrendReq + +from helper_funcs import * + # ------------------------------------------------------------------------------------------------------------------- def mentions(l_args, s_ticker, s_start): diff --git a/sentiment/reddit_api.py b/sentiment/reddit_api.py index 61132119b40..53de80deeef 100644 --- a/sentiment/reddit_api.py +++ b/sentiment/reddit_api.py @@ -1,18 +1,17 @@ import argparse -from prettytable import PrettyTable -from datetime import datetime, timedelta -import pandas as pd -from psaw import PushshiftAPI -import praw -from datetime import datetime -from pytz import timezone -from holidays import US as holidaysUS -from helper_funcs import * import re -import finviz -import config_terminal as cfg import warnings +import finviz +import praw +from holidays import US as holidaysUS +from prettytable import PrettyTable +from psaw import PushshiftAPI + +import config_terminal as cfg +from helper_funcs import * + + # ------------------------------------------------------------------------------------------------------------------- def get_last_time_market_was_open(dt): # Check if it is a weekend diff --git a/sentiment/sen_menu.py b/sentiment/sen_menu.py index 392c924dfc8..3f9a16e3a04 100644 --- a/sentiment/sen_menu.py +++ b/sentiment/sen_menu.py @@ -1,9 +1,9 @@ -import config_terminal as cfg import argparse + +from sentiment import google_api from sentiment import reddit_api from sentiment import stocktwits_api from sentiment import twitter_api -from sentiment import google_api # ----------------------------------------------------------------------------------------------------------------------- @@ -130,4 +130,4 @@ def sen_menu(s_ticker, s_start): # ------------------------------------------------------------------------------------------------------------ else: - print("Command not recognized!") \ No newline at end of file + print("Command not recognized!") diff --git a/sentiment/stocktwits_api.py b/sentiment/stocktwits_api.py index 685f38478c7..1af224f0ca9 100644 --- a/sentiment/stocktwits_api.py +++ b/sentiment/stocktwits_api.py @@ -1,8 +1,11 @@ import argparse -import requests + import pandas as pd +import requests + from helper_funcs import * + # ------------------------------------------------------------------------------------------------------------------- def bullbear(l_args, s_ticker): parser = argparse.ArgumentParser(prog='bullbear', diff --git a/sentiment/twitter_api.py b/sentiment/twitter_api.py index 37cf9cac6a0..e8828bfe206 100644 --- a/sentiment/twitter_api.py +++ b/sentiment/twitter_api.py @@ -1,11 +1,11 @@ import argparse -import requests -import pandas as pd -import re + +import dateutil import flair import matplotlib.pyplot as plt -import iso8601 -import dateutil +import pandas as pd +import requests + import config_terminal as cfg from helper_funcs import * diff --git a/technical_analysis/momentum.py b/technical_analysis/momentum.py index 41575ee7fec..9284760f899 100644 --- a/technical_analysis/momentum.py +++ b/technical_analysis/momentum.py @@ -1,7 +1,10 @@ import argparse + import pandas_ta as ta -from helper_funcs import * from pandas.plotting import register_matplotlib_converters + +from helper_funcs import * + register_matplotlib_converters() import matplotlib.pyplot as plt @@ -354,4 +357,3 @@ def stoch(l_args, s_ticker, s_interval, df_stock): except: print("") - \ No newline at end of file diff --git a/technical_analysis/overlap.py b/technical_analysis/overlap.py index 93c8d8871d2..ac9c5a9da35 100644 --- a/technical_analysis/overlap.py +++ b/technical_analysis/overlap.py @@ -1,7 +1,10 @@ import argparse + import pandas_ta as ta -from helper_funcs import * from pandas.plotting import register_matplotlib_converters + +from helper_funcs import * + register_matplotlib_converters() @@ -166,4 +169,3 @@ def vwap(l_args, s_ticker, s_interval, df_stock): except: print("") - \ No newline at end of file diff --git a/technical_analysis/ta_menu.py b/technical_analysis/ta_menu.py index ffea7aa291f..207966e6f7b 100644 --- a/technical_analysis/ta_menu.py +++ b/technical_analysis/ta_menu.py @@ -1,21 +1,12 @@ -import FundamentalAnalysis as fa -from alpha_vantage.fundamentaldata import FundamentalData -import config_terminal as cfg import argparse -import datetime -from datetime import datetime -from helper_funcs import * -import pandas as pd -import json -import requests -from pandas.io.json import json_normalize -from technical_analysis import overlap as ta_overlap from technical_analysis import momentum as ta_momentum +from technical_analysis import overlap as ta_overlap from technical_analysis import trend as ta_trend from technical_analysis import volatility as ta_volatility from technical_analysis import volume as ta_volume + # ----------------------------------------------------------------------------------------------------------------------- def print_technical_analysis(s_ticker, s_start, s_interval): """ Print help """ diff --git a/technical_analysis/trend.py b/technical_analysis/trend.py index 70b2f4d21ce..1f5ebe19532 100644 --- a/technical_analysis/trend.py +++ b/technical_analysis/trend.py @@ -1,7 +1,10 @@ import argparse + import pandas_ta as ta -from helper_funcs import * from pandas.plotting import register_matplotlib_converters + +from helper_funcs import * + register_matplotlib_converters() # ----------------------------------------------------- ADX ----------------------------------------------------- @@ -154,4 +157,3 @@ def aroon(l_args, s_ticker, s_interval, df_stock): except: print("") - \ No newline at end of file diff --git a/technical_analysis/volatility.py b/technical_analysis/volatility.py index fc2deac49f8..67649a61d46 100644 --- a/technical_analysis/volatility.py +++ b/technical_analysis/volatility.py @@ -1,7 +1,10 @@ import argparse + import pandas_ta as ta -from helper_funcs import * from pandas.plotting import register_matplotlib_converters + +from helper_funcs import * + register_matplotlib_converters() # ----------------------------------------------------- BBANDS ----------------------------------------------------- @@ -75,4 +78,3 @@ def bbands(l_args, s_ticker, s_interval, df_stock): except: print("") - \ No newline at end of file diff --git a/technical_analysis/volume.py b/technical_analysis/volume.py index b0d270767b4..87be4efe897 100644 --- a/technical_analysis/volume.py +++ b/technical_analysis/volume.py @@ -1,7 +1,10 @@ import argparse + import pandas_ta as ta -from helper_funcs import * from pandas.plotting import register_matplotlib_converters + +from helper_funcs import * + register_matplotlib_converters() # ------------------------------------------------------- AD ------------------------------------------------------- @@ -171,4 +174,3 @@ def obv(l_args, s_ticker, s_interval, df_stock): except: print("") - \ No newline at end of file From 32f52751fc78d78cfb5757ed1bb5e25a9209d470 Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Thu, 25 Feb 2021 10:40:09 +0200 Subject: [PATCH 65/72] Avoid star imports --- discovery/fidelity_api.py | 2 +- discovery/seeking_alpha_api.py | 2 +- discovery/short_interest_api.py | 3 ++- discovery/yahoo_finance_api.py | 3 --- due_diligence/business_insider_api.py | 2 +- due_diligence/finviz_api.py | 4 +--- due_diligence/market_watch_api.py | 2 +- due_diligence/quandl_api.py | 2 +- due_diligence/reddit_api.py | 3 ++- fundamental_analysis/alpha_vantage_api.py | 4 +++- fundamental_analysis/financial_modeling_prep_api.py | 6 ++++-- fundamental_analysis/yahoo_finance_api.py | 3 ++- gamestonk_terminal.py | 4 ++-- prediction_techniques/arima.py | 2 +- prediction_techniques/fbprophet.py | 3 ++- prediction_techniques/knn.py | 2 +- prediction_techniques/neural_networks.py | 2 +- prediction_techniques/pred_menu.py | 2 -- prediction_techniques/regression.py | 2 +- prediction_techniques/sma.py | 2 +- sentiment/google_api.py | 3 +-- sentiment/reddit_api.py | 3 ++- sentiment/stocktwits_api.py | 2 +- sentiment/twitter_api.py | 6 ++++-- technical_analysis/momentum.py | 2 +- technical_analysis/overlap.py | 2 +- technical_analysis/trend.py | 3 ++- technical_analysis/volatility.py | 2 +- technical_analysis/volume.py | 3 ++- 29 files changed, 43 insertions(+), 38 deletions(-) diff --git a/discovery/fidelity_api.py b/discovery/fidelity_api.py index d469c55cf6d..7fb46117fa1 100644 --- a/discovery/fidelity_api.py +++ b/discovery/fidelity_api.py @@ -4,7 +4,7 @@ import pandas as pd import requests from bs4 import BeautifulSoup -from helper_funcs import * +from helper_funcs import check_positive # ---------------------------------------------------- ORDERS ---------------------------------------------------- diff --git a/discovery/seeking_alpha_api.py b/discovery/seeking_alpha_api.py index 1d38cf33518..b9f80391af4 100644 --- a/discovery/seeking_alpha_api.py +++ b/discovery/seeking_alpha_api.py @@ -4,7 +4,7 @@ import pandas as pd import requests from bs4 import BeautifulSoup -from helper_funcs import * +from helper_funcs import check_positive # ------------------------------------------------ EARNINGS_RELEASE_DATES ------------------------------------------------- diff --git a/discovery/short_interest_api.py b/discovery/short_interest_api.py index 247df24b6bb..93d44dd848a 100644 --- a/discovery/short_interest_api.py +++ b/discovery/short_interest_api.py @@ -1,10 +1,11 @@ import argparse +import re import pandas as pd import requests from bs4 import BeautifulSoup -from helper_funcs import * +from helper_funcs import check_positive # ------------------------------------------------ HIGH_SHORT_INTEREST ------------------------------------------------- diff --git a/discovery/yahoo_finance_api.py b/discovery/yahoo_finance_api.py index d0eeaf6b788..e68953971cd 100644 --- a/discovery/yahoo_finance_api.py +++ b/discovery/yahoo_finance_api.py @@ -3,9 +3,6 @@ import argparse import pandas as pd -#from helper_funcs import * - - # ---------------------------------------------------- GAINERS ---------------------------------------------------- def gainers(l_args): parser = argparse.ArgumentParser(prog='gainers', diff --git a/due_diligence/business_insider_api.py b/due_diligence/business_insider_api.py index c323a95cb05..d894f1d3421 100644 --- a/due_diligence/business_insider_api.py +++ b/due_diligence/business_insider_api.py @@ -8,7 +8,7 @@ import requests from bs4 import BeautifulSoup from pandas.plotting import register_matplotlib_converters -from helper_funcs import check_positive +from helper_funcs import check_positive, get_next_stock_market_days register_matplotlib_converters() diff --git a/due_diligence/finviz_api.py b/due_diligence/finviz_api.py index 64a80d3fd7f..b34850fe1ec 100644 --- a/due_diligence/finviz_api.py +++ b/due_diligence/finviz_api.py @@ -2,9 +2,7 @@ import argparse import finviz import pandas as pd - -from helper_funcs import * - +from helper_funcs import check_positive # ---------------------------------------------------- INSIDER ---------------------------------------------------- def insider(l_args, s_ticker): diff --git a/due_diligence/market_watch_api.py b/due_diligence/market_watch_api.py index 54e5bdc6b03..952ae8d3b0c 100644 --- a/due_diligence/market_watch_api.py +++ b/due_diligence/market_watch_api.py @@ -5,7 +5,7 @@ import pandas as pd import requests from bs4 import BeautifulSoup -from helper_funcs import * +from helper_funcs import check_positive, clean_data_values_to_float, int_or_round_float # ---------------------------------------------------- SEC FILLINGS ---------------------------------------------------- diff --git a/due_diligence/quandl_api.py b/due_diligence/quandl_api.py index a4e9c557ecb..e5745e51999 100644 --- a/due_diligence/quandl_api.py +++ b/due_diligence/quandl_api.py @@ -6,7 +6,7 @@ import quandl from matplotlib import pyplot as plt import config_terminal as cfg -from helper_funcs import * +from helper_funcs import check_positive, long_number_format # -------------------------------------------------------- SHORT_INTEREST -------------------------------------------------------- diff --git a/due_diligence/reddit_api.py b/due_diligence/reddit_api.py index 1f589ba58da..432f5311057 100644 --- a/due_diligence/reddit_api.py +++ b/due_diligence/reddit_api.py @@ -1,11 +1,12 @@ import argparse +from datetime import datetime, timedelta import praw from prettytable import PrettyTable from psaw import PushshiftAPI import config_terminal as cfg -from helper_funcs import * +from helper_funcs import check_positive # ------------------------------------------------------------------------------------------------------------------- diff --git a/fundamental_analysis/alpha_vantage_api.py b/fundamental_analysis/alpha_vantage_api.py index 08e3968586e..fc5c01b04ba 100644 --- a/fundamental_analysis/alpha_vantage_api.py +++ b/fundamental_analysis/alpha_vantage_api.py @@ -6,10 +6,12 @@ from alpha_vantage.fundamentaldata import FundamentalData from pandas.io.json import json_normalize import config_terminal as cfg -from helper_funcs import * # ---------------------------------------------------- OVERVIEW ---------------------------------------------------- +from helper_funcs import long_number_format, check_positive + + def overview(l_args, s_ticker): parser = argparse.ArgumentParser(prog='overview', description="""Prints an overview about the company. The following fields are expected: diff --git a/fundamental_analysis/financial_modeling_prep_api.py b/fundamental_analysis/financial_modeling_prep_api.py index 5badf276bb2..5ea3d1b92c8 100644 --- a/fundamental_analysis/financial_modeling_prep_api.py +++ b/fundamental_analysis/financial_modeling_prep_api.py @@ -4,10 +4,12 @@ import FundamentalAnalysis as fa # Financial Modeling Prep import pandas as pd import config_terminal as cfg -from helper_funcs import * # ---------------------------------------------------- PROFILE ---------------------------------------------------- +from helper_funcs import check_positive, long_number_format + + def profile(l_args, s_ticker): parser = argparse.ArgumentParser(prog='profile', description="""Prints information about, among other things, the industry, sector @@ -61,7 +63,7 @@ def quote(l_args, s_ticker): df_fa.loc['Market cap'][0] = long_number_format(df_fa.loc['Market cap'][0]) df_fa.loc['Shares outstanding'][0] = long_number_format(df_fa.loc['Shares outstanding'][0]) df_fa.loc['Volume'][0] = long_number_format(df_fa.loc['Volume'][0]) - earning_announcment = datetime.strptime(df_fa.loc['Earnings announcement'][0][0:19],"%Y-%m-%dT%H:%M:%S") + earning_announcment = datetime.datetime.strptime(df_fa.loc['Earnings announcement'][0][0:19],"%Y-%m-%dT%H:%M:%S") df_fa.loc['Earnings announcement'][0] = f"{earning_announcment.date()} {earning_announcment.time()}" print(df_fa.to_string(header=False)) diff --git a/fundamental_analysis/yahoo_finance_api.py b/fundamental_analysis/yahoo_finance_api.py index fbf1e7115e0..e98c74024c8 100644 --- a/fundamental_analysis/yahoo_finance_api.py +++ b/fundamental_analysis/yahoo_finance_api.py @@ -1,9 +1,10 @@ import argparse +from datetime import datetime import pandas as pd import yfinance as yf -from helper_funcs import * +from helper_funcs import long_number_format # ---------------------------------------------------- INFO ---------------------------------------------------- diff --git a/gamestonk_terminal.py b/gamestonk_terminal.py index 17795911db9..8581a0d4a06 100644 --- a/gamestonk_terminal.py +++ b/gamestonk_terminal.py @@ -11,7 +11,7 @@ import res_menu as rm from discovery import disc_menu as dm from due_diligence import dd_menu as ddm from fundamental_analysis import fa_menu as fam -from helper_funcs import * +from helper_funcs import valid_date, check_positive, plot_view_stock, b_is_stock_market_open from prediction_techniques import pred_menu as pm from sentiment import sen_menu as sm from technical_analysis import ta_menu as tam @@ -314,7 +314,7 @@ def main(): b_quit = pm.pred_menu(df_stock, s_ticker, s_start, s_interval) # If stock data is intradaily, we need to get data again as prediction techniques work on daily adjusted data else: - df_stock_pred, _ = ts.get_daily_adjusted(symbol=s_ticker, outputsize='full') + df_stock_pred, _ = TimeSeries.get_daily_adjusted(symbol=s_ticker, outputsize='full') df_stock_pred = df_stock_pred.sort_index(ascending=True) df_stock_pred = df_stock_pred[s_start:] b_quit = pm.pred_menu(df_stock_pred, s_ticker, s_start, s_interval="1440min") diff --git a/prediction_techniques/arima.py b/prediction_techniques/arima.py index 338dd09844f..571d7028ab4 100644 --- a/prediction_techniques/arima.py +++ b/prediction_techniques/arima.py @@ -4,7 +4,7 @@ import matplotlib.pyplot as plt import pandas as pd from pandas.plotting import register_matplotlib_converters -from helper_funcs import * +from helper_funcs import check_positive, get_next_stock_market_days register_matplotlib_converters() import pmdarima diff --git a/prediction_techniques/fbprophet.py b/prediction_techniques/fbprophet.py index efe4798c0a4..335a0a23d5c 100644 --- a/prediction_techniques/fbprophet.py +++ b/prediction_techniques/fbprophet.py @@ -4,8 +4,9 @@ import matplotlib.pyplot as plt import pandas as pd from pandas.plotting import register_matplotlib_converters +from helper_funcs import get_next_stock_market_days, check_positive + register_matplotlib_converters() -from helper_funcs import * from fbprophet import Prophet import warnings warnings.simplefilter("ignore") diff --git a/prediction_techniques/knn.py b/prediction_techniques/knn.py index 8ca411e7e55..656a3a4556f 100644 --- a/prediction_techniques/knn.py +++ b/prediction_techniques/knn.py @@ -4,7 +4,7 @@ import matplotlib.pyplot as plt import pandas as pd from pandas.plotting import register_matplotlib_converters -from helper_funcs import * +from helper_funcs import check_positive, get_next_stock_market_days register_matplotlib_converters() from sklearn import neighbors diff --git a/prediction_techniques/neural_networks.py b/prediction_techniques/neural_networks.py index 6518f2e5463..7fb8c36de42 100644 --- a/prediction_techniques/neural_networks.py +++ b/prediction_techniques/neural_networks.py @@ -5,7 +5,7 @@ import numpy as np import pandas as pd from pandas.plotting import register_matplotlib_converters -from helper_funcs import * +from helper_funcs import check_positive, get_next_stock_market_days register_matplotlib_converters() diff --git a/prediction_techniques/pred_menu.py b/prediction_techniques/pred_menu.py index 718adfb7e7d..568cb791a5d 100644 --- a/prediction_techniques/pred_menu.py +++ b/prediction_techniques/pred_menu.py @@ -1,6 +1,4 @@ import argparse -from pandas.plotting import register_matplotlib_converters -import argparse from pandas.plotting import register_matplotlib_converters diff --git a/prediction_techniques/regression.py b/prediction_techniques/regression.py index 7a760078c53..af219522aee 100644 --- a/prediction_techniques/regression.py +++ b/prediction_techniques/regression.py @@ -4,7 +4,7 @@ import matplotlib.pyplot as plt import pandas as pd from pandas.plotting import register_matplotlib_converters -from helper_funcs import * +from helper_funcs import check_positive, get_next_stock_market_days register_matplotlib_converters() from TimeSeriesCrossValidation import splitTrain diff --git a/prediction_techniques/sma.py b/prediction_techniques/sma.py index cb6a56f34b3..d73ae577dae 100644 --- a/prediction_techniques/sma.py +++ b/prediction_techniques/sma.py @@ -5,7 +5,7 @@ import numpy as np import pandas as pd from pandas.plotting import register_matplotlib_converters -from helper_funcs import * +from helper_funcs import get_next_stock_market_days, check_positive register_matplotlib_converters() diff --git a/sentiment/google_api.py b/sentiment/google_api.py index 32e5543a863..00ae0b6b06f 100644 --- a/sentiment/google_api.py +++ b/sentiment/google_api.py @@ -2,8 +2,7 @@ import argparse import matplotlib.pyplot as plt from pytrends.request import TrendReq - -from helper_funcs import * +from helper_funcs import check_positive, valid_date # ------------------------------------------------------------------------------------------------------------------- diff --git a/sentiment/reddit_api.py b/sentiment/reddit_api.py index 53de80deeef..348908adfb5 100644 --- a/sentiment/reddit_api.py +++ b/sentiment/reddit_api.py @@ -1,6 +1,7 @@ import argparse import re import warnings +from datetime import timedelta, datetime import finviz import praw @@ -9,7 +10,7 @@ from prettytable import PrettyTable from psaw import PushshiftAPI import config_terminal as cfg -from helper_funcs import * +from helper_funcs import check_positive # ------------------------------------------------------------------------------------------------------------------- diff --git a/sentiment/stocktwits_api.py b/sentiment/stocktwits_api.py index 1af224f0ca9..378d79e7f75 100644 --- a/sentiment/stocktwits_api.py +++ b/sentiment/stocktwits_api.py @@ -3,7 +3,7 @@ import argparse import pandas as pd import requests -from helper_funcs import * +from helper_funcs import check_positive # ------------------------------------------------------------------------------------------------------------------- diff --git a/sentiment/twitter_api.py b/sentiment/twitter_api.py index e8828bfe206..fedd06f5b06 100644 --- a/sentiment/twitter_api.py +++ b/sentiment/twitter_api.py @@ -1,13 +1,15 @@ import argparse +from datetime import datetime, timedelta -import dateutil +import dateutil.parser import flair import matplotlib.pyplot as plt import pandas as pd +import numpy as np import requests import config_terminal as cfg -from helper_funcs import * +from helper_funcs import clean_tweet, get_data # ------------------------------------------------- INFERENCE ------------------------------------------------- diff --git a/technical_analysis/momentum.py b/technical_analysis/momentum.py index 9284760f899..8bf1fe6abf6 100644 --- a/technical_analysis/momentum.py +++ b/technical_analysis/momentum.py @@ -3,7 +3,7 @@ import argparse import pandas_ta as ta from pandas.plotting import register_matplotlib_converters -from helper_funcs import * +from helper_funcs import check_positive register_matplotlib_converters() import matplotlib.pyplot as plt diff --git a/technical_analysis/overlap.py b/technical_analysis/overlap.py index ac9c5a9da35..b1456c17270 100644 --- a/technical_analysis/overlap.py +++ b/technical_analysis/overlap.py @@ -3,7 +3,7 @@ import argparse import pandas_ta as ta from pandas.plotting import register_matplotlib_converters -from helper_funcs import * +from helper_funcs import check_positive, plot_stock_ta register_matplotlib_converters() diff --git a/technical_analysis/trend.py b/technical_analysis/trend.py index 1f5ebe19532..21a3ca4fdba 100644 --- a/technical_analysis/trend.py +++ b/technical_analysis/trend.py @@ -1,9 +1,10 @@ import argparse import pandas_ta as ta +import matplotlib.pyplot as plt from pandas.plotting import register_matplotlib_converters -from helper_funcs import * +from helper_funcs import check_positive register_matplotlib_converters() diff --git a/technical_analysis/volatility.py b/technical_analysis/volatility.py index 67649a61d46..ee76ee06cfb 100644 --- a/technical_analysis/volatility.py +++ b/technical_analysis/volatility.py @@ -3,7 +3,7 @@ import argparse import pandas_ta as ta from pandas.plotting import register_matplotlib_converters -from helper_funcs import * +from helper_funcs import check_positive register_matplotlib_converters() diff --git a/technical_analysis/volume.py b/technical_analysis/volume.py index 87be4efe897..7266a32cd90 100644 --- a/technical_analysis/volume.py +++ b/technical_analysis/volume.py @@ -1,9 +1,10 @@ import argparse import pandas_ta as ta +import matplotlib.pyplot as plt from pandas.plotting import register_matplotlib_converters -from helper_funcs import * +from helper_funcs import check_positive register_matplotlib_converters() From 7a22988d92ab44a8e4cf8e28938a6187818b6ad2 Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Wed, 3 Mar 2021 21:56:11 +0200 Subject: [PATCH 66/72] Get rid of exception-eating bare except:s --- due_diligence/business_insider_api.py | 531 +++++----- due_diligence/financial_modeling_prep_api.py | 20 +- due_diligence/finviz_api.py | 86 +- due_diligence/market_watch_api.py | 346 +++---- due_diligence/quandl_api.py | 95 +- due_diligence/reddit_api.py | 141 ++- fundamental_analysis/alpha_vantage_api.py | 416 ++++---- fundamental_analysis/business_insider_api.py | 82 +- fundamental_analysis/fa_menu.py | 22 +- .../financial_modeling_prep_api.py | 537 +++++----- fundamental_analysis/finviz_api.py | 27 +- fundamental_analysis/market_watch_api.py | 435 ++++---- fundamental_analysis/yahoo_finance_api.py | 223 ++-- gamestonk_terminal.py | 6 +- prediction_techniques/arima.py | 90 +- prediction_techniques/fbprophet.py | 62 +- prediction_techniques/knn.py | 70 +- prediction_techniques/neural_networks.py | 347 +++---- prediction_techniques/regression.py | 81 +- prediction_techniques/sma.py | 77 +- sentiment/google_api.py | 133 ++- sentiment/reddit_api.py | 969 +++++++++--------- sentiment/stocktwits_api.py | 148 ++- sentiment/twitter_api.py | 389 ++++--- technical_analysis/momentum.py | 499 +++++---- technical_analysis/overlap.py | 207 ++-- technical_analysis/trend.py | 211 ++-- technical_analysis/volatility.py | 91 +- technical_analysis/volume.py | 245 +++-- 29 files changed, 3136 insertions(+), 3450 deletions(-) diff --git a/due_diligence/business_insider_api.py b/due_diligence/business_insider_api.py index d894f1d3421..a76f4948387 100644 --- a/due_diligence/business_insider_api.py +++ b/due_diligence/business_insider_api.py @@ -21,187 +21,178 @@ def price_target_from_analysts(l_args, df_stock, s_ticker, s_start, s_interval): parser.add_argument('-n', "--num", action="store", dest="n_num", type=check_positive, default=10, help='number of latest price targets from analysts to print.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return - - url_market_business_insider = f"https://markets.businessinsider.com/stocks/{s_ticker.lower()}-stock" - text_soup_market_business_insider = BeautifulSoup(requests.get(url_market_business_insider).text, "lxml") - - for script in text_soup_market_business_insider.find_all('script'): - # Get Analyst data - if 'window.analyseChartConfigs.push' in script.get_text(): - # Extract config data: - s_analyst_data = script.get_text().split("config: ",1)[1].split(",\r\n",1)[0] - d_analyst_data = json.loads(s_analyst_data) - break - - #pprint.pprint(d_analyst_data) - df_analyst_data = pd.DataFrame.from_dict(d_analyst_data['Markers']) - df_analyst_data = df_analyst_data[['DateLabel', 'Company', 'InternalRating', 'PriceTarget']] - df_analyst_data.columns = ['Date', 'Company', 'Rating', 'Price Target'] - df_analyst_data - df_analyst_data['Rating'].replace({'gut': 'BUY', - 'neutral': 'HOLD', - 'schlecht':'SELL'}, inplace=True) - df_analyst_data['Date'] = pd.to_datetime(df_analyst_data['Date']) - df_analyst_data = df_analyst_data.set_index('Date') - - # Slice start of ratings - if s_start: - df_analyst_data = df_analyst_data[s_start:] - - if s_interval == "1440min": - plt.plot(df_stock.index, df_stock['5. adjusted close'].values, lw=3) - # Intraday - else: - plt.plot(df_stock.index, df_stock['4. close'].values, lw=3) - - if s_start: - plt.plot(df_analyst_data.groupby(by=['Date']).mean()[s_start:]) - else: - plt.plot(df_analyst_data.groupby(by=['Date']).mean()) - - plt.scatter(df_analyst_data.index, df_analyst_data['Price Target'], c='r', s=40) - - plt.legend(['Closing Price', 'Average Price Target', 'Price Target']) - - plt.title(f"{s_ticker} (Time Series) and Price Target") - plt.xlim(df_stock.index[0], df_stock.index[-1]) - plt.xlabel('Time') - plt.ylabel('Share Price ($)') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.show() - print("") - - pd.set_option('display.max_colwidth', -1) - print(df_analyst_data.sort_index(ascending=False).head(ns_parser.n_num).to_string()) - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return + url_market_business_insider = f"https://markets.businessinsider.com/stocks/{s_ticker.lower()}-stock" + text_soup_market_business_insider = BeautifulSoup(requests.get(url_market_business_insider).text, "lxml") + + for script in text_soup_market_business_insider.find_all('script'): + # Get Analyst data + if 'window.analyseChartConfigs.push' in script.get_text(): + # Extract config data: + s_analyst_data = script.get_text().split("config: ",1)[1].split(",\r\n",1)[0] + d_analyst_data = json.loads(s_analyst_data) + break + + #pprint.pprint(d_analyst_data) + df_analyst_data = pd.DataFrame.from_dict(d_analyst_data['Markers']) + df_analyst_data = df_analyst_data[['DateLabel', 'Company', 'InternalRating', 'PriceTarget']] + df_analyst_data.columns = ['Date', 'Company', 'Rating', 'Price Target'] + df_analyst_data + df_analyst_data['Rating'].replace({'gut': 'BUY', + 'neutral': 'HOLD', + 'schlecht':'SELL'}, inplace=True) + df_analyst_data['Date'] = pd.to_datetime(df_analyst_data['Date']) + df_analyst_data = df_analyst_data.set_index('Date') + + # Slice start of ratings + if s_start: + df_analyst_data = df_analyst_data[s_start:] + + if s_interval == "1440min": + plt.plot(df_stock.index, df_stock['5. adjusted close'].values, lw=3) + # Intraday + else: + plt.plot(df_stock.index, df_stock['4. close'].values, lw=3) + + if s_start: + plt.plot(df_analyst_data.groupby(by=['Date']).mean()[s_start:]) + else: + plt.plot(df_analyst_data.groupby(by=['Date']).mean()) + + plt.scatter(df_analyst_data.index, df_analyst_data['Price Target'], c='r', s=40) + + plt.legend(['Closing Price', 'Average Price Target', 'Price Target']) + + plt.title(f"{s_ticker} (Time Series) and Price Target") + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.xlabel('Time') + plt.ylabel('Share Price ($)') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.show() + print("") + + pd.set_option('display.max_colwidth', -1) + print(df_analyst_data.sort_index(ascending=False).head(ns_parser.n_num).to_string()) + print("") + # ----------------------------------------------- ESTIMATES ----------------------------------------------- def estimates(l_args, s_ticker): parser = argparse.ArgumentParser(prog='est', description="""Yearly estimates and quarter earnings/revenues [Source: Business Insider]""") - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return - - url_market_business_insider = f"https://markets.businessinsider.com/stocks/{s_ticker.lower()}-stock" - text_soup_market_business_insider = BeautifulSoup(requests.get(url_market_business_insider).text, "lxml") - - l_estimates_year_header = list() - l_estimates_quarter_header = list() - for estimates_header in text_soup_market_business_insider.findAll('th', {'class': 'table__th text-right'}): - s_estimates_header = estimates_header.text.strip() - if s_estimates_header.isdigit(): - l_estimates_year_header.append(s_estimates_header) - elif ('in %' not in s_estimates_header) and ('Job' not in s_estimates_header): - l_estimates_quarter_header.append(s_estimates_header) - - l_estimates_year_metric = list() - for estimates_year_metric in text_soup_market_business_insider.findAll('td', {'class': 'table__td black'}): - l_estimates_year_metric.append(estimates_year_metric.text) - - l_estimates_quarter_metric = list() - for estimates_quarter_metric in text_soup_market_business_insider.findAll('td', {'class': 'table__td font-color-dim-gray'}): - l_estimates_quarter_metric.append(estimates_quarter_metric.text) - - d_metric_year = dict() - d_metric_quarter_earnings = dict() - d_metric_quarter_revenues = dict() - l_metrics = list() - n_metrics = 0 - b_year = True - for idx, metric_value in enumerate(text_soup_market_business_insider.findAll('td', {'class': 'table__td text-right'})): - - if b_year: - # YEAR metrics - l_metrics.append(metric_value.text.strip()) - - # Check if we have processed all year metrics - if n_metrics > len(l_estimates_year_metric)-1: - b_year = False - n_metrics = 0 - l_metrics = list() - idx_y = idx - - # Add value to dictionary - if (idx+1)%len(l_estimates_year_header) == 0: - d_metric_year[l_estimates_year_metric[n_metrics]] = l_metrics - l_metrics = list() - n_metrics += 1 - - if not b_year: - # QUARTER metrics - l_metrics.append(metric_value.text.strip()) - - # Check if we have processed all quarter metrics - if n_metrics > len(l_estimates_quarter_metric)-1: - break - - # Add value to dictionary - if (idx-idx_y+1)%len(l_estimates_quarter_header) == 0: - if n_metrics < 4: - d_metric_quarter_earnings[l_estimates_quarter_metric[n_metrics]] = l_metrics - else: - d_metric_quarter_revenues[l_estimates_quarter_metric[n_metrics-4]] = l_metrics - l_metrics = list() - n_metrics += 1 - - df_year_estimates = pd.DataFrame.from_dict(d_metric_year, orient='index', columns=l_estimates_year_header) - df_year_estimates.index.name = 'YEARLY ESTIMATES' - df_quarter_earnings = pd.DataFrame.from_dict(d_metric_quarter_earnings, orient='index', columns=l_estimates_quarter_header) - #df_quarter_earnings.index.name = 'Earnings' - df_quarter_revenues = pd.DataFrame.from_dict(d_metric_quarter_revenues, orient='index', columns=l_estimates_quarter_header) - #df_quarter_revenues.index.name = 'Revenues' - - l_quarter = list() - l_date = list() - for quarter_title in df_quarter_earnings.columns: - l_quarter.append(re.split(' ending',quarter_title)[0]) - if len(re.split(' ending',quarter_title)) == 2: - l_date.append('ending ' + re.split(' ending',quarter_title)[1].strip()) - else: - l_date.append('-') - - df_quarter_earnings.columns = l_quarter - df_quarter_earnings.loc["Date"] = l_date - df_quarter_earnings = df_quarter_earnings.reindex(["Date", "No. of Analysts", "Average Estimate", "Year Ago", "Publish Date"]) - - df_quarter_revenues.columns = l_quarter - df_quarter_revenues.loc["Date"] = l_date - df_quarter_revenues = df_quarter_revenues.reindex(["Date", "No. of Analysts", "Average Estimate", "Year Ago", "Publish Date"]) - - print(df_year_estimates.to_string()) - print("") - print("QUARTER ESTIMATES EARNINGS") - print(df_quarter_earnings.to_string()) - print("") - print("QUARTER ESTIMATES REVENUES") - print(df_quarter_revenues.to_string()) - print("") - - print(text_soup_market_business_insider.find('div', {'class': "text_right instrument-description"}).text.strip()) - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return + url_market_business_insider = f"https://markets.businessinsider.com/stocks/{s_ticker.lower()}-stock" + text_soup_market_business_insider = BeautifulSoup(requests.get(url_market_business_insider).text, "lxml") + + l_estimates_year_header = list() + l_estimates_quarter_header = list() + for estimates_header in text_soup_market_business_insider.findAll('th', {'class': 'table__th text-right'}): + s_estimates_header = estimates_header.text.strip() + if s_estimates_header.isdigit(): + l_estimates_year_header.append(s_estimates_header) + elif ('in %' not in s_estimates_header) and ('Job' not in s_estimates_header): + l_estimates_quarter_header.append(s_estimates_header) + + l_estimates_year_metric = list() + for estimates_year_metric in text_soup_market_business_insider.findAll('td', {'class': 'table__td black'}): + l_estimates_year_metric.append(estimates_year_metric.text) + + l_estimates_quarter_metric = list() + for estimates_quarter_metric in text_soup_market_business_insider.findAll('td', {'class': 'table__td font-color-dim-gray'}): + l_estimates_quarter_metric.append(estimates_quarter_metric.text) + + d_metric_year = dict() + d_metric_quarter_earnings = dict() + d_metric_quarter_revenues = dict() + l_metrics = list() + n_metrics = 0 + b_year = True + for idx, metric_value in enumerate(text_soup_market_business_insider.findAll('td', {'class': 'table__td text-right'})): + + if b_year: + # YEAR metrics + l_metrics.append(metric_value.text.strip()) + + # Check if we have processed all year metrics + if n_metrics > len(l_estimates_year_metric)-1: + b_year = False + n_metrics = 0 + l_metrics = list() + idx_y = idx + + # Add value to dictionary + if (idx+1)%len(l_estimates_year_header) == 0: + d_metric_year[l_estimates_year_metric[n_metrics]] = l_metrics + l_metrics = list() + n_metrics += 1 + + if not b_year: + # QUARTER metrics + l_metrics.append(metric_value.text.strip()) + + # Check if we have processed all quarter metrics + if n_metrics > len(l_estimates_quarter_metric)-1: + break + + # Add value to dictionary + if (idx-idx_y+1)%len(l_estimates_quarter_header) == 0: + if n_metrics < 4: + d_metric_quarter_earnings[l_estimates_quarter_metric[n_metrics]] = l_metrics + else: + d_metric_quarter_revenues[l_estimates_quarter_metric[n_metrics-4]] = l_metrics + l_metrics = list() + n_metrics += 1 + + df_year_estimates = pd.DataFrame.from_dict(d_metric_year, orient='index', columns=l_estimates_year_header) + df_year_estimates.index.name = 'YEARLY ESTIMATES' + df_quarter_earnings = pd.DataFrame.from_dict(d_metric_quarter_earnings, orient='index', columns=l_estimates_quarter_header) + #df_quarter_earnings.index.name = 'Earnings' + df_quarter_revenues = pd.DataFrame.from_dict(d_metric_quarter_revenues, orient='index', columns=l_estimates_quarter_header) + #df_quarter_revenues.index.name = 'Revenues' + + l_quarter = list() + l_date = list() + for quarter_title in df_quarter_earnings.columns: + l_quarter.append(re.split(' ending',quarter_title)[0]) + if len(re.split(' ending',quarter_title)) == 2: + l_date.append('ending ' + re.split(' ending',quarter_title)[1].strip()) + else: + l_date.append('-') + + df_quarter_earnings.columns = l_quarter + df_quarter_earnings.loc["Date"] = l_date + df_quarter_earnings = df_quarter_earnings.reindex(["Date", "No. of Analysts", "Average Estimate", "Year Ago", "Publish Date"]) + + df_quarter_revenues.columns = l_quarter + df_quarter_revenues.loc["Date"] = l_date + df_quarter_revenues = df_quarter_revenues.reindex(["Date", "No. of Analysts", "Average Estimate", "Year Ago", "Publish Date"]) + + print(df_year_estimates.to_string()) + print("") + print("QUARTER ESTIMATES EARNINGS") + print(df_quarter_earnings.to_string()) + print("") + print("QUARTER ESTIMATES REVENUES") + print(df_quarter_revenues.to_string()) + print("") + + print(text_soup_market_business_insider.find('div', {'class': "text_right instrument-description"}).text.strip()) + print("") + + # ----------------------------------------------- INSIDER_ACTIVITY ----------------------------------------------- def insider_activity(l_args, df_stock, s_ticker, s_start, s_interval): @@ -210,108 +201,104 @@ def insider_activity(l_args, df_stock, s_ticker, s_start, s_interval): parser.add_argument('-n', "--num", action="store", dest="n_num", type=check_positive, default=10, help='number of latest insider activity.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return - - url_market_business_insider = f"https://markets.businessinsider.com/stocks/{s_ticker.lower()}-stock" - text_soup_market_business_insider = BeautifulSoup(requests.get(url_market_business_insider).text, "lxml") - - d_insider = dict() - l_insider_vals = list() - for idx, insider_val in enumerate(text_soup_market_business_insider.findAll('td', {'class':"table__td text-center"})): - #print(insider_val.text.strip()) - - l_insider_vals.append(insider_val.text.strip()) - - # Add value to dictionary - if (idx+1)%6 == 0: - # Check if we are still parsing insider trading activity - if '/' not in l_insider_vals[0]: - break - d_insider[(idx+1)//6] = l_insider_vals - l_insider_vals = list() - - df_insider = pd.DataFrame.from_dict(d_insider, orient='index', - columns = ['Date', 'Shares Traded', 'Shares Held', 'Price', 'Type', 'Option']) - - df_insider['Date'] = pd.to_datetime(df_insider['Date']) - df_insider = df_insider.set_index('Date') - df_insider = df_insider.sort_index(ascending=True) - - if s_start: - df_insider = df_insider[s_start:] - - pfig, ax = plt.subplots() - - if s_interval == "1440min": - plt.plot(df_stock.index, df_stock['5. adjusted close'].values, lw=3) - else: # Intraday - plt.plot(df_stock.index, df_stock['4. close'].values, lw=3) - - plt.title(f"{s_ticker.upper()} (Time Series) and Price Target") - - plt.xlabel('Time') - plt.ylabel('Share Price ($)') - - df_insider['Trade'] = df_insider.apply(lambda row: (1, -1)[row.Type == 'Sell'] * float(row['Shares Traded'].replace(',','')), axis=1) - plt.xlim(df_insider.index[0], df_stock.index[-1]) - min_price, max_price = ax.get_ylim() - - price_range = max_price - min_price - shares_range = df_insider[df_insider['Type'] == 'Buy'].groupby(by=['Date']).sum()['Trade'].max() - df_insider[df_insider['Type'] == 'Sell'].groupby(by=['Date']).sum()['Trade'].min() - n_proportion = price_range / shares_range - - for ind in df_insider[df_insider['Type'] == 'Sell'].groupby(by=['Date']).sum().index: - if ind in df_stock.index: - ind_dt = ind - else: - ind_dt = get_next_stock_market_days(ind, 1)[0] - - n_stock_price = 0 - if s_interval == "1440min": - n_stock_price = df_stock['5. adjusted close'][ind_dt] - else: - n_stock_price = df_stock['4. close'][ind_dt] - - plt.vlines(x=ind_dt, - ymin= n_stock_price + n_proportion * float(df_insider[df_insider['Type'] == 'Sell'].groupby(by=['Date']).sum()['Trade'][ind]), - ymax= n_stock_price, - colors='red', ls='-', lw=5) - - for ind in df_insider[df_insider['Type'] == 'Buy'].groupby(by=['Date']).sum().index: - if ind in df_stock.index: - ind_dt = ind - else: - ind_dt = get_next_stock_market_days(ind, 1)[0] - - n_stock_price = 0 - if s_interval == "1440min": - n_stock_price = df_stock['5. adjusted close'][ind_dt] - else: - n_stock_price = df_stock['4. close'][ind_dt] - - plt.vlines(x=ind_dt, - ymin=n_stock_price, - ymax=n_stock_price + n_proportion * float(df_insider[df_insider['Type'] == 'Buy'].groupby(by=['Date']).sum()['Trade'][ind]), - colors='green', ls='-', lw=5) - - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.show() - - l_names = list() - for s_name in text_soup_market_business_insider.findAll('a', {'onclick':"silentTrackPI()"}): - l_names.append(s_name.text.strip()) - df_insider['Insider'] = l_names - - print(df_insider.sort_index(ascending=False).head(n=ns_parser.n_num).to_string()) - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return + + url_market_business_insider = f"https://markets.businessinsider.com/stocks/{s_ticker.lower()}-stock" + text_soup_market_business_insider = BeautifulSoup(requests.get(url_market_business_insider).text, "lxml") + + d_insider = dict() + l_insider_vals = list() + for idx, insider_val in enumerate(text_soup_market_business_insider.findAll('td', {'class':"table__td text-center"})): + #print(insider_val.text.strip()) + + l_insider_vals.append(insider_val.text.strip()) + + # Add value to dictionary + if (idx+1)%6 == 0: + # Check if we are still parsing insider trading activity + if '/' not in l_insider_vals[0]: + break + d_insider[(idx+1)//6] = l_insider_vals + l_insider_vals = list() + + df_insider = pd.DataFrame.from_dict(d_insider, orient='index', + columns = ['Date', 'Shares Traded', 'Shares Held', 'Price', 'Type', 'Option']) + + df_insider['Date'] = pd.to_datetime(df_insider['Date']) + df_insider = df_insider.set_index('Date') + df_insider = df_insider.sort_index(ascending=True) + + if s_start: + df_insider = df_insider[s_start:] + + pfig, ax = plt.subplots() + + if s_interval == "1440min": + plt.plot(df_stock.index, df_stock['5. adjusted close'].values, lw=3) + else: # Intraday + plt.plot(df_stock.index, df_stock['4. close'].values, lw=3) + + plt.title(f"{s_ticker.upper()} (Time Series) and Price Target") + + plt.xlabel('Time') + plt.ylabel('Share Price ($)') + + df_insider['Trade'] = df_insider.apply(lambda row: (1, -1)[row.Type == 'Sell'] * float(row['Shares Traded'].replace(',','')), axis=1) + plt.xlim(df_insider.index[0], df_stock.index[-1]) + min_price, max_price = ax.get_ylim() + + price_range = max_price - min_price + shares_range = df_insider[df_insider['Type'] == 'Buy'].groupby(by=['Date']).sum()['Trade'].max() - df_insider[df_insider['Type'] == 'Sell'].groupby(by=['Date']).sum()['Trade'].min() + n_proportion = price_range / shares_range + + for ind in df_insider[df_insider['Type'] == 'Sell'].groupby(by=['Date']).sum().index: + if ind in df_stock.index: + ind_dt = ind + else: + ind_dt = get_next_stock_market_days(ind, 1)[0] + + n_stock_price = 0 + if s_interval == "1440min": + n_stock_price = df_stock['5. adjusted close'][ind_dt] + else: + n_stock_price = df_stock['4. close'][ind_dt] + + plt.vlines(x=ind_dt, + ymin= n_stock_price + n_proportion * float(df_insider[df_insider['Type'] == 'Sell'].groupby(by=['Date']).sum()['Trade'][ind]), + ymax= n_stock_price, + colors='red', ls='-', lw=5) + + for ind in df_insider[df_insider['Type'] == 'Buy'].groupby(by=['Date']).sum().index: + if ind in df_stock.index: + ind_dt = ind + else: + ind_dt = get_next_stock_market_days(ind, 1)[0] + + n_stock_price = 0 + if s_interval == "1440min": + n_stock_price = df_stock['5. adjusted close'][ind_dt] + else: + n_stock_price = df_stock['4. close'][ind_dt] + + plt.vlines(x=ind_dt, + ymin=n_stock_price, + ymax=n_stock_price + n_proportion * float(df_insider[df_insider['Type'] == 'Buy'].groupby(by=['Date']).sum()['Trade'][ind]), + colors='green', ls='-', lw=5) + + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.show() + + l_names = list() + for s_name in text_soup_market_business_insider.findAll('a', {'onclick':"silentTrackPI()"}): + l_names.append(s_name.text.strip()) + df_insider['Insider'] = l_names + + print(df_insider.sort_index(ascending=False).head(n=ns_parser.n_num).to_string()) + print("") + diff --git a/due_diligence/financial_modeling_prep_api.py b/due_diligence/financial_modeling_prep_api.py index 936202a7594..02dab3c200e 100644 --- a/due_diligence/financial_modeling_prep_api.py +++ b/due_diligence/financial_modeling_prep_api.py @@ -12,19 +12,13 @@ def rating(l_args, s_ticker): is a (strong) buy, neutral or a (strong) sell. The following fields are expected: P/B, ROA, DCF, P/E, ROE, and D/E. [Source: Financial Modeling Prep]""") - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return - - df_fa = fa.rating(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP) - print(df_fa) - - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return + df_fa = fa.rating(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP) + print(df_fa) + + print("") diff --git a/due_diligence/finviz_api.py b/due_diligence/finviz_api.py index b34850fe1ec..512dee2d364 100644 --- a/due_diligence/finviz_api.py +++ b/due_diligence/finviz_api.py @@ -14,25 +14,20 @@ def insider(l_args, s_ticker): parser.add_argument('-n', "--num", action="store", dest="n_num", type=check_positive, default=10, help='number of latest inside traders.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return - - d_finviz_insider = finviz.get_insider(s_ticker) - df_fa = pd.DataFrame.from_dict(d_finviz_insider) - df_fa.set_index("Date", inplace=True) - df_fa = df_fa[['Relationship', 'Transaction', '#Shares', 'Cost', 'Value ($)', '#Shares Total', 'Insider Trading', 'SEC Form 4']] - print(df_fa.head(n=ns_parser.n_num)) - - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return + d_finviz_insider = finviz.get_insider(s_ticker) + df_fa = pd.DataFrame.from_dict(d_finviz_insider) + df_fa.set_index("Date", inplace=True) + df_fa = df_fa[['Relationship', 'Transaction', '#Shares', 'Cost', 'Value ($)', '#Shares Total', 'Insider Trading', 'SEC Form 4']] + print(df_fa.head(n=ns_parser.n_num)) + + print("") + # ---------------------------------------------------- NEWS ---------------------------------------------------- def news(l_args, s_ticker): @@ -43,29 +38,25 @@ def news(l_args, s_ticker): parser.add_argument('-n', "--num", action="store", dest="n_num", type=check_positive, default=5, help='Number of latest news being printed.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return - - d_finviz_news = finviz.get_news(s_ticker) - i=0 - for s_news_title, s_news_link in {*d_finviz_news}: - print(f"-> {s_news_title}") - print(f"{s_news_link}\n") - i+=1 - - if i > (ns_parser.n_num-1): - break - - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return + d_finviz_news = finviz.get_news(s_ticker) + i=0 + for s_news_title, s_news_link in {*d_finviz_news}: + print(f"-> {s_news_title}") + print(f"{s_news_link}\n") + i+=1 + + if i > (ns_parser.n_num-1): + break + + print("") + + # ---------------------------------------------------- ANALYST ---------------------------------------------------- def analyst(l_args, s_ticker): @@ -74,19 +65,14 @@ def analyst(l_args, s_ticker): are expected: date, analyst, category, price from, price to, and rating. [Source: Finviz]""") - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return - - d_finviz_analyst_price = finviz.get_analyst_price_targets(s_ticker) - df_fa = pd.DataFrame.from_dict(d_finviz_analyst_price) - df_fa.set_index("date", inplace=True) - print(df_fa) - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return + + d_finviz_analyst_price = finviz.get_analyst_price_targets(s_ticker) + df_fa = pd.DataFrame.from_dict(d_finviz_analyst_price) + df_fa.set_index("date", inplace=True) + print(df_fa) + print("") diff --git a/due_diligence/market_watch_api.py b/due_diligence/market_watch_api.py index 952ae8d3b0c..ad978b3a76f 100644 --- a/due_diligence/market_watch_api.py +++ b/due_diligence/market_watch_api.py @@ -18,52 +18,47 @@ def sec_fillings(l_args, s_ticker): parser.add_argument('-n', "--num", action="store", dest="n_num", type=check_positive, default=5, help='number of latest SEC filings.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return - - pd.set_option('display.max_colwidth', -1) - - url_financials = f"https://www.marketwatch.com/investing/stock/{s_ticker}/financials/secfilings" - - text_soup_financials = BeautifulSoup(requests.get(url_financials).text,"lxml") - - a_financials_header = list() - b_ready_to_process_info = False - soup_financials = text_soup_financials.findAll('tr', {'class': 'table__row'}) - for financials_info in soup_financials: - a_financials = financials_info.text.split('\n') - - # If header has been processed and dataframe created ready to populate the SEC information - if b_ready_to_process_info: - l_financials_info = [a_financials[2]] - l_financials_info.extend(a_financials[5:-1]) - l_financials_info.append(financials_info.a['href']) - # Append data values to financials - df_financials.loc[len(df_financials.index)] = l_financials_info - - if 'Filing Date' in a_financials: - l_financials_header = [a_financials[2]] - l_financials_header.extend(a_financials[5:-1]) - l_financials_header.append('Link') - - df_financials = pd.DataFrame(columns=l_financials_header) - df_financials.set_index('Filing Date') - b_ready_to_process_info = True - - # Set Filing Date as index - df_financials = df_financials.set_index('Filing Date') - - print(df_financials.head(n=ns_parser.n_num).to_string()) - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return + pd.set_option('display.max_colwidth', -1) + + url_financials = f"https://www.marketwatch.com/investing/stock/{s_ticker}/financials/secfilings" + + text_soup_financials = BeautifulSoup(requests.get(url_financials).text,"lxml") + + a_financials_header = list() + b_ready_to_process_info = False + soup_financials = text_soup_financials.findAll('tr', {'class': 'table__row'}) + for financials_info in soup_financials: + a_financials = financials_info.text.split('\n') + + # If header has been processed and dataframe created ready to populate the SEC information + if b_ready_to_process_info: + l_financials_info = [a_financials[2]] + l_financials_info.extend(a_financials[5:-1]) + l_financials_info.append(financials_info.a['href']) + # Append data values to financials + df_financials.loc[len(df_financials.index)] = l_financials_info + + if 'Filing Date' in a_financials: + l_financials_header = [a_financials[2]] + l_financials_header.extend(a_financials[5:-1]) + l_financials_header.append('Link') + + df_financials = pd.DataFrame(columns=l_financials_header) + df_financials.set_index('Filing Date') + b_ready_to_process_info = True + + # Set Filing Date as index + df_financials = df_financials.set_index('Filing Date') + + print(df_financials.head(n=ns_parser.n_num).to_string()) + print("") + # ---------------------------------------------------- Sean Seah Warnings ---------------------------------------------------- def sean_seah_warnings(l_args, s_ticker): @@ -79,140 +74,135 @@ def sean_seah_warnings(l_args, s_ticker): parser.add_argument('-d', "--debug", action="store_true", default=False, dest="b_debug", help='print insights into warnings calculation.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return - - if ns_parser.b_info: - filepath = 'fundamental_analysis/info_sean_seah.txt' - with open(filepath) as fp: - line = fp.readline() - while line: - print("{}".format(line.strip())) - line = fp.readline() - print("") - - # From INCOME STATEMENT, get: 'EPS (Basic)', 'Net Income', 'Interest Expense', 'EBITDA' - url_financials = f"https://www.marketwatch.com/investing/stock/{s_ticker}/financials/income" - text_soup_financials = BeautifulSoup(requests.get(url_financials).text,"lxml") - - # Define financials columns - a_financials_header = list() - for financials_header in text_soup_financials.findAll('th', {'class': 'overflow__heading'}): - a_financials_header.append(financials_header.text.strip('\n').split('\n')[0]) - df_financials = pd.DataFrame(columns=a_financials_header[0:-1]) - - # Add financials values - soup_financials = text_soup_financials.findAll('tr', {'class': 'table__row '}) - soup_financials += text_soup_financials.findAll('tr', {'class': 'table__row is-highlighted'}) - for financials_info in soup_financials: - a_financials_info = financials_info.text.split('\n') - l_financials = [a_financials_info[2]] - l_financials.extend(a_financials_info[5:-2]) - # Append data values to financials - df_financials.loc[len(df_financials.index)] = l_financials - - # Set item name as index - df_financials = df_financials.set_index('Item') - - df_sean_seah = df_financials.loc[['EPS (Basic)', 'Net Income', 'Interest Expense', 'EBITDA']] - - # From BALANCE SHEET, get: 'Liabilities & Shareholders\' Equity', 'Long-Term Debt' - url_financials = f"https://www.marketwatch.com/investing/stock/{s_ticker}/financials/balance-sheet" - text_soup_financials = BeautifulSoup(requests.get(url_financials).text,"lxml") - - # Define financials columns - a_financials_header = list() - for financials_header in text_soup_financials.findAll('th', {'class': 'overflow__heading'}): - a_financials_header.append(financials_header.text.strip('\n').split('\n')[0]) - - s_header_end_trend = "5-year trend" - df_financials = pd.DataFrame(columns=a_financials_header[0:a_financials_header.index(s_header_end_trend)]) - - # Add financials values - soup_financials = text_soup_financials.findAll('tr', {'class': 'table__row '}) - soup_financials += text_soup_financials.findAll('tr', {'class': 'table__row is-highlighted'}) - for financials_info in soup_financials: - a_financials_info = financials_info.text.split('\n') - l_financials = [a_financials_info[2]] - l_financials.extend(a_financials_info[5:-2]) - # Append data values to financials - df_financials.loc[len(df_financials.index)] = l_financials - - # Set item name as index - df_financials = df_financials.set_index('Item') - - # Create dataframe to compute meaningful metrics from sean seah book - df_sean_seah = df_sean_seah.append(df_financials.loc[['Total Shareholders\' Equity', 'Liabilities & Shareholders\' Equity', 'Long-Term Debt']]) - - # Clean these metrics by parsing their values to float - df_sean_seah = df_sean_seah.applymap(lambda x: clean_data_values_to_float(x)) - - # Add additional necessary metrics - series = df_sean_seah.loc['Net Income']/df_sean_seah.loc['Total Shareholders\' Equity'] - series.name = "ROE" - df_sean_seah = df_sean_seah.append(series) - - series = df_sean_seah.loc['EBITDA']/df_sean_seah.loc['Interest Expense'] - series.name = "Interest Coverage Ratio" - df_sean_seah = df_sean_seah.append(series) - - series = df_sean_seah.loc['Net Income']/df_sean_seah.loc['Liabilities & Shareholders\' Equity'] - series.name = "ROA" - df_sean_seah = df_sean_seah.append(series) - - print(df_sean_seah.applymap(lambda x: int_or_round_float(x)).to_string()) - - n_warnings = 0 - print("\nWARNINGS:") - - if np.any(df_sean_seah.loc['EPS (Basic)'].diff().dropna().values < 0): - print("NO consistent historical earnings per share") - n_warnings += 1 - if ns_parser.b_debug: - sa_eps = np.array2string(df_sean_seah.loc['EPS (Basic)'].values, formatter={'float_kind': lambda x: int_or_round_float(x)}) - print(f" EPS: {sa_eps}") - sa_growth = np.array2string(df_sean_seah.loc['EPS (Basic)'].diff().dropna().values, formatter={'float_kind': lambda x: int_or_round_float(x)}) - print(f" Growth: {sa_growth} < 0") - - if np.any(df_sean_seah.loc['ROE'].values < 0.15): - print("NOT consistently high return on equity") - n_warnings += 1 - if ns_parser.b_debug: - sa_roe = np.array2string(df_sean_seah.loc['ROE'].values, formatter={'float_kind': lambda x: int_or_round_float(x)}) - print(f" ROE: {sa_roe} < 0.15") - - if np.any(df_sean_seah.loc['ROA'].values < 0.07): - print("NOT consistently high return on assets") - n_warnings += 1 - if ns_parser.b_debug: - sa_roa = np.array2string(df_sean_seah.loc['ROA'].values, formatter={'float_kind': lambda x: int_or_round_float(x)}) - print(f" ROA: {sa_roa} < 0.07") - - if np.any(df_sean_seah.loc['Long-Term Debt'].values > 5*df_sean_seah.loc['Net Income'].values): - print("5x Net Income < Long-Term Debt") - n_warnings += 1 - if ns_parser.b_debug: - sa_net_income = np.array2string(df_sean_seah.loc['Net Income'].values, formatter={'float_kind': lambda x: int_or_round_float(x)}) - print(f" NET Income: {sa_net_income}") - sa_5_long_term_debt = np.array2string(5*df_sean_seah.loc['Long-Term Debt'].values, formatter={'float_kind': lambda x: int_or_round_float(x)}) - print(f" lower than 5x Long-Term Debt: {sa_5_long_term_debt}") - - if np.any(df_sean_seah.loc['Interest Coverage Ratio'].values < 3): - print("Interest coverage ratio less than 3") - n_warnings += 1 - if ns_parser.b_debug: - sa_interest_coverage_ratio = np.array2string(100*df_sean_seah.loc['Interest Coverage Ratio'].values, formatter={'float_kind': lambda x: int_or_round_float(x)}) - print(f" Interest Coverage Ratio: {sa_interest_coverage_ratio} < 3") - - if n_warnings == 0: - print("None. Good stonk") - - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return + + if ns_parser.b_info: + filepath = 'fundamental_analysis/info_sean_seah.txt' + with open(filepath) as fp: + line = fp.readline() + while line: + print("{}".format(line.strip())) + line = fp.readline() + print("") + + # From INCOME STATEMENT, get: 'EPS (Basic)', 'Net Income', 'Interest Expense', 'EBITDA' + url_financials = f"https://www.marketwatch.com/investing/stock/{s_ticker}/financials/income" + text_soup_financials = BeautifulSoup(requests.get(url_financials).text,"lxml") + + # Define financials columns + a_financials_header = list() + for financials_header in text_soup_financials.findAll('th', {'class': 'overflow__heading'}): + a_financials_header.append(financials_header.text.strip('\n').split('\n')[0]) + df_financials = pd.DataFrame(columns=a_financials_header[0:-1]) + + # Add financials values + soup_financials = text_soup_financials.findAll('tr', {'class': 'table__row '}) + soup_financials += text_soup_financials.findAll('tr', {'class': 'table__row is-highlighted'}) + for financials_info in soup_financials: + a_financials_info = financials_info.text.split('\n') + l_financials = [a_financials_info[2]] + l_financials.extend(a_financials_info[5:-2]) + # Append data values to financials + df_financials.loc[len(df_financials.index)] = l_financials + + # Set item name as index + df_financials = df_financials.set_index('Item') + + df_sean_seah = df_financials.loc[['EPS (Basic)', 'Net Income', 'Interest Expense', 'EBITDA']] + + # From BALANCE SHEET, get: 'Liabilities & Shareholders\' Equity', 'Long-Term Debt' + url_financials = f"https://www.marketwatch.com/investing/stock/{s_ticker}/financials/balance-sheet" + text_soup_financials = BeautifulSoup(requests.get(url_financials).text,"lxml") + + # Define financials columns + a_financials_header = list() + for financials_header in text_soup_financials.findAll('th', {'class': 'overflow__heading'}): + a_financials_header.append(financials_header.text.strip('\n').split('\n')[0]) + + s_header_end_trend = "5-year trend" + df_financials = pd.DataFrame(columns=a_financials_header[0:a_financials_header.index(s_header_end_trend)]) + + # Add financials values + soup_financials = text_soup_financials.findAll('tr', {'class': 'table__row '}) + soup_financials += text_soup_financials.findAll('tr', {'class': 'table__row is-highlighted'}) + for financials_info in soup_financials: + a_financials_info = financials_info.text.split('\n') + l_financials = [a_financials_info[2]] + l_financials.extend(a_financials_info[5:-2]) + # Append data values to financials + df_financials.loc[len(df_financials.index)] = l_financials + + # Set item name as index + df_financials = df_financials.set_index('Item') + + # Create dataframe to compute meaningful metrics from sean seah book + df_sean_seah = df_sean_seah.append(df_financials.loc[['Total Shareholders\' Equity', 'Liabilities & Shareholders\' Equity', 'Long-Term Debt']]) + + # Clean these metrics by parsing their values to float + df_sean_seah = df_sean_seah.applymap(lambda x: clean_data_values_to_float(x)) + + # Add additional necessary metrics + series = df_sean_seah.loc['Net Income']/df_sean_seah.loc['Total Shareholders\' Equity'] + series.name = "ROE" + df_sean_seah = df_sean_seah.append(series) + + series = df_sean_seah.loc['EBITDA']/df_sean_seah.loc['Interest Expense'] + series.name = "Interest Coverage Ratio" + df_sean_seah = df_sean_seah.append(series) + + series = df_sean_seah.loc['Net Income']/df_sean_seah.loc['Liabilities & Shareholders\' Equity'] + series.name = "ROA" + df_sean_seah = df_sean_seah.append(series) + + print(df_sean_seah.applymap(lambda x: int_or_round_float(x)).to_string()) + + n_warnings = 0 + print("\nWARNINGS:") + + if np.any(df_sean_seah.loc['EPS (Basic)'].diff().dropna().values < 0): + print("NO consistent historical earnings per share") + n_warnings += 1 + if ns_parser.b_debug: + sa_eps = np.array2string(df_sean_seah.loc['EPS (Basic)'].values, formatter={'float_kind': lambda x: int_or_round_float(x)}) + print(f" EPS: {sa_eps}") + sa_growth = np.array2string(df_sean_seah.loc['EPS (Basic)'].diff().dropna().values, formatter={'float_kind': lambda x: int_or_round_float(x)}) + print(f" Growth: {sa_growth} < 0") + + if np.any(df_sean_seah.loc['ROE'].values < 0.15): + print("NOT consistently high return on equity") + n_warnings += 1 + if ns_parser.b_debug: + sa_roe = np.array2string(df_sean_seah.loc['ROE'].values, formatter={'float_kind': lambda x: int_or_round_float(x)}) + print(f" ROE: {sa_roe} < 0.15") + + if np.any(df_sean_seah.loc['ROA'].values < 0.07): + print("NOT consistently high return on assets") + n_warnings += 1 + if ns_parser.b_debug: + sa_roa = np.array2string(df_sean_seah.loc['ROA'].values, formatter={'float_kind': lambda x: int_or_round_float(x)}) + print(f" ROA: {sa_roa} < 0.07") + + if np.any(df_sean_seah.loc['Long-Term Debt'].values > 5*df_sean_seah.loc['Net Income'].values): + print("5x Net Income < Long-Term Debt") + n_warnings += 1 + if ns_parser.b_debug: + sa_net_income = np.array2string(df_sean_seah.loc['Net Income'].values, formatter={'float_kind': lambda x: int_or_round_float(x)}) + print(f" NET Income: {sa_net_income}") + sa_5_long_term_debt = np.array2string(5*df_sean_seah.loc['Long-Term Debt'].values, formatter={'float_kind': lambda x: int_or_round_float(x)}) + print(f" lower than 5x Long-Term Debt: {sa_5_long_term_debt}") + + if np.any(df_sean_seah.loc['Interest Coverage Ratio'].values < 3): + print("Interest coverage ratio less than 3") + n_warnings += 1 + if ns_parser.b_debug: + sa_interest_coverage_ratio = np.array2string(100*df_sean_seah.loc['Interest Coverage Ratio'].values, formatter={'float_kind': lambda x: int_or_round_float(x)}) + print(f" Interest Coverage Ratio: {sa_interest_coverage_ratio} < 3") + + if n_warnings == 0: + print("None. Good stonk") + + print("") diff --git a/due_diligence/quandl_api.py b/due_diligence/quandl_api.py index e5745e51999..9246ac965b4 100644 --- a/due_diligence/quandl_api.py +++ b/due_diligence/quandl_api.py @@ -20,55 +20,50 @@ def short_interest(l_args, s_ticker, s_start): parser.add_argument('-d', "--days", action="store", dest="n_days", type=check_positive, default=10, help='number of latest days to print data.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return - - quandl.ApiConfig.api_key = cfg.API_KEY_QUANDL - - if ns_parser.b_nyse: - df_short_interest = quandl.get(f"FINRA/FNYX_{s_ticker}") - else: - df_short_interest = quandl.get(f"FINRA/FNSQ_{s_ticker}") - - df_short_interest = df_short_interest[s_start:] - df_short_interest.columns = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_short_interest.columns.tolist()] - df_short_interest['% of Volume Shorted'] = round(100*df_short_interest['Short Volume']/df_short_interest['Total Volume'], 2) - - fig, ax = plt.subplots() - ax.bar(df_short_interest.index, df_short_interest['Short Volume'], 0.3, color='r') - ax.bar(df_short_interest.index, df_short_interest['Total Volume']-df_short_interest['Short Volume'], 0.3, bottom=df_short_interest['Short Volume'], color='b') - ax.set_ylabel('Shares') - ax.set_xlabel('Date') - - if s_start: - ax.set_title(f"{('NASDAQ', 'NYSE')[ns_parser.b_nyse]} Short Interest on {s_ticker} from {s_start.date()}") - else: - ax.set_title(f"{('NASDAQ', 'NYSE')[ns_parser.b_nyse]} Short Interest on {s_ticker}") - - ax.legend(labels=['Short Volume', 'Total Volume']) - ax.tick_params(axis='both', which='major') - ax.yaxis.set_major_formatter(ticker.EngFormatter()) - ax_twin = ax.twinx() - ax_twin.tick_params(axis='y', colors='green') - ax_twin.set_ylabel('Percentage of Volume Shorted', color='green') - ax_twin.plot(df_short_interest.index, df_short_interest['% of Volume Shorted'], color='green') - ax_twin.tick_params(axis='y', which='major', color='green') - ax_twin.yaxis.set_major_formatter(ticker.FormatStrFormatter('%.0f%%')) - plt.xlim([df_short_interest.index[0], df_short_interest.index[-1]]) - - df_short_interest['% of Volume Shorted'] = df_short_interest['% of Volume Shorted'].apply(lambda x: f'{x/100:.2%}') - df_short_interest = df_short_interest.applymap(lambda x: long_number_format(x)).sort_index(ascending=False) - - pd.set_option('display.max_colwidth', 70) - print(df_short_interest.head(n=ns_parser.n_days).to_string()) - print("") - - plt.show() - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return + + quandl.ApiConfig.api_key = cfg.API_KEY_QUANDL + + if ns_parser.b_nyse: + df_short_interest = quandl.get(f"FINRA/FNYX_{s_ticker}") + else: + df_short_interest = quandl.get(f"FINRA/FNSQ_{s_ticker}") + + df_short_interest = df_short_interest[s_start:] + df_short_interest.columns = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_short_interest.columns.tolist()] + df_short_interest['% of Volume Shorted'] = round(100*df_short_interest['Short Volume']/df_short_interest['Total Volume'], 2) + + fig, ax = plt.subplots() + ax.bar(df_short_interest.index, df_short_interest['Short Volume'], 0.3, color='r') + ax.bar(df_short_interest.index, df_short_interest['Total Volume']-df_short_interest['Short Volume'], 0.3, bottom=df_short_interest['Short Volume'], color='b') + ax.set_ylabel('Shares') + ax.set_xlabel('Date') + + if s_start: + ax.set_title(f"{('NASDAQ', 'NYSE')[ns_parser.b_nyse]} Short Interest on {s_ticker} from {s_start.date()}") + else: + ax.set_title(f"{('NASDAQ', 'NYSE')[ns_parser.b_nyse]} Short Interest on {s_ticker}") + + ax.legend(labels=['Short Volume', 'Total Volume']) + ax.tick_params(axis='both', which='major') + ax.yaxis.set_major_formatter(ticker.EngFormatter()) + ax_twin = ax.twinx() + ax_twin.tick_params(axis='y', colors='green') + ax_twin.set_ylabel('Percentage of Volume Shorted', color='green') + ax_twin.plot(df_short_interest.index, df_short_interest['% of Volume Shorted'], color='green') + ax_twin.tick_params(axis='y', which='major', color='green') + ax_twin.yaxis.set_major_formatter(ticker.FormatStrFormatter('%.0f%%')) + plt.xlim([df_short_interest.index[0], df_short_interest.index[-1]]) + + df_short_interest['% of Volume Shorted'] = df_short_interest['% of Volume Shorted'].apply(lambda x: f'{x/100:.2%}') + df_short_interest = df_short_interest.applymap(lambda x: long_number_format(x)).sort_index(ascending=False) + + pd.set_option('display.max_colwidth', 70) + print(df_short_interest.head(n=ns_parser.n_days).to_string()) + print("") + + plt.show() diff --git a/due_diligence/reddit_api.py b/due_diligence/reddit_api.py index 432f5311057..1a3d852c829 100644 --- a/due_diligence/reddit_api.py +++ b/due_diligence/reddit_api.py @@ -22,91 +22,88 @@ def due_diligence(l_args, s_ticker): help="""search through all flairs (apart from Yolo and Meme), otherwise we focus on specific flairs: DD, technical analysis, Catalyst, News, Advice, Chart """) - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") + return - praw_api = praw.Reddit(client_id=cfg.API_REDDIT_CLIENT_ID, - client_secret=cfg.API_REDDIT_CLIENT_SECRET, - username=cfg.API_REDDIT_USERNAME, - user_agent=cfg.API_REDDIT_USER_AGENT, - password=cfg.API_REDDIT_PASSWORD) + praw_api = praw.Reddit(client_id=cfg.API_REDDIT_CLIENT_ID, + client_secret=cfg.API_REDDIT_CLIENT_SECRET, + username=cfg.API_REDDIT_USERNAME, + user_agent=cfg.API_REDDIT_USER_AGENT, + password=cfg.API_REDDIT_PASSWORD) - psaw_api = PushshiftAPI() + psaw_api = PushshiftAPI() - n_ts_after = int((datetime.today() - timedelta(days=ns_parser.n_days)).timestamp()) - l_flair_text = ['DD', 'technical analysis', 'Catalyst', 'News', 'Advice', 'Chart'] - l_sub_reddits = ['pennystocks', 'RobinHoodPennyStocks', 'Daytrading', 'StockMarket', 'stocks', 'investing', 'wallstreetbets'] + n_ts_after = int((datetime.today() - timedelta(days=ns_parser.n_days)).timestamp()) + l_flair_text = ['DD', 'technical analysis', 'Catalyst', 'News', 'Advice', 'Chart'] + l_sub_reddits = ['pennystocks', 'RobinHoodPennyStocks', 'Daytrading', 'StockMarket', 'stocks', 'investing', 'wallstreetbets'] - submissions = psaw_api.search_submissions(after=int(n_ts_after), - subreddit=l_sub_reddits, - q=s_ticker, - filter=['id']) - d_submission = {} - n_flair_posts_found = 0 - while True: - submission = next(submissions, None) - if submission: - # Get more information about post using PRAW api - submission = praw_api.submission(id=submission.id) + submissions = psaw_api.search_submissions(after=int(n_ts_after), + subreddit=l_sub_reddits, + q=s_ticker, + filter=['id']) + d_submission = {} + n_flair_posts_found = 0 + while True: + submission = next(submissions, None) + if submission: + # Get more information about post using PRAW api + submission = praw_api.submission(id=submission.id) - # Ensure that the post hasn't been removed in the meanwhile - if not submission.removed_by_category: + # Ensure that the post hasn't been removed in the meanwhile + if not submission.removed_by_category: - # Either just filter out Yolo, and Meme flairs, or focus on DD, based on b_DD flag - if (submission.link_flair_text in l_flair_text, - submission.link_flair_text not in ['Yolo', 'Meme'])[ns_parser.b_all]: + # Either just filter out Yolo, and Meme flairs, or focus on DD, based on b_DD flag + if (submission.link_flair_text in l_flair_text, + submission.link_flair_text not in ['Yolo', 'Meme'])[ns_parser.b_all]: - # Refactor data - s_datetime = datetime.utcfromtimestamp(submission.created_utc).strftime("%d/%m/%Y %H:%M:%S") - s_link = f"https://www.reddit.com{submission.permalink}" - s_all_awards = "" - for award in submission.all_awardings: - s_all_awards += f"{award['count']} {award['name']}\n" - s_all_awards = s_all_awards[:-2] + # Refactor data + s_datetime = datetime.utcfromtimestamp(submission.created_utc).strftime("%d/%m/%Y %H:%M:%S") + s_link = f"https://www.reddit.com{submission.permalink}" + s_all_awards = "" + for award in submission.all_awardings: + s_all_awards += f"{award['count']} {award['name']}\n" + s_all_awards = s_all_awards[:-2] - # Create dictionary with data to construct dataframe allows to save data - d_submission[submission.id] = { - 'created_utc': s_datetime, - 'subreddit': submission.subreddit, - 'link_flair_text': submission.link_flair_text, - 'title':submission.title, - 'score': submission.score, - 'link': s_link, - 'num_comments': submission.num_comments, - 'upvote_ratio': submission.upvote_ratio, - 'awards': s_all_awards - } + # Create dictionary with data to construct dataframe allows to save data + d_submission[submission.id] = { + 'created_utc': s_datetime, + 'subreddit': submission.subreddit, + 'link_flair_text': submission.link_flair_text, + 'title':submission.title, + 'score': submission.score, + 'link': s_link, + 'num_comments': submission.num_comments, + 'upvote_ratio': submission.upvote_ratio, + 'awards': s_all_awards + } - # Print post data collected so far - print(f"{s_datetime} - {submission.title}") - print(f"{s_link}") - t_post = PrettyTable(['Subreddit', 'Flair', 'Score', '# Comments', 'Upvote %', "Awards"]) - t_post.add_row([submission.subreddit, submission.link_flair_text, submission.score, - submission.num_comments,f"{round(100*submission.upvote_ratio)}%", s_all_awards]) - print(t_post) - print("\n") + # Print post data collected so far + print(f"{s_datetime} - {submission.title}") + print(f"{s_link}") + t_post = PrettyTable(['Subreddit', 'Flair', 'Score', '# Comments', 'Upvote %', "Awards"]) + t_post.add_row([submission.subreddit, submission.link_flair_text, submission.score, + submission.num_comments,f"{round(100*submission.upvote_ratio)}%", s_all_awards]) + print(t_post) + print("\n") - # If needed, submission.comments could give us the top comments + # If needed, submission.comments could give us the top comments - # Increment count of valid posts found - n_flair_posts_found += 1 + # Increment count of valid posts found + n_flair_posts_found += 1 - # Check if number of wanted posts found has been reached - if n_flair_posts_found > ns_parser.n_limit-1: - break - - # Check if search_submissions didn't get anymore posts - else: + # Check if number of wanted posts found has been reached + if n_flair_posts_found > ns_parser.n_limit-1: break - print(f"{('No more posts with specified requirements found.', '')[n_flair_posts_found > ns_parser.n_limit-1]}") - # Create df with found data. Useful for saving all info in excel file. - #df_submissions = pd.DataFrame.from_dict(d_submission, orient='index', columns=list(d_submission[next(iter(d_submission.keys()))].keys())) - #df_submissions.sort_values(by=['created_utc'], inplace=True, ascending=True) + # Check if search_submissions didn't get anymore posts + else: + break + + print(f"{('No more posts with specified requirements found.', '')[n_flair_posts_found > ns_parser.n_limit-1]}") + # Create df with found data. Useful for saving all info in excel file. + #df_submissions = pd.DataFrame.from_dict(d_submission, orient='index', columns=list(d_submission[next(iter(d_submission.keys()))].keys())) + #df_submissions.sort_values(by=['created_utc'], inplace=True, ascending=True) - except: - print("") diff --git a/fundamental_analysis/alpha_vantage_api.py b/fundamental_analysis/alpha_vantage_api.py index fc5c01b04ba..aeb05ae2123 100644 --- a/fundamental_analysis/alpha_vantage_api.py +++ b/fundamental_analysis/alpha_vantage_api.py @@ -27,59 +27,57 @@ def overview(l_args, s_ticker): Percent insiders, Percent institutions, Forward annual dividend rate, Forward annual dividend yield, Payout ratio, Dividend date, Ex dividend date, Last split factor, and Last split date. [Source: Alpha Vantage]""") - - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - # Request OVERVIEW data from Alpha Vantage API - s_req = f"https://www.alphavantage.co/query?function=OVERVIEW&symbol={s_ticker}&apikey={cfg.API_KEY_ALPHAVANTAGE}" - result = requests.get(s_req, stream=True) - - # If the returned data was successful - if result.status_code == 200: - # Parse json data to dataframe - df_fa = json_normalize(result.json()) - # Keep json data sorting in dataframe - df_fa = df_fa[list(result.json().keys())].T - df_fa = df_fa.applymap(lambda x: long_number_format(x)) - df_fa.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fa.index.tolist()] - df_fa.index = [s_val.capitalize() for s_val in df_fa.index] - df_fa = df_fa.rename(index={"E b i t d a":"EBITDA", - "P e ratio":"PE ratio", - "P e g ratio":"PEG ratio", - "E p s":"EPS", - "Revenue per share t t m":"Revenue per share TTM", - "Operating margin t t m":"Operating margin TTM", - "Return on assets t t m":"Return on assets TTM", - "Return on equity t t m":"Return on equity TTM", - "Revenue t t m":"Revenue TTM", - "Gross profit t t m":"Gross profit TTM", - "Diluted e p s t t m":"Diluted EPS TTM", - "Quarterly earnings growth y o y":"Quarterly earnings growth YOY", - "Quarterly revenue growth y o y":"Quarterly revenue growth YOY", - "Trailing p e":"Trailing PE", - "Forward p e":"Forward PE", - "Price to sales ratio t t m":"Price to sales ratio TTM", - "E v to revenue":"EV to revenue", - "E v to e b i t d a":"EV to EBITDA"}) - - pd.set_option('display.max_colwidth', -1) - - print(df_fa.drop(index=['Description']).to_string(header=False)) - print(f"Description: {df_fa.loc['Description'][0]}") - print("") - else: - print(f"Error: {result.status_code}") - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return + # Request OVERVIEW data from Alpha Vantage API + s_req = f"https://www.alphavantage.co/query?function=OVERVIEW&symbol={s_ticker}&apikey={cfg.API_KEY_ALPHAVANTAGE}" + result = requests.get(s_req, stream=True) + + # If the returned data was successful + if result.status_code == 200: + # Parse json data to dataframe + df_fa = json_normalize(result.json()) + # Keep json data sorting in dataframe + df_fa = df_fa[list(result.json().keys())].T + df_fa = df_fa.applymap(lambda x: long_number_format(x)) + df_fa.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fa.index.tolist()] + df_fa.index = [s_val.capitalize() for s_val in df_fa.index] + df_fa = df_fa.rename(index={ + "E b i t d a": "EBITDA", + "P e ratio": "PE ratio", + "P e g ratio": "PEG ratio", + "E p s": "EPS", + "Revenue per share t t m": "Revenue per share TTM", + "Operating margin t t m": "Operating margin TTM", + "Return on assets t t m": "Return on assets TTM", + "Return on equity t t m": "Return on equity TTM", + "Revenue t t m": "Revenue TTM", + "Gross profit t t m": "Gross profit TTM", + "Diluted e p s t t m": "Diluted EPS TTM", + "Quarterly earnings growth y o y": "Quarterly earnings growth YOY", + "Quarterly revenue growth y o y": "Quarterly revenue growth YOY", + "Trailing p e": "Trailing PE", + "Forward p e": "Forward PE", + "Price to sales ratio t t m": "Price to sales ratio TTM", + "E v to revenue": "EV to revenue", + "E v to e b i t d a": "EV to EBITDA", + }) + + pd.set_option('display.max_colwidth', -1) + + print(df_fa.drop(index=['Description']).to_string(header=False)) + print(f"Description: {df_fa.loc['Description'][0]}") + print("") + else: + print(f"Error: {result.status_code}") + print("") + + # ------------------------------------------------------ KEY ------------------------------------------------------ def key(l_args, s_ticker): @@ -89,46 +87,42 @@ def key(l_args, s_ticker): Market capitalization, EBITDA, EPS, PE ratio, PEG ratio, Price to book ratio, Return on equity TTM, Payout ratio, Price to sales ratio TTM, Dividend yield, 50 day moving average, Analyst target price, Beta [Source: Alpha Vantage API]""") - - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - # Request OVERVIEW data - s_req = f"https://www.alphavantage.co/query?function=OVERVIEW&symbol={s_ticker}&apikey={cfg.API_KEY_ALPHAVANTAGE}" - result = requests.get(s_req, stream=True) - - # If the returned data was successful - if result.status_code == 200: - df_fa = json_normalize(result.json()) - df_fa = df_fa[list(result.json().keys())].T - - df_fa = df_fa.applymap(lambda x: long_number_format(x)) - df_fa.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fa.index.tolist()] - df_fa.index = [s_val.capitalize() for s_val in df_fa.index] - df_fa = df_fa.rename(index={"E b i t d a":"EBITDA", - "P e ratio":"PE ratio", - "P e g ratio":"PEG ratio", - "E p s":"EPS", - "Return on equity t t m":"Return on equity TTM", - "Price to sales ratio t t m":"Price to sales ratio TTM"}) - as_key_metrics = ["Market capitalization", "EBITDA", "EPS", "PE ratio", "PEG ratio", "Price to book ratio", - "Return on equity TTM", "Payout ratio", "Price to sales ratio TTM", "Dividend yield", - "50 day moving average", "Analyst target price", "Beta"] - print(df_fa.loc[as_key_metrics].to_string(header=False)) - print("") - else: - print(f"Error: {result.status_code}") - - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return + # Request OVERVIEW data + s_req = f"https://www.alphavantage.co/query?function=OVERVIEW&symbol={s_ticker}&apikey={cfg.API_KEY_ALPHAVANTAGE}" + result = requests.get(s_req, stream=True) + + # If the returned data was successful + if result.status_code == 200: + df_fa = json_normalize(result.json()) + df_fa = df_fa[list(result.json().keys())].T + + df_fa = df_fa.applymap(lambda x: long_number_format(x)) + df_fa.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fa.index.tolist()] + df_fa.index = [s_val.capitalize() for s_val in df_fa.index] + df_fa = df_fa.rename(index={"E b i t d a":"EBITDA", + "P e ratio":"PE ratio", + "P e g ratio":"PEG ratio", + "E p s":"EPS", + "Return on equity t t m":"Return on equity TTM", + "Price to sales ratio t t m":"Price to sales ratio TTM"}) + as_key_metrics = ["Market capitalization", "EBITDA", "EPS", "PE ratio", "PEG ratio", "Price to book ratio", + "Return on equity TTM", "Payout ratio", "Price to sales ratio TTM", "Dividend yield", + "50 day moving average", "Analyst target price", "Beta"] + print(df_fa.loc[as_key_metrics].to_string(header=False)) + print("") + else: + print(f"Error: {result.status_code}") + + print("") + + # ---------------------------------------------------- INCOME_STATEMENT ---------------------------------------------------- def income_statement(l_args, s_ticker): @@ -147,40 +141,35 @@ def income_statement(l_args, s_ticker): parser.add_argument('-q', "--quarter", action="store_true", default=False, dest="b_quarter", help='Quarter fundamental data flag.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return - - if ns_parser.n_num == 1: - pd.set_option('display.max_colwidth', -1) - else: - pd.options.display.max_colwidth = 40 - - fd = FundamentalData(key=cfg.API_KEY_ALPHAVANTAGE, output_format='pandas') - if ns_parser.b_quarter: - df_fa, d_fd_metadata = fd.get_income_statement_quarterly(symbol=s_ticker) - else: - df_fa, d_fd_metadata = fd.get_income_statement_annual(symbol=s_ticker) - - df_fa = df_fa.set_index('fiscalDateEnding') - df_fa = df_fa.head(n=ns_parser.n_num).T - df_fa = df_fa.mask(df_fa.astype(object).eq(ns_parser.n_num*['None'])).dropna() - df_fa = df_fa.mask(df_fa.astype(object).eq(ns_parser.n_num*['0'])).dropna() - df_fa = df_fa.applymap(lambda x: long_number_format(x)) - df_fa.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fa.index.tolist()] - df_fa.index = [s_val.capitalize() for s_val in df_fa.index] - df_fa.columns.name = "Fiscal Date Ending" - print(df_fa) - - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return - + + if ns_parser.n_num == 1: + pd.set_option('display.max_colwidth', -1) + else: + pd.options.display.max_colwidth = 40 + + fd = FundamentalData(key=cfg.API_KEY_ALPHAVANTAGE, output_format='pandas') + if ns_parser.b_quarter: + df_fa, d_fd_metadata = fd.get_income_statement_quarterly(symbol=s_ticker) + else: + df_fa, d_fd_metadata = fd.get_income_statement_annual(symbol=s_ticker) + + df_fa = df_fa.set_index('fiscalDateEnding') + df_fa = df_fa.head(n=ns_parser.n_num).T + df_fa = df_fa.mask(df_fa.astype(object).eq(ns_parser.n_num*['None'])).dropna() + df_fa = df_fa.mask(df_fa.astype(object).eq(ns_parser.n_num*['0'])).dropna() + df_fa = df_fa.applymap(lambda x: long_number_format(x)) + df_fa.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fa.index.tolist()] + df_fa.index = [s_val.capitalize() for s_val in df_fa.index] + df_fa.columns.name = "Fiscal Date Ending" + print(df_fa) + + print("") + # ---------------------------------------------------- BALANCE_SHEET ---------------------------------------------------- def balance_sheet(l_args, s_ticker): @@ -205,39 +194,35 @@ def balance_sheet(l_args, s_ticker): parser.add_argument('-q', "--quarter", action="store_true", default=False, dest="b_quarter", help='Quarter fundamental data flag.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return - - if ns_parser.n_num == 1: - pd.set_option('display.max_colwidth', -1) - else: - pd.options.display.max_colwidth = 40 - - fd = FundamentalData(key=cfg.API_KEY_ALPHAVANTAGE, output_format='pandas') - if ns_parser.b_quarter: - df_fa, d_fd_metadata = fd.get_balance_sheet_quarterly(symbol=s_ticker) - else: - df_fa, d_fd_metadata = fd.get_balance_sheet_annual(symbol=s_ticker) - - df_fa = df_fa.set_index('fiscalDateEnding') - df_fa = df_fa.head(n=ns_parser.n_num).T - df_fa = df_fa.mask(df_fa.astype(object).eq(ns_parser.n_num*['None'])).dropna() - df_fa = df_fa.mask(df_fa.astype(object).eq(ns_parser.n_num*['0'])).dropna() - df_fa = df_fa.applymap(lambda x: long_number_format(x)) - df_fa.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fa.index.tolist()] - df_fa.index = [s_val.capitalize() for s_val in df_fa.index] - df_fa.columns.name = "Fiscal Date Ending" - print(df_fa) - - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return + + if ns_parser.n_num == 1: + pd.set_option('display.max_colwidth', -1) + else: + pd.options.display.max_colwidth = 40 + + fd = FundamentalData(key=cfg.API_KEY_ALPHAVANTAGE, output_format='pandas') + if ns_parser.b_quarter: + df_fa, d_fd_metadata = fd.get_balance_sheet_quarterly(symbol=s_ticker) + else: + df_fa, d_fd_metadata = fd.get_balance_sheet_annual(symbol=s_ticker) + + df_fa = df_fa.set_index('fiscalDateEnding') + df_fa = df_fa.head(n=ns_parser.n_num).T + df_fa = df_fa.mask(df_fa.astype(object).eq(ns_parser.n_num*['None'])).dropna() + df_fa = df_fa.mask(df_fa.astype(object).eq(ns_parser.n_num*['0'])).dropna() + df_fa = df_fa.applymap(lambda x: long_number_format(x)) + df_fa.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fa.index.tolist()] + df_fa.index = [s_val.capitalize() for s_val in df_fa.index] + df_fa.columns.name = "Fiscal Date Ending" + print(df_fa) + + print("") + # ---------------------------------------------------- CASH_FLOW ---------------------------------------------------- @@ -260,40 +245,36 @@ def cash_flow(l_args, s_ticker): parser.add_argument('-q', "--quarter", action="store_true", default=False, dest="b_quarter", help='Quarter fundamental data flag.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return - - if ns_parser.n_num == 1: - pd.set_option('display.max_colwidth', -1) - else: - pd.options.display.max_colwidth = 40 - - fd = FundamentalData(key=cfg.API_KEY_ALPHAVANTAGE, output_format='pandas') - if ns_parser.b_quarter: - df_fa, d_fd_metadata = fd.get_cash_flow_quarterly(symbol=s_ticker) - else: - df_fa, d_fd_metadata = fd.get_cash_flow_annual(symbol=s_ticker) - - df_fa = df_fa.set_index('fiscalDateEnding') - df_fa = df_fa.head(n=ns_parser.n_num).T - df_fa = df_fa.mask(df_fa.astype(object).eq(ns_parser.n_num*['None'])).dropna() - df_fa = df_fa.mask(df_fa.astype(object).eq(ns_parser.n_num*['0'])).dropna() - df_fa = df_fa.applymap(lambda x: long_number_format(x)) - df_fa.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fa.index.tolist()] - df_fa.index = [s_val.capitalize() for s_val in df_fa.index] - df_fa.columns.name = "Fiscal Date Ending" - print(df_fa) - - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return + if ns_parser.n_num == 1: + pd.set_option('display.max_colwidth', -1) + else: + pd.options.display.max_colwidth = 40 + + fd = FundamentalData(key=cfg.API_KEY_ALPHAVANTAGE, output_format='pandas') + if ns_parser.b_quarter: + df_fa, d_fd_metadata = fd.get_cash_flow_quarterly(symbol=s_ticker) + else: + df_fa, d_fd_metadata = fd.get_cash_flow_annual(symbol=s_ticker) + + df_fa = df_fa.set_index('fiscalDateEnding') + df_fa = df_fa.head(n=ns_parser.n_num).T + df_fa = df_fa.mask(df_fa.astype(object).eq(ns_parser.n_num*['None'])).dropna() + df_fa = df_fa.mask(df_fa.astype(object).eq(ns_parser.n_num*['0'])).dropna() + df_fa = df_fa.applymap(lambda x: long_number_format(x)) + df_fa.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fa.index.tolist()] + df_fa.index = [s_val.capitalize() for s_val in df_fa.index] + df_fa.columns.name = "Fiscal Date Ending" + print(df_fa) + + print("") + + # ---------------------------------------------------- EARNINGS ---------------------------------------------------- def earnings(l_args, s_ticker): @@ -304,47 +285,42 @@ def earnings(l_args, s_ticker): parser.add_argument('-q', "--quarter", action="store_true", default=False, dest="b_quarter", help='Quarter fundamental data flag.') parser.add_argument('-n', "--num", action="store", dest="n_num", type=check_positive, default=5, help='Number of latest info') - - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if ns_parser.n_num == 1: - pd.set_option('display.max_colwidth', -1) - else: - pd.options.display.max_colwidth = 40 - - # Request EARNINGS data from Alpha Vantage API - s_req = f"https://www.alphavantage.co/query?function=EARNINGS&symbol={s_ticker}&apikey={cfg.API_KEY_FINANCIALMODELINGPREP}" - result = requests.get(s_req, stream=True) - - # If the returned data was successful - if result.status_code == 200: - df_fa = json_normalize(result.json()) - if ns_parser.b_quarter: - df_fa = pd.DataFrame(df_fa['quarterlyEarnings'][0]) - df_fa = df_fa[["fiscalDateEnding", "reportedDate", "reportedEPS", "estimatedEPS", "surprise", "surprisePercentage"]] - df_fa = df_fa.rename(columns={"fiscalDateEnding":"Fiscal Date Ending", - "reportedEPS":"Reported EPS", - "estimatedEPS":"Estimated EPS", - "reportedDate":"Reported Date", - "surprise":"Surprise", - "surprisePercentage":"Surprise Percentage"}) - else: - df_fa = pd.DataFrame(df_fa['annualEarnings'][0]) - df_fa = df_fa.rename(columns={"fiscalDateEnding":"Fiscal Date Ending", - "reportedEPS":"Reported EPS"}) - - print(df_fa.head(n=ns_parser.n_num).T.to_string(header=False)) - print("") - else: - print(f"Error: {result.status_code}") - - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return + + if ns_parser.n_num == 1: + pd.set_option('display.max_colwidth', -1) + else: + pd.options.display.max_colwidth = 40 + + # Request EARNINGS data from Alpha Vantage API + s_req = f"https://www.alphavantage.co/query?function=EARNINGS&symbol={s_ticker}&apikey={cfg.API_KEY_FINANCIALMODELINGPREP}" + result = requests.get(s_req, stream=True) + + # If the returned data was successful + if result.status_code == 200: + df_fa = json_normalize(result.json()) + if ns_parser.b_quarter: + df_fa = pd.DataFrame(df_fa['quarterlyEarnings'][0]) + df_fa = df_fa[["fiscalDateEnding", "reportedDate", "reportedEPS", "estimatedEPS", "surprise", "surprisePercentage"]] + df_fa = df_fa.rename(columns={"fiscalDateEnding":"Fiscal Date Ending", + "reportedEPS":"Reported EPS", + "estimatedEPS":"Estimated EPS", + "reportedDate":"Reported Date", + "surprise":"Surprise", + "surprisePercentage":"Suprise Percentage"}) + else: + df_fa = pd.DataFrame(df_fa['annualEarnings'][0]) + df_fa = df_fa.rename(columns={"fiscalDateEnding":"Fiscal Date Ending", + "reportedEPS":"Reported EPS"}) + + print(df_fa.head(n=ns_parser.n_num).T.to_string(header=False)) + print("") + else: + print(f"Error: {result.status_code}") + + print("") diff --git a/fundamental_analysis/business_insider_api.py b/fundamental_analysis/business_insider_api.py index b9e43e25376..14f83070c8f 100644 --- a/fundamental_analysis/business_insider_api.py +++ b/fundamental_analysis/business_insider_api.py @@ -12,49 +12,43 @@ def management(l_args, s_ticker): description="""Print management team. Namely: Name, Title, Information from google and (potentially) Insider Activity page. [Source: Business Insider]""") - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return - - url_market_business_insider = f"https://markets.businessinsider.com/stocks/{s_ticker.lower()}-stock" - text_soup_market_business_insider = BeautifulSoup(requests.get(url_market_business_insider).text, "lxml") - - l_titles = list() - for s_title in text_soup_market_business_insider.findAll('td', {'class': 'table__td text-right'}): - if any(c.isalpha() for c in s_title.text.strip()) and ('USD' not in s_title.text.strip()): - l_titles.append(s_title.text.strip()) - - l_names = list() - for s_name in text_soup_market_business_insider.findAll('td', {'class': 'table__td table--allow-wrap'}): - l_names.append(s_name.text.strip()) - - df_management = pd.DataFrame({'Name': l_names[-len(l_titles):], 'Title':l_titles}, columns=['Name','Title']) - - df_management['Info'] = '-' - df_management['Insider Activity'] = '-' - df_management = df_management.set_index('Name') - - for s_name in df_management.index: - df_management.loc[s_name]['Info'] = f"http://www.google.com/search?q={s_name} {s_ticker.upper()}".replace(' ', '%20') - - s_url_base = "https://markets.businessinsider.com" - for insider in text_soup_market_business_insider.findAll('a', {'onclick':"silentTrackPI()"}): - for s_name in df_management.index: - if fuzz.token_set_ratio(s_name, insider.text.strip()) > 70: - df_management.loc[s_name]['Insider Activity'] = s_url_base + insider.attrs['href'] - - for ind in df_management.index: - s_name = f"{ind}{(max([len(x) for x in df_management.index])-len(ind))*' '}" - s_title = f"{df_management['Title'][ind]}{(max([len(x) for x in df_management['Title']])-len(df_management['Title'][ind]))*' '}" - s_management = f"""{s_name} {s_title} {df_management['Info'][ind]}""" - print(s_management) - if df_management['Insider Activity'][ind] not in '-': - print(f"{df_management['Insider Activity'][ind]}") - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return + + url_market_business_insider = f"https://markets.businessinsider.com/stocks/{s_ticker.lower()}-stock" + text_soup_market_business_insider = BeautifulSoup(requests.get(url_market_business_insider).text, "lxml") + + l_titles = list() + for s_title in text_soup_market_business_insider.findAll('td', {'class': 'table__td text-right'}): + if any(c.isalpha() for c in s_title.text.strip()) and ('USD' not in s_title.text.strip()): + l_titles.append(s_title.text.strip()) + + l_names = list() + for s_name in text_soup_market_business_insider.findAll('td', {'class': 'table__td table--allow-wrap'}): + l_names.append(s_name.text.strip()) + + df_management = pd.DataFrame({'Name': l_names[-len(l_titles):], 'Title':l_titles}, columns=['Name','Title']) + + df_management['Info'] = '-' + df_management['Insider Activity'] = '-' + df_management = df_management.set_index('Name') + + for s_name in df_management.index: + df_management.loc[s_name]['Info'] = f"http://www.google.com/search?q={s_name} {s_ticker.upper()}".replace(' ', '%20') + + s_url_base = "https://markets.businessinsider.com" + for insider in text_soup_market_business_insider.findAll('a', {'onclick':"silentTrackPI()"}): + for s_name in df_management.index: + if fuzz.token_set_ratio(s_name, insider.text.strip()) > 70: + df_management.loc[s_name]['Insider Activity'] = s_url_base + insider.attrs['href'] + + for ind in df_management.index: + s_name = f"{ind}{(max([len(x) for x in df_management.index])-len(ind))*' '}" + s_title = f"{df_management['Title'][ind]}{(max([len(x) for x in df_management['Title']])-len(df_management['Title'][ind]))*' '}" + s_management = f"""{s_name} {s_title} {df_management['Info'][ind]}""" + print(s_management) + if df_management['Insider Activity'][ind] not in '-': + print(f"{df_management['Insider Activity'][ind]}") diff --git a/fundamental_analysis/fa_menu.py b/fundamental_analysis/fa_menu.py index 5eb1f18a78e..6631712d1e2 100644 --- a/fundamental_analysis/fa_menu.py +++ b/fundamental_analysis/fa_menu.py @@ -69,23 +69,19 @@ def info(l_args, s_ticker): description="""Provides information about main key metrics. Namely: EBITDA, EPS, P/E, PEG, FCF, P/B, ROE, DPR, P/S, Dividend Yield Ratio, D/E, and Beta.""") - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}") - filepath = 'fundamental_analysis/key_metrics_explained.txt' - with open(filepath) as fp: + filepath = 'fundamental_analysis/key_metrics_explained.txt' + with open(filepath) as fp: + line = fp.readline() + while line: + print("{}".format(line.strip())) line = fp.readline() - while line: - print("{}".format(line.strip())) - line = fp.readline() - print("") + print("") - except: - print("ERROR!\n") - return # ---------------------------------------------------- MENU ---------------------------------------------------- diff --git a/fundamental_analysis/financial_modeling_prep_api.py b/fundamental_analysis/financial_modeling_prep_api.py index 5ea3d1b92c8..dbfcba6e398 100644 --- a/fundamental_analysis/financial_modeling_prep_api.py +++ b/fundamental_analysis/financial_modeling_prep_api.py @@ -1,3 +1,4 @@ +import argparse import datetime import FundamentalAnalysis as fa # Financial Modeling Prep @@ -18,27 +19,22 @@ def profile(l_args, s_ticker): Default image, Description, Exchange, Exchange short name, Full time employees, Image, Industry, Ipo date, Isin, Last div, Mkt cap, Phone, Price, Range, Sector, State, Symbol, Vol avg, Website, Zip. [Source: Financial Modeling Prep]""") - - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - df_fa = fa.profile(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP) - df_fa.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fa.index.tolist()] - df_fa.index = [s_val.capitalize() for s_val in df_fa.index] - print(df_fa.drop(index=['Description', 'Image']).to_string(header=False)) - print(f"\nImage: {df_fa.loc['Image'][0]}") - print(f"\nDescription: {df_fa.loc['Description'][0]}") - - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return - + + df_fa = fa.profile(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP) + df_fa.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fa.index.tolist()] + df_fa.index = [s_val.capitalize() for s_val in df_fa.index] + print(df_fa.drop(index=['Description', 'Image']).to_string(header=False)) + print(f"\nImage: {df_fa.loc['Image'][0]}") + print(f"\nDescription: {df_fa.loc['Description'][0]}") + + print("") + # ---------------------------------------------------- QUOTE ---------------------------------------------------- def quote(l_args, s_ticker): @@ -49,30 +45,24 @@ def quote(l_args, s_ticker): Day high, Day low, Earnings announcement, Eps, Exchange, Market cap, Name, Open, Pe, Previous close, Price, Price avg200, Price avg50, Shares outstanding, Symbol, Timestamp, Volume, Year high, and Year low. [Source: Financial Modeling Prep]""") - - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return - - df_fa = fa.quote(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP) - df_fa.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fa.index.tolist()] - df_fa.index = [s_val.capitalize() for s_val in df_fa.index] - df_fa.loc['Market cap'][0] = long_number_format(df_fa.loc['Market cap'][0]) - df_fa.loc['Shares outstanding'][0] = long_number_format(df_fa.loc['Shares outstanding'][0]) - df_fa.loc['Volume'][0] = long_number_format(df_fa.loc['Volume'][0]) - earning_announcment = datetime.datetime.strptime(df_fa.loc['Earnings announcement'][0][0:19],"%Y-%m-%dT%H:%M:%S") - df_fa.loc['Earnings announcement'][0] = f"{earning_announcment.date()} {earning_announcment.time()}" - print(df_fa.to_string(header=False)) - - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return - + + df_fa = fa.quote(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP) + df_fa.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fa.index.tolist()] + df_fa.index = [s_val.capitalize() for s_val in df_fa.index] + df_fa.loc['Market cap'][0] = long_number_format(df_fa.loc['Market cap'][0]) + df_fa.loc['Shares outstanding'][0] = long_number_format(df_fa.loc['Shares outstanding'][0]) + df_fa.loc['Volume'][0] = long_number_format(df_fa.loc['Volume'][0]) + earning_announcment = datetime.datetime.strptime(df_fa.loc['Earnings announcement'][0][0:19],"%Y-%m-%dT%H:%M:%S") + df_fa.loc['Earnings announcement'][0] = f"{earning_announcment.date()} {earning_announcment.time()}" + print(df_fa.to_string(header=False)) + + print("") + # ---------------------------------------------------- ENTERPRISE ---------------------------------------------------- def enterprise(l_args, s_ticker): @@ -86,36 +76,32 @@ def enterprise(l_args, s_ticker): help='Number of latest years/quarters.') parser.add_argument('-q', "--quarter", action="store_true", default=False, dest="b_quarter", help='Quarter fundamental data flag.') - - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if ns_parser.n_num == 1: - pd.set_option('display.max_colwidth', -1) - else: - pd.options.display.max_colwidth = 40 - - if ns_parser.b_quarter: - df_fa = fa.enterprise(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period='quarter') - else: - df_fa = fa.enterprise(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP) - - df_fa = df_fa.iloc[:, 0:ns_parser.n_num] - df_fa = df_fa.applymap(lambda x: long_number_format(x)) - df_fa.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fa.index.tolist()] - df_fa.index = [s_val.capitalize() for s_val in df_fa.index] - print(df_fa) - - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return + if ns_parser.n_num == 1: + pd.set_option('display.max_colwidth', -1) + else: + pd.options.display.max_colwidth = 40 + + if ns_parser.b_quarter: + df_fa = fa.enterprise(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period='quarter') + else: + df_fa = fa.enterprise(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP) + + df_fa = df_fa.iloc[:, 0:ns_parser.n_num] + df_fa = df_fa.applymap(lambda x: long_number_format(x)) + df_fa.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fa.index.tolist()] + df_fa.index = [s_val.capitalize() for s_val in df_fa.index] + print(df_fa) + + print("") + + # ------------------------------------------ DISCOUNTED CASH FLOW ------------------------------------------------------ def discounted_cash_flow(l_args, s_ticker): @@ -127,37 +113,33 @@ def discounted_cash_flow(l_args, s_ticker): help='Number of latest years/quarters.') parser.add_argument('-q', "--quarter", action="store_true", default=False, dest="b_quarter", help='Quarter fundamental data flag.') - - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if ns_parser.n_num == 1: - pd.set_option('display.max_colwidth', -1) - else: - pd.options.display.max_colwidth = 40 - - if ns_parser.b_quarter: - df_fa = fa.discounted_cash_flow(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period='quarter') - else: - df_fa = fa.discounted_cash_flow(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP) - - df_fa = df_fa.iloc[:, 0:ns_parser.n_num] - df_fa = df_fa.applymap(lambda x: long_number_format(x)) - df_fa.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fa.index.tolist()] - df_fa.index = [s_val.capitalize() for s_val in df_fa.index] - df_fa = df_fa.rename(index={"D c f": "DCF"}) - print(df_fa) - - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return + if ns_parser.n_num == 1: + pd.set_option('display.max_colwidth', -1) + else: + pd.options.display.max_colwidth = 40 + + if ns_parser.b_quarter: + df_fa = fa.discounted_cash_flow(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period='quarter') + else: + df_fa = fa.discounted_cash_flow(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP) + + df_fa = df_fa.iloc[:, 0:ns_parser.n_num] + df_fa = df_fa.applymap(lambda x: long_number_format(x)) + df_fa.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fa.index.tolist()] + df_fa.index = [s_val.capitalize() for s_val in df_fa.index] + df_fa = df_fa.rename(index={"D c f": "DCF"}) + print(df_fa) + + print("") + + # ---------------------------------------------------- INCOME_STATEMENT ---------------------------------------------------- def income_statement(l_args, s_ticker): @@ -177,43 +159,39 @@ def income_statement(l_args, s_ticker): parser.add_argument('-q', "--quarter", action="store_true", default=False, dest="b_quarter", help='Quarter fundamental data flag.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return - - if ns_parser.n_num == 1: - pd.set_option('display.max_colwidth', -1) - else: - pd.options.display.max_colwidth = 40 - - if ns_parser.b_quarter: - df_fa = fa.income_statement(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period='quarter') - else: - df_fa = fa.income_statement(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP) - - df_fa = df_fa.iloc[:, 0:ns_parser.n_num] - df_fa = df_fa.mask(df_fa.astype(object).eq(ns_parser.n_num*['None'])).dropna() - df_fa = df_fa.mask(df_fa.astype(object).eq(ns_parser.n_num*['0'])).dropna() - df_fa = df_fa.applymap(lambda x: long_number_format(x)) - df_fa.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fa.index.tolist()] - df_fa.index = [s_val.capitalize() for s_val in df_fa.index] - df_fa.columns.name = "Fiscal Date Ending" - print(df_fa.drop(index=['Final link', 'Link']).to_string()) - - pd.set_option('display.max_colwidth', -1) - print("") - print(df_fa.loc['Final link'].to_frame().to_string()) - print("") - print(df_fa.loc['Link'].to_frame().to_string()) - - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return + + if ns_parser.n_num == 1: + pd.set_option('display.max_colwidth', -1) + else: + pd.options.display.max_colwidth = 40 + + if ns_parser.b_quarter: + df_fa = fa.income_statement(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period='quarter') + else: + df_fa = fa.income_statement(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP) + + df_fa = df_fa.iloc[:, 0:ns_parser.n_num] + df_fa = df_fa.mask(df_fa.astype(object).eq(ns_parser.n_num*['None'])).dropna() + df_fa = df_fa.mask(df_fa.astype(object).eq(ns_parser.n_num*['0'])).dropna() + df_fa = df_fa.applymap(lambda x: long_number_format(x)) + df_fa.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fa.index.tolist()] + df_fa.index = [s_val.capitalize() for s_val in df_fa.index] + df_fa.columns.name = "Fiscal Date Ending" + print(df_fa.drop(index=['Final link', 'Link']).to_string()) + + pd.set_option('display.max_colwidth', -1) + print("") + print(df_fa.loc['Final link'].to_frame().to_string()) + print("") + print(df_fa.loc['Link'].to_frame().to_string()) + + print("") + # ---------------------------------------------------- BALANCE_SHEET ---------------------------------------------------- @@ -239,43 +217,39 @@ def balance_sheet(l_args, s_ticker): parser.add_argument('-q', "--quarter", action="store_true", default=False, dest="b_quarter", help='Quarter fundamental data flag.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return - - if ns_parser.n_num == 1: - pd.set_option('display.max_colwidth', -1) - else: - pd.options.display.max_colwidth = 40 - - if ns_parser.b_quarter: - df_fa = fa.balance_sheet_statement(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period='quarter') - else: - df_fa = fa.balance_sheet_statement(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP) - - df_fa = df_fa.iloc[:, 0:ns_parser.n_num] - df_fa = df_fa.mask(df_fa.astype(object).eq(ns_parser.n_num*['None'])).dropna() - df_fa = df_fa.mask(df_fa.astype(object).eq(ns_parser.n_num*['0'])).dropna() - df_fa = df_fa.applymap(lambda x: long_number_format(x)) - df_fa.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fa.index.tolist()] - df_fa.index = [s_val.capitalize() for s_val in df_fa.index] - df_fa.columns.name = "Fiscal Date Ending" - print(df_fa.drop(index=['Final link', 'Link']).to_string()) - - pd.set_option('display.max_colwidth', -1) - print("") - print(df_fa.loc['Final link'].to_frame().to_string()) - print("") - print(df_fa.loc['Link'].to_frame().to_string()) - - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return + + if ns_parser.n_num == 1: + pd.set_option('display.max_colwidth', -1) + else: + pd.options.display.max_colwidth = 40 + + if ns_parser.b_quarter: + df_fa = fa.balance_sheet_statement(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period='quarter') + else: + df_fa = fa.balance_sheet_statement(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP) + + df_fa = df_fa.iloc[:, 0:ns_parser.n_num] + df_fa = df_fa.mask(df_fa.astype(object).eq(ns_parser.n_num*['None'])).dropna() + df_fa = df_fa.mask(df_fa.astype(object).eq(ns_parser.n_num*['0'])).dropna() + df_fa = df_fa.applymap(lambda x: long_number_format(x)) + df_fa.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fa.index.tolist()] + df_fa.index = [s_val.capitalize() for s_val in df_fa.index] + df_fa.columns.name = "Fiscal Date Ending" + print(df_fa.drop(index=['Final link', 'Link']).to_string()) + + pd.set_option('display.max_colwidth', -1) + print("") + print(df_fa.loc['Final link'].to_frame().to_string()) + print("") + print(df_fa.loc['Link'].to_frame().to_string()) + + print("") + # ---------------------------------------------------- CASH_FLOW ---------------------------------------------------- @@ -298,44 +272,39 @@ def cash_flow(l_args, s_ticker): parser.add_argument('-q', "--quarter", action="store_true", default=False, dest="b_quarter", help='Quarter fundamental data flag.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return - - if ns_parser.n_num == 1: - pd.set_option('display.max_colwidth', -1) - else: - pd.options.display.max_colwidth = 40 - - if ns_parser.b_quarter: - df_fa = fa.cash_flow_statement(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period='quarter') - else: - df_fa = fa.cash_flow_statement(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP) - - df_fa = df_fa.iloc[:, 0:ns_parser.n_num] - df_fa = df_fa.mask(df_fa.astype(object).eq(ns_parser.n_num*['None'])).dropna() - df_fa = df_fa.mask(df_fa.astype(object).eq(ns_parser.n_num*['0'])).dropna() - df_fa = df_fa.applymap(lambda x: long_number_format(x)) - df_fa.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fa.index.tolist()] - df_fa.index = [s_val.capitalize() for s_val in df_fa.index] - df_fa.columns.name = "Fiscal Date Ending" - print(df_fa.drop(index=['Final link', 'Link']).to_string()) - - pd.set_option('display.max_colwidth', -1) - print("") - print(df_fa.loc['Final link'].to_frame().to_string()) - print("") - print(df_fa.loc['Link'].to_frame().to_string()) - - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return - + + if ns_parser.n_num == 1: + pd.set_option('display.max_colwidth', -1) + else: + pd.options.display.max_colwidth = 40 + + if ns_parser.b_quarter: + df_fa = fa.cash_flow_statement(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period='quarter') + else: + df_fa = fa.cash_flow_statement(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP) + + df_fa = df_fa.iloc[:, 0:ns_parser.n_num] + df_fa = df_fa.mask(df_fa.astype(object).eq(ns_parser.n_num*['None'])).dropna() + df_fa = df_fa.mask(df_fa.astype(object).eq(ns_parser.n_num*['0'])).dropna() + df_fa = df_fa.applymap(lambda x: long_number_format(x)) + df_fa.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fa.index.tolist()] + df_fa.index = [s_val.capitalize() for s_val in df_fa.index] + df_fa.columns.name = "Fiscal Date Ending" + print(df_fa.drop(index=['Final link', 'Link']).to_string()) + + pd.set_option('display.max_colwidth', -1) + print("") + print(df_fa.loc['Final link'].to_frame().to_string()) + print("") + print(df_fa.loc['Link'].to_frame().to_string()) + + print("") + # ---------------------------------------------------- KEY_METRICS ---------------------------------------------------- def key_metrics(l_args, s_ticker): @@ -362,39 +331,35 @@ def key_metrics(l_args, s_ticker): parser.add_argument('-q', "--quarter", action="store_true", default=False, dest="b_quarter", help='Quarter fundamental data flag.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return - - if ns_parser.n_num == 1: - pd.set_option('display.max_colwidth', -1) - else: - pd.options.display.max_colwidth = 50 - - if ns_parser.b_quarter: - df_fa = fa.key_metrics(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period='quarter') - else: - df_fa = fa.key_metrics(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP) - - df_fa = df_fa.iloc[:, 0:ns_parser.n_num] - df_fa = df_fa.mask(df_fa.astype(object).eq(ns_parser.n_num*['None'])).dropna() - df_fa = df_fa.mask(df_fa.astype(object).eq(ns_parser.n_num*['0'])).dropna() - df_fa = df_fa.applymap(lambda x: long_number_format(x)) - df_fa.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fa.index.tolist()] - df_fa.index = [s_val.capitalize() for s_val in df_fa.index] - df_fa.columns.name = "Fiscal Date Ending" - df_fa = df_fa.rename(index={"Enterprise value over e b i t d a": "Enterprise value over EBITDA"}) - df_fa = df_fa.rename(index={"Net debt to e b i t d a": "Net debt to EBITDA"}) - print(df_fa) - - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return + + if ns_parser.n_num == 1: + pd.set_option('display.max_colwidth', -1) + else: + pd.options.display.max_colwidth = 50 + + if ns_parser.b_quarter: + df_fa = fa.key_metrics(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period='quarter') + else: + df_fa = fa.key_metrics(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP) + + df_fa = df_fa.iloc[:, 0:ns_parser.n_num] + df_fa = df_fa.mask(df_fa.astype(object).eq(ns_parser.n_num*['None'])).dropna() + df_fa = df_fa.mask(df_fa.astype(object).eq(ns_parser.n_num*['0'])).dropna() + df_fa = df_fa.applymap(lambda x: long_number_format(x)) + df_fa.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fa.index.tolist()] + df_fa.index = [s_val.capitalize() for s_val in df_fa.index] + df_fa.columns.name = "Fiscal Date Ending" + df_fa = df_fa.rename(index={"Enterprise value over e b i t d a": "Enterprise value over EBITDA"}) + df_fa = df_fa.rename(index={"Net debt to e b i t d a": "Net debt to EBITDA"}) + print(df_fa) + + print("") + # ---------------------------------------------------- FINANCIAL_RATIOS ---------------------------------------------------- @@ -423,39 +388,34 @@ def financial_ratios(l_args, s_ticker): parser.add_argument('-q', "--quarter", action="store_true", default=False, dest="b_quarter", help='Quarter fundamental data flag.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return - - if ns_parser.n_num == 1: - pd.set_option('display.max_colwidth', -1) - else: - pd.options.display.max_colwidth = 40 - - if ns_parser.b_quarter: - df_fa = fa.financial_ratios(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period='quarter') - else: - df_fa = fa.financial_ratios(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP) - - df_fa = df_fa.iloc[:, 0:ns_parser.n_num] - df_fa = df_fa.mask(df_fa.astype(object).eq(ns_parser.n_num*['None'])).dropna() - df_fa = df_fa.mask(df_fa.astype(object).eq(ns_parser.n_num*['0'])).dropna() - df_fa = df_fa.applymap(lambda x: long_number_format(x)) - df_fa.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fa.index.tolist()] - df_fa.index = [s_val.capitalize() for s_val in df_fa.index] - df_fa.columns.name = "Fiscal Date Ending" - df_fa = df_fa.rename(index={"Net income per e b t": "Net income per EBT"}) - print(df_fa) - - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return + if ns_parser.n_num == 1: + pd.set_option('display.max_colwidth', -1) + else: + pd.options.display.max_colwidth = 40 + + if ns_parser.b_quarter: + df_fa = fa.financial_ratios(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period='quarter') + else: + df_fa = fa.financial_ratios(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP) + + df_fa = df_fa.iloc[:, 0:ns_parser.n_num] + df_fa = df_fa.mask(df_fa.astype(object).eq(ns_parser.n_num*['None'])).dropna() + df_fa = df_fa.mask(df_fa.astype(object).eq(ns_parser.n_num*['0'])).dropna() + df_fa = df_fa.applymap(lambda x: long_number_format(x)) + df_fa.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fa.index.tolist()] + df_fa.index = [s_val.capitalize() for s_val in df_fa.index] + df_fa.columns.name = "Fiscal Date Ending" + df_fa = df_fa.rename(index={"Net income per e b t": "Net income per EBT"}) + print(df_fa) + + print("") + # ---------------------------------------------------- FINANCIAL_STATEMENT_GROWTH ---------------------------------------------------- def financial_statement_growth(l_args, s_ticker): @@ -480,38 +440,29 @@ def financial_statement_growth(l_args, s_ticker): parser.add_argument('-q', "--quarter", action="store_true", default=False, dest="b_quarter", help='Quarter fundamental data flag.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return - - if ns_parser.n_num == 1: - pd.set_option('display.max_colwidth', -1) - else: - pd.options.display.max_colwidth = 50 - - if ns_parser.b_quarter: - df_fa = fa.financial_statement_growth(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period='quarter') - else: - df_fa = fa.financial_statement_growth(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP) - - df_fa = df_fa.iloc[:, 0:ns_parser.n_num] - df_fa = df_fa.mask(df_fa.astype(object).eq(ns_parser.n_num*['None'])).dropna() - df_fa = df_fa.mask(df_fa.astype(object).eq(ns_parser.n_num*['0'])).dropna() - df_fa = df_fa.applymap(lambda x: long_number_format(x)) - df_fa.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fa.index.tolist()] - df_fa.index = [s_val.capitalize() for s_val in df_fa.index] - df_fa.columns.name = "Fiscal Date Ending" - print(df_fa) - - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return -<<<<<<< HEAD - -======= ->>>>>>> 63fc66c... Clean up imports + + if ns_parser.n_num == 1: + pd.set_option('display.max_colwidth', -1) + else: + pd.options.display.max_colwidth = 50 + + if ns_parser.b_quarter: + df_fa = fa.financial_statement_growth(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period='quarter') + else: + df_fa = fa.financial_statement_growth(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP) + + df_fa = df_fa.iloc[:, 0:ns_parser.n_num] + df_fa = df_fa.mask(df_fa.astype(object).eq(ns_parser.n_num*['None'])).dropna() + df_fa = df_fa.mask(df_fa.astype(object).eq(ns_parser.n_num*['0'])).dropna() + df_fa = df_fa.applymap(lambda x: long_number_format(x)) + df_fa.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_fa.index.tolist()] + df_fa.index = [s_val.capitalize() for s_val in df_fa.index] + df_fa.columns.name = "Fiscal Date Ending" + print(df_fa) + + print("") diff --git a/fundamental_analysis/finviz_api.py b/fundamental_analysis/finviz_api.py index 10110ba25e9..c806da7651c 100644 --- a/fundamental_analysis/finviz_api.py +++ b/fundamental_analysis/finviz_api.py @@ -6,7 +6,7 @@ import pandas as pd # ---------------------------------------------------- SCREENER ---------------------------------------------------- def screener(l_args, s_ticker): - parser = argparse.ArgumentParser(prog='screener', + parser = argparse.ArgumentParser(prog='screener', description="""Print several metrics about the company. The following fields are expected: Company, Sector, Industry, Country, Index, P/E, EPS (ttm), Insider Own, Shs Outstand, Perf Week, Market Cap, Forward P/E, EPS next Y, Insider Trans, @@ -18,21 +18,16 @@ def screener(l_args, s_ticker): Debt/Eq, EPS Q/Q, Profit Margin, Rel Volume, Prev Close, Shortable, LT Debt/Eq, Earnings, Payout, Avg Volume, Price, Recom, SMA20, SMA50, SMA200, Volume, Change. [Source: Finviz]""") - - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - d_finviz_stock = finviz.get_stock(s_ticker) - df_fa = pd.DataFrame.from_dict(d_finviz_stock, orient='index', columns=['Values']) - df_fa = df_fa[df_fa.Values != '-'] - print(df_fa.to_string(header=False)) - - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return + + d_finviz_stock = finviz.get_stock(s_ticker) + df_fa = pd.DataFrame.from_dict(d_finviz_stock, orient='index', columns=['Values']) + df_fa = df_fa[df_fa.Values != '-'] + print(df_fa.to_string(header=False)) + + print("") diff --git a/fundamental_analysis/market_watch_api.py b/fundamental_analysis/market_watch_api.py index d4beebea557..d9f33d537e5 100644 --- a/fundamental_analysis/market_watch_api.py +++ b/fundamental_analysis/market_watch_api.py @@ -27,43 +27,38 @@ def income(l_args, s_ticker): parser.add_argument('-q', "--quarter", action="store_true", default=False, dest="b_quarter", help='Quarter fundamental data flag.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return - - if ns_parser.b_quarter: - url_financials = f"https://www.marketwatch.com/investing/stock/{s_ticker}/financials/income/quarter" - else: - url_financials = f"https://www.marketwatch.com/investing/stock/{s_ticker}/financials/income" - - text_soup_financials = BeautifulSoup(requests.get(url_financials).text, "lxml") - - # Define financials columns - a_financials_header = list() - for financials_header in text_soup_financials.findAll('th', {'class': 'overflow__heading'}): - a_financials_header.append(financials_header.text.strip('\n').split('\n')[0]) - df_financials = pd.DataFrame(columns=a_financials_header[0:-1]) - - # Add financials values - soup_financials = text_soup_financials.findAll('tr', {'class': 'table__row '}) - soup_financials += text_soup_financials.findAll('tr', {'class': 'table__row is-highlighted'}) - for financials_info in soup_financials: - a_financials_info = financials_info.text.split('\n') - l_financials = [a_financials_info[2]] - l_financials.extend(a_financials_info[5:-2]) - # Append data values to financials - df_financials.loc[len(df_financials.index)] = l_financials - - print(df_financials.to_string(index=False)) - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return + if ns_parser.b_quarter: + url_financials = f"https://www.marketwatch.com/investing/stock/{s_ticker}/financials/income/quarter" + else: + url_financials = f"https://www.marketwatch.com/investing/stock/{s_ticker}/financials/income" + + text_soup_financials = BeautifulSoup(requests.get(url_financials).text, "lxml") + + # Define financials columns + a_financials_header = list() + for financials_header in text_soup_financials.findAll('th', {'class': 'overflow__heading'}): + a_financials_header.append(financials_header.text.strip('\n').split('\n')[0]) + df_financials = pd.DataFrame(columns=a_financials_header[0:-1]) + + # Add financials values + soup_financials = text_soup_financials.findAll('tr', {'class': 'table__row '}) + soup_financials += text_soup_financials.findAll('tr', {'class': 'table__row is-highlighted'}) + for financials_info in soup_financials: + a_financials_info = financials_info.text.split('\n') + l_financials = [a_financials_info[2]] + l_financials.extend(a_financials_info[5:-2]) + # Append data values to financials + df_financials.loc[len(df_financials.index)] = l_financials + + print(df_financials.to_string(index=False)) + print("") + # ---------------------------------------------------- ASSETS ---------------------------------------------------- def assets(l_args, s_ticker): @@ -82,45 +77,40 @@ def assets(l_args, s_ticker): parser.add_argument('-q', "--quarter", action="store_true", default=False, dest="b_quarter", help='Quarter fundamental data flag.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}") - if ns_parser.b_quarter: - url_financials = f"https://www.marketwatch.com/investing/stock/{s_ticker}/financials/balance-sheet/quarter" - else: - url_financials = f"https://www.marketwatch.com/investing/stock/{s_ticker}/financials/balance-sheet" - - text_soup_financials = BeautifulSoup(requests.get(url_financials).text, "lxml") + if ns_parser.b_quarter: + url_financials = f"https://www.marketwatch.com/investing/stock/{s_ticker}/financials/balance-sheet/quarter" + else: + url_financials = f"https://www.marketwatch.com/investing/stock/{s_ticker}/financials/balance-sheet" - # Define financials columns - a_financials_header = list() - for financials_header in text_soup_financials.findAll('th', {'class': 'overflow__heading'}): - a_financials_header.append(financials_header.text.strip('\n').split('\n')[0]) - s_header_end_trend = ("5-year trend", "5- qtr trend")[ns_parser.b_quarter] - df_financials = pd.DataFrame(columns=a_financials_header[0:a_financials_header.index(s_header_end_trend)]) + text_soup_financials = BeautifulSoup(requests.get(url_financials).text, "lxml") - # Add financials values - soup_financials = text_soup_financials.findAll('tr', {'class': 'table__row '}) - soup_financials += text_soup_financials.findAll('tr', {'class': 'table__row is-highlighted'}) - for financials_info in soup_financials: - a_financials_info = financials_info.text.split('\n') - l_financials = [a_financials_info[2]] - l_financials.extend(a_financials_info[5:-2]) - # Append data values to financials - df_financials.loc[len(df_financials.index)] = l_financials + # Define financials columns + a_financials_header = list() + for financials_header in text_soup_financials.findAll('th', {'class': 'overflow__heading'}): + a_financials_header.append(financials_header.text.strip('\n').split('\n')[0]) + s_header_end_trend = ("5-year trend", "5- qtr trend")[ns_parser.b_quarter] + df_financials = pd.DataFrame(columns=a_financials_header[0:a_financials_header.index(s_header_end_trend)]) - # Set item name as index - df_financials = df_financials.set_index('Item') + # Add financials values + soup_financials = text_soup_financials.findAll('tr', {'class': 'table__row '}) + soup_financials += text_soup_financials.findAll('tr', {'class': 'table__row is-highlighted'}) + for financials_info in soup_financials: + a_financials_info = financials_info.text.split('\n') + l_financials = [a_financials_info[2]] + l_financials.extend(a_financials_info[5:-2]) + # Append data values to financials + df_financials.loc[len(df_financials.index)] = l_financials - print(df_financials.iloc[:33].to_string()) - print("") + # Set item name as index + df_financials = df_financials.set_index('Item') - except: - print("") - return + print(df_financials.iloc[:33].to_string()) + print("") # ---------------------------------------------------- LIABILITIES ---------------------------------------------------- @@ -143,47 +133,43 @@ def liabilities(l_args, s_ticker): parser.add_argument('-q', "--quarter", action="store_true", default=False, dest="b_quarter", help='Quarter fundamental data flag.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return - - if ns_parser.b_quarter: - url_financials = f"https://www.marketwatch.com/investing/stock/{s_ticker}/financials/balance-sheet/quarter" - else: - url_financials = f"https://www.marketwatch.com/investing/stock/{s_ticker}/financials/balance-sheet" - - text_soup_financials = BeautifulSoup(requests.get(url_financials).text, "lxml") - - # Define financials columns - a_financials_header = list() - for financials_header in text_soup_financials.findAll('th', {'class': 'overflow__heading'}): - a_financials_header.append(financials_header.text.strip('\n').split('\n')[0]) - s_header_end_trend = ("5-year trend", "5- qtr trend")[ns_parser.b_quarter] - df_financials = pd.DataFrame(columns=a_financials_header[0:a_financials_header.index(s_header_end_trend)]) - - # Add financials values - soup_financials = text_soup_financials.findAll('tr', {'class': 'table__row '}) - soup_financials += text_soup_financials.findAll('tr', {'class': 'table__row is-highlighted'}) - for financials_info in soup_financials: - a_financials_info = financials_info.text.split('\n') - l_financials = [a_financials_info[2]] - l_financials.extend(a_financials_info[5:-2]) - # Append data values to financials - df_financials.loc[len(df_financials.index)] = l_financials - - # Set item name as index - df_financials = df_financials.set_index('Item') - - print(df_financials.iloc[34:].to_string()) - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return + if ns_parser.b_quarter: + url_financials = f"https://www.marketwatch.com/investing/stock/{s_ticker}/financials/balance-sheet/quarter" + else: + url_financials = f"https://www.marketwatch.com/investing/stock/{s_ticker}/financials/balance-sheet" + + text_soup_financials = BeautifulSoup(requests.get(url_financials).text, "lxml") + + # Define financials columns + a_financials_header = list() + for financials_header in text_soup_financials.findAll('th', {'class': 'overflow__heading'}): + a_financials_header.append(financials_header.text.strip('\n').split('\n')[0]) + s_header_end_trend = ("5-year trend", "5- qtr trend")[ns_parser.b_quarter] + df_financials = pd.DataFrame(columns=a_financials_header[0:a_financials_header.index(s_header_end_trend)]) + + # Add financials values + soup_financials = text_soup_financials.findAll('tr', {'class': 'table__row '}) + soup_financials += text_soup_financials.findAll('tr', {'class': 'table__row is-highlighted'}) + for financials_info in soup_financials: + a_financials_info = financials_info.text.split('\n') + l_financials = [a_financials_info[2]] + l_financials.extend(a_financials_info[5:-2]) + # Append data values to financials + df_financials.loc[len(df_financials.index)] = l_financials + + # Set item name as index + df_financials = df_financials.set_index('Item') + + print(df_financials.iloc[34:].to_string()) + print("") + + # ---------------------------------------------------- OPERATING ---------------------------------------------------- def operating(l_args, s_ticker): @@ -197,53 +183,49 @@ def operating(l_args, s_ticker): parser.add_argument('-q', "--quarter", action="store_true", default=False, dest="b_quarter", help='Quarter fundamental data flag.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return - - - if ns_parser.b_quarter: - url_financials = f"https://www.marketwatch.com/investing/stock/{s_ticker}/financials/cash-flow/quarter" - else: - url_financials = f"https://www.marketwatch.com/investing/stock/{s_ticker}/financials/cash-flow" - - text_soup_financials = BeautifulSoup(requests.get(url_financials).text,"lxml") - - # Define financials columns - a_financials_header = list() - for financials_header in text_soup_financials.findAll('th', {'class': 'overflow__heading'}): - a_financials_header.append(financials_header.text.strip('\n').split('\n')[0]) - - s_header_end_trend = ("5-year trend", "5- qtr trend")[ns_parser.b_quarter] - df_financials = pd.DataFrame(columns=a_financials_header[0:a_financials_header.index(s_header_end_trend)]) - - # Add financials values - soup_financials = text_soup_financials.findAll('tr', {'class': 'table__row '}) - soup_financials += text_soup_financials.findAll('tr', {'class': 'table__row is-highlighted'}) - for financials_info in soup_financials: - a_financials_info = financials_info.text.split('\n') - l_financials = [a_financials_info[2]] - l_financials.extend(a_financials_info[5:-2]) - n_vals_to_add = len(df_financials.columns)-len(l_financials) - if n_vals_to_add > 0: - l_financials.append(n_vals_to_add * ' ') - # Append data values to financials - df_financials.loc[len(df_financials.index)] = l_financials - - # Set item name as index - df_financials = df_financials.set_index('Item') - - print(df_financials.iloc[:16].to_string()) - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return + if ns_parser.b_quarter: + url_financials = f"https://www.marketwatch.com/investing/stock/{s_ticker}/financials/cash-flow/quarter" + else: + url_financials = f"https://www.marketwatch.com/investing/stock/{s_ticker}/financials/cash-flow" + + text_soup_financials = BeautifulSoup(requests.get(url_financials).text,"lxml") + + # Define financials columns + a_financials_header = list() + for financials_header in text_soup_financials.findAll('th', {'class': 'overflow__heading'}): + a_financials_header.append(financials_header.text.strip('\n').split('\n')[0]) + + s_header_end_trend = ("5-year trend", "5- qtr trend")[ns_parser.b_quarter] + df_financials = pd.DataFrame(columns=a_financials_header[0:a_financials_header.index(s_header_end_trend)]) + + # Add financials values + soup_financials = text_soup_financials.findAll('tr', {'class': 'table__row '}) + soup_financials += text_soup_financials.findAll('tr', {'class': 'table__row is-highlighted'}) + for financials_info in soup_financials: + a_financials_info = financials_info.text.split('\n') + l_financials = [a_financials_info[2]] + l_financials.extend(a_financials_info[5:-2]) + n_vals_to_add = len(df_financials.columns)-len(l_financials) + if n_vals_to_add > 0: + l_financials.append(n_vals_to_add * ' ') + # Append data values to financials + df_financials.loc[len(df_financials.index)] = l_financials + + # Set item name as index + df_financials = df_financials.set_index('Item') + + print(df_financials.iloc[:16].to_string()) + print("") + + + # ---------------------------------------------------- INVESTING ---------------------------------------------------- def investing(l_args, s_ticker): parser = argparse.ArgumentParser(prog='investing', @@ -256,51 +238,47 @@ def investing(l_args, s_ticker): parser.add_argument('-q', "--quarter", action="store_true", default=False, dest="b_quarter", help='Quarter fundamental data flag.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return - - if ns_parser.b_quarter: - url_financials = f"https://www.marketwatch.com/investing/stock/{s_ticker}/financials/cash-flow/quarter" - else: - url_financials = f"https://www.marketwatch.com/investing/stock/{s_ticker}/financials/cash-flow" - - text_soup_financials = BeautifulSoup(requests.get(url_financials).text,"lxml") - - # Define financials columns - a_financials_header = list() - for financials_header in text_soup_financials.findAll('th', {'class': 'overflow__heading'}): - a_financials_header.append(financials_header.text.strip('\n').split('\n')[0]) - - s_header_end_trend = ("5-year trend", "5- qtr trend")[ns_parser.b_quarter] - df_financials = pd.DataFrame(columns=a_financials_header[0:a_financials_header.index(s_header_end_trend)]) - - # Add financials values - soup_financials = text_soup_financials.findAll('tr', {'class': 'table__row '}) - soup_financials += text_soup_financials.findAll('tr', {'class': 'table__row is-highlighted'}) - for financials_info in soup_financials: - a_financials_info = financials_info.text.split('\n') - l_financials = [a_financials_info[2]] - l_financials.extend(a_financials_info[5:-2]) - n_vals_to_add = len(df_financials.columns)-len(l_financials) - if n_vals_to_add > 0: - l_financials.append(n_vals_to_add * ' ') - # Append data values to financials - df_financials.loc[len(df_financials.index)] = l_financials - - # Set item name as index - df_financials = df_financials.set_index('Item') - - print(df_financials.iloc[17:30].to_string()) - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return + if ns_parser.b_quarter: + url_financials = f"https://www.marketwatch.com/investing/stock/{s_ticker}/financials/cash-flow/quarter" + else: + url_financials = f"https://www.marketwatch.com/investing/stock/{s_ticker}/financials/cash-flow" + + text_soup_financials = BeautifulSoup(requests.get(url_financials).text,"lxml") + + # Define financials columns + a_financials_header = list() + for financials_header in text_soup_financials.findAll('th', {'class': 'overflow__heading'}): + a_financials_header.append(financials_header.text.strip('\n').split('\n')[0]) + + s_header_end_trend = ("5-year trend", "5- qtr trend")[ns_parser.b_quarter] + df_financials = pd.DataFrame(columns=a_financials_header[0:a_financials_header.index(s_header_end_trend)]) + + # Add financials values + soup_financials = text_soup_financials.findAll('tr', {'class': 'table__row '}) + soup_financials += text_soup_financials.findAll('tr', {'class': 'table__row is-highlighted'}) + for financials_info in soup_financials: + a_financials_info = financials_info.text.split('\n') + l_financials = [a_financials_info[2]] + l_financials.extend(a_financials_info[5:-2]) + n_vals_to_add = len(df_financials.columns)-len(l_financials) + if n_vals_to_add > 0: + l_financials.append(n_vals_to_add * ' ') + # Append data values to financials + df_financials.loc[len(df_financials.index)] = l_financials + + # Set item name as index + df_financials = df_financials.set_index('Item') + + print(df_financials.iloc[17:30].to_string()) + print("") + + # ---------------------------------------------------- FINANCING ---------------------------------------------------- def financing(l_args, s_ticker): @@ -317,47 +295,42 @@ def financing(l_args, s_ticker): parser.add_argument('-q', "--quarter", action="store_true", default=False, dest="b_quarter", help='Quarter fundamental data flag.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return - - if ns_parser.b_quarter: - url_financials = f"https://www.marketwatch.com/investing/stock/{s_ticker}/financials/cash-flow/quarter" - else: - url_financials = f"https://www.marketwatch.com/investing/stock/{s_ticker}/financials/cash-flow" - - text_soup_financials = BeautifulSoup(requests.get(url_financials).text,"lxml") - - # Define financials columns - a_financials_header = list() - for financials_header in text_soup_financials.findAll('th', {'class': 'overflow__heading'}): - a_financials_header.append(financials_header.text.strip('\n').split('\n')[0]) - - s_header_end_trend = ("5-year trend", "5- qtr trend")[ns_parser.b_quarter] - df_financials = pd.DataFrame(columns=a_financials_header[0:a_financials_header.index(s_header_end_trend)]) - - # Add financials values - soup_financials = text_soup_financials.findAll('tr', {'class': 'table__row '}) - soup_financials += text_soup_financials.findAll('tr', {'class': 'table__row is-highlighted'}) - for financials_info in soup_financials: - a_financials_info = financials_info.text.split('\n') - l_financials = [a_financials_info[2]] - l_financials.extend(a_financials_info[5:-2]) - n_vals_to_add = len(df_financials.columns)-len(l_financials) - if n_vals_to_add > 0: - l_financials.append(n_vals_to_add * ' ') - # Append data values to financials - df_financials.loc[len(df_financials.index)] = l_financials - - # Set item name as index - df_financials = df_financials.set_index('Item') - - print(df_financials.iloc[31:].to_string()) - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return + + if ns_parser.b_quarter: + url_financials = f"https://www.marketwatch.com/investing/stock/{s_ticker}/financials/cash-flow/quarter" + else: + url_financials = f"https://www.marketwatch.com/investing/stock/{s_ticker}/financials/cash-flow" + + text_soup_financials = BeautifulSoup(requests.get(url_financials).text,"lxml") + + # Define financials columns + a_financials_header = list() + for financials_header in text_soup_financials.findAll('th', {'class': 'overflow__heading'}): + a_financials_header.append(financials_header.text.strip('\n').split('\n')[0]) + + s_header_end_trend = ("5-year trend", "5- qtr trend")[ns_parser.b_quarter] + df_financials = pd.DataFrame(columns=a_financials_header[0:a_financials_header.index(s_header_end_trend)]) + + # Add financials values + soup_financials = text_soup_financials.findAll('tr', {'class': 'table__row '}) + soup_financials += text_soup_financials.findAll('tr', {'class': 'table__row is-highlighted'}) + for financials_info in soup_financials: + a_financials_info = financials_info.text.split('\n') + l_financials = [a_financials_info[2]] + l_financials.extend(a_financials_info[5:-2]) + n_vals_to_add = len(df_financials.columns)-len(l_financials) + if n_vals_to_add > 0: + l_financials.append(n_vals_to_add * ' ') + # Append data values to financials + df_financials.loc[len(df_financials.index)] = l_financials + + # Set item name as index + df_financials = df_financials.set_index('Item') + + print(df_financials.iloc[31:].to_string()) + print("") diff --git a/fundamental_analysis/yahoo_finance_api.py b/fundamental_analysis/yahoo_finance_api.py index e98c74024c8..1d1fa0a7a7c 100644 --- a/fundamental_analysis/yahoo_finance_api.py +++ b/fundamental_analysis/yahoo_finance_api.py @@ -29,91 +29,83 @@ def info(l_args, s_ticker): Date short interest, PEG ratio, Short percent of float, Shares short prior month, Regular market price, Logo_url. [Source: Yahoo Finance]""") - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return - - stock = yf.Ticker(s_ticker) - df_info = pd.DataFrame(stock.info.items(), columns=['Metric', 'Value']) - df_info = df_info.set_index('Metric') - - df_info.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_info.index.tolist()] - df_info.index = [s_val.capitalize() for s_val in df_info.index] - - df_info.loc['Last split date'].values[0] = datetime.fromtimestamp(df_info.loc['Last split date'].values[0]).strftime('%d/%m/%Y') - - df_info = df_info.mask(df_info['Value'].astype(str).eq('[]')).dropna() - df_info = df_info.applymap(lambda x: long_number_format(x)) - - df_info = df_info.rename(index={"Address1": "Address", - "Average daily volume10 day": "Average daily volume 10 day", - "Average volume10days": "Average volume 10 days", - "Price to sales trailing12 months": "Price to sales trailing 12 months"}) - df_info.index = df_info.index.str.replace('eps','EPS') - df_info.index = df_info.index.str.replace('p e','PE') - df_info.index = df_info.index.str.replace('Peg','PEG') - - pd.set_option('display.max_colwidth', -1) - print(df_info.drop(index=['Long business summary']).to_string(header=False)) - print("") - print(df_info.loc['Long business summary'].values[0]) - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return + stock = yf.Ticker(s_ticker) + df_info = pd.DataFrame(stock.info.items(), columns=['Metric', 'Value']) + df_info = df_info.set_index('Metric') + + df_info.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_info.index.tolist()] + df_info.index = [s_val.capitalize() for s_val in df_info.index] + + df_info.loc['Last split date'].values[0] = datetime.fromtimestamp(df_info.loc['Last split date'].values[0]).strftime('%d/%m/%Y') + + df_info = df_info.mask(df_info['Value'].astype(str).eq('[]')).dropna() + df_info = df_info.applymap(lambda x: long_number_format(x)) + + df_info = df_info.rename(index={"Address1": "Address", + "Average daily volume10 day": "Average daily volume 10 day", + "Average volume10days": "Average volume 10 days", + "Price to sales trailing12 months": "Price to sales trailing 12 months"}) + df_info.index = df_info.index.str.replace('eps','EPS') + df_info.index = df_info.index.str.replace('p e','PE') + df_info.index = df_info.index.str.replace('Peg','PEG') + + pd.set_option('display.max_colwidth', -1) + print(df_info.drop(index=['Long business summary']).to_string(header=False)) + print("") + print(df_info.loc['Long business summary'].values[0]) + print("") + + # ---------------------------------------------------- SHAREHOLDERS ---------------------------------------------------- def shareholders(l_args, s_ticker): parser = argparse.ArgumentParser(prog='shrs', description="""Print Major, institutional and mutualfunds shareholders. [Source: Yahoo Finance]""") - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return - - stock = yf.Ticker(s_ticker) - pd.set_option('display.max_colwidth', -1) - - # Major holders - print("Major holders") - df_major_holders = stock.major_holders - df_major_holders[1] = df_major_holders[1].apply(lambda x: x.replace('%', 'Percentage')) - print(df_major_holders.to_string(index=False, header=False)) - print("") - - # Institutional holders - print("Institutional holders") - df_institutional_shareholders = stock.institutional_holders - df_institutional_shareholders.columns = df_institutional_shareholders.columns.str.replace('% Out','Stake') - df_institutional_shareholders['Shares'] = df_institutional_shareholders['Shares'].apply(lambda x: long_number_format(x)) - df_institutional_shareholders['Value'] = df_institutional_shareholders['Value'].apply(lambda x: long_number_format(x)) - df_institutional_shareholders['Stake'] = df_institutional_shareholders['Stake'].apply(lambda x: str("{:.2f}".format(100*x))+' %') - print(df_institutional_shareholders.to_string(index=False)) - print("") - - # Mutualfunds holders - print("Mutualfunds holders") - df_mutualfund_shareholders = stock.mutualfund_holders - df_mutualfund_shareholders.columns = df_mutualfund_shareholders.columns.str.replace('% Out','Stake') - df_mutualfund_shareholders['Shares'] = df_mutualfund_shareholders['Shares'].apply(lambda x: long_number_format(x)) - df_mutualfund_shareholders['Value'] = df_mutualfund_shareholders['Value'].apply(lambda x: long_number_format(x)) - df_mutualfund_shareholders['Stake'] = df_mutualfund_shareholders['Stake'].apply(lambda x: str("{:.2f}".format(100*x))+' %') - print(df_mutualfund_shareholders.to_string(index=False)) - - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return + stock = yf.Ticker(s_ticker) + pd.set_option('display.max_colwidth', -1) + + # Major holders + print("Major holders") + df_major_holders = stock.major_holders + df_major_holders[1] = df_major_holders[1].apply(lambda x: x.replace('%', 'Percentage')) + print(df_major_holders.to_string(index=False, header=False)) + print("") + + # Institutional holders + print("Institutional holders") + df_institutional_shareholders = stock.institutional_holders + df_institutional_shareholders.columns = df_institutional_shareholders.columns.str.replace('% Out','Stake') + df_institutional_shareholders['Shares'] = df_institutional_shareholders['Shares'].apply(lambda x: long_number_format(x)) + df_institutional_shareholders['Value'] = df_institutional_shareholders['Value'].apply(lambda x: long_number_format(x)) + df_institutional_shareholders['Stake'] = df_institutional_shareholders['Stake'].apply(lambda x: str("{:.2f}".format(100*x))+' %') + print(df_institutional_shareholders.to_string(index=False)) + print("") + + # Mutualfunds holders + print("Mutualfunds holders") + df_mutualfund_shareholders = stock.mutualfund_holders + df_mutualfund_shareholders.columns = df_mutualfund_shareholders.columns.str.replace('% Out','Stake') + df_mutualfund_shareholders['Shares'] = df_mutualfund_shareholders['Shares'].apply(lambda x: long_number_format(x)) + df_mutualfund_shareholders['Value'] = df_mutualfund_shareholders['Value'].apply(lambda x: long_number_format(x)) + df_mutualfund_shareholders['Stake'] = df_mutualfund_shareholders['Stake'].apply(lambda x: str("{:.2f}".format(100*x))+' %') + print(df_mutualfund_shareholders.to_string(index=False)) + + print("") + + # ---------------------------------------------------- SUSTAINABILITY ---------------------------------------------------- def sustainability(l_args, s_ticker): @@ -124,39 +116,34 @@ def sustainability(l_args, s_ticker): Tobacco, Totalesg, Highestcontroversy, Esgperformance, Coal, Pesticides, Adult, Percentile, Peergroup, Smallarms, Environmentscore, Governancepercentile, Militarycontract. [Source: Yahoo Finance]""") - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return - - stock = yf.Ticker(s_ticker) - pd.set_option('display.max_colwidth', -1) - - df_sustainability = stock.sustainability - - df_sustainability.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_sustainability.index.tolist()] - df_sustainability.index = [s_val.capitalize() for s_val in df_sustainability.index] - - df_sustainability = df_sustainability.rename(index={"Controversialweapons": "Controversial Weapons", - "Socialpercentile": "Social Percentile", - "Peercount": "Peer Count", - "Governancescore": "Governance Score", - "Environmentpercentile": "Environment Percentile", - "Animaltesting": "Animal Testing", - "Highestcontroversy": "Highest Controversy", - "Environmentscore": "Environment Score", - "Governancepercentile": "Governance Percentile", - "Militarycontract": "Military Contract"}) - - print(df_sustainability.to_string(header=False)) - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return + stock = yf.Ticker(s_ticker) + pd.set_option('display.max_colwidth', -1) + + df_sustainability = stock.sustainability + + df_sustainability.index = [''.join(' ' + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_sustainability.index.tolist()] + df_sustainability.index = [s_val.capitalize() for s_val in df_sustainability.index] + + df_sustainability = df_sustainability.rename(index={"Controversialweapons": "Controversial Weapons", + "Socialpercentile": "Social Percentile", + "Peercount": "Peer Count", + "Governancescore": "Governance Score", + "Environmentpercentile": "Environment Percentile", + "Animaltesting": "Animal Testing", + "Highestcontroversy": "Highest Controversy", + "Environmentscore": "Environment Score", + "Governancepercentile": "Governance Percentile", + "Militarycontract": "Military Contract"}) + + print(df_sustainability.to_string(header=False)) + print("") + # ---------------------------------------------------- CALENDAR_EARNINGS ---------------------------------------------------- def calendar_earnings(l_args, s_ticker): @@ -164,24 +151,18 @@ def calendar_earnings(l_args, s_ticker): description="""Calendar earnings of the company. Including revenue and earnings estimates. [Source: Yahoo Finance]""") - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return - - stock = yf.Ticker(s_ticker) - df_calendar = stock.calendar - df_calendar.iloc[0,0] = df_calendar.iloc[0,0].date().strftime("%d/%m/%Y") - df_calendar.iloc[:, 0] = df_calendar.iloc[:, 0].apply(lambda x: long_number_format(x)) - - print(f"Earnings Date: {df_calendar.iloc[:, 0]['Earnings Date']}") - print(f"Earnings Estimate Avg: {df_calendar.iloc[:, 0]['Earnings Average']} [{df_calendar.iloc[:, 0]['Earnings Low']}, {df_calendar.iloc[:, 0]['Earnings High']}]") - print(f"Revenue Estimate Avg: {df_calendar.iloc[:, 0]['Revenue Average']} [{df_calendar.iloc[:, 0]['Revenue Low']}, {df_calendar.iloc[:, 0]['Revenue High']}]") - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return + stock = yf.Ticker(s_ticker) + df_calendar = stock.calendar + df_calendar.iloc[0,0] = df_calendar.iloc[0,0].date().strftime("%d/%m/%Y") + df_calendar.iloc[:, 0] = df_calendar.iloc[:, 0].apply(lambda x: long_number_format(x)) + + print(f"Earnings Date: {df_calendar.iloc[:, 0]['Earnings Date']}") + print(f"Earnings Estimate Avg: {df_calendar.iloc[:, 0]['Earnings Average']} [{df_calendar.iloc[:, 0]['Earnings Low']}, {df_calendar.iloc[:, 0]['Earnings High']}]") + print(f"Revenue Estimate Avg: {df_calendar.iloc[:, 0]['Revenue Average']} [{df_calendar.iloc[:, 0]['Revenue Low']}, {df_calendar.iloc[:, 0]['Revenue High']}]") + print("") diff --git a/gamestonk_terminal.py b/gamestonk_terminal.py index 8581a0d4a06..bdcdea5d2f6 100644 --- a/gamestonk_terminal.py +++ b/gamestonk_terminal.py @@ -54,7 +54,8 @@ def load(l_args, s_ticker, s_start, s_interval, df_stock): df_stock.sort_index(ascending=True, inplace=True) - except: + except Exception as exc: + print("ERROR:", exc) print("Either the ticker or the API_KEY are invalids. Try again!") return [s_ticker, s_start, s_interval, df_stock] @@ -108,7 +109,8 @@ def view(l_args, s_ticker, s_start, s_interval, df_stock): else: df_stock, d_stock_metadata = ts.get_intraday(symbol=s_ticker, outputsize='full', interval=s_interval) - except: + except Exception as exc: + print("ERROR:", exc) print("Either the ticker or the API_KEY are invalids. Try again!") return diff --git a/prediction_techniques/arima.py b/prediction_techniques/arima.py index 571d7028ab4..fb39667f3a0 100644 --- a/prediction_techniques/arima.py +++ b/prediction_techniques/arima.py @@ -34,57 +34,53 @@ def arima(l_args, s_ticker, s_interval, df_stock): parser.add_argument('-r', "--results", action="store_true", dest="b_results", default=False, help='results about ARIMA summary flag.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") + return - # Machine Learning model - if ns_parser.s_order: - t_order = tuple([int(ord) for ord in list(ns_parser.s_order)]) - model = ARIMA(df_stock['5. adjusted close'].values, order=t_order).fit() - l_predictions = model.predict(start=len(df_stock['5. adjusted close'])+1, end=len(df_stock['5. adjusted close'])+ns_parser.n_days) + # Machine Learning model + if ns_parser.s_order: + t_order = tuple([int(ord) for ord in list(ns_parser.s_order)]) + model = ARIMA(df_stock['5. adjusted close'].values, order=t_order).fit() + l_predictions = model.predict(start=len(df_stock['5. adjusted close'])+1, end=len(df_stock['5. adjusted close'])+ns_parser.n_days) + else: + if ns_parser.b_seasonal: + model = pmdarima.auto_arima(df_stock['5. adjusted close'].values, error_action='ignore', seasonal=True, m=5, information_criteria=ns_parser.s_ic) else: - if ns_parser.b_seasonal: - model = pmdarima.auto_arima(df_stock['5. adjusted close'].values, error_action='ignore', seasonal=True, m=5, information_criteria=ns_parser.s_ic) - else: - model = pmdarima.auto_arima(df_stock['5. adjusted close'].values, error_action='ignore', seasonal=False, information_criteria=ns_parser.s_ic) - l_predictions = model.predict(n_periods=ns_parser.n_days) + model = pmdarima.auto_arima(df_stock['5. adjusted close'].values, error_action='ignore', seasonal=False, information_criteria=ns_parser.s_ic) + l_predictions = model.predict(n_periods=ns_parser.n_days) - # Prediction data - l_pred_days = get_next_stock_market_days(last_stock_day=df_stock['5. adjusted close'].index[-1], n_next_days=ns_parser.n_days) - df_pred = pd.Series(l_predictions, index=l_pred_days, name='Price') + # Prediction data + l_pred_days = get_next_stock_market_days(last_stock_day=df_stock['5. adjusted close'].index[-1], n_next_days=ns_parser.n_days) + df_pred = pd.Series(l_predictions, index=l_pred_days, name='Price') - if ns_parser.b_results: - print(model.summary()) - print("") - - # Plotting - plt.plot(df_stock.index, df_stock['5. adjusted close'], lw=2) - if ns_parser.s_order: - plt.title(f"ARIMA {str(t_order)} on {s_ticker} - {ns_parser.n_days} days prediction") - else: - plt.title(f"ARIMA {model.order} on {s_ticker} - {ns_parser.n_days} days prediction") - plt.xlim(df_stock.index[0], get_next_stock_market_days(df_pred.index[-1], 1)[-1] ) - plt.xlabel('Time') - plt.ylabel('Share Price ($)') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.plot([df_stock.index[-1], df_pred.index[0]], [df_stock['5. adjusted close'].values[-1], df_pred.values[0]], lw=1, c='tab:green', linestyle='--') - plt.plot(df_pred.index, df_pred, lw=2, c='tab:green') - plt.axvspan(df_stock.index[-1], df_pred.index[-1], facecolor='tab:orange', alpha=0.2) - xmin, xmax, ymin, ymax = plt.axis() - plt.vlines(df_stock.index[-1], ymin, ymax, linewidth=1, linestyle='--', color='k') - plt.show() - - # Print prediction data - print("Predicted share price:") - df_pred = df_pred.apply(lambda x: f"{x:.2f} $") - print(df_pred.to_string()) + if ns_parser.b_results: + print(model.summary()) print("") - except: - print("") + # Plotting + plt.plot(df_stock.index, df_stock['5. adjusted close'], lw=2) + if ns_parser.s_order: + plt.title(f"ARIMA {str(t_order)} on {s_ticker} - {ns_parser.n_days} days prediction") + else: + plt.title(f"ARIMA {model.order} on {s_ticker} - {ns_parser.n_days} days prediction") + plt.xlim(df_stock.index[0], get_next_stock_market_days(df_pred.index[-1], 1)[-1] ) + plt.xlabel('Time') + plt.ylabel('Share Price ($)') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.plot([df_stock.index[-1], df_pred.index[0]], [df_stock['5. adjusted close'].values[-1], df_pred.values[0]], lw=1, c='tab:green', linestyle='--') + plt.plot(df_pred.index, df_pred, lw=2, c='tab:green') + plt.axvspan(df_stock.index[-1], df_pred.index[-1], facecolor='tab:orange', alpha=0.2) + xmin, xmax, ymin, ymax = plt.axis() + plt.vlines(df_stock.index[-1], ymin, ymax, linewidth=1, linestyle='--', color='k') + plt.show() + + # Print prediction data + print("Predicted share price:") + df_pred = df_pred.apply(lambda x: f"{x:.2f} $") + print(df_pred.to_string()) + print("") diff --git a/prediction_techniques/fbprophet.py b/prediction_techniques/fbprophet.py index 335a0a23d5c..4daedddb444 100644 --- a/prediction_techniques/fbprophet.py +++ b/prediction_techniques/fbprophet.py @@ -20,42 +20,38 @@ def fbprophet(l_args, s_ticker, s_interval, df_stock): parser.add_argument('-d', "--days", action="store", dest="n_days", type=check_positive, default=5, help='prediction days') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") + return - df_stock = df_stock.sort_index(ascending=True) - df_stock.reset_index(level=0, inplace=True) - df_stock = df_stock[['date', '5. adjusted close']] - df_stock = df_stock.rename(columns={"date": "ds", "5. adjusted close": "y"}) - df_stock['ds'] = pd.to_datetime(df_stock['ds']) + df_stock = df_stock.sort_index(ascending=True) + df_stock.reset_index(level=0, inplace=True) + df_stock = df_stock[['date', '5. adjusted close']] + df_stock = df_stock.rename(columns={"date": "ds", "5. adjusted close": "y"}) + df_stock['ds'] = pd.to_datetime(df_stock['ds']) - model = Prophet(yearly_seasonality=False, daily_seasonality=False) - model.fit(df_stock) + model = Prophet(yearly_seasonality=False, daily_seasonality=False) + model.fit(df_stock) - l_pred_days = get_next_stock_market_days(last_stock_day=pd.to_datetime(df_stock['ds'].values[-1]), n_next_days=ns_parser.n_days) - close_prices = model.make_future_dataframe(periods=ns_parser.n_days) - forecast = model.predict(close_prices) + l_pred_days = get_next_stock_market_days(last_stock_day=pd.to_datetime(df_stock['ds'].values[-1]), n_next_days=ns_parser.n_days) + close_prices = model.make_future_dataframe(periods=ns_parser.n_days) + forecast = model.predict(close_prices) - fig, ax = plt.subplots() - model.plot(forecast, ax=ax, xlabel='Time', ylabel='Share Price ($)') - xmin, xmax, ymin, ymax = ax.axis() - ax.vlines(df_stock['ds'].values[-1], ymin, ymax, linewidth=2, linestyle='--', color='k') - plt.axvspan(df_stock['ds'].values[-1], l_pred_days[-1], facecolor='tab:orange', alpha=0.2) - plt.ylim(ymin, ymax) - plt.xlim(df_stock['ds'].values[0], get_next_stock_market_days(l_pred_days[-1], 1)[-1]) - plt.title(f"Fb Prophet on {s_ticker} - {ns_parser.n_days} days prediction") - plt.show() + fig, ax = plt.subplots() + model.plot(forecast, ax=ax, xlabel='Time', ylabel='Share Price ($)') + xmin, xmax, ymin, ymax = ax.axis() + ax.vlines(df_stock['ds'].values[-1], ymin, ymax, linewidth=2, linestyle='--', color='k') + plt.axvspan(df_stock['ds'].values[-1], l_pred_days[-1], facecolor='tab:orange', alpha=0.2) + plt.ylim(ymin, ymax) + plt.xlim(df_stock['ds'].values[0], get_next_stock_market_days(l_pred_days[-1], 1)[-1]) + plt.title(f"Fb Prophet on {s_ticker} - {ns_parser.n_days} days prediction") + plt.show() - print("") - print("Predicted share price:") - df_pred = forecast['yhat'][-ns_parser.n_days:].apply(lambda x: f"{x:.2f} $") - df_pred.index = l_pred_days - print(df_pred.to_string()) - print("") - - except: - print("") + print("") + print("Predicted share price:") + df_pred = forecast['yhat'][-ns_parser.n_days:].apply(lambda x: f"{x:.2f} $") + df_pred.index = l_pred_days + print(df_pred.to_string()) + print("") diff --git a/prediction_techniques/knn.py b/prediction_techniques/knn.py index 656a3a4556f..3590bd542bf 100644 --- a/prediction_techniques/knn.py +++ b/prediction_techniques/knn.py @@ -26,46 +26,42 @@ def k_nearest_neighbors(l_args, s_ticker, s_interval, df_stock): parser.add_argument('-n', "--neighbors", action="store", dest="n_neighbors", type=check_positive, default=20, help='number of neighbors to use on the algorithm.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") + return - # Split training data - stock_x, stock_y = splitTrain.split_train(df_stock['5. adjusted close'].values, ns_parser.n_inputs, ns_parser.n_days, ns_parser.n_jumps) + # Split training data + stock_x, stock_y = splitTrain.split_train(df_stock['5. adjusted close'].values, ns_parser.n_inputs, ns_parser.n_days, ns_parser.n_jumps) - # Machine Learning model - knn = neighbors.KNeighborsRegressor(n_neighbors=ns_parser.n_neighbors) - knn.fit(stock_x, stock_y) + # Machine Learning model + knn = neighbors.KNeighborsRegressor(n_neighbors=ns_parser.n_neighbors) + knn.fit(stock_x, stock_y) - # Prediction data - l_predictions = knn.predict(df_stock['5. adjusted close'].values[-ns_parser.n_inputs:].reshape(1, -1))[0] - l_pred_days = get_next_stock_market_days(last_stock_day=df_stock['5. adjusted close'].index[-1], n_next_days=ns_parser.n_days) - df_pred = pd.Series(l_predictions, index=l_pred_days, name='Price') + # Prediction data + l_predictions = knn.predict(df_stock['5. adjusted close'].values[-ns_parser.n_inputs:].reshape(1, -1))[0] + l_pred_days = get_next_stock_market_days(last_stock_day=df_stock['5. adjusted close'].index[-1], n_next_days=ns_parser.n_days) + df_pred = pd.Series(l_predictions, index=l_pred_days, name='Price') - # Plotting - plt.plot(df_stock.index, df_stock['5. adjusted close'], lw=2) - plt.title(f"{ns_parser.n_neighbors}-Nearest Neighbors on {s_ticker} - {ns_parser.n_days} days prediction") - plt.xlim(df_stock.index[0], get_next_stock_market_days(df_pred.index[-1], 1)[-1]) - plt.xlabel('Time') - plt.ylabel('Share Price ($)') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.plot([df_stock.index[-1], df_pred.index[0]], [df_stock['5. adjusted close'].values[-1], df_pred.values[0]], lw=1, c='tab:green', linestyle='--') - plt.plot(df_pred.index, df_pred, lw=2, c='tab:green') - plt.axvspan(df_stock.index[-1], df_pred.index[-1], facecolor='tab:orange', alpha=0.2) - xmin, xmax, ymin, ymax = plt.axis() - plt.vlines(df_stock.index[-1], ymin, ymax, linewidth=1, linestyle='--', color='k') - plt.show() + # Plotting + plt.plot(df_stock.index, df_stock['5. adjusted close'], lw=2) + plt.title(f"{ns_parser.n_neighbors}-Nearest Neighbors on {s_ticker} - {ns_parser.n_days} days prediction") + plt.xlim(df_stock.index[0], get_next_stock_market_days(df_pred.index[-1], 1)[-1]) + plt.xlabel('Time') + plt.ylabel('Share Price ($)') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.plot([df_stock.index[-1], df_pred.index[0]], [df_stock['5. adjusted close'].values[-1], df_pred.values[0]], lw=1, c='tab:green', linestyle='--') + plt.plot(df_pred.index, df_pred, lw=2, c='tab:green') + plt.axvspan(df_stock.index[-1], df_pred.index[-1], facecolor='tab:orange', alpha=0.2) + xmin, xmax, ymin, ymax = plt.axis() + plt.vlines(df_stock.index[-1], ymin, ymax, linewidth=1, linestyle='--', color='k') + plt.show() - # Print prediction data - print("Predicted share price:") - df_pred = df_pred.apply(lambda x: f"{x:.2f} $") - print(df_pred.to_string()) - print("") - - except: - print("") + # Print prediction data + print("Predicted share price:") + df_pred = df_pred.apply(lambda x: f"{x:.2f} $") + print(df_pred.to_string()) + print("") diff --git a/prediction_techniques/neural_networks.py b/prediction_techniques/neural_networks.py index 7fb8c36de42..21886f308e9 100644 --- a/prediction_techniques/neural_networks.py +++ b/prediction_techniques/neural_networks.py @@ -92,77 +92,74 @@ def mlp(l_args, s_ticker, s_interval, df_stock): parser.add_argument('-l', "--loss", action="store", dest="s_loss", default='mae', choices=['mae', 'mape', 'mse', 'msle'], help='loss function.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") + return - # Pre-process data - if ns_parser.s_preprocessing == 'standardization': - scaler = StandardScaler() - stock_train_data = scaler.fit_transform(np.array(df_stock['5. adjusted close'].values.reshape(-1, 1))) - elif ns_parser.s_preprocessing == 'normalization': - scaler = MinMaxScaler() - stock_train_data = scaler.fit_transform(np.array(df_stock['5. adjusted close'].values.reshape(-1, 1))) - else: # No pre-processing - stock_train_data = np.array(df_stock['5. adjusted close'].values.reshape(-1, 1)) + # Pre-process data + if ns_parser.s_preprocessing == 'standardization': + scaler = StandardScaler() + stock_train_data = scaler.fit_transform(np.array(df_stock['5. adjusted close'].values.reshape(-1, 1))) + elif ns_parser.s_preprocessing == 'normalization': + scaler = MinMaxScaler() + stock_train_data = scaler.fit_transform(np.array(df_stock['5. adjusted close'].values.reshape(-1, 1))) + else: # No pre-processing + stock_train_data = np.array(df_stock['5. adjusted close'].values.reshape(-1, 1)) - # Split training data for the neural network - stock_x, stock_y = splitTrain.split_train(stock_train_data, ns_parser.n_inputs, ns_parser.n_days, numJumps=ns_parser.n_jumps) - stock_x = np.array(stock_x) - stock_x = np.reshape(stock_x, (stock_x.shape[0], stock_x.shape[1])) - stock_y = np.array(stock_y) - stock_y = np.reshape(stock_y, (stock_y.shape[0], stock_y.shape[1])) + # Split training data for the neural network + stock_x, stock_y = splitTrain.split_train(stock_train_data, ns_parser.n_inputs, ns_parser.n_days, numJumps=ns_parser.n_jumps) + stock_x = np.array(stock_x) + stock_x = np.reshape(stock_x, (stock_x.shape[0], stock_x.shape[1])) + stock_y = np.array(stock_y) + stock_y = np.reshape(stock_y, (stock_y.shape[0], stock_y.shape[1])) - # Build Neural Network model - model = build_neural_network_model(cfg_nn_models.MultiLayer_Perceptron, ns_parser.n_inputs, ns_parser.n_days) - model.compile(optimizer=ns_parser.s_optimizer, loss=ns_parser.s_loss) + # Build Neural Network model + model = build_neural_network_model(cfg_nn_models.MultiLayer_Perceptron, ns_parser.n_inputs, ns_parser.n_days) + model.compile(optimizer=ns_parser.s_optimizer, loss=ns_parser.s_loss) - # Train our model - model.fit(stock_x, stock_y, epochs=ns_parser.n_epochs, verbose=1); - print("") + # Train our model + model.fit(stock_x, stock_y, epochs=ns_parser.n_epochs, verbose=1); + print("") - print(model.summary()) - print("") + print(model.summary()) + print("") - # Prediction - yhat = model.predict(stock_train_data[-ns_parser.n_inputs:].reshape(1, ns_parser.n_inputs), verbose=0) + # Prediction + yhat = model.predict(stock_train_data[-ns_parser.n_inputs:].reshape(1, ns_parser.n_inputs), verbose=0) - # Re-scale the data back - if (ns_parser.s_preprocessing == 'standardization') or (ns_parser.s_preprocessing == 'normalization'): - y_pred_test_t = scaler.inverse_transform(yhat.tolist()) - else: - y_pred_test_t = yhat + # Re-scale the data back + if (ns_parser.s_preprocessing == 'standardization') or (ns_parser.s_preprocessing == 'normalization'): + y_pred_test_t = scaler.inverse_transform(yhat.tolist()) + else: + y_pred_test_t = yhat - l_pred_days = get_next_stock_market_days(last_stock_day=df_stock['5. adjusted close'].index[-1], n_next_days=ns_parser.n_days) - df_pred = pd.Series(y_pred_test_t[0].tolist(), index=l_pred_days, name='Price') + l_pred_days = get_next_stock_market_days(last_stock_day=df_stock['5. adjusted close'].index[-1], n_next_days=ns_parser.n_days) + df_pred = pd.Series(y_pred_test_t[0].tolist(), index=l_pred_days, name='Price') - # Plotting - plt.plot(df_stock.index, df_stock['5. adjusted close'], lw=3) - plt.title(f"MLP on {s_ticker} - {ns_parser.n_days} days prediction") - plt.xlim(df_stock.index[0], get_next_stock_market_days(df_pred.index[-1], 1)[-1]) - plt.xlabel('Time') - plt.ylabel('Share Price ($)') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.plot([df_stock.index[-1], df_pred.index[0]], [df_stock['5. adjusted close'].values[-1], df_pred.values[0]], lw=1, c='tab:green', linestyle='--') - plt.plot(df_pred.index, df_pred, lw=2, c='tab:green') - plt.axvspan(df_stock.index[-1], df_pred.index[-1], facecolor='tab:orange', alpha=0.2) - xmin, xmax, ymin, ymax = plt.axis() - plt.vlines(df_stock.index[-1], ymin, ymax, colors='k', linewidth=3, linestyle='--', color='k') - plt.show() + # Plotting + plt.plot(df_stock.index, df_stock['5. adjusted close'], lw=3) + plt.title(f"MLP on {s_ticker} - {ns_parser.n_days} days prediction") + plt.xlim(df_stock.index[0], get_next_stock_market_days(df_pred.index[-1], 1)[-1]) + plt.xlabel('Time') + plt.ylabel('Share Price ($)') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.plot([df_stock.index[-1], df_pred.index[0]], [df_stock['5. adjusted close'].values[-1], df_pred.values[0]], lw=1, c='tab:green', linestyle='--') + plt.plot(df_pred.index, df_pred, lw=2, c='tab:green') + plt.axvspan(df_stock.index[-1], df_pred.index[-1], facecolor='tab:orange', alpha=0.2) + xmin, xmax, ymin, ymax = plt.axis() + plt.vlines(df_stock.index[-1], ymin, ymax, colors='k', linewidth=3, linestyle='--', color='k') + plt.show() - # Print prediction data - print("Predicted share price:") - df_pred = df_pred.apply(lambda x: f"{x:.2f} $") - print(df_pred.to_string()) - print("") + # Print prediction data + print("Predicted share price:") + df_pred = df_pred.apply(lambda x: f"{x:.2f} $") + print(df_pred.to_string()) + print("") - except: - print("") # -------------------------------------------------- RNN -------------------------------------------------- @@ -185,77 +182,73 @@ def rnn(l_args, s_ticker, s_interval, df_stock): parser.add_argument('-l', "--loss", action="store", dest="s_loss", default='mae', choices=['mae', 'mape', 'mse', 'msle'], help='loss function.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") + return - # Pre-process data - if ns_parser.s_preprocessing == 'standardization': - scaler = StandardScaler() - stock_train_data = scaler.fit_transform(np.array(df_stock['5. adjusted close'].values.reshape(-1, 1))) - elif ns_parser.s_preprocessing == 'normalization': - scaler = MinMaxScaler() - stock_train_data = scaler.fit_transform(np.array(df_stock['5. adjusted close'].values.reshape(-1, 1))) - else: # No pre-processing - stock_train_data = np.array(df_stock['5. adjusted close'].values.reshape(-1, 1)) + # Pre-process data + if ns_parser.s_preprocessing == 'standardization': + scaler = StandardScaler() + stock_train_data = scaler.fit_transform(np.array(df_stock['5. adjusted close'].values.reshape(-1, 1))) + elif ns_parser.s_preprocessing == 'normalization': + scaler = MinMaxScaler() + stock_train_data = scaler.fit_transform(np.array(df_stock['5. adjusted close'].values.reshape(-1, 1))) + else: # No pre-processing + stock_train_data = np.array(df_stock['5. adjusted close'].values.reshape(-1, 1)) - # Split training data for the neural network - stock_x, stock_y = splitTrain.split_train(stock_train_data, ns_parser.n_inputs, ns_parser.n_days, numJumps=ns_parser.n_jumps) - stock_x = np.array(stock_x) - stock_x = np.reshape(stock_x, (stock_x.shape[0], stock_x.shape[1], 1)) - stock_y = np.array(stock_y) - stock_y = np.reshape(stock_y, (stock_y.shape[0], stock_y.shape[1], 1)) + # Split training data for the neural network + stock_x, stock_y = splitTrain.split_train(stock_train_data, ns_parser.n_inputs, ns_parser.n_days, numJumps=ns_parser.n_jumps) + stock_x = np.array(stock_x) + stock_x = np.reshape(stock_x, (stock_x.shape[0], stock_x.shape[1], 1)) + stock_y = np.array(stock_y) + stock_y = np.reshape(stock_y, (stock_y.shape[0], stock_y.shape[1], 1)) - # Build Neural Network model - model = build_neural_network_model(cfg_nn_models.Recurrent_Neural_Network, ns_parser.n_inputs, ns_parser.n_days) - model.compile(optimizer=ns_parser.s_optimizer, loss=ns_parser.s_loss) + # Build Neural Network model + model = build_neural_network_model(cfg_nn_models.Recurrent_Neural_Network, ns_parser.n_inputs, ns_parser.n_days) + model.compile(optimizer=ns_parser.s_optimizer, loss=ns_parser.s_loss) - # Train our model - model.fit(stock_x, stock_y, epochs=ns_parser.n_epochs, verbose=1); - print("") + # Train our model + model.fit(stock_x, stock_y, epochs=ns_parser.n_epochs, verbose=1); + print("") - print(model.summary()) - print("") + print(model.summary()) + print("") - # Prediction - yhat = model.predict(stock_train_data[-ns_parser.n_inputs:].reshape(1, ns_parser.n_inputs, 1), verbose=0) + # Prediction + yhat = model.predict(stock_train_data[-ns_parser.n_inputs:].reshape(1, ns_parser.n_inputs, 1), verbose=0) - # Re-scale the data back - if (ns_parser.s_preprocessing == 'standardization') or (ns_parser.s_preprocessing == 'normalization'): - y_pred_test_t = scaler.inverse_transform(yhat.tolist()) - else: - y_pred_test_t = yhat + # Re-scale the data back + if (ns_parser.s_preprocessing == 'standardization') or (ns_parser.s_preprocessing == 'normalization'): + y_pred_test_t = scaler.inverse_transform(yhat.tolist()) + else: + y_pred_test_t = yhat - l_pred_days = get_next_stock_market_days(last_stock_day=df_stock['5. adjusted close'].index[-1], n_next_days=ns_parser.n_days) - df_pred = pd.Series(y_pred_test_t[0].tolist(), index=l_pred_days, name='Price') + l_pred_days = get_next_stock_market_days(last_stock_day=df_stock['5. adjusted close'].index[-1], n_next_days=ns_parser.n_days) + df_pred = pd.Series(y_pred_test_t[0].tolist(), index=l_pred_days, name='Price') - # Plotting - plt.plot(df_stock.index, df_stock['5. adjusted close'], lw=3) - plt.title(f"RNN on {s_ticker} - {ns_parser.n_days} days prediction") - plt.xlim(df_stock.index[0], get_next_stock_market_days(df_pred.index[-1], 1)[-1]) - plt.xlabel('Time') - plt.ylabel('Share Price ($)') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.plot([df_stock.index[-1], df_pred.index[0]], [df_stock['5. adjusted close'].values[-1], df_pred.values[0]], lw=1, c='tab:green', linestyle='--') - plt.plot(df_pred.index, df_pred, lw=2, c='tab:green') - plt.axvspan(df_stock.index[-1], df_pred.index[-1], facecolor='tab:orange', alpha=0.2) - xmin, xmax, ymin, ymax = plt.axis() - plt.vlines(df_stock.index[-1], ymin, ymax, colors='k', linewidth=3, linestyle='--', color='k') - plt.show() + # Plotting + plt.plot(df_stock.index, df_stock['5. adjusted close'], lw=3) + plt.title(f"RNN on {s_ticker} - {ns_parser.n_days} days prediction") + plt.xlim(df_stock.index[0], get_next_stock_market_days(df_pred.index[-1], 1)[-1]) + plt.xlabel('Time') + plt.ylabel('Share Price ($)') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.plot([df_stock.index[-1], df_pred.index[0]], [df_stock['5. adjusted close'].values[-1], df_pred.values[0]], lw=1, c='tab:green', linestyle='--') + plt.plot(df_pred.index, df_pred, lw=2, c='tab:green') + plt.axvspan(df_stock.index[-1], df_pred.index[-1], facecolor='tab:orange', alpha=0.2) + xmin, xmax, ymin, ymax = plt.axis() + plt.vlines(df_stock.index[-1], ymin, ymax, colors='k', linewidth=3, linestyle='--', color='k') + plt.show() - # Print prediction data - print("Predicted share price:") - df_pred = df_pred.apply(lambda x: f"{x:.2f} $") - print(df_pred.to_string()) - print("") - - except: - print("") + # Print prediction data + print("Predicted share price:") + df_pred = df_pred.apply(lambda x: f"{x:.2f} $") + print(df_pred.to_string()) + print("") # -------------------------------------------------- LSTM -------------------------------------------------- @@ -278,74 +271,70 @@ def lstm(l_args, s_ticker, s_interval, df_stock): parser.add_argument('-l', "--loss", action="store", dest="s_loss", default='mae', choices=['mae', 'mape', 'mse', 'msle'], help='loss function.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") + return - # Pre-process data - if ns_parser.s_preprocessing == 'standardization': - scaler = StandardScaler() - stock_train_data = scaler.fit_transform(np.array(df_stock['5. adjusted close'].values.reshape(-1, 1))) - elif ns_parser.s_preprocessing == 'normalization': - scaler = MinMaxScaler() - stock_train_data = scaler.fit_transform(np.array(df_stock['5. adjusted close'].values.reshape(-1, 1))) - else: # No pre-processing - stock_train_data = np.array(df_stock['5. adjusted close'].values.reshape(-1, 1)) + # Pre-process data + if ns_parser.s_preprocessing == 'standardization': + scaler = StandardScaler() + stock_train_data = scaler.fit_transform(np.array(df_stock['5. adjusted close'].values.reshape(-1, 1))) + elif ns_parser.s_preprocessing == 'normalization': + scaler = MinMaxScaler() + stock_train_data = scaler.fit_transform(np.array(df_stock['5. adjusted close'].values.reshape(-1, 1))) + else: # No pre-processing + stock_train_data = np.array(df_stock['5. adjusted close'].values.reshape(-1, 1)) - # Split training data for the neural network - stock_x, stock_y = splitTrain.split_train(stock_train_data, ns_parser.n_inputs, ns_parser.n_days, numJumps=ns_parser.n_jumps) - stock_x = np.array(stock_x) - stock_x = np.reshape(stock_x, (stock_x.shape[0], stock_x.shape[1], 1)) - stock_y = np.array(stock_y) - stock_y = np.reshape(stock_y, (stock_y.shape[0], stock_y.shape[1], 1)) + # Split training data for the neural network + stock_x, stock_y = splitTrain.split_train(stock_train_data, ns_parser.n_inputs, ns_parser.n_days, numJumps=ns_parser.n_jumps) + stock_x = np.array(stock_x) + stock_x = np.reshape(stock_x, (stock_x.shape[0], stock_x.shape[1], 1)) + stock_y = np.array(stock_y) + stock_y = np.reshape(stock_y, (stock_y.shape[0], stock_y.shape[1], 1)) - # Build Neural Network model - model = build_neural_network_model(cfg_nn_models.Long_Short_Term_Memory, ns_parser.n_inputs, ns_parser.n_days) - model.compile(optimizer=ns_parser.s_optimizer, loss=ns_parser.s_loss) + # Build Neural Network model + model = build_neural_network_model(cfg_nn_models.Long_Short_Term_Memory, ns_parser.n_inputs, ns_parser.n_days) + model.compile(optimizer=ns_parser.s_optimizer, loss=ns_parser.s_loss) - # Train our model - model.fit(stock_x, stock_y, epochs=ns_parser.n_epochs, verbose=1); - print("") + # Train our model + model.fit(stock_x, stock_y, epochs=ns_parser.n_epochs, verbose=1); + print("") - print(model.summary()) - print("") + print(model.summary()) + print("") - # Prediction - yhat = model.predict(stock_train_data[-ns_parser.n_inputs:].reshape(1, ns_parser.n_inputs, 1), verbose=0) + # Prediction + yhat = model.predict(stock_train_data[-ns_parser.n_inputs:].reshape(1, ns_parser.n_inputs, 1), verbose=0) - # Re-scale the data back - if (ns_parser.s_preprocessing == 'standardization') or (ns_parser.s_preprocessing == 'normalization'): - y_pred_test_t = scaler.inverse_transform(yhat.tolist()) - else: - y_pred_test_t = yhat + # Re-scale the data back + if (ns_parser.s_preprocessing == 'standardization') or (ns_parser.s_preprocessing == 'normalization'): + y_pred_test_t = scaler.inverse_transform(yhat.tolist()) + else: + y_pred_test_t = yhat - l_pred_days = get_next_stock_market_days(last_stock_day=df_stock['5. adjusted close'].index[-1], n_next_days=ns_parser.n_days) - df_pred = pd.Series(y_pred_test_t[0].tolist(), index=l_pred_days, name='Price') + l_pred_days = get_next_stock_market_days(last_stock_day=df_stock['5. adjusted close'].index[-1], n_next_days=ns_parser.n_days) + df_pred = pd.Series(y_pred_test_t[0].tolist(), index=l_pred_days, name='Price') - # Plotting - plt.plot(df_stock.index, df_stock['5. adjusted close'], lw=3) - plt.title(f"LSTM on {s_ticker} - {ns_parser.n_days} days prediction") - plt.xlim(df_stock.index[0], get_next_stock_market_days(df_pred.index[-1], 1)[-1]) - plt.xlabel('Time') - plt.ylabel('Share Price ($)') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.plot([df_stock.index[-1], df_pred.index[0]], [df_stock['5. adjusted close'].values[-1], df_pred.values[0]], lw=1, c='tab:green', linestyle='--') - plt.plot(df_pred.index, df_pred, lw=2, c='tab:green') - plt.axvspan(df_stock.index[-1], df_pred.index[-1], facecolor='tab:orange', alpha=0.2) - xmin, xmax, ymin, ymax = plt.axis() - plt.vlines(df_stock.index[-1], ymin, ymax, colors='k', linewidth=3, linestyle='--', color='k') - plt.show() + # Plotting + plt.plot(df_stock.index, df_stock['5. adjusted close'], lw=3) + plt.title(f"LSTM on {s_ticker} - {ns_parser.n_days} days prediction") + plt.xlim(df_stock.index[0], get_next_stock_market_days(df_pred.index[-1], 1)[-1]) + plt.xlabel('Time') + plt.ylabel('Share Price ($)') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.plot([df_stock.index[-1], df_pred.index[0]], [df_stock['5. adjusted close'].values[-1], df_pred.values[0]], lw=1, c='tab:green', linestyle='--') + plt.plot(df_pred.index, df_pred, lw=2, c='tab:green') + plt.axvspan(df_stock.index[-1], df_pred.index[-1], facecolor='tab:orange', alpha=0.2) + xmin, xmax, ymin, ymax = plt.axis() + plt.vlines(df_stock.index[-1], ymin, ymax, colors='k', linewidth=3, linestyle='--', color='k') + plt.show() - # Print prediction data - print("Predicted share price:") - df_pred = df_pred.apply(lambda x: f"{x:.2f} $") - print(df_pred.to_string()) - print("") - - except: - print("") + # Print prediction data + print("Predicted share price:") + df_pred = df_pred.apply(lambda x: f"{x:.2f} $") + print(df_pred.to_string()) + print("") diff --git a/prediction_techniques/regression.py b/prediction_techniques/regression.py index af219522aee..c6a853516db 100644 --- a/prediction_techniques/regression.py +++ b/prediction_techniques/regression.py @@ -36,53 +36,48 @@ def regression(l_args, s_ticker, s_interval, df_stock, polynomial): parser.add_argument('-p', "--polynomial", action="store", dest="n_polynomial", type=check_positive, required=True, help='polynomial associated with regression.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") + return - # Split training data - stock_x, stock_y = splitTrain.split_train(df_stock['5. adjusted close'].values, ns_parser.n_inputs, ns_parser.n_days, ns_parser.n_jumps) + # Split training data + stock_x, stock_y = splitTrain.split_train(df_stock['5. adjusted close'].values, ns_parser.n_inputs, ns_parser.n_days, ns_parser.n_jumps) - # Machine Learning model - if polynomial == LINEAR: - model = linear_model.LinearRegression(n_jobs=-1) - else: - if polynomial == USER_INPUT: - polynomial = ns_parser.n_polynomial - model = pipeline.make_pipeline(preprocessing.PolynomialFeatures(polynomial), linear_model.Ridge()) + # Machine Learning model + if polynomial == LINEAR: + model = linear_model.LinearRegression(n_jobs=-1) + else: + if polynomial == USER_INPUT: + polynomial = ns_parser.n_polynomial + model = pipeline.make_pipeline(preprocessing.PolynomialFeatures(polynomial), linear_model.Ridge()) - model.fit(stock_x, stock_y) - l_predictions = model.predict(df_stock['5. adjusted close'].values[-ns_parser.n_inputs:].reshape(1, -1))[0] - - # Prediction data - l_pred_days = get_next_stock_market_days(last_stock_day=df_stock['5. adjusted close'].index[-1], n_next_days=ns_parser.n_days) - df_pred = pd.Series(l_predictions, index=l_pred_days, name='Price') + model.fit(stock_x, stock_y) + l_predictions = model.predict(df_stock['5. adjusted close'].values[-ns_parser.n_inputs:].reshape(1, -1))[0] - # Plotting - plt.plot(df_stock.index, df_stock['5. adjusted close'], lw=2) - plt.title(f"Regression (polynomial {polynomial}) on {s_ticker} - {ns_parser.n_days} days prediction") - plt.xlim(df_stock.index[0], get_next_stock_market_days(df_pred.index[-1], 1)[-1] ) - plt.xlabel('Time') - plt.ylabel('Share Price ($)') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.plot([df_stock.index[-1], df_pred.index[0]], [df_stock['5. adjusted close'].values[-1], df_pred.values[0]], lw=1, c='tab:green', linestyle='--') - plt.plot(df_pred.index, df_pred, lw=2, c='tab:green') - plt.axvspan(df_stock.index[-1], df_pred.index[-1], facecolor='tab:orange', alpha=0.2) - xmin, xmax, ymin, ymax = plt.axis() - plt.vlines(df_stock.index[-1], ymin, ymax, linewidth=1, linestyle='--', color='k') - plt.show() + # Prediction data + l_pred_days = get_next_stock_market_days(last_stock_day=df_stock['5. adjusted close'].index[-1], n_next_days=ns_parser.n_days) + df_pred = pd.Series(l_predictions, index=l_pred_days, name='Price') - # Print prediction data - print("Predicted share price:") - df_pred = df_pred.apply(lambda x: f"{x:.2f} $") - print(df_pred.to_string()) - print("") - - except: - print("") + # Plotting + plt.plot(df_stock.index, df_stock['5. adjusted close'], lw=2) + plt.title(f"Regression (polynomial {polynomial}) on {s_ticker} - {ns_parser.n_days} days prediction") + plt.xlim(df_stock.index[0], get_next_stock_market_days(df_pred.index[-1], 1)[-1] ) + plt.xlabel('Time') + plt.ylabel('Share Price ($)') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.plot([df_stock.index[-1], df_pred.index[0]], [df_stock['5. adjusted close'].values[-1], df_pred.values[0]], lw=1, c='tab:green', linestyle='--') + plt.plot(df_pred.index, df_pred, lw=2, c='tab:green') + plt.axvspan(df_stock.index[-1], df_pred.index[-1], facecolor='tab:orange', alpha=0.2) + xmin, xmax, ymin, ymax = plt.axis() + plt.vlines(df_stock.index[-1], ymin, ymax, linewidth=1, linestyle='--', color='k') + plt.show() + # Print prediction data + print("Predicted share price:") + df_pred = df_pred.apply(lambda x: f"{x:.2f} $") + print(df_pred.to_string()) + print("") diff --git a/prediction_techniques/sma.py b/prediction_techniques/sma.py index d73ae577dae..608b60129a6 100644 --- a/prediction_techniques/sma.py +++ b/prediction_techniques/sma.py @@ -25,49 +25,44 @@ def simple_moving_average(l_args, s_ticker, s_interval, df_stock): parser.add_argument('-d', "--days", action="store", dest="n_days", type=check_positive, default=5, help='prediction days.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") + return - # Prediction data - l_predictions = list() - for pred_day in range(ns_parser.n_days): - if pred_day < ns_parser.n_length: - l_ma_stock = df_stock['5. adjusted close'].values[-ns_parser.n_length+pred_day:] - else: - l_ma_stock = list() - l_predictions.append(np.mean(np.append(l_ma_stock, l_predictions))) + # Prediction data + l_predictions = list() + for pred_day in range(ns_parser.n_days): + if pred_day < ns_parser.n_length: + l_ma_stock = df_stock['5. adjusted close'].values[-ns_parser.n_length+pred_day:] + else: + l_ma_stock = list() + l_predictions.append(np.mean(np.append(l_ma_stock, l_predictions))) - l_pred_days = get_next_stock_market_days(last_stock_day=df_stock['5. adjusted close'].index[-1], n_next_days=ns_parser.n_days) - df_pred = pd.Series(l_predictions, index=l_pred_days, name='Price') + l_pred_days = get_next_stock_market_days(last_stock_day=df_stock['5. adjusted close'].index[-1], n_next_days=ns_parser.n_days) + df_pred = pd.Series(l_predictions, index=l_pred_days, name='Price') - # Plotting - plt.plot(df_stock.index, df_stock['5. adjusted close'], lw=2) - plt.title(f"{ns_parser.n_length} Moving Average on {s_ticker} - {ns_parser.n_days} days prediction") - plt.xlim(df_stock.index[0], get_next_stock_market_days(df_pred.index[-1], 1)[-1]) - plt.xlabel('Time') - plt.ylabel('Share Price ($)') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - df_ma = df_stock['5. adjusted close'].rolling(window=ns_parser.n_length).mean() - plt.plot(df_ma.index, df_ma, lw=2, linestyle='--', c='tab:orange') - plt.plot([df_stock.index[-1], df_pred.index[0]], [df_stock['5. adjusted close'].values[-1], df_pred.values[0]], lw=1, c='tab:green', linestyle='--') - plt.plot(df_pred.index, df_pred, lw=2, c='tab:green') - plt.axvspan(df_stock.index[-1], df_pred.index[-1], facecolor='tab:orange', alpha=0.2) - xmin, xmax, ymin, ymax = plt.axis() - plt.vlines(df_stock.index[-1], ymin, ymax, linewidth=1, linestyle='--', color='k') - plt.show() - - # Print prediction data - print("Predicted share price:") - df_pred = df_pred.apply(lambda x: f"{x:.2f} $") - print(df_pred.to_string()) - print("") - - except: - print("") + # Plotting + plt.plot(df_stock.index, df_stock['5. adjusted close'], lw=2) + plt.title(f"{ns_parser.n_length} Moving Average on {s_ticker} - {ns_parser.n_days} days prediction") + plt.xlim(df_stock.index[0], get_next_stock_market_days(df_pred.index[-1], 1)[-1]) + plt.xlabel('Time') + plt.ylabel('Share Price ($)') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + df_ma = df_stock['5. adjusted close'].rolling(window=ns_parser.n_length).mean() + plt.plot(df_ma.index, df_ma, lw=2, linestyle='--', c='tab:orange') + plt.plot([df_stock.index[-1], df_pred.index[0]], [df_stock['5. adjusted close'].values[-1], df_pred.values[0]], lw=1, c='tab:green', linestyle='--') + plt.plot(df_pred.index, df_pred, lw=2, c='tab:green') + plt.axvspan(df_stock.index[-1], df_pred.index[-1], facecolor='tab:orange', alpha=0.2) + xmin, xmax, ymin, ymax = plt.axis() + plt.vlines(df_stock.index[-1], ymin, ymax, linewidth=1, linestyle='--', color='k') + plt.show() + # Print prediction data + print("Predicted share price:") + df_pred = df_pred.apply(lambda x: f"{x:.2f} $") + print(df_pred.to_string()) + print("") diff --git a/sentiment/google_api.py b/sentiment/google_api.py index 00ae0b6b06f..1f76bf6853f 100644 --- a/sentiment/google_api.py +++ b/sentiment/google_api.py @@ -14,34 +14,31 @@ def mentions(l_args, s_ticker, s_start): parser.add_argument('-s', "--start", type=valid_date, dest="s_start", default=s_start, help="starting date (format YYYY-MM-DD) from when we are interested in stock's mentions.") - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") + return - pytrend = TrendReq() - pytrend.build_payload(kw_list=[s_ticker]) - df_interest = pytrend.interest_over_time() + pytrend = TrendReq() + pytrend.build_payload(kw_list=[s_ticker]) + df_interest = pytrend.interest_over_time() - plt.title(f"Interest over time on {s_ticker}") - if ns_parser.s_start: - df_interest = df_interest[ns_parser.s_start:] - plt.bar(df_interest.index, df_interest[s_ticker], width=2) - plt.bar(df_interest.index[-1], df_interest[s_ticker].values[-1], color='tab:orange', width=2) - else: - plt.bar(df_interest.index, df_interest[s_ticker], width=1) - plt.bar(df_interest.index[-1], df_interest[s_ticker].values[-1], color='tab:orange', width=1) + plt.title(f"Interest over time on {s_ticker}") + if ns_parser.s_start: + df_interest = df_interest[ns_parser.s_start:] + plt.bar(df_interest.index, df_interest[s_ticker], width=2) + plt.bar(df_interest.index[-1], df_interest[s_ticker].values[-1], color='tab:orange', width=2) + else: + plt.bar(df_interest.index, df_interest[s_ticker], width=1) + plt.bar(df_interest.index[-1], df_interest[s_ticker].values[-1], color='tab:orange', width=1) - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.ylabel('Interest [%]') - plt.xlabel("Time") - plt.show() - print("") + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.ylabel('Interest [%]') + plt.xlabel("Time") + plt.show() + print("") - except: - print("") # ------------------------------------------------------------------------------------------------------------------- @@ -52,29 +49,25 @@ def regions(l_args, s_ticker): parser.add_argument('-n', "--num", action="store", dest="n_num", type=check_positive, default=10, help='number of regions to plot that show highest interest.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") + return - pytrend = TrendReq() - pytrend.build_payload(kw_list=[s_ticker]) - df_interest_region = pytrend.interest_by_region() - df_interest_region = df_interest_region.sort_values([s_ticker], ascending=False).head(ns_parser.n_num) + pytrend = TrendReq() + pytrend.build_payload(kw_list=[s_ticker]) + df_interest_region = pytrend.interest_by_region() + df_interest_region = df_interest_region.sort_values([s_ticker], ascending=False).head(ns_parser.n_num) - plt.figure(figsize=(25,5)) - plt.title(f"Top's regions interest on {s_ticker}") - plt.bar(df_interest_region.index, df_interest_region[s_ticker], width=0.8) - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.ylabel('Interest [%]') - plt.xlabel("Time") - plt.show() - print("") - - except: - print("") + plt.figure(figsize=(25,5)) + plt.title(f"Top's regions interest on {s_ticker}") + plt.bar(df_interest_region.index, df_interest_region[s_ticker], width=0.8) + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.ylabel('Interest [%]') + plt.xlabel("Time") + plt.show() + print("") # ------------------------------------------------------------------------------------------------------------------- @@ -85,24 +78,21 @@ def queries(l_args, s_ticker): parser.add_argument('-n', "--num", action="store", dest="n_num", type=check_positive, default=10, help='number of top related queries to print.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") + return - pytrend = TrendReq() - pytrend.build_payload(kw_list=[s_ticker]) - df_related_queries = pytrend.related_queries() - df_related_queries = df_related_queries[s_ticker]['top'].head(ns_parser.n_num) - df_related_queries['value'] = df_related_queries['value'].apply(lambda x: str(x)+'%') - print(f"Top {s_ticker}'s related queries") - print(df_related_queries.to_string(index=False)) - print("") + pytrend = TrendReq() + pytrend.build_payload(kw_list=[s_ticker]) + df_related_queries = pytrend.related_queries() + df_related_queries = df_related_queries[s_ticker]['top'].head(ns_parser.n_num) + df_related_queries['value'] = df_related_queries['value'].apply(lambda x: str(x)+'%') + print(f"Top {s_ticker}'s related queries") + print(df_related_queries.to_string(index=False)) + print("") - except: - print("") # ------------------------------------------------------------------------------------------------------------------- @@ -113,21 +103,16 @@ def rise(l_args, s_ticker): parser.add_argument('-n', "--num", action="store", dest="n_num", type=check_positive, default=10, help='number of top rising related queries to print.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return - - pytrend = TrendReq() - pytrend.build_payload(kw_list=[s_ticker]) - df_related_queries = pytrend.related_queries() - df_related_queries = df_related_queries[s_ticker]['rising'].head(ns_parser.n_num) - print(f"Top rising {s_ticker}'s related queries") - print(df_related_queries.to_string(index=False)) - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") + return + pytrend = TrendReq() + pytrend.build_payload(kw_list=[s_ticker]) + df_related_queries = pytrend.related_queries() + df_related_queries = df_related_queries[s_ticker]['rising'].head(ns_parser.n_num) + print(f"Top rising {s_ticker}'s related queries") + print(df_related_queries.to_string(index=False)) + print("") diff --git a/sentiment/reddit_api.py b/sentiment/reddit_api.py index 348908adfb5..5408b1fbef4 100644 --- a/sentiment/reddit_api.py +++ b/sentiment/reddit_api.py @@ -35,139 +35,136 @@ def watchlist(l_args): parser.add_argument('-l', "--limit", action="store", dest="n_limit", type=check_positive, default=5, help='limit of posts with watchlists retrieved.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - l_sub_reddits = ['pennystocks', 'RobinHoodPennyStocks', 'Daytrading', 'StockMarket', 'stocks', 'investing', 'wallstreetbets'] + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") + return - d_submission = {} - d_watchlist_tickers = {} - l_watchlist_links = list() - l_watchlist_author = list() - ls_text = list() + l_sub_reddits = ['pennystocks', 'RobinHoodPennyStocks', 'Daytrading', 'StockMarket', 'stocks', 'investing', 'wallstreetbets'] - praw_api = praw.Reddit(client_id=cfg.API_REDDIT_CLIENT_ID, - client_secret=cfg.API_REDDIT_CLIENT_SECRET, - username=cfg.API_REDDIT_USERNAME, - user_agent=cfg.API_REDDIT_USER_AGENT, - password=cfg.API_REDDIT_PASSWORD) + d_submission = {} + d_watchlist_tickers = {} + l_watchlist_links = list() + l_watchlist_author = list() + ls_text = list() - dt_last_time_market_close = get_last_time_market_was_open(datetime.now()-timedelta(hours=24)) - n_ts_after = int(dt_last_time_market_close.timestamp()) - psaw_api = PushshiftAPI() - submissions = psaw_api.search_submissions(after=n_ts_after, - subreddit=l_sub_reddits, - q='WATCHLIST|Watchlist|watchlist', - filter=['id']) + praw_api = praw.Reddit(client_id=cfg.API_REDDIT_CLIENT_ID, + client_secret=cfg.API_REDDIT_CLIENT_SECRET, + username=cfg.API_REDDIT_USERNAME, + user_agent=cfg.API_REDDIT_USER_AGENT, + password=cfg.API_REDDIT_PASSWORD) - n_flair_posts_found = 0 - while True: - submission = next(submissions, None) - if submission: - # Get more information about post using PRAW api - submission = praw_api.submission(id=submission.id) + dt_last_time_market_close = get_last_time_market_was_open(datetime.now()-timedelta(hours=24)) + n_ts_after = int(dt_last_time_market_close.timestamp()) + psaw_api = PushshiftAPI() + submissions = psaw_api.search_submissions(after=n_ts_after, + subreddit=l_sub_reddits, + q='WATCHLIST|Watchlist|watchlist', + filter=['id']) - # Ensure that the post hasn't been removed by moderator in the meanwhile, - #that there is a description and it's not just an image, that the flair is - #meaningful, and that we aren't re-considering same author's watchlist - if not submission.removed_by_category and submission.selftext \ - and submission.link_flair_text not in ['Yolo', 'Meme'] \ - and submission.author.name not in l_watchlist_author: - ls_text = list() - ls_text.append(submission.selftext) - ls_text.append(submission.title) + n_flair_posts_found = 0 + while True: + submission = next(submissions, None) + if submission: + # Get more information about post using PRAW api + submission = praw_api.submission(id=submission.id) - submission.comments.replace_more(limit=0) - for comment in submission.comments.list(): - ls_text.append(comment.body) + # Ensure that the post hasn't been removed by moderator in the meanwhile, + #that there is a description and it's not just an image, that the flair is + #meaningful, and that we aren't re-considering same author's watchlist + if not submission.removed_by_category and submission.selftext \ + and submission.link_flair_text not in ['Yolo', 'Meme'] \ + and submission.author.name not in l_watchlist_author: + ls_text = list() + ls_text.append(submission.selftext) + ls_text.append(submission.title) - l_tickers_found = list() - for s_text in ls_text: - for s_ticker in set(re.findall(r'([A-Z]{3,5} )', s_text)): - l_tickers_found.append(s_ticker.strip()) + submission.comments.replace_more(limit=0) + for comment in submission.comments.list(): + ls_text.append(comment.body) - if l_tickers_found: - # Add another author's name to the parsed watchlists - l_watchlist_author.append(submission.author.name) + l_tickers_found = list() + for s_text in ls_text: + for s_ticker in set(re.findall(r'([A-Z]{3,5} )', s_text)): + l_tickers_found.append(s_ticker.strip()) - # Lookup stock tickers within a watchlist - for key in l_tickers_found: - if key in d_watchlist_tickers: - # Increment stock ticker found - d_watchlist_tickers[key] += 1 - else: - # Initialize stock ticker found - d_watchlist_tickers[key] = 1 + if l_tickers_found: + # Add another author's name to the parsed watchlists + l_watchlist_author.append(submission.author.name) - l_watchlist_links.append(f"https://www.reddit.com{submission.permalink}") - # delete below, not necessary I reckon. Probably just link? + # Lookup stock tickers within a watchlist + for key in l_tickers_found: + if key in d_watchlist_tickers: + # Increment stock ticker found + d_watchlist_tickers[key] += 1 + else: + # Initialize stock ticker found + d_watchlist_tickers[key] = 1 - # Refactor data - s_datetime = datetime.utcfromtimestamp(submission.created_utc).strftime("%d/%m/%Y %H:%M:%S") - s_link = f"https://www.reddit.com{submission.permalink}" - s_all_awards = "" - for award in submission.all_awardings: - s_all_awards += f"{award['count']} {award['name']}\n" - s_all_awards = s_all_awards[:-2] + l_watchlist_links.append(f"https://www.reddit.com{submission.permalink}") + # delete below, not necessary I reckon. Probably just link? - # Create dictionary with data to construct dataframe allows to save data - d_submission[submission.id] = { - 'created_utc': s_datetime, - 'subreddit': submission.subreddit, - 'link_flair_text': submission.link_flair_text, - 'title':submission.title, - 'score': submission.score, - 'link': s_link, - 'num_comments': submission.num_comments, - 'upvote_ratio': submission.upvote_ratio, - 'awards': s_all_awards - } + # Refactor data + s_datetime = datetime.utcfromtimestamp(submission.created_utc).strftime("%d/%m/%Y %H:%M:%S") + s_link = f"https://www.reddit.com{submission.permalink}" + s_all_awards = "" + for award in submission.all_awardings: + s_all_awards += f"{award['count']} {award['name']}\n" + s_all_awards = s_all_awards[:-2] - # Print post data collected so far - print(f"\n{s_datetime} - {submission.title}") - print(f"{s_link}") - t_post = PrettyTable(['Subreddit', 'Flair', 'Score', '# Comments', 'Upvote %', "Awards"]) - t_post.add_row([submission.subreddit, submission.link_flair_text, submission.score, - submission.num_comments,f"{round(100*submission.upvote_ratio)}%", s_all_awards]) - print(t_post) - print("") + # Create dictionary with data to construct dataframe allows to save data + d_submission[submission.id] = { + 'created_utc': s_datetime, + 'subreddit': submission.subreddit, + 'link_flair_text': submission.link_flair_text, + 'title':submission.title, + 'score': submission.score, + 'link': s_link, + 'num_comments': submission.num_comments, + 'upvote_ratio': submission.upvote_ratio, + 'awards': s_all_awards + } - # Increment count of valid posts found - n_flair_posts_found += 1 + # Print post data collected so far + print(f"\n{s_datetime} - {submission.title}") + print(f"{s_link}") + t_post = PrettyTable(['Subreddit', 'Flair', 'Score', '# Comments', 'Upvote %', "Awards"]) + t_post.add_row([submission.subreddit, submission.link_flair_text, submission.score, + submission.num_comments,f"{round(100*submission.upvote_ratio)}%", s_all_awards]) + print(t_post) + print("") - # Check if number of wanted posts found has been reached - if n_flair_posts_found > ns_parser.n_limit-1: - break + # Increment count of valid posts found + n_flair_posts_found += 1 - # Check if search_submissions didn't get anymore posts - else: + # Check if number of wanted posts found has been reached + if n_flair_posts_found > ns_parser.n_limit-1: break - if n_flair_posts_found: - lt_watchlist_sorted = sorted(d_watchlist_tickers.items(), key=lambda item: item[1], reverse=True) - s_watchlist_tickers = "" - n_tickers = 0 - for t_ticker in lt_watchlist_sorted: - try: - # If try doesn't trigger exception, it means that this stock exists on finviz - #thus we can print it. - finviz.get_stock(t_ticker[0]) - if int(t_ticker[1]) > 1: - s_watchlist_tickers += f"{t_ticker[1]} {t_ticker[0]}, " - n_tickers += 1 - except: - pass - if n_tickers: - print("The following stock tickers have been mentioned more than once across the previous watchlists:") - print(s_watchlist_tickers[:-2]+'\n') - print("") + # Check if search_submissions didn't get anymore posts + else: + break - except: - print("") + if n_flair_posts_found: + lt_watchlist_sorted = sorted(d_watchlist_tickers.items(), key=lambda item: item[1], reverse=True) + s_watchlist_tickers = "" + n_tickers = 0 + for t_ticker in lt_watchlist_sorted: + try: + # If try doesn't trigger exception, it means that this stock exists on finviz + #thus we can print it. + finviz.get_stock(t_ticker[0]) + if int(t_ticker[1]) > 1: + s_watchlist_tickers += f"{t_ticker[1]} {t_ticker[0]}, " + n_tickers += 1 + except: + pass + if n_tickers: + print("The following stock tickers have been mentioned more than once across the previous watchlists:") + print(s_watchlist_tickers[:-2]+'\n') + print("") # ------------------------------------------------------------------------------------------------------------------- @@ -182,110 +179,106 @@ def popular_tickers(l_args): parser.add_argument('-d', "--days", action="store", dest="n_days", type=check_positive, default=1, help="look for the tickers from those n past days.") - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") + return - n_ts_after = int((datetime.today() - timedelta(days=ns_parser.n_days)).timestamp()) + n_ts_after = int((datetime.today() - timedelta(days=ns_parser.n_days)).timestamp()) - if ns_parser.s_subreddit: - if ',' in ns_parser.s_subreddit: - l_sub_reddits = ns_parser.s_subreddit.split(',') + if ns_parser.s_subreddit: + if ',' in ns_parser.s_subreddit: + l_sub_reddits = ns_parser.s_subreddit.split(',') + else: + l_sub_reddits = [ns_parser.s_subreddit] + else: + l_sub_reddits = ['pennystocks', 'RobinHoodPennyStocks', 'Daytrading', 'StockMarket', 'stocks', 'investing', 'wallstreetbets'] + + d_submission = {} + d_watchlist_tickers = {} + l_watchlist_links = list() + l_watchlist_author = list() + + praw_api = praw.Reddit(client_id=cfg.API_REDDIT_CLIENT_ID, + client_secret=cfg.API_REDDIT_CLIENT_SECRET, + username=cfg.API_REDDIT_USERNAME, + user_agent=cfg.API_REDDIT_USER_AGENT, + password=cfg.API_REDDIT_PASSWORD) + + psaw_api = PushshiftAPI() + + for s_sub_reddit in l_sub_reddits: + print(f"Search for latest tickers under {ns_parser.n_limit} '{s_sub_reddit}' posts") + submissions = psaw_api.search_submissions(after=int(n_ts_after), + subreddit=s_sub_reddit, + limit=ns_parser.n_limit, + filter=['id']) + + n_tickers = 0 + while True: + submission = next(submissions, None) + if submission: + # Get more information about post using PRAW api + submission = praw_api.submission(id=submission.id) + + # Ensure that the post hasn't been removed by moderator in the meanwhile, + #that there is a description and it's not just an image, that the flair is + #meaningful, and that we aren't re-considering same author's content + if not submission.removed_by_category and (submission.selftext or submission.title) \ + and submission.author.name not in l_watchlist_author: + ls_text = list() + ls_text.append(submission.selftext) + ls_text.append(submission.title) + + submission.comments.replace_more(limit=0) + for comment in submission.comments.list(): + ls_text.append(comment.body) + + l_tickers_found = list() + for s_text in ls_text: + for s_ticker in set(re.findall(r'([A-Z]{3,5} )', s_text)): + l_tickers_found.append(s_ticker.strip()) + + if l_tickers_found: + n_tickers += len(l_tickers_found) + + # Add another author's name to the parsed watchlists + l_watchlist_author.append(submission.author.name) + + # Lookup stock tickers within a watchlist + for key in l_tickers_found: + if key in d_watchlist_tickers: + # Increment stock ticker found + d_watchlist_tickers[key] += 1 + else: + # Initialize stock ticker found + d_watchlist_tickers[key] = 1 + + # Check if search_submissions didn't get anymore posts else: - l_sub_reddits = [ns_parser.s_subreddit] - else: - l_sub_reddits = ['pennystocks', 'RobinHoodPennyStocks', 'Daytrading', 'StockMarket', 'stocks', 'investing', 'wallstreetbets'] + break - d_submission = {} - d_watchlist_tickers = {} - l_watchlist_links = list() - l_watchlist_author = list() + print(f" {n_tickers} tickers found.") - praw_api = praw.Reddit(client_id=cfg.API_REDDIT_CLIENT_ID, - client_secret=cfg.API_REDDIT_CLIENT_SECRET, - username=cfg.API_REDDIT_USERNAME, - user_agent=cfg.API_REDDIT_USER_AGENT, - password=cfg.API_REDDIT_PASSWORD) - - psaw_api = PushshiftAPI() - - for s_sub_reddit in l_sub_reddits: - print(f"Search for latest tickers under {ns_parser.n_limit} '{s_sub_reddit}' posts") - submissions = psaw_api.search_submissions(after=int(n_ts_after), - subreddit=s_sub_reddit, - limit=ns_parser.n_limit, - filter=['id']) - - n_tickers = 0 - while True: - submission = next(submissions, None) - if submission: - # Get more information about post using PRAW api - submission = praw_api.submission(id=submission.id) - - # Ensure that the post hasn't been removed by moderator in the meanwhile, - #that there is a description and it's not just an image, that the flair is - #meaningful, and that we aren't re-considering same author's content - if not submission.removed_by_category and (submission.selftext or submission.title) \ - and submission.author.name not in l_watchlist_author: - ls_text = list() - ls_text.append(submission.selftext) - ls_text.append(submission.title) - - submission.comments.replace_more(limit=0) - for comment in submission.comments.list(): - ls_text.append(comment.body) - - l_tickers_found = list() - for s_text in ls_text: - for s_ticker in set(re.findall(r'([A-Z]{3,5} )', s_text)): - l_tickers_found.append(s_ticker.strip()) - - if l_tickers_found: - n_tickers += len(l_tickers_found) - - # Add another author's name to the parsed watchlists - l_watchlist_author.append(submission.author.name) - - # Lookup stock tickers within a watchlist - for key in l_tickers_found: - if key in d_watchlist_tickers: - # Increment stock ticker found - d_watchlist_tickers[key] += 1 - else: - # Initialize stock ticker found - d_watchlist_tickers[key] = 1 - - # Check if search_submissions didn't get anymore posts - else: - break - - print(f" {n_tickers} tickers found.") - - lt_watchlist_sorted = sorted(d_watchlist_tickers.items(), key=lambda item: item[1], reverse=True) - if lt_watchlist_sorted: - print(f"\nThe following TOP10 tickers have been mentioned in the last {ns_parser.n_days} days:") - n_top_stocks = 0 - for t_ticker in lt_watchlist_sorted: - if n_top_stocks > 9: - break - try: - # If try doesn't trigger exception, it means that this stock exists on finviz - #thus we can print it. - finviz.get_stock(t_ticker[0]) - print(f"{t_ticker[1]} {t_ticker[0]}") - n_top_stocks += 1 - except: - pass - else: - print("No tickers found") - print("") - - except: - print("") + lt_watchlist_sorted = sorted(d_watchlist_tickers.items(), key=lambda item: item[1], reverse=True) + if lt_watchlist_sorted: + print(f"\nThe following TOP10 tickers have been mentioned in the last {ns_parser.n_days} days:") + n_top_stocks = 0 + for t_ticker in lt_watchlist_sorted: + if n_top_stocks > 9: + break + try: + # If try doesn't trigger exception, it means that this stock exists on finviz + #thus we can print it. + finviz.get_stock(t_ticker[0]) + print(f"{t_ticker[1]} {t_ticker[0]}") + n_top_stocks += 1 + except: + pass + else: + print("No tickers found") + print("") # ------------------------------------------------------------------------------------------------------------------- @@ -297,127 +290,123 @@ def spac_community(l_args): parser.add_argument('-p', "--popular", action="store_true", default=False, dest="b_popular", help='popular flag, if true the posts retrieved are based on score rather than time') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") + return - praw_api = praw.Reddit(client_id=cfg.API_REDDIT_CLIENT_ID, - client_secret=cfg.API_REDDIT_CLIENT_SECRET, - username=cfg.API_REDDIT_USERNAME, - user_agent=cfg.API_REDDIT_USER_AGENT, - password=cfg.API_REDDIT_PASSWORD) + praw_api = praw.Reddit(client_id=cfg.API_REDDIT_CLIENT_ID, + client_secret=cfg.API_REDDIT_CLIENT_SECRET, + username=cfg.API_REDDIT_USERNAME, + user_agent=cfg.API_REDDIT_USER_AGENT, + password=cfg.API_REDDIT_PASSWORD) - d_submission = {} - d_watchlist_tickers = {} - l_watchlist_links = list() - l_watchlist_author = list() + d_submission = {} + d_watchlist_tickers = {} + l_watchlist_links = list() + l_watchlist_author = list() - psaw_api = PushshiftAPI() + psaw_api = PushshiftAPI() - if ns_parser.b_popular: - submissions = praw_api.subreddit('SPACs').hot(limit=ns_parser.n_limit) + if ns_parser.b_popular: + submissions = praw_api.subreddit('SPACs').hot(limit=ns_parser.n_limit) + else: + submissions = praw_api.subreddit('SPACs').new(limit=ns_parser.n_limit) + + while True: + submission = next(submissions, None) + if submission: + # Get more information about post using PRAW api + submission = praw_api.submission(id=submission.id) + + # Ensure that the post hasn't been removed by moderator in the meanwhile, + #that there is a description and it's not just an image, that the flair is + #meaningful, and that we aren't re-considering same author's watchlist + if not submission.removed_by_category and submission.selftext \ + and submission.link_flair_text not in ['Yolo', 'Meme'] \ + and submission.author.name not in l_watchlist_author: + ls_text = list() + ls_text.append(submission.selftext) + ls_text.append(submission.title) + + submission.comments.replace_more(limit=0) + for comment in submission.comments.list(): + ls_text.append(comment.body) + + l_tickers_found = list() + for s_text in ls_text: + for s_ticker in set(re.findall(r'([A-Z]{3,5} )', s_text)): + l_tickers_found.append(s_ticker.strip()) + + if l_tickers_found: + # Add another author's name to the parsed watchlists + l_watchlist_author.append(submission.author.name) + + # Lookup stock tickers within a watchlist + for key in l_tickers_found: + if key in d_watchlist_tickers: + # Increment stock ticker found + d_watchlist_tickers[key] += 1 + else: + # Initialize stock ticker found + d_watchlist_tickers[key] = 1 + + l_watchlist_links.append(f"https://www.reddit.com{submission.permalink}") + # delete below, not necessary I reckon. Probably just link? + + # Refactor data + s_datetime = datetime.utcfromtimestamp(submission.created_utc).strftime("%d/%m/%Y %H:%M:%S") + s_link = f"https://www.reddit.com{submission.permalink}" + s_all_awards = "" + for award in submission.all_awardings: + s_all_awards += f"{award['count']} {award['name']}\n" + s_all_awards = s_all_awards[:-2] + + # Create dictionary with data to construct dataframe allows to save data + d_submission[submission.id] = { + 'created_utc': s_datetime, + 'subreddit': submission.subreddit, + 'link_flair_text': submission.link_flair_text, + 'title':submission.title, + 'score': submission.score, + 'link': s_link, + 'num_comments': submission.num_comments, + 'upvote_ratio': submission.upvote_ratio, + 'awards': s_all_awards + } + + # Print post data collected so far + print(f"{s_datetime} - {submission.title}") + print(f"{s_link}") + t_post = PrettyTable(['Subreddit', 'Flair', 'Score', '# Comments', 'Upvote %', "Awards"]) + t_post.add_row([submission.subreddit, submission.link_flair_text, submission.score, + submission.num_comments,f"{round(100*submission.upvote_ratio)}%", s_all_awards]) + print(t_post) + print("\n") + + # Check if search_submissions didn't get anymore posts else: - submissions = praw_api.subreddit('SPACs').new(limit=ns_parser.n_limit) + break - while True: - submission = next(submissions, None) - if submission: - # Get more information about post using PRAW api - submission = praw_api.submission(id=submission.id) - - # Ensure that the post hasn't been removed by moderator in the meanwhile, - #that there is a description and it's not just an image, that the flair is - #meaningful, and that we aren't re-considering same author's watchlist - if not submission.removed_by_category and submission.selftext \ - and submission.link_flair_text not in ['Yolo', 'Meme'] \ - and submission.author.name not in l_watchlist_author: - ls_text = list() - ls_text.append(submission.selftext) - ls_text.append(submission.title) - - submission.comments.replace_more(limit=0) - for comment in submission.comments.list(): - ls_text.append(comment.body) - - l_tickers_found = list() - for s_text in ls_text: - for s_ticker in set(re.findall(r'([A-Z]{3,5} )', s_text)): - l_tickers_found.append(s_ticker.strip()) - - if l_tickers_found: - # Add another author's name to the parsed watchlists - l_watchlist_author.append(submission.author.name) - - # Lookup stock tickers within a watchlist - for key in l_tickers_found: - if key in d_watchlist_tickers: - # Increment stock ticker found - d_watchlist_tickers[key] += 1 - else: - # Initialize stock ticker found - d_watchlist_tickers[key] = 1 - - l_watchlist_links.append(f"https://www.reddit.com{submission.permalink}") - # delete below, not necessary I reckon. Probably just link? - - # Refactor data - s_datetime = datetime.utcfromtimestamp(submission.created_utc).strftime("%d/%m/%Y %H:%M:%S") - s_link = f"https://www.reddit.com{submission.permalink}" - s_all_awards = "" - for award in submission.all_awardings: - s_all_awards += f"{award['count']} {award['name']}\n" - s_all_awards = s_all_awards[:-2] - - # Create dictionary with data to construct dataframe allows to save data - d_submission[submission.id] = { - 'created_utc': s_datetime, - 'subreddit': submission.subreddit, - 'link_flair_text': submission.link_flair_text, - 'title':submission.title, - 'score': submission.score, - 'link': s_link, - 'num_comments': submission.num_comments, - 'upvote_ratio': submission.upvote_ratio, - 'awards': s_all_awards - } - - # Print post data collected so far - print(f"{s_datetime} - {submission.title}") - print(f"{s_link}") - t_post = PrettyTable(['Subreddit', 'Flair', 'Score', '# Comments', 'Upvote %', "Awards"]) - t_post.add_row([submission.subreddit, submission.link_flair_text, submission.score, - submission.num_comments,f"{round(100*submission.upvote_ratio)}%", s_all_awards]) - print(t_post) - print("\n") - - # Check if search_submissions didn't get anymore posts - else: - break - - if d_watchlist_tickers: - lt_watchlist_sorted = sorted(d_watchlist_tickers.items(), key=lambda item: item[1], reverse=True) - s_watchlist_tickers = "" - n_tickers = 0 - for t_ticker in lt_watchlist_sorted: - try: - # If try doesn't trigger exception, it means that this stock exists on finviz - #thus we can print it. - finviz.get_stock(t_ticker[0]) - if int(t_ticker[1]) > 1: - s_watchlist_tickers += f"{t_ticker[1]} {t_ticker[0]}, " - n_tickers += 1 - except: - pass - if n_tickers: - print("The following stock tickers have been mentioned more than once across the previous SPACs:") - print(s_watchlist_tickers[:-2]) - print("") - - except: - print("") + if d_watchlist_tickers: + lt_watchlist_sorted = sorted(d_watchlist_tickers.items(), key=lambda item: item[1], reverse=True) + s_watchlist_tickers = "" + n_tickers = 0 + for t_ticker in lt_watchlist_sorted: + try: + # If try doesn't trigger exception, it means that this stock exists on finviz + #thus we can print it. + finviz.get_stock(t_ticker[0]) + if int(t_ticker[1]) > 1: + s_watchlist_tickers += f"{t_ticker[1]} {t_ticker[0]}, " + n_tickers += 1 + except: + pass + if n_tickers: + print("The following stock tickers have been mentioned more than once across the previous SPACs:") + print(s_watchlist_tickers[:-2]) + print("") # ------------------------------------------------------------------------------------------------------------------- @@ -429,138 +418,134 @@ def spac(l_args): parser.add_argument('-d', "--days", action="store", dest="n_days", type=check_positive, default=5, help="look for the tickers from those n past days.") - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") + return - praw_api = praw.Reddit(client_id=cfg.API_REDDIT_CLIENT_ID, - client_secret=cfg.API_REDDIT_CLIENT_SECRET, - username=cfg.API_REDDIT_USERNAME, - user_agent=cfg.API_REDDIT_USER_AGENT, - password=cfg.API_REDDIT_PASSWORD) + praw_api = praw.Reddit(client_id=cfg.API_REDDIT_CLIENT_ID, + client_secret=cfg.API_REDDIT_CLIENT_SECRET, + username=cfg.API_REDDIT_USERNAME, + user_agent=cfg.API_REDDIT_USER_AGENT, + password=cfg.API_REDDIT_PASSWORD) - d_submission = {} - d_watchlist_tickers = {} - l_watchlist_links = list() - l_watchlist_author = list() + d_submission = {} + d_watchlist_tickers = {} + l_watchlist_links = list() + l_watchlist_author = list() - n_ts_after = int((datetime.today() - timedelta(days=ns_parser.n_days)).timestamp()) - l_sub_reddits = ['pennystocks', 'RobinHoodPennyStocks', 'Daytrading', 'StockMarket', 'stocks', 'investing', 'wallstreetbets'] + n_ts_after = int((datetime.today() - timedelta(days=ns_parser.n_days)).timestamp()) + l_sub_reddits = ['pennystocks', 'RobinHoodPennyStocks', 'Daytrading', 'StockMarket', 'stocks', 'investing', 'wallstreetbets'] - warnings.filterwarnings("ignore") # To avoid printing the warning - psaw_api = PushshiftAPI() - submissions = psaw_api.search_submissions(after=n_ts_after, - subreddit=l_sub_reddits, - q='SPAC|Spac|spac|Spacs|spacs', - filter=['id']) - n_flair_posts_found = 0 - while True: - submission = next(submissions, None) - if submission: - # Get more information about post using PRAW api - submission = praw_api.submission(id=submission.id) + warnings.filterwarnings("ignore") # To avoid printing the warning + psaw_api = PushshiftAPI() + submissions = psaw_api.search_submissions(after=n_ts_after, + subreddit=l_sub_reddits, + q='SPAC|Spac|spac|Spacs|spacs', + filter=['id']) + n_flair_posts_found = 0 + while True: + submission = next(submissions, None) + if submission: + # Get more information about post using PRAW api + submission = praw_api.submission(id=submission.id) - # Ensure that the post hasn't been removed by moderator in the meanwhile, - #that there is a description and it's not just an image, that the flair is - #meaningful, and that we aren't re-considering same author's watchlist - if not submission.removed_by_category and submission.selftext \ - and submission.link_flair_text not in ['Yolo', 'Meme'] \ - and submission.author.name not in l_watchlist_author: + # Ensure that the post hasn't been removed by moderator in the meanwhile, + #that there is a description and it's not just an image, that the flair is + #meaningful, and that we aren't re-considering same author's watchlist + if not submission.removed_by_category and submission.selftext \ + and submission.link_flair_text not in ['Yolo', 'Meme'] \ + and submission.author.name not in l_watchlist_author: - ls_text = list() - ls_text.append(submission.selftext) - ls_text.append(submission.title) + ls_text = list() + ls_text.append(submission.selftext) + ls_text.append(submission.title) - submission.comments.replace_more(limit=0) - for comment in submission.comments.list(): - ls_text.append(comment.body) + submission.comments.replace_more(limit=0) + for comment in submission.comments.list(): + ls_text.append(comment.body) - l_tickers_found = list() - for s_text in ls_text: - for s_ticker in set(re.findall(r'([A-Z]{3,5} )', s_text)): - l_tickers_found.append(s_ticker.strip()) + l_tickers_found = list() + for s_text in ls_text: + for s_ticker in set(re.findall(r'([A-Z]{3,5} )', s_text)): + l_tickers_found.append(s_ticker.strip()) - if l_tickers_found: - # Add another author's name to the parsed watchlists - l_watchlist_author.append(submission.author.name) + if l_tickers_found: + # Add another author's name to the parsed watchlists + l_watchlist_author.append(submission.author.name) - # Lookup stock tickers within a watchlist - for key in l_tickers_found: - if key in d_watchlist_tickers: - # Increment stock ticker found - d_watchlist_tickers[key] += 1 - else: - # Initialize stock ticker found - d_watchlist_tickers[key] = 1 + # Lookup stock tickers within a watchlist + for key in l_tickers_found: + if key in d_watchlist_tickers: + # Increment stock ticker found + d_watchlist_tickers[key] += 1 + else: + # Initialize stock ticker found + d_watchlist_tickers[key] = 1 - l_watchlist_links.append(f"https://www.reddit.com{submission.permalink}") - # delete below, not necessary I reckon. Probably just link? + l_watchlist_links.append(f"https://www.reddit.com{submission.permalink}") + # delete below, not necessary I reckon. Probably just link? - # Refactor data - s_datetime = datetime.utcfromtimestamp(submission.created_utc).strftime("%d/%m/%Y %H:%M:%S") - s_link = f"https://www.reddit.com{submission.permalink}" - s_all_awards = "" - for award in submission.all_awardings: - s_all_awards += f"{award['count']} {award['name']}\n" - s_all_awards = s_all_awards[:-2] + # Refactor data + s_datetime = datetime.utcfromtimestamp(submission.created_utc).strftime("%d/%m/%Y %H:%M:%S") + s_link = f"https://www.reddit.com{submission.permalink}" + s_all_awards = "" + for award in submission.all_awardings: + s_all_awards += f"{award['count']} {award['name']}\n" + s_all_awards = s_all_awards[:-2] - # Create dictionary with data to construct dataframe allows to save data - d_submission[submission.id] = { - 'created_utc': s_datetime, - 'subreddit': submission.subreddit, - 'link_flair_text': submission.link_flair_text, - 'title':submission.title, - 'score': submission.score, - 'link': s_link, - 'num_comments': submission.num_comments, - 'upvote_ratio': submission.upvote_ratio, - 'awards': s_all_awards - } + # Create dictionary with data to construct dataframe allows to save data + d_submission[submission.id] = { + 'created_utc': s_datetime, + 'subreddit': submission.subreddit, + 'link_flair_text': submission.link_flair_text, + 'title':submission.title, + 'score': submission.score, + 'link': s_link, + 'num_comments': submission.num_comments, + 'upvote_ratio': submission.upvote_ratio, + 'awards': s_all_awards + } - # Print post data collected so far - print(f"{s_datetime} - {submission.title}") - print(f"{s_link}") - t_post = PrettyTable(['Subreddit', 'Flair', 'Score', '# Comments', 'Upvote %', "Awards"]) - t_post.add_row([submission.subreddit, submission.link_flair_text, submission.score, - submission.num_comments,f"{round(100*submission.upvote_ratio)}%", s_all_awards]) - print(t_post) - print("\n") + # Print post data collected so far + print(f"{s_datetime} - {submission.title}") + print(f"{s_link}") + t_post = PrettyTable(['Subreddit', 'Flair', 'Score', '# Comments', 'Upvote %', "Awards"]) + t_post.add_row([submission.subreddit, submission.link_flair_text, submission.score, + submission.num_comments,f"{round(100*submission.upvote_ratio)}%", s_all_awards]) + print(t_post) + print("\n") - # Increment count of valid posts found - n_flair_posts_found += 1 + # Increment count of valid posts found + n_flair_posts_found += 1 - # Check if number of wanted posts found has been reached - if n_flair_posts_found > ns_parser.n_limit-1: - break - - # Check if search_submissions didn't get anymore posts - else: + # Check if number of wanted posts found has been reached + if n_flair_posts_found > ns_parser.n_limit-1: break - if n_flair_posts_found: - lt_watchlist_sorted = sorted(d_watchlist_tickers.items(), key=lambda item: item[1], reverse=True) - s_watchlist_tickers = "" - n_tickers = 0 - for t_ticker in lt_watchlist_sorted: - try: - # If try doesn't trigger exception, it means that this stock exists on finviz - #thus we can print it. - finviz.get_stock(t_ticker[0]) - if int(t_ticker[1]) > 1: - s_watchlist_tickers += f"{t_ticker[1]} {t_ticker[0]}, " - n_tickers += 1 - except: - pass - if n_tickers: - print("The following stock tickers have been mentioned more than once across the previous SPACs:") - print(s_watchlist_tickers[:-2]) - print("") + # Check if search_submissions didn't get anymore posts + else: + break - except: - print("") + if n_flair_posts_found: + lt_watchlist_sorted = sorted(d_watchlist_tickers.items(), key=lambda item: item[1], reverse=True) + s_watchlist_tickers = "" + n_tickers = 0 + for t_ticker in lt_watchlist_sorted: + try: + # If try doesn't trigger exception, it means that this stock exists on finviz + #thus we can print it. + finviz.get_stock(t_ticker[0]) + if int(t_ticker[1]) > 1: + s_watchlist_tickers += f"{t_ticker[1]} {t_ticker[0]}, " + n_tickers += 1 + except: + pass + if n_tickers: + print("The following stock tickers have been mentioned more than once across the previous SPACs:") + print(s_watchlist_tickers[:-2]) + print("") # ------------------------------------------------------------------------------------------------------------------- @@ -572,74 +557,68 @@ def wsb_community(l_args): parser.add_argument('-n', "--new", action="store_true", default=False, dest="b_new", help='new flag, if true the posts retrieved are based on being more recent rather than their score.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") + return - praw_api = praw.Reddit(client_id=cfg.API_REDDIT_CLIENT_ID, - client_secret=cfg.API_REDDIT_CLIENT_SECRET, - username=cfg.API_REDDIT_USERNAME, - user_agent=cfg.API_REDDIT_USER_AGENT, - password=cfg.API_REDDIT_PASSWORD) + praw_api = praw.Reddit(client_id=cfg.API_REDDIT_CLIENT_ID, + client_secret=cfg.API_REDDIT_CLIENT_SECRET, + username=cfg.API_REDDIT_USERNAME, + user_agent=cfg.API_REDDIT_USER_AGENT, + password=cfg.API_REDDIT_PASSWORD) - d_submission = {} - l_watchlist_links = list() + d_submission = {} + l_watchlist_links = list() - psaw_api = PushshiftAPI() + psaw_api = PushshiftAPI() - if ns_parser.b_new: - submissions = praw_api.subreddit('wallstreetbets').new(limit=ns_parser.n_limit) - else: - submissions = praw_api.subreddit('wallstreetbets').hot(limit=ns_parser.n_limit) + if ns_parser.b_new: + submissions = praw_api.subreddit('wallstreetbets').new(limit=ns_parser.n_limit) + else: + submissions = praw_api.subreddit('wallstreetbets').hot(limit=ns_parser.n_limit) - while True: - submission = next(submissions, None) - if submission: - # Get more information about post using PRAW api - submission = praw_api.submission(id=submission.id) + while True: + submission = next(submissions, None) + if submission: + # Get more information about post using PRAW api + submission = praw_api.submission(id=submission.id) - # Ensure that the post hasn't been removed by moderator in the meanwhile, - #that there is a description and it's not just an image, that the flair is - #meaningful, and that we aren't re-considering same author's watchlist - if not submission.removed_by_category: + # Ensure that the post hasn't been removed by moderator in the meanwhile, + #that there is a description and it's not just an image, that the flair is + #meaningful, and that we aren't re-considering same author's watchlist + if not submission.removed_by_category: - l_watchlist_links.append(f"https://www.reddit.com{submission.permalink}") + l_watchlist_links.append(f"https://www.reddit.com{submission.permalink}") - # Refactor data - s_datetime = datetime.utcfromtimestamp(submission.created_utc).strftime("%d/%m/%Y %H:%M:%S") - s_link = f"https://www.reddit.com{submission.permalink}" - s_all_awards = "" - for award in submission.all_awardings: - s_all_awards += f"{award['count']} {award['name']}\n" - s_all_awards = s_all_awards[:-2] + # Refactor data + s_datetime = datetime.utcfromtimestamp(submission.created_utc).strftime("%d/%m/%Y %H:%M:%S") + s_link = f"https://www.reddit.com{submission.permalink}" + s_all_awards = "" + for award in submission.all_awardings: + s_all_awards += f"{award['count']} {award['name']}\n" + s_all_awards = s_all_awards[:-2] - # Create dictionary with data to construct dataframe allows to save data - d_submission[submission.id] = { - 'created_utc': s_datetime, - 'subreddit': submission.subreddit, - 'link_flair_text': submission.link_flair_text, - 'title':submission.title, - 'score': submission.score, - 'link': s_link, - 'num_comments': submission.num_comments, - 'upvote_ratio': submission.upvote_ratio, - 'awards': s_all_awards - } + # Create dictionary with data to construct dataframe allows to save data + d_submission[submission.id] = { + 'created_utc': s_datetime, + 'subreddit': submission.subreddit, + 'link_flair_text': submission.link_flair_text, + 'title':submission.title, + 'score': submission.score, + 'link': s_link, + 'num_comments': submission.num_comments, + 'upvote_ratio': submission.upvote_ratio, + 'awards': s_all_awards + } - # Print post data collected so far - print(f"{s_datetime} - {submission.title}") - print(f"{s_link}") - t_post = PrettyTable(['Subreddit', 'Flair', 'Score', '# Comments', 'Upvote %', "Awards"]) - t_post.add_row([submission.subreddit, submission.link_flair_text, submission.score, - submission.num_comments,f"{round(100*submission.upvote_ratio)}%", s_all_awards]) - print(t_post) - print("") - # Check if search_submissions didn't get anymore posts - else: - break - print("") - except: + # Print post data collected so far + print(f"{s_datetime} - {submission.title}") + print(f"{s_link}") + t_post = PrettyTable(['Subreddit', 'Flair', 'Score', '# Comments', 'Upvote %', "Awards"]) + t_post.add_row([submission.subreddit, submission.link_flair_text, submission.score, + submission.num_comments,f"{round(100*submission.upvote_ratio)}%", s_all_awards]) + print(t_post) + print("") print("") diff --git a/sentiment/stocktwits_api.py b/sentiment/stocktwits_api.py index 378d79e7f75..153d9345fb7 100644 --- a/sentiment/stocktwits_api.py +++ b/sentiment/stocktwits_api.py @@ -15,34 +15,31 @@ def bullbear(l_args, s_ticker): parser.add_argument('-t', "--ticker", action="store", dest="s_ticker", type=str, default=s_ticker, help='ticker to gather sentiment from.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") + return - result = requests.get(f"https://api.stocktwits.com/api/2/streams/symbol/{ns_parser.s_ticker}.json") - if result.status_code == 200: - print(f"Watchlist count: {result.json()['symbol']['watchlist_count']}") - n_cases = 0 - n_bull = 0 - n_bear = 0 - for message in result.json()['messages']: - if (message['entities']['sentiment']): - n_cases += 1 - n_bull += (message['entities']['sentiment']['basic'] == 'Bullish') - n_bear += (message['entities']['sentiment']['basic'] == 'Bearish') - if n_cases > 0: - print(f"\nOver {n_cases} sentiment messages:") - print(f"Bullish {round(100*n_bull/n_cases, 2)}%") - print(f"Bearish {round(100*n_bear/n_cases, 2)}%") - else: - print("Invalid symbol") - print("") + result = requests.get(f"https://api.stocktwits.com/api/2/streams/symbol/{ns_parser.s_ticker}.json") + if result.status_code == 200: + print(f"Watchlist count: {result.json()['symbol']['watchlist_count']}") + n_cases = 0 + n_bull = 0 + n_bear = 0 + for message in result.json()['messages']: + if (message['entities']['sentiment']): + n_cases += 1 + n_bull += (message['entities']['sentiment']['basic'] == 'Bullish') + n_bear += (message['entities']['sentiment']['basic'] == 'Bearish') + if n_cases > 0: + print(f"\nOver {n_cases} sentiment messages:") + print(f"Bullish {round(100*n_bull/n_cases, 2)}%") + print(f"Bearish {round(100*n_bear/n_cases, 2)}%") + else: + print("Invalid symbol") + print("") - except: - print("") # ------------------------------------------------------------------------------------------------------------------- @@ -55,26 +52,23 @@ def messages(l_args, s_ticker): parser.add_argument('-l', "--limit", action="store", dest="n_lim", type=check_positive, default=30, help='limit messages shown.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") + return - result = requests.get(f"https://api.stocktwits.com/api/2/streams/symbol/{ns_parser.s_ticker}.json") - if result.status_code == 200: - for idx, message in enumerate(result.json()['messages']): - print("------------------------------------------------------------------------------------------") - print(message['body']) - if idx > ns_parser.n_lim-1: - break - else: - print("Invalid symbol") - print("") + result = requests.get(f"https://api.stocktwits.com/api/2/streams/symbol/{ns_parser.s_ticker}.json") + if result.status_code == 200: + for idx, message in enumerate(result.json()['messages']): + print("------------------------------------------------------------------------------------------") + print(message['body']) + if idx > ns_parser.n_lim-1: + break + else: + print("Invalid symbol") + print("") - except: - print("") # ------------------------------------------------------------------------------------------------------------------- @@ -82,28 +76,24 @@ def trending(l_args): parser = argparse.ArgumentParser(prog='trending', description="""Stocks trending. [Source: Stocktwits]""") - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") + return - result = requests.get(f"https://api.stocktwits.com/api/2/trending/symbols.json") - if result.status_code == 200: - l_symbols = list() - for symbol in result.json()['symbols']: - l_symbols.append([symbol['symbol'], symbol['watchlist_count'], symbol['title']]) + result = requests.get(f"https://api.stocktwits.com/api/2/trending/symbols.json") + if result.status_code == 200: + l_symbols = list() + for symbol in result.json()['symbols']: + l_symbols.append([symbol['symbol'], symbol['watchlist_count'], symbol['title']]) - pd.set_option('display.max_colwidth', -1) - df_trending = pd.DataFrame(l_symbols, columns=['Ticker', 'Watchlist Count', 'Name']) - print(df_trending.to_string(index=False)) - else: - print("Error!") - print("") - - except: - print("") + pd.set_option('display.max_colwidth', -1) + df_trending = pd.DataFrame(l_symbols, columns=['Ticker', 'Watchlist Count', 'Name']) + print(df_trending.to_string(index=False)) + else: + print("Error!") + print("") # ------------------------------------------------------------------------------------------------------------------- @@ -116,26 +106,22 @@ def stalker(l_args): parser.add_argument('-l', "--limit", action="store", dest="n_lim", type=check_positive, default=30, help='limit messages shown.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") + return - result = requests.get(f"https://api.stocktwits.com/api/2/streams/user/{ns_parser.s_user}.json") + result = requests.get(f"https://api.stocktwits.com/api/2/streams/user/{ns_parser.s_user}.json") - if result.status_code == 200: - for idx, message in enumerate(result.json()['messages']): - print("------------------------------------------------------------------------------------------") - print(message['created_at'].replace('T', ' ').replace('Z', '')) - print(message['body']) - print("") - if idx > ns_parser.n_lim-1: - break - else: - print("Invalid user") - print("") - - except: - print("") + if result.status_code == 200: + for idx, message in enumerate(result.json()['messages']): + print("------------------------------------------------------------------------------------------") + print(message['created_at'].replace('T', ' ').replace('Z', '')) + print(message['body']) + print("") + if idx > ns_parser.n_lim-1: + break + else: + print("Invalid user") + print("") diff --git a/sentiment/twitter_api.py b/sentiment/twitter_api.py index fedd06f5b06..11feda577a4 100644 --- a/sentiment/twitter_api.py +++ b/sentiment/twitter_api.py @@ -24,88 +24,85 @@ def inference(l_args, s_ticker): parser.add_argument('-n', "--num", action="store", dest="n_num", type=int, default=100, choices=range(10,101), help='num of latest tweets to infer from.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") + return - # Get tweets using Twitter API - params = { - 'q': '$'+s_ticker, - 'tweet_mode': 'extended', - 'lang': 'en', - 'count': str(ns_parser.n_num) - } + # Get tweets using Twitter API + params = { + 'q': '$'+s_ticker, + 'tweet_mode': 'extended', + 'lang': 'en', + 'count': str(ns_parser.n_num) + } - # Request Twitter API - response = requests.get('https://api.twitter.com/1.1/search/tweets.json', - params=params, - headers={'authorization': 'Bearer '+ cfg.API_TWITTER_BEARER_TOKEN}) + # Request Twitter API + response = requests.get('https://api.twitter.com/1.1/search/tweets.json', + params=params, + headers={'authorization': 'Bearer '+ cfg.API_TWITTER_BEARER_TOKEN}) - # Create dataframe - df_tweets = pd.DataFrame() + # Create dataframe + df_tweets = pd.DataFrame() - # Check that the API response was successful - if response.status_code == 200: - for tweet in response.json()['statuses']: - row = get_data(tweet) - df_tweets = df_tweets.append(row, ignore_index=True) + # Check that the API response was successful + if response.status_code == 200: + for tweet in response.json()['statuses']: + row = get_data(tweet) + df_tweets = df_tweets.append(row, ignore_index=True) - # Load sentiment model - sentiment_model = flair.models.TextClassifier.load('en-sentiment') - print("") + # Load sentiment model + sentiment_model = flair.models.TextClassifier.load('en-sentiment') + print("") - # We will append probability/sentiment preds later - probs = [] - sentiments = [] - for s_tweet in df_tweets['text'].to_list(): - tweet = clean_tweet(s_tweet, s_ticker) + # We will append probability/sentiment preds later + probs = [] + sentiments = [] + for s_tweet in df_tweets['text'].to_list(): + tweet = clean_tweet(s_tweet, s_ticker) - # Make sentiment prediction - sentence = flair.data.Sentence(tweet) - sentiment_model.predict(sentence) + # Make sentiment prediction + sentence = flair.data.Sentence(tweet) + sentiment_model.predict(sentence) - # Extract sentiment prediction (POSITIVE/NEGATIVE) and confidence (0-1) - probs.append(sentence.labels[0].score) - sentiments.append(sentence.labels[0].value) + # Extract sentiment prediction (POSITIVE/NEGATIVE) and confidence (0-1) + probs.append(sentence.labels[0].score) + sentiments.append(sentence.labels[0].value) - # Add probability and sentiment predictions to tweets dataframe - df_tweets['probability'] = probs - df_tweets['sentiment'] = sentiments + # Add probability and sentiment predictions to tweets dataframe + df_tweets['probability'] = probs + df_tweets['sentiment'] = sentiments - # Add sentiment estimation (probability positive for POSITIVE sentiment, and negative for NEGATIVE sentiment) - df_tweets['sentiment_estimation'] = df_tweets.apply(lambda row: row['probability']*(-1, 1)[row['sentiment']=='POSITIVE'], axis=1).cumsum() - # Cumulative sentiment_estimation - df_tweets['prob_sen'] = df_tweets.apply(lambda row: row['probability']*(-1, 1)[row['sentiment']=='POSITIVE'], axis=1) + # Add sentiment estimation (probability positive for POSITIVE sentiment, and negative for NEGATIVE sentiment) + df_tweets['sentiment_estimation'] = df_tweets.apply(lambda row: row['probability']*(-1, 1)[row['sentiment']=='POSITIVE'], axis=1).cumsum() + # Cumulative sentiment_estimation + df_tweets['prob_sen'] = df_tweets.apply(lambda row: row['probability']*(-1, 1)[row['sentiment']=='POSITIVE'], axis=1) - # Percentage of confidence - if df_tweets['sentiment_estimation'].values[-1] > 0: - n_pos = df_tweets[df_tweets['prob_sen']>0]['prob_sen'].sum() - n_pct = round(100*n_pos/df_tweets['probability'].sum()) - else: - n_neg = abs(df_tweets[df_tweets['prob_sen']<0]['prob_sen'].sum()) - n_pct = round(100*n_neg/df_tweets['probability'].sum()) + # Percentage of confidence + if df_tweets['sentiment_estimation'].values[-1] > 0: + n_pos = df_tweets[df_tweets['prob_sen']>0]['prob_sen'].sum() + n_pct = round(100*n_pos/df_tweets['probability'].sum()) + else: + n_neg = abs(df_tweets[df_tweets['prob_sen']<0]['prob_sen'].sum()) + n_pct = round(100*n_neg/df_tweets['probability'].sum()) - # Parse tweets - dt_from = dateutil.parser.parse(df_tweets['created_at'].values[-1]) - dt_to = dateutil.parser.parse(df_tweets['created_at'].values[0]) - print(f"From: {dt_from.strftime('%Y-%m-%d %H:%M:%S')}") - print(f"To: {dt_to.strftime('%Y-%m-%d %H:%M:%S')}") + # Parse tweets + dt_from = dateutil.parser.parse(df_tweets['created_at'].values[-1]) + dt_to = dateutil.parser.parse(df_tweets['created_at'].values[0]) + print(f"From: {dt_from.strftime('%Y-%m-%d %H:%M:%S')}") + print(f"To: {dt_to.strftime('%Y-%m-%d %H:%M:%S')}") - print(f"{len(df_tweets)} tweets were analyzed.") - dt_delta = (dt_to - dt_from) - n_freq = dt_delta.total_seconds()/len(df_tweets) - print(f"Frequency of approx 1 tweet every {round(n_freq)} seconds.") + print(f"{len(df_tweets)} tweets were analyzed.") + dt_delta = (dt_to - dt_from) + n_freq = dt_delta.total_seconds()/len(df_tweets) + print(f"Frequency of approx 1 tweet every {round(n_freq)} seconds.") - s_sen = f"{('NEGATIVE', 'POSITIVE')[int(df_tweets['sentiment_estimation'].values[-1] > 0)]}" - s_conf = f"{round(100*df_tweets['sentiment_estimation'].values[-1]/df_tweets['probability'].sum())}%" - print(f"The sentiment of {s_ticker} is: {s_sen} ({s_conf})") - print("") + s_sen = f"{('NEGATIVE', 'POSITIVE')[int(df_tweets['sentiment_estimation'].values[-1] > 0)]}" + s_conf = f"{round(100*df_tweets['sentiment_estimation'].values[-1]/df_tweets['probability'].sum())}%" + print(f"The sentiment of {s_ticker} is: {s_sen} ({s_conf})") + print("") - except: - print("") # ------------------------------------------------- SENTIMENT ------------------------------------------------- @@ -124,158 +121,154 @@ def sentiment(l_args, s_ticker): parser.add_argument('-d', "--days", action="store", dest="n_days_past", type=int, default=7, choices=range(1,8), help='num of days in the past to extract tweets.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") + return - # Setup API request params and headers - headers = {'authorization': f'Bearer {cfg.API_TWITTER_BEARER_TOKEN}'} - params = { - 'query': f'({s_ticker}) (lang:en)', - 'max_results': str(ns_parser.n_tweets), - 'tweet.fields': 'created_at,lang' - } + # Setup API request params and headers + headers = {'authorization': f'Bearer {cfg.API_TWITTER_BEARER_TOKEN}'} + params = { + 'query': f'({s_ticker}) (lang:en)', + 'max_results': str(ns_parser.n_tweets), + 'tweet.fields': 'created_at,lang' + } - # Date format string required by twitter - dtformat = '%Y-%m-%dT%H:%M:%SZ' + # Date format string required by twitter + dtformat = '%Y-%m-%dT%H:%M:%SZ' - # Algorithm to extract - dt_recent = datetime.now() - timedelta(seconds=20) - dt_old = dt_recent - timedelta(days=ns_parser.n_days_past) - print(f"From {dt_recent.date()} retrieving {ns_parser.n_tweets*24} tweets ({ns_parser.n_tweets} tweets/hour)") + # Algorithm to extract + dt_recent = datetime.now() - timedelta(seconds=20) + dt_old = dt_recent - timedelta(days=ns_parser.n_days_past) + print(f"From {dt_recent.date()} retrieving {ns_parser.n_tweets*24} tweets ({ns_parser.n_tweets} tweets/hour)") - df_tweets = pd.DataFrame() - while True: - # Iterate until we haven't passed the old number of days - if dt_recent < dt_old: - break + df_tweets = pd.DataFrame() + while True: + # Iterate until we haven't passed the old number of days + if dt_recent < dt_old: + break - # Update past datetime - dt_past = dt_recent - timedelta(minutes=60) + # Update past datetime + dt_past = dt_recent - timedelta(minutes=60) - if dt_past.day < dt_recent.day: - print(f"From {dt_past.date()} retrieving {ns_parser.n_tweets*24} tweets ({ns_parser.n_tweets} tweets/hour)") + if dt_past.day < dt_recent.day: + print(f"From {dt_past.date()} retrieving {ns_parser.n_tweets*24} tweets ({ns_parser.n_tweets} tweets/hour)") - # Assign from and to datetime parameters for the API - params['start_time'] = dt_past.strftime(dtformat) - params['end_time'] = dt_recent.strftime(dtformat) + # Assign from and to datetime parameters for the API + params['start_time'] = dt_past.strftime(dtformat) + params['end_time'] = dt_recent.strftime(dtformat) - # Send API request - response = requests.get('https://api.twitter.com/2/tweets/search/recent', - params=params, - headers=headers) + # Send API request + response = requests.get('https://api.twitter.com/2/tweets/search/recent', + params=params, + headers=headers) - # Update recent datetime - dt_recent = dt_past + # Update recent datetime + dt_recent = dt_past - # If response from API request is a success - if response.status_code == 200: + # If response from API request is a success + if response.status_code == 200: - # Iteratively append our tweet data to our dataframe - for tweet in response.json()['data']: - row = get_data(tweet) - df_tweets = df_tweets.append(row, ignore_index=True) + # Iteratively append our tweet data to our dataframe + for tweet in response.json()['data']: + row = get_data(tweet) + df_tweets = df_tweets.append(row, ignore_index=True) - # Load sentiment model - print("") - sentiment_model = flair.models.TextClassifier.load('en-sentiment'); - print("") + # Load sentiment model + print("") + sentiment_model = flair.models.TextClassifier.load('en-sentiment'); + print("") - # Append probability and sentiment preds later - probs = [] - sentiments = [] - for s_tweet in df_tweets['text'].to_list(): - tweet = clean_tweet(s_tweet, s_ticker) + # Append probability and sentiment preds later + probs = [] + sentiments = [] + for s_tweet in df_tweets['text'].to_list(): + tweet = clean_tweet(s_tweet, s_ticker) - # Make sentiment prediction - sentence = flair.data.Sentence(tweet) - sentiment_model.predict(sentence) + # Make sentiment prediction + sentence = flair.data.Sentence(tweet) + sentiment_model.predict(sentence) - # Extract sentiment prediction (POSITIVE/NEGATIVE) and confidence (0-1) - probs.append(sentence.labels[0].score) - sentiments.append(sentence.labels[0].value) + # Extract sentiment prediction (POSITIVE/NEGATIVE) and confidence (0-1) + probs.append(sentence.labels[0].score) + sentiments.append(sentence.labels[0].value) - # Add probability and sentiment predictions to tweets dataframe - df_tweets['probability'] = probs - df_tweets['sentiment'] = sentiments + # Add probability and sentiment predictions to tweets dataframe + df_tweets['probability'] = probs + df_tweets['sentiment'] = sentiments - # Sort tweets per date - df_tweets.sort_index(ascending=False, inplace=True) + # Sort tweets per date + df_tweets.sort_index(ascending=False, inplace=True) - # Add sentiment estimation (probability positive for POSITIVE sentiment, and negative for NEGATIVE sentiment) - df_tweets['sentiment_estimation'] = df_tweets.apply(lambda row: row['probability']*(-1, 1)[row['sentiment']=='POSITIVE'], axis=1).cumsum() - # Cumulative sentiment_estimation - df_tweets['prob_sen'] = df_tweets.apply(lambda row: row['probability']*(-1, 1)[row['sentiment']=='POSITIVE'], axis=1) + # Add sentiment estimation (probability positive for POSITIVE sentiment, and negative for NEGATIVE sentiment) + df_tweets['sentiment_estimation'] = df_tweets.apply(lambda row: row['probability']*(-1, 1)[row['sentiment']=='POSITIVE'], axis=1).cumsum() + # Cumulative sentiment_estimation + df_tweets['prob_sen'] = df_tweets.apply(lambda row: row['probability']*(-1, 1)[row['sentiment']=='POSITIVE'], axis=1) - # Percentage of confidence - if df_tweets['sentiment_estimation'].values[-1] > 0: - n_pos = df_tweets[df_tweets['prob_sen']>0]['prob_sen'].sum() - n_pct = round(100*n_pos/df_tweets['probability'].sum()) - else: - n_neg = abs(df_tweets[df_tweets['prob_sen']<0]['prob_sen'].sum()) - n_pct = round(100*n_neg/df_tweets['probability'].sum()) - s_sen = f"{('NEGATIVE', 'POSITIVE')[int(df_tweets['sentiment_estimation'].values[-1] > 0)]}" + # Percentage of confidence + if df_tweets['sentiment_estimation'].values[-1] > 0: + n_pos = df_tweets[df_tweets['prob_sen']>0]['prob_sen'].sum() + n_pct = round(100*n_pos/df_tweets['probability'].sum()) + else: + n_neg = abs(df_tweets[df_tweets['prob_sen']<0]['prob_sen'].sum()) + n_pct = round(100*n_neg/df_tweets['probability'].sum()) + s_sen = f"{('NEGATIVE', 'POSITIVE')[int(df_tweets['sentiment_estimation'].values[-1] > 0)]}" - #df_tweets.to_csv(r'notebooks/tweets.csv', index=False) - df_tweets.reset_index(inplace=True) + #df_tweets.to_csv(r'notebooks/tweets.csv', index=False) + df_tweets.reset_index(inplace=True) - # Plotting - plt.subplot(211) - plt.title(f"Twitter's {s_ticker} sentiment over time is {s_sen} ({n_pct} %)") - plt.plot(df_tweets.index, df_tweets['sentiment_estimation'].values, lw=3, c='cyan') - plt.xlim(df_tweets.index[0], df_tweets.index[-1]) - plt.grid(b=True, which='major', color='#666666', linestyle='-', lw=1.5, alpha=0.5) - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.ylabel('Cumulative Sentiment') - l_xticks = list() - l_xlabels = list() - l_xticks.append(0) - l_xlabels.append(df_tweets['created_at'].values[0].split(' ')[0]) - n_day = datetime.strptime(df_tweets['created_at'].values[0], "%Y-%m-%d %H:%M:%S").day - n_idx = 0 - n_next_idx = 0 - for n_next_idx, dt_created in enumerate(df_tweets['created_at']): - if datetime.strptime(dt_created, "%Y-%m-%d %H:%M:%S").day > n_day: - l_xticks.append(n_next_idx) - l_xlabels.append(df_tweets['created_at'].values[n_next_idx].split(' ')[0]) - l_val_days = df_tweets['sentiment_estimation'].values[n_idx:n_next_idx]-df_tweets['sentiment_estimation'].values[n_idx] - plt.plot(range(n_idx, n_next_idx), l_val_days, lw=3, c='tab:blue') - n_day_avg = np.mean(l_val_days) - if n_day_avg > 0: - plt.hlines(n_day_avg, n_idx, n_next_idx, linewidth=2.5, linestyle='--', color='green', lw=3) - else: - plt.hlines(n_day_avg, n_idx, n_next_idx, linewidth=2.5, linestyle='--', color='red', lw=3) - n_idx = n_next_idx - n_day += 1 - l_val_days = df_tweets['sentiment_estimation'].values[n_idx:]-df_tweets['sentiment_estimation'].values[n_idx] - plt.plot(range(n_idx, len(df_tweets)), l_val_days, lw=3, c='tab:blue') - n_day_avg = np.mean(l_val_days) - if n_day_avg > 0: - plt.hlines(n_day_avg, n_idx, len(df_tweets), linewidth=2.5, linestyle='--', color='green', lw=3) - else: - plt.hlines(n_day_avg, n_idx, len(df_tweets), linewidth=2.5, linestyle='--', color='red', lw=3) - l_xticks.append(len(df_tweets)) - datetime.strptime(dt_created, "%Y-%m-%d %H:%M:%S") + timedelta(days=1) - l_xlabels.append(datetime.strftime(datetime.strptime(df_tweets['created_at'].values[len(df_tweets)-1], "%Y-%m-%d %H:%M:%S") + timedelta(days=1), "%Y-%m-%d")) - plt.xticks(l_xticks, l_xlabels) - plt.axhspan(plt.gca().get_ylim()[0], 0, facecolor='r', alpha=0.1) - plt.axhspan(0, plt.gca().get_ylim()[1], facecolor='g', alpha=0.1) + # Plotting + plt.subplot(211) + plt.title(f"Twitter's {s_ticker} sentiment over time is {s_sen} ({n_pct} %)") + plt.plot(df_tweets.index, df_tweets['sentiment_estimation'].values, lw=3, c='cyan') + plt.xlim(df_tweets.index[0], df_tweets.index[-1]) + plt.grid(b=True, which='major', color='#666666', linestyle='-', lw=1.5, alpha=0.5) + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.ylabel('Cumulative Sentiment') + l_xticks = list() + l_xlabels = list() + l_xticks.append(0) + l_xlabels.append(df_tweets['created_at'].values[0].split(' ')[0]) + n_day = datetime.strptime(df_tweets['created_at'].values[0], "%Y-%m-%d %H:%M:%S").day + n_idx = 0 + n_next_idx = 0 + for n_next_idx, dt_created in enumerate(df_tweets['created_at']): + if datetime.strptime(dt_created, "%Y-%m-%d %H:%M:%S").day > n_day: + l_xticks.append(n_next_idx) + l_xlabels.append(df_tweets['created_at'].values[n_next_idx].split(' ')[0]) + l_val_days = df_tweets['sentiment_estimation'].values[n_idx:n_next_idx]-df_tweets['sentiment_estimation'].values[n_idx] + plt.plot(range(n_idx, n_next_idx), l_val_days, lw=3, c='tab:blue') + n_day_avg = np.mean(l_val_days) + if n_day_avg > 0: + plt.hlines(n_day_avg, n_idx, n_next_idx, linewidth=2.5, linestyle='--', color='green', lw=3) + else: + plt.hlines(n_day_avg, n_idx, n_next_idx, linewidth=2.5, linestyle='--', color='red', lw=3) + n_idx = n_next_idx + n_day += 1 + l_val_days = df_tweets['sentiment_estimation'].values[n_idx:]-df_tweets['sentiment_estimation'].values[n_idx] + plt.plot(range(n_idx, len(df_tweets)), l_val_days, lw=3, c='tab:blue') + n_day_avg = np.mean(l_val_days) + if n_day_avg > 0: + plt.hlines(n_day_avg, n_idx, len(df_tweets), linewidth=2.5, linestyle='--', color='green', lw=3) + else: + plt.hlines(n_day_avg, n_idx, len(df_tweets), linewidth=2.5, linestyle='--', color='red', lw=3) + l_xticks.append(len(df_tweets)) + datetime.strptime(dt_created, "%Y-%m-%d %H:%M:%S") + timedelta(days=1) + l_xlabels.append(datetime.strftime(datetime.strptime(df_tweets['created_at'].values[len(df_tweets)-1], "%Y-%m-%d %H:%M:%S") + timedelta(days=1), "%Y-%m-%d")) + plt.xticks(l_xticks, l_xlabels) + plt.axhspan(plt.gca().get_ylim()[0], 0, facecolor='r', alpha=0.1) + plt.axhspan(0, plt.gca().get_ylim()[1], facecolor='g', alpha=0.1) - plt.subplot(212) - plt.bar(df_tweets[df_tweets['prob_sen']>0].index, df_tweets[df_tweets['prob_sen']>0]['prob_sen'].values, color='green') - plt.bar(df_tweets[df_tweets['prob_sen']<0].index, df_tweets[df_tweets['prob_sen']<0]['prob_sen'].values, color='red') - for l_x in l_xticks[1:]: - plt.vlines(l_x, -1, 1, linewidth=2, linestyle='--', color='k', lw=3) - plt.xlim(df_tweets.index[0], df_tweets.index[-1]) - plt.xticks(l_xticks, l_xlabels) - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.ylabel('Sentiment') - plt.xlabel("Time") - plt.show() - - except: - print("") + plt.subplot(212) + plt.bar(df_tweets[df_tweets['prob_sen']>0].index, df_tweets[df_tweets['prob_sen']>0]['prob_sen'].values, color='green') + plt.bar(df_tweets[df_tweets['prob_sen']<0].index, df_tweets[df_tweets['prob_sen']<0]['prob_sen'].values, color='red') + for l_x in l_xticks[1:]: + plt.vlines(l_x, -1, 1, linewidth=2, linestyle='--', color='k', lw=3) + plt.xlim(df_tweets.index[0], df_tweets.index[-1]) + plt.xticks(l_xticks, l_xlabels) + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.ylabel('Sentiment') + plt.xlabel("Time") + plt.show() diff --git a/technical_analysis/momentum.py b/technical_analysis/momentum.py index 8bf1fe6abf6..100789e36ef 100644 --- a/technical_analysis/momentum.py +++ b/technical_analysis/momentum.py @@ -21,74 +21,71 @@ def cci(l_args, s_ticker, s_interval, df_stock): parser.add_argument('-s', "--scalar", action="store", dest="n_scalar", type=check_positive, default=0.015, help='scalar') parser.add_argument('-o', "--offset", action="store", dest="n_offset", type=check_positive, default=0, help='offset') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") + return - # Daily - if s_interval == "1440min": - df_ta = ta.cci(high=df_stock['2. high'], low=df_stock['3. low'], close=df_stock['5. adjusted close'], - length=ns_parser.n_length, scalar=ns_parser.n_scalar, offset=ns_parser.n_offset).dropna() - - plt.subplot(211) - plt.title(f"Commodity Channel Index (CCI) on {s_ticker}") - plt.plot(df_stock.index, df_stock['5. adjusted close'].values, 'k', lw=2) - plt.xlim(df_stock.index[0], df_stock.index[-1]) - plt.ylabel(f'Share Price ($)') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.subplot(212) - plt.plot(df_ta.index, df_ta.values, 'b', lw=2) - plt.xlim(df_stock.index[0], df_stock.index[-1]) - plt.axhspan(100, plt.gca().get_ylim()[1], facecolor='r', alpha=0.2) - plt.axhspan(plt.gca().get_ylim()[0], -100, facecolor='g', alpha=0.2) - plt.axhline(100, linewidth=3, color='r', ls='--') - plt.axhline(-100, linewidth=3, color='g', ls='--') - plt.xlabel('Time') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.gca().twinx() - plt.ylim(plt.gca().get_ylim()) - plt.yticks([.2, .8], ('OVERSOLD', 'OVERBOUGHT')) - plt.show() + # Daily + if s_interval == "1440min": + df_ta = ta.cci(high=df_stock['2. high'], low=df_stock['3. low'], close=df_stock['5. adjusted close'], + length=ns_parser.n_length, scalar=ns_parser.n_scalar, offset=ns_parser.n_offset).dropna() - # Intraday - else: - df_ta = ta.cci(high=df_stock['2. high'], low=df_stock['3. low'], close=df_stock['4. close'], - length=ns_parser.n_length, scalar=ns_parser.n_scalar, offset=ns_parser.n_offset).dropna() - - plt.subplot(211) - plt.title(f"Commodity Channel Index (CCI) on {s_ticker}") - plt.plot(df_stock.index, df_stock['4. close'].values, 'k', lw=2) - plt.xlim(df_stock.index[0], df_stock.index[-1]) - plt.ylabel(f'Share Price ($)') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.subplot(212) - plt.plot(df_ta.index, df_ta.values, 'b', lw=2) - plt.xlim(df_stock.index[0], df_stock.index[-1]) - plt.axhspan(100, plt.gca().get_ylim()[1], facecolor='r', alpha=0.2) - plt.axhspan(plt.gca().get_ylim()[0], -100, facecolor='g', alpha=0.2) - plt.axhline(100, linewidth=3, color='r', ls='--') - plt.axhline(-100, linewidth=3, color='g', ls='--') - plt.xlabel('Time') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.gca().twinx() - plt.ylim(plt.gca().get_ylim()) - plt.yticks([.2, .8], ('OVERSOLD', 'OVERBOUGHT')) - plt.show() - print("") + plt.subplot(211) + plt.title(f"Commodity Channel Index (CCI) on {s_ticker}") + plt.plot(df_stock.index, df_stock['5. adjusted close'].values, 'k', lw=2) + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.ylabel(f'Share Price ($)') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.subplot(212) + plt.plot(df_ta.index, df_ta.values, 'b', lw=2) + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.axhspan(100, plt.gca().get_ylim()[1], facecolor='r', alpha=0.2) + plt.axhspan(plt.gca().get_ylim()[0], -100, facecolor='g', alpha=0.2) + plt.axhline(100, linewidth=3, color='r', ls='--') + plt.axhline(-100, linewidth=3, color='g', ls='--') + plt.xlabel('Time') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.gca().twinx() + plt.ylim(plt.gca().get_ylim()) + plt.yticks([.2, .8], ('OVERSOLD', 'OVERBOUGHT')) + plt.show() + + # Intraday + else: + df_ta = ta.cci(high=df_stock['2. high'], low=df_stock['3. low'], close=df_stock['4. close'], + length=ns_parser.n_length, scalar=ns_parser.n_scalar, offset=ns_parser.n_offset).dropna() + + plt.subplot(211) + plt.title(f"Commodity Channel Index (CCI) on {s_ticker}") + plt.plot(df_stock.index, df_stock['4. close'].values, 'k', lw=2) + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.ylabel(f'Share Price ($)') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.subplot(212) + plt.plot(df_ta.index, df_ta.values, 'b', lw=2) + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.axhspan(100, plt.gca().get_ylim()[1], facecolor='r', alpha=0.2) + plt.axhspan(plt.gca().get_ylim()[0], -100, facecolor='g', alpha=0.2) + plt.axhline(100, linewidth=3, color='r', ls='--') + plt.axhline(-100, linewidth=3, color='g', ls='--') + plt.xlabel('Time') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.gca().twinx() + plt.ylim(plt.gca().get_ylim()) + plt.yticks([.2, .8], ('OVERSOLD', 'OVERBOUGHT')) + plt.show() + print("") - except: - print("") # ----------------------------------------------------- MACD ----------------------------------------------------- @@ -113,70 +110,67 @@ def macd(l_args, s_ticker, s_interval, df_stock): parser.add_argument('-o', "--offset", action="store", dest="n_offset", type=check_positive, default=0, help='How many periods to offset the result.') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") + return - # Daily - if s_interval == "1440min": - df_ta = ta.macd(df_stock['5. adjusted close'], fast=ns_parser.n_fast, slow=ns_parser.n_slow, - signal=ns_parser.n_signal, offset=ns_parser.n_offset).dropna() + # Daily + if s_interval == "1440min": + df_ta = ta.macd(df_stock['5. adjusted close'], fast=ns_parser.n_fast, slow=ns_parser.n_slow, + signal=ns_parser.n_signal, offset=ns_parser.n_offset).dropna() - plt.subplot(211) - plt.title(f"Moving Average Convergence Divergence (MACD) on {s_ticker}") - plt.plot(df_stock.index, df_stock['4. close'].values, 'k', lw=2) - plt.xlim(df_stock.index[0], df_stock.index[-1]) - plt.ylabel(f'Share Price ($)') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.subplot(212) - plt.plot(df_ta.index, df_ta.iloc[:,0].values, 'b', lw=2) - plt.plot(df_ta.index, df_ta.iloc[:,2].values, 'r', lw=2) - plt.bar(df_ta.index, df_ta.iloc[:,1].values, color='g') - plt.legend([f'MACD Line {df_ta.columns[0]}', - f'Signal Line {df_ta.columns[2]}', - f'Histogram {df_ta.columns[1]}']) - plt.xlim(df_stock.index[0], df_stock.index[-1]) - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.xlabel('Time') - plt.show() + plt.subplot(211) + plt.title(f"Moving Average Convergence Divergence (MACD) on {s_ticker}") + plt.plot(df_stock.index, df_stock['4. close'].values, 'k', lw=2) + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.ylabel(f'Share Price ($)') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.subplot(212) + plt.plot(df_ta.index, df_ta.iloc[:,0].values, 'b', lw=2) + plt.plot(df_ta.index, df_ta.iloc[:,2].values, 'r', lw=2) + plt.bar(df_ta.index, df_ta.iloc[:,1].values, color='g') + plt.legend([f'MACD Line {df_ta.columns[0]}', + f'Signal Line {df_ta.columns[2]}', + f'Histogram {df_ta.columns[1]}']) + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.xlabel('Time') + plt.show() - # Intraday - else: - df_ta = ta.macd(df_stock['4. close'], fast=ns_parser.n_fast, slow=ns_parser.n_slow, - signal=ns_parser.n_signal, offset=ns_parser.n_offset).dropna() + # Intraday + else: + df_ta = ta.macd(df_stock['4. close'], fast=ns_parser.n_fast, slow=ns_parser.n_slow, + signal=ns_parser.n_signal, offset=ns_parser.n_offset).dropna() - plt.subplot(211) - plt.title(f"Moving Average Convergence Divergence (MACD) on {s_ticker}") - plt.plot(df_stock.index, df_stock['4. close'].values, 'k', lw=2) - plt.xlim(df_stock.index[0], df_stock.index[-1]) - plt.ylabel(f'Share Price ($)') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.subplot(212) - plt.plot(df_ta.index, df_ta.iloc[:,0].values, 'b', lw=2) - plt.plot(df_ta.index, df_ta.iloc[:,2].values, 'r', lw=2) - plt.bar(df_ta.index, df_ta.iloc[:,1].values, color='g') - plt.legend([f'MACD Line {df_ta.columns[0]}', - f'Signal Line {df_ta.columns[2]}', - f'Histogram {df_ta.columns[1]}']) - plt.xlim(df_stock.index[0], df_stock.index[-1]) - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.xlabel('Time') - plt.show() - print("") + plt.subplot(211) + plt.title(f"Moving Average Convergence Divergence (MACD) on {s_ticker}") + plt.plot(df_stock.index, df_stock['4. close'].values, 'k', lw=2) + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.ylabel(f'Share Price ($)') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.subplot(212) + plt.plot(df_ta.index, df_ta.iloc[:,0].values, 'b', lw=2) + plt.plot(df_ta.index, df_ta.iloc[:,2].values, 'r', lw=2) + plt.bar(df_ta.index, df_ta.iloc[:,1].values, color='g') + plt.legend([f'MACD Line {df_ta.columns[0]}', + f'Signal Line {df_ta.columns[2]}', + f'Histogram {df_ta.columns[1]}']) + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.xlabel('Time') + plt.show() + print("") - except: - print("") # ----------------------------------------------------- RSI ----------------------------------------------------- @@ -193,76 +187,72 @@ def rsi(l_args, s_ticker, s_interval, df_stock): parser.add_argument('-d', "--drift", action="store", dest="n_drift", type=check_positive, default=1, help='drift') parser.add_argument('-o', "--offset", action="store", dest="n_offset", type=check_positive, default=0, help='offset') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") + return - # Daily - if s_interval == "1440min": - df_ta = ta.rsi(df_stock['5. adjusted close'], length=ns_parser.n_length, scalar=ns_parser.n_scalar, - drift=ns_parser.n_drift, offset=ns_parser.n_offset).dropna() + # Daily + if s_interval == "1440min": + df_ta = ta.rsi(df_stock['5. adjusted close'], length=ns_parser.n_length, scalar=ns_parser.n_scalar, + drift=ns_parser.n_drift, offset=ns_parser.n_offset).dropna() - plt.subplot(211) - plt.plot(df_stock.index, df_stock['5. adjusted close'].values, 'k', lw=2) - plt.title(f"Relative Strength Index (RSI) on {s_ticker}") - plt.xlim(df_stock.index[0], df_stock.index[-1]) - plt.ylabel(f'Share Price ($)') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.subplot(212) - plt.plot(df_ta.index, df_ta.values, 'b', lw=2) - plt.xlim(df_stock.index[0], df_stock.index[-1]) - plt.axhspan(70, 100, facecolor='r', alpha=0.2) - plt.axhspan(0, 30, facecolor='g', alpha=0.2) - plt.axhline(70, linewidth=3, color='r', ls='--') - plt.axhline(30, linewidth=3, color='g', ls='--') - plt.xlabel('Time') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.ylim([0, 100]) - plt.gca().twinx() - plt.ylim(plt.gca().get_ylim()) - plt.yticks([.15, .85], ('OVERSOLD', 'OVERBOUGHT')) - plt.show() + plt.subplot(211) + plt.plot(df_stock.index, df_stock['5. adjusted close'].values, 'k', lw=2) + plt.title(f"Relative Strength Index (RSI) on {s_ticker}") + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.ylabel(f'Share Price ($)') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.subplot(212) + plt.plot(df_ta.index, df_ta.values, 'b', lw=2) + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.axhspan(70, 100, facecolor='r', alpha=0.2) + plt.axhspan(0, 30, facecolor='g', alpha=0.2) + plt.axhline(70, linewidth=3, color='r', ls='--') + plt.axhline(30, linewidth=3, color='g', ls='--') + plt.xlabel('Time') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.ylim([0, 100]) + plt.gca().twinx() + plt.ylim(plt.gca().get_ylim()) + plt.yticks([.15, .85], ('OVERSOLD', 'OVERBOUGHT')) + plt.show() - # Intraday - else: - df_ta = ta.rsi(df_stock['4. close'], length=ns_parser.n_length, scalar=ns_parser.n_scalar, - drift=ns_parser.n_drift, offset=ns_parser.n_offset).dropna() + # Intraday + else: + df_ta = ta.rsi(df_stock['4. close'], length=ns_parser.n_length, scalar=ns_parser.n_scalar, + drift=ns_parser.n_drift, offset=ns_parser.n_offset).dropna() - plt.subplot(211) - plt.plot(df_stock.index, df_stock['4. close'].values, 'k', lw=2) - plt.title(f"Relative Strength Index (RSI) on {s_ticker}") - plt.xlim(df_stock.index[0], df_stock.index[-1]) - plt.ylabel(f'Share Price ($)') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.subplot(212) - plt.plot(df_ta.index, df_ta.values, 'b', lw=2) - plt.xlim(df_stock.index[0], df_stock.index[-1]) - plt.axhspan(70, 100, facecolor='r', alpha=0.2) - plt.axhspan(0, 30, facecolor='g', alpha=0.2) - plt.axhline(70, linewidth=3, color='r', ls='--') - plt.axhline(30, linewidth=3, color='g', ls='--') - plt.xlabel('Time') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.ylim([0, 100]) - plt.gca().twinx() - plt.ylim(plt.gca().get_ylim()) - plt.yticks([.15, .85], ('OVERSOLD', 'OVERBOUGHT')) - plt.show() - print("") - - except: - print("") + plt.subplot(211) + plt.plot(df_stock.index, df_stock['4. close'].values, 'k', lw=2) + plt.title(f"Relative Strength Index (RSI) on {s_ticker}") + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.ylabel(f'Share Price ($)') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.subplot(212) + plt.plot(df_ta.index, df_ta.values, 'b', lw=2) + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.axhspan(70, 100, facecolor='r', alpha=0.2) + plt.axhspan(0, 30, facecolor='g', alpha=0.2) + plt.axhline(70, linewidth=3, color='r', ls='--') + plt.axhline(30, linewidth=3, color='g', ls='--') + plt.xlabel('Time') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.ylim([0, 100]) + plt.gca().twinx() + plt.ylim(plt.gca().get_ylim()) + plt.yticks([.15, .85], ('OVERSOLD', 'OVERBOUGHT')) + plt.show() + print("") # ----------------------------------------------------- STOCH ----------------------------------------------------- @@ -283,77 +273,74 @@ def stoch(l_args, s_ticker, s_interval, df_stock): help='The time period of the slowk moving average') parser.add_argument('-o', "--offset", action="store", dest="n_offset", type=check_positive, default=0, help='offset') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") + return - # Daily - if s_interval == "1440min": - df_ta = ta.stoch(high=df_stock['2. high'], low=df_stock['3. low'], close=df_stock['5. adjusted close'], k=ns_parser.n_fastkperiod, - d=ns_parser.n_slowdperiod, smooth_k=ns_parser.n_slowkperiod, offset=ns_parser.n_offset).dropna() - - plt.subplot(211) - plt.plot(df_stock.index, df_stock['5. adjusted close'].values, 'k', lw=2) - plt.title(f"Stochastic Relative Strength Index (STOCH RSI) on {s_ticker}") - plt.xlim(df_stock.index[0], df_stock.index[-1]) - plt.ylabel(f'Share Price ($)') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.subplot(212) - plt.plot(df_ta.index, df_ta.iloc[:,0].values, 'k', lw=2) - plt.plot(df_ta.index, df_ta.iloc[:,1].values, 'b', lw=2, ls='--') - plt.xlim(df_stock.index[0], df_stock.index[-1]) - plt.axhspan(80, 100, facecolor='r', alpha=0.2) - plt.axhspan(0, 20, facecolor='g', alpha=0.2) - plt.axhline(80, linewidth=3, color='r', ls='--') - plt.axhline(20, linewidth=3, color='g', ls='--') - plt.legend([f'%K {df_ta.columns[0]}', f'%D {df_ta.columns[1]}']) - plt.xlabel('Time') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.ylim([0, 100]) - plt.gca().twinx() - plt.ylim(plt.gca().get_ylim()) - plt.yticks([.1, .9], ('OVERSOLD', 'OVERBOUGHT')) - plt.show() + # Daily + if s_interval == "1440min": + df_ta = ta.stoch(high=df_stock['2. high'], low=df_stock['3. low'], close=df_stock['5. adjusted close'], k=ns_parser.n_fastkperiod, + d=ns_parser.n_slowdperiod, smooth_k=ns_parser.n_slowkperiod, offset=ns_parser.n_offset).dropna() - # Intraday - else: - df_ta = ta.stoch(high=df_stock['2. high'], low=df_stock['3. low'], close=df_stock['4. close'], k=ns_parser.n_fastkperiod, - d=ns_parser.n_slowdperiod, smooth_k=ns_parser.n_slowkperiod, offset=ns_parser.n_offset).dropna() + plt.subplot(211) + plt.plot(df_stock.index, df_stock['5. adjusted close'].values, 'k', lw=2) + plt.title(f"Stochastic Relative Strength Index (STOCH RSI) on {s_ticker}") + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.ylabel(f'Share Price ($)') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.subplot(212) + plt.plot(df_ta.index, df_ta.iloc[:,0].values, 'k', lw=2) + plt.plot(df_ta.index, df_ta.iloc[:,1].values, 'b', lw=2, ls='--') + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.axhspan(80, 100, facecolor='r', alpha=0.2) + plt.axhspan(0, 20, facecolor='g', alpha=0.2) + plt.axhline(80, linewidth=3, color='r', ls='--') + plt.axhline(20, linewidth=3, color='g', ls='--') + plt.legend([f'%K {df_ta.columns[0]}', f'%D {df_ta.columns[1]}']) + plt.xlabel('Time') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.ylim([0, 100]) + plt.gca().twinx() + plt.ylim(plt.gca().get_ylim()) + plt.yticks([.1, .9], ('OVERSOLD', 'OVERBOUGHT')) + plt.show() - plt.subplot(211) - plt.plot(df_stock.index, df_stock['4. close'].values, 'k', lw=2) - plt.title(f"Stochastic Relative Strength Index (STOCH RSI) on {s_ticker}") - plt.xlim(df_stock.index[0], df_stock.index[-1]) - plt.ylabel(f'Share Price ($)') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.subplot(212) - plt.plot(df_ta.index, df_ta.iloc[:,0].values, 'k', lw=2) - plt.plot(df_ta.index, df_ta.iloc[:,1].values, 'b', lw=2, ls='--') - plt.xlim(df_stock.index[0], df_stock.index[-1]) - plt.axhspan(80, 100, facecolor='r', alpha=0.2) - plt.axhspan(0, 20, facecolor='g', alpha=0.2) - plt.axhline(80, linewidth=3, color='r', ls='--') - plt.axhline(20, linewidth=3, color='g', ls='--') - plt.legend([f'%K {df_ta.columns[0]}', f'%D {df_ta.columns[1]}']) - plt.xlabel('Time') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.ylim([0, 100]) - plt.gca().twinx() - plt.ylim(plt.gca().get_ylim()) - plt.yticks([.1, .9], ('OVERSOLD', 'OVERBOUGHT')) - plt.show() - print("") + # Intraday + else: + df_ta = ta.stoch(high=df_stock['2. high'], low=df_stock['3. low'], close=df_stock['4. close'], k=ns_parser.n_fastkperiod, + d=ns_parser.n_slowdperiod, smooth_k=ns_parser.n_slowkperiod, offset=ns_parser.n_offset).dropna() + + plt.subplot(211) + plt.plot(df_stock.index, df_stock['4. close'].values, 'k', lw=2) + plt.title(f"Stochastic Relative Strength Index (STOCH RSI) on {s_ticker}") + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.ylabel(f'Share Price ($)') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.subplot(212) + plt.plot(df_ta.index, df_ta.iloc[:,0].values, 'k', lw=2) + plt.plot(df_ta.index, df_ta.iloc[:,1].values, 'b', lw=2, ls='--') + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.axhspan(80, 100, facecolor='r', alpha=0.2) + plt.axhspan(0, 20, facecolor='g', alpha=0.2) + plt.axhline(80, linewidth=3, color='r', ls='--') + plt.axhline(20, linewidth=3, color='g', ls='--') + plt.legend([f'%K {df_ta.columns[0]}', f'%D {df_ta.columns[1]}']) + plt.xlabel('Time') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.ylim([0, 100]) + plt.gca().twinx() + plt.ylim(plt.gca().get_ylim()) + plt.yticks([.1, .9], ('OVERSOLD', 'OVERBOUGHT')) + plt.show() + print("") - except: - print("") diff --git a/technical_analysis/overlap.py b/technical_analysis/overlap.py index b1456c17270..a1038325976 100644 --- a/technical_analysis/overlap.py +++ b/technical_analysis/overlap.py @@ -1,4 +1,5 @@ import argparse +import matplotlib.pyplot as plt import pandas_ta as ta from pandas.plotting import register_matplotlib_converters @@ -23,25 +24,22 @@ def ema(l_args, s_ticker, s_interval, df_stock): parser.add_argument('-l', "--length", action="store", dest="n_length", type=check_positive, default=20, help='length') parser.add_argument('-o', "--offset", action="store", dest="n_offset", type=check_positive, default=0, help='offset') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") + return - # Daily - if s_interval == "1440min": - df_ta = ta.ema(df_stock['5. adjusted close'], length=ns_parser.n_length, offset=ns_parser.n_offset).dropna() - plot_stock_ta(df_stock['5. adjusted close'], s_ticker, df_ta, f"{ns_parser.n_length} EMA") + # Daily + if s_interval == "1440min": + df_ta = ta.ema(df_stock['5. adjusted close'], length=ns_parser.n_length, offset=ns_parser.n_offset).dropna() + plot_stock_ta(df_stock['5. adjusted close'], s_ticker, df_ta, f"{ns_parser.n_length} EMA") - # Intraday - else: - df_ta = ta.ema(df_stock['4. close'], length=ns_parser.n_length, offset=ns_parser.n_offset).dropna() - plot_stock_ta(df_stock['4. close'], s_ticker, df_ta, f"{ns_parser.n_length} EMA") + # Intraday + else: + df_ta = ta.ema(df_stock['4. close'], length=ns_parser.n_length, offset=ns_parser.n_offset).dropna() + plot_stock_ta(df_stock['4. close'], s_ticker, df_ta, f"{ns_parser.n_length} EMA") - except: - print("") # ----------------------------------------------------- SMA ----------------------------------------------------- @@ -58,54 +56,51 @@ def sma(l_args, s_ticker, s_interval, df_stock): parser.add_argument('-l', "--length", dest="l_length", type=lambda s: [int(item) for item in s.split(',')], default=[20, 50], help='length of MA window') parser.add_argument('-o', "--offset", action="store", dest="n_offset", type=check_positive, default=0, help='offset') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") + return - # Daily - if s_interval == "1440min": - plt.plot(df_stock.index, df_stock['5. adjusted close'].values, color='k') - l_legend = list() - l_legend.append(s_ticker) - for length in ns_parser.l_length: - df_ta = ta.sma(df_stock['5. adjusted close'], length=length, offset=ns_parser.n_offset).dropna() - plt.plot(df_ta.index, df_ta.values) - l_legend.append(f"{length} SMA") - plt.title(f"SMA on {s_ticker}") - plt.xlim(df_stock.index[0], df_stock.index[-1]) - plt.xlabel('Time') - plt.ylabel('Share Price ($)') - plt.legend(l_legend) - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.show() + # Daily + if s_interval == "1440min": + plt.plot(df_stock.index, df_stock['5. adjusted close'].values, color='k') + l_legend = list() + l_legend.append(s_ticker) + for length in ns_parser.l_length: + df_ta = ta.sma(df_stock['5. adjusted close'], length=length, offset=ns_parser.n_offset).dropna() + plt.plot(df_ta.index, df_ta.values) + l_legend.append(f"{length} SMA") + plt.title(f"SMA on {s_ticker}") + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.xlabel('Time') + plt.ylabel('Share Price ($)') + plt.legend(l_legend) + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.show() - # Intraday - else: - plt.plot(df_stock.index, df_stock['4. close'].values, color='k') - l_legend = list() - l_legend.append(s_ticker) - for length in ns_parser.n_length: - df_ta = ta.sma(df_stock['4. close'], length=length, offset=ns_parser.n_offset).dropna() - plt.plot(df_ta.index, df_ta.values) - l_legend.append(f"{length} SMA") - plt.title(f"SMA on {s_ticker}") - plt.xlim(df_stock.index[0], df_stock.index[-1]) - plt.xlabel('Time') - plt.ylabel('Share Price ($)') - plt.legend(l_legend) - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.show() - print("") + # Intraday + else: + plt.plot(df_stock.index, df_stock['4. close'].values, color='k') + l_legend = list() + l_legend.append(s_ticker) + for length in ns_parser.n_length: + df_ta = ta.sma(df_stock['4. close'], length=length, offset=ns_parser.n_offset).dropna() + plt.plot(df_ta.index, df_ta.values) + l_legend.append(f"{length} SMA") + plt.title(f"SMA on {s_ticker}") + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.xlabel('Time') + plt.ylabel('Share Price ($)') + plt.legend(l_legend) + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.show() + print("") - except: - print("") # ----------------------------------------------------- VWAP ----------------------------------------------------- @@ -116,56 +111,52 @@ def vwap(l_args, s_ticker, s_interval, df_stock): parser.add_argument('-o', "--offset", action="store", dest="n_offset", type=check_positive, default=0, help='offset') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") + return - # Daily - if s_interval == "1440min": - df_ta = ta.vwap(high=df_stock['2. high'], low=df_stock['3. low'], close=df_stock['5. adjusted close'], - volume=df_stock['6. volume'], offset=ns_parser.n_offset) + # Daily + if s_interval == "1440min": + df_ta = ta.vwap(high=df_stock['2. high'], low=df_stock['3. low'], close=df_stock['5. adjusted close'], + volume=df_stock['6. volume'], offset=ns_parser.n_offset) - pfig, axPrice = plt.subplots() - plt.plot(df_stock.index, df_stock['5. adjusted close'].values, color='k') - plt.plot(df_ta.index, df_ta.values) - plt.title(f"VWAP on {s_ticker}") - plt.xlim(df_stock.index[0], df_stock.index[-1]) - plt.xlabel('Time') - plt.ylabel('Share Price ($)') - plt.legend([s_ticker, "VWAP"]) - axVolume = axPrice.twinx() - plt.bar(df_stock.index, df_stock['6. volume'].values, color='k', alpha=0.8, width=.3) - plt.ylabel('Volume') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.show() - print("") - - # Intraday - else: - df_ta = ta.vwap(high=df_stock['2. high'], low=df_stock['3. low'], close=df_stock['4. close'], - volume=df_stock['5. volume'], offset=ns_parser.n_offset) - - pfig, axPrice = plt.subplots() - plt.plot(df_stock.index, df_stock['4. close'].values, color='k') - plt.plot(df_ta.index, df_ta.values) - plt.title(f"VWAP on {s_ticker}") - plt.xlim(df_stock.index[0], df_stock.index[-1]) - plt.xlabel('Time') - plt.ylabel('Share Price ($)') - plt.legend([s_ticker, "VWAP"]) - axVolume = axPrice.twinx() - plt.bar(df_stock.index, df_stock['5. volume'].values, color='k', alpha=0.8, width=.3) - plt.ylabel('Volume') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.show() - print("") - - except: + pfig, axPrice = plt.subplots() + plt.plot(df_stock.index, df_stock['5. adjusted close'].values, color='k') + plt.plot(df_ta.index, df_ta.values) + plt.title(f"VWAP on {s_ticker}") + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.xlabel('Time') + plt.ylabel('Share Price ($)') + plt.legend([s_ticker, "VWAP"]) + axVolume = axPrice.twinx() + plt.bar(df_stock.index, df_stock['6. volume'].values, color='k', alpha=0.8, width=.3) + plt.ylabel('Volume') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.show() + print("") + + # Intraday + else: + df_ta = ta.vwap(high=df_stock['2. high'], low=df_stock['3. low'], close=df_stock['4. close'], + volume=df_stock['5. volume'], offset=ns_parser.n_offset) + + pfig, axPrice = plt.subplots() + plt.plot(df_stock.index, df_stock['4. close'].values, color='k') + plt.plot(df_ta.index, df_ta.values) + plt.title(f"VWAP on {s_ticker}") + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.xlabel('Time') + plt.ylabel('Share Price ($)') + plt.legend([s_ticker, "VWAP"]) + axVolume = axPrice.twinx() + plt.bar(df_stock.index, df_stock['5. volume'].values, color='k', alpha=0.8, width=.3) + plt.ylabel('Volume') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.show() print("") diff --git a/technical_analysis/trend.py b/technical_analysis/trend.py index 21a3ca4fdba..3dc0e959610 100644 --- a/technical_analysis/trend.py +++ b/technical_analysis/trend.py @@ -21,74 +21,71 @@ def adx(l_args, s_ticker, s_interval, df_stock): parser.add_argument('-d', "--drift", action="store", dest="n_drift", type=check_positive, default=1, help='drift') parser.add_argument('-o', "--offset", action="store", dest="n_offset", type=check_positive, default=0, help='offset') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") + return - # Daily - if s_interval == "1440min": - df_ta = ta.adx(high=df_stock['2. high'], low=df_stock['3. low'], close=df_stock['5. adjusted close'], length=ns_parser.n_length, - scalar=ns_parser.n_scalar, drift=ns_parser.n_drift, offset=ns_parser.n_offset).dropna() + # Daily + if s_interval == "1440min": + df_ta = ta.adx(high=df_stock['2. high'], low=df_stock['3. low'], close=df_stock['5. adjusted close'], length=ns_parser.n_length, + scalar=ns_parser.n_scalar, drift=ns_parser.n_drift, offset=ns_parser.n_offset).dropna() - plt.subplot(211) - plt.plot(df_stock.index, df_stock['5. adjusted close'].values, 'k', lw=2) - plt.title(f"Average Directional Movement Index (ADX) on {s_ticker}") - plt.xlim(df_stock.index[0], df_stock.index[-1]) - plt.ylabel(f'Share Price ($)') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.subplot(212) - plt.plot(df_ta.index, df_ta.iloc[:,0].values, 'b', lw=2) - plt.plot(df_ta.index, df_ta.iloc[:,1].values, 'g', lw=1) - plt.plot(df_ta.index, df_ta.iloc[:,2].values, 'r', lw=1) - plt.xlim(df_stock.index[0], df_stock.index[-1]) - plt.axhline(25, linewidth=3, color='k', ls='--') - plt.legend([f'ADX ({df_ta.columns[0]})', - f'+DI ({df_ta.columns[1]})', - f'- DI ({df_ta.columns[2]})']) - plt.xlabel('Time') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.ylim([0, 100]) - plt.show() + plt.subplot(211) + plt.plot(df_stock.index, df_stock['5. adjusted close'].values, 'k', lw=2) + plt.title(f"Average Directional Movement Index (ADX) on {s_ticker}") + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.ylabel(f'Share Price ($)') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.subplot(212) + plt.plot(df_ta.index, df_ta.iloc[:,0].values, 'b', lw=2) + plt.plot(df_ta.index, df_ta.iloc[:,1].values, 'g', lw=1) + plt.plot(df_ta.index, df_ta.iloc[:,2].values, 'r', lw=1) + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.axhline(25, linewidth=3, color='k', ls='--') + plt.legend([f'ADX ({df_ta.columns[0]})', + f'+DI ({df_ta.columns[1]})', + f'- DI ({df_ta.columns[2]})']) + plt.xlabel('Time') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.ylim([0, 100]) + plt.show() - # Intraday - else: - df_ta = ta.adx(high=df_stock['2. high'], low=df_stock['3. low'], close=df_stock['4. close'], length=ns_parser.n_length, - scalar=ns_parser.n_scalar, drift=ns_parser.n_drift, offset=ns_parser.n_offset).dropna() - - plt.subplot(211) - plt.plot(df_stock.index, df_stock['4. close'].values, 'k', lw=2) - plt.title(f"Average Directional Movement Index (ADX) on {s_ticker}") - plt.xlim(df_stock.index[0], df_stock.index[-1]) - plt.ylabel(f'Share Price ($)') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.subplot(212) - plt.plot(df_ta.index, df_ta.iloc[:,0].values, 'b', lw=2) - plt.plot(df_ta.index, df_ta.iloc[:,1].values, 'g', lw=1) - plt.plot(df_ta.index, df_ta.iloc[:,2].values, 'r', lw=1) - plt.xlim(df_stock.index[0], df_stock.index[-1]) - plt.axhline(25, linewidth=3, color='k', ls='--') - plt.legend([f'ADX ({df_ta.columns[0]})', - f'+DI ({df_ta.columns[1]})', - f'- DI ({df_ta.columns[2]})']) - plt.xlabel('Time') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.ylim([0, 100]) - plt.show() - print("") + # Intraday + else: + df_ta = ta.adx(high=df_stock['2. high'], low=df_stock['3. low'], close=df_stock['4. close'], length=ns_parser.n_length, + scalar=ns_parser.n_scalar, drift=ns_parser.n_drift, offset=ns_parser.n_offset).dropna() + + plt.subplot(211) + plt.plot(df_stock.index, df_stock['4. close'].values, 'k', lw=2) + plt.title(f"Average Directional Movement Index (ADX) on {s_ticker}") + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.ylabel(f'Share Price ($)') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.subplot(212) + plt.plot(df_ta.index, df_ta.iloc[:,0].values, 'b', lw=2) + plt.plot(df_ta.index, df_ta.iloc[:,1].values, 'g', lw=1) + plt.plot(df_ta.index, df_ta.iloc[:,2].values, 'r', lw=1) + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.axhline(25, linewidth=3, color='k', ls='--') + plt.legend([f'ADX ({df_ta.columns[0]})', + f'+DI ({df_ta.columns[1]})', + f'- DI ({df_ta.columns[2]})']) + plt.xlabel('Time') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.ylim([0, 100]) + plt.show() + print("") - except: - print("") # ----------------------------------------------------- AROON ----------------------------------------------------- @@ -109,52 +106,48 @@ def aroon(l_args, s_ticker, s_interval, df_stock): parser.add_argument('-s', "--scalar", action="store", dest="n_scalar", type=check_positive, default=100, help='scalar') parser.add_argument('-o', "--offset", action="store", dest="n_offset", type=check_positive, default=0, help='offset') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") + return - df_ta = ta.aroon(high=df_stock['2. high'], low=df_stock['3. low'], length=ns_parser.n_length, - scalar=ns_parser.n_scalar, offset=ns_parser.n_offset).dropna() - - plt.subplot(311) - # Daily - if s_interval == "1440min": - #plot_stock_and_ta(df_stock['5. adjusted close'], s_ticker, df_ta.iloc[:,-1], "AROON") - plt.plot(df_stock.index, df_stock['5. adjusted close'].values, 'k', lw=2) - # Intraday - else: - #plot_stock_and_ta(df_stock['4. close'], s_ticker, df_ta.iloc[:,-1], "AROON") - plt.plot(df_stock.index, df_stock['4. close'].values, 'k', lw=2) - plt.title(f"Aroon on {s_ticker}") - plt.xlim(df_stock.index[0], df_stock.index[-1]) - plt.ylabel(f'Share Price ($)') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.subplot(312) - plt.plot(df_ta.index, df_ta.iloc[:,0].values, 'r', lw=2) - plt.plot(df_ta.index, df_ta.iloc[:,1].values, 'g', lw=2) - plt.xlim(df_stock.index[0], df_stock.index[-1]) - plt.axhline(50, linewidth=1, color='k', ls='--') - plt.legend([f'Aroon DOWN ({df_ta.columns[0]})', - f'Aroon UP ({df_ta.columns[1]})']) - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.ylim([0, 100]) - plt.subplot(313) - plt.plot(df_ta.index, df_ta.iloc[:,2].values, 'b', lw=2) - plt.xlabel('Time') - plt.legend([f'Aroon OSC ({df_ta.columns[2]})']) - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.ylim([-100, 100]) - plt.show() - print("") + df_ta = ta.aroon(high=df_stock['2. high'], low=df_stock['3. low'], length=ns_parser.n_length, + scalar=ns_parser.n_scalar, offset=ns_parser.n_offset).dropna() - except: - print("") + plt.subplot(311) + # Daily + if s_interval == "1440min": + #plot_stock_and_ta(df_stock['5. adjusted close'], s_ticker, df_ta.iloc[:,-1], "AROON") + plt.plot(df_stock.index, df_stock['5. adjusted close'].values, 'k', lw=2) + # Intraday + else: + #plot_stock_and_ta(df_stock['4. close'], s_ticker, df_ta.iloc[:,-1], "AROON") + plt.plot(df_stock.index, df_stock['4. close'].values, 'k', lw=2) + plt.title(f"Aroon on {s_ticker}") + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.ylabel(f'Share Price ($)') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.subplot(312) + plt.plot(df_ta.index, df_ta.iloc[:,0].values, 'r', lw=2) + plt.plot(df_ta.index, df_ta.iloc[:,1].values, 'g', lw=2) + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.axhline(50, linewidth=1, color='k', ls='--') + plt.legend([f'Aroon DOWN ({df_ta.columns[0]})', + f'Aroon UP ({df_ta.columns[1]})']) + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.ylim([0, 100]) + plt.subplot(313) + plt.plot(df_ta.index, df_ta.iloc[:,2].values, 'b', lw=2) + plt.xlabel('Time') + plt.legend([f'Aroon OSC ({df_ta.columns[2]})']) + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.ylim([-100, 100]) + plt.show() + print("") diff --git a/technical_analysis/volatility.py b/technical_analysis/volatility.py index ee76ee06cfb..7ffcf5965d1 100644 --- a/technical_analysis/volatility.py +++ b/technical_analysis/volatility.py @@ -1,6 +1,7 @@ import argparse import pandas_ta as ta +import matplotlib.pyplot as plt from pandas.plotting import register_matplotlib_converters from helper_funcs import check_positive @@ -26,55 +27,51 @@ def bbands(l_args, s_ticker, s_interval, df_stock): parser.add_argument('-m', "--mamode", action="store", dest="s_mamode", default="sma", help='mamode') parser.add_argument('-o', "--offset", action="store", dest="n_offset", type=check_positive, default=0, help='offset') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") + return - # Daily - if s_interval == "1440min": - df_ta = ta.bbands(close=df_stock['5. adjusted close'], length=ns_parser.n_length, std=ns_parser.n_std, - mamode=ns_parser.s_mamode, offset=ns_parser.n_offset).dropna() - #plot_stock_ta(df_stock['5. adjusted close'], s_ticker, df_ta, "BBANDS") + # Daily + if s_interval == "1440min": + df_ta = ta.bbands(close=df_stock['5. adjusted close'], length=ns_parser.n_length, std=ns_parser.n_std, + mamode=ns_parser.s_mamode, offset=ns_parser.n_offset).dropna() + #plot_stock_ta(df_stock['5. adjusted close'], s_ticker, df_ta, "BBANDS") - plt.plot(df_stock.index, df_stock['5. adjusted close'].values, color='k', lw=3) - plt.plot(df_ta.index, df_ta.iloc[:,0].values, 'r', lw=2) - plt.plot(df_ta.index, df_ta.iloc[:,1].values, 'b', lw=1.5, ls='--') - plt.plot(df_ta.index, df_ta.iloc[:,2].values, 'g', lw=2) - plt.title(f"Bollinger Band (BBands) on {s_ticker}") - plt.xlim(df_stock.index[0], df_stock.index[-1]) - plt.xlabel('Time') - plt.ylabel('Share Price ($)') - plt.legend([s_ticker, df_ta.columns[0], df_ta.columns[1], df_ta.columns[2]]) - plt.gca().fill_between(df_ta.index, df_ta.iloc[:,0].values, df_ta.iloc[:,2].values, alpha=.1, color='b') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.show() - - # Intraday - else: - df_ta = ta.bbands(close=df_stock['4. close'], length=ns_parser.n_length, std=ns_parser.n_std, - mamode=ns_parser.s_mamode, offset=ns_parser.n_offset).dropna() - #plot_stock_ta(df_stock['4. close'], s_ticker, df_ta, "BBANDS") + plt.plot(df_stock.index, df_stock['5. adjusted close'].values, color='k', lw=3) + plt.plot(df_ta.index, df_ta.iloc[:,0].values, 'r', lw=2) + plt.plot(df_ta.index, df_ta.iloc[:,1].values, 'b', lw=1.5, ls='--') + plt.plot(df_ta.index, df_ta.iloc[:,2].values, 'g', lw=2) + plt.title(f"Bollinger Band (BBands) on {s_ticker}") + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.xlabel('Time') + plt.ylabel('Share Price ($)') + plt.legend([s_ticker, df_ta.columns[0], df_ta.columns[1], df_ta.columns[2]]) + plt.gca().fill_between(df_ta.index, df_ta.iloc[:,0].values, df_ta.iloc[:,2].values, alpha=.1, color='b') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.show() - plt.plot(df_stock.index, df_stock['4. close'].values, color='k', lw=3) - plt.plot(df_ta.index, df_ta.iloc[:,0].values, 'r', lw=2) - plt.plot(df_ta.index, df_ta.iloc[:,1].values, 'b', lw=1.5, ls='--') - plt.plot(df_ta.index, df_ta.iloc[:,2].values, 'g', lw=2) - plt.title(f"Bollinger Band (BBands) on {s_ticker}") - plt.xlim(df_stock.index[0], df_stock.index[-1]) - plt.xlabel('Time') - plt.ylabel('Share Price ($)') - plt.legend([s_ticker, df_ta.columns[0], df_ta.columns[1], df_ta.columns[2]]) - plt.gca().fill_between(df_ta.index, df_ta.iloc[:,0].values, df_ta.iloc[:,2].values, alpha=.1, color='b') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.show() - print("") + # Intraday + else: + df_ta = ta.bbands(close=df_stock['4. close'], length=ns_parser.n_length, std=ns_parser.n_std, + mamode=ns_parser.s_mamode, offset=ns_parser.n_offset).dropna() + #plot_stock_ta(df_stock['4. close'], s_ticker, df_ta, "BBANDS") - except: - print("") + plt.plot(df_stock.index, df_stock['4. close'].values, color='k', lw=3) + plt.plot(df_ta.index, df_ta.iloc[:,0].values, 'r', lw=2) + plt.plot(df_ta.index, df_ta.iloc[:,1].values, 'b', lw=1.5, ls='--') + plt.plot(df_ta.index, df_ta.iloc[:,2].values, 'g', lw=2) + plt.title(f"Bollinger Band (BBands) on {s_ticker}") + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.xlabel('Time') + plt.ylabel('Share Price ($)') + plt.legend([s_ticker, df_ta.columns[0], df_ta.columns[1], df_ta.columns[2]]) + plt.gca().fill_between(df_ta.index, df_ta.iloc[:,0].values, df_ta.iloc[:,2].values, alpha=.1, color='b') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.show() + print("") diff --git a/technical_analysis/volume.py b/technical_analysis/volume.py index 7266a32cd90..b967e5257f4 100644 --- a/technical_analysis/volume.py +++ b/technical_analysis/volume.py @@ -25,82 +25,77 @@ def ad(l_args, s_ticker, s_interval, df_stock): parser.add_argument('-o', "--offset", action="store", dest="n_offset", type=check_positive, default=0, help='offset') parser.add_argument('--open', action="store_true", default=False, dest="b_use_open", help='uses open value of stock') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return - - # Daily - if s_interval == "1440min": - # Use open stock values - if ns_parser.b_use_open: - df_ta = ta.ad(high=df_stock['2. high'], low=df_stock['3. low'], close=df_stock['5. adjusted close'], - volume=df_stock['6. volume'], offset=ns_parser.n_offset, open_=df_stock['1. open']).dropna() - # Do not use open stock values - else: - df_ta = ta.ad(high=df_stock['2. high'], low=df_stock['3. low'], close=df_stock['5. adjusted close'], - volume=df_stock['6. volume'], offset=ns_parser.n_offset).dropna() - - axPrice = plt.subplot(211) - plt.plot(df_stock.index, df_stock['5. adjusted close'].values, 'k', lw=2) - plt.title(f"Accumulation/Distribution Line (AD) on {s_ticker}") - plt.xlim(df_stock.index[0], df_stock.index[-1]) - plt.ylabel(f'Share Price ($)') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - axVolume = axPrice.twinx() - plt.bar(df_stock.index, df_stock['6. volume'].values, color='k', alpha=0.8, width=.3) - plt.subplot(212) - plt.plot(df_ta.index, df_ta.values, 'b', lw=1) - plt.xlim(df_stock.index[0], df_stock.index[-1]) - plt.axhline(0, linewidth=2, color='k', ls='--') - plt.legend([f'Chaikin Oscillator']) - plt.xlabel('Time') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.show() - - # Intraday - else: - # Use open stock values - if ns_parser.b_use_open: - df_ta = ta.ad(high=df_stock['2. high'], low=df_stock['3. low'], close=df_stock['4. close'], - volume=df_stock['5. volume'], offset=ns_parser.n_offset, open_=df_stock['1. open']).dropna() - # Do not use open stock values - else: - df_ta = ta.ad(high=df_stock['2. high'], low=df_stock['3. low'], close=df_stock['4. close'], - volume=df_stock['5. volume'], offset=ns_parser.n_offset).dropna() - - axPrice = plt.subplot(211) - plt.plot(df_stock.index, df_stock['4. close'].values, 'k', lw=2) - plt.title(f"Accumulation/Distribution Line (AD) on {s_ticker}") - plt.xlim(df_stock.index[0], df_stock.index[-1]) - plt.ylabel(f'Share Price ($)') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - axVolume = axPrice.twinx() - plt.bar(df_stock.index, df_stock['5. volume'].values, color='k', alpha=0.8, width=.3) - plt.subplot(212) - plt.plot(df_ta.index, df_ta.values, 'b', lw=1) - plt.xlim(df_stock.index[0], df_stock.index[-1]) - plt.axhline(0, linewidth=2, color='k', ls='--') - plt.legend([f'Chaikin Oscillator']) - plt.xlabel('Time') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.show() - print("") - - except: - print("") + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") return - + + # Daily + if s_interval == "1440min": + # Use open stock values + if ns_parser.b_use_open: + df_ta = ta.ad(high=df_stock['2. high'], low=df_stock['3. low'], close=df_stock['5. adjusted close'], + volume=df_stock['6. volume'], offset=ns_parser.n_offset, open_=df_stock['1. open']).dropna() + # Do not use open stock values + else: + df_ta = ta.ad(high=df_stock['2. high'], low=df_stock['3. low'], close=df_stock['5. adjusted close'], + volume=df_stock['6. volume'], offset=ns_parser.n_offset).dropna() + + axPrice = plt.subplot(211) + plt.plot(df_stock.index, df_stock['5. adjusted close'].values, 'k', lw=2) + plt.title(f"Accumulation/Distribution Line (AD) on {s_ticker}") + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.ylabel(f'Share Price ($)') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + axVolume = axPrice.twinx() + plt.bar(df_stock.index, df_stock['6. volume'].values, color='k', alpha=0.8, width=.3) + plt.subplot(212) + plt.plot(df_ta.index, df_ta.values, 'b', lw=1) + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.axhline(0, linewidth=2, color='k', ls='--') + plt.legend([f'Chaikin Oscillator']) + plt.xlabel('Time') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.show() + + # Intraday + else: + # Use open stock values + if ns_parser.b_use_open: + df_ta = ta.ad(high=df_stock['2. high'], low=df_stock['3. low'], close=df_stock['4. close'], + volume=df_stock['5. volume'], offset=ns_parser.n_offset, open_=df_stock['1. open']).dropna() + # Do not use open stock values + else: + df_ta = ta.ad(high=df_stock['2. high'], low=df_stock['3. low'], close=df_stock['4. close'], + volume=df_stock['5. volume'], offset=ns_parser.n_offset).dropna() + + axPrice = plt.subplot(211) + plt.plot(df_stock.index, df_stock['4. close'].values, 'k', lw=2) + plt.title(f"Accumulation/Distribution Line (AD) on {s_ticker}") + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.ylabel(f'Share Price ($)') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + axVolume = axPrice.twinx() + plt.bar(df_stock.index, df_stock['5. volume'].values, color='k', alpha=0.8, width=.3) + plt.subplot(212) + plt.plot(df_ta.index, df_ta.values, 'b', lw=1) + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.axhline(0, linewidth=2, color='k', ls='--') + plt.legend([f'Chaikin Oscillator']) + plt.xlabel('Time') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.show() + print("") + # ------------------------------------------------------- OBV ------------------------------------------------------- def obv(l_args, s_ticker, s_interval, df_stock): @@ -115,63 +110,59 @@ def obv(l_args, s_ticker, s_interval, df_stock): parser.add_argument('-o', "--offset", action="store", dest="n_offset", type=check_positive, default=0, help='offset') - try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}\n") - return + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}\n") + return - # Daily - if s_interval == "1440min": - df_ta = ta.obv(close=df_stock['5. adjusted close'], volume=df_stock['6. volume'], offset=ns_parser.n_offset).dropna() + # Daily + if s_interval == "1440min": + df_ta = ta.obv(close=df_stock['5. adjusted close'], volume=df_stock['6. volume'], offset=ns_parser.n_offset).dropna() - axPrice = plt.subplot(211) - plt.plot(df_stock.index, df_stock['5. adjusted close'].values, 'k', lw=2) - plt.title(f"On-Balance Volume (OBV) on {s_ticker}") - plt.xlim(df_stock.index[0], df_stock.index[-1]) - plt.ylabel(f'Share Price ($)') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - axVolume = axPrice.twinx() - plt.bar(df_stock.index, df_stock['6. volume'].values, color='k', alpha=0.8, width=.3) - plt.subplot(212) - plt.plot(df_ta.index, df_ta.values, 'b', lw=1) - plt.xlim(df_stock.index[0], df_stock.index[-1]) - plt.legend([f'OBV']) - plt.xlabel('Time') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.show() - + axPrice = plt.subplot(211) + plt.plot(df_stock.index, df_stock['5. adjusted close'].values, 'k', lw=2) + plt.title(f"On-Balance Volume (OBV) on {s_ticker}") + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.ylabel(f'Share Price ($)') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + axVolume = axPrice.twinx() + plt.bar(df_stock.index, df_stock['6. volume'].values, color='k', alpha=0.8, width=.3) + plt.subplot(212) + plt.plot(df_ta.index, df_ta.values, 'b', lw=1) + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.legend([f'OBV']) + plt.xlabel('Time') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.show() - # Intraday - else: - df_ta = ta.obv(close=df_stock['4. close'], volume=df_stock['5. volume'], offset=ns_parser.n_offset).dropna() - axPrice = plt.subplot(211) - plt.plot(df_stock.index, df_stock['5. adjusted close'].values, 'k', lw=2) - plt.title(f"On-Balance Volume (OBV) on {s_ticker}") - plt.xlim(df_stock.index[0], df_stock.index[-1]) - plt.ylabel(f'Share Price ($)') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - axVolume = axPrice.twinx() - plt.bar(df_stock.index, df_stock['5. volume'].values, color='k', alpha=0.8, width=.3) - plt.subplot(212) - plt.plot(df_ta.index, df_ta.values, 'b', lw=1) - plt.xlim(df_stock.index[0], df_stock.index[-1]) - plt.legend([f'OBV']) - plt.xlabel('Time') - plt.grid(b=True, which='major', color='#666666', linestyle='-') - plt.minorticks_on() - plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) - plt.show() + # Intraday + else: + df_ta = ta.obv(close=df_stock['4. close'], volume=df_stock['5. volume'], offset=ns_parser.n_offset).dropna() - print("") + axPrice = plt.subplot(211) + plt.plot(df_stock.index, df_stock['5. adjusted close'].values, 'k', lw=2) + plt.title(f"On-Balance Volume (OBV) on {s_ticker}") + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.ylabel(f'Share Price ($)') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + axVolume = axPrice.twinx() + plt.bar(df_stock.index, df_stock['5. volume'].values, color='k', alpha=0.8, width=.3) + plt.subplot(212) + plt.plot(df_ta.index, df_ta.values, 'b', lw=1) + plt.xlim(df_stock.index[0], df_stock.index[-1]) + plt.legend([f'OBV']) + plt.xlabel('Time') + plt.grid(b=True, which='major', color='#666666', linestyle='-') + plt.minorticks_on() + plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2) + plt.show() - except: - print("") + print("") From 6c79415767e9a40fc23cd44cabbbea01a9464b20 Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Thu, 25 Feb 2021 11:01:14 +0200 Subject: [PATCH 67/72] Catch exceptions from subprograms in menus --- discovery/disc_menu.py | 91 +++++++++--------- due_diligence/dd_menu.py | 79 +++++++-------- fundamental_analysis/fa_menu.py | 149 +++++++++++++++-------------- prediction_techniques/pred_menu.py | 81 ++++++++-------- sentiment/sen_menu.py | 95 +++++++++--------- technical_analysis/ta_menu.py | 84 ++++++++-------- 6 files changed, 300 insertions(+), 279 deletions(-) diff --git a/discovery/disc_menu.py b/discovery/disc_menu.py index 5e2c0e64d03..5d5fb260e52 100644 --- a/discovery/disc_menu.py +++ b/discovery/disc_menu.py @@ -58,57 +58,60 @@ def disc_menu(): except SystemExit: print("The command selected doesn't exist\n") continue - - if ns_known_args.cmd == 'help': - print_discovery() - elif ns_known_args.cmd == 'q': - # Just leave the DISC menu - return False + try: + if ns_known_args.cmd == 'help': + print_discovery() - elif ns_known_args.cmd == 'quit': - # Abandon the program - return True + elif ns_known_args.cmd == 'q': + # Just leave the DISC menu + return False - # --------------------------------------------------- FINVIZ --------------------------------------------------- - elif ns_known_args.cmd == 'map': - finviz_api.map_sp500(l_args) - - # ------------------------------------------------ ALPHA VANTAGE ----------------------------------------------- - elif ns_known_args.cmd == 'sectors': - alpha_vantage_api.sectors(l_args) - - # ------------------------------------------------ YAHOO FINANCE ------------------------------------------------ - elif ns_known_args.cmd == 'gainers': - yahoo_finance_api.gainers(l_args) + elif ns_known_args.cmd == 'quit': + # Abandon the program + return True - # -------------------------------------------------- SPACHERO -------------------------------------------------- - elif ns_known_args.cmd == 'spachero': - spachero_api.spachero(l_args) + # --------------------------------------------------- FINVIZ --------------------------------------------------- + elif ns_known_args.cmd == 'map': + finviz_api.map_sp500(l_args) - # -------------------------------------------------- UNUSUAL WHALES -------------------------------------------------- - elif ns_known_args.cmd == 'uwhales': - unusual_whales_api.unusual_whales(l_args) + # ------------------------------------------------ ALPHA VANTAGE ----------------------------------------------- + elif ns_known_args.cmd == 'sectors': + alpha_vantage_api.sectors(l_args) - # --------------------------------------------------- FIDELITY --------------------------------------------------- - elif ns_known_args.cmd == 'orders': - fidelity_api.orders(l_args) + # ------------------------------------------------ YAHOO FINANCE ------------------------------------------------ + elif ns_known_args.cmd == 'gainers': + yahoo_finance_api.gainers(l_args) - # ------------------------------------------------ SIMPLY WALL ST ------------------------------------------------ - elif ns_known_args.cmd == 'simply_wallst': - simply_wallst_api.simply_wallst(l_args) + # -------------------------------------------------- SPACHERO -------------------------------------------------- + elif ns_known_args.cmd == 'spachero': + spachero_api.spachero(l_args) - # ------------------------------------------------ SEEKING ALPHA ------------------------------------------------ - elif ns_known_args.cmd == 'up_earnings': - seeking_alpha_api.earnings_release_dates(l_args) + # -------------------------------------------------- UNUSUAL WHALES -------------------------------------------------- + elif ns_known_args.cmd == 'uwhales': + unusual_whales_api.unusual_whales(l_args) - # ------------------------------------------------ SHORT_INTEREST ------------------------------------------------ - elif ns_known_args.cmd == 'high_short': - short_interest_api.high_short_interest(l_args) - - elif ns_known_args.cmd == 'low_float': - short_interest_api.low_float(l_args) + # --------------------------------------------------- FIDELITY --------------------------------------------------- + elif ns_known_args.cmd == 'orders': + fidelity_api.orders(l_args) - # ------------------------------------------------------------------------------------------------------------ - else: - print("Command not recognized!") + # ------------------------------------------------ SIMPLY WALL ST ------------------------------------------------ + elif ns_known_args.cmd == 'simply_wallst': + simply_wallst_api.simply_wallst(l_args) + + # ------------------------------------------------ SEEKING ALPHA ------------------------------------------------ + elif ns_known_args.cmd == 'up_earnings': + seeking_alpha_api.earnings_release_dates(l_args) + + # ------------------------------------------------ SHORT_INTEREST ------------------------------------------------ + elif ns_known_args.cmd == 'high_short': + short_interest_api.high_short_interest(l_args) + + elif ns_known_args.cmd == 'low_float': + short_interest_api.low_float(l_args) + + # ------------------------------------------------------------------------------------------------------------ + else: + print("Command not recognized!") + except Exception as exc: + print("ERROR:", exc) diff --git a/due_diligence/dd_menu.py b/due_diligence/dd_menu.py index 118faec9b5c..564eee92a9b 100644 --- a/due_diligence/dd_menu.py +++ b/due_diligence/dd_menu.py @@ -67,55 +67,58 @@ def dd_menu(df_stock, s_ticker, s_start, s_interval): print("The command selected doesn't exist\n") continue - if ns_known_args.cmd == 'help': - print_due_diligence(s_ticker, s_start, s_interval) + try: + if ns_known_args.cmd == 'help': + print_due_diligence(s_ticker, s_start, s_interval) - elif ns_known_args.cmd == 'q': - # Just leave the DD menu - return False + elif ns_known_args.cmd == 'q': + # Just leave the DD menu + return False - elif ns_known_args.cmd == 'quit': - # Abandon the program - return True + elif ns_known_args.cmd == 'quit': + # Abandon the program + return True - # REDDIT API - elif ns_known_args.cmd == 'red': - r_api.due_diligence(l_args, s_ticker) + # REDDIT API + elif ns_known_args.cmd == 'red': + r_api.due_diligence(l_args, s_ticker) - # FINVIZ API - elif ns_known_args.cmd == 'insider': - fvz_api.insider(l_args, s_ticker) + # FINVIZ API + elif ns_known_args.cmd == 'insider': + fvz_api.insider(l_args, s_ticker) - elif ns_known_args.cmd == 'news': - fvz_api.news(l_args, s_ticker) + elif ns_known_args.cmd == 'news': + fvz_api.news(l_args, s_ticker) - elif ns_known_args.cmd == 'analyst': - fvz_api.analyst(l_args, s_ticker) + elif ns_known_args.cmd == 'analyst': + fvz_api.analyst(l_args, s_ticker) - # BUSINESS INSIDER API - elif ns_known_args.cmd == 'pt': - bi_api.price_target_from_analysts(l_args, df_stock, s_ticker, s_start, s_interval) + # BUSINESS INSIDER API + elif ns_known_args.cmd == 'pt': + bi_api.price_target_from_analysts(l_args, df_stock, s_ticker, s_start, s_interval) - elif ns_known_args.cmd == 'est': - bi_api.estimates(l_args, s_ticker) + elif ns_known_args.cmd == 'est': + bi_api.estimates(l_args, s_ticker) - elif ns_known_args.cmd == 'ins': - bi_api.insider_activity(l_args, df_stock, s_ticker, s_start, s_interval) + elif ns_known_args.cmd == 'ins': + bi_api.insider_activity(l_args, df_stock, s_ticker, s_start, s_interval) - # FINANCIAL MODELING PREP API - elif ns_known_args.cmd == 'rating': - fmp_api.rating(l_args, s_ticker) + # FINANCIAL MODELING PREP API + elif ns_known_args.cmd == 'rating': + fmp_api.rating(l_args, s_ticker) - # MARKET WATCH API - elif ns_known_args.cmd == 'sec': - mw_api.sec_fillings(l_args, s_ticker) + # MARKET WATCH API + elif ns_known_args.cmd == 'sec': + mw_api.sec_fillings(l_args, s_ticker) - elif ns_known_args.cmd == 'warnings': - mw_api.sean_seah_warnings(l_args, s_ticker) + elif ns_known_args.cmd == 'warnings': + mw_api.sean_seah_warnings(l_args, s_ticker) - # QUANDL API - elif ns_known_args.cmd == 'short': - q_api.short_interest(l_args, s_ticker, s_start) + # QUANDL API + elif ns_known_args.cmd == 'short': + q_api.short_interest(l_args, s_ticker, s_start) - else: - print("Command not recognized!") + else: + print("Command not recognized!") + except Exception as exc: + print("ERROR:", exc) diff --git a/fundamental_analysis/fa_menu.py b/fundamental_analysis/fa_menu.py index 6631712d1e2..60a029a1860 100644 --- a/fundamental_analysis/fa_menu.py +++ b/fundamental_analysis/fa_menu.py @@ -116,106 +116,109 @@ def fa_menu(s_ticker, s_start, s_interval): #if ns_known_args.cmd == 'info': # info(l_args, s_ticker) - if ns_known_args.cmd == 'help': - print_fundamental_analysis(s_ticker, s_start, s_interval) + try: + if ns_known_args.cmd == 'help': + print_fundamental_analysis(s_ticker, s_start, s_interval) - elif ns_known_args.cmd == 'q': - # Just leave the FA menu - return False + elif ns_known_args.cmd == 'q': + # Just leave the FA menu + return False - elif ns_known_args.cmd == 'quit': - # Abandon the program - return True + elif ns_known_args.cmd == 'quit': + # Abandon the program + return True - # BUSINESS INSIDER API - elif ns_known_args.cmd == 'mgmt': - bi_api.management(l_args, s_ticker) + # BUSINESS INSIDER API + elif ns_known_args.cmd == 'mgmt': + bi_api.management(l_args, s_ticker) - # FINVIZ API - elif ns_known_args.cmd == 'screener': - fvz_api.screener(l_args, s_ticker) + # FINVIZ API + elif ns_known_args.cmd == 'screener': + fvz_api.screener(l_args, s_ticker) - # MARKET WATCH API - elif ns_known_args.cmd == 'income': - mw_api.income(l_args, s_ticker) + # MARKET WATCH API + elif ns_known_args.cmd == 'income': + mw_api.income(l_args, s_ticker) - elif ns_known_args.cmd == 'assets': - mw_api.assets(l_args, s_ticker) + elif ns_known_args.cmd == 'assets': + mw_api.assets(l_args, s_ticker) - elif ns_known_args.cmd == 'liabilities': - mw_api.liabilities(l_args, s_ticker) + elif ns_known_args.cmd == 'liabilities': + mw_api.liabilities(l_args, s_ticker) - elif ns_known_args.cmd == 'operating': - mw_api.operating(l_args, s_ticker) + elif ns_known_args.cmd == 'operating': + mw_api.operating(l_args, s_ticker) - elif ns_known_args.cmd == 'investing': - mw_api.investing(l_args, s_ticker) + elif ns_known_args.cmd == 'investing': + mw_api.investing(l_args, s_ticker) - elif ns_known_args.cmd == 'financing': - mw_api.financing(l_args, s_ticker) + elif ns_known_args.cmd == 'financing': + mw_api.financing(l_args, s_ticker) - # YAHOO FINANCE API - elif ns_known_args.cmd == 'info': - yf_api.info(l_args, s_ticker) + # YAHOO FINANCE API + elif ns_known_args.cmd == 'info': + yf_api.info(l_args, s_ticker) - elif ns_known_args.cmd == 'shrs': - yf_api.shareholders(l_args, s_ticker) + elif ns_known_args.cmd == 'shrs': + yf_api.shareholders(l_args, s_ticker) - elif ns_known_args.cmd == 'sust': - yf_api.sustainability(l_args, s_ticker) + elif ns_known_args.cmd == 'sust': + yf_api.sustainability(l_args, s_ticker) - elif ns_known_args.cmd == 'cal': - yf_api.calendar_earnings(l_args, s_ticker) + elif ns_known_args.cmd == 'cal': + yf_api.calendar_earnings(l_args, s_ticker) - # ALPHA VANTAGE API - elif ns_known_args.cmd == 'overview': - av_api.overview(l_args, s_ticker) + # ALPHA VANTAGE API + elif ns_known_args.cmd == 'overview': + av_api.overview(l_args, s_ticker) - elif ns_known_args.cmd == 'incom': - av_api.income_statement(l_args, s_ticker) + elif ns_known_args.cmd == 'incom': + av_api.income_statement(l_args, s_ticker) - elif ns_known_args.cmd == 'balance': - av_api.balance_sheet(l_args, s_ticker) + elif ns_known_args.cmd == 'balance': + av_api.balance_sheet(l_args, s_ticker) - elif ns_known_args.cmd == 'cash': - av_api.cash_flow(l_args, s_ticker) + elif ns_known_args.cmd == 'cash': + av_api.cash_flow(l_args, s_ticker) - elif ns_known_args.cmd == 'earnings': - av_api.earnings(l_args, s_ticker) + elif ns_known_args.cmd == 'earnings': + av_api.earnings(l_args, s_ticker) - # FINANCIAL MODELING PREP API - # Details: - elif ns_known_args.cmd == 'profile': - fmp_api.profile(l_args, s_ticker) + # FINANCIAL MODELING PREP API + # Details: + elif ns_known_args.cmd == 'profile': + fmp_api.profile(l_args, s_ticker) - elif ns_known_args.cmd == 'quote': - fmp_api.quote(l_args, s_ticker) + elif ns_known_args.cmd == 'quote': + fmp_api.quote(l_args, s_ticker) - elif ns_known_args.cmd == 'enterprise': - fmp_api.enterprise(l_args, s_ticker) + elif ns_known_args.cmd == 'enterprise': + fmp_api.enterprise(l_args, s_ticker) - elif ns_known_args.cmd == 'dcf': - fmp_api.discounted_cash_flow(l_args, s_ticker) + elif ns_known_args.cmd == 'dcf': + fmp_api.discounted_cash_flow(l_args, s_ticker) - # Financial statement: - elif ns_known_args.cmd == 'inc': - fmp_api.income_statement(l_args, s_ticker) + # Financial statement: + elif ns_known_args.cmd == 'inc': + fmp_api.income_statement(l_args, s_ticker) - elif ns_known_args.cmd == 'bal': - fmp_api.balance_sheet(l_args, s_ticker) + elif ns_known_args.cmd == 'bal': + fmp_api.balance_sheet(l_args, s_ticker) - elif ns_known_args.cmd == 'cashf': - fmp_api.cash_flow(l_args, s_ticker) + elif ns_known_args.cmd == 'cashf': + fmp_api.cash_flow(l_args, s_ticker) - # Ratios: - elif ns_known_args.cmd == 'metrics': - fmp_api.key_metrics(l_args, s_ticker) + # Ratios: + elif ns_known_args.cmd == 'metrics': + fmp_api.key_metrics(l_args, s_ticker) - elif ns_known_args.cmd == 'ratios': - fmp_api.financial_ratios(l_args, s_ticker) + elif ns_known_args.cmd == 'ratios': + fmp_api.financial_ratios(l_args, s_ticker) - elif ns_known_args.cmd == 'growth': - fmp_api.financial_statement_growth(l_args, s_ticker) + elif ns_known_args.cmd == 'growth': + fmp_api.financial_statement_growth(l_args, s_ticker) - else: - print("Command not recognized!") + else: + print("Command not recognized!") + except Exception as exc: + print("ERROR:", exc) diff --git a/prediction_techniques/pred_menu.py b/prediction_techniques/pred_menu.py index 568cb791a5d..ee43a8b4b1e 100644 --- a/prediction_techniques/pred_menu.py +++ b/prediction_techniques/pred_menu.py @@ -66,56 +66,59 @@ def pred_menu(df_stock, s_ticker, s_start, s_interval): print("The command selected doesn't exist\n") continue - if ns_known_args.cmd == 'help': - print_prediction(s_ticker, s_start, s_interval) + try: + if ns_known_args.cmd == 'help': + print_prediction(s_ticker, s_start, s_interval) - elif ns_known_args.cmd == 'q': - # Just leave the FA menu - return False + elif ns_known_args.cmd == 'q': + # Just leave the FA menu + return False - elif ns_known_args.cmd == 'quit': - # Abandon the program - return True + elif ns_known_args.cmd == 'quit': + # Abandon the program + return True - # ------------------------------------------ SIMPLE MOVING AVERAGE ------------------------------------------ - elif ns_known_args.cmd == 'sma': - sma.simple_moving_average(l_args, s_ticker, s_interval, df_stock) + # ------------------------------------------ SIMPLE MOVING AVERAGE ------------------------------------------ + elif ns_known_args.cmd == 'sma': + sma.simple_moving_average(l_args, s_ticker, s_interval, df_stock) - # ------------------------------------------- k NEAREST NEIGHBORS ------------------------------------------ - elif ns_known_args.cmd == 'knn': - knn.k_nearest_neighbors(l_args, s_ticker, s_interval, df_stock) + # ------------------------------------------- k NEAREST NEIGHBORS ------------------------------------------ + elif ns_known_args.cmd == 'knn': + knn.k_nearest_neighbors(l_args, s_ticker, s_interval, df_stock) - # ----------------------------------------------- REGRESSION ------------------------------------------------- - elif ns_known_args.cmd == 'linear': - regression.regression(l_args, s_ticker, s_interval, df_stock, regression.LINEAR) + # ----------------------------------------------- REGRESSION ------------------------------------------------- + elif ns_known_args.cmd == 'linear': + regression.regression(l_args, s_ticker, s_interval, df_stock, regression.LINEAR) - elif ns_known_args.cmd == 'quadratic': - regression.regression(l_args, s_ticker, s_interval, df_stock, regression.QUADRATIC) + elif ns_known_args.cmd == 'quadratic': + regression.regression(l_args, s_ticker, s_interval, df_stock, regression.QUADRATIC) - elif ns_known_args.cmd == 'cubic': - regression.regression(l_args, s_ticker, s_interval, df_stock, regression.CUBIC) + elif ns_known_args.cmd == 'cubic': + regression.regression(l_args, s_ticker, s_interval, df_stock, regression.CUBIC) - elif ns_known_args.cmd == 'regression': - regression.regression(l_args, s_ticker, s_interval, df_stock, regression.USER_INPUT) + elif ns_known_args.cmd == 'regression': + regression.regression(l_args, s_ticker, s_interval, df_stock, regression.USER_INPUT) - # ------------------------------------------------- ARIMA ------------------------------------------------- - elif ns_known_args.cmd == 'arima': - arima.arima(l_args, s_ticker, s_interval, df_stock) + # ------------------------------------------------- ARIMA ------------------------------------------------- + elif ns_known_args.cmd == 'arima': + arima.arima(l_args, s_ticker, s_interval, df_stock) - # ------------------------------------------------ FBPROPHET ------------------------------------------------ - elif ns_known_args.cmd == 'prophet': - fbprophet.fbprophet(l_args, s_ticker, s_interval, df_stock) + # ------------------------------------------------ FBPROPHET ------------------------------------------------ + elif ns_known_args.cmd == 'prophet': + fbprophet.fbprophet(l_args, s_ticker, s_interval, df_stock) - # ---------------------------------------------- NEURAL NETWORK ---------------------------------------------- - elif ns_known_args.cmd == 'mlp': - neural_networks.mlp(l_args, s_ticker, s_interval, df_stock) + # ---------------------------------------------- NEURAL NETWORK ---------------------------------------------- + elif ns_known_args.cmd == 'mlp': + neural_networks.mlp(l_args, s_ticker, s_interval, df_stock) - elif ns_known_args.cmd == 'rnn': - neural_networks.rnn(l_args, s_ticker, s_interval, df_stock) + elif ns_known_args.cmd == 'rnn': + neural_networks.rnn(l_args, s_ticker, s_interval, df_stock) - elif ns_known_args.cmd == 'lstm': - neural_networks.lstm(l_args, s_ticker, s_interval, df_stock) + elif ns_known_args.cmd == 'lstm': + neural_networks.lstm(l_args, s_ticker, s_interval, df_stock) - # ------------------------------------------------------------------------------------------------------------ - else: - print("Command not recognized!") + # ------------------------------------------------------------------------------------------------------------ + else: + print("Command not recognized!") + except Exception as exc: + print("ERROR:", exc) diff --git a/sentiment/sen_menu.py b/sentiment/sen_menu.py index 3f9a16e3a04..b7df2a50ea2 100644 --- a/sentiment/sen_menu.py +++ b/sentiment/sen_menu.py @@ -68,66 +68,71 @@ def sen_menu(s_ticker, s_start): print("The command selected doesn't exist\n") continue - if ns_known_args.cmd == 'help': - print_sentiment() + try: - elif ns_known_args.cmd == 'q': - # Just leave the DISC menu - return False - elif ns_known_args.cmd == 'quit': - # Abandon the program - return True + if ns_known_args.cmd == 'help': + print_sentiment() - # ---------------------------------------------------- REDDIT --------------------------------------------------- - elif ns_known_args.cmd == 'watchlist': - reddit_api.watchlist(l_args) + elif ns_known_args.cmd == 'q': + # Just leave the DISC menu + return False - elif ns_known_args.cmd == 'spac': - reddit_api.spac(l_args) + elif ns_known_args.cmd == 'quit': + # Abandon the program + return True - elif ns_known_args.cmd == 'spac_c': - reddit_api.spac_community(l_args) + # ---------------------------------------------------- REDDIT --------------------------------------------------- + elif ns_known_args.cmd == 'watchlist': + reddit_api.watchlist(l_args) - elif ns_known_args.cmd == 'wsb': - reddit_api.wsb_community(l_args) + elif ns_known_args.cmd == 'spac': + reddit_api.spac(l_args) - elif ns_known_args.cmd == 'popular': - reddit_api.popular_tickers(l_args) + elif ns_known_args.cmd == 'spac_c': + reddit_api.spac_community(l_args) - # ---------------------------------------------------- STOCKTWITS --------------------------------------------------- - elif ns_known_args.cmd == 'bullbear': - stocktwits_api.bullbear(l_args, s_ticker) + elif ns_known_args.cmd == 'wsb': + reddit_api.wsb_community(l_args) - elif ns_known_args.cmd == 'messages': - stocktwits_api.messages(l_args, s_ticker) + elif ns_known_args.cmd == 'popular': + reddit_api.popular_tickers(l_args) - elif ns_known_args.cmd == 'trending': - stocktwits_api.trending(l_args) + # ---------------------------------------------------- STOCKTWITS --------------------------------------------------- + elif ns_known_args.cmd == 'bullbear': + stocktwits_api.bullbear(l_args, s_ticker) - elif ns_known_args.cmd == 'stalker': - stocktwits_api.stalker(l_args) + elif ns_known_args.cmd == 'messages': + stocktwits_api.messages(l_args, s_ticker) - # ----------------------------------------------------- TWITTER --------------------------------------------------- - elif ns_known_args.cmd == 'infer': - twitter_api.inference(l_args, s_ticker) + elif ns_known_args.cmd == 'trending': + stocktwits_api.trending(l_args) - elif ns_known_args.cmd == 'sentiment': - twitter_api.sentiment(l_args, s_ticker) + elif ns_known_args.cmd == 'stalker': + stocktwits_api.stalker(l_args) - # ----------------------------------------------------- GOOGLE --------------------------------------------------- - elif ns_known_args.cmd == 'mentions': - google_api.mentions(l_args, s_ticker, s_start) + # ----------------------------------------------------- TWITTER --------------------------------------------------- + elif ns_known_args.cmd == 'infer': + twitter_api.inference(l_args, s_ticker) - elif ns_known_args.cmd == 'regions': - google_api.regions(l_args, s_ticker) + elif ns_known_args.cmd == 'sentiment': + twitter_api.sentiment(l_args, s_ticker) - elif ns_known_args.cmd == 'queries': - google_api.queries(l_args, s_ticker) + # ----------------------------------------------------- GOOGLE --------------------------------------------------- + elif ns_known_args.cmd == 'mentions': + google_api.mentions(l_args, s_ticker, s_start) - elif ns_known_args.cmd == 'rise': - google_api.rise(l_args, s_ticker) + elif ns_known_args.cmd == 'regions': + google_api.regions(l_args, s_ticker) - # ------------------------------------------------------------------------------------------------------------ - else: - print("Command not recognized!") + elif ns_known_args.cmd == 'queries': + google_api.queries(l_args, s_ticker) + + elif ns_known_args.cmd == 'rise': + google_api.rise(l_args, s_ticker) + + # ------------------------------------------------------------------------------------------------------------ + else: + print("Command not recognized!") + except Exception as exc: + print("ERROR:", exc) diff --git a/technical_analysis/ta_menu.py b/technical_analysis/ta_menu.py index 207966e6f7b..0bed1a0fa95 100644 --- a/technical_analysis/ta_menu.py +++ b/technical_analysis/ta_menu.py @@ -69,58 +69,62 @@ def ta_menu(df_stock, s_ticker, s_start, s_interval): print("The command selected doesn't exist\n") continue - if ns_known_args.cmd == 'help': - print_technical_analysis(s_ticker, s_start, s_interval) + try: - elif ns_known_args.cmd == 'q': - # Just leave the FA menu - return False + if ns_known_args.cmd == 'help': + print_technical_analysis(s_ticker, s_start, s_interval) - elif ns_known_args.cmd == 'quit': - # Abandon the program - return True + elif ns_known_args.cmd == 'q': + # Just leave the FA menu + return False - # -------------------------------------------------- OVERLAP -------------------------------------------------- - elif ns_known_args.cmd == 'ema': - ta_overlap.ema(l_args, s_ticker, s_interval, df_stock) + elif ns_known_args.cmd == 'quit': + # Abandon the program + return True - elif ns_known_args.cmd == 'sma': - ta_overlap.sma(l_args, s_ticker, s_interval, df_stock) + # -------------------------------------------------- OVERLAP -------------------------------------------------- + elif ns_known_args.cmd == 'ema': + ta_overlap.ema(l_args, s_ticker, s_interval, df_stock) - elif ns_known_args.cmd == 'vwap': - ta_overlap.vwap(l_args, s_ticker, s_interval, df_stock) + elif ns_known_args.cmd == 'sma': + ta_overlap.sma(l_args, s_ticker, s_interval, df_stock) - # --------------------------------------------------- MOMENTUM --------------------------------------------------- - elif ns_known_args.cmd == 'cci': - ta_momentum.cci(l_args, s_ticker, s_interval, df_stock) + elif ns_known_args.cmd == 'vwap': + ta_overlap.vwap(l_args, s_ticker, s_interval, df_stock) - elif ns_known_args.cmd == 'macd': - ta_momentum.macd(l_args, s_ticker, s_interval, df_stock) + # --------------------------------------------------- MOMENTUM --------------------------------------------------- + elif ns_known_args.cmd == 'cci': + ta_momentum.cci(l_args, s_ticker, s_interval, df_stock) - elif ns_known_args.cmd == 'rsi': - ta_momentum.rsi(l_args, s_ticker, s_interval, df_stock) + elif ns_known_args.cmd == 'macd': + ta_momentum.macd(l_args, s_ticker, s_interval, df_stock) - elif ns_known_args.cmd == 'stoch': - ta_momentum.stoch(l_args, s_ticker, s_interval, df_stock) + elif ns_known_args.cmd == 'rsi': + ta_momentum.rsi(l_args, s_ticker, s_interval, df_stock) - # ---------------------------------------------------- TREND ---------------------------------------------------- - elif ns_known_args.cmd == 'adx': - ta_trend.adx(l_args, s_ticker, s_interval, df_stock) + elif ns_known_args.cmd == 'stoch': + ta_momentum.stoch(l_args, s_ticker, s_interval, df_stock) - elif ns_known_args.cmd == 'aroon': - ta_trend.aroon(l_args, s_ticker, s_interval, df_stock) + # ---------------------------------------------------- TREND ---------------------------------------------------- + elif ns_known_args.cmd == 'adx': + ta_trend.adx(l_args, s_ticker, s_interval, df_stock) - # -------------------------------------------------- VOLATILITY -------------------------------------------------- - elif ns_known_args.cmd == 'bbands': - ta_volatility.bbands(l_args, s_ticker, s_interval, df_stock) + elif ns_known_args.cmd == 'aroon': + ta_trend.aroon(l_args, s_ticker, s_interval, df_stock) - # ---------------------------------------------------- VOLUME ---------------------------------------------------- - elif ns_known_args.cmd == 'ad': - ta_volume.ad(l_args, s_ticker, s_interval, df_stock) + # -------------------------------------------------- VOLATILITY -------------------------------------------------- + elif ns_known_args.cmd == 'bbands': + ta_volatility.bbands(l_args, s_ticker, s_interval, df_stock) - elif ns_known_args.cmd == 'obv': - ta_volume.obv(l_args, s_ticker, s_interval, df_stock) + # ---------------------------------------------------- VOLUME ---------------------------------------------------- + elif ns_known_args.cmd == 'ad': + ta_volume.ad(l_args, s_ticker, s_interval, df_stock) - # ------------------------------------------------------------------------------------------------------------ - else: - print("Command not recognized!") + elif ns_known_args.cmd == 'obv': + ta_volume.obv(l_args, s_ticker, s_interval, df_stock) + + # ------------------------------------------------------------------------------------------------------------ + else: + print("Command not recognized!") + except Exception as exc: + print("ERROR:", exc) From 7cbe4ef9a88c011427ee46e6bb2c1a29257b7b8c Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Thu, 25 Feb 2021 11:06:36 +0200 Subject: [PATCH 68/72] Make some imports late to allow running without all requirements --- prediction_techniques/fbprophet.py | 2 +- prediction_techniques/neural_networks.py | 4 ++-- sentiment/twitter_api.py | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/prediction_techniques/fbprophet.py b/prediction_techniques/fbprophet.py index 4daedddb444..3d6beb52492 100644 --- a/prediction_techniques/fbprophet.py +++ b/prediction_techniques/fbprophet.py @@ -7,7 +7,6 @@ from pandas.plotting import register_matplotlib_converters from helper_funcs import get_next_stock_market_days, check_positive register_matplotlib_converters() -from fbprophet import Prophet import warnings warnings.simplefilter("ignore") @@ -32,6 +31,7 @@ def fbprophet(l_args, s_ticker, s_interval, df_stock): df_stock = df_stock.rename(columns={"date": "ds", "5. adjusted close": "y"}) df_stock['ds'] = pd.to_datetime(df_stock['ds']) + from fbprophet import Prophet model = Prophet(yearly_seasonality=False, daily_seasonality=False) model.fit(df_stock) diff --git a/prediction_techniques/neural_networks.py b/prediction_techniques/neural_networks.py index 21886f308e9..f28425424f0 100644 --- a/prediction_techniques/neural_networks.py +++ b/prediction_techniques/neural_networks.py @@ -12,8 +12,6 @@ register_matplotlib_converters() from TimeSeriesCrossValidation import splitTrain from sklearn.preprocessing import MinMaxScaler, StandardScaler -from tensorflow.keras.models import Sequential -from tensorflow.keras.layers import LSTM, SimpleRNN, Dense, Dropout import config_neural_network_models as cfg_nn_models @@ -26,6 +24,8 @@ simplefilter(action='ignore', category=FutureWarning) # ---------------------------------------------------------------------------------------------------- def build_neural_network_model(Recurrent_Neural_Network, n_inputs, n_days): + from tensorflow.keras.models import Sequential + from tensorflow.keras.layers import LSTM, SimpleRNN, Dense, Dropout model = Sequential() for idx_layer, d_layer in enumerate(Recurrent_Neural_Network): diff --git a/sentiment/twitter_api.py b/sentiment/twitter_api.py index 11feda577a4..7019be01e4b 100644 --- a/sentiment/twitter_api.py +++ b/sentiment/twitter_api.py @@ -2,7 +2,6 @@ import argparse from datetime import datetime, timedelta import dateutil.parser -import flair import matplotlib.pyplot as plt import pandas as pd import numpy as np @@ -14,6 +13,7 @@ from helper_funcs import clean_tweet, get_data # ------------------------------------------------- INFERENCE ------------------------------------------------- def inference(l_args, s_ticker): + import flair parser = argparse.ArgumentParser(prog='infer', description="""Print quick sentiment inference from last tweets that contain the ticker. This model splits the text into character-level @@ -107,6 +107,7 @@ def inference(l_args, s_ticker): # ------------------------------------------------- SENTIMENT ------------------------------------------------- def sentiment(l_args, s_ticker): + import flair parser = argparse.ArgumentParser(prog='sen', description="""Plot in-depth sentiment predicted from tweets from last days that contain pre-defined ticker. This model splits the text into character-level From 431e40c583c9f3cad3bf78c7711fd3824420b45a Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Thu, 25 Feb 2021 11:21:55 +0200 Subject: [PATCH 69/72] Late-import modules in menus --- discovery/disc_menu.py | 19 +++++++++---------- due_diligence/dd_menu.py | 14 ++++++-------- fundamental_analysis/fa_menu.py | 13 ++++++------- prediction_techniques/pred_menu.py | 13 ++++++------- sentiment/sen_menu.py | 10 ++++------ 5 files changed, 31 insertions(+), 38 deletions(-) diff --git a/discovery/disc_menu.py b/discovery/disc_menu.py index 5d5fb260e52..111d8230611 100644 --- a/discovery/disc_menu.py +++ b/discovery/disc_menu.py @@ -1,15 +1,5 @@ import argparse -from discovery import alpha_vantage_api -from discovery import fidelity_api -from discovery import finviz_api -from discovery import seeking_alpha_api -from discovery import short_interest_api -from discovery import simply_wallst_api -from discovery import spachero_api -from discovery import unusual_whales_api -from discovery import yahoo_finance_api - # ----------------------------------------------------------------------------------------------------------------------- def print_discovery(): @@ -36,6 +26,15 @@ def print_discovery(): # ---------------------------------------------------- MENU ---------------------------------------------------- def disc_menu(): + from discovery import alpha_vantage_api + from discovery import fidelity_api + from discovery import finviz_api + from discovery import seeking_alpha_api + from discovery import short_interest_api + from discovery import simply_wallst_api + from discovery import spachero_api + from discovery import unusual_whales_api + from discovery import yahoo_finance_api # Add list of arguments that the discovery parser accepts disc_parser = argparse.ArgumentParser(prog='discovery', add_help=False) diff --git a/due_diligence/dd_menu.py b/due_diligence/dd_menu.py index 564eee92a9b..8b441ec945d 100644 --- a/due_diligence/dd_menu.py +++ b/due_diligence/dd_menu.py @@ -1,13 +1,5 @@ import argparse -from due_diligence import business_insider_api as bi_api -from due_diligence import financial_modeling_prep_api as fmp_api -from due_diligence import finviz_api as fvz_api -from due_diligence import market_watch_api as mw_api -from due_diligence import quandl_api as q_api -from due_diligence import reddit_api as r_api - - # ----------------------------------------------------------------------------------------------------------------------- def print_due_diligence(s_ticker, s_start, s_interval): """ Print help """ @@ -41,6 +33,12 @@ def print_due_diligence(s_ticker, s_start, s_interval): # ---------------------------------------------------- MENU ---------------------------------------------------- def dd_menu(df_stock, s_ticker, s_start, s_interval): + from due_diligence import business_insider_api as bi_api + from due_diligence import financial_modeling_prep_api as fmp_api + from due_diligence import finviz_api as fvz_api + from due_diligence import market_watch_api as mw_api + from due_diligence import quandl_api as q_api + from due_diligence import reddit_api as r_api # Add list of arguments that the due diligence parser accepts dd_parser = argparse.ArgumentParser(prog='dd', add_help=False) diff --git a/fundamental_analysis/fa_menu.py b/fundamental_analysis/fa_menu.py index 60a029a1860..2b35238ff46 100644 --- a/fundamental_analysis/fa_menu.py +++ b/fundamental_analysis/fa_menu.py @@ -1,12 +1,5 @@ import argparse -from fundamental_analysis import alpha_vantage_api as av_api -from fundamental_analysis import business_insider_api as bi_api -from fundamental_analysis import financial_modeling_prep_api as fmp_api -from fundamental_analysis import finviz_api as fvz_api -from fundamental_analysis import market_watch_api as mw_api -from fundamental_analysis import yahoo_finance_api as yf_api - # ----------------------------------------------------------------------------------------------------------------------- def print_fundamental_analysis(s_ticker, s_start, s_interval): @@ -86,6 +79,12 @@ def info(l_args, s_ticker): # ---------------------------------------------------- MENU ---------------------------------------------------- def fa_menu(s_ticker, s_start, s_interval): + from fundamental_analysis import alpha_vantage_api as av_api + from fundamental_analysis import business_insider_api as bi_api + from fundamental_analysis import financial_modeling_prep_api as fmp_api + from fundamental_analysis import finviz_api as fvz_api + from fundamental_analysis import market_watch_api as mw_api + from fundamental_analysis import yahoo_finance_api as yf_api # Add list of arguments that the fundamental analysis parser accepts fa_parser = argparse.ArgumentParser(prog='fa', add_help=False) diff --git a/prediction_techniques/pred_menu.py b/prediction_techniques/pred_menu.py index ee43a8b4b1e..ffc77fba333 100644 --- a/prediction_techniques/pred_menu.py +++ b/prediction_techniques/pred_menu.py @@ -4,12 +4,6 @@ from pandas.plotting import register_matplotlib_converters register_matplotlib_converters() -from prediction_techniques import sma -from prediction_techniques import knn -from prediction_techniques import regression -from prediction_techniques import arima -from prediction_techniques import fbprophet -from prediction_techniques import neural_networks # ----------------------------------------------------------------------------------------------------------------------- def print_prediction(s_ticker, s_start, s_interval): @@ -43,7 +37,12 @@ def print_prediction(s_ticker, s_start, s_interval): # ---------------------------------------------------- MENU ---------------------------------------------------- def pred_menu(df_stock, s_ticker, s_start, s_interval): - + from prediction_techniques import sma + from prediction_techniques import knn + from prediction_techniques import regression + from prediction_techniques import arima + from prediction_techniques import fbprophet + from prediction_techniques import neural_networks # Add list of arguments that the prediction techniques parser accepts pred_parser = argparse.ArgumentParser(prog='pred', add_help=False) pred_parser.add_argument('cmd', choices=['help', 'q', 'quit', diff --git a/sentiment/sen_menu.py b/sentiment/sen_menu.py index b7df2a50ea2..a4f1d700a58 100644 --- a/sentiment/sen_menu.py +++ b/sentiment/sen_menu.py @@ -1,10 +1,5 @@ import argparse -from sentiment import google_api -from sentiment import reddit_api -from sentiment import stocktwits_api -from sentiment import twitter_api - # ----------------------------------------------------------------------------------------------------------------------- def print_sentiment(): @@ -44,7 +39,10 @@ def print_sentiment(): # ---------------------------------------------------- MENU ---------------------------------------------------- def sen_menu(s_ticker, s_start): - + from sentiment import google_api + from sentiment import reddit_api + from sentiment import stocktwits_api + from sentiment import twitter_api # Add list of arguments that the discovery parser accepts sen_parser = argparse.ArgumentParser(prog='sen', add_help=False) sen_parser.add_argument('cmd', choices=['help', 'q', 'quit', From c6032c59d54c4adcc82f30983a062522b471b898 Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Thu, 25 Feb 2021 14:33:38 +0200 Subject: [PATCH 70/72] DRY off research menu --- res_menu.py | 212 +++++++++++----------------------------------------- 1 file changed, 44 insertions(+), 168 deletions(-) diff --git a/res_menu.py b/res_menu.py index e103c05347b..35453a44b54 100644 --- a/res_menu.py +++ b/res_menu.py @@ -34,9 +34,47 @@ def print_research(): return +def get_resource_url(cmd, s_ticker): + if cmd == 'macroaxis': + return f"https://www.macroaxis.com/invest/market/{s_ticker}" + if cmd == 'yahoo': + return f"https://finance.yahoo.com/quote/{s_ticker}" + if cmd == 'finviz': + return f"https://finviz.com/quote.ashx?t={s_ticker}" + if cmd == 'marketwatch': + return f"https://www.marketwatch.com/investing/stock/{s_ticker}" + if cmd == 'fool': + return f"https://www.fool.com/quote/{s_ticker}" + if cmd == 'businessinsider': + return f"https://markets.businessinsider.com/stocks/{s_ticker}-stock/" + if cmd == 'fmp': + return f"https://financialmodelingprep.com/financial-summary/{s_ticker}" + if cmd == 'fidelity': + return f"https://eresearch.fidelity.com/eresearch/goto/evaluate/snapshot.jhtml?symbols={s_ticker}" + if cmd == 'tradingview': + return f"https://www.tradingview.com/symbols/{s_ticker}" + if cmd == 'marketchameleon': + return f"https://marketchameleon.com/Overview/{s_ticker}" + if cmd == 'stockrow': + return f"https://stockrow.com/{s_ticker}" + if cmd == 'barchart': + return f"https://www.barchart.com/stocks/quotes/{s_ticker}/overview" + if cmd == 'grufity': + return f"https://grufity.com/stock/{s_ticker}" + if cmd == 'fintel': + return f"https://fintel.io/s/us/{s_ticker}" + if cmd == 'zacks': + return f"https://www.zacks.com/stock/quote/{s_ticker}" + if cmd == 'macrotrends': + return f"https://www.macrotrends.net/stocks/charts/{s_ticker}/{s_ticker}/market-cap" + if cmd == 'newsfilter': + return f"https://newsfilter.io/search?query={s_ticker}" + if cmd == 'resources': + return f"https://moongangcapital.com/free-stock-market-resources/" + raise NotImplementedError('Invalid command') + # ---------------------------------------------------- MENU ---------------------------------------------------- def res_menu(s_ticker): - # Add list of arguments that the research parser accepts res_parser = argparse.ArgumentParser(prog='discovery', add_help=False) res_parser.add_argument('cmd', choices=['help', 'q', 'quit', @@ -69,171 +107,9 @@ def res_menu(s_ticker): elif ns_known_args.cmd == 'quit': # Abandon the program return True - - # ------------------------------------------------------------------------------------------------------------ - elif ns_known_args.cmd == 'macroaxis': - try: - webbrowser.open(f"https://www.macroaxis.com/invest/market/{s_ticker}") - print("") - except SystemExit: - print("") - return - - # ------------------------------------------------------------------------------------------------------------ - elif ns_known_args.cmd == 'yahoo': - try: - webbrowser.open(f"https://finance.yahoo.com/quote/{s_ticker}") - print("") - except SystemExit: - print("") - return - - # ------------------------------------------------------------------------------------------------------------ - elif ns_known_args.cmd == 'finviz': - try: - webbrowser.open(f"https://finviz.com/quote.ashx?t={s_ticker}") - print("") - except SystemExit: - print("") - return - - # ------------------------------------------------------------------------------------------------------------ - elif ns_known_args.cmd == 'marketwatch': - try: - webbrowser.open(f"https://www.marketwatch.com/investing/stock/{s_ticker}") - print("") - except SystemExit: - print("") - return - - # ------------------------------------------------------------------------------------------------------------ - elif ns_known_args.cmd == 'fool': - try: - webbrowser.open(f"https://www.fool.com/quote/{s_ticker}") - print("") - except SystemExit: - print("") - return - - # ------------------------------------------------------------------------------------------------------------ - elif ns_known_args.cmd == 'businessinsider': - try: - webbrowser.open(f"https://markets.businessinsider.com/stocks/{s_ticker}-stock/") - print("") - except SystemExit: - print("") - return - - # ------------------------------------------------------------------------------------------------------------ - elif ns_known_args.cmd == 'fmp': - try: - webbrowser.open(f"https://financialmodelingprep.com/financial-summary/{s_ticker}") - print("") - except SystemExit: - print("") - return - - # ------------------------------------------------------------------------------------------------------------ - elif ns_known_args.cmd == 'fidelity': - try: - webbrowser.open(f"https://eresearch.fidelity.com/eresearch/goto/evaluate/snapshot.jhtml?symbols={s_ticker}") - print("") - except SystemExit: - print("") - return - - # ------------------------------------------------------------------------------------------------------------ - elif ns_known_args.cmd == 'tradingview': - try: - webbrowser.open(f"https://www.tradingview.com/symbols/{s_ticker}") - print("") - except SystemExit: - print("") - return - - # ------------------------------------------------------------------------------------------------------------ - elif ns_known_args.cmd == 'marketchameleon': - try: - webbrowser.open(f"https://marketchameleon.com/Overview/{s_ticker}") - print("") - except SystemExit: - print("") - return - - # ------------------------------------------------------------------------------------------------------------ - elif ns_known_args.cmd == 'stockrow': - try: - webbrowser.open(f"https://stockrow.com/{s_ticker}") - print("") - except SystemExit: - print("") - return - - # ------------------------------------------------------------------------------------------------------------ - elif ns_known_args.cmd == 'barchart': - try: - webbrowser.open(f"https://www.barchart.com/stocks/quotes/{s_ticker}/overview") - print("") - except SystemExit: - print("") - return - - # ------------------------------------------------------------------------------------------------------------ - elif ns_known_args.cmd == 'grufity': - try: - webbrowser.open(f"https://grufity.com/stock/{s_ticker}") - print("") - except SystemExit: - print("") - return - - # ------------------------------------------------------------------------------------------------------------ - elif ns_known_args.cmd == 'fintel': - try: - webbrowser.open(f"https://fintel.io/s/us/{s_ticker}") - print("") - except SystemExit: - print("") - return - - # ------------------------------------------------------------------------------------------------------------ - elif ns_known_args.cmd == 'zacks': - try: - webbrowser.open(f"https://www.zacks.com/stock/quote/{s_ticker}") - print("") - except SystemExit: - print("") - return - - # ------------------------------------------------------------------------------------------------------------ - elif ns_known_args.cmd == 'macrotrends': - try: - webbrowser.open(f"https://www.macrotrends.net/stocks/charts/{s_ticker}/{s_ticker}/market-cap") - print("") - except SystemExit: - print("") - return - - # ------------------------------------------------------------------------------------------------------------ - elif ns_known_args.cmd == 'newsfilter': - try: - webbrowser.open(f"https://newsfilter.io/search?query={s_ticker}") - print("") - except SystemExit: - print("") - return - - # ------------------------------------------------------------------------------------------------------------ - elif ns_known_args.cmd == 'resources': - try: - #webbrowser.open(f"https://www.tradinganalysisresources.com/2020/05/free-references-and-resources.html") - webbrowser.open(f"https://moongangcapital.com/free-stock-market-resources/") - - print("") - except SystemExit: - print("") - return - - # ------------------------------------------------------------------------------------------------------------ else: - print("Command not recognized!") + try: + url = get_resource_url(ns_known_args.cmd, s_ticker) + webbrowser.open(url) + except Exception as exc: + print("ERROR:", exc) From 0e1b98cfc52f1dc15c0bbddd0f2f5e8a940a384d Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Wed, 3 Mar 2021 21:50:41 +0200 Subject: [PATCH 71/72] Fix indent snafu --- fundamental_analysis/alpha_vantage_api.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/fundamental_analysis/alpha_vantage_api.py b/fundamental_analysis/alpha_vantage_api.py index aeb05ae2123..2a3c957ff31 100644 --- a/fundamental_analysis/alpha_vantage_api.py +++ b/fundamental_analysis/alpha_vantage_api.py @@ -6,8 +6,6 @@ from alpha_vantage.fundamentaldata import FundamentalData from pandas.io.json import json_normalize import config_terminal as cfg - - # ---------------------------------------------------- OVERVIEW ---------------------------------------------------- from helper_funcs import long_number_format, check_positive @@ -307,12 +305,14 @@ def earnings(l_args, s_ticker): if ns_parser.b_quarter: df_fa = pd.DataFrame(df_fa['quarterlyEarnings'][0]) df_fa = df_fa[["fiscalDateEnding", "reportedDate", "reportedEPS", "estimatedEPS", "surprise", "surprisePercentage"]] - df_fa = df_fa.rename(columns={"fiscalDateEnding":"Fiscal Date Ending", - "reportedEPS":"Reported EPS", - "estimatedEPS":"Estimated EPS", - "reportedDate":"Reported Date", - "surprise":"Surprise", - "surprisePercentage":"Suprise Percentage"}) + df_fa = df_fa.rename(columns={ + "fiscalDateEnding": "Fiscal Date Ending", + "reportedEPS": "Reported EPS", + "estimatedEPS": "Estimated EPS", + "reportedDate": "Reported Date", + "surprise": "Surprise", + "surprisePercentage": "Surprise Percentage", + }) else: df_fa = pd.DataFrame(df_fa['annualEarnings'][0]) df_fa = df_fa.rename(columns={"fiscalDateEnding":"Fiscal Date Ending", From e0c32bd78ed2bd3d5fefafd72e7c068a46ccef80 Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Wed, 3 Mar 2021 22:10:02 +0200 Subject: [PATCH 72/72] Make lint happy? --- due_diligence/market_watch_api.py | 1 + 1 file changed, 1 insertion(+) diff --git a/due_diligence/market_watch_api.py b/due_diligence/market_watch_api.py index ad978b3a76f..251587ea779 100644 --- a/due_diligence/market_watch_api.py +++ b/due_diligence/market_watch_api.py @@ -30,6 +30,7 @@ def sec_fillings(l_args, s_ticker): text_soup_financials = BeautifulSoup(requests.get(url_financials).text,"lxml") + df_financials = None a_financials_header = list() b_ready_to_process_info = False soup_financials = text_soup_financials.findAll('tr', {'class': 'table__row'})