diff --git a/.gitignore b/.gitignore index ab4a70189b6..3ccfd94a901 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,9 @@ gamestonk_terminal/config_plot.py gamestonk_terminal/config_terminal.py gamestonk_terminal/feature_flags.py gamestonk_terminal/jupyter/reports/stored/* +gamestonk_terminal/jupyter/dashboards/.ipynb_checkpoints +gamestonk_terminal/jupyter/reports/.ipynb_checkpoints +gamestonk_terminal/jupyter/widgets/.ipynb_checkpoints !gamestonk_terminal/jupyter/reports/stored/.gitkeep !gamestonk_terminal/jupyter/dashboards/*.ipynb !gamestonk_terminal/jupyter/reports/*.ipynb diff --git a/bots/requirements.txt b/bots/requirements.txt index dbb27a3f5d9..21cae8c51c0 100755 --- a/bots/requirements.txt +++ b/bots/requirements.txt @@ -1,44 +1,44 @@ aiohttp==3.8.1; python_version >= "3.6" and python_full_version >= "3.8.0" -aiosignal==1.2.0; python_version >= "3.6" +aiosignal==1.2.0; python_version >= "3.6" and python_full_version >= "3.8.0" alabaster==0.7.12; python_version >= "3.7" alpha-vantage==2.3.1 ansiwrap==0.8.4; python_version >= "3.6" anyio==3.5.0; python_full_version >= "3.6.2" and python_version >= "3.7" -appnope==0.1.2; platform_system == "Darwin" and python_version >= "3.8" and sys_platform == "darwin" -argon2-cffi-bindings==21.2.0; python_version >= "3.6" +appnope==0.1.2; platform_system == "Darwin" and python_version >= "3.8" and sys_platform == "darwin" and python_full_version >= "3.6.2" +argon2-cffi-bindings==21.2.0; python_version >= "3.7" argon2-cffi==21.3.0; python_version >= "3.7" ascii-magic==1.6; python_version >= "3.5" asgiref==3.5.0; python_version >= "3.7" astor==0.8.1; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.7" astroid==2.9.3; python_full_version >= "3.6.2" -asttokens==2.0.5; python_version >= "3.8" +asttokens==2.0.5; python_full_version >= "3.6.2" and python_version >= "3.8" async-generator==1.10; python_version >= "3.7" and python_version < "4.0" -async-timeout==4.0.2; python_version >= "3.6" +async-timeout==4.0.2; python_version >= "3.6" and python_full_version >= "3.8.0" atomicwrites==1.4.0; python_version >= "3.7" and python_full_version < "3.0.0" and sys_platform == "win32" or sys_platform == "win32" and python_version >= "3.7" and python_full_version >= "3.4.0" -attrs==21.4.0; python_version >= "3.7" and python_full_version < "3.0.0" and python_version < "4.0" or python_full_version >= "3.5.0" and python_version >= "3.7" and python_version < "4.0" +attrs==21.4.0; python_full_version >= "3.8.0" and python_version >= "3.7" and (python_version >= "3.7" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.7" and python_version < "4.0" and python_full_version >= "3.5.0") and (python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.6" and python_version < "4.0" and python_full_version >= "3.5.0") and (python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.7") babel==2.9.1; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.7" -backcall==0.2.0; python_version >= "3.8" +backcall==0.2.0; python_full_version >= "3.6.2" and python_version >= "3.8" backports.zoneinfo==0.2.1; python_version < "3.9" and python_version >= "3.6" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6") bandit==1.7.4; python_version >= "3.7" beartype==0.7.1; python_version >= "3.8" and python_version < "4.0" and python_full_version >= "3.6.0" beautifulsoup4==4.10.0; python_full_version > "3.0.0" and python_version >= "3.7" black==22.1.0; python_full_version >= "3.6.2" bleach==4.1.0; python_version >= "3.7" -boto3==1.21.22; python_version >= "3.6" -botocore==1.24.22; python_version >= "3.6" +boto3==1.21.25; python_version >= "3.6" +botocore==1.24.25; python_version >= "3.6" bs4==0.0.1 bt==0.2.9; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.6.0") -certifi==2021.10.8; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version < "4" -cffi==1.15.0 +certifi==2021.10.8; python_full_version >= "3.7.1" and python_version < "4" and python_version >= "3.8" and python_full_version < "4.0.0" and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0") and (python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.7") +cffi==1.15.0; python_version >= "3.7" cfgv==3.3.1; python_full_version >= "3.6.1" -charset-normalizer==2.0.12; python_full_version >= "3.6.0" and python_version >= "3.6" +charset-normalizer==2.0.12; python_full_version >= "3.8.0" and python_version >= "3.8" and python_version < "4.0" and python_full_version < "4.0.0" and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0") and (python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.7") click==8.0.4; python_version >= "3.7" and python_full_version >= "3.6.2" codespell==2.1.0; python_version >= "3.5" -colorama==0.4.4; python_full_version >= "3.6.2" and python_full_version < "4.0.0" and (python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.5") and (python_version >= "3.6" and python_full_version < "3.0.0" and sys_platform == "win32" or sys_platform == "win32" and python_version >= "3.6" and python_full_version >= "3.5.0") and sys_platform == "win32" and (python_version >= "3.7" and python_full_version < "3.0.0" and sys_platform == "win32" or sys_platform == "win32" and python_version >= "3.7" and python_full_version >= "3.5.0") and (python_version >= "3.7" and python_full_version < "3.0.0" and platform_system == "Windows" or platform_system == "Windows" and python_version >= "3.7" and python_full_version >= "3.5.0") and (python_version >= "2.7" and python_full_version < "3.0.0" and platform_system == "Windows" or python_full_version >= "3.5.0" and platform_system == "Windows") and (python_version >= "3.6" and python_full_version < "3.0.0" and platform_system == "Windows" or platform_system == "Windows" and python_version >= "3.6" and python_full_version >= "3.5.0") and (python_version >= "3.8" and python_full_version < "3.0.0" and sys_platform == "win32" or sys_platform == "win32" and python_version >= "3.8" and python_full_version >= "3.5.0") +colorama==0.4.4; python_full_version >= "3.6.2" and python_full_version < "4.0.0" and (python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.5") and (python_version >= "3.6" and python_full_version < "3.0.0" and sys_platform == "win32" or sys_platform == "win32" and python_version >= "3.6" and python_full_version >= "3.5.0") and sys_platform == "win32" and (python_version >= "3.7" and python_full_version < "3.0.0" and sys_platform == "win32" or sys_platform == "win32" and python_version >= "3.7" and python_full_version >= "3.5.0") and (python_version >= "3.7" and python_full_version < "3.0.0" and platform_system == "Windows" or platform_system == "Windows" and python_version >= "3.7" and python_full_version >= "3.5.0") and (python_version >= "3.6" and python_full_version < "3.0.0" and platform_system == "Windows" or python_full_version >= "3.5.0" and platform_system == "Windows" and python_version >= "3.6") and platform_system == "Windows" and python_version >= "3.8" commonmark==0.9.1; python_full_version >= "3.6.2" and python_full_version < "4.0.0" convertdate==2.4.0; python_version >= "3.7" and python_version < "4" coverage==6.3.2; python_version >= "3.7" -cryptography==36.0.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version < "4" and python_version >= "3.6" +cryptography==36.0.2; python_version >= "3.7" and python_full_version < "3.0.0" and python_version < "4.0" or python_full_version >= "3.6.0" and python_version < "4" and python_version >= "3.7" cssselect==1.1.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" cvxpy==1.2.0; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.7" cycler==0.11.0; python_version >= "3.7" @@ -46,7 +46,7 @@ cython==0.29.28; python_version >= "3.7" and python_full_version < "3.0.0" and s dateparser==1.1.1; python_version >= "3.5" datetime==4.4; python_version >= "3.5" debugpy==1.5.1; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.7" -decorator==5.1.1; python_version >= "3.8" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.8" +decorator==5.1.1; python_full_version >= "3.6.2" and python_version >= "3.8" and (python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.5") defusedxml==0.7.1; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.7" degiro-connector==2.0.18; python_full_version >= "3.7.1" and python_full_version < "4.0.0" deprecation==2.1.0 @@ -56,10 +56,10 @@ distlib==0.3.4; python_full_version >= "3.6.1" dnspython==2.2.1; python_version >= "3.6" and python_version < "4.0" docutils==0.16; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.7" ecos==2.0.10; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.7" -entrypoints==0.4; python_full_version >= "3.6.1" and python_version >= "3.7" +entrypoints==0.4; python_full_version >= "3.7.0" and python_version >= "3.7" et-xmlfile==1.1.0; python_version >= "3.6" exchange-calendars==3.6.1; python_version >= "3.7" and python_full_version >= "3.7.0" -executing==0.8.3; python_version >= "3.8" +executing==0.8.3; python_full_version >= "3.6.2" and python_version >= "3.8" fastapi==0.73.0; python_full_version >= "3.6.1" fear-greed-index==0.1.4; python_version >= "3.7" ffn==0.3.6; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" @@ -69,26 +69,26 @@ finnhub-python==2.4.11 finviz==1.4.4 finvizfinance==0.12.2; python_version >= "3.5" flake8==3.9.2; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.5.0") -fonttools==4.31.1; python_version >= "3.7" +fonttools==4.31.2; python_version >= "3.7" formulaic==0.3.2; python_version >= "3.7" fred==3.1 fredapi==0.4.3 frozendict==2.3.0; python_version >= "3.6" -frozenlist==1.3.0; python_version >= "3.7" +frozenlist==1.3.0; python_version >= "3.7" and python_full_version >= "3.8.0" fundamentalanalysis==0.2.12 future==0.18.2; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" gitdb==4.0.9; python_version >= "3.7" gitpython==3.1.27; python_version >= "3.7" -grpcio==1.44.0; python_full_version >= "3.7.1" and python_full_version < "4.0.0" and python_version >= "3.6" +grpcio==1.45.0; python_full_version >= "3.7.1" and python_full_version < "4.0.0" and python_version >= "3.6" h11==0.13.0; python_version >= "3.7" and python_version < "4.0" and python_full_version >= "3.7.0" hijri-converter==2.2.3; python_version >= "3.6" holidays==0.11.3.1; python_version >= "3.6" identify==2.4.12; python_version >= "3.7" and python_full_version >= "3.6.1" -idna==3.3; python_full_version >= "3.6.2" and python_version >= "3.7" and python_version < "4" +idna==3.3; python_full_version >= "3.8.0" and python_version >= "3.8" and python_version < "4" and python_full_version < "4.0.0" and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0") and (python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.7") imagesize==1.3.0; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.7" inflection==0.5.1; python_version >= "3.6" iniconfig==1.1.1; python_version >= "3.7" -interface-meta==1.2.4; python_version >= "3.7" +interface-meta==1.2.5; python_version >= "3.7" investpy==1.0.8; python_version >= "3.7" ipykernel==6.9.2; python_version >= "3.7" ipympl==0.8.8 @@ -97,22 +97,22 @@ ipython==8.1.1; python_full_version >= "3.6.2" and python_version >= "3.8" ipywidgets==7.7.0 iso8601==0.1.16 isort==5.10.1; python_full_version >= "3.6.2" and python_version < "4.0" -jedi==0.18.1; python_version >= "3.8" -jinja2==3.0.3; python_version >= "3.7" +jedi==0.18.1; python_full_version >= "3.6.2" and python_version >= "3.8" +jinja2==3.1.0; python_version >= "3.7" jmespath==1.0.0; python_version >= "3.7" -joblib==1.1.0; python_version >= "3.7" +joblib==1.1.0; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.7" json5==0.9.6; python_version >= "3.7" jsonschema==3.2.0 jupyter-client==7.1.2; python_full_version >= "3.7.0" and python_version >= "3.7" jupyter-console==6.4.3; python_version >= "3.6" -jupyter-core==4.9.2; python_full_version >= "3.6.1" and python_version >= "3.7" +jupyter-core==4.9.2; python_full_version >= "3.7.0" and python_version >= "3.7" jupyter-server==1.15.6; python_version >= "3.7" jupyter==1.0.0 jupyterlab-pygments==0.1.2; python_version >= "3.7" jupyterlab-server==2.11.2; python_version >= "3.7" jupyterlab-widgets==1.1.0; python_version >= "3.6" jupyterlab==3.3.2; python_version >= "3.7" -kaleido==0.2.1; python_version >= "3.8" and python_version < "4.0" +kaleido==0.2.1.post1 kiwisolver==1.4.0; python_version >= "3.7" korean-lunar-calendar==0.2.1; python_version >= "3.7" and python_full_version >= "3.7.0" lazy-object-proxy==1.7.1; python_version >= "3.6" and python_full_version >= "3.6.2" @@ -121,7 +121,7 @@ lxml==4.8.0; python_version >= "3.7" and python_full_version < "3.0.0" or python m2r2==0.2.8; python_version >= "3.7" markdown-it-py==1.1.0; python_version >= "3.6" and python_version < "4.0" markupsafe==2.1.1; python_version >= "3.7" -matplotlib-inline==0.1.3; python_version >= "3.8" +matplotlib-inline==0.1.3; python_full_version >= "3.6.2" and python_version >= "3.8" matplotlib==3.5.1; python_version >= "3.7" mccabe==0.6.1; python_full_version >= "3.6.2" mdit-py-plugins==0.2.8; python_version >= "3.6" and python_version < "4.0" @@ -129,11 +129,12 @@ mistune==0.8.4; python_version >= "3.7" mock==4.0.3; python_version >= "3.6" more-itertools==8.12.0; python_version >= "3.6" mplfinance==0.12.8b9 -multidict==6.0.2; python_version >= "3.7" +multidict==6.0.2; python_version >= "3.7" and python_full_version >= "3.8.0" multitasking==0.0.10 mypy-extensions==0.4.3; python_version >= "3.7" and python_full_version >= "3.6.2" mypy==0.930; python_version >= "3.6" myst-parser==0.15.2; python_version >= "3.6" +natsort==8.1.0; python_version >= "3.6" nbclassic==0.3.7; python_version >= "3.7" nbclient==0.5.13; python_full_version >= "3.7.0" and python_version >= "3.7" nbconvert==6.4.4; python_version >= "3.7" @@ -156,12 +157,12 @@ pandas-ta==0.3.14b pandas==1.3.5; python_full_version >= "3.7.1" pandocfilters==1.5.0; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.7" papermill==2.3.4; python_version >= "3.6" -parso==0.8.3; python_version >= "3.8" +parso==0.8.3; python_full_version >= "3.6.2" and python_version >= "3.8" pathspec==0.9.0; python_full_version >= "3.6.2" patsy==0.5.2; python_version >= "3.7" pbr==5.8.1; python_version >= "3.7" -pexpect==4.8.0; sys_platform != "win32" and python_version >= "3.8" -pickleshare==0.7.5; python_version >= "3.8" +pexpect==4.8.0; sys_platform != "win32" and python_version >= "3.8" and python_full_version >= "3.6.2" +pickleshare==0.7.5; python_full_version >= "3.6.2" and python_version >= "3.8" pillow==9.0.1; python_version >= "3.7" and python_version < "4" platformdirs==2.5.1; python_version >= "3.7" and python_full_version >= "3.6.2" plotly==5.6.0; python_version >= "3.6" @@ -176,14 +177,14 @@ property-cached==1.6.4; python_version >= "3.7" protobuf==3.19.4; python_full_version >= "3.7.1" and python_full_version < "4.0.0" and python_version >= "3.5" psaw==0.0.12; python_version >= "3" psutil==5.9.0; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.7" -ptyprocess==0.7.0; os_name != "nt" and python_version >= "3.8" and sys_platform != "win32" -pure-eval==0.2.2; python_version >= "3.8" -py==1.11.0; python_version >= "3.7" and python_full_version < "3.0.0" and implementation_name == "pypy" or python_full_version >= "3.5.0" and python_version >= "3.7" and implementation_name == "pypy" +ptyprocess==0.7.0; os_name != "nt" and python_version >= "3.8" and sys_platform != "win32" and python_full_version >= "3.6.2" +pure-eval==0.2.2; python_full_version >= "3.6.2" and python_version >= "3.8" +py==1.11.0; python_full_version >= "3.7.0" and python_version >= "3.7" and implementation_name == "pypy" pyally==1.1.2 pycodestyle==2.7.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" pycoingecko==2.2.0 -pycparser==2.21; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" -pydantic==1.9.0; python_full_version >= "3.6.1" +pycparser==2.21; python_version >= "3.7" and python_full_version < "3.0.0" and python_version < "4.0" and os_name == "nt" and implementation_name != "pypy" or python_full_version >= "3.6.0" and python_version < "4" and python_version >= "3.7" and os_name == "nt" and implementation_name != "pypy" +pydantic==1.8.2; python_full_version >= "3.6.1" pyex==0.5.0 pyflakes==2.3.1; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" pygments==2.11.2; python_version >= "3.5" @@ -196,13 +197,13 @@ pymongo==3.11.0; (python_version >= "2.7" and python_full_version < "3.0.0") or pynacl==1.5.0; python_version >= "3.6" pyobjc-core==8.4.1; python_version >= "3.6" and sys_platform == "darwin" pyobjc-framework-cocoa==8.4.1; python_version >= "3.6" and sys_platform == "darwin" -pyopenssl==22.0.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version < "4" and python_version >= "3.6" +pyopenssl==22.0.0; python_version >= "3.7" and python_full_version < "3.0.0" and python_version < "4.0" or python_full_version >= "3.6.0" and python_version < "4" and python_version >= "3.7" pyotp==2.6.0; python_version >= "3" pyparsing==3.0.7; python_version >= "3.7" -pyportfolioopt==1.5.1; python_full_version >= "3.6.1" and python_full_version < "4.0.0" +pyportfolioopt==1.5.2; python_full_version >= "3.6.1" and python_full_version < "4.0.0" pyprind==2.11.3; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" pyrsistent==0.18.1; python_version >= "3.7" -pysocks==1.7.1; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version < "4" +pysocks==1.7.1; python_version >= "3.7" and python_full_version < "3.0.0" and python_version < "4.0" or python_full_version >= "3.6.0" and python_version < "4" and python_version >= "3.7" pytelegrambotapi==4.4.0 pytest-cov==3.0.0; python_version >= "3.6" pytest-mock==3.7.0; python_version >= "3.7" @@ -210,16 +211,16 @@ pytest-recording==0.12.0; python_version >= "3.5" pytest==6.2.5; python_version >= "3.6" python-binance==1.0.15 python-coinmarketcap==0.2 -python-dateutil==2.8.2; python_full_version >= "3.7.1" and python_version >= "3.7" and (python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.7") and (python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.5") and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.6") +python-dateutil==2.8.2; python_full_version >= "3.7.1" and python_version >= "3.7" and python_full_version < "4.0.0" and (python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.7") and (python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.5") and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.6") python-dotenv==0.19.2; python_version >= "3.5" pytrends==4.8.0 pytz-deprecation-shim==0.1.0.post0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" -pytz==2022.1; python_full_version >= "3.7.1" and python_version >= "3.7" and (python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.7") +pytz==2022.1; python_full_version >= "3.7.1" and python_version >= "3.7" and python_full_version < "4.0.0" and (python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.7") pyupgrade==2.31.1; python_version >= "3.7" -pywin32==303; sys_platform == "win32" and platform_python_implementation != "PyPy" and python_version >= "3.7" +pywin32==303; sys_platform == "win32" and platform_python_implementation != "PyPy" and python_version >= "3.7" and python_full_version >= "3.7.0" pywinpty==2.0.5; os_name == "nt" and python_version >= "3.7" pyyaml==6.0; python_version >= "3.7" and python_full_version >= "3.6.1" -pyzmq==22.3.0; python_full_version >= "3.6.1" and python_version >= "3.7" +pyzmq==22.3.0; python_full_version >= "3.7.0" and python_version >= "3.7" qdldl==0.1.5.post0; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.7" qtconsole==5.2.2; python_version >= "3.6" qtpy==2.0.1; python_version >= "3.6" @@ -233,7 +234,7 @@ rich==10.16.2; python_full_version >= "3.6.2" and python_full_version < "4.0.0" robin-stocks==2.1.0; python_version >= "3" s3transfer==0.5.2; python_version >= "3.6" scikit-learn==1.0.2; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.7" -scipy==1.8.0; python_version >= "3.8" and python_version < "3.11" and python_full_version >= "3.6.1" and python_full_version < "4.0.0" and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0") +scipy==1.8.0; python_version >= "3.8" and python_version < "3.11" and python_full_version >= "3.6.1" and python_full_version < "4.0.0" and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0") and (python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.7") screeninfo==0.6.7 scs==3.2.0; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.7" seaborn==0.11.2; python_version >= "3.6" @@ -241,7 +242,7 @@ selenium==4.1.3; python_version >= "3.7" and python_version < "4.0" send2trash==1.8.0; python_version >= "3.7" sentiment-investor==2.1.0; python_version >= "3.8" and python_version < "4.0" setuptools-scm==6.4.2; python_version >= "3.7" -six==1.16.0; python_full_version >= "3.7.1" and python_version >= "3.7" and python_full_version < "4.0.0" and (python_version >= "3.8" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.8" and python_version < "4.0" and python_full_version >= "3.3.0") and (python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.5") and (python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.7") and (python_version >= "3.8" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.8") +six==1.16.0; python_full_version >= "3.7.1" and python_version >= "3.8" and python_full_version < "4.0.0" and (python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.7") and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.3.0") and (python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.5") slack-bolt==1.13.0; python_version >= "3.6" slack-sdk==3.15.2; python_full_version >= "3.6.0" and python_version >= "3.6" smmap==5.0.0; python_version >= "3.7" @@ -260,24 +261,24 @@ sphinxcontrib-qthelp==1.0.3; python_version >= "3.7" sphinxcontrib-serializinghtml==1.1.5; python_version >= "3.7" squarify==0.4.3 sseclient==0.0.27 -stack-data==0.2.0; python_version >= "3.8" +stack-data==0.2.0; python_full_version >= "3.6.2" and python_version >= "3.8" starlette==0.17.1; python_version >= "3.6" and python_full_version >= "3.6.1" statsmodels==0.13.2; python_version >= "3.7" stevedore==3.5.0; python_version >= "3.7" tabulate==0.8.9; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" temporal-cache==0.1.4 -tenacity==8.0.1; python_version >= "3.8" and python_version < "4.0" +tenacity==8.0.1; python_version >= "3.6" terminado==0.13.3; python_version >= "3.7" testpath==0.6.0; python_version >= "3.7" textwrap3==0.9.2; python_version >= "3.6" thepassiveinvestor==1.0.10 -threadpoolctl==3.1.0; python_version >= "3.7" +threadpoolctl==3.1.0; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.7" tokenize-rt==4.2.1; python_full_version >= "3.6.2" and python_version >= "3.7" toml==0.10.2; python_full_version >= "3.6.2" and python_version >= "3.6" and (python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.7") tomli==2.0.1; python_version >= "3.7" and python_full_version >= "3.6.2" toolz==0.11.2; python_version >= "3.7" and python_full_version >= "3.7.0" -tornado==6.1; python_full_version >= "3.6.1" and python_version >= "3.7" -tqdm==4.63.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" +tornado==6.1; python_full_version >= "3.7.0" and python_version >= "3.7" +tqdm==4.63.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" tradingview-ta==3.2.10; python_version >= "3.6" traitlets==5.1.1; python_full_version >= "3.7.0" and python_version >= "3.8" trio-websocket==0.9.2; python_version >= "3.7" and python_version < "4.0" @@ -295,21 +296,21 @@ ujson==5.1.0; python_version >= "3.7" undetected-chromedriver==3.1.5.post4 unidecode==1.3.4; python_version >= "3.7" update-checker==0.18.0; python_version >= "3.6" and python_version < "4.0" -urllib3==1.26.9; python_version >= "3.7" and python_full_version < "3.0.0" and python_version < "4.0" or python_full_version >= "3.6.0" and python_version < "4" and python_version >= "3.7" +urllib3==1.26.9; python_full_version >= "3.7.1" and python_version < "4" and python_version >= "3.8" and python_full_version < "4.0.0" and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0") and (python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.7") and (python_version >= "3.7" and python_full_version < "3.0.0" and python_version < "4.0" or python_full_version >= "3.5.0" and python_version < "4" and python_version >= "3.7") and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version < "4" and python_version >= "3.6") user-agent==0.1.10 uvicorn==0.17.6; python_version >= "3.7" vadersentiment==3.3.2 valinvest==0.0.2; python_version >= "3.6" vcrpy==4.1.1; python_version >= "3.5" virtualenv==20.13.4; python_full_version >= "3.6.1" -voila==0.3.3; python_version >= "3.7" -wcwidth==0.2.5; python_full_version >= "3.6.2" and python_version >= "3.6" +voila==0.3.4; python_version >= "3.7" +wcwidth==0.2.5; python_full_version >= "3.6.2" and python_version >= "3.8" webencodings==0.5.1; python_version >= "3.7" websocket-client==1.3.1; python_version >= "3.8" and python_version < "4.0" websockets==9.1; python_full_version >= "3.6.1" and python_version >= "3.7" widgetsnbextension==3.6.0 wrapt==1.13.3; python_full_version >= "3.7.1" and python_full_version < "4.0.0" and (python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.5") and (python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.7") wsproto==1.1.0; python_version >= "3.7" and python_version < "4.0" and python_full_version >= "3.7.0" -yarl==1.7.2; python_version >= "3.6" +yarl==1.7.2; python_version >= "3.6" and python_full_version >= "3.8.0" yfinance==0.1.70 zope.interface==5.4.0; python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.5" diff --git a/example.gst b/example.gst deleted file mode 100644 index c4918f49f37..00000000000 --- a/example.gst +++ /dev/null @@ -1,9 +0,0 @@ -stocks -load pltr -dd -pt -rot -../ins -stats -../ta -fib \ No newline at end of file diff --git a/gamestonk_terminal/api.py b/gamestonk_terminal/api.py index de8edb6cd7a..0f3b52d9ee4 100644 --- a/gamestonk_terminal/api.py +++ b/gamestonk_terminal/api.py @@ -10,5 +10,6 @@ from .etf import etf_api as etf from .forex import forex_api as forex from .mutual_funds import mutual_fund_api as funds from .portfolio import portfolio_api as portfolio +from .jupyter import widget_helpers as widgets from .config_terminal import theme diff --git a/gamestonk_terminal/cryptocurrency/crypto_api.py b/gamestonk_terminal/cryptocurrency/crypto_api.py index bef76b3a1fc..8688547a929 100644 --- a/gamestonk_terminal/cryptocurrency/crypto_api.py +++ b/gamestonk_terminal/cryptocurrency/crypto_api.py @@ -1,4 +1,7 @@ """Crypto context API.""" +import os +from gamestonk_terminal.helper_classes import ModelsNamespace as _models + # flake8: noqa # pylint: disable=unused-import @@ -7,6 +10,7 @@ from .cryptocurrency_helpers import display_all_coins as coins from .cryptocurrency_helpers import load from .cryptocurrency_helpers import find from .cryptocurrency_helpers import plot_chart as chart +from .cryptocurrency_helpers import plot_candles as candle # Context menus from .defi import defi_api as defi @@ -25,3 +29,6 @@ try: except Exception: # print("Prediction API is not available.") pass + +# Models +models = _models(os.path.abspath(os.path.dirname(__file__))) diff --git a/gamestonk_terminal/cryptocurrency/cryptocurrency_helpers.py b/gamestonk_terminal/cryptocurrency/cryptocurrency_helpers.py index 04cbbeb7c46..af6e9ad488a 100644 --- a/gamestonk_terminal/cryptocurrency/cryptocurrency_helpers.py +++ b/gamestonk_terminal/cryptocurrency/cryptocurrency_helpers.py @@ -1008,7 +1008,7 @@ def plot_candles( } # This plot has 2 axes - if not external_axes: + if external_axes is None: candle_chart_kwargs["returnfig"] = True candle_chart_kwargs["figratio"] = (10, 7) candle_chart_kwargs["figscale"] = 1.10 @@ -1036,7 +1036,7 @@ def plot_candles( (ax, volume) = external_axes candle_chart_kwargs["volume"] = volume else: - ax = external_axes + ax = external_axes[0] candle_chart_kwargs["ax"] = ax diff --git a/gamestonk_terminal/helper_funcs.py b/gamestonk_terminal/helper_funcs.py index eab1be3e069..c35b5f234fc 100644 --- a/gamestonk_terminal/helper_funcs.py +++ b/gamestonk_terminal/helper_funcs.py @@ -1108,7 +1108,7 @@ def check_file_type_saved(valid_types: List[str] = None): Parameters ---------- filenames: str - filneames to be saved separated with comma + filenames to be saved separated with comma Returns ------- diff --git a/gamestonk_terminal/jupyter/dashboards/crypto.ipynb b/gamestonk_terminal/jupyter/dashboards/crypto.ipynb new file mode 100644 index 00000000000..830e666a7db --- /dev/null +++ b/gamestonk_terminal/jupyter/dashboards/crypto.ipynb @@ -0,0 +1,160 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "6e198e40-0c33-45b3-a79b-2d9ee9eff7b9", + "metadata": { + "tags": [] + }, + "source": [ + "# Cryptocurrency exchange rates to USD ($)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "da655985-c9b7-492e-aefa-fbe3bc1865d5", + "metadata": {}, + "outputs": [], + "source": [ + "import json\n", + "import os\n", + "\n", + "import ipywidgets as ipw\n", + "from IPython.display import display\n", + "import pandas as pd\n", + "\n", + "from gamestonk_terminal import api as gst\n", + "\n", + "ipw.HTML(f\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dcbbf867-af50-4d06-ae5c-7c09647aa55d", + "metadata": {}, + "outputs": [], + "source": [ + "COIN_LIST = (\n", + " \"BTC,ETH,USDT,BNB,USDC,XRP,LUNA,ADA,\"\n", + " + \"SOL,AVAX,DOT,BUSD,DOGE,UST,SHIB,WBTC,\"\n", + " + \"MATIC,CRO,DAI,LTC,ATOM,NEAR,LINK,BCH,\"\n", + " + \"UNI,TRX,FTT,ETC,LEO,ALGO,XLM,MANA,\"\n", + " + \"BTCB,HBAR,EGLD,ICP,SAND,XMR,WAVES,VET,\"\n", + " + \"APE,FIL,FTM,AXS,THETA,KLAY,XTZ,RUNE\"\n", + ").split(\",\")\n", + "exchange_rates = {}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "deeeb80a-3675-44fb-9a1b-2325d8da4e7d", + "metadata": {}, + "outputs": [], + "source": [ + "def get_exchange_rate(coin: str, days: int = 2):\n", + " \"\"\"Get exchange rate for a cryptocurrency agains USD.\"\"\"\n", + " (_, _, _, _, current_df, _,) = gst.crypto.load(\n", + " coin=coin,\n", + " source=\"cp\",\n", + " days=days,\n", + " vs=\"usd\",\n", + " interval=\"1day\",\n", + " should_load_ta_data=True,\n", + " )\n", + " price_color = \"neutral_color\"\n", + " if current_df[\"Close\"].iloc[-1] > current_df[\"Close\"].iloc[-2]:\n", + " price_color = \"up_color\"\n", + " elif current_df[\"Close\"].iloc[-1] < current_df[\"Close\"].iloc[-2]:\n", + " price_color = \"down_color\"\n", + " price = str(current_df[\"Close\"].iloc[-1])[:7]\n", + "\n", + " return price, price_color" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "18acf5cb-6cbf-484d-8042-107c030098de", + "metadata": {}, + "outputs": [], + "source": [ + "def show_rates(btn):\n", + " \"\"\"Show exchange rates in grid box widget.\"\"\"\n", + " grid.children = ()\n", + " for coin in COIN_LIST:\n", + " if coin not in exchange_rates.keys():\n", + " exchange_rates[coin] = {\"price\": None, \"color\": None}\n", + " try:\n", + " price, price_color = get_exchange_rate(coin=coin)\n", + " except:\n", + " price, price_color = \"-------\", \"neutral_color\"\n", + " widgets = list(grid.children)\n", + " widgets.append(\n", + " ipw.HTML(\n", + " gst.widgets.price_card(\n", + " ticker=coin,\n", + " price=price,\n", + " price_color=price_color,\n", + " )\n", + " )\n", + " )\n", + " grid.children = tuple(widgets)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cf2021e9-de8a-466e-b341-fcd6abda64b5", + "metadata": {}, + "outputs": [], + "source": [ + "update_rates = ipw.Button(description=\"Update rates\")\n", + "update_rates.on_click(show_rates)\n", + "header = ipw.HBox([update_rates])\n", + "\n", + "layout = ipw.Layout(grid_template_columns=\"1fr \" * 8)\n", + "grid = ipw.GridBox(\n", + " [],\n", + " layout=layout,\n", + ")\n", + "\n", + "display(header, grid)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "19dfcbfe-eaec-406e-bb3c-72d1b3538a6e", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.12" + }, + "voila": { + "theme": "dark" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/gamestonk_terminal/jupyter/dashboards/dashboards_controller.py b/gamestonk_terminal/jupyter/dashboards/dashboards_controller.py index 6451389b103..c19ce5af98d 100644 --- a/gamestonk_terminal/jupyter/dashboards/dashboards_controller.py +++ b/gamestonk_terminal/jupyter/dashboards/dashboards_controller.py @@ -25,7 +25,14 @@ logger = logging.getLogger(__name__) class DashboardsController(BaseController): """Dashboards Controller class""" - CHOICES_COMMANDS = ["stocks", "correlation", "vsurf", "chains", "shortdata"] + CHOICES_COMMANDS = [ + "stocks", + "correlation", + "vsurf", + "chains", + "shortdata", + "crypto", + ] PATH = "/jupyter/dashboards/" def __init__(self, queue: List[str] = None): @@ -43,7 +50,8 @@ class DashboardsController(BaseController): correlation stock correlations vsurf options volatility surface chains options chain analysis - shortdata finra shortdata analysis[/cmds] + shortdata finra shortdata analysis + crypto cryptocurrency exchange rates against USD[/cmds] """ console.print(text=help_text, menu="Jupyter - Dashboards") @@ -64,14 +72,19 @@ class DashboardsController(BaseController): @log_start_end(log=logger) def call_chains(self, other_args: List[str]): - """Process vsurf command""" + """Process chains command""" create_call(other_args, "chains", "") @log_start_end(log=logger) def call_shortdata(self, other_args: List[str]): - """Process vsurf command""" + """Process shortdata command""" create_call(other_args, "shortdata", "") + @log_start_end(log=logger) + def call_crypto(self, other_args: List[str]): + """Process crypto command""" + create_call(other_args, "crypto", "") + def create_call(other_args: List[str], name: str, filename: str = None) -> None: filename = filename if filename else name diff --git a/gamestonk_terminal/jupyter/reports/due_diligence.ipynb b/gamestonk_terminal/jupyter/reports/due_diligence.ipynb deleted file mode 100644 index b540e8b308f..00000000000 --- a/gamestonk_terminal/jupyter/reports/due_diligence.ipynb +++ /dev/null @@ -1,299 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "phantom-facility", - "metadata": {}, - "outputs": [], - "source": [ - "# Import most generic modules\n", - "import importlib\n", - "import pathlib\n", - "import os\n", - "import sys\n", - "from datetime import datetime, timedelta\n", - "import pandas as pd\n", - "from IPython.display import display, Markdown\n", - "import warnings\n", - "\n", - "warnings.filterwarnings(\"ignore\")\n", - "module_path = os.path.abspath(os.path.join(\"../..\"))\n", - "\n", - "if module_path not in sys.path:\n", - " sys.path.append(module_path)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "compact-count", - "metadata": { - "tags": [ - "parameters" - ] - }, - "outputs": [], - "source": [ - "# Parameters that will be replaced when calling this notebook\n", - "ticker = \"AAPL\"\n", - "\n", - "report_name = (\n", - " f\"{datetime.now().strftime('%Y%m%d_%H%M%S')}_due_diligence_{ticker.upper()}\"\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "possible-constraint", - "metadata": {}, - "outputs": [], - "source": [ - "display(\n", - " Markdown(\n", - " f\"# {ticker.upper()} - Due Diligence - {datetime.now().strftime('%Y/%m/%d %H:%M:%S')}\"\n", - " )\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3a473d25", - "metadata": {}, - "outputs": [], - "source": [ - "base_path = os.path.abspath(os.path.join(\".\"))\n", - "report_cache_dir = pathlib.Path(base_path, \"stored\")\n", - "\n", - "if not os.path.isdir(report_cache_dir):\n", - " print(\"Reports data directory not found.\")\n", - " print(f\"Creating {report_cache_dir}\")\n", - " os.mkdir(report_cache_dir)\n", - "else:\n", - " print(f\"Found reports directory {report_cache_dir}\")" - ] - }, - { - "cell_type": "markdown", - "id": "temporal-clerk", - "metadata": {}, - "source": [ - "## Candle View" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d783ed59-1fb2-44f2-b4b0-bfdfee9afcb6", - "metadata": {}, - "outputs": [], - "source": [ - "from gamestonk_terminal.stocks import stocks_helper\n", - "\n", - "df_stock_cache = pathlib.Path(report_cache_dir, f\"{ticker}_stock_data.pkl\")\n", - "if os.path.isfile(df_stock_cache):\n", - " print(f\"Found a cache file. Loading {df_stock_cache}\")\n", - " df_stock = pd.read_pickle(df_stock_cache)\n", - "else:\n", - " print(\"Cache file not found. Getting data.\")\n", - " df_stock = stocks_helper.load_ticker(\n", - " ticker, (datetime.now() - timedelta(days=180)).strftime(\"%Y-%m-%d\")\n", - " )\n", - " df_stock = stocks_helper.find_trendline(df_stock, \"OC_High\", \"high\")\n", - " df_stock = stocks_helper.find_trendline(df_stock, \"OC_Low\", \"low\")\n", - " print(f\"Saving cache file {ticker}_stock_data.pkl\")\n", - " df_stock.to_pickle(df_stock_cache)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "transsexual-trance", - "metadata": {}, - "outputs": [], - "source": [ - "import mplfinance as mpf\n", - "\n", - "mc = mpf.make_marketcolors(\n", - " up=\"green\", down=\"red\", edge=\"black\", wick=\"black\", volume=\"in\", ohlc=\"i\"\n", - ")\n", - "s = mpf.make_mpf_style(marketcolors=mc, gridstyle=\":\", y_on_right=True)\n", - "\n", - "ap0 = []\n", - "\n", - "if \"OC_High_trend\" in df_stock.columns:\n", - " ap0.append(\n", - " mpf.make_addplot(df_stock[\"OC_High_trend\"], color=\"g\"),\n", - " )\n", - "\n", - "if \"OC_Low_trend\" in df_stock.columns:\n", - " ap0.append(\n", - " mpf.make_addplot(df_stock[\"OC_Low_trend\"], color=\"b\"),\n", - " )\n", - "\n", - "mpf.plot(\n", - " df_stock,\n", - " type=\"candle\",\n", - " mav=(20, 50, 200),\n", - " volume=True,\n", - " addplot=ap0,\n", - " xrotation=0,\n", - " style=s,\n", - " figratio=(10, 7),\n", - " figscale=2.00,\n", - " update_width_config=dict(\n", - " candle_linewidth=1.0, candle_width=0.8, volume_linewidth=1.0\n", - " ),\n", - ")" - ] - }, - { - "cell_type": "markdown", - "id": "political-intake", - "metadata": {}, - "source": [ - "## Analyst Targets" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "numerous-begin", - "metadata": {}, - "outputs": [], - "source": [ - "from gamestonk_terminal.stocks.due_diligence import finviz_view\n", - "\n", - "try:\n", - " finviz_view.analyst(ticker=ticker, export=\"\")\n", - "except Exception as e:\n", - " print(e)" - ] - }, - { - "cell_type": "markdown", - "id": "3cfd302c", - "metadata": {}, - "source": [ - "## Fundamentals" - ] - }, - { - "cell_type": "markdown", - "id": "written-lease", - "metadata": {}, - "source": [ - "### Annual Income Statement" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "played-vancouver", - "metadata": {}, - "outputs": [], - "source": [ - "from gamestonk_terminal.stocks.fundamental_analysis import av_view\n", - "\n", - "av_view.display_income_statement(ticker, limit=1)" - ] - }, - { - "cell_type": "markdown", - "id": "smooth-forge", - "metadata": {}, - "source": [ - "### Quarterly Income Statement" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "juvenile-throw", - "metadata": {}, - "outputs": [], - "source": [ - "from gamestonk_terminal.stocks.fundamental_analysis import av_view\n", - "\n", - "av_view.display_income_statement(ticker, limit=1, quarterly=True)" - ] - }, - { - "cell_type": "markdown", - "id": "passive-nerve", - "metadata": {}, - "source": [ - "### Annual Balance Sheet" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "nominated-empire", - "metadata": {}, - "outputs": [], - "source": [ - "from gamestonk_terminal.stocks.fundamental_analysis import av_view\n", - "\n", - "av_view.display_balance_sheet(ticker, limit=1)" - ] - }, - { - "cell_type": "markdown", - "id": "special-bargain", - "metadata": {}, - "source": [ - "### Annual Cash Flow" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "focused-thanks", - "metadata": {}, - "outputs": [], - "source": [ - "from gamestonk_terminal.stocks.fundamental_analysis import av_view\n", - "\n", - "av_view.display_cash_flow(ticker, limit=1)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "sought-phase", - "metadata": {}, - "outputs": [], - "source": [ - "!jupyter nbconvert {report_name + \".ipynb\"} --to html --no-input" - ] - } - ], - "metadata": { - "celltoolbar": "Tags", - "interpreter": { - "hash": "bdefb52be37b6ab26a82d292d220aaeebafdd00af58c431a8f759eb373ff9ec1" - }, - "kernelspec": { - "display_name": "Python 3.8.12 ('gst')", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.10" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/gamestonk_terminal/jupyter/reports/due_dilligence.ipynb b/gamestonk_terminal/jupyter/reports/due_dilligence.ipynb new file mode 100644 index 00000000000..cf0e8ef4952 --- /dev/null +++ b/gamestonk_terminal/jupyter/reports/due_dilligence.ipynb @@ -0,0 +1,445 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "70ba2c8a", + "metadata": {}, + "source": [ + "## Notebook setup" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "driven-billion", + "metadata": {}, + "outputs": [], + "source": [ + "import io\n", + "import warnings\n", + "from datetime import datetime, timedelta\n", + "\n", + "import matplotlib.pyplot as plt\n", + "import matplotlib_inline.backend_inline\n", + "\n", + "from gamestonk_terminal import api as gst\n", + "from gamestonk_terminal.helper_classes import TerminalStyle\n", + "\n", + "%matplotlib inline\n", + "matplotlib_inline.backend_inline.set_matplotlib_formats(\"svg\")\n", + "warnings.filterwarnings(\"ignore\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c3fe7db5-ec6a-42cf-9e66-52dc1de22370", + "metadata": {}, + "outputs": [], + "source": [ + "try:\n", + " theme = TerminalStyle(\"light\", \"light\", \"light\")\n", + "except:\n", + " pass\n", + "stylesheet = gst.widgets.html_report_stylesheet()" + ] + }, + { + "cell_type": "markdown", + "id": "807fda4e", + "metadata": {}, + "source": [ + "## Select Ticker" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "intended-sherman", + "metadata": { + "tags": [ + "parameters" + ] + }, + "outputs": [], + "source": [ + "# Parameters that will be replaced when calling this notebook\n", + "ticker = \"AMC\"\n", + "report_name = \"\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1be26dae-cafe-4a22-80aa-eff296fc1a9b", + "metadata": {}, + "outputs": [], + "source": [ + "ticker_data = gst.stocks.load(ticker, start=datetime.now() - timedelta(days=365))\n", + "ticker_data = gst.stocks.process_candle(ticker_data)\n", + "\n", + "report_title = (f\"{ticker.upper()} Due Diligence report ({datetime.now().strftime('%Y-%m-%d %H:%M:%S')})\")\n", + "report_title" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e3b15d6f-dc9e-4f97-aa07-37d949a4e4bb", + "metadata": {}, + "outputs": [], + "source": [ + "overview = gst.stocks.fa.models.yahoo_finance.get_info(ticker=ticker).transpose()[\n", + " \"Long business summary\"\n", + "][0]\n", + "overview" + ] + }, + { + "cell_type": "markdown", + "id": "f8a0d747", + "metadata": {}, + "source": [ + "## Data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "aca4b6ef", + "metadata": {}, + "outputs": [], + "source": [ + "(\n", + " df_year_estimates,\n", + " df_quarter_earnings,\n", + " df_quarter_revenues,\n", + ") = gst.stocks.dd.models.business_insider.get_estimates(ticker)" + ] + }, + { + "cell_type": "markdown", + "id": "b9c8feff", + "metadata": { + "tags": [] + }, + "source": [ + "### 1. Yearly Estimates" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c0f0a1ca", + "metadata": {}, + "outputs": [], + "source": [ + "display_year = sorted(df_year_estimates.columns.tolist())[:3]\n", + "df_year_estimates = df_year_estimates[display_year].head(5)\n", + "df_year_estimates" + ] + }, + { + "cell_type": "markdown", + "id": "64d3d490", + "metadata": { + "tags": [] + }, + "source": [ + "### 2. Quarterly Earnings" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fde46353", + "metadata": {}, + "outputs": [], + "source": [ + "df_quarter_earnings" + ] + }, + { + "cell_type": "markdown", + "id": "d13a1e5e", + "metadata": { + "tags": [] + }, + "source": [ + "### 3. Quarterly Revenues" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "51dfd9d2", + "metadata": {}, + "outputs": [], + "source": [ + "df_quarter_revenues" + ] + }, + { + "cell_type": "markdown", + "id": "6303e520", + "metadata": { + "tags": [] + }, + "source": [ + "### 4. SEC Filings" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3022130e", + "metadata": {}, + "outputs": [], + "source": [ + "df_sec_filings = gst.stocks.dd.models.marketwatch.get_sec_filings(ticker)[\n", + " [\"Type\", \"Category\", \"Link\"]\n", + "].head(5)\n", + "df_sec_filings" + ] + }, + { + "cell_type": "markdown", + "id": "1e201003", + "metadata": { + "tags": [] + }, + "source": [ + "### 5. Analyst Ratings" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4662b1ac", + "metadata": {}, + "outputs": [], + "source": [ + "df_analyst = gst.stocks.dd.models.finviz.get_analyst_data(ticker)\n", + "df_analyst[\"target_to\"] = df_analyst[\"target_to\"].combine_first(df_analyst[\"target\"])\n", + "df_analyst = df_analyst[[\"category\", \"analyst\", \"rating\", \"target_to\"]].rename(\n", + " columns={\n", + " \"category\": \"Category\",\n", + " \"analyst\": \"Analyst\",\n", + " \"rating\": \"Rating\",\n", + " \"target_to\": \"Price Target\",\n", + " }\n", + ")\n", + "df_analyst" + ] + }, + { + "cell_type": "markdown", + "id": "ade589d6-d80f-4651-acb7-929943114ef0", + "metadata": {}, + "source": [ + "## Plots" + ] + }, + { + "cell_type": "markdown", + "id": "621ed931-57e9-4ca6-afe8-8ef278122c77", + "metadata": {}, + "source": [ + "### 1. Price history" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "394668e1-1158-4a2b-8a38-04c72a6abdd6", + "metadata": {}, + "outputs": [], + "source": [ + "fig, (candles, volume) = plt.subplots(nrows=2, ncols=1, figsize=(5, 3), dpi=150)\n", + "gst.stocks.candle(\n", + " s_ticker=ticker,\n", + " df_stock=ticker_data,\n", + " use_matplotlib=True,\n", + " external_axes=[candles, volume],\n", + ")\n", + "candles.set_xticklabels(\"\")\n", + "fig.tight_layout()\n", + "\n", + "f = io.BytesIO()\n", + "fig.savefig(f, format=\"svg\")\n", + "price_chart = f.getvalue().decode(\"utf-8\")" + ] + }, + { + "cell_type": "markdown", + "id": "bf07a909", + "metadata": {}, + "source": [ + "### 2. Price Target" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "900686a3", + "metadata": {}, + "outputs": [], + "source": [ + "fig, ax = plt.subplots(figsize=(8, 3), dpi=150)\n", + "gst.stocks.dd.pt(\n", + " ticker=ticker,\n", + " start=\"2021-10-25\",\n", + " interval=\"1440min\",\n", + " stock=ticker_data,\n", + " num=10,\n", + " raw=False,\n", + " external_axes=[ax],\n", + ")\n", + "fig.tight_layout()\n", + "f = io.BytesIO()\n", + "fig.savefig(f, format=\"svg\")\n", + "price_target_chart = f.getvalue().decode(\"utf-8\")" + ] + }, + { + "cell_type": "markdown", + "id": "63c0538c", + "metadata": {}, + "source": [ + "### 3. Ratings over time" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f3733ff2", + "metadata": {}, + "outputs": [], + "source": [ + "fig, ax = plt.subplots(figsize=(8, 3), dpi=150)\n", + "gst.stocks.dd.rot(\n", + " ticker=ticker,\n", + " num=10,\n", + " raw=False,\n", + " export=\"\",\n", + " external_axes=[ax],\n", + ")\n", + "fig.tight_layout()\n", + "f = io.BytesIO()\n", + "fig.savefig(f, format=\"svg\")\n", + "ratings_over_time_chart = f.getvalue().decode(\"utf-8\")" + ] + }, + { + "cell_type": "markdown", + "id": "ac501a32-124d-4d21-aae1-a8d147bb1071", + "metadata": {}, + "source": [ + "## Render the report template to a file" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "mounted-phase", + "metadata": {}, + "outputs": [], + "source": [ + "body = \"\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "abfe37e4-ea38-42c3-8fb5-7cceb233fb12", + "metadata": {}, + "outputs": [], + "source": [ + "# Title\n", + "body += gst.widgets.h(1, report_title)\n", + "\n", + "body += gst.widgets.h(2, \"Overview\")\n", + "body += gst.widgets.row([gst.widgets.p(overview)])\n", + "\n", + "\n", + "# Analysts ratings\n", + "body += gst.widgets.h(2, \"Analyst assessments\")\n", + "body += gst.widgets.row([price_target_chart])\n", + "body += gst.widgets.row([df_analyst.to_html()])\n", + "body += gst.widgets.row([ratings_over_time_chart])\n", + "\n", + "# Price history and yearly estimates\n", + "body += gst.widgets.row(\n", + " [\n", + " gst.widgets.h(3, \"Price history\") + price_chart,\n", + " gst.widgets.h(3, \"Estimates\") + df_year_estimates.head().to_html(),\n", + " ]\n", + ")\n", + "\n", + "# Earnings and revenues\n", + "body += gst.widgets.h(2, \"Earnings and revenues\")\n", + "body += gst.widgets.row([df_quarter_earnings.head().to_html()])\n", + "body += gst.widgets.row([df_quarter_revenues.head().to_html()])\n", + "\n", + "# Sec filings and insider trading\n", + "body += gst.widgets.h(2, \"SEC filings\")\n", + "body += gst.widgets.row([df_sec_filings.to_html()])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "eb26492f-d13f-4302-b36d-ea8ee0020f82", + "metadata": {}, + "outputs": [], + "source": [ + "report = gst.widgets.html_report(title=report_name, stylesheet=stylesheet, body=body)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ee07c30c-9b38-4035-b128-20b7c9989951", + "metadata": {}, + "outputs": [], + "source": [ + "# to save the results\n", + "with open(report_name + \".html\", \"w\") as fh:\n", + " fh.write(report)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "34991096-bc3a-4134-b519-aa3a490abe98", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "celltoolbar": "Tags", + "interpreter": { + "hash": "31090e8428bc3cbe850895ffb75aca3a30f914a21038b56ab61f04d2ddd7301b" + }, + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/gamestonk_terminal/jupyter/reports/reports_controller.py b/gamestonk_terminal/jupyter/reports/reports_controller.py index 3c4edb365c4..f84e61f6e63 100644 --- a/gamestonk_terminal/jupyter/reports/reports_controller.py +++ b/gamestonk_terminal/jupyter/reports/reports_controller.py @@ -133,7 +133,7 @@ Select one of the following reports:[/info][cmds] (known_args, other_args) = self.parser.parse_known_args(an_input.split()) - if not other_args and an_input in ("1", "3", "4"): + if not other_args and an_input in ("2", "3", "5"): console.print("[red]Error: No ticker provided\n[/red]") logger.error("Exception: No ticker provided") return self.queue diff --git a/gamestonk_terminal/jupyter/widget_helpers.py b/gamestonk_terminal/jupyter/widget_helpers.py new file mode 100644 index 00000000000..090a5ce87ae --- /dev/null +++ b/gamestonk_terminal/jupyter/widget_helpers.py @@ -0,0 +1,97 @@ +"""Widgets Helper Library. + +A library of `ipywidgets` wrappers for notebook based reports and voila dashboards. +The library includes both python code and html/css/js elements that can be found in the +`./widgets` folder. +""" +import os +from typing import List +from jinja2 import Template + + +def price_card_stylesheet(): + """Load a default CSS stylesheet from file.""" + with open( + os.path.join(os.path.dirname(os.path.abspath(__file__)), "widgets", "style.css") + ) as f: + style = f.read() + return style + + +def price_card(ticker: str, price: str, price_color: str = "neutral_color") -> str: + """Prepare a styled HTML element of a 128 by 128 price card. + + Parameters + ---------- + ticker : str + Instrument ticker for the price card + price : str + Instrument price as a string + price_color : str, optional + The color of the price. Accepts "up_color", "down_color" and default "neutral_color" + + Returns + ------- + str + HTML code as string + """ + with open( + os.path.join(os.path.dirname(os.path.abspath(__file__)), "widgets", "card.j2") + ) as f: + template = Template(f.read()) + card = template.render(ticker=ticker, price=price, price_color=price_color) + return card + + +def html_report_stylesheet(): + """Load a default CSS stylesheet from file.""" + with open( + os.path.join( + os.path.dirname(os.path.abspath(__file__)), "widgets", "report.css" + ) + ) as f: + style = f.read() + return style + + +def html_report(title: str = "", stylesheet: str = "", body: str = "") -> str: + """Prepare a styled HTML page element. + + Parameters + ---------- + title : str, optional + Contents of the title tag, by default "" + stylesheet : str, optional + Contents of the stylesheet tag, by default "" + body : str, optional + Contents of the body tag, by default "" + + Returns + ------- + str + HTML code as string + """ + with open( + os.path.join(os.path.dirname(os.path.abspath(__file__)), "widgets", "report.j2") + ) as f: + template = Template(f.read()) + card = template.render(title=title, stylesheet=stylesheet, body=body) + return card + + +def h(level: int, text: str) -> str: + """Wrap text into an HTML `h` tag.""" + return f"{text}" + + +def p(text: str) -> str: + """Wrap text into an HTML `p` tag.""" + return f"

{text}

" + + +def row(elements: List) -> str: + with open( + os.path.join(os.path.dirname(os.path.abspath(__file__)), "widgets", "row.j2") + ) as f: + template = Template(f.read()) + return template.render(elements=elements) diff --git a/gamestonk_terminal/jupyter/widgets/card.j2 b/gamestonk_terminal/jupyter/widgets/card.j2 new file mode 100644 index 00000000000..09e630ad46b --- /dev/null +++ b/gamestonk_terminal/jupyter/widgets/card.j2 @@ -0,0 +1,8 @@ +
+
+
+

{{ ticker }}

+

{{ price }}

+
+
+
diff --git a/gamestonk_terminal/jupyter/widgets/report.css b/gamestonk_terminal/jupyter/widgets/report.css new file mode 100644 index 00000000000..07a9fcadab3 --- /dev/null +++ b/gamestonk_terminal/jupyter/widgets/report.css @@ -0,0 +1,224 @@ +.body { + background-color: #ffffff; + color: #000000; + font-weight: 400; + text-decoration: none; + vertical-align: baseline; + font-size: 12pt; + font-family: 'Consolas', Arial, Helvetica, sans-serif; + font-style: normal; + margin-top: 30px; + margin-bottom: 30px; + margin-left: 50px; + margin-left: 50px; + padding: 0 +} + +.title { + padding-top: 0pt; + color: #000000; + font-size: 42pt; + font-weight: 800; + padding-bottom: 0pt; + line-height: 1.15; + page-break-after: avoid; + text-align: center +} + +.subtitle { + padding-top: 0pt; + color: #666666; + font-size: 33pt; + padding-bottom: 10pt; + line-height: 1.15; + page-break-after: avoid; + font-style: italic; + text-align: center +} + +li { + color: #000000; + font-size: 13pt; +} + +p { + margin: 0; + color: #000000; + font-size: 13pt; +} + +h1 { + padding-top: 10pt; + color: #000000; + font-size: 28pt; + padding-bottom: 0pt; + line-height: 1.15; + page-break-after: avoid; + text-align: left +} + +h2 { + padding-top: 10pt; + color: #000000; + font-weight: 700; + font-size: 21pt; + padding-bottom: 0pt; + line-height: 1.15; + page-break-after: avoid; + text-align: left +} + +h3 { + padding-top: 8pt; + color: #666666; + font-weight: 700; + font-size: 14pt; + padding-bottom: 0pt; + line-height: 1.15; + page-break-after: avoid; + text-align: left +} + +h4 { + padding-top: 8pt; + -webkit-text-decoration-skip: none; + color: #666666; + text-decoration: underline; + font-size: 13pt; + padding-bottom: 0pt; + line-height: 1.15; + page-break-after: avoid; + text-decoration-skip-ink: none; + text-align: left +} + +h5 { + padding-top: 8pt; + color: #666666; + font-size: 13pt; + padding-bottom: 0pt; + line-height: 1.15; + page-break-after: avoid; + text-align: left +} + +h6 { + padding-top: 8pt; + color: #666666; + font-size: 13pt; + padding-bottom: 0pt; + line-height: 1.15; + page-break-after: avoid; + font-style: italic; + text-align: left +} + +table { + border-collapse: collapse; + border-spacing: 0; + border-width: 0; + border-top-color: #ffffff; + border-bottom-color: #ffffff; + border-left-color: #ffffff; + border-right-color: #ffffff; + color: black; + table-layout: fixed; + margin-left: 0; + margin-right: 0; + margin-top: 15pt; + margin-bottom: 30pt; + padding: 3pt; +} + +table thead { + color: black; + text-align: center; +} + +table thead tr th { + border-top: 0; + border-bottom: 0; + border-left: 1; + border-left-color: #000000; + border-right: 1; + border-right-color: #000000; + padding-right: 5pt; + padding-left: 5pt; + font-weight: 600; +} + +table thead tr th:first-child { + border-left: 0; +} + +table thead tr th:last-child { + border-right: 0; +} + +table tbody { + color: black; +} + +table tbody tr td { + border: 1; + border-color: #000000; + padding-left: 7pt; + padding-right: 7pt; +} + +table tbody tr th { + border: 1; + border-color: #000000; + font-weight: 200; + text-align: right; + padding-left: 7pt; + padding-right: 7pt; +} + +table tbody tr th:first-child { + border-left: 0; +} + +table tbody tr th:last-child { + border-right: 0; +} + +table tbody tr:last-child th { + border-bottom: 0; +} + +table tbody tr td:first-child { + border-left: 0; +} + +table tbody tr td:last-child { + border-right: 0; +} + +table tbody tr:last-child td { + border-bottom: 0; +} + +tbody tr:nth-child(even) { + background-color: rgb(216, 216, 216); +} + +@media print { + table { + -webkit-print-color-adjust: exact; + } +} + +.hcontainer { + margin: 10pt; + width: 1000px; +} + +.item { + display: inline-block; + *display: inline; + zoom: 1; + padding-left: 10pt; + padding-right: 10pt; + vertical-align: top; +} diff --git a/gamestonk_terminal/jupyter/widgets/report.j2 b/gamestonk_terminal/jupyter/widgets/report.j2 new file mode 100644 index 00000000000..718424f8136 --- /dev/null +++ b/gamestonk_terminal/jupyter/widgets/report.j2 @@ -0,0 +1,19 @@ + + + + + {% if title %} + {{ title }} + {% else %} + Gamestonk Terminal + {% endif %} + {% if stylesheet %} + + {% endif %} + + + {{ body }} + + diff --git a/gamestonk_terminal/jupyter/widgets/row.j2 b/gamestonk_terminal/jupyter/widgets/row.j2 new file mode 100644 index 00000000000..5e8a5a6bb4d --- /dev/null +++ b/gamestonk_terminal/jupyter/widgets/row.j2 @@ -0,0 +1,5 @@ +
+ {% for item in elements %} +
{{ item }}
+ {% endfor %} +
diff --git a/gamestonk_terminal/jupyter/widgets/style.css b/gamestonk_terminal/jupyter/widgets/style.css new file mode 100644 index 00000000000..7584138ab99 --- /dev/null +++ b/gamestonk_terminal/jupyter/widgets/style.css @@ -0,0 +1,54 @@ +.container { + position: relative; +} + +.container .card { + font-family: Consolas, sans-serif; + position: relative; + width: 128px; + height: 128px; + background: #000000; + border-radius: 5px; + border-color: rgb(142, 142, 142); + border-style: solid; + border-width: 0.5px; + overflow: hidden; +} + +.container .card .contentBx { + position: absolute; + top: 28; + bottom: 32; + width: 100%; + text-align: center; + z-index: 10; +} + +.container .card .contentBx h1 { + position: relative; + font-size: 24px; + font-weight: 600; + letter-spacing: 1px; + color: #fff; + margin-top: 28px; + margin-bottom: 10px; +} + +.container .card .contentBx h2 { + position: relative; + font-size: 24px; + font-weight: 600; + letter-spacing: 1px; +} + +.up_color { + color: #00ACFF; +} + +.down_color { + color: #e4003a; +} + +.neutral_color { + color: #ffed00; +} diff --git a/gamestonk_terminal/stocks/due_diligence/finnhub_view.py b/gamestonk_terminal/stocks/due_diligence/finnhub_view.py index fa08223af46..b593125dbc9 100644 --- a/gamestonk_terminal/stocks/due_diligence/finnhub_view.py +++ b/gamestonk_terminal/stocks/due_diligence/finnhub_view.py @@ -77,7 +77,13 @@ def plot_rating_over_time( @log_start_end(log=logger) @check_api_key(["API_FINNHUB_KEY"]) -def rating_over_time(ticker: str, num: int, raw: bool, export: str): +def rating_over_time( + ticker: str, + num: int, + raw: bool, + export: str, + external_axes: Optional[List[plt.Axes]] = None, +): """Rating over time (monthly). [Source: Finnhub] Parameters @@ -116,9 +122,7 @@ def rating_over_time(ticker: str, num: int, raw: bool, export: str): title="Monthly Rating", ) else: - plot_rating_over_time(df_rot.head(num), ticker) - - console.print("") + plot_rating_over_time(df_rot.head(num), ticker, external_axes) export_data( export, diff --git a/gamestonk_terminal/stocks/stocks_helper.py b/gamestonk_terminal/stocks/stocks_helper.py index 9748c188d95..e1d5c69c920 100644 --- a/gamestonk_terminal/stocks/stocks_helper.py +++ b/gamestonk_terminal/stocks/stocks_helper.py @@ -401,12 +401,13 @@ def display_candle( theme.visualize_output(force_tight_layout=False) else: - if len(external_axes) != 1: + if len(external_axes) != 2: logger.error("Expected list of one axis item.") - console.print("[red]Expected list of 1 axis items./n[/red]") + console.print("[red]Expected list of 2 axis items./n[/red]") return - (ax1,) = external_axes + ax1, ax2 = external_axes candle_chart_kwargs["ax"] = ax1 + candle_chart_kwargs["volume"] = ax2 mpf.plot(df_stock, **candle_chart_kwargs) else: diff --git a/jupyterlab/README.md b/jupyterlab/README.md index dbab20472e0..38b89d874e8 100644 --- a/jupyterlab/README.md +++ b/jupyterlab/README.md @@ -1,9 +1,24 @@ -# Jupyter Lab Extensions for using Gamestonk Terminal +# Jupyter Ecosystem integration + +The Jupyter ecosystem has created Open Source tools that have become the de-facto +standard for data related tasks. + +This folder contains source code for a bunch of tools that help using the functionality +of the terminal in connection with Jupyter: + +1. Jupyter Lab Extensions for using Gamestonk Terminal + +## 1. Jupyter Lab Extensions for using Gamestonk Terminal + +Documentation, GST and GST-settings are 3 Jupyter Lab extensions that illustrate how +the terminal can be integrated with Jupyter Lab based IDEs. + +*NOTE: The extensions should be considered prototypes and are not production-ready.* 1. Only bash is supported (only macOS, Linux and WSL). No support for Windows powershell or command prompt. 2. The input values are not escaped -## Installation +### Installation To install the Terminal Launcher and the Settings Extensions run the following commands from the [root folder of the project](/): @@ -16,7 +31,7 @@ jupyter labextension install jupyterlab/gst-settings jupyter labextension install jupyterlab/documentation ``` -## Development setup +### Development setup In this section `gst` extension will be used as an example. diff --git a/poetry.lock b/poetry.lock index 02e32ae03f4..a97e59d4e54 100644 --- a/poetry.lock +++ b/poetry.lock @@ -714,6 +714,14 @@ idna = ["idna (>=2.1,<4.0)"] trio = ["trio (>=0.14,<0.20)"] wmi = ["wmi (>=1.5.1,<2.0.0)"] +[[package]] +name = "docstring-to-markdown" +version = "0.10" +description = "On the fly conversion of Python docstrings to markdown" +category = "main" +optional = true +python-versions = ">=3.6" + [[package]] name = "docutils" version = "0.16" @@ -1378,6 +1386,20 @@ parso = ">=0.8.0,<0.9.0" qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] testing = ["Django (<3.1)", "colorama", "docopt", "pytest (<7.0.0)"] +[[package]] +name = "jedi-language-server" +version = "0.35.1" +description = "A language server for Jedi!" +category = "main" +optional = true +python-versions = ">=3.6,<4.0" + +[package.dependencies] +docstring-to-markdown = "<1.0.0" +jedi = ">=0.18.0,<0.19.0" +pydantic = ">=1.7,<2.0" +pygls = ">=0.11.1,<0.12.0" + [[package]] name = "jinja2" version = "3.1.0" @@ -1503,6 +1525,18 @@ python-versions = ">=3.6" pywin32 = {version = ">=1.0", markers = "sys_platform == \"win32\" and platform_python_implementation != \"PyPy\""} traitlets = "*" +[[package]] +name = "jupyter-lsp" +version = "1.5.1" +description = "Multi-Language Server WebSocket proxy for Jupyter Notebook/Lab server" +category = "main" +optional = true +python-versions = ">=3.6" + +[package.dependencies] +entrypoints = "*" +jupyter-server = ">=1.1.2" + [[package]] name = "jupyter-server" version = "1.15.6" @@ -1554,6 +1588,29 @@ tornado = ">=6.1.0" test = ["coverage", "pytest (>=6.0)", "pytest-cov", "pytest-console-scripts", "pytest-check-links (>=0.5)", "jupyterlab-server[test] (>=2.2,<3.0)", "requests", "requests-cache", "virtualenv", "check-manifest"] ui-tests = ["build"] +[[package]] +name = "jupyterlab-code-formatter" +version = "1.4.10" +description = "Code formatter for JupyterLab" +category = "main" +optional = true +python-versions = ">=3.6" + +[package.dependencies] +jupyterlab = ">=3.0,<4.0" + +[[package]] +name = "jupyterlab-lsp" +version = "3.10.1" +description = "Coding assistance for JupyterLab with Language Server Protocol" +category = "main" +optional = true +python-versions = ">=3.7" + +[package.dependencies] +jupyter-lsp = ">=1.4.0" +jupyterlab = ">=3.1.0,<4.0.0a0" + [[package]] name = "jupyterlab-pygments" version = "0.1.2" @@ -2585,7 +2642,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "pydantic" -version = "1.9.0" +version = "1.8.2" description = "Data validation and settings management using python 3.6 type hinting" category = "main" optional = true @@ -2631,6 +2688,24 @@ category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +[[package]] +name = "pygls" +version = "0.11.3" +description = "a pythonic generic language server (pronounced like \"pie glass\")." +category = "main" +optional = true +python-versions = "*" + +[package.dependencies] +pydantic = ">=1.7,<1.9" +typeguard = ">=2.10.0,<3" + +[package.extras] +dev = ["bandit (==1.6.0)", "flake8 (==3.7.7)", "mypy (==0.812)"] +docs = ["sphinx (==2.0.1)", "sphinx-rtd-theme (==0.4.3)"] +test = ["mock (==3.0.5)", "pytest (==4.5.0)", "pytest-asyncio (==0.10.0)"] +ws = ["websockets (>=9.0.0,<10.0.0)"] + [[package]] name = "pygments" version = "2.11.2" @@ -3924,6 +3999,18 @@ async-generator = ">=1.10" trio = ">=0.11" wsproto = ">=0.14" +[[package]] +name = "typeguard" +version = "2.13.3" +description = "Run-time type checker for Python" +category = "main" +optional = true +python-versions = ">=3.5.3" + +[package.extras] +doc = ["sphinx-rtd-theme", "sphinx-autodoc-typehints (>=1.2.0)"] +test = ["pytest", "typing-extensions", "mypy"] + [[package]] name = "types-python-dateutil" version = "2.8.10" @@ -4305,12 +4392,13 @@ testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"] [extras] bots = ["boto3", "pyimgur", "fastapi", "uvicorn", "disnake", "PyNaCl", "pyTelegramBotAPI", "slack-bolt", "undetected-chromedriver", "natsort", "kaleido"] +jupyterlab = ["jupyterlab-code-formatter", "jupyterlab-lsp", "jedi-language-server"] prediction = ["tensorflow"] [metadata] lock-version = "1.1" python-versions = "^3.8,<3.10" -content-hash = "0eff08c14b4accbde60ed901ce7bb0b6c67e6e0f3c584c4dd51d6d59ebb237e7" +content-hash = "23c984180dd26ed0132f110d22bc2477c8af574e40572a8106c1ccf39a1fb4ec" [metadata.files] absl-py = [ @@ -4848,6 +4936,10 @@ dnspython = [ {file = "dnspython-2.2.1-py3-none-any.whl", hash = "sha256:a851e51367fb93e9e1361732c1d60dab63eff98712e503ea7d92e6eccb109b4f"}, {file = "dnspython-2.2.1.tar.gz", hash = "sha256:0f7569a4a6ff151958b64304071d370daa3243d15941a7beedf0c9fe5105603e"}, ] +docstring-to-markdown = [ + {file = "docstring-to-markdown-0.10.tar.gz", hash = "sha256:12f75b0c7b7572defea2d9e24b57ef7ac38c3e26e91c0e5547cfc02b1c168bf6"}, + {file = "docstring_to_markdown-0.10-py3-none-any.whl", hash = "sha256:a2cd520599d1499d4a5d4eb16dea5bdebe32e5627504fb417d5733570f3d4d0b"}, +] docutils = [ {file = "docutils-0.16-py2.py3-none-any.whl", hash = "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af"}, {file = "docutils-0.16.tar.gz", hash = "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc"}, @@ -5200,6 +5292,10 @@ jedi = [ {file = "jedi-0.18.1-py2.py3-none-any.whl", hash = "sha256:637c9635fcf47945ceb91cd7f320234a7be540ded6f3e99a50cb6febdfd1ba8d"}, {file = "jedi-0.18.1.tar.gz", hash = "sha256:74137626a64a99c8eb6ae5832d99b3bdd7d29a3850fe2aa80a4126b2a7d949ab"}, ] +jedi-language-server = [ + {file = "jedi-language-server-0.35.1.tar.gz", hash = "sha256:e31185e79e1abdcc5a077305cb24cd3a44798a2db525045b40f6b647dc5bdf08"}, + {file = "jedi_language_server-0.35.1-py3-none-any.whl", hash = "sha256:532c16a9199d902bdc88ca991da176fe177f0b3019b826b50bf568a0b0081167"}, +] jinja2 = [ {file = "Jinja2-3.1.0-py3-none-any.whl", hash = "sha256:da424924c069a4013730d8dd010cbecac7e7bb752be388db3741688bffb48dc6"}, {file = "Jinja2-3.1.0.tar.gz", hash = "sha256:a2f09a92f358b96b5f6ca6ecb4502669c4acb55d8733bbb2b2c9c4af5564c605"}, @@ -5237,6 +5333,10 @@ jupyter-core = [ {file = "jupyter_core-4.9.2-py3-none-any.whl", hash = "sha256:f875e4d27e202590311d468fa55f90c575f201490bd0c18acabe4e318db4a46d"}, {file = "jupyter_core-4.9.2.tar.gz", hash = "sha256:d69baeb9ffb128b8cd2657fcf2703f89c769d1673c851812119e3a2a0e93ad9a"}, ] +jupyter-lsp = [ + {file = "jupyter-lsp-1.5.1.tar.gz", hash = "sha256:751abd35413be99a4331f3597b09341adc755589ed32091ac2f686db3d61267e"}, + {file = "jupyter_lsp-1.5.1-py3-none-any.whl", hash = "sha256:28bb4c44f0c78b4fe55041b2209a8a1f33b1719f39e5e280d8c4d689dc44ca31"}, +] jupyter-server = [ {file = "jupyter_server-1.15.6-py3-none-any.whl", hash = "sha256:e393934c19fcc324a7fca77f811eacd91201440f04c6fbb15c959c463baaa9c5"}, {file = "jupyter_server-1.15.6.tar.gz", hash = "sha256:56bd6f580d1f46b62294990e8e78651025729f5d3fc798f10f2c03f0cdcbf28d"}, @@ -5245,6 +5345,14 @@ jupyterlab = [ {file = "jupyterlab-3.3.2-py3-none-any.whl", hash = "sha256:32c9e3fae93d02f7a071f5e69a7a5450fa4bf087dd3d5aca58c7dd2adf2565d3"}, {file = "jupyterlab-3.3.2.tar.gz", hash = "sha256:3c716bf5592cb28c5c55c615c6e5bd3efc71898f6957d13719b56478bbbb587a"}, ] +jupyterlab-code-formatter = [ + {file = "jupyterlab_code_formatter-1.4.10-py3-none-any.whl", hash = "sha256:10a7f2ab44a4539a44ec6bf3fc3b27e7ed22c7ab975e6503823e21d7e60abae7"}, + {file = "jupyterlab_code_formatter-1.4.10.tar.gz", hash = "sha256:1645fd80b99d590d60fe0f3c078c9101ad62dfdbfac5e78b4c2d334896ab526f"}, +] +jupyterlab-lsp = [ + {file = "jupyterlab-lsp-3.10.1.tar.gz", hash = "sha256:9ad6ef22c4972b85480797034fc7914728eb78f1856b4dab3361686e4f20c9dd"}, + {file = "jupyterlab_lsp-3.10.1-py3-none-any.whl", hash = "sha256:5e142680d47736a894945d2846217f1d693961fb938ce978d0cb406b6c53c8ac"}, +] jupyterlab-pygments = [ {file = "jupyterlab_pygments-0.1.2-py2.py3-none-any.whl", hash = "sha256:abfb880fd1561987efaefcb2d2ac75145d2a5d0139b1876d5be806e32f630008"}, {file = "jupyterlab_pygments-0.1.2.tar.gz", hash = "sha256:cfcda0873626150932f438eccf0f8bf22bfa92345b814890ab360d666b254146"}, @@ -6059,41 +6167,28 @@ pycparser = [ {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, ] pydantic = [ - {file = "pydantic-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cb23bcc093697cdea2708baae4f9ba0e972960a835af22560f6ae4e7e47d33f5"}, - {file = "pydantic-1.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1d5278bd9f0eee04a44c712982343103bba63507480bfd2fc2790fa70cd64cf4"}, - {file = "pydantic-1.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab624700dc145aa809e6f3ec93fb8e7d0f99d9023b713f6a953637429b437d37"}, - {file = "pydantic-1.9.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c8d7da6f1c1049eefb718d43d99ad73100c958a5367d30b9321b092771e96c25"}, - {file = "pydantic-1.9.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:3c3b035103bd4e2e4a28da9da7ef2fa47b00ee4a9cf4f1a735214c1bcd05e0f6"}, - {file = "pydantic-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3011b975c973819883842c5ab925a4e4298dffccf7782c55ec3580ed17dc464c"}, - {file = "pydantic-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:086254884d10d3ba16da0588604ffdc5aab3f7f09557b998373e885c690dd398"}, - {file = "pydantic-1.9.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:0fe476769acaa7fcddd17cadd172b156b53546ec3614a4d880e5d29ea5fbce65"}, - {file = "pydantic-1.9.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8e9dcf1ac499679aceedac7e7ca6d8641f0193c591a2d090282aaf8e9445a46"}, - {file = "pydantic-1.9.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d1e4c28f30e767fd07f2ddc6f74f41f034d1dd6bc526cd59e63a82fe8bb9ef4c"}, - {file = "pydantic-1.9.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:c86229333cabaaa8c51cf971496f10318c4734cf7b641f08af0a6fbf17ca3054"}, - {file = "pydantic-1.9.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:c0727bda6e38144d464daec31dff936a82917f431d9c39c39c60a26567eae3ed"}, - {file = "pydantic-1.9.0-cp36-cp36m-win_amd64.whl", hash = "sha256:dee5ef83a76ac31ab0c78c10bd7d5437bfdb6358c95b91f1ba7ff7b76f9996a1"}, - {file = "pydantic-1.9.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d9c9bdb3af48e242838f9f6e6127de9be7063aad17b32215ccc36a09c5cf1070"}, - {file = "pydantic-1.9.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ee7e3209db1e468341ef41fe263eb655f67f5c5a76c924044314e139a1103a2"}, - {file = "pydantic-1.9.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0b6037175234850ffd094ca77bf60fb54b08b5b22bc85865331dd3bda7a02fa1"}, - {file = "pydantic-1.9.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b2571db88c636d862b35090ccf92bf24004393f85c8870a37f42d9f23d13e032"}, - {file = "pydantic-1.9.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8b5ac0f1c83d31b324e57a273da59197c83d1bb18171e512908fe5dc7278a1d6"}, - {file = "pydantic-1.9.0-cp37-cp37m-win_amd64.whl", hash = "sha256:bbbc94d0c94dd80b3340fc4f04fd4d701f4b038ebad72c39693c794fd3bc2d9d"}, - {file = "pydantic-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e0896200b6a40197405af18828da49f067c2fa1f821491bc8f5bde241ef3f7d7"}, - {file = "pydantic-1.9.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7bdfdadb5994b44bd5579cfa7c9b0e1b0e540c952d56f627eb227851cda9db77"}, - {file = "pydantic-1.9.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:574936363cd4b9eed8acdd6b80d0143162f2eb654d96cb3a8ee91d3e64bf4cf9"}, - {file = "pydantic-1.9.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c556695b699f648c58373b542534308922c46a1cda06ea47bc9ca45ef5b39ae6"}, - {file = "pydantic-1.9.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:f947352c3434e8b937e3aa8f96f47bdfe6d92779e44bb3f41e4c213ba6a32145"}, - {file = "pydantic-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5e48ef4a8b8c066c4a31409d91d7ca372a774d0212da2787c0d32f8045b1e034"}, - {file = "pydantic-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:96f240bce182ca7fe045c76bcebfa0b0534a1bf402ed05914a6f1dadff91877f"}, - {file = "pydantic-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:815ddebb2792efd4bba5488bc8fde09c29e8ca3227d27cf1c6990fc830fd292b"}, - {file = "pydantic-1.9.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6c5b77947b9e85a54848343928b597b4f74fc364b70926b3c4441ff52620640c"}, - {file = "pydantic-1.9.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c68c3bc88dbda2a6805e9a142ce84782d3930f8fdd9655430d8576315ad97ce"}, - {file = "pydantic-1.9.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5a79330f8571faf71bf93667d3ee054609816f10a259a109a0738dac983b23c3"}, - {file = "pydantic-1.9.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f5a64b64ddf4c99fe201ac2724daada8595ada0d102ab96d019c1555c2d6441d"}, - {file = "pydantic-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a733965f1a2b4090a5238d40d983dcd78f3ecea221c7af1497b845a9709c1721"}, - {file = "pydantic-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:2cc6a4cb8a118ffec2ca5fcb47afbacb4f16d0ab8b7350ddea5e8ef7bcc53a16"}, - {file = "pydantic-1.9.0-py3-none-any.whl", hash = "sha256:085ca1de245782e9b46cefcf99deecc67d418737a1fd3f6a4f511344b613a5b3"}, - {file = "pydantic-1.9.0.tar.gz", hash = "sha256:742645059757a56ecd886faf4ed2441b9c0cd406079c2b4bee51bcc3fbcd510a"}, + {file = "pydantic-1.8.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:05ddfd37c1720c392f4e0d43c484217b7521558302e7069ce8d318438d297739"}, + {file = "pydantic-1.8.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:a7c6002203fe2c5a1b5cbb141bb85060cbff88c2d78eccbc72d97eb7022c43e4"}, + {file = "pydantic-1.8.2-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:589eb6cd6361e8ac341db97602eb7f354551482368a37f4fd086c0733548308e"}, + {file = "pydantic-1.8.2-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:10e5622224245941efc193ad1d159887872776df7a8fd592ed746aa25d071840"}, + {file = "pydantic-1.8.2-cp36-cp36m-win_amd64.whl", hash = "sha256:99a9fc39470010c45c161a1dc584997f1feb13f689ecf645f59bb4ba623e586b"}, + {file = "pydantic-1.8.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a83db7205f60c6a86f2c44a61791d993dff4b73135df1973ecd9eed5ea0bda20"}, + {file = "pydantic-1.8.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:41b542c0b3c42dc17da70554bc6f38cbc30d7066d2c2815a94499b5684582ecb"}, + {file = "pydantic-1.8.2-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:ea5cb40a3b23b3265f6325727ddfc45141b08ed665458be8c6285e7b85bd73a1"}, + {file = "pydantic-1.8.2-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:18b5ea242dd3e62dbf89b2b0ec9ba6c7b5abaf6af85b95a97b00279f65845a23"}, + {file = "pydantic-1.8.2-cp37-cp37m-win_amd64.whl", hash = "sha256:234a6c19f1c14e25e362cb05c68afb7f183eb931dd3cd4605eafff055ebbf287"}, + {file = "pydantic-1.8.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:021ea0e4133e8c824775a0cfe098677acf6fa5a3cbf9206a376eed3fc09302cd"}, + {file = "pydantic-1.8.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:e710876437bc07bd414ff453ac8ec63d219e7690128d925c6e82889d674bb505"}, + {file = "pydantic-1.8.2-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:ac8eed4ca3bd3aadc58a13c2aa93cd8a884bcf21cb019f8cfecaae3b6ce3746e"}, + {file = "pydantic-1.8.2-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:4a03cbbe743e9c7247ceae6f0d8898f7a64bb65800a45cbdc52d65e370570820"}, + {file = "pydantic-1.8.2-cp38-cp38-win_amd64.whl", hash = "sha256:8621559dcf5afacf0069ed194278f35c255dc1a1385c28b32dd6c110fd6531b3"}, + {file = "pydantic-1.8.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8b223557f9510cf0bfd8b01316bf6dd281cf41826607eada99662f5e4963f316"}, + {file = "pydantic-1.8.2-cp39-cp39-manylinux1_i686.whl", hash = "sha256:244ad78eeb388a43b0c927e74d3af78008e944074b7d0f4f696ddd5b2af43c62"}, + {file = "pydantic-1.8.2-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:05ef5246a7ffd2ce12a619cbb29f3307b7c4509307b1b49f456657b43529dc6f"}, + {file = "pydantic-1.8.2-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:54cd5121383f4a461ff7644c7ca20c0419d58052db70d8791eacbbe31528916b"}, + {file = "pydantic-1.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:4be75bebf676a5f0f87937c6ddb061fa39cbea067240d98e298508c1bda6f3f3"}, + {file = "pydantic-1.8.2-py3-none-any.whl", hash = "sha256:fec866a0b59f372b7e776f2d7308511784dace622e0992a0b59ea3ccee0ae833"}, + {file = "pydantic-1.8.2.tar.gz", hash = "sha256:26464e57ccaafe72b7ad156fdaa4e9b9ef051f69e175dbbb463283000c05ab7b"}, ] pyex = [ {file = "pyEX-0.5.0-py2.py3-none-any.whl", hash = "sha256:8860b8eb9c15d91e5f552786fbe8f8ecd46c4c4931e5cb82ba41187eb603f742"}, @@ -6103,6 +6198,10 @@ pyflakes = [ {file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"}, {file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"}, ] +pygls = [ + {file = "pygls-0.11.3-py3-none-any.whl", hash = "sha256:5c925b182f2b0aa38d0ce83a9829ca5aed8eb9c7079cffc5bddff2da1033b58f"}, + {file = "pygls-0.11.3.tar.gz", hash = "sha256:4d86fc854e6d6613cd42bf7511e9c6aac947fc8d62ff973a705570b036d969f2"}, +] pygments = [ {file = "Pygments-2.11.2-py3-none-any.whl", hash = "sha256:44238f1b60a76d78fc8ca0528ee429702aae011c265fe6a8dd8b63049ae41c65"}, {file = "Pygments-2.11.2.tar.gz", hash = "sha256:4e426f72023d88d03b2fa258de560726ce890ff3b630f88c21cbb8b2503b8c6a"}, @@ -7006,6 +7105,10 @@ trio-websocket = [ {file = "trio-websocket-0.9.2.tar.gz", hash = "sha256:a3d34de8fac26023eee701ed1e7bf4da9a8326b61a62934ec9e53b64970fd8fe"}, {file = "trio_websocket-0.9.2-py3-none-any.whl", hash = "sha256:5b558f6e83cc20a37c3b61202476c5295d1addf57bd65543364e0337e37ed2bc"}, ] +typeguard = [ + {file = "typeguard-2.13.3-py3-none-any.whl", hash = "sha256:5e3e3be01e887e7eafae5af63d1f36c849aaa94e3a0112097312aabfa16284f1"}, + {file = "typeguard-2.13.3.tar.gz", hash = "sha256:00edaa8da3a133674796cf5ea87d9f4b4c367d77476e185e80251cc13dfbb8c4"}, +] types-python-dateutil = [ {file = "types-python-dateutil-2.8.10.tar.gz", hash = "sha256:6bcf3aae7242e5793bafd7b2bcfb4e255eb7b2b3144acd0df0e182dce58ccad3"}, {file = "types_python_dateutil-2.8.10-py3-none-any.whl", hash = "sha256:1f6d2305513d54da353a9dde7ed8a9ef46e8987377291612a0e2b9aac2d2b875"}, diff --git a/pyproject.toml b/pyproject.toml index 12b2c984720..557072a3c18 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -91,9 +91,13 @@ finnhub-python = "^2.4.10" linearmodels = "^4.25" black = "22.1" undetected-chromedriver = {version = "^3.1.5", optional = true} +ipywidgets = "^7.7.0" boto3 = {version = "^1.21.14", optional = true} natsort = {version = "^8.1.0", optional = true} kaleido = {version = "^0.2.1", optional = true} +jupyterlab-code-formatter = {version = "^1.4.10", optional = true} +jupyterlab-lsp = {version = "^3.10.1", optional = true} +jedi-language-server = {version = "^0.35.1", optional = true} [tool.poetry.dev-dependencies] @@ -124,6 +128,7 @@ pytest-cov = "^3.0.0" [tool.poetry.extras] prediction = ["tensorflow"] bots = ["boto3", "pyimgur", "fastapi", "uvicorn", "disnake", "PyNaCl", "pyTelegramBotAPI", "slack-bolt", "undetected-chromedriver", "natsort", "kaleido"] +jupyterlab = ["jupyterlab-code-formatter", "jupyterlab-lsp", "jedi-language-server"] [build-system] requires = ["poetry-core>=1.0.0"] diff --git a/styles/default/light.mplstyle b/styles/default/light.mplstyle index 419801b7d7b..807f6caa752 100644 --- a/styles/default/light.mplstyle +++ b/styles/default/light.mplstyle @@ -45,7 +45,7 @@ axes.labelcolor: 0F0F0F axes.grid: true axes.grid.which: major -axes.prop_cycle: cycler('color', ['254495', '48277c', '822661', 'c13246', 'e4003a', 'ef7d00', 'ffed00', '00aaff', '9b30d9', 'af005f', '5f00af', 'af87ff']) +axes.prop_cycle: cycler('color', ['254495', 'c13246', '48277c', 'e4003a', 'ef7d00', '822661', 'ffed00', '00aaff', '9b30d9', 'af005f', '5f00af', 'af87ff']) xtick.color: 0F0F0F ytick.color: 0F0F0F diff --git a/tests/gamestonk_terminal/jupyter/dashboards/test_dashboard_controller.py b/tests/gamestonk_terminal/jupyter/dashboards/test_dashboard_controller.py deleted file mode 100644 index 237d5f93ece..00000000000 --- a/tests/gamestonk_terminal/jupyter/dashboards/test_dashboard_controller.py +++ /dev/null @@ -1,143 +0,0 @@ -import os - -import pytest - -from gamestonk_terminal.jupyter.dashboards import dashboards_controller - - -@pytest.mark.vcr(record_mode="none") -@pytest.mark.parametrize( - "queue, expected", - [ - (["load", "help"], []), - (["quit", "help"], ["help"]), - ], -) -def test_menu_with_queue(expected, mocker, queue): - path_controller = "gamestonk_terminal.jupyter.dashboards.dashboards_controller" - - # MOCK SWITCH - mocker.patch( - target=f"{path_controller}.DashboardsController.switch", - return_value=["quit"], - ) - result_menu = dashboards_controller.DashboardsController(queue=queue).menu() - - assert result_menu == expected - - -@pytest.mark.vcr(record_mode="none") -def test_menu_without_queue_completion(mocker): - path_controller = "gamestonk_terminal.jupyter.dashboards.dashboards_controller" - - # ENABLE AUTO-COMPLETION : HELPER_FUNCS.MENU - mocker.patch( - target="gamestonk_terminal.feature_flags.USE_PROMPT_TOOLKIT", - new=True, - ) - mocker.patch( - target="gamestonk_terminal.parent_classes.session", - ) - mocker.patch( - target="gamestonk_terminal.parent_classes.session.prompt", - return_value="quit", - ) - - # DISABLE AUTO-COMPLETION : CONTROLLER.COMPLETER - mocker.patch.object( - target=dashboards_controller.gtff, - attribute="USE_PROMPT_TOOLKIT", - new=True, - ) - mocker.patch( - target=f"{path_controller}.session", - ) - mocker.patch( - target=f"{path_controller}.session.prompt", - return_value="quit", - ) - - result_menu = dashboards_controller.DashboardsController(queue=None).menu() - - assert result_menu == [] - - -@pytest.mark.vcr(record_mode="none") -@pytest.mark.record_stdout -def test_print_help(): - controller = dashboards_controller.DashboardsController(queue=None) - controller.print_help() - - -@pytest.mark.vcr(record_mode="none") -@pytest.mark.parametrize( - "an_input, expected_queue", - [ - ("", []), - ("/help", ["home", "help"]), - ("help/help", ["help", "help"]), - ("q", ["quit"]), - ("h", []), - ( - "r", - ["quit", "quit", "reset", "jupyter", "dashboards"], - ), - ], -) -def test_switch(an_input, expected_queue): - controller = dashboards_controller.DashboardsController(queue=None) - queue = controller.switch(an_input=an_input) - - assert queue == expected_queue - - -@pytest.mark.vcr(record_mode="none") -def test_call_cls(mocker): - mocker.patch("os.system") - - controller = dashboards_controller.DashboardsController(queue=None) - controller.call_cls([]) - - assert controller.queue == [] - os.system.assert_called_once_with("cls||clear") - - -@pytest.mark.vcr(record_mode="none") -@pytest.mark.parametrize( - "func, queue, expected_queue", - [ - ( - "call_exit", - [], - ["quit", "quit", "quit"], - ), - ("call_exit", ["help"], ["quit", "quit", "quit", "help"]), - ("call_home", [], ["quit", "quit"]), - ("call_help", [], []), - ("call_quit", [], ["quit"]), - ("call_quit", ["help"], ["quit", "help"]), - ( - "call_reset", - [], - ["quit", "quit", "reset", "jupyter", "dashboards"], - ), - ( - "call_reset", - ["help"], - [ - "quit", - "quit", - "reset", - "jupyter", - "dashboards", - "help", - ], - ), - ], -) -def test_call_func_expect_queue(expected_queue, func, queue): - controller = dashboards_controller.DashboardsController(queue=queue) - result = getattr(controller, func)([]) - - assert result is None - assert controller.queue == expected_queue diff --git a/tests/gamestonk_terminal/jupyter/dashboards/test_dashboards_controller.py b/tests/gamestonk_terminal/jupyter/dashboards/test_dashboards_controller.py index e69de29bb2d..237d5f93ece 100644 --- a/tests/gamestonk_terminal/jupyter/dashboards/test_dashboards_controller.py +++ b/tests/gamestonk_terminal/jupyter/dashboards/test_dashboards_controller.py @@ -0,0 +1,143 @@ +import os + +import pytest + +from gamestonk_terminal.jupyter.dashboards import dashboards_controller + + +@pytest.mark.vcr(record_mode="none") +@pytest.mark.parametrize( + "queue, expected", + [ + (["load", "help"], []), + (["quit", "help"], ["help"]), + ], +) +def test_menu_with_queue(expected, mocker, queue): + path_controller = "gamestonk_terminal.jupyter.dashboards.dashboards_controller" + + # MOCK SWITCH + mocker.patch( + target=f"{path_controller}.DashboardsController.switch", + return_value=["quit"], + ) + result_menu = dashboards_controller.DashboardsController(queue=queue).menu() + + assert result_menu == expected + + +@pytest.mark.vcr(record_mode="none") +def test_menu_without_queue_completion(mocker): + path_controller = "gamestonk_terminal.jupyter.dashboards.dashboards_controller" + + # ENABLE AUTO-COMPLETION : HELPER_FUNCS.MENU + mocker.patch( + target="gamestonk_terminal.feature_flags.USE_PROMPT_TOOLKIT", + new=True, + ) + mocker.patch( + target="gamestonk_terminal.parent_classes.session", + ) + mocker.patch( + target="gamestonk_terminal.parent_classes.session.prompt", + return_value="quit", + ) + + # DISABLE AUTO-COMPLETION : CONTROLLER.COMPLETER + mocker.patch.object( + target=dashboards_controller.gtff, + attribute="USE_PROMPT_TOOLKIT", + new=True, + ) + mocker.patch( + target=f"{path_controller}.session", + ) + mocker.patch( + target=f"{path_controller}.session.prompt", + return_value="quit", + ) + + result_menu = dashboards_controller.DashboardsController(queue=None).menu() + + assert result_menu == [] + + +@pytest.mark.vcr(record_mode="none") +@pytest.mark.record_stdout +def test_print_help(): + controller = dashboards_controller.DashboardsController(queue=None) + controller.print_help() + + +@pytest.mark.vcr(record_mode="none") +@pytest.mark.parametrize( + "an_input, expected_queue", + [ + ("", []), + ("/help", ["home", "help"]), + ("help/help", ["help", "help"]), + ("q", ["quit"]), + ("h", []), + ( + "r", + ["quit", "quit", "reset", "jupyter", "dashboards"], + ), + ], +) +def test_switch(an_input, expected_queue): + controller = dashboards_controller.DashboardsController(queue=None) + queue = controller.switch(an_input=an_input) + + assert queue == expected_queue + + +@pytest.mark.vcr(record_mode="none") +def test_call_cls(mocker): + mocker.patch("os.system") + + controller = dashboards_controller.DashboardsController(queue=None) + controller.call_cls([]) + + assert controller.queue == [] + os.system.assert_called_once_with("cls||clear") + + +@pytest.mark.vcr(record_mode="none") +@pytest.mark.parametrize( + "func, queue, expected_queue", + [ + ( + "call_exit", + [], + ["quit", "quit", "quit"], + ), + ("call_exit", ["help"], ["quit", "quit", "quit", "help"]), + ("call_home", [], ["quit", "quit"]), + ("call_help", [], []), + ("call_quit", [], ["quit"]), + ("call_quit", ["help"], ["quit", "help"]), + ( + "call_reset", + [], + ["quit", "quit", "reset", "jupyter", "dashboards"], + ), + ( + "call_reset", + ["help"], + [ + "quit", + "quit", + "reset", + "jupyter", + "dashboards", + "help", + ], + ), + ], +) +def test_call_func_expect_queue(expected_queue, func, queue): + controller = dashboards_controller.DashboardsController(queue=queue) + result = getattr(controller, func)([]) + + assert result is None + assert controller.queue == expected_queue diff --git a/tests/gamestonk_terminal/jupyter/dashboards/txt/test_dashboard_controller/test_print_help.txt b/tests/gamestonk_terminal/jupyter/dashboards/txt/test_dashboards_controller/test_print_help.txt similarity index 78% rename from tests/gamestonk_terminal/jupyter/dashboards/txt/test_dashboard_controller/test_print_help.txt rename to tests/gamestonk_terminal/jupyter/dashboards/txt/test_dashboards_controller/test_print_help.txt index 6cdb205ec41..462da2bae0e 100644 --- a/tests/gamestonk_terminal/jupyter/dashboards/txt/test_dashboard_controller/test_print_help.txt +++ b/tests/gamestonk_terminal/jupyter/dashboards/txt/test_dashboards_controller/test_print_help.txt @@ -4,4 +4,5 @@ vsurf options volatility surface chains options chain analysis shortdata finra shortdata analysis + crypto cryptocurrency exchange rates against USD diff --git a/tests/gamestonk_terminal/jupyter/test_jupter_controller.py b/tests/gamestonk_terminal/jupyter/test_jupyter_controller.py similarity index 100% rename from tests/gamestonk_terminal/jupyter/test_jupter_controller.py rename to tests/gamestonk_terminal/jupyter/test_jupyter_controller.py diff --git a/tests/gamestonk_terminal/jupyter/txt/test_jupter_controller/test_print_help.txt b/tests/gamestonk_terminal/jupyter/txt/test_jupyter_controller/test_print_help.txt similarity index 100% rename from tests/gamestonk_terminal/jupyter/txt/test_jupter_controller/test_print_help.txt rename to tests/gamestonk_terminal/jupyter/txt/test_jupyter_controller/test_print_help.txt