mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-10-27 12:40:35 +00:00
Merge branch 'develop' into hotfix/bug-#3960
This commit is contained in:
18
.github/release-drafter.yml
vendored
18
.github/release-drafter.yml
vendored
@@ -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
62
.github/workflows/build-release.yml
vendored
Normal 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 }}
|
||||
1
.github/workflows/docker.yml
vendored
1
.github/workflows/docker.yml
vendored
@@ -40,3 +40,4 @@ jobs:
|
||||
- name: Publishing the Docker image
|
||||
run: |
|
||||
docker push "${OPENBBTERMINAL_DOCKER_POETRY_IMAGE}"
|
||||
if: startsWith(github.ref, 'refs/heads/main')
|
||||
|
||||
8
.github/workflows/gh-pages.yml
vendored
8
.github/workflows/gh-pages.yml
vendored
@@ -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
52
.github/workflows/integration-test.yml
vendored
Normal 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
|
||||
12
.github/workflows/intel_macos_build.yml
vendored
12
.github/workflows/intel_macos_build.yml
vendored
@@ -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
|
||||
|
||||
2
.github/workflows/labels.yml
vendored
2
.github/workflows/labels.yml
vendored
@@ -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
|
||||
|
||||
8
.github/workflows/linting.yml
vendored
8
.github/workflows/linting.yml
vendored
@@ -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
|
||||
|
||||
|
||||
17
.github/workflows/m1_macos_build.yml
vendored
17
.github/workflows/m1_macos_build.yml
vendored
@@ -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
|
||||
|
||||
1
.github/workflows/mac.yml
vendored
1
.github/workflows/mac.yml
vendored
@@ -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:
|
||||
|
||||
117
.github/workflows/nightly-build.yml
vendored
117
.github/workflows/nightly-build.yml
vendored
@@ -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
79
.github/workflows/pypi.yml
vendored
Normal 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 }}
|
||||
1
.github/workflows/test.yml
vendored
1
.github/workflows/test.yml
vendored
@@ -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]
|
||||
|
||||
16
.github/workflows/unit-test.yml
vendored
16
.github/workflows/unit-test.yml
vendored
@@ -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:
|
||||
|
||||
1
.github/workflows/windows.yml
vendored
1
.github/workflows/windows.yml
vendored
@@ -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:
|
||||
|
||||
104
.github/workflows/windows10_build.yml
vendored
104
.github/workflows/windows10_build.yml
vendored
@@ -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
|
||||
|
||||
8
.pre-commit-config.yaml
vendored
8
.pre-commit-config.yaml
vendored
@@ -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
4
CONTRIBUTING.md
vendored
@@ -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}"
|
||||
)
|
||||
|
||||
|
||||
2
build/docker/compose.env
vendored
2
build/docker/compose.env
vendored
@@ -1,2 +1,2 @@
|
||||
OPENBBTERMINAL_DOCKER_REGISTRY="ghcr.io"
|
||||
OPENBBTERMINAL_DOCKER_RELEASE_VERSION="2.1.0"
|
||||
OPENBBTERMINAL_DOCKER_RELEASE_VERSION="2.3.1"
|
||||
|
||||
2
build/docker/docker-compose.yaml
vendored
2
build/docker/docker-compose.yaml
vendored
@@ -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
|
||||
|
||||
2
build/nsis/setup.nsi
vendored
2
build/nsis/setup.nsi
vendored
@@ -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}"
|
||||
|
||||
;--------------------------------
|
||||
|
||||
2
build/pyinstaller/.env
vendored
2
build/pyinstaller/.env
vendored
@@ -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
|
||||
|
||||
3
build/pyinstaller/hooks/hook-xgboost.py
Normal file
3
build/pyinstaller/hooks/hook-xgboost.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from PyInstaller.utils.hooks import collect_all
|
||||
|
||||
datas, binaries, hiddenimports = collect_all("xgboost")
|
||||
41
build/pyinstaller/terminal.spec
vendored
41
build/pyinstaller/terminal.spec
vendored
@@ -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",
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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}",
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
266
openbb_terminal/alternative/realestate/landRegistry_model.py
Normal file
266
openbb_terminal/alternative/realestate/landRegistry_model.py
Normal 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
|
||||
149
openbb_terminal/alternative/realestate/landRegistry_view.py
Normal file
149
openbb_terminal/alternative/realestate/landRegistry_view.py
Normal 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,
|
||||
)
|
||||
266
openbb_terminal/alternative/realestate/realestate_controller.py
Normal file
266
openbb_terminal/alternative/realestate/realestate_controller.py
Normal 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"
|
||||
)
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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}"
|
||||
)
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
"""Reddit Helpers"""
|
||||
__docformat__ = "numpy"
|
||||
|
||||
from typing import List
|
||||
import re
|
||||
from typing import List
|
||||
|
||||
import praw
|
||||
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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
|
||||
@@ -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}",
|
||||
)
|
||||
@@ -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])
|
||||
|
||||
|
||||
@@ -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},
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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 = {}
|
||||
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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__)
|
||||
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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__)
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from typing import Optional
|
||||
import logging
|
||||
from typing import Optional
|
||||
|
||||
import pandas as pd
|
||||
|
||||
|
||||
@@ -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__)
|
||||
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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__)
|
||||
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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__)
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import os
|
||||
import uuid
|
||||
from pathlib import Path
|
||||
|
||||
from openbb_terminal.core.config.paths import USER_DATA_DIRECTORY
|
||||
|
||||
# IMPORTATION THIRDPARTY
|
||||
|
||||
@@ -3,7 +3,6 @@ from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
|
||||
# IMPORTATION THIRDPARTY
|
||||
|
||||
# IMPORTATION INTERNAL
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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":
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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}")
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
__docformat__ = "numpy"
|
||||
|
||||
from typing import Any, Optional
|
||||
|
||||
import requests
|
||||
from requests.adapters import HTTPAdapter
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user