Merge branch 'develop' into hotfix/bug-#3960

This commit is contained in:
northern-64bit
2023-02-05 17:40:10 +01:00
committed by GitHub
1233 changed files with 590666 additions and 471408 deletions

View File

@@ -1,10 +1,28 @@
name-template: 'OpenBB Terminal v$NEXT_MINOR_VERSION'
tag-template: 'v$NEXT_MINOR_VERSION'
exclude-contributors:
- 'jmaslek'
- 'DidierRLopes'
- 'JerBouma'
- 'deeleeramone'
- 'hjoaquim'
- 'jose-donato'
- 'luqman-bello'
- 'martinb-bb'
- 'montezdesousa'
- 'tehcoderer'
- 'Chavithra'
- 'colin99d'
- 'northern-64bit'
- 'piiq'
- 'andrewkenreich'
template: |
## Thank you and welcome to our new contributors 🔥
$CONTRIBUTORS
## What's new 🎉
## What's changed 🚀
$CHANGES

62
.github/workflows/build-release.yml vendored Normal file
View File

@@ -0,0 +1,62 @@
name: Build & Release
env:
OPENBB_ENABLE_QUICK_EXIT: true
OPENBB_LOG_COLLECT: false
OPENBB_USE_ION: false
OPENBB_USE_PROMPT_TOOLKIT: false
PIP_DEFAULT_TIMEOUT: 100
PYTHONNOUSERSITE: 1
on:
push:
branches:
- release/*
- main
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
actions: write
jobs:
trigger-windows-build:
runs-on: ubuntu-latest
steps:
- name: Trigger Windows Build
uses: aurelien-baudet/workflow-dispatch@v2
with:
workflow: windows10_build.yml
token: ${{ secrets.GITHUB_TOKEN }}
wait-for-completion-timeout: 2h
trigger-macos-build:
runs-on: ubuntu-latest
steps:
- name: Trigger M1 MacOs Build
uses: aurelien-baudet/workflow-dispatch@v2
with:
workflow: m1_macos_build.yml
token: ${{ secrets.GITHUB_TOKEN }}
wait-for-completion-timeout: 2h
trigger-intel-build:
runs-on: ubuntu-latest
steps:
- name: Trigger Intel MacOs Build
uses: aurelien-baudet/workflow-dispatch@v2
with:
workflow: intel_macos_build.yml
token: ${{ secrets.GITHUB_TOKEN }}
wait-for-completion-timeout: 2h
trigger-docker-build:
runs-on: ubuntu-latest
steps:
- name: Trigger docker Build
uses: aurelien-baudet/workflow-dispatch@v2
with:
workflow: docker.yml
token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -40,3 +40,4 @@ jobs:
- name: Publishing the Docker image
run: |
docker push "${OPENBBTERMINAL_DOCKER_POETRY_IMAGE}"
if: startsWith(github.ref, 'refs/heads/main')

View File

@@ -1,16 +1,14 @@
name: Deploy to GitHub Pages
on:
pull_request:
push:
branches:
- main
types: [closed]
- release/*
jobs:
generate:
name: Generate and Deploy documentation
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
steps:
- name: Git checkout
@@ -67,6 +65,7 @@ jobs:
# Docs: https://github.com/peaceiris/actions-gh-pages#%EF%B8%8F-docusaurus
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
if: startsWith(github.ref, 'refs/heads/main')
with:
github_token: ${{ secrets.DEPLOY_TOKEN }}
publish_dir: ./website/build
@@ -77,3 +76,4 @@ jobs:
# You can swap them out with your own user credentials.
user_name: github-actions[bot]
user_email: 41898282+github-actions[bot]@users.noreply.github.com

52
.github/workflows/integration-test.yml vendored Normal file
View File

@@ -0,0 +1,52 @@
name: Integration Tests
on:
push:
branches:
- release/*
- main
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
integration-tests:
runs-on: ubuntu-latest
steps:
- name: Checkout code
if: github.event_name == 'push'
uses: actions/checkout@v3
- name: Checkout specific ref
if: github.event_name == 'pull_request'
run: git fetch origin ${{ github.event.pull_request.head.ref }} && git checkout FETCH_HEAD
- name: Setup Python 3.9
uses: actions/setup-python@v4
with:
python-version: "3.9"
architecture: x64
- name: Install Poetry
uses: snok/install-poetry@v1
with:
version: 1.1.13
virtualenvs-create: true
virtualenvs-in-project: true
- name: Load cached venv
id: cached-poetry-dependencies
uses: actions/cache@v3
with:
path: .venv
key: venv-${{ runner.os }}-v1-${{ hashFiles('**/poetry.lock') }}
- name: Install dependencies
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
run: poetry install --no-interaction -E optimization
- name: Run integration tests
run: |
source $VENV
python terminal.py /home/runner/work/OpenBBTerminal/OpenBBTerminal/openbb_terminal/miscellaneous/integration_tests_scripts -t

View File

@@ -1,12 +1,20 @@
name: Intel MacOS Build
env:
OPENBB_ENABLE_QUICK_EXIT: true
OPENBB_LOG_COLLECT: false
OPENBB_USE_ION: false
OPENBB_USE_PROMPT_TOOLKIT: false
OPENBB_FILE_OVERWRITE: true
PIP_DEFAULT_TIMEOUT: 100
PYTHONNOUSERSITE: 1
on: workflow_dispatch
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
Build:
name: Intel MacOS Build
@@ -104,6 +112,8 @@ jobs:
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/prophet/stan_model/cmdstan-2.26.1/stan/lib/stan_math/lib/tbb/*.dylib
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/torch/.dylibs/*.dylib
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/sklearn/.dylibs/*.dylib
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/scipy/.dylibs/*.dylib
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/xgboost/.dylibs/*.dylib
echo "Code Signing Other Files"
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/prophet/stan_model/prophet_model.bin
@@ -168,7 +178,7 @@ jobs:
- name: Unmount DMG
run: hdiutil detach /dev/disk2
- name: Run Integration Tests
run: /Users/openbb/Desktop/OpenBB\ Terminal/.OpenBB/OpenBBTerminal /Users/openbb/actions-runner/_work/OpenBBTerminal/OpenBBTerminal/openbb_terminal/miscellaneous/scripts -t
run: /Users/openbb/Desktop/OpenBB\ Terminal/.OpenBB/OpenBBTerminal /Users/openbb/actions-runner/_work/OpenBBTerminal/OpenBBTerminal/openbb_terminal/miscellaneous/integration_tests_scripts -t
- name: Remove OpenBB Folder
run: rm -rf /Users/openbb/Desktop/OpenBB\ Terminal
- name: Remove OpenBB Exports Folder

View File

@@ -10,7 +10,7 @@ jobs:
with:
mode: minimum
count: 1
labels: "guides, bug, build, do not merge, docker, docs, duplicate, enhancement, feat XS, feat S, feat M, feat L, feat XL, help wanted, refactor, tests, discord, dependencies, notebookreports, dashboards, analytics, portfolio, installer, SDK, HACKTOBERFEST, "
labels: "guides, bug, build, do not merge, docker, docs, duplicate, enhancement, feat XS, feat S, feat M, feat L, feat XL, help wanted, refactor, tests, discord, dependencies, notebookreports, dashboards, analytics, portfolio, installer, SDK, release "
- uses: mheap/github-action-required-labels@v1
with:
mode: exactly

View File

@@ -5,6 +5,7 @@ env:
OPENBB_LOG_COLLECT: false
OPENBB_USE_ION: false
OPENBB_USE_PROMPT_TOOLKIT: false
OPENBB_FILE_OVERWRITE: true
PIP_DEFAULT_TIMEOUT: 100
on:
@@ -14,11 +15,11 @@ on:
branches:
- 'feature/*'
- 'hotfix/*'
- 'release/[0-9]+\.[0-9]+\.[0-9]+(rc[0-9]+)?'
- 'release/*'
# Cancel previous runs that are not yet completed.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
group: ${{ github.event_name }}-${{ github.repository }}-${{ github.ref }}
cancel-in-progress: true
jobs:
@@ -42,7 +43,7 @@ jobs:
restore-keys: ${{ runner.os }}-linting-${{ hashFiles('**/poetry.lock') }}
- run: |
pip install bandit black codespell mypy==0.982 pyupgrade safety pylint==2.15.2 packaging==22 ruff==0.0.212
pip install bandit black codespell mypy==0.982 pyupgrade safety pylint==2.15.2 packaging==22 ruff==0.0.236
pip install types-pytz types-requests types-termcolor types-tabulate types-PyYAML types-python-dateutil types-setuptools types-six
- run: bandit -x ./tests -r . || true
- run: black --diff --check .
@@ -50,7 +51,6 @@ jobs:
- run: ruff .
- run: mypy --ignore-missing-imports openbb_terminal
- run: shopt -s globstar && pyupgrade --py38-plus **/*.py
- run: safety check
- run: |
pylint terminal.py openbb_terminal tests

View File

@@ -1,12 +1,20 @@
name: M1 MacOS Build
env:
OPENBB_ENABLE_QUICK_EXIT: true
OPENBB_LOG_COLLECT: false
OPENBB_USE_ION: false
OPENBB_USE_PROMPT_TOOLKIT: false
OPENBB_FILE_OVERWRITE: true
PIP_DEFAULT_TIMEOUT: 100
PYTHONNOUSERSITE: 1
on: workflow_dispatch
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
Build:
name: M1 MacOS Build
@@ -45,16 +53,21 @@ jobs:
activate-environment: build_env
auto-activate-base: false
use-only-tar-bz2: true # Needed for caching some reason
- name: Run Poetry
run: poetry install
run: poetry install -vvv
- name: Install Pyinstaller
run: poetry install -E installer
- name: Poetry Install Portfolio Optimization and Forecasting Toolkits
run: poetry install -E all
- name: Install Specific Papermill
run: |
pip uninstall papermill -y
pip install git+https://github.com/nteract/papermill.git@main
# This is basically the same as build4mac.sh
- name: Build Bundle
run: |
@@ -89,7 +102,7 @@ jobs:
- name: Unmount DMG
run: hdiutil detach /dev/disk4
- name: Run Integration Tests
run: /Users/openbb/Desktop/OpenBB\ Terminal/.OpenBB/OpenBBTerminal /Users/openbb/actions-runner/_work/OpenBBTerminal/OpenBBTerminal/openbb_terminal/miscellaneous/scripts -t
run: /Users/openbb/Desktop/OpenBB\ Terminal/.OpenBB/OpenBBTerminal /Users/openbb/actions-runner/_work/OpenBBTerminal/OpenBBTerminal/openbb_terminal/miscellaneous/integration_tests_scripts -t
- name: Remove OpenBB Folder
run: rm -rf /Users/openbb/Desktop/OpenBB\ Terminal
- name: Remove OpenBB Exports Folder

View File

@@ -5,6 +5,7 @@ env:
OPENBB_USE_ION: false
OPENBB_USE_PROMPT_TOOLKIT: false
PIP_DEFAULT_TIMEOUT: 100
OPENBB_FILE_OVERWRITE: true
PYTHONNOUSERSITE: 1
on:
push:

View File

@@ -1,4 +1,4 @@
name: Nightly Build on the develop branch
name: Nightly Build
env:
OPENBB_ENABLE_QUICK_EXIT: true
@@ -6,91 +6,52 @@ env:
OPENBB_USE_ION: false
OPENBB_USE_PROMPT_TOOLKIT: false
PIP_DEFAULT_TIMEOUT: 100
OPENBB_FILE_OVERWRITE: true
PYTHONNOUSERSITE: 1
on:
schedule:
- cron: "0 0 * * *"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
actions: write
jobs:
Windows-Build:
name: Windows10 Build
runs-on: [self-hosted, Windows, x64]
# Configuring -------------
trigger-windows-build:
runs-on: ubuntu-latest
steps:
- name: Setup Windows Git Configuration # This is under the assumption that git is already installed on the system
run: |
Set-ItemProperty 'HKLM:\System\CurrentControlSet\Control\FileSystem' -Name 'LongPathsEnabled' -value 1
git config --system core.longpaths true
- name: Checkout
uses: actions/checkout@v2.4.2
- name: Trigger Windows Build
uses: aurelien-baudet/workflow-dispatch@v2
with:
ref: develop
- name: Activate Base & Create OpenBB Environment
run: |
conda activate base
conda env create -n obb --file build/conda/conda-3-9-env-full.yaml
conda init
conda activate obb
conda env list
- name: Poetry Install
# Conda activate needs to be run every time because of the way that the workflow steps work
# on powershell where it creates a new shell every time for every step
run: |
conda activate obb
poetry install
- name: Poetry Install Portfolio Optimization and Forecasting Toolkits
run: |
conda activate obb
poetry install -E all
- name: Poetry Install Installer
run: |
conda activate obb
poetry install -E installer
- name: Install Specific Papermill
run: |
conda activate obb
pip uninstall papermill -y
pip install git+https://github.com/nteract/papermill.git@main
# Building ------------
- name: Build Terminal.spec file
run: |
conda activate obb
pyinstaller build/pyinstaller/terminal.spec --clean
- name: Move Files into App Folder
run: cp -r .\dist\OpenBBTerminal\ .\build\nsis\app\
# don't need this because log collection is turned off
# - name: Remove Log Data
# run: Remove-Item .\build\nsis\app\openbb_terminal\logs\ -Recurse
- name: Build Exe File
run: |
conda activate obb
C:\'.\Program Files (x86)\'\nsis\makensis.exe .\build\nsis\setup.nsi
- name: Save Build Artifact
uses: actions/upload-artifact@v3
workflow: windows10_build.yml
token: ${{ secrets.GITHUB_TOKEN }}
wait-for-completion-timeout: 2h
trigger-macos-build:
runs-on: ubuntu-latest
steps:
- name: Trigger M1 MacOs Build
uses: aurelien-baudet/workflow-dispatch@v2
with:
name: Windows EXE Artifact
path: '.\build\nsis\OpenBB Terminal Setup.exe'
- name: Run Integration Tests
run: |
dist\OpenBBTerminal\OpenBBTerminal.exe C:\Users\Administrator\actions-runner\_work\OpenBBTerminal\OpenBBTerminal\openbb_terminal\miscellaneous\scripts -t
# Cleaning ------------------------
# Make sure to add Remove-Item C:\Users\Administrator\Desktop\OPENBB-exports -Recurse whenever integration tests get fixed
- name: Remove Previous Build
run: |
Remove-Item '.\build\nsis\OpenBB Terminal Setup.exe' -Recurse
Remove-Item .\build\nsis\app\ -Recurse
Remove-Item .\dist\ -Recurse
Remove-Item .\build\terminal\ -Recurse
- name: Deactivate & Remove Conda Environment
run: |
conda deactivate obb
conda deactivate base
conda env remove -n obb
Remove-Item C:\Users\Administrator\miniconda3\envs\obb\ -Recurse
workflow: m1_macos_build.yml
token: ${{ secrets.GITHUB_TOKEN }}
wait-for-completion-timeout: 2h
trigger-intel-build:
runs-on: ubuntu-latest
steps:
- name: Trigger Intel MacOs Build
uses: aurelien-baudet/workflow-dispatch@v2
with:
workflow: intel_macos_build.yml
token: ${{ secrets.GITHUB_TOKEN }}
wait-for-completion-timeout: 2h
trigger-docker-build:
runs-on: ubuntu-latest
steps:
- name: Trigger docker Build
uses: aurelien-baudet/workflow-dispatch@v2
with:
workflow: docker.yml
token: ${{ secrets.GITHUB_TOKEN }}

79
.github/workflows/pypi.yml vendored Normal file
View File

@@ -0,0 +1,79 @@
name: Deploy to PyPI
on:
push:
branches:
- release/*
- main
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
deploy-test-pypi:
name: Build and publish distributions 📦 to PyPI and TestPyPI
if: startsWith(github.ref, 'refs/heads/release/')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Python 3.9
uses: actions/setup-python@v4
with:
python-version: "3.9"
- name: Install pypa/build
run: >-
python -m
pip install
build
--user
- name: Build a binary wheel and a source tarball
run: >-
python -m
build
--sdist
--wheel
--outdir dist/
.
- name: Publish distribution 📦 to Test PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.TEST_PYPI_API_TOKEN }}
repository_url: https://test.pypi.org/legacy/
deploy-pypi:
name: Build and publish distributions 📦 to PyPI and TestPyPI
if: startsWith(github.ref, 'refs/heads/main')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Python 3.9
uses: actions/setup-python@v4
with:
python-version: "3.9"
- name: Install pypa/build
run: >-
python -m
pip install
build
--user
- name: Build a binary wheel and a source tarball
run: >-
python -m
build
--sdist
--wheel
--outdir dist/
.
- name: Publish distribution 📦 to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.PYPI_API_TOKEN }}

View File

@@ -4,6 +4,7 @@ env:
OPENBB_LOG_COLLECT: false
OPENBB_USE_ION: false
OPENBB_USE_PROMPT_TOOLKIT: false
OPENBB_FILE_OVERWRITE: true
PIP_DEFAULT_TIMEOUT: 100
on: [workflow_dispatch]

View File

@@ -5,6 +5,7 @@ env:
OPENBB_LOG_COLLECT: false
OPENBB_USE_ION: false
OPENBB_USE_PROMPT_TOOLKIT: false
OPENBB_FILE_OVERWRITE: true
PIP_DEFAULT_TIMEOUT: 100
on:
@@ -13,6 +14,9 @@ on:
- develop
- main
types: [opened, synchronize, edited, closed]
push:
branches:
- release/*
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
@@ -22,7 +26,8 @@ jobs:
check-files-changed:
name: Check for changes
runs-on: ubuntu-latest
if: github.event.pull_request.merged != true
# Run this job only if the PR is not merged and the event is not a push
if: github.event.pull_request.merged == false && github.event_name != 'push'
outputs:
check-changes: ${{ steps.check-changes.outputs.check-changes }}
steps:
@@ -100,7 +105,7 @@ jobs:
tests-python:
name: Vanilla Python Tests - ${{ matrix.python-version }}
needs: [check-files-changed, base-test]
needs: [base-test]
runs-on: ${{ matrix.os }}
strategy:
fail-fast: true
@@ -149,7 +154,7 @@ jobs:
MPLBACKEND: Agg
run: |
source $VENV
pytest tests/ --optimization
pytest tests/ --optimization --autodoc
- name: Start Terminal and exit
run: |
@@ -159,7 +164,8 @@ jobs:
full-test:
name: Full Test Suite - (${{ matrix.python-version }}, ${{ matrix.os }})
runs-on: ${{ matrix.os }}
if: github.event.pull_request.merged == true
# Run only when a PR is merged or a push to release/* branch
if: github.event_name == 'push' || github.event.pull_request.merged == true
strategy:
fail-fast: true
matrix:
@@ -217,7 +223,7 @@ jobs:
tests-conda:
name: Anaconda Python Tests - (${{ matrix.python-version }}, ${{ matrix.os }})
runs-on: ${{ matrix.os }}-latest
if: github.event.pull_request.merged == true
if: github.event_name == 'push' || github.event.pull_request.merged == true
strategy:
fail-fast: false
matrix:

View File

@@ -4,6 +4,7 @@ env:
OPENBB_LOG_COLLECT: false
OPENBB_USE_ION: false
OPENBB_USE_PROMPT_TOOLKIT: false
OPENBB_FILE_OVERWRITE: true
PIP_DEFAULT_TIMEOUT: 100
PYTHONNOUSERSITE: 1
on:

View File

@@ -1,4 +1,5 @@
name: Windows10 Build
env:
OPENBB_ENABLE_QUICK_EXIT: true
OPENBB_LOG_COLLECT: false
@@ -6,50 +7,74 @@ env:
OPENBB_USE_PROMPT_TOOLKIT: false
PIP_DEFAULT_TIMEOUT: 100
PYTHONNOUSERSITE: 1
on: workflow_dispatch
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
Windows-Build:
name: Windows10 Build
runs-on: [self-hosted, Windows, x64]
name: Windows10 Build ENV
runs-on: windows-latest
# Configuring -------------
steps:
- name: Setup Windows Git Configuration # This is under the assumption that git is already installed on the system
run: |
Set-ItemProperty 'HKLM:\System\CurrentControlSet\Control\FileSystem' -Name 'LongPathsEnabled' -value 1
git config --system core.longpaths true
Set-ItemProperty 'HKLM:\System\CurrentControlSet\Control\FileSystem' -Name 'LongPathsEnabled' -value 1
git config --system core.longpaths true
- name: Checkout
uses: actions/checkout@v2.4.2
- name: Activate Base & Create OpenBB Environment
- name: Set up Python & Create OpenBB Environment
uses: actions/setup-python@v4
with:
python-version: '3.9'
- name: Create and start virtual environment
run: |
conda activate base
conda env create -n obb --file build/conda/conda-3-9-env-full.yaml
conda init
conda activate obb
conda env list
- name: Poetry Install
# Conda activate needs to be run every time because of the way that the workflow steps work
# on powershell where it creates a new shell every time for every step
python -m venv venv
source venv/Scripts/activate
python -m pip install --upgrade pip
python -m pip install poetry==1.1.13
python -m pip install setuptools==64.0.2 wheel
python -m pip install charset_normalizer==2.1.1
python -m poetry install -E installer -E all
python -m pip uninstall papermill -y
python -m pip install git+https://github.com/nteract/papermill.git@main
python -m PyInstaller build/pyinstaller/terminal.spec --clean
shell: bash
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
name: OpenBB-Windows10-ENV
path: dist
Build-Exe:
name: Windows10 Build-Exe
runs-on: [self-hosted, Windows, x64]
needs: Windows-Build
# Configuring -------------
steps:
- name: Setup Windows Git Configuration # This is under the assumption that git is already installed on the system
run: |
conda activate obb
poetry install
- name: Poetry Install Portfolio Optimization and Forecasting Toolkits
run: |
conda activate obb
poetry install -E all
- name: Poetry Install Installer
run: |
conda activate obb
poetry install -E installer
- name: Install Specific Papermill
run: |
conda activate obb
pip uninstall papermill -y
pip install git+https://github.com/nteract/papermill.git@main
# Building ------------
- name: Build Terminal.spec file
run: |
conda activate obb
pyinstaller build/pyinstaller/terminal.spec --clean
Set-ItemProperty 'HKLM:\System\CurrentControlSet\Control\FileSystem' -Name 'LongPathsEnabled' -value 1
git config --system core.longpaths true
- name: Checkout
uses: actions/checkout@v2.4.2
- name: Download Artifact
uses: actions/download-artifact@v2
with:
name: OpenBB-Windows10-ENV
path: dist
- name: Move Files into App Folder
run: cp -r .\dist\OpenBBTerminal\ .\build\nsis\app\
# don't need this because log collection is turned off
@@ -57,16 +82,18 @@ jobs:
# run: Remove-Item .\build\nsis\app\openbb_terminal\logs\ -Recurse
- name: Build Exe File
run: |
conda activate obb
C:\'.\Program Files (x86)\'\nsis\makensis.exe .\build\nsis\setup.nsi
- name: Save Build Artifact
uses: actions/upload-artifact@v3
with:
name: Windows EXE Artifact
path: '.\build\nsis\OpenBB Terminal Setup.exe'
- name: Run Integration Tests
run: |
dist\OpenBBTerminal\OpenBBTerminal.exe C:\Users\Administrator\actions-runner\_work\OpenBBTerminal\OpenBBTerminal\openbb_terminal\miscellaneous\scripts -t
dist\OpenBBTerminal\OpenBBTerminal.exe -t
# Cleaning ------------------------
# Make sure to add Remove-Item C:\Users\Administrator\Desktop\OPENBB-exports -Recurse whenever integration tests get fixed
- name: Remove Previous Build
@@ -74,10 +101,3 @@ jobs:
Remove-Item '.\build\nsis\OpenBB Terminal Setup.exe' -Recurse
Remove-Item .\build\nsis\app\ -Recurse
Remove-Item .\dist\ -Recurse
Remove-Item .\build\terminal\ -Recurse
- name: Deactivate & Remove Conda Environment
run: |
conda deactivate obb
conda deactivate base
conda env remove -n obb
Remove-Item C:\Users\Administrator\miniconda3\envs\obb\ -Recurse

View File

@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.3.0
rev: v4.4.0
hooks:
- id: check-yaml
- id: end-of-file-fixer
@@ -10,11 +10,11 @@ repos:
- id: check-merge-conflict
- id: detect-private-key
- repo: https://github.com/psf/black
rev: 22.10.0
rev: 22.12.0
hooks:
- id: black
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: 'v0.0.212'
rev: 'v0.0.236'
hooks:
- id: ruff
- repo: https://github.com/codespell-project/codespell
@@ -65,7 +65,7 @@ repos:
]
exclude: package.lock.json
- repo: https://github.com/asottile/pyupgrade
rev: v3.2.2
rev: v3.3.1
hooks:
- id: pyupgrade
args: [--py38-plus]

4
CONTRIBUTING.md vendored
View File

@@ -106,7 +106,7 @@ def get_most_shorted() -> pd.DataFrame:
url = "https://finance.yahoo.com/screener/predefined/most_shorted_stocks"
data = pd.read_html(
requests.get(url, headers={"User-Agent": get_user_agent()}).text
request(url, headers={"User-Agent": get_user_agent()}).text
)[0]
data = data.iloc[:, :-1]
return data
@@ -137,7 +137,7 @@ def get_economy_calendar_events() -> pd.DataFrame:
pd.DataFrame
Get dataframe with economic calendar events
"""
response = requests.get(
response = request(
f"https://finnhub.io/api/v1/calendar/economic?token={cfg.API_FINNHUB_KEY}"
)

View File

@@ -1,2 +1,2 @@
OPENBBTERMINAL_DOCKER_REGISTRY="ghcr.io"
OPENBBTERMINAL_DOCKER_RELEASE_VERSION="2.1.0"
OPENBBTERMINAL_DOCKER_RELEASE_VERSION="2.3.1"

View File

@@ -7,6 +7,6 @@ services:
- ~/OpenBBUserData:/home/python/OpenBBUserData
- ~/.openbb_terminal:/home/python/.openbb_terminal
platform: linux/amd64
image: ghcr.io/openbb-finance/openbbterminal/openbb:2.1.0
image: ghcr.io/openbb-finance/openbbterminal/openbb:2.3.1
stdin_open: true # docker run -i
tty: true # docker run -t

View File

@@ -10,7 +10,7 @@
!define NAME "OpenBB Terminal"
!define COMPANY "OpenBB"
!define APPFILE "OpenBBTerminal.exe"
!define VERSION "2.1.0"
!define VERSION "2.3.1"
!define SLUG "${NAME} v${VERSION}"
;--------------------------------

View File

@@ -1,5 +1,5 @@
OPENBB_LOGGING_APP_NAME=gst_packaged
OPENBB_LOGGING_COMMIT_HASH=sha:b0ef0ee6
OPENBB_LOGGING_COMMIT_HASH=sha:dbd2097
OPENBB_ENABLE_PREDICT=false
OPENBB_ENABLE_CHECK_API=true
OPENBB_ENABLE_THOUGHTS_DAY=false

View File

@@ -0,0 +1,3 @@
from PyInstaller.utils.hooks import collect_all
datas, binaries, hiddenimports = collect_all("xgboost")

View File

@@ -1,17 +1,15 @@
# -*- mode: python ; coding: utf-8 -*-
import os
import pathlib
import subprocess
import sys
from pathlib import Path
import scipy
from dotenv import set_key
from PyInstaller.compat import is_darwin, is_win
from PyInstaller.building.api import PYZ, EXE, COLLECT
from PyInstaller.building.splash import Splash
from PyInstaller.building.api import COLLECT, EXE, PYZ
from PyInstaller.building.build_main import Analysis
# import subprocess
from PyInstaller.building.splash import Splash
from PyInstaller.compat import is_darwin, is_win
from openbb_terminal.loggers import get_commit_hash
@@ -22,21 +20,30 @@ build_type = (
)
# Local python environment packages folder
pathex = os.path.join(os.path.dirname(os.__file__), "site-packages")
venv_path = Path(sys.executable).parent.parent.resolve()
# Check if we are running in a conda environment
if is_darwin:
pathex = os.path.join(os.path.dirname(os.__file__), "site-packages")
else:
if "site-packages" in list(venv_path.iterdir()):
pathex = str(venv_path / "site-packages")
else:
pathex = str(venv_path / "lib" / "site-packages")
# Removing unused ARM64 binary
binary_to_remove = pathlib.Path(
os.path.join(pathex, "_scs_direct.cpython-39-darwin.so")
)
binary_to_remove = Path(os.path.join(pathex, "_scs_direct.cpython-39-darwin.so"))
print("Removing ARM64 Binary: _scs_direct.cpython-39-darwin.so")
binary_to_remove.unlink(missing_ok=True)
build_assets_folder = os.path.join(os.getcwd(), "build", "pyinstaller")
# Removing inspect hook
destination = pathlib.Path(
destination = Path(
os.path.join(pathex, "pyinstaller/hooks/rthooks", "pyi_rth_inspect.py")
)
print("Replacing Pyinstaller Hook: pyi_rth_inspect.py")
source = "build/pyinstaller/hooks/pyi_rth_inspect.py"
source = os.path.join(build_assets_folder, "hooks", "pyi_rth_inspect.py")
subprocess.run(["cp", source, str(destination)], check=True)
@@ -74,7 +81,10 @@ added_files = [
(os.path.join(pathex, "blib2to3", "Grammar.txt"), "blib2to3"),
(os.path.join(pathex, "blib2to3", "PatternGrammar.txt"), "blib2to3"),
]
if is_win:
added_files.append(
(os.path.join(f"{os.path.dirname(scipy.__file__)}.libs"), "scipy.libs/"),
)
# Python libraries that are explicitly pulled into the bundle
hidden_imports = [
"sklearn.utils._cython_blas",
@@ -99,6 +109,7 @@ hidden_imports = [
"_sysconfigdata__darwin_darwin",
"prophet",
"debugpy",
"scipy.sparse.linalg._isolve._iterative",
]

View File

@@ -1,9 +1,9 @@
"""Check reserved command arguments in Controllers"""
import os
import sys
import glob
import os
import re
from typing import Optional, Any
import sys
from typing import Any, Optional
RESERVED_ARGS = {
"f": "file",

View File

@@ -63,7 +63,7 @@ setup_args = dict(
)
try:
from jupyter_packaging import wrap_installers, npm_builder, get_data_files
from jupyter_packaging import get_data_files, npm_builder, wrap_installers
post_develop = npm_builder(
build_cmd="install:extension", source_dir="src", build_dir=lab_path

View File

@@ -63,7 +63,7 @@ setup_args = dict(
)
try:
from jupyter_packaging import wrap_installers, npm_builder, get_data_files
from jupyter_packaging import get_data_files, npm_builder, wrap_installers
post_develop = npm_builder(
build_cmd="install:extension", source_dir="src", build_dir=lab_path

View File

@@ -61,7 +61,7 @@ setup_args = dict(
)
try:
from jupyter_packaging import wrap_installers, npm_builder, get_data_files
from jupyter_packaging import get_data_files, npm_builder, wrap_installers
post_develop = npm_builder(
build_cmd="install:extension", source_dir="src", build_dir=lab_path

View File

@@ -5,17 +5,16 @@ import argparse
import logging
from typing import List
from openbb_terminal.custom_prompt_toolkit import NestedCompleter
from openbb_terminal import feature_flags as obbff
from openbb_terminal.alternative import hackernews_view
from openbb_terminal.custom_prompt_toolkit import NestedCompleter
from openbb_terminal.decorators import log_start_end
from openbb_terminal.helper_funcs import (
EXPORT_ONLY_RAW_DATA_ALLOWED,
)
from openbb_terminal.menu import session
from openbb_terminal.parent_classes import BaseController
from openbb_terminal.rich_config import console, MenuText
from openbb_terminal.alternative import hackernews_view
from openbb_terminal.rich_config import MenuText, console
logger = logging.getLogger(__name__)
# pylint:disable=import-outside-toplevel
@@ -25,7 +24,7 @@ class AlternativeDataController(BaseController):
"""Alternative Controller class"""
CHOICES_COMMANDS: List[str] = ["hn"]
CHOICES_MENUS = ["covid", "oss"]
CHOICES_MENUS = ["covid", "oss", "realestate"]
PATH = "/alternative/"
CHOICES_GENERATION = True
@@ -43,6 +42,7 @@ class AlternativeDataController(BaseController):
mt = MenuText("alternative/")
mt.add_menu("covid")
mt.add_menu("oss")
mt.add_menu("realestate")
mt.add_raw("\n")
mt.add_cmd("hn")
console.print(text=mt.menu_text, menu="Alternative")
@@ -80,4 +80,19 @@ class AlternativeDataController(BaseController):
)
if ns_parser:
hackernews_view.display_stories(limit=ns_parser.limit)
hackernews_view.display_stories(
limit=ns_parser.limit,
export=ns_parser.export,
sheet_name=" ".join(ns_parser.sheet_name)
if ns_parser.sheet_name
else None,
)
@log_start_end(log=logger)
def call_realestate(self, _):
"""Process realestate command."""
from openbb_terminal.alternative.realestate.realestate_controller import (
RealEstateController,
)
self.queue = self.load_class(RealEstateController, self.queue)

View File

@@ -7,10 +7,10 @@ import pathlib
from typing import List
import pandas as pd
from openbb_terminal.custom_prompt_toolkit import NestedCompleter
from openbb_terminal import feature_flags as obbff
from openbb_terminal.alternative.covid import covid_view
from openbb_terminal.custom_prompt_toolkit import NestedCompleter
from openbb_terminal.decorators import log_start_end
from openbb_terminal.helper_funcs import (
EXPORT_BOTH_RAW_DATA_AND_FIGURES,
@@ -19,7 +19,7 @@ from openbb_terminal.helper_funcs import (
)
from openbb_terminal.menu import session
from openbb_terminal.parent_classes import BaseController
from openbb_terminal.rich_config import console, MenuText
from openbb_terminal.rich_config import MenuText, console
logger = logging.getLogger(__name__)
@@ -125,6 +125,9 @@ class CovidController(BaseController):
raw=ns_parser.raw,
limit=ns_parser.limit,
export=ns_parser.export,
sheet_name=" ".join(ns_parser.sheet_name)
if ns_parser.sheet_name
else None,
)
@log_start_end(log=logger)
@@ -150,6 +153,9 @@ class CovidController(BaseController):
raw=ns_parser.raw,
limit=ns_parser.limit,
export=ns_parser.export,
sheet_name=" ".join(ns_parser.sheet_name)
if ns_parser.sheet_name
else None,
)
@log_start_end(log=logger)
@@ -175,6 +181,9 @@ class CovidController(BaseController):
raw=ns_parser.raw,
limit=ns_parser.limit,
export=ns_parser.export,
sheet_name=" ".join(ns_parser.sheet_name)
if ns_parser.sheet_name
else None,
)
@log_start_end(log=logger)
@@ -200,6 +209,9 @@ class CovidController(BaseController):
raw=ns_parser.raw,
limit=ns_parser.limit,
export=ns_parser.export,
sheet_name=" ".join(ns_parser.sheet_name)
if ns_parser.sheet_name
else None,
)
@log_start_end(log=logger)
@@ -251,4 +263,8 @@ class CovidController(BaseController):
limit=ns_parser.limit,
ascend=ns_parser.reverse,
threshold=ns_parser.threshold,
export=ns_parser.export,
sheet_name=" ".join(ns_parser.sheet_name)
if ns_parser.sheet_name
else None,
)

View File

@@ -3,24 +3,23 @@ __docformat__ = "numpy"
import logging
import os
from typing import Optional, List
from typing import List, Optional
import matplotlib.pyplot as plt
import pandas as pd
from openbb_terminal.config_terminal import theme
from openbb_terminal.alternative.covid import covid_model
from openbb_terminal.config_plot import PLOT_DPI
from openbb_terminal.config_terminal import theme
from openbb_terminal.decorators import log_start_end
from openbb_terminal.helper_funcs import (
export_data,
is_valid_axes_count,
plot_autoscale,
print_rich_table,
is_valid_axes_count,
)
from openbb_terminal.rich_config import console
logger = logging.getLogger(__name__)
@@ -133,6 +132,7 @@ def display_covid_ov(
raw: bool = False,
limit: int = 10,
export: str = "",
sheet_name: str = None,
plot: bool = True,
) -> None:
"""Prints table showing historical cases and deaths by country.
@@ -145,6 +145,8 @@ def display_covid_ov(
Flag to display raw data
limit: int
Number of raw data to show
sheet_name: str
Optionally specify the name of the sheet the data is exported to.
export: str
Format to export data
plot: bool
@@ -165,7 +167,14 @@ def display_covid_ov(
)
if export:
export_data(export, os.path.dirname(os.path.abspath(__file__)), "ov", data)
data = covid_model.get_covid_ov(country, limit)
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"ov",
data,
sheet_name,
)
@log_start_end(log=logger)
@@ -175,6 +184,7 @@ def display_covid_stat(
raw: bool = False,
limit: int = 10,
export: str = "",
sheet_name: str = None,
plot: bool = True,
) -> None:
"""Prints table showing historical cases and deaths by country.
@@ -189,6 +199,8 @@ def display_covid_stat(
Flag to display raw data
limit: int
Number of raw data to show
sheet_name: str
Optionally specify the name of the sheet the data is exported to.
export: str
Format to export data
plot : bool
@@ -213,7 +225,13 @@ def display_covid_stat(
cols = data.columns.tolist()
cols = cols[-1:] + cols[:-1]
data = data[cols]
export_data(export, os.path.dirname(os.path.abspath(__file__)), stat, data)
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
stat,
data,
sheet_name,
)
@log_start_end(log=logger)
@@ -223,6 +241,7 @@ def display_case_slopes(
threshold: int = 10000,
ascend: bool = False,
export: str = "",
sheet_name: str = None,
) -> None:
"""Prints table showing countries with the highest case slopes.
@@ -253,4 +272,5 @@ def display_case_slopes(
os.path.dirname(os.path.abspath(__file__)),
f"slopes_{days_back}day",
data,
sheet_name,
)

View File

@@ -3,10 +3,11 @@ __docformat__ = "numpy"
import logging
import pandas as pd
import requests
from openbb_terminal.decorators import log_start_end
from openbb_terminal.helper_funcs import request
logger = logging.getLogger(__name__)
@@ -24,12 +25,12 @@ def get_stories(limit: int = 10) -> pd.DataFrame:
DataFrame with stories
"""
res = requests.get("https://hacker-news.firebaseio.com/v0/topstories.json")
res = request("https://hacker-news.firebaseio.com/v0/topstories.json")
if res.status_code == 200:
top_stories = res.json()
stories = []
for story_id in top_stories[:limit]:
story = requests.get(
story = request(
f"https://hacker-news.firebaseio.com/v0/item/{story_id}.json"
).json()
stories.append(story)

View File

@@ -15,12 +15,14 @@ logger = logging.getLogger(__name__)
@log_start_end(log=logger)
def display_stories(limit: int = 10, export: str = "") -> None:
def display_stories(limit: int = 10, export: str = "", sheet_name: str = None) -> None:
"""View top stories from HackerNews.
Parameters
----------
limit: int
Number of stories to return
sheet_name: str
Optionally specify the name of the sheet the data is exported to.
export: str
Export dataframe data to csv,json,xlsx file
"""
@@ -28,4 +30,10 @@ def display_stories(limit: int = 10, export: str = "") -> None:
if not df.empty:
df.columns = [col.capitalize() for col in df.columns]
print_rich_table(df, title="HackerNews Top Stories")
export_data(export, os.path.dirname(os.path.abspath(__file__)), "hn", df)
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"hn",
df,
sheet_name,
)

View File

@@ -3,16 +3,16 @@ __docformat__ = "numpy"
# pylint: disable=C0201,W1401
import logging
from typing import Any, Dict, Optional
import math
from datetime import datetime
import requests
from typing import Any, Dict, Optional
import pandas as pd
from openbb_terminal import config_terminal as cfg
from openbb_terminal.decorators import check_api_key, log_start_end
from openbb_terminal.helper_funcs import get_user_agent, request
from openbb_terminal.rich_config import console
from openbb_terminal.helper_funcs import get_user_agent
logger = logging.getLogger(__name__)
@@ -33,7 +33,7 @@ def get_github_data(url: str, **kwargs) -> Optional[Dict[str, Any]]:
Dict[str, Any]
Dictionary with data
"""
res = requests.get(
res = request(
url,
headers={
"Authorization": f"token {cfg.API_GITHUB_KEY}",

View File

@@ -3,22 +3,23 @@ __docformat__ = "numpy"
import logging
import os
from typing import Optional, List
from typing import List, Optional
from matplotlib import pyplot as plt
from matplotlib import ticker
from openbb_terminal.config_terminal import theme
from openbb_terminal.alternative.oss import github_model
from openbb_terminal.config_plot import PLOT_DPI
from openbb_terminal.config_terminal import theme
from openbb_terminal.cryptocurrency.dataframe_helpers import (
lambda_long_number_format_with_type_check,
)
from openbb_terminal.decorators import log_start_end
from openbb_terminal.helper_funcs import (
export_data,
is_valid_axes_count,
plot_autoscale,
print_rich_table,
is_valid_axes_count,
)
from openbb_terminal.alternative.oss import github_model
from openbb_terminal.cryptocurrency.dataframe_helpers import (
lambda_long_number_format_with_type_check,
)
logger = logging.getLogger(__name__)
@@ -26,7 +27,10 @@ logger = logging.getLogger(__name__)
@log_start_end(log=logger)
def display_star_history(
repo: str, export: str = "", external_axes: Optional[List[plt.Axes]] = None
repo: str,
export: str = "",
sheet_name: str = None,
external_axes: Optional[List[plt.Axes]] = None,
) -> None:
"""Plots repo summary [Source: https://api.github.com].
@@ -58,7 +62,13 @@ def display_star_history(
if external_axes is None:
theme.visualize_output()
export_data(export, os.path.dirname(os.path.abspath(__file__)), "sh", df)
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"sh",
df,
sheet_name,
)
@log_start_end(log=logger)
@@ -67,6 +77,7 @@ def display_top_repos(
categories: str = "",
limit: int = 10,
export: str = "",
sheet_name: str = None,
external_axes: Optional[List[plt.Axes]] = None,
) -> None:
"""Plots repo summary [Source: https://api.github.com].
@@ -116,11 +127,17 @@ def display_top_repos(
if external_axes is None:
theme.visualize_output()
export_data(export, os.path.dirname(os.path.abspath(__file__)), "tr", df)
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"tr",
df,
sheet_name,
)
@log_start_end(log=logger)
def display_repo_summary(repo: str, export: str = "") -> None:
def display_repo_summary(repo: str, export: str = "", sheet_name: str = None) -> None:
"""Prints table showing repo summary [Source: https://api.github.com].
Parameters
@@ -141,4 +158,5 @@ def display_repo_summary(repo: str, export: str = "") -> None:
os.path.dirname(os.path.abspath(__file__)),
"rs",
data,
sheet_name,
)

View File

@@ -5,21 +5,19 @@ import argparse
import logging
from typing import List
from openbb_terminal.custom_prompt_toolkit import NestedCompleter
from openbb_terminal import feature_flags as obbff
from openbb_terminal.alternative.oss import github_view
from openbb_terminal.alternative.oss import runa_view, runa_model
from openbb_terminal.alternative.oss import github_view, runa_model, runa_view
from openbb_terminal.custom_prompt_toolkit import NestedCompleter
from openbb_terminal.decorators import log_start_end
from openbb_terminal.helper_funcs import (
EXPORT_BOTH_RAW_DATA_AND_FIGURES,
EXPORT_ONLY_RAW_DATA_ALLOWED,
valid_repo,
parse_and_split_input,
valid_repo,
)
from openbb_terminal.menu import session
from openbb_terminal.parent_classes import BaseController
from openbb_terminal.rich_config import console, MenuText
from openbb_terminal.rich_config import MenuText, console
logger = logging.getLogger(__name__)
@@ -121,7 +119,11 @@ class OSSController(BaseController):
if ns_parser:
if valid_repo(ns_parser.repo):
github_view.display_repo_summary(
repo=ns_parser.repo, export=ns_parser.export
repo=ns_parser.repo,
export=ns_parser.export,
sheet_name=" ".join(ns_parser.sheet_name)
if ns_parser.sheet_name
else None,
)
@log_start_end(log=logger)
@@ -200,6 +202,9 @@ class OSSController(BaseController):
show_growth=ns_parser.show_growth,
chart_type=ns_parser.chart_type,
export=ns_parser.export,
sheet_name=" ".join(ns_parser.sheet_name)
if ns_parser.sheet_name
else None,
)
@log_start_end(log=logger)
@@ -244,4 +249,7 @@ class OSSController(BaseController):
categories=ns_parser.categories,
limit=ns_parser.limit,
export=ns_parser.export,
sheet_name=" ".join(ns_parser.sheet_name)
if ns_parser.sheet_name
else None,
)

View File

@@ -9,7 +9,7 @@ from requests.adapters import HTTPAdapter, RetryError
from urllib3.util.retry import Retry
from openbb_terminal.decorators import log_start_end
from openbb_terminal.helper_funcs import get_user_agent
from openbb_terminal.helper_funcs import get_user_agent, request
from openbb_terminal.rich_config import console
logger = logging.getLogger(__name__)
@@ -80,7 +80,7 @@ def _make_request(url: str) -> Union[BeautifulSoup, None]:
headers = {"User-Agent": get_user_agent()}
session = _retry_session("https://runacap.com/")
try:
req = session.get(url, headers=headers, timeout=5)
req = session.get(url, headers=headers)
except Exception as error:
logger.exception(str(error))
console.print(error)
@@ -109,7 +109,7 @@ def get_startups() -> pd.DataFrame:
pd.DataFrame
list of startups
"""
response = requests.get("https://runacap.com/ross-index/", timeout=10)
response = request("https://runacap.com/ross-index/")
soup = BeautifulSoup(response.content, "html.parser")
startups = []
if soup:

View File

@@ -1,25 +1,28 @@
"""Rekt view"""
import logging
import os
from typing import Optional, List
from typing import List, Optional
from matplotlib import pyplot as plt
from matplotlib import ticker
from openbb_terminal.alternative.oss import runa_model
from openbb_terminal.config_plot import PLOT_DPI
from openbb_terminal.config_terminal import theme
from openbb_terminal.decorators import log_start_end
from openbb_terminal.helper_funcs import (
export_data,
plot_autoscale,
lambda_long_number_format,
print_rich_table,
is_valid_axes_count,
lambda_long_number_format,
plot_autoscale,
print_rich_table,
)
from openbb_terminal.config_terminal import theme
from openbb_terminal.config_plot import PLOT_DPI
from openbb_terminal.rich_config import console
logger = logging.getLogger(__name__)
# pylint: disable=too-many-arguments
@log_start_end(log=logger)
def display_rossindex(
@@ -30,6 +33,7 @@ def display_rossindex(
show_growth: bool = True,
chart_type: str = "stars",
export: str = "",
sheet_name: str = None,
external_axes: Optional[List[plt.Axes]] = None,
) -> None:
"""Plots list of startups from ross index [Source: https://runacap.com/]
@@ -128,4 +132,5 @@ def display_rossindex(
os.path.dirname(os.path.abspath(__file__)),
"runaidx",
df,
sheet_name,
)

View File

@@ -0,0 +1,266 @@
""" UK Land Registry Model """
__docformat__ = "numpy"
import io
import logging
import pandas as pd
from SPARQLWrapper.Wrapper import CSV, SPARQLWrapper
from openbb_terminal.decorators import log_start_end
logger = logging.getLogger(__name__)
def pcd_format(postcode: str):
return (
postcode[0 : len(postcode) - 3].strip()
+ " "
+ postcode[len(postcode) - 3 : len(postcode)]
)
@log_start_end(log=logger)
def get_estate_sales(postcode: str, limit: int = 25) -> pd.DataFrame:
"""All sales for specified postcode.
Parameters
----------
postcode : str
Postcode
limit : int
number of rows to return
Returns
-------
pd.DataFrame
All sales with that postcode
"""
if not postcode:
return pd.DataFrame()
# the upper is done since SDK calls don't appear to go through the controller
pcd_postcode = pcd_format(postcode.upper())
query = f"""
PREFIX lrppi: <http://landregistry.data.gov.uk/def/ppi/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX lrcommon: <http://landregistry.data.gov.uk/def/common/>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX ukhpi: <http://landregistry.data.gov.uk/def/ukhpi/>
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX sr: <http://data.ordnancesurvey.co.uk/ontology/spatialrelations/>
SELECT ?paon ?saon ?street ?town ?county ?postcode ?amount ?date ?id ?category
WHERE
{{ VALUES ?postcode {{ "{pcd_postcode}" }}
?addr lrcommon:postcode ?postcode .
?transx lrppi:propertyAddress ?addr ;
lrppi:pricePaid ?amount ;
lrppi:transactionId ?id ;
lrppi:transactionDate ?date .
?transx lrppi:transactionCategory/skos:prefLabel ?category.
OPTIONAL {{ ?addr lrcommon:county ?county }}
OPTIONAL {{ ?addr lrcommon:paon ?paon }}
OPTIONAL {{ ?addr lrcommon:saon ?saon }}
OPTIONAL {{ ?addr lrcommon:street ?street }}
OPTIONAL {{ ?addr lrcommon:town ?town }}
}}
ORDER BY DESC(?date)
LIMIT {limit}
"""
endpoint = "http://landregistry.data.gov.uk/landregistry/query"
# df = sparql_dataframe.get(endpoint, query)
df = pd.DataFrame()
sparql = SPARQLWrapper(endpoint)
sparql.setReturnFormat(CSV)
sparql.setQuery(query)
results = sparql.query().convert()
if isinstance(results, bytes):
_csv = io.StringIO(results.decode("utf-8"))
# print( pd.read_csv(_csv, sep=","))
df = pd.read_csv(_csv, sep=",")
return df
@log_start_end(log=logger)
def get_towns_sold_prices(
town: str,
start_date: str,
end_date: str,
limit: int = 25,
) -> pd.DataFrame:
"""Get towns sold house price data.
Parameters
----------
town : str
town
start_date : str
startDate
end_date : str
endDate
limit : int
number of rows to return
Returns
-------
pd.DataFrame
All sales for that town within the date range specified
"""
# the upper is done since SDK calls don't appear to go through the controller
town = town.upper()
query = f"""
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix owl: <http://www.w3.org/2002/07/owl#>
prefix xsd: <http://www.w3.org/2001/XMLSchema#>
prefix sr: <http://data.ordnancesurvey.co.uk/ontology/spatialrelations/>
prefix ukhpi: <http://landregistry.data.gov.uk/def/ukhpi/>
prefix lrppi: <http://landregistry.data.gov.uk/def/ppi/>
prefix skos: <http://www.w3.org/2004/02/skos/core#>
prefix lrcommon: <http://landregistry.data.gov.uk/def/common/>
SELECT ?paon ?saon ?street ?county ?postcode ?amount ?date ?category
WHERE
{{
VALUES ?town {{"{town}"^^xsd:string}}
?addr lrcommon:town ?town ;
lrcommon:postcode ?postcode.
?transx lrppi:propertyAddress ?addr ;
lrppi:pricePaid ?amount ;
lrppi:transactionDate ?date ;
lrppi:transactionCategory/skos:prefLabel ?category.
FILTER (
?date > "{start_date}"^^xsd:date &&
?date < "{end_date}"^^xsd:date
).
OPTIONAL {{?addr lrcommon:county ?county}}
OPTIONAL {{?addr lrcommon:paon ?paon}}
OPTIONAL {{?addr lrcommon:saon ?saon}}
OPTIONAL {{?addr lrcommon:saon ?postcode}}
OPTIONAL {{?addr lrcommon:street ?street}}
}}
ORDER BY (?date && ?postcode)
LIMIT {limit}
"""
endpoint = "http://landregistry.data.gov.uk/landregistry/query"
df = pd.DataFrame()
sparql = SPARQLWrapper(endpoint)
sparql.setReturnFormat(CSV)
sparql.setQuery(query)
sparql.method = "POST"
results = sparql.query().convert()
if isinstance(results, bytes):
_csv = io.StringIO(results.decode("utf-8"))
df = pd.read_csv(_csv, sep=",")
return df
@log_start_end(log=logger)
def get_region_stats(
region: str, start_date: str = "2010-01-01", end_date: str = ""
) -> pd.DataFrame:
"""Get regional house price statistics.
Parameters
----------
region : str
region
startd_ate : str
startDate
end_date : str
endDate
Returns
-------
pd.DataFrame
All stats for that region within the date range specified
"""
region = region.lower()
query = f"""
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix owl: <http://www.w3.org/2002/07/owl#>
prefix xsd: <http://www.w3.org/2001/XMLSchema#>
prefix sr: <http://data.ordnancesurvey.co.uk/ontology/spatialrelations/>
prefix ukhpi: <http://landregistry.data.gov.uk/def/ukhpi/>
prefix lrppi: <http://landregistry.data.gov.uk/def/ppi/>
prefix skos: <http://www.w3.org/2004/02/skos/core#>
prefix lrcommon: <http://landregistry.data.gov.uk/def/common/>
SELECT ?month ?avgPrice ?avgPriceCash ?totalSalesVolume ?avgPriceExistingProperty
?avgPriceFirstTimeBuyer
?avgPriceDetached ?hpi ?detachedhpi ?newbuildhpi
{{
values ?refRegion {{<http://landregistry.data.gov.uk/id/region/{region}>}}
?region ukhpi:refPeriodStart ?month ;
ukhpi:housePriceIndex ?hpi ;
ukhpi:refRegion ?refRegion ;
ukhpi:averagePrice ?avgPrice ;
ukhpi:averagePriceCash ?avgPriceCash ;
ukhpi:salesVolume ?totalSalesVolume ;
ukhpi:averagePriceDetached ?avgPriceDetached ;
ukhpi:averagePriceExistingProperty ?avgPriceExistingProperty ;
ukhpi:averagePriceFirstTimeBuyer ?avgPriceFirstTimeBuyer ;
ukhpi:housePriceIndexDetached ?detachedhpi ;
ukhpi:housePriceIndexNewBuild ?newbuildhpi .
?refRegion rdfs:label ?regionLabel .
FILTER(LANG(?regionLabel) = "en").
FILTER (
?month > "{start_date}"^^xsd:date &&
?month < "{end_date}"^^xsd:date
)
OPTIONAL {{?region ukhpi:housePriceIndexDetached ?detachedhpi}}
OPTIONAL {{?region ukhpi:housePriceIndexNewBuild ?newbuildhpi }}
OPTIONAL {{?region ukhpi:averagePrice ?averagePrice }}
}}
ORDER BY (?month)
"""
endpoint = "http://landregistry.data.gov.uk/landregistry/query"
df = pd.DataFrame()
sparql = SPARQLWrapper(endpoint)
sparql.setReturnFormat(CSV)
sparql.setQuery(query)
sparql.method = "POST"
results = sparql.query().convert()
if isinstance(results, bytes):
_csv = io.StringIO(results.decode("utf-8"))
df = pd.read_csv(_csv, sep=",")
return df

View File

@@ -0,0 +1,149 @@
""" UK Land Registry View """
__docformat__ = "numpy"
import logging
import os
from openbb_terminal.alternative.realestate import landRegistry_model
from openbb_terminal.decorators import log_start_end
from openbb_terminal.helper_funcs import export_data, print_rich_table
from openbb_terminal.rich_config import console
logger = logging.getLogger(__name__)
@log_start_end(log=logger)
def display_estate_sales(postcode: str, limit: int, export: str = "") -> None:
"""Display real estate sales.
Parameters
----------
postcode : str
Postcode
limit : int
number of rows to return
"""
sales = landRegistry_model.get_estate_sales(postcode, limit)
if sales.empty or len(sales) == 0:
console.print(
"[red]"
+ "No data loaded.\n"
+ "Make sure you picked a valid postcode."
+ "[/red]\n"
)
return
print_rich_table(
sales,
show_index=False,
title=f"[bold]{postcode}[/bold]",
)
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"sales",
sales,
)
@log_start_end(log=logger)
def display_towns_sold_prices(
town: str, start_date: str, end_date: str, limit: int, export: str = ""
):
"""Get towns sold house price data.
Parameters
----------
town : str
town
start_date : str
startDate
end_date : str
endDate
limit : int
number of rows to return
Returns
-------
pd.DataFrame
All sales for that town within the date range specified
"""
sales = landRegistry_model.get_towns_sold_prices(town, start_date, end_date, limit)
if sales.empty or len(sales) == 0:
console.print(
"[red]"
+ "No data loaded.\n"
+ "Make sure you picked a valid town and date range."
+ "[/red]\n"
)
return
print_rich_table(
sales,
show_index=False,
title=f"[bold]{town} : {start_date} - {end_date}[/bold]",
)
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"towns_sold_prices",
sales,
)
@log_start_end(log=logger)
def display_region_stats(region: str, start_date: str, end_date: str, export: str = ""):
"""Get towns sold house price data.
Parameters
----------
region : str
region
start_date : str
startDate
end_date : str
endDate
Returns
-------
pd.DataFrame
All stats for that region within the date range specified
"""
stats = landRegistry_model.get_region_stats(region, start_date, end_date)
if stats.empty or len(stats) == 0:
console.print(
"[red]"
+ "No data loaded.\n"
+ "Make sure you picked a valid region and date range."
+ "[/red]\n"
)
return
print_rich_table(
stats,
show_index=False,
title=f"[bold]{region} : {start_date} - {end_date}[/bold]",
)
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"region_stats",
stats,
)

View File

@@ -0,0 +1,266 @@
"""Trading Hours Controller."""
__docformat__ = "numpy"
import argparse
import logging
from datetime import datetime, timedelta
from typing import List
from openbb_terminal import feature_flags as obbff
from openbb_terminal.alternative.realestate import landRegistry_view
from openbb_terminal.custom_prompt_toolkit import NestedCompleter
from openbb_terminal.decorators import log_start_end
from openbb_terminal.helper_funcs import (
EXPORT_ONLY_RAW_DATA_ALLOWED,
check_positive,
)
from openbb_terminal.menu import session
from openbb_terminal.parent_classes import BaseController
from openbb_terminal.rich_config import MenuText, console
logger = logging.getLogger(__name__)
def get_relative_date(months: int):
date = datetime.now() - timedelta(days=365 / 12 * months)
return date.strftime("%Y-%m-%d")
def start_date():
return get_relative_date(13)
def end_date():
return get_relative_date(1)
class RealEstateController(BaseController):
"""Real Estate Controller class."""
CHOICES_COMMANDS = ["sales", "townsales", "regionstats"]
PATH = "/alternative/realestate/"
CHOICES_GENERATION = True
# FILE_PATH = os.path.join(os.path.dirname(__file__), "README.md")
def __init__(self, queue: List[str] = None):
"""Construct Data."""
super().__init__(queue)
self.enddate = None
self.startdate = None
self.town = None
self.postcode = None
self.region = None
self.limit = 25
if session and obbff.USE_PROMPT_TOOLKIT:
choices: dict = self.choices_default
self.completer = NestedCompleter.from_nested_dict(choices)
def print_help(self):
mt = MenuText("alternative/realestate/")
mt.add_cmd("sales")
mt.add_cmd("townsales")
mt.add_cmd("regionstats")
console.print(text=mt.menu_text, menu="UK Real Estate Sales Data")
@log_start_end(log=logger)
def call_sales(self, other_args: List[str]):
"""Process 'postcode' command."""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="sales",
description="Select the postcode you want to see sold house price data for. [Source: UK Land Registry]",
)
parser.add_argument(
"-p",
"--postcode",
help="Postcode",
type=str.upper,
required="-h" not in other_args,
dest="postcode",
metavar="postcode",
)
parser.add_argument(
"-l",
"--limit",
help="Number of entries to return",
type=check_positive,
required=False,
dest="limit",
metavar="limit",
default=25,
)
if (
other_args
and "-p" not in other_args[0]
and "--postcode" not in other_args[0]
and "-h" not in other_args
):
other_args.insert(0, "-p")
ns_parser = self.parse_known_args_and_warn(
parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED
)
if ns_parser:
if ns_parser.postcode:
landRegistry_view.display_estate_sales(
ns_parser.postcode, ns_parser.limit, export=ns_parser.export
)
else:
console.print("[red]Select valid postcode[/red]\n")
@log_start_end(log=logger)
def call_townsales(self, other_args: List[str]):
"""Process 'townsales' command."""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="townsales",
description="""Select the town and date range you want to see sold house price data for.
[Source: UK Land Registry]""",
)
parser.add_argument(
"-t",
"--town",
help="Town that we want sales information for",
type=str.upper,
required="-h" not in other_args,
dest="town",
metavar="town",
)
parser.add_argument(
"-s",
"--startdate",
help="Start date that we want sales information for",
type=str,
required=False,
dest="startdate",
metavar="startdate",
default=start_date(),
)
parser.add_argument(
"-e",
"--enddate",
help="End date that we want sales information for",
type=str,
required=False,
dest="enddate",
metavar="enddate",
default=end_date(),
)
parser.add_argument(
"-l",
"--limit",
help="Number of entries to return",
type=check_positive,
required=False,
dest="limit",
metavar="limit",
default=25,
)
if (
other_args
and "-t" not in other_args[0]
and "--town" not in other_args[0]
and "-h" not in other_args
):
other_args.insert(0, "-t")
ns_parser = self.parse_known_args_and_warn(
parser,
other_args,
EXPORT_ONLY_RAW_DATA_ALLOWED,
)
if ns_parser:
if ns_parser.town and ns_parser.startdate and ns_parser.enddate:
landRegistry_view.display_towns_sold_prices(
ns_parser.town,
ns_parser.startdate,
ns_parser.enddate,
ns_parser.limit,
ns_parser.export,
)
else:
console.print(
"[red]Select the town you want to know about and a valid date range.[/red]\n"
)
@log_start_end(log=logger)
def call_regionstats(self, other_args: List[str]):
"""Process 'regionstats' command."""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="regionstats",
description="Select the region and date range you want see stats for. [Source: UK Land Registry]",
)
parser.add_argument(
"-r",
"--region",
help="Region that we want stats for",
type=str.lower,
required="-h" not in other_args,
dest="region",
metavar="region",
)
parser.add_argument(
"-s",
"--startdate",
help="Start date that we want sales information for",
type=str,
required=False,
dest="startdate",
metavar="startdate",
default=start_date(),
)
parser.add_argument(
"-e",
"--enddate",
help="End date that we want sales information for",
type=str,
required=False,
dest="enddate",
metavar="enddate",
default=end_date(),
)
if (
other_args
and "-r" not in other_args[0]
and "--region" not in other_args[0]
and "-h" not in other_args
):
other_args.insert(0, "-r")
ns_parser = self.parse_known_args_and_warn(
parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED
)
if ns_parser:
if ns_parser.region and ns_parser.startdate and ns_parser.enddate:
landRegistry_view.display_region_stats(
ns_parser.region,
ns_parser.startdate,
ns_parser.enddate,
ns_parser.export,
)
else:
console.print(
"[red]Select the region you want to know about and a valid date range.[/red]\n"
)

View File

@@ -1,6 +1,6 @@
# This is for helpers that do NOT import any OpenBB Modules
from typing import Callable, Any, Literal
import os
from typing import Any, Callable, Literal
from rich.console import Console

View File

@@ -4,9 +4,9 @@ __docformat__ = "numpy"
import logging
import pandas as pd
import requests
from openbb_terminal.decorators import log_start_end
from openbb_terminal.helper_funcs import request
logger = logging.getLogger(__name__)
@@ -25,7 +25,7 @@ def get_sentiment(symbol: str) -> pd.DataFrame:
pd.DataFrame
Empty if there was an issue with data retrieval
"""
result = requests.get(f"https://api.finbrain.tech/v0/sentiments/{symbol}")
result = request(f"https://api.finbrain.tech/v0/sentiments/{symbol}")
sentiment = pd.DataFrame()
if result.status_code == 200:
result_json = result.json()

View File

@@ -3,25 +3,24 @@ __docformat__ = "numpy"
import logging
import os
from typing import Optional, List
from typing import List, Optional
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from openbb_terminal.config_terminal import theme
from openbb_terminal import rich_config
from openbb_terminal.common.behavioural_analysis import finbrain_model
from openbb_terminal.config_plot import PLOT_DPI
from openbb_terminal.config_terminal import theme
from openbb_terminal.decorators import log_start_end
from openbb_terminal.helper_funcs import (
export_data,
is_valid_axes_count,
plot_autoscale,
print_rich_table,
is_valid_axes_count,
)
from openbb_terminal.rich_config import console
from openbb_terminal import rich_config
logger = logging.getLogger(__name__)
@@ -37,6 +36,7 @@ def display_sentiment_analysis(
symbol: str,
raw: bool = False,
export: str = "",
sheet_name: str = None,
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plots Sentiment analysis from FinBrain. Prints table if raw is True. [Source: FinBrain]
@@ -47,6 +47,8 @@ def display_sentiment_analysis(
Ticker symbol to get the sentiment analysis from
raw: False
Display raw table data
sheet_name: str
Optionally specify the name of the sheet the data is exported to.
export: str
Format to export data
external_axes: Optional[List[plt.Axes]], optional
@@ -138,5 +140,9 @@ def display_sentiment_analysis(
)
export_data(
export, os.path.dirname(os.path.abspath(__file__)), "headlines", sentiment
export,
os.path.dirname(os.path.abspath(__file__)),
"headlines",
sentiment,
sheet_name,
)

View File

@@ -4,10 +4,10 @@ __docformat__ = "numpy"
import logging
import pandas as pd
import requests
from openbb_terminal import config_terminal as cfg
from openbb_terminal.decorators import check_api_key, log_start_end
from openbb_terminal.helper_funcs import request
from openbb_terminal.rich_config import console
logger = logging.getLogger(__name__)
@@ -28,7 +28,7 @@ def get_sentiment_stats(ticker: str) -> pd.DataFrame:
pd.DataFrame
Get sentiment stats
"""
response = requests.get(
response = request(
f"https://finnhub.io/api/v1/news-sentiment?symbol={ticker}&token={cfg.API_FINNHUB_KEY}"
)

View File

@@ -7,17 +7,16 @@ import os
import pandas as pd
from openbb_terminal.common.behavioural_analysis import finnhub_model
from openbb_terminal.decorators import log_start_end
from openbb_terminal.decorators import check_api_key, log_start_end
from openbb_terminal.helper_funcs import export_data
from openbb_terminal.rich_config import console
from openbb_terminal.decorators import check_api_key
logger = logging.getLogger(__name__)
@log_start_end(log=logger)
@check_api_key(["API_FINNHUB_KEY"])
def display_sentiment_stats(ticker: str, export: str = ""):
def display_sentiment_stats(ticker: str, export: str = "", sheet_name: str = None):
"""
Prints Sentiment stats which displays buzz, news score, articles last week, articles weekly average,
bullish vs bearish percentages, sector average bullish percentage, and sector average news score
@@ -55,6 +54,7 @@ Sector Average News Score: {round(100*d_stats['sectorAverageNewsScore'],2)} %"""
os.path.dirname(os.path.abspath(__file__)),
"stats",
pd.DataFrame(d_stats),
sheet_name,
)
else:

View File

@@ -3,20 +3,20 @@ __docformat__ = "numpy"
import logging
import os
from typing import Optional, List
import pandas as pd
from typing import List, Optional
import matplotlib.pyplot as plt
import pandas as pd
from openbb_terminal.config_terminal import theme
from openbb_terminal.config_plot import PLOT_DPI
from openbb_terminal.common.behavioural_analysis import google_model
from openbb_terminal.config_plot import PLOT_DPI
from openbb_terminal.config_terminal import theme
from openbb_terminal.decorators import log_start_end
from openbb_terminal.helper_funcs import (
export_data,
is_valid_axes_count,
plot_autoscale,
print_rich_table,
is_valid_axes_count,
)
logger = logging.getLogger(__name__)
@@ -27,6 +27,7 @@ def display_mentions(
symbol: str,
start_date: str = "",
export: str = "",
sheet_name: str = None,
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plots weekly bars of stock's interest over time. other users watchlist. [Source: Google].
@@ -37,6 +38,8 @@ def display_mentions(
Ticker symbol
start_date : str
Start date as YYYY-MM-DD string
sheet_name: str
Optionally specify the name of the sheet the data is exported to.
export: str
Format to export data
external_axes : Optional[List[plt.Axes]], optional
@@ -80,7 +83,11 @@ def display_mentions(
theme.visualize_output()
export_data(
export, os.path.dirname(os.path.abspath(__file__)), "mentions", df_interest
export,
os.path.dirname(os.path.abspath(__file__)),
"mentions",
df_interest,
sheet_name,
)
@@ -90,6 +97,7 @@ def display_correlation_interest(
data: pd.DataFrame,
words: List[str],
export: str = "",
sheet_name: str = None,
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plots interest over time of words/sentences versus stock price. [Source: Google].
@@ -102,6 +110,8 @@ def display_correlation_interest(
Data dataframe
words : List[str]
Words to check for interest for
sheet_name: str
Optionally specify the name of the sheet the data is exported to.
export: str
Format to export data
external_axes : Optional[List[plt.Axes]], optional
@@ -136,6 +146,8 @@ def display_correlation_interest(
colors = theme.get_colors()[1:]
for idx, word in enumerate(words):
df_interest = google_model.get_mentions(word)
if df_interest.empty:
continue
ax[1].plot(df_interest.index, df_interest[word], "-", color=colors[idx])
ax[1].set_ylabel("Interest [%]")
@@ -148,7 +160,11 @@ def display_correlation_interest(
theme.visualize_output()
export_data(
export, os.path.dirname(os.path.abspath(__file__)), "interest", df_interest
export,
os.path.dirname(os.path.abspath(__file__)),
"interest",
df_interest,
sheet_name,
)
@@ -157,6 +173,7 @@ def display_regions(
symbol: str,
limit: int = 5,
export: str = "",
sheet_name: str = None,
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plots bars of regions based on stock's interest. [Source: Google].
@@ -167,6 +184,8 @@ def display_regions(
Ticker symbol
limit: int
Number of regions to show
sheet_name: str
Optionally specify the name of the sheet the data is exported to.
export: str
Format to export data
external_axes : Optional[List[plt.Axes]], optional
@@ -199,11 +218,19 @@ def display_regions(
if external_axes is None:
theme.visualize_output()
export_data(export, os.path.dirname(os.path.abspath(__file__)), "regions", df)
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"regions",
df,
sheet_name,
)
@log_start_end(log=logger)
def display_queries(symbol: str, limit: int = 5, export: str = ""):
def display_queries(
symbol: str, limit: int = 5, export: str = "", sheet_name: str = None
):
"""Prints table showing top related queries with this stock's query. [Source: Google].
Parameters
@@ -212,6 +239,8 @@ def display_queries(symbol: str, limit: int = 5, export: str = ""):
Ticker symbol
limit: int
Number of regions to show
sheet_name: str
Optionally specify the name of the sheet the data is exported to.
export: str
Format to export data
{"csv","json","xlsx","png","jpg","pdf","svg"}
@@ -233,11 +262,14 @@ def display_queries(symbol: str, limit: int = 5, export: str = ""):
os.path.dirname(os.path.abspath(__file__)),
"queries",
df,
sheet_name,
)
@log_start_end(log=logger)
def display_rise(symbol: str, limit: int = 10, export: str = ""):
def display_rise(
symbol: str, limit: int = 10, export: str = "", sheet_name: str = None
):
"""Prints top rising related queries with this stock's query. [Source: Google].
Parameters
@@ -246,6 +278,8 @@ def display_rise(symbol: str, limit: int = 10, export: str = ""):
Ticker symbol
limit: int
Number of queries to show
sheet_name: str
Optionally specify the name of the sheet the data is exported to.
export: str
Format to export data
"""
@@ -261,5 +295,9 @@ def display_rise(symbol: str, limit: int = 10, export: str = ""):
)
export_data(
export, os.path.dirname(os.path.abspath(__file__)), "rise", df_related_queries
export,
os.path.dirname(os.path.abspath(__file__)),
"rise",
df_related_queries,
sheet_name,
)

View File

@@ -1,8 +1,8 @@
"""Reddit Helpers"""
__docformat__ = "numpy"
from typing import List
import re
from typing import List
import praw

View File

@@ -3,9 +3,9 @@ __docformat__ = "numpy"
# pylint:disable=too-many-lines
import logging
import warnings
from datetime import datetime, timedelta
from typing import List, Tuple
import warnings
import finviz
import pandas as pd
@@ -528,7 +528,6 @@ def get_spac(
try:
for submission in submissions:
# Get more information about post using PRAW api
submission = praw_api.submission(id=submission.id)
@@ -814,13 +813,11 @@ def get_due_dilligence(
# 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"],
)[show_all_flairs]:
s_datetime = datetime.utcfromtimestamp(
submission.created_utc
).strftime("%Y-%m-%d %H:%M:%S")

View File

@@ -14,15 +14,14 @@ import praw
import seaborn as sns
from openbb_terminal.common.behavioural_analysis import reddit_model
from openbb_terminal.config_terminal import theme
from openbb_terminal.config_plot import PLOT_DPI
from openbb_terminal.decorators import check_api_key
from openbb_terminal.decorators import log_start_end
from openbb_terminal.config_terminal import theme
from openbb_terminal.decorators import check_api_key, log_start_end
from openbb_terminal.helper_funcs import (
export_data,
is_valid_axes_count,
plot_autoscale,
print_rich_table,
is_valid_axes_count,
)
from openbb_terminal.rich_config import console
@@ -193,7 +192,11 @@ def display_watchlist(limit: int = 5):
]
)
def display_popular_tickers(
limit: int = 10, post_limit: int = 50, subreddits: str = "", export: str = ""
limit: int = 10,
post_limit: int = 50,
subreddits: str = "",
export: str = "",
sheet_name: str = None,
):
"""Prints table showing latest popular tickers. [Source: Reddit].
@@ -224,6 +227,7 @@ def display_popular_tickers(
os.path.dirname(os.path.abspath(__file__)),
"popular",
popular_tickers_df,
sheet_name,
)
@@ -408,6 +412,7 @@ def display_redditsent(
subreddits: str = "all",
display: bool = False,
export: str = "",
sheet_name: str = None,
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plots Reddit sentiment about a search term. Prints table showing if display is True.
@@ -430,6 +435,8 @@ def display_redditsent(
Comma-separated list of subreddits
display: bool
Enable printing of raw sentiment values for each post
sheet_name: str
Optionally specify the name of the sheet the data is exported to.
export: str
Format to export data
external_axes: Optional[List[plt.Axes]]
@@ -469,4 +476,5 @@ def display_redditsent(
os.path.dirname(os.path.abspath(__file__)),
"polarity_scores",
df,
sheet_name,
)

View File

@@ -1,195 +0,0 @@
"""SentimentInvestor Model"""
__docformat__ = "numpy"
from typing import Union, Dict, Optional
from datetime import datetime, timedelta
import logging
import pandas as pd
import requests
from openbb_terminal import config_terminal as cfg
from openbb_terminal.decorators import log_start_end, check_api_key
from openbb_terminal.rich_config import console
logger = logging.getLogger(__name__)
@log_start_end(log=logger)
@check_api_key(["API_SENTIMENTINVESTOR_TOKEN"])
def get_historical(
symbol: str,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
number: int = 100,
) -> pd.DataFrame:
"""Get hour-level sentiment data for the chosen symbol.
Source: [Sentiment Investor]
Parameters
----------
symbol: str
Ticker to view sentiment data
start_date: Optional[str]
Initial date like string or unix timestamp (e.g. 12-21-2021)
end_date: Optional[str]
End date like string or unix timestamp (e.g. 12-21-2021)
number : int
Number of results returned by API call
Maximum 250 per api call
Returns
-------
pd.DataFrame
Dataframe of historical sentiment
"""
if start_date is None:
start_date = (datetime.utcnow() - timedelta(days=7)).strftime("%Y-%m-%d")
if end_date is None:
end_date = datetime.utcnow().strftime("%Y-%m-%d")
payload: Dict[str, Union[int, str]] = {
"token": cfg.API_SENTIMENTINVESTOR_TOKEN,
"symbol": symbol,
"start": str(start_date),
"end": str(end_date),
"limit": number,
}
response = requests.get(
"https://api.sentimentinvestor.com/v1/historical", params=payload
)
response_json = response.json()
df = pd.DataFrame()
if "results" in response_json:
if response_json["results"]:
df = pd.DataFrame(response_json["results"])
df = df.set_index("timestamp_date")
df.index = pd.to_datetime(df.index)
else:
console.print("No data found.\n")
elif "error" in response_json:
if "Authorization error" in response_json["error"]:
console.print("[red]Invalid API Key[/red]\n")
else:
console.print({response_json["error"]})
return df
@check_api_key(["API_SENTIMENTINVESTOR_TOKEN"])
def check_supported_ticker(symbol: str) -> bool:
"""Check if the ticker is supported.
Source: [Sentiment Investor]
Parameters
----------
symbol: str
Ticker symbol to view sentiment data
Returns
-------
bool
True if ticker is supported
"""
payload: Dict[str, str] = {
"token": cfg.API_SENTIMENTINVESTOR_TOKEN,
"symbol": symbol,
}
response = requests.get(
"https://api.sentimentinvestor.com/v1/supported", params=payload
)
if response.status_code >= 500:
return False
response_json = response.json()
result = False
if "result" in response_json:
# if ticker is valid, payload has result key
if response_json["result"]:
result = response_json["result"]
else:
console.print(
f"[red]Ticker {symbol} not supported. Please try another one![/red]\n"
)
elif "error" in response_json:
if "Authorization error" in response_json["error"]:
console.print("[red]Invalid API Key[/red]\n")
else:
console.print({response_json["error"]})
return result
@check_api_key(["API_SENTIMENTINVESTOR_TOKEN"])
def get_trending(
start_date: Optional[str] = None,
hour: int = 0,
number: int = 10,
) -> pd.DataFrame:
"""Get sentiment data on the most talked about tickers
within the last hour Source: [Sentiment Investor].
Parameters
----------
start_date : Optional[str]
Initial date, format YYYY-MM-DD
hour: int
Hour of the day in 24-hour notation (e.g. 14)
number : int
Number of results returned by API call
Maximum 250 per api call
Returns
-------
pd.DataFrame
Dataframe of trending data
"""
if start_date is None:
start_date = datetime.today().strftime("%Y-%m-%d")
# type is datetime
start_timestamp = datetime.strptime(start_date, "%Y-%m-%d") + timedelta(hours=hour)
payload: Dict[str, Union[int, str]] = {
"token": cfg.API_SENTIMENTINVESTOR_TOKEN,
"start": str(start_timestamp),
"end": str(start_timestamp),
"limit": number,
}
response = requests.get(
"https://api.sentimentinvestor.com/v1/trending", params=payload
)
if response.status_code >= 500:
return pd.DataFrame()
response_json = response.json()
df = pd.DataFrame()
if "results" in response_json:
if response_json["results"]:
df = pd.DataFrame(response_json["results"])
else:
console.print(f"No data found for start date of {str(start_timestamp)}.\n")
elif "error" in response_json:
if "Authorization error" in response_json["error"]:
console.print("[red]Invalid API Key[/red]\n")
else:
console.print({response_json["error"]})
return df

View File

@@ -1,217 +0,0 @@
"""SentimentInvestor View"""
__docformat__ = "numpy"
import logging
import os
from typing import Optional, List
from datetime import datetime, timedelta
from matplotlib import pyplot as plt
from matplotlib.lines import Line2D
import pandas as pd
from openbb_terminal.config_terminal import theme
from openbb_terminal.config_plot import PLOT_DPI
from openbb_terminal.rich_config import console
from openbb_terminal.common.behavioural_analysis import sentimentinvestor_model
from openbb_terminal.decorators import log_start_end
from openbb_terminal.decorators import check_api_key
from openbb_terminal.helper_funcs import (
export_data,
print_rich_table,
plot_autoscale,
is_valid_axes_count,
)
logger = logging.getLogger(__name__)
@log_start_end(log=logger)
@check_api_key(["API_SENTIMENTINVESTOR_TOKEN"])
def display_historical(
symbol: str,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
number: int = 100,
raw: bool = False,
limit: int = 10,
export: str = "",
external_axes: Optional[List[plt.Axes]] = None,
):
"""Display historical sentiment data of a ticker,
and plot a chart with RHI and AHI.
Parameters
----------
symbol: str
Ticker symbol to view sentiment data
start_date: Optional[str]
Initial date like string or unix timestamp (e.g. 2021-12-21)
end_date: Optional[str]
End date like string or unix timestamp (e.g. 2022-01-15)
number: int
Number of results returned by API call
Maximum 250 per api call
raw: boolean
Whether to display raw data, by default False
limit: int
Number of results display on the terminal
Default: 10
export: str
Format to export data
external_axes: Optional[List[plt.Axes]], optional
External axes (2 axes are expected in the list), by default None
"""
if start_date is None:
start_date = (datetime.utcnow() - timedelta(days=7)).strftime("%Y-%m-%d")
if end_date is None:
end_date = datetime.utcnow().strftime("%Y-%m-%d")
supported_ticker = sentimentinvestor_model.check_supported_ticker(symbol)
# Check to see if the ticker is supported
if not supported_ticker:
logger.error("Ticker not supported")
console.print(
f"[red]Ticker {symbol} not supported. Please try another one![/red]\n"
)
return
df = sentimentinvestor_model.get_historical(symbol, start_date, end_date, number)
if df.empty:
return
# This plot has 2 axes
if external_axes is None:
_, ax1 = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
ax2 = ax1.twinx()
elif is_valid_axes_count(external_axes, 2):
(ax1, ax2) = external_axes
else:
return
ax1.plot(df.index, df["RHI"], color=theme.get_colors()[0])
ax2.plot(df.index, df["AHI"], color=theme.get_colors(reverse=True)[0])
ax1.set_ylabel("RHI")
ax1.set_title("Hourly-level data of RHI and AHI")
ax1.set_xlim(df.index[0], df.index[-1])
theme.style_primary_axis(ax1)
ax1.yaxis.set_label_position("left")
ax2.set_ylabel("AHI")
theme.style_primary_axis(ax2)
ax2.yaxis.set_label_position("right")
ax2.grid(visible=False)
# Manually construct the chart legend
colors = [theme.get_colors()[0], theme.get_colors(reverse=True)[0]]
lines = [Line2D([0], [0], color=c) for c in colors]
labels = ["RHI", "AHI"]
ax2.legend(lines, labels)
if external_axes is None:
theme.visualize_output()
export_data(
export,
os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
"hist",
df,
)
RAW_COLS = ["twitter", "stocktwits", "yahoo", "likes", "RHI", "AHI"]
if raw:
df.index = df.index.strftime("%Y-%m-%d %H:%M")
df.index.name = "Time"
print_rich_table(
df[RAW_COLS].head(limit),
headers=[
"Twitter",
"Stocktwits",
"Yahoo",
"Likes",
"RHI",
"AHI",
],
show_index=True,
index_name="Time",
title="Historical Sentiment Data",
)
@log_start_end(log=logger)
@check_api_key(["API_SENTIMENTINVESTOR_TOKEN"])
def display_trending(
start_date: Optional[str] = None,
hour: int = 0,
number: int = 10,
limit: int = 10,
export: str = "",
):
"""Display most talked about tickers within
the last hour together with their sentiment data.
Parameters
----------
start_date : Optional[str]
Initial date, format YYYY-MM-DD
hour: int
Hour of the day in 24-hour notation (e.g. 14)
number : int
Number of results returned by API call
Maximum 250 per api call
limit: int
Number of results display on the terminal
Default: 10
export: str
Format to export data
"""
if start_date is None:
start_date = datetime.today().strftime("%Y-%m-%d")
df = sentimentinvestor_model.get_trending(start_date, hour, number)
if df.empty:
return
export_data(
export,
os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
"trend",
df,
)
RAW_COLS = [
"total",
"twitter",
"stocktwits",
"yahoo",
"likes",
"RHI",
"AHI",
]
RAW_COLS = [col for col in RAW_COLS if col in df.columns.tolist()]
df.ticker = df.ticker.str.upper()
df = df.set_index("ticker")
df.timestamp_date = pd.to_datetime(df.timestamp_date)
timestamp = df.timestamp_date[0].strftime("%Y-%m-%d %H:%M")
print_rich_table(
df[RAW_COLS].head(limit),
headers=[col.upper() for col in RAW_COLS],
show_index=True,
index_name="TICKER",
title=f"Most trending stocks at {timestamp}",
)

View File

@@ -5,9 +5,9 @@ import logging
from typing import Any, Dict, List, Tuple
import pandas as pd
import requests
from openbb_terminal.decorators import log_start_end
from openbb_terminal.helper_funcs import request
logger = logging.getLogger(__name__)
@@ -29,9 +29,7 @@ def get_bullbear(symbol: str) -> Tuple[int, int, int, int]:
Number of bullish statements,
Number of bearish statements,
"""
result = requests.get(
f"https://api.stocktwits.com/api/2/streams/symbol/{symbol}.json"
)
result = request(f"https://api.stocktwits.com/api/2/streams/symbol/{symbol}.json")
if result.status_code == 200:
result_json = result.json()
watchlist_count = result_json["symbol"]["watchlist_count"]
@@ -64,9 +62,7 @@ def get_messages(symbol: str, limit: int = 30) -> pd.DataFrame:
pd.DataFrame
Dataframe of messages
"""
result = requests.get(
f"https://api.stocktwits.com/api/2/streams/symbol/{symbol}.json"
)
result = request(f"https://api.stocktwits.com/api/2/streams/symbol/{symbol}.json")
if result.status_code == 200:
return pd.DataFrame(
[message["body"] for message in result.json()["messages"][:limit]]
@@ -84,7 +80,7 @@ def get_trending() -> pd.DataFrame:
pd.DataFrame
Dataframe of trending tickers and watchlist count
"""
result = requests.get("https://api.stocktwits.com/api/2/trending/symbols.json")
result = request("https://api.stocktwits.com/api/2/trending/symbols.json")
if result.status_code == 200:
l_symbols = [
[symbol["symbol"], symbol["watchlist_count"], symbol["title"]]
@@ -115,7 +111,7 @@ def get_stalker(user: str, limit: int = 30) -> List[Dict[str, Any]]:
List[Dict[str, Any]]
List of posts
"""
result = requests.get(f"https://api.stocktwits.com/api/2/streams/user/{user}.json")
result = request(f"https://api.stocktwits.com/api/2/streams/user/{user}.json")
if result.status_code == 200:
return list(result.json()["messages"][:limit])

View File

@@ -1,17 +1,16 @@
"""Twitter Model"""
__docformat__ = "numpy"
from datetime import datetime, timedelta
import logging
from datetime import datetime, timedelta
from typing import Optional
import pandas as pd
import requests
from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer
from openbb_terminal import config_terminal as cfg
from openbb_terminal.decorators import check_api_key, log_start_end
from openbb_terminal.helper_funcs import clean_tweet, get_data
from openbb_terminal.helper_funcs import clean_tweet, get_data, request
from openbb_terminal.rich_config import console
logger = logging.getLogger(__name__)
@@ -58,7 +57,7 @@ def load_analyze_tweets(
params["end_time"] = end_date
# Request Twitter API
response = requests.get(
response = request(
"https://api.twitter.com/2/tweets/search/recent",
params=params, # type: ignore
headers={"authorization": "Bearer " + cfg.API_TWITTER_BEARER_TOKEN},

View File

@@ -3,7 +3,7 @@ __docformat__ = "numpy"
import logging
import os
from typing import Optional, List
from typing import List, Optional
import matplotlib.pyplot as plt
import numpy as np
@@ -11,14 +11,14 @@ import pandas as pd
from dateutil import parser as dparse
import openbb_terminal.config_plot as cfg_plot
from openbb_terminal.config_terminal import theme
from openbb_terminal.common.behavioural_analysis import twitter_model
from openbb_terminal.config_terminal import theme
from openbb_terminal.decorators import log_start_end
from openbb_terminal.helper_funcs import (
export_data,
plot_autoscale,
get_closing_price,
is_valid_axes_count,
plot_autoscale,
)
from openbb_terminal.rich_config import console
@@ -26,7 +26,9 @@ logger = logging.getLogger(__name__)
@log_start_end(log=logger)
def display_inference(symbol: str, limit: int = 100, export: str = ""):
def display_inference(
symbol: str, limit: int = 100, export: str = "", sheet_name: str = None
):
"""Prints Inference sentiment from past n tweets.
Parameters
@@ -35,6 +37,8 @@ def display_inference(symbol: str, limit: int = 100, export: str = ""):
Stock ticker symbol
limit: int
Number of tweets to analyze
sheet_name: str
Optionally specify the name of the sheet the data is exported to.
export: str
Format to export tweet dataframe
"""
@@ -72,7 +76,13 @@ def display_inference(symbol: str, limit: int = 100, export: str = ""):
f"Of the last {len(df_tweets)} tweets, {100*percent_neg:.2f} % had a higher negative sentiment"
)
export_data(export, os.path.dirname(os.path.abspath(__file__)), "infer", df_tweets)
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"infer",
df_tweets,
sheet_name,
)
@log_start_end(log=logger)
@@ -82,6 +92,7 @@ def display_sentiment(
n_days_past: int = 2,
compare: bool = False,
export: str = "",
sheet_name: str = None,
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plots sentiments from symbol
@@ -96,6 +107,8 @@ def display_sentiment(
Number of days to extract tweets for
compare: bool
Show corresponding change in stock price
sheet_name: str
Optionally specify the name of the sheet the data is exported to.
export: str
Format to export tweet dataframe
external_axes: Optional[List[plt.Axes]], optional
@@ -185,5 +198,9 @@ def display_sentiment(
theme.visualize_output()
export_data(
export, os.path.dirname(os.path.abspath(__file__)), "sentiment", df_tweets
export,
os.path.dirname(os.path.abspath(__file__)),
"sentiment",
df_tweets,
sheet_name,
)

View File

@@ -3,12 +3,12 @@ __docformat__ = "numpy"
import logging
from pathlib import Path
from typing import Dict, Any, Optional
from typing import Any, Dict, Optional
import pandas as pd
import statsmodels.api as sm
from pandas import errors
from linearmodels.datasets import wage_panel
from pandas import errors
from openbb_terminal.decorators import log_start_end
from openbb_terminal.rich_config import console

View File

@@ -4,9 +4,11 @@ __docformat__ = "numpy"
import os
from typing import List
from urllib.parse import quote
import certifi
import feedparser
import pandas as pd
from openbb_terminal.rich_config import console

View File

@@ -4,10 +4,10 @@ __docformat__ = "numpy"
import logging
import os
from openbb_terminal.common import feedparser_model
from openbb_terminal.decorators import log_start_end
from openbb_terminal.helper_funcs import export_data
from openbb_terminal.rich_config import console
from openbb_terminal.common import feedparser_model
logger = logging.getLogger(__name__)
@@ -18,6 +18,7 @@ def display_news(
sources: str = "",
limit: int = 5,
export: str = "",
sheet_name: str = None,
sort: str = "published",
):
"""Plots news for a given term and source. [Source: Feedparser]
@@ -48,4 +49,5 @@ def display_news(
os.path.dirname(os.path.abspath(__file__)),
f"news_{'_'.join(term)}_{'_'.join(sources)}",
articles,
sheet_name,
)

View File

@@ -2,13 +2,14 @@
__docformat__ = "numpy"
import logging
from datetime import datetime, timedelta
from typing import Any, List, Optional, Tuple
import requests
import pandas as pd
from openbb_terminal import config_terminal as cfg
from openbb_terminal.decorators import check_api_key, log_start_end
from openbb_terminal.helper_funcs import request
from openbb_terminal.rich_config import console
logger = logging.getLogger(__name__)
@@ -58,7 +59,7 @@ def get_news(
link += f"&apiKey={cfg.API_NEWS_TOKEN}"
response = requests.get(link)
response = request(link)
articles = {}

View File

@@ -1,17 +1,15 @@
""" News View """
__docformat__ = "numpy"
import os
import logging
import os
from typing import Optional
import pandas as pd
from openbb_terminal.decorators import check_api_key
from openbb_terminal.common import newsapi_model
from openbb_terminal.decorators import log_start_end
from openbb_terminal.helper_funcs import export_data
from openbb_terminal.helper_funcs import print_rich_table
from openbb_terminal.decorators import check_api_key, log_start_end
from openbb_terminal.helper_funcs import export_data, print_rich_table
logger = logging.getLogger(__name__)
@@ -25,6 +23,7 @@ def display_news(
show_newest: bool = True,
sources: str = "",
export: str = "",
sheet_name: str = None,
) -> None:
"""Prints table showing news for a given term. [Source: NewsAPI]
@@ -53,4 +52,5 @@ def display_news(
os.path.dirname(os.path.abspath(__file__)),
f"news_{query}_{'_'.join(sources)}",
pd.DataFrame(tables),
sheet_name,
)

View File

@@ -4,13 +4,14 @@ __docformat__ = "numpy"
import logging
import warnings
from typing import Tuple, Union
import numpy as np
import pandas as pd
import statsmodels.api as sm
from scipy import stats
from statsmodels.tools.sm_exceptions import MissingDataError
from statsmodels.tsa.seasonal import DecomposeResult, seasonal_decompose
from statsmodels.tsa.stattools import adfuller, kpss
from scipy import stats
import numpy as np
from openbb_terminal.decorators import log_start_end
@@ -277,7 +278,6 @@ def get_var(
std = data_return.std(axis=0)
if adjusted_var:
# Kurtosis
# Measures height and sharpness of the central peak relative to that of a standard bell curve
k = data_return.kurtosis(axis=0)

View File

@@ -8,32 +8,32 @@ import logging
import os
import warnings
from datetime import datetime
from typing import Any, Optional, List
from typing import Any, List, Optional
import matplotlib
import matplotlib.dates as mdates
import matplotlib.patches as mpatches
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import numpy as np
import pandas as pd
import seaborn as sns
import statsmodels.api as sm
from scipy import stats
from detecta import detect_cusum
from statsmodels.graphics.gofplots import qqplot
from pandas.plotting import register_matplotlib_converters
from scipy import stats
from statsmodels.graphics.gofplots import qqplot
from openbb_terminal.config_terminal import theme
from openbb_terminal.common.quantitative_analysis import qa_model
from openbb_terminal.config_plot import PLOT_DPI
from openbb_terminal.config_terminal import theme
from openbb_terminal.decorators import log_start_end
from openbb_terminal.helper_funcs import (
export_data,
is_valid_axes_count,
lambda_long_number_format,
plot_autoscale,
print_rich_table,
reindex_dates,
lambda_long_number_format,
is_valid_axes_count,
)
from openbb_terminal.rich_config import console
@@ -50,7 +50,9 @@ def lambda_color_red(val: Any) -> str:
@log_start_end(log=logger)
def display_summary(data: pd.DataFrame, export: str = "") -> None:
def display_summary(
data: pd.DataFrame, export: str = "", sheet_name: str = None
) -> None:
"""Prints table showing summary statistics
Parameters
@@ -75,6 +77,7 @@ def display_summary(data: pd.DataFrame, export: str = "") -> None:
os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
"summary",
summary,
sheet_name,
)
@@ -161,6 +164,7 @@ def display_cdf(
target: str,
symbol: str = "",
export: str = "",
sheet_name: str = None,
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plots Cumulative Distribution Function
@@ -263,6 +267,7 @@ def display_cdf(
os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
"cdf",
pd.DataFrame(cdf),
sheet_name,
)
@@ -660,6 +665,7 @@ def display_seasonal(
target: str,
multiplicative: bool = False,
export: str = "",
sheet_name: str = None,
external_axes: Optional[List[plt.Axes]] = None,
) -> None:
"""Plots seasonal decomposition data
@@ -798,11 +804,14 @@ def display_seasonal(
os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
"summary",
cycle.join(trend),
sheet_name,
)
@log_start_end(log=logger)
def display_normality(data: pd.DataFrame, target: str, export: str = "") -> None:
def display_normality(
data: pd.DataFrame, target: str, export: str = "", sheet_name: str = None
) -> None:
"""Prints table showing normality statistics
Parameters
@@ -832,6 +841,7 @@ def display_normality(data: pd.DataFrame, target: str, export: str = "") -> None
os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
"normality",
normal,
sheet_name,
)
@@ -842,6 +852,7 @@ def display_unitroot(
fuller_reg: str = "c",
kpss_reg: str = "c",
export: str = "",
sheet_name: str = None,
):
"""Prints table showing unit root test calculations
@@ -873,6 +884,7 @@ def display_unitroot(
os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
"unitroot",
data,
sheet_name,
)
@@ -883,6 +895,7 @@ def display_raw(
ascend: bool = False,
limit: int = 20,
export: str = "",
sheet_name: str = None,
) -> None:
"""Prints table showing raw stock data
@@ -931,6 +944,7 @@ def display_raw(
os.path.dirname(os.path.abspath(__file__)),
"raw",
data,
sheet_name,
)
@@ -942,6 +956,7 @@ def display_line(
markers_lines: Optional[List[datetime]] = None,
markers_scatter: Optional[List[datetime]] = None,
export: str = "",
sheet_name: str = None,
external_axes: Optional[List[plt.Axes]] = None,
) -> None:
"""Display line plot of data
@@ -958,6 +973,8 @@ def display_line(
List of dates to highlight using vertical lines
markers_scatter: Optional[List[datetime]]
List of dates to highlight using scatter
sheet_name: str
Optionally specify the name of the sheet the data is exported to.
export: str
Format to export data
external_axes : Optional[List[plt.Axes]], optional
@@ -1042,6 +1059,7 @@ def display_line(
export,
os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
"line",
sheet_name,
)

View File

@@ -3,20 +3,20 @@ __docformat__ = "numpy"
import logging
import os
from typing import Optional, List
from typing import List, Optional
import matplotlib.pyplot as plt
import pandas as pd
from openbb_terminal.config_terminal import theme
from openbb_terminal.common.quantitative_analysis import rolling_model
from openbb_terminal.config_plot import PLOT_DPI
from openbb_terminal.config_terminal import theme
from openbb_terminal.decorators import log_start_end
from openbb_terminal.helper_funcs import (
export_data,
is_valid_axes_count,
plot_autoscale,
reindex_dates,
is_valid_axes_count,
)
logger = logging.getLogger(__name__)
@@ -29,6 +29,7 @@ def display_mean_std(
symbol: str = "",
window: int = 14,
export: str = "",
sheet_name: str = None,
external_axes: Optional[List[plt.Axes]] = None,
) -> None:
"""Plots mean std deviation
@@ -43,6 +44,8 @@ def display_mean_std(
Stock ticker
window : int
Length of window
sheet_name: str
Optionally specify the name of the sheet the data is exported to.
export: str
Format to export data
external_axes: Optional[List[plt.Axes]], optional
@@ -128,6 +131,7 @@ def display_mean_std(
os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
"rolling",
rolling_mean.join(rolling_std, lsuffix="_mean", rsuffix="_std"),
sheet_name,
)
@@ -138,6 +142,7 @@ def display_spread(
symbol: str = "",
window: int = 14,
export: str = "",
sheet_name: str = None,
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plots rolling spread
@@ -154,6 +159,8 @@ def display_spread(
Stock ticker
window : int
Length of window
sheet_name: str
Optionally specify the name of the sheet the data is exported to.
export: str
Format to export data
external_axes: Optional[List[plt.Axes]], optional
@@ -238,6 +245,7 @@ def display_spread(
os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
"spread",
df_sd.join(df_var, lsuffix="_sd", rsuffix="_var"),
sheet_name,
)
@@ -249,6 +257,7 @@ def display_quantile(
window: int = 14,
quantile: float = 0.5,
export: str = "",
sheet_name: str = None,
external_axes: Optional[List[plt.Axes]] = None,
) -> None:
"""Plots rolling quantile
@@ -265,6 +274,8 @@ def display_quantile(
Length of window
quantile: float
Quantile to get
sheet_name: str
Optionally specify the name of the sheet the data is exported to.
export: str
Format to export data
external_axes: Optional[List[plt.Axes]], optional
@@ -334,6 +345,7 @@ def display_quantile(
os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
"quantile",
df_med.join(df_quantile),
sheet_name,
)
@@ -344,6 +356,7 @@ def display_skew(
target: str,
window: int = 14,
export: str = "",
sheet_name: str = None,
external_axes: Optional[List[plt.Axes]] = None,
) -> None:
"""Plots rolling skew
@@ -358,6 +371,8 @@ def display_skew(
Column in data to look at
window: int
Length of window
sheet_name: str
Optionally specify the name of the sheet the data is exported to.
export: str
Format to export data
external_axes: Optional[List[plt.Axes]], optional
@@ -417,6 +432,7 @@ def display_skew(
os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
"skew",
df_skew,
sheet_name,
)
@@ -427,6 +443,7 @@ def display_kurtosis(
target: str,
window: int = 14,
export: str = "",
sheet_name: str = None,
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plots rolling kurtosis
@@ -441,6 +458,8 @@ def display_kurtosis(
Column in data to look at
window: int
Length of window
sheet_name: str
Optionally specify the name of the sheet the data is exported to.
export: str
Format to export data
external_axes: Optional[List[plt.Axes]], optional
@@ -503,4 +522,5 @@ def display_kurtosis(
os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
"kurtosis",
df_kurt,
sheet_name,
)

View File

@@ -6,9 +6,9 @@ from typing import Any, Tuple
import pandas as pd
from openbb_terminal.common.technical_analysis import ta_helpers
from openbb_terminal.decorators import log_start_end
from openbb_terminal.rich_config import console
from openbb_terminal.common.technical_analysis import ta_helpers
logger = logging.getLogger(__name__)

View File

@@ -3,24 +3,26 @@ __docformat__ = "numpy"
import logging
import os
from typing import Optional, Union, List
from typing import List, Optional, Union
import matplotlib.pyplot as plt
import pandas as pd
from openbb_terminal.config_terminal import theme
from openbb_terminal.common.technical_analysis import custom_indicators_model
from openbb_terminal.common.technical_analysis import (
custom_indicators_model,
ta_helpers,
)
from openbb_terminal.config_plot import PLOT_DPI
from openbb_terminal.config_terminal import theme
from openbb_terminal.decorators import log_start_end
from openbb_terminal.helper_funcs import (
export_data,
is_intraday,
is_valid_axes_count,
plot_autoscale,
print_rich_table,
reindex_dates,
is_intraday,
is_valid_axes_count,
)
from openbb_terminal.common.technical_analysis import ta_helpers
logger = logging.getLogger(__name__)
@@ -33,6 +35,7 @@ def fibonacci_retracement(
end_date: Optional[Union[str, None]] = None,
symbol: str = "",
export: str = "",
sheet_name: str = None,
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plots Calculated fibonacci retracement levels
@@ -49,6 +52,8 @@ def fibonacci_retracement(
User picked date for ending retracement
symbol: str
Ticker symbol
sheet_name: str
Optionally specify the name of the sheet the data is exported to.
export: str
Format to export data
external_axes : Optional[List[plt.Axes]], optional
@@ -138,4 +143,5 @@ def fibonacci_retracement(
os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
"fib",
df_fib,
sheet_name,
)

View File

@@ -9,8 +9,8 @@ import pandas as pd
import pandas_ta as ta
from sklearn.linear_model import LinearRegression
from openbb_terminal.decorators import log_start_end
from openbb_terminal.common.technical_analysis import ta_helpers
from openbb_terminal.decorators import log_start_end
from openbb_terminal.rich_config import console
logger = logging.getLogger(__name__)

View File

@@ -3,27 +3,26 @@ __docformat__ = "numpy"
import logging
import os
from typing import Optional, List
from typing import List, Optional
import matplotlib.pyplot as plt
import mplfinance as mpf
import numpy as np
import pandas as pd
from pandas.plotting import register_matplotlib_converters
import mplfinance as mpf
from openbb_terminal.config_terminal import theme
from openbb_terminal.common.technical_analysis import momentum_model
from openbb_terminal.common.technical_analysis import momentum_model, ta_helpers
from openbb_terminal.config_plot import PLOT_DPI
from openbb_terminal.config_terminal import theme
from openbb_terminal.decorators import log_start_end
from openbb_terminal.helper_funcs import (
export_data,
plot_autoscale,
reindex_dates,
is_valid_axes_count,
plot_autoscale,
print_rich_table,
reindex_dates,
)
from openbb_terminal.rich_config import console
from openbb_terminal.common.technical_analysis import ta_helpers
logger = logging.getLogger(__name__)
@@ -37,6 +36,7 @@ def display_cci(
scalar: float = 0.0015,
symbol: str = "",
export: str = "",
sheet_name: str = None,
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plots CCI Indicator
@@ -119,6 +119,7 @@ def display_cci(
os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
"cci",
df_ta,
sheet_name,
)
@@ -130,6 +131,7 @@ def display_macd(
n_signal: int = 9,
symbol: str = "",
export: str = "",
sheet_name: str = None,
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plots MACD signal
@@ -212,6 +214,7 @@ def display_macd(
os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
"macd",
df_ta,
sheet_name,
)
@@ -223,6 +226,7 @@ def display_rsi(
drift: int = 1,
symbol: str = "",
export: str = "",
sheet_name: str = None,
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plots RSI Indicator
@@ -300,6 +304,7 @@ def display_rsi(
os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
"rsi",
df_ta,
sheet_name,
)
@@ -311,6 +316,7 @@ def display_stoch(
slowkperiod: int = 3,
symbol: str = "",
export: str = "",
sheet_name: str = None,
external_axes: Optional[List[plt.Axes]] = None,
) -> None:
"""Plots stochastic oscillator signal
@@ -399,6 +405,7 @@ def display_stoch(
os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
"stoch",
df_ta,
sheet_name,
)
@@ -408,6 +415,7 @@ def display_fisher(
window: int = 14,
symbol: str = "",
export: str = "",
sheet_name: str = None,
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plots Fisher Indicator
@@ -492,6 +500,7 @@ def display_fisher(
os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
"fisher",
df_ta,
sheet_name,
)
@@ -501,6 +510,7 @@ def display_cg(
window: int = 14,
symbol: str = "",
export: str = "",
sheet_name: str = None,
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plots center of gravity Indicator
@@ -563,6 +573,7 @@ def display_cg(
os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
"cg",
df_ta,
sheet_name,
)
@@ -572,6 +583,7 @@ def display_clenow_momentum(
symbol: str = "",
window: int = 90,
export: str = "",
sheet_name: str = None,
external_axes: Optional[List[plt.Axes]] = None,
):
"""Prints table and plots clenow momentum
@@ -638,6 +650,7 @@ def display_clenow_momentum(
export,
os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
"clenow",
sheet_name,
)
@@ -646,6 +659,7 @@ def display_demark(
symbol: str = "",
min_to_show: int = 5,
export: str = "",
sheet_name: Optional[str] = "",
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plot demark sequential indicator
@@ -753,4 +767,5 @@ def display_demark(
os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
"demark",
stock_data,
sheet_name,
)

View File

@@ -41,7 +41,7 @@ def ema(data: pd.Series, length: int = 50, offset: int = 0) -> pd.DataFrame:
@log_start_end(log=logger)
def sma(data: pd.Series, length: int = 50, offset: int = 0) -> pd.DataFrame:
"""Gets simple moving average (EMA) for stock
"""Gets simple moving average (SMA) for stock
Parameters
----------
@@ -136,7 +136,7 @@ def zlma(data: pd.Series, length: int = 50, offset: int = 0) -> pd.DataFrame:
@log_start_end(log=logger)
def vwap(data: pd.Series, offset: int = 0) -> pd.DataFrame:
def vwap(data: pd.DataFrame, offset: int = 0) -> pd.DataFrame:
"""Gets volume weighted average price (VWAP)
Parameters

View File

@@ -10,21 +10,23 @@ import mplfinance as mpf
import pandas as pd
from pandas.plotting import register_matplotlib_converters
from openbb_terminal.config_terminal import theme
from openbb_terminal.common.technical_analysis import overlap_model
from openbb_terminal.config_plot import PLOT_DPI
from openbb_terminal.config_terminal import theme
from openbb_terminal.decorators import log_start_end
from openbb_terminal.helper_funcs import (
export_data,
is_valid_axes_count,
lambda_long_number_format_y_axis,
plot_autoscale,
reindex_dates,
lambda_long_number_format_y_axis,
is_valid_axes_count,
)
from openbb_terminal.rich_config import console
logger = logging.getLogger(__name__)
# pylint: disable=too-many-arguments
register_matplotlib_converters()
@@ -36,6 +38,7 @@ def view_ma(
ma_type: str = "EMA",
symbol: str = "",
export: str = "",
sheet_name: str = None,
external_axes: Optional[List[plt.Axes]] = None,
) -> None:
"""Plots MA technical indicator
@@ -52,6 +55,8 @@ def view_ma(
Type of moving average. Either "EMA" "ZLMA" or "SMA"
symbol: str
Ticker
sheet_name: str
Optionally specify the name of the sheet the data is exported to.
export: str
Format to export data
external_axes: Optional[List[plt.Axes]], optional
@@ -126,6 +131,7 @@ def view_ma(
os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
f"{ma_type.lower()}{'_'.join([str(win) for win in window])}",
price_df,
sheet_name,
)
@@ -138,6 +144,7 @@ def view_vwap(
offset: int = 0,
interval: str = "",
export: str = "",
sheet_name: str = None,
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plots VWMA technical indicator
@@ -233,4 +240,5 @@ def view_vwap(
os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
"VWAP",
df_vwap,
sheet_name,
)

View File

@@ -1,5 +1,5 @@
from typing import Optional
import logging
from typing import Optional
import pandas as pd

View File

@@ -6,8 +6,8 @@ import logging
import pandas as pd
import pandas_ta as ta
from openbb_terminal.decorators import log_start_end
from openbb_terminal.common.technical_analysis import ta_helpers
from openbb_terminal.decorators import log_start_end
logger = logging.getLogger(__name__)

View File

@@ -3,23 +3,22 @@ __docformat__ = "numpy"
import logging
import os
from typing import Optional, List
from typing import List, Optional
import matplotlib.pyplot as plt
import pandas as pd
from pandas.plotting import register_matplotlib_converters
from openbb_terminal.config_terminal import theme
from openbb_terminal.common.technical_analysis import trend_indicators_model
from openbb_terminal.common.technical_analysis import ta_helpers, trend_indicators_model
from openbb_terminal.config_plot import PLOT_DPI
from openbb_terminal.config_terminal import theme
from openbb_terminal.decorators import log_start_end
from openbb_terminal.helper_funcs import (
export_data,
is_valid_axes_count,
plot_autoscale,
reindex_dates,
is_valid_axes_count,
)
from openbb_terminal.common.technical_analysis import ta_helpers
logger = logging.getLogger(__name__)
@@ -34,6 +33,7 @@ def display_adx(
drift: int = 1,
symbol: str = "",
export: str = "",
sheet_name: str = None,
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plots ADX indicator
@@ -114,6 +114,7 @@ def display_adx(
os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
"adx",
df_ta,
sheet_name,
)
@@ -124,6 +125,7 @@ def display_aroon(
scalar: int = 100,
symbol: str = "",
export: str = "",
sheet_name: str = None,
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plots Aroon indicator
@@ -138,6 +140,8 @@ def display_aroon(
Ticker
scalar: int
Scalar variable
sheet_name: str
Optionally specify the name of the sheet the data is exported to.
export: str
Format to export data
external_axes: Optional[List[plt.Axes]], optional
@@ -204,4 +208,5 @@ def display_aroon(
os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
"aroon",
df_ta,
sheet_name,
)

View File

@@ -6,8 +6,8 @@ import logging
import pandas as pd
import pandas_ta as ta
from openbb_terminal.decorators import log_start_end
from openbb_terminal.common.technical_analysis import ta_helpers
from openbb_terminal.decorators import log_start_end
logger = logging.getLogger(__name__)

View File

@@ -3,25 +3,26 @@ __docformat__ = "numpy"
import logging
import os
from typing import Optional, List
from typing import List, Optional
import matplotlib.pyplot as plt
import pandas as pd
from openbb_terminal.config_terminal import theme
from openbb_terminal.common.technical_analysis import volatility_model
from openbb_terminal.common.technical_analysis import ta_helpers, volatility_model
from openbb_terminal.config_plot import PLOT_DPI
from openbb_terminal.config_terminal import theme
from openbb_terminal.decorators import log_start_end
from openbb_terminal.helper_funcs import (
export_data,
is_valid_axes_count,
plot_autoscale,
reindex_dates,
is_valid_axes_count,
)
from openbb_terminal.common.technical_analysis import ta_helpers
logger = logging.getLogger(__name__)
# pylint: disable=too-many-arguments
@log_start_end(log=logger)
def display_bbands(
@@ -31,6 +32,7 @@ def display_bbands(
n_std: float = 2,
mamode: str = "sma",
export: str = "",
sheet_name: str = None,
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plots bollinger bands
@@ -105,6 +107,7 @@ def display_bbands(
os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
"bbands",
df_ta,
sheet_name,
)
@@ -115,6 +118,7 @@ def display_donchian(
upper_length: int = 20,
lower_length: int = 20,
export: str = "",
sheet_name: str = None,
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plots donchian channels
@@ -187,6 +191,7 @@ def display_donchian(
os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
"donchian",
df_ta,
sheet_name,
)
@@ -199,6 +204,7 @@ def view_kc(
offset: int = 0,
symbol: str = "",
export: str = "",
sheet_name: str = None,
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plots Keltner Channels Indicator
@@ -218,6 +224,8 @@ def view_kc(
Offset value
symbol: str
Ticker symbol
sheet_name: str
Optionally specify the name of the sheet the data is exported to.
export: str
Format to export data
external_axes: Optional[List[plt.Axes]], optional
@@ -282,6 +290,7 @@ def view_kc(
os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
"kc",
df_ta,
sheet_name,
)
@@ -293,6 +302,7 @@ def display_atr(
mamode: str = "sma",
offset: int = 0,
export: str = "",
sheet_name: str = None,
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plots ATR
@@ -354,4 +364,5 @@ def display_atr(
os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
"atr",
df_ta,
sheet_name,
)

View File

@@ -6,8 +6,8 @@ import logging
import pandas as pd
import pandas_ta as ta
from openbb_terminal.decorators import log_start_end
from openbb_terminal.common.technical_analysis import ta_helpers
from openbb_terminal.decorators import log_start_end
from openbb_terminal.rich_config import console
logger = logging.getLogger(__name__)

View File

@@ -3,23 +3,22 @@ __docformat__ = "numpy"
import logging
import os
from typing import Optional, List
from typing import List, Optional
import matplotlib.pyplot as plt
import pandas as pd
from openbb_terminal.config_terminal import theme
from openbb_terminal.common.technical_analysis import volume_model
from openbb_terminal.common.technical_analysis import ta_helpers, volume_model
from openbb_terminal.config_plot import PLOT_DPI
from openbb_terminal.config_terminal import theme
from openbb_terminal.decorators import log_start_end
from openbb_terminal.helper_funcs import (
export_data,
is_valid_axes_count,
plot_autoscale,
reindex_dates,
is_valid_axes_count,
)
from openbb_terminal.rich_config import console
from openbb_terminal.common.technical_analysis import ta_helpers
logger = logging.getLogger(__name__)
@@ -30,6 +29,7 @@ def display_ad(
use_open: bool = False,
symbol: str = "",
export: str = "",
sheet_name: str = None,
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plots AD technical indicator
@@ -42,6 +42,8 @@ def display_ad(
Whether to use open prices in calculation
symbol : str
Ticker symbol
sheet_name: str
Optionally specify the name of the sheet the data is exported to.
export: str
Format to export data as
external_axes : Optional[List[plt.Axes]], optional
@@ -134,6 +136,7 @@ def display_ad(
os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
"ad",
df_ta,
sheet_name,
)
@@ -145,6 +148,7 @@ def display_adosc(
use_open: bool = False,
symbol: str = "",
export: str = "",
sheet_name: str = None,
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plots AD Osc Indicator
@@ -242,6 +246,7 @@ def display_adosc(
os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
"adosc",
df_ta,
sheet_name,
)
@@ -250,6 +255,7 @@ def display_obv(
data: pd.DataFrame,
symbol: str = "",
export: str = "",
sheet_name: str = None,
external_axes: Optional[List[plt.Axes]] = None,
):
"""Plots OBV technical indicator
@@ -260,6 +266,8 @@ def display_obv(
Dataframe of ohlc prices
symbol : str
Ticker
sheet_name: str
Optionally specify the name of the sheet the data is exported to.
export: str
Format to export data as
external_axes : Optional[List[plt.Axes]], optional
@@ -345,4 +353,5 @@ def display_obv(
os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
"obv",
df_ta,
sheet_name,
)

View File

@@ -19,6 +19,10 @@ dotenv.load_dotenv(USER_ENV_FILE)
dotenv.load_dotenv(REPOSITORY_ENV_FILE, override=True)
dotenv.load_dotenv(PACKAGE_ENV_FILE, override=True)
# Network requests
# Set request timeout
REQUEST_TIMEOUT = load_env_vars("OPENBB_REQUEST_TIMEOUT", int, 5)
# Terminal UX section
MPL_STYLE = os.getenv("OPENBB_MPLSTYLE") or "dark"
PMF_STYLE = os.getenv("OPENBB_PMFSTYLE") or "dark"

View File

@@ -5,6 +5,7 @@ from os import environ
from types import MethodType
from typing import Callable, List
from unittest.mock import patch
from openbb_terminal.helper_funcs import check_file_type_saved, check_positive
from openbb_terminal.rich_config import get_ordered_list_sources

View File

@@ -1,14 +1,27 @@
# IMPORTATION STANDARD
from pathlib import Path
import os
import dotenv
from pathlib import Path
from dotenv import load_dotenv
def load_dotenv_with_priority():
"""Loads the dotenv files in the following order:
1. Repository .env file
2. Package .env file
3. User .env file
This allows the user to override the package settings with their own
settings, and the package to override the repository settings.
"""
load_dotenv(REPOSITORY_ENV_FILE, override=True)
load_dotenv(PACKAGE_ENV_FILE, override=True)
load_dotenv(USER_ENV_FILE, override=True)
def get_user_data_directory():
""" "
Gets user data path from .env file
"""
dotenv.load_dotenv(USER_ENV_FILE)
"""Gets user data path from .env file or returns default path"""
load_dotenv_with_priority()
if os.getenv("OPENBB_USER_DATA_DIRECTORY"):
user_data_directory = Path(os.getenv("OPENBB_USER_DATA_DIRECTORY"))
else:

View File

@@ -2,16 +2,16 @@
from typing import List
from openbb_terminal.core.config.paths import (
SETTINGS_DIRECTORY,
USER_DATA_DIRECTORY,
USER_ENV_FILE,
REPOSITORY_ENV_FILE,
SETTINGS_DIRECTORY,
USER_CUSTOM_IMPORTS_DIRECTORY,
USER_DATA_DIRECTORY,
USER_DATA_SOURCES_DEFAULT_FILE,
USER_ENV_FILE,
USER_EXPORTS_DIRECTORY,
USER_PORTFOLIO_DATA_DIRECTORY,
USER_PRESETS_DIRECTORY,
USER_ROUTINES_DIRECTORY,
USER_DATA_SOURCES_DEFAULT_FILE,
)
# pylint: disable=W0603

View File

@@ -2,35 +2,32 @@
"""Main Testing Module"""
__docformat__ = "numpy"
from functools import partial
from multiprocessing.pool import Pool
from multiprocessing import cpu_count
from pathlib import Path
import re
import time
from typing import Any, List, Dict, Optional, Tuple
from traceback import FrameSummary, format_list, extract_tb
import argparse
import logging
import sys
import os
from openbb_terminal.helper_funcs import check_positive
import re
import sys
import time
from functools import partial
from multiprocessing import cpu_count
from multiprocessing.pool import Pool
from pathlib import Path
from traceback import FrameSummary, extract_tb, format_list
from typing import Any, Dict, List, Optional, Tuple
from openbb_terminal.rich_config import console
from openbb_terminal.core.config.paths import (
MISCELLANEOUS_DIRECTORY,
REPOSITORY_DIRECTORY,
)
from openbb_terminal.helper_funcs import check_non_negative
from openbb_terminal.rich_config import console
from openbb_terminal.terminal_controller import (
insert_start_slash,
terminal,
replace_dynamic,
obbff,
replace_dynamic,
terminal,
)
from openbb_terminal.terminal_helper import (
is_reset,
suppress_stdout,
)
from openbb_terminal.terminal_helper import is_reset, suppress_stdout
logger = logging.getLogger(__name__)
special_arguments_values = [
@@ -128,7 +125,6 @@ def convert_list_to_test_files(path_list: List[str]) -> List[Path]:
test_files = []
for path in path_list:
if path.startswith(
str(Path("openbb_terminal", "core", "integration_tests", "scripts"))
):
@@ -374,18 +370,16 @@ def run_test_files(
-------
Tuple[int, int, Dict[str, Dict[str, Any]], float]
"""
os.environ["DEBUG_MODE"] = "true"
n_successes = 0
n_failures = 0
fails: Dict[str, Dict[str, Any]] = {}
if test_files:
n = len(test_files)
start = time.time()
if verbose and not subprocesses:
if subprocesses == 0:
console.print(
f"* Running {n} script(s) sequentially...\n",
style="bold",
@@ -410,7 +404,6 @@ def run_test_files(
style="bold",
)
with Pool(processes=subprocesses) as pool:
# Choosing chunksize: line 477 .../lib/python3.9/multiprocessing/pool.py
chunksize, extra = divmod(n, subprocesses * 4)
if extra:
@@ -427,7 +420,6 @@ def run_test_files(
chunksize=chunksize,
)
):
file_short_name, exception = result
if exception:
n_failures += 1
@@ -504,7 +496,6 @@ def display_summary(
console.print("\n" + to_section_title("integration test summary"))
for file, exception in fails.items():
# Assuming the broken command is the last one called in the traceback
broken_cmd = "unknown"
frame: FrameSummary
@@ -642,7 +633,7 @@ def parse_args_and_run():
help="The number of subprocesses to use to run the tests."
" Default is the minimum between number of collected scripts and CPUs.",
dest="subprocesses",
type=check_positive,
type=check_non_negative,
default=None,
)
parser.add_argument(
@@ -670,12 +661,13 @@ def parse_args_and_run():
special_args_dict = {x: getattr(ns_parser, x) for x in special_arguments_values}
if ns_parser.verbose and ns_parser.subprocesses:
console.print(
"WARNING: verbose mode and multiprocessing are not compatible. "
"The output of the scripts is mixed up. Consider running without --subproc.\n",
style="yellow",
)
if ns_parser.verbose:
if ns_parser.subprocesses is None or ns_parser.subprocesses > 0:
console.print(
"WARNING: verbose mode and multiprocessing are not compatible. "
"The output of the scripts is mixed up. Consider running with --subproc 0.\n",
style="yellow",
)
if ns_parser.list_:
return display_available_scripts(ns_parser.path, ns_parser.skip)
@@ -697,6 +689,12 @@ def main():
if "--test" in sys.argv:
sys.argv.remove("--test")
os.environ["OPENBB_ENABLE_QUICK_EXIT"] = "False"
os.environ["OPENBB_LOG_COLLECT"] = "False"
os.environ["OPENBB_USE_ION"] = "True"
os.environ["OPENBB_USE_PROMPT_TOOLKIT"] = "False"
os.environ["DEBUG_MODE"] = "True"
parse_args_and_run()

View File

@@ -1,11 +1,10 @@
from typing import Any, Optional, List
from typing import Any, List, Optional
import openbb_terminal.config_terminal as cfg
from openbb_terminal.core.library.metadata import Metadata
from openbb_terminal.core.library.trail_map import TrailMap
from openbb_terminal.core.library.operation import Operation
from openbb_terminal import feature_flags as obbff
from openbb_terminal.core.library.metadata import Metadata
from openbb_terminal.core.library.operation import Operation
from openbb_terminal.core.library.trail_map import TrailMap
# pylint: disable=import-outside-toplevel
@@ -159,10 +158,10 @@ class BreadcrumbLogger:
@staticmethod
def __initialize_logging() -> None:
from openbb_terminal.loggers import setup_logging # pylint: disable=C0415
from openbb_terminal.core.log.generation.settings_logger import ( # pylint: disable=C0415
log_all_settings,
)
from openbb_terminal.loggers import setup_logging # pylint: disable=C0415
cfg.LOGGING_SUB_APP = "sdk"
setup_logging()

View File

@@ -1,12 +1,10 @@
import json
from importlib import import_module
from logging import getLogger, Logger
from inspect import signature
from logging import Logger, getLogger
from typing import Any, Callable, Dict, List, Optional
from inspect import signature
import openbb_terminal.config_terminal as cfg
from openbb_terminal.core.library.metadata import Metadata
from openbb_terminal.core.library.trail_map import TrailMap
@@ -115,7 +113,6 @@ class Operation:
class OperationLogger:
last_method: Dict[Any, Any] = {}
def __init__(
@@ -231,7 +228,6 @@ class OperationLogger:
"""
if func_module == "openbb_terminal.keys_model":
from openbb_terminal.core.log.generation.settings_logger import ( # pylint: disable=C0415
log_keys,
)

View File

@@ -8,7 +8,6 @@ from openbb_terminal.base_helpers import load_env_vars, strtobool
from openbb_terminal.core.config.paths import MISCELLANEOUS_DIRECTORY, USER_ENV_FILE
from openbb_terminal.rich_config import console
DISABLE_FORECASTING_WARNING = load_env_vars(
"OPENBB_DISABLE_FORECASTING_WARNING", strtobool, False
)

View File

@@ -1,21 +1,21 @@
# IMPORTATION STANDARD
from copy import deepcopy
from threading import Thread
from queue import SimpleQueue
from pathlib import Path
from queue import SimpleQueue
from threading import Thread
# IMPORTATION THIRDPARTY
# IMPORTATION INTERNAL
from openbb_terminal.feature_flags import LOG_COLLECTION
from openbb_terminal.core.log.collection.s3_sender import send_to_s3
from openbb_terminal.core.log.constants import (
ARCHIVES_FOLDER_NAME,
S3_FOLDER_SUFFIX,
TMP_FOLDER_NAME,
)
from openbb_terminal.core.log.collection.s3_sender import send_to_s3
from openbb_terminal.core.log.generation.settings import Settings
# IMPORTATION THIRDPARTY
# IMPORTATION INTERNAL
from openbb_terminal.feature_flags import LOG_COLLECTION
# DO NOT USE THE FILE LOGGER IN THIS MODULE

View File

@@ -2,6 +2,7 @@
import os
import uuid
from pathlib import Path
from openbb_terminal.core.config.paths import USER_DATA_DIRECTORY
# IMPORTATION THIRDPARTY

View File

@@ -3,7 +3,6 @@ from datetime import datetime
from pathlib import Path
from typing import List
# IMPORTATION THIRDPARTY
# IMPORTATION INTERNAL

View File

@@ -3,7 +3,6 @@ import logging
import re
# IMPORTATION THIRDPARTY
# IMPORTATION INTERNAL
from openbb_terminal.core.config.paths import HOME_DIRECTORY
from openbb_terminal.core.log.generation.settings import AppSettings

View File

@@ -4,19 +4,18 @@ from logging.handlers import TimedRotatingFileHandler
from pathlib import Path
from typing import Callable
# IMPORTATION THIRDPARTY
# IMPORTATION INTERNAL
from openbb_terminal.core.log.constants import ARCHIVES_FOLDER_NAME, TMP_FOLDER_NAME
from openbb_terminal.core.log.collection.log_sender import LogSender
from openbb_terminal.core.log.collection.logging_clock import LoggingClock, Precision
# IMPORTATION THIRDPARTY
# IMPORTATION INTERNAL
from openbb_terminal.core.log.constants import ARCHIVES_FOLDER_NAME, TMP_FOLDER_NAME
from openbb_terminal.core.log.generation.directories import get_log_dir, get_log_sub_dir
from openbb_terminal.core.log.generation.expired_files import (
get_expired_file_list,
get_timestamp_from_x_days,
remove_file_list,
)
from openbb_terminal.core.log.generation.settings import Settings

View File

@@ -1,20 +1,17 @@
# IMPORTATION STANDARD
import platform
import json
import logging
import platform
from types import FunctionType, ModuleType
# IMPORTATION THIRDPARTY
# IMPORTATION INTERNAL
import openbb_terminal.feature_flags as obbff
from openbb_terminal import config_terminal as cfg
from openbb_terminal.terminal_helper import is_packaged_application
from openbb_terminal.core.log.generation.path_tracking_file_handler import (
PathTrackingFileHandler,
)
from openbb_terminal.terminal_helper import is_packaged_application
SENSITIVE_WORDS = [
"API",
@@ -108,7 +105,6 @@ def log_keys() -> None:
current_keys = {}
for cfg_var_name in var_list:
cfg_var_value = getattr(cfg, cfg_var_name)
if cfg_var_value != "REPLACE_ME":

View File

@@ -1,9 +1,10 @@
from inspect import getmembers, isfunction
from typing import List, Callable, Tuple
from datetime import datetime
import importlib.util
from pathlib import Path
import os
from datetime import datetime
from inspect import getmembers, isfunction
from pathlib import Path
from typing import Callable, List, Tuple
import pandas as pd
try:

View File

@@ -2,17 +2,18 @@
__docformat__ = "numpy"
import argparse
import binascii
import logging
from typing import Optional, Any, Union
import hmac
import hashlib
import time
import base64
import requests
import binascii
import hashlib
import hmac
import logging
import time
from typing import Any, Optional, Union
from requests.auth import AuthBase
import openbb_terminal.config_terminal as cfg
from openbb_terminal.helper_funcs import request
from openbb_terminal.rich_config import console
logger = logging.getLogger(__name__)
@@ -26,9 +27,14 @@ class CoinbaseProAuth(AuthBase):
self.secret_key = secret_key
self.passphrase = passphrase
def __call__(self, request):
def __call__(self, request_coinbase):
timestamp = str(time.time())
message = timestamp + request.method + request.path_url + (request.body or "")
message = (
timestamp
+ request_coinbase.method
+ request_coinbase.path_url
+ (request_coinbase.body or "")
)
message = message.encode("ascii")
try:
@@ -39,7 +45,7 @@ class CoinbaseProAuth(AuthBase):
logger.exception(str(e))
signature_b64 = ""
request.headers.update(
request_coinbase.headers.update(
{
"CB-ACCESS-SIGN": signature_b64,
"CB-ACCESS-TIMESTAMP": timestamp,
@@ -48,7 +54,7 @@ class CoinbaseProAuth(AuthBase):
"Content-Type": "application/json",
}
)
return request
return request_coinbase
class CoinbaseRequestException(Exception):
@@ -119,7 +125,7 @@ def make_coinbase_request(
"""
url = "https://api.pro.coinbase.com"
response = requests.get(url + endpoint, params=params, auth=auth)
response = request(url + endpoint, params=params, auth=auth)
if not 200 <= response.status_code < 300:
raise CoinbaseApiException(f"Invalid Authentication: {response.text}")

View File

@@ -2,6 +2,7 @@
__docformat__ = "numpy"
from typing import Any, Optional
import requests
from requests.adapters import HTTPAdapter

View File

@@ -6,21 +6,21 @@ import argparse
import logging
import os
from typing import List
from openbb_terminal.custom_prompt_toolkit import NestedCompleter
from openbb_terminal.cryptocurrency import cryptocurrency_helpers, pyth_model, pyth_view
from openbb_terminal import feature_flags as obbff
from openbb_terminal.cryptocurrency import cryptocurrency_helpers, pyth_model, pyth_view
from openbb_terminal.cryptocurrency.crypto_views import find
from openbb_terminal.cryptocurrency.cryptocurrency_helpers import (
display_all_coins,
plot_chart,
)
from openbb_terminal.cryptocurrency.crypto_views import find
from openbb_terminal.cryptocurrency.due_diligence import (
binance_view,
coinpaprika_view,
finbrain_crypto_view,
pycoingecko_view,
)
from openbb_terminal.custom_prompt_toolkit import NestedCompleter
from openbb_terminal.decorators import log_start_end
from openbb_terminal.helper_funcs import (
EXPORT_BOTH_RAW_DATA_AND_FIGURES,
@@ -30,7 +30,7 @@ from openbb_terminal.helper_funcs import (
)
from openbb_terminal.menu import session
from openbb_terminal.parent_classes import CryptoBaseController
from openbb_terminal.rich_config import console, MenuText
from openbb_terminal.rich_config import MenuText, console
# pylint: disable=import-outside-toplevel
@@ -295,6 +295,7 @@ class CryptoController(CryptoBaseController):
os.path.join(os.path.dirname(os.path.abspath(__file__))),
f"{self.symbol}",
self.current_df,
" ".join(ns_parser.sheet_name) if ns_parser.sheet_name else None,
)
plot_chart(
@@ -520,6 +521,9 @@ class CryptoController(CryptoBaseController):
skip=ns_parser.skip,
show_all=True,
export=ns_parser.export,
sheet_name=" ".join(ns_parser.sheet_name)
if ns_parser.sheet_name
else None,
)
else:
find(
@@ -528,6 +532,9 @@ class CryptoController(CryptoBaseController):
key=ns_parser.key,
limit=ns_parser.limit,
export=ns_parser.export,
sheet_name=" ".join(ns_parser.sheet_name)
if ns_parser.sheet_name
else None,
)
@log_start_end(log=logger)

View File

@@ -1,4 +1,5 @@
import difflib
import pandas as pd
from openbb_terminal.rich_config import console
@@ -64,7 +65,6 @@ def find(
def _find_CoinGecko(key: str, query: str, limit: int) -> pd.DataFrame:
# pylint: disable=C0415
from openbb_terminal.cryptocurrency.discovery.pycoingecko_model import (
get_coin_list,
@@ -85,7 +85,6 @@ def _find_CoinGecko(key: str, query: str, limit: int) -> pd.DataFrame:
def _find_CoinPaprika(key: str, query: str, limit: int) -> pd.DataFrame:
# pylint: disable=C0415
from openbb_terminal.cryptocurrency.due_diligence.coinpaprika_model import (
get_coin_list,
@@ -107,14 +106,13 @@ def _find_CoinPaprika(key: str, query: str, limit: int) -> pd.DataFrame:
def _find_Binance(key: str, query: str, limit: int) -> pd.DataFrame:
# pylint: disable=C0415
from openbb_terminal.cryptocurrency.discovery.pycoingecko_model import (
get_coin_list,
)
from openbb_terminal.cryptocurrency.cryptocurrency_helpers import (
load_binance_map,
)
from openbb_terminal.cryptocurrency.discovery.pycoingecko_model import (
get_coin_list,
)
# TODO: Fix it in future. Determine if user looks for symbol like ETH or ethereum
if len(query) > 5:
@@ -134,14 +132,13 @@ def _find_Binance(key: str, query: str, limit: int) -> pd.DataFrame:
def _find_Coinbase(key: str, query: str, limit: int) -> pd.DataFrame:
# pylint: disable=C0415
from openbb_terminal.cryptocurrency.discovery.pycoingecko_model import (
get_coin_list,
)
from openbb_terminal.cryptocurrency.cryptocurrency_helpers import (
load_coinbase_map,
)
from openbb_terminal.cryptocurrency.discovery.pycoingecko_model import (
get_coin_list,
)
if len(query) > 5:
key = "id"

View File

@@ -1,7 +1,7 @@
import os
from openbb_terminal.helper_funcs import print_rich_table, export_data
from openbb_terminal.cryptocurrency import crypto_models
from openbb_terminal.helper_funcs import export_data, print_rich_table
def find(
@@ -10,6 +10,7 @@ def find(
key: str = "symbol",
limit: int = 10,
export: str = "",
sheet_name: str = None,
) -> None:
"""Find similar coin by coin name,symbol or id.
@@ -48,4 +49,5 @@ def find(
os.path.dirname(os.path.abspath(__file__)),
"find",
df,
sheet_name,
)

View File

@@ -4,9 +4,9 @@
import difflib
import json
import logging
from typing import Union, Optional, List
import os
from datetime import datetime, timedelta
from typing import List, Optional, Union
import ccxt
import matplotlib.pyplot as plt
@@ -625,6 +625,7 @@ def load_yf_data(symbol: str, currency: str, interval: str, days: int):
start=datetime.now() - timedelta(days=days),
progress=False,
interval=interval,
ignore_tz=True,
).sort_index(ascending=False)
df_coin.index.names = ["date"]
@@ -638,7 +639,13 @@ def load_yf_data(symbol: str, currency: str, interval: str, days: int):
def display_all_coins(
source: str, symbol: str, limit: int, skip: int, show_all: bool, export: str
source: str,
symbol: str,
limit: int,
skip: int,
show_all: bool,
export: str,
sheet_name: str,
) -> None:
"""Find similar coin by coin name,symbol or id.
If you don't remember exact name or id of the Coin at CoinGecko, CoinPaprika, Coinbase, Binance
@@ -689,7 +696,6 @@ def display_all_coins(
df.drop("index", axis=1, inplace=True)
else:
if source == "CoinGecko":
coins_df = pycoingecko_model.get_coin_list().drop("index", axis=1)
df = _create_closest_match_df(symbol.lower(), coins_df, limit, cutoff)
@@ -744,6 +750,7 @@ def display_all_coins(
os.path.dirname(os.path.abspath(__file__)),
"coins",
df,
sheet_name,
)

View File

@@ -26,10 +26,10 @@ for category in categories:
- Endpoint: [https://api.llama.fi/protocols](https://api.llama.fi/protocols)
```python
import requests
import request
API_URL = "https://api.llama.fi"
url = f"{API_URL}/protocols"
r = requests.get(url)
r = request(url)
data = r.json()
protocols = {}
for protocol in data:

View File

@@ -3,9 +3,11 @@ __docformat__ = "numpy"
import math
import re
from typing import Union, Any, Optional
import textwrap
from typing import Any, Optional, Union
import pandas as pd
from openbb_terminal.helper_funcs import lambda_long_number_format
@@ -125,7 +127,6 @@ def lambda_very_long_number_formatter(num: Union[str, int, float]) -> str:
def prettify_paragraph(text):
# Add tab to the beginning of paragraph
text = "\t" + text
pat = "(?<!\n)\n(?!\n)"

Some files were not shown because too many files have changed in this diff Show More