portfolio: Small feature + controller tests (#1246)

* Small feature + controller tests

* update test after merge

* Website + bump down pandas

Co-authored-by: didierlopes.eth <dro.lopes@campus.fct.unl.pt>
This commit is contained in:
jmaslek
2022-01-23 12:15:08 -05:00
committed by GitHub
parent 20db556b3c
commit a7d25dced5
12 changed files with 409 additions and 106 deletions

View File

@@ -17,6 +17,7 @@ from gamestonk_terminal.helper_funcs import (
valid_date,
check_positive_float,
check_positive,
EXPORT_ONLY_FIGURES_ALLOWED,
)
from gamestonk_terminal.menu import session
@@ -35,16 +36,7 @@ from gamestonk_terminal.helper_funcs import parse_known_args_and_warn
class PortfolioController(BaseController):
"""Portfolio Controller class"""
CHOICES_COMMANDS = [
"load",
"save",
"show",
"add",
"rmv",
"ar",
"rmr",
"al",
]
CHOICES_COMMANDS = ["load", "save", "show", "add", "rmv", "ar", "rmr", "al", "mdd"]
CHOICES_MENUS = [
"bro",
"po",
@@ -93,6 +85,7 @@ class PortfolioController(BaseController):
[info]Graphs:[/info][cmds]
rmr graph your returns versus the market's returns
al displays the allocation of the portfolio
mdd display portfolio drawdown[/cmds]
"""
console.print(text=help_text, menu="Portfolio")
@@ -402,3 +395,24 @@ class PortfolioController(BaseController):
console.print("Cannot generate a graph from an empty dataframe\n")
else:
console.print("Please add items to the portfolio\n")
def call_mdd(self, other_args: List[str]):
"""Process mdd command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="mdd",
description="Show portfolio drawdown",
)
ns_parser = parse_known_args_and_warn(
parser, other_args, export_allowed=EXPORT_ONLY_FIGURES_ALLOWED
)
if ns_parser:
if not self.portfolio.empty:
val, _ = portfolio_model.convert_df(self.portfolio)
if not val.empty:
df_m = yfinance_model.get_market(val.index[0], "SPY")
returns, _ = portfolio_model.get_return(val, df_m, 365)
portfolio_view.display_drawdown(returns[["return"]].dropna())
else:
console.print("[red]No portfolio loaded.\n[/red]")

View File

@@ -40,7 +40,7 @@ def save_df(df: pd.DataFrame, name: str) -> None:
elif ".json" in name:
df.to_json(path, index=False)
elif ".xlsx" in name:
df = df.to_excel(path, index=False, engine="openpyxl")
df.to_excel(path, index=False, engine="openpyxl")
def load_df(name: str) -> pd.DataFrame:
@@ -597,3 +597,28 @@ performance_text = (
". The information ratio is the excess return on systematic risk. An information ratio of"
" 0.4 to 0.6 is considered good."
)
def calculate_drawdown(input_series: pd.Series, is_returns: bool = False) -> pd.Series:
"""Calculate the drawdown (MDD) of historical series. Note that the calculation is done
on cumulative returns (or prices). The definition of drawdown is
DD = (current value - rolling maximum) / rolling maximum
Parameters
----------
input_series: pd.DataFrame
Dataframe of input values
is_returns: bool
Flag to indicate inputs are returns
Returns
pd.Series
Drawdown series
-------
"""
if is_returns:
input_series = (1 + input_series).cumprod()
rolling_max = input_series.cummax()
drawdown = (input_series - rolling_max) / rolling_max
return drawdown

View File

@@ -5,6 +5,7 @@ from typing import List
from datetime import datetime
from io import BytesIO
from os import path
import os
import numpy as np
import pandas as pd
@@ -24,7 +25,7 @@ from gamestonk_terminal.portfolio import (
yfinance_model,
)
from gamestonk_terminal.portfolio import reportlab_helpers
from gamestonk_terminal.helper_funcs import get_rf
from gamestonk_terminal.helper_funcs import get_rf, plot_autoscale, export_data
from gamestonk_terminal.portfolio.portfolio_optimization import optimizer_model
from gamestonk_terminal.rich_config import console
@@ -295,6 +296,40 @@ def display_allocation(data: pd.DataFrame, graph: bool):
plt.show()
def display_drawdown(holdings: pd.DataFrame, export: str = ""):
"""Display drawdown curve
Parameters
----------
holdings: pd.DataFrame
Dataframe of holdings vs time
export: str
Format to export data
"""
drawdown = portfolio_model.calculate_drawdown(holdings)
fig, ax = plt.subplots(2, 1, figsize=plot_autoscale(), dpi=PLOT_DPI)
ax[0].plot(holdings.index, holdings)
ax[0].set_title("Cumulative Returns")
ax[1].plot(holdings.index, drawdown)
ax[1].fill_between(holdings.index, np.asarray(drawdown["return"]), alpha=0.4)
ax[1].set_title("Portfolio Drawdown")
ax[0].grid()
ax[1].grid()
fig.autofmt_xdate()
fig.tight_layout()
if gtff.USE_ION:
plt.ion()
console.print()
plt.show()
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"mdd",
)
class Report:
def __init__(self, df: pd.DataFrame, hist: pd.DataFrame, m_tick: str, n: int):
"""Generate financial reports.

View File

@@ -761,6 +761,7 @@ class PredictionTechniquesController(BaseController):
help="Number of simulations to perform",
dest="n_sims",
default=100,
type=check_positive,
)
parser.add_argument(
"--dist",

61
poetry.lock generated vendored
View File

@@ -1957,23 +1957,23 @@ pyparsing = ">=2.0.2,<3.0.5 || >3.0.5"
[[package]]
name = "pandas"
version = "1.4.0"
version = "1.3.5"
description = "Powerful data structures for data analysis, time series, and statistics"
category = "main"
optional = false
python-versions = ">=3.8"
python-versions = ">=3.7.1"
[package.dependencies]
numpy = [
{version = ">=1.18.5", markers = "platform_machine != \"aarch64\" and platform_machine != \"arm64\" and python_version < \"3.10\""},
{version = ">=1.17.3", markers = "platform_machine != \"aarch64\" and platform_machine != \"arm64\" and python_version < \"3.10\""},
{version = ">=1.19.2", markers = "platform_machine == \"aarch64\" and python_version < \"3.10\""},
{version = ">=1.20.0", markers = "platform_machine == \"arm64\" and python_version < \"3.10\""},
]
python-dateutil = ">=2.8.1"
pytz = ">=2020.1"
python-dateutil = ">=2.7.3"
pytz = ">=2017.3"
[package.extras]
test = ["hypothesis (>=5.5.3)", "pytest (>=6.0)", "pytest-xdist (>=1.31)"]
test = ["hypothesis (>=3.58)", "pytest (>=6.0)", "pytest-xdist"]
[[package]]
name = "pandas-datareader"
@@ -3836,7 +3836,7 @@ prediction = ["tensorflow"]
[metadata]
lock-version = "1.1"
python-versions = "^3.8,<3.10"
content-hash = "65028ccaf95086a7576f5910cb4b439e7626f73c04879c4b4c4fc7ba66bbc935"
content-hash = "67f5d4c5a7cf6088cd5a77ff1fadb13af8a765c2231e7d8bd5eae9bb90292516"
[metadata.files]
absl-py = [
@@ -4200,7 +4200,6 @@ cvxpy = [
{file = "cvxpy-1.1.18-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9f82ca609e34577062940d5c32bc1f687fcf83d39ca92ec0d04fb1f290b43355"},
{file = "cvxpy-1.1.18-cp39-cp39-manylinux_2_24_x86_64.whl", hash = "sha256:569f7298539a2bd8704209628af11ecf1bca0cff2d5e27c46b57ffea921a01cf"},
{file = "cvxpy-1.1.18-cp39-cp39-win_amd64.whl", hash = "sha256:2eb079877d23f03494141102d6cf9d3139edf5e1dc07bfa3f767f4c79e837ecb"},
{file = "cvxpy-1.1.18.tar.gz", hash = "sha256:5baefe1f2ed6937749b293586c6ce4f42ed30e7890223f7661ccb2bb7df70bef"},
]
cycler = [
{file = "cycler-0.11.0-py3-none-any.whl", hash = "sha256:3a27e95f763a428a739d2add979fa7494c912a32c17c4c38c4d5f082cad165a3"},
@@ -5159,27 +5158,31 @@ packaging = [
{file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
]
pandas = [
{file = "pandas-1.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:de62cf699122dcef175988f0714678e59c453dc234c5b47b7136bfd7641e3c8c"},
{file = "pandas-1.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:46a18572f3e1cb75db59d9461940e9ba7ee38967fa48dd58f4139197f6e32280"},
{file = "pandas-1.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:73f7da2ccc38cc988b74e5400b430b7905db5f2c413ff215506bea034eaf832d"},
{file = "pandas-1.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5229c95db3a907451dacebc551492db6f7d01743e49bbc862f4a6010c227d187"},
{file = "pandas-1.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe454180ad31bbbe1e5d111b44443258730467f035e26b4e354655ab59405871"},
{file = "pandas-1.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:784cca3f69cfd7f6bd7c7fdb44f2bbab17e6de55725e9ff36d6f382510dfefb5"},
{file = "pandas-1.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:de8f8999864399529e8514a2e6bfe00fd161f0a667903655552ed12e583ae3cb"},
{file = "pandas-1.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0f19504f2783526fb5b4de675ea69d68974e21c1624f4b92295d057a31d5ec5f"},
{file = "pandas-1.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f045bb5c6bfaba536089573bf97d6b8ccc7159d951fe63904c395a5e486fbe14"},
{file = "pandas-1.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5280d057ddae06fe4a3cd6aa79040b8c205cd6dd21743004cf8635f39ed01712"},
{file = "pandas-1.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f3b74335390dda49f5d5089fab71958812bf56f42aa27663ee4c16d19f4f1c5"},
{file = "pandas-1.4.0-cp38-cp38-win32.whl", hash = "sha256:51e5da3802aaee1aa4254108ffaf1129a15fb3810b7ce8da1ec217c655b418f5"},
{file = "pandas-1.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:f103a5cdcd66cb18882ccdc18a130c31c3cfe3529732e7f10a8ab3559164819c"},
{file = "pandas-1.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:4a8d5a200f8685e7ea562b2f022c77ab7cb82c1ca5b240e6965faa6f84e5c1e9"},
{file = "pandas-1.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b5af258c7b090cca7b742cf2bd67ad1919aa9e4e681007366c9edad2d6a3d42b"},
{file = "pandas-1.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:156aac90dd7b303bf0b91bae96c0503212777f86c731e41929c571125d26c8e9"},
{file = "pandas-1.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2dad075089e17a72391de33021ad93720aff258c3c4b68c78e1cafce7e447045"},
{file = "pandas-1.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d59c958d6b8f96fdf850c7821571782168d5acfe75ccf78cd8d1ac15fb921df"},
{file = "pandas-1.4.0-cp39-cp39-win32.whl", hash = "sha256:55ec0e192eefa26d823fc25a1f213d6c304a3592915f368e360652994cdb8d9a"},
{file = "pandas-1.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:23c04dab11f3c6359cfa7afa83d3d054a8f8c283d773451184d98119ef54da97"},
{file = "pandas-1.4.0.tar.gz", hash = "sha256:cdd76254c7f0a1583bd4e4781fb450d0ebf392e10d3f12e92c95575942e37df5"},
{file = "pandas-1.3.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:62d5b5ce965bae78f12c1c0df0d387899dd4211ec0bdc52822373f13a3a022b9"},
{file = "pandas-1.3.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:adfeb11be2d54f275142c8ba9bf67acee771b7186a5745249c7d5a06c670136b"},
{file = "pandas-1.3.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:60a8c055d58873ad81cae290d974d13dd479b82cbb975c3e1fa2cf1920715296"},
{file = "pandas-1.3.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd541ab09e1f80a2a1760032d665f6e032d8e44055d602d65eeea6e6e85498cb"},
{file = "pandas-1.3.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2651d75b9a167cc8cc572cf787ab512d16e316ae00ba81874b560586fa1325e0"},
{file = "pandas-1.3.5-cp310-cp310-win_amd64.whl", hash = "sha256:aaf183a615ad790801fa3cf2fa450e5b6d23a54684fe386f7e3208f8b9bfbef6"},
{file = "pandas-1.3.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:344295811e67f8200de2390093aeb3c8309f5648951b684d8db7eee7d1c81fb7"},
{file = "pandas-1.3.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:552020bf83b7f9033b57cbae65589c01e7ef1544416122da0c79140c93288f56"},
{file = "pandas-1.3.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5cce0c6bbeb266b0e39e35176ee615ce3585233092f685b6a82362523e59e5b4"},
{file = "pandas-1.3.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d28a3c65463fd0d0ba8bbb7696b23073efee0510783340a44b08f5e96ffce0c"},
{file = "pandas-1.3.5-cp37-cp37m-win32.whl", hash = "sha256:a62949c626dd0ef7de11de34b44c6475db76995c2064e2d99c6498c3dba7fe58"},
{file = "pandas-1.3.5-cp37-cp37m-win_amd64.whl", hash = "sha256:8025750767e138320b15ca16d70d5cdc1886e8f9cc56652d89735c016cd8aea6"},
{file = "pandas-1.3.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:fe95bae4e2d579812865db2212bb733144e34d0c6785c0685329e5b60fcb85dd"},
{file = "pandas-1.3.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f261553a1e9c65b7a310302b9dbac31cf0049a51695c14ebe04e4bfd4a96f02"},
{file = "pandas-1.3.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b6dbec5f3e6d5dc80dcfee250e0a2a652b3f28663492f7dab9a24416a48ac39"},
{file = "pandas-1.3.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d3bc49af96cd6285030a64779de5b3688633a07eb75c124b0747134a63f4c05f"},
{file = "pandas-1.3.5-cp38-cp38-win32.whl", hash = "sha256:b6b87b2fb39e6383ca28e2829cddef1d9fc9e27e55ad91ca9c435572cdba51bf"},
{file = "pandas-1.3.5-cp38-cp38-win_amd64.whl", hash = "sha256:a395692046fd8ce1edb4c6295c35184ae0c2bbe787ecbe384251da609e27edcb"},
{file = "pandas-1.3.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bd971a3f08b745a75a86c00b97f3007c2ea175951286cdda6abe543e687e5f2f"},
{file = "pandas-1.3.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37f06b59e5bc05711a518aa10beaec10942188dccb48918bb5ae602ccbc9f1a0"},
{file = "pandas-1.3.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c21778a688d3712d35710501f8001cdbf96eb70a7c587a3d5613573299fdca6"},
{file = "pandas-1.3.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3345343206546545bc26a05b4602b6a24385b5ec7c75cb6059599e3d56831da2"},
{file = "pandas-1.3.5-cp39-cp39-win32.whl", hash = "sha256:c69406a2808ba6cf580c2255bcf260b3f214d2664a3a4197d0e640f573b46fd3"},
{file = "pandas-1.3.5-cp39-cp39-win_amd64.whl", hash = "sha256:32e1a26d5ade11b547721a72f9bfc4bd113396947606e00d5b4a5b79b3dcb006"},
{file = "pandas-1.3.5.tar.gz", hash = "sha256:1e4285f5de1012de20ca46b188ccf33521bff61ba5c5ebd78b4fb28e5416a9f1"},
]
pandas-datareader = [
{file = "pandas-datareader-0.10.0.tar.gz", hash = "sha256:9fc3c63d39bc0c10c2683f1c6d503ff625020383e38f6cbe14134826b454d5a6"},

2
pyproject.toml vendored
View File

@@ -69,7 +69,7 @@ pmdarima = "^1.8.4"
pyrsistent = "^0.18.0"
openpyxl = "^3.0.9"
jsonschema = "3.2.0"
pandas = "^1.3.4"
pandas = "1.3.5"
ipympl = "^0.8.2"
voila = "^0.3.0"
rich = "^10.16.1"

64
requirements-full.txt vendored
View File

@@ -6,40 +6,40 @@ ansiwrap==0.8.4; python_version >= "3.6"
anyio==3.5.0; python_full_version >= "3.6.2" and python_version >= "3.7"
appdirs==1.4.4; python_full_version >= "3.6.2" and python_version >= "3.6"
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"
argon2-cffi-bindings==21.2.0; python_version >= "3.7"
argon2-cffi==21.3.0; python_version >= "3.7"
astroid==2.9.3; python_full_version >= "3.6.2"
asttokens==2.0.5; python_version >= "3.8"
astunparse==1.6.3
async-timeout==3.0.1; python_full_version >= "3.5.3" and python_version >= "3.6"
atomicwrites==1.4.0; 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.4.0"
attrs==21.4.0; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "4.0" or python_full_version >= "3.5.0" and python_version >= "3.6" and python_version < "4.0"
attrs==21.4.0; python_full_version >= "3.7.0" and python_version >= "3.6" and python_version < "4.0"
babel==2.9.1; python_full_version >= "3.6.8" and python_full_version < "4.0.0" and python_version >= "3.6" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6")
backcall==0.2.0; 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.1; python_version >= "3.5"
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.5"
beautifulsoup4==4.10.0; python_full_version >= "3.6.8" and python_full_version < "4.0.0" and python_version >= "3.5"
black==21.7b0; python_full_version >= "3.6.2"
bleach==4.1.0; python_version >= "3.7"
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")
cachetools==5.0.0; python_version >= "3.7" and python_version < "4.0" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6")
certifi==2021.10.8; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0"
cffi==1.15.0; implementation_name == "pypy" and python_version >= "3.6"
certifi==2021.10.8; python_full_version >= "3.7.1" and python_version >= "3.6" 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.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.6.0") and (python_version >= "3" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3")
cffi==1.15.0; implementation_name == "pypy" and python_version >= "3.7" and python_full_version >= "3.7.0"
cfgv==3.3.1; python_full_version >= "3.6.1"
chardet==4.0.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6"
charset-normalizer==2.0.10; python_full_version >= "3.6.0" and python_version >= "3"
charset-normalizer==2.0.10; python_full_version >= "3.7.1" and python_version >= "3.6" 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.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.6.0") and (python_version >= "3" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3")
click==8.0.3; python_full_version >= "3.6.2" and python_version >= "3.6"
codespell==2.1.0; python_version >= "3.5"
colorama==0.4.4; python_full_version >= "3.6.8" and python_full_version < "4.0.0" 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.6" and (python_version >= "3.5" and python_full_version < "3.0.0" and platform_system == "Windows" or platform_system == "Windows" and python_version >= "3.5" 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.8" and python_full_version < "4.0.0" 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.6" and (python_version >= "3.5" and python_full_version < "3.0.0" and platform_system == "Windows" or platform_system == "Windows" and python_version >= "3.5" 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" 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")
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.2; python_version >= "3.6"
cryptography==36.0.1; python_version >= "3.6"
cssselect==1.1.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0"
cvxpy==1.1.18; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.6"
cycler==0.11.0; python_version >= "3.7"
cycler==0.11.0; python_full_version >= "3.6.8" and python_full_version < "4.0.0" and python_version >= "3.7"
cython==0.29.26; python_version >= "3.6" and python_full_version < "3.0.0" and sys_platform == "darwin" or python_full_version >= "3.3.0" and sys_platform == "darwin" and python_version >= "3.6"
dateparser==1.1.0; python_version >= "3.5"
datetime==4.3; python_version >= "3.5"
@@ -53,7 +53,7 @@ distlib==0.3.4; python_full_version >= "3.6.1"
dnspython==2.2.0; python_version >= "3.6" and python_version < "4.0"
docutils==0.16; python_full_version >= "3.6.8" and python_full_version < "4.0.0" and python_version >= "3.6" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6")
ecos==2.0.10; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.6"
entrypoints==0.3; python_full_version >= "3.6.1" and python_version >= "3.7"
entrypoints==0.3; python_full_version >= "3.7.0" and python_version >= "3.7"
et-xmlfile==1.1.0; python_version >= "3.6"
exchange-calendars==3.5.1; python_version >= "3.7" and python_full_version >= "3.7.0"
executing==0.8.2; python_version >= "3.8"
@@ -65,7 +65,7 @@ finviz==1.4.3
finvizfinance==0.9.10; 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")
flatbuffers==2.0
fonttools==4.28.5; python_version >= "3.7"
fonttools==4.28.5; python_full_version >= "3.6.8" and python_full_version < "4.0.0" and python_version >= "3.7"
fred==3.1
fredapi==0.4.3
frozendict==2.2.0; python_version >= "3.6"
@@ -82,7 +82,7 @@ h5py==3.6.0; python_version >= "3.7"
hijri-converter==2.2.2; python_version >= "3.6"
holidays==0.11.3.1; python_version >= "3.6"
identify==2.4.4; python_full_version >= "3.6.1"
idna==3.3; python_full_version >= "3.6.2" and python_version >= "3.7"
idna==3.3; python_full_version >= "3.7.1" and python_version >= "3.7" 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.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.6.0") and (python_version >= "3" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3")
imagesize==1.3.0; python_full_version >= "3.6.8" and python_full_version < "4.0.0" and python_version >= "3.6"
importlib-metadata==4.10.1; python_version < "3.10" and python_version >= "3.7"
inflection==0.5.1; python_version >= "3.6"
@@ -90,19 +90,19 @@ iniconfig==1.1.1; python_version >= "3.6"
investpy==1.0.7; python_version >= "3"
ipykernel==6.7.0; python_version >= "3.7"
ipympl==0.8.7
ipython-genutils==0.2.0; python_version >= "3.7"
ipython-genutils==0.2.0; python_full_version >= "3.7.0" and python_version >= "3.7"
ipython==8.0.1; python_version >= "3.8"
ipywidgets==7.6.5
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_full_version >= "3.6.8" and python_full_version < "4.0.0" and 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.6"
jsonschema==3.2.0
jupyter-client==7.1.2; python_full_version >= "3.7.0" and python_version >= "3.7"
jupyter-console==6.4.0; python_version >= "3.6"
jupyter-core==4.9.1; python_full_version >= "3.6.1" and python_version >= "3.7"
jupyter-core==4.9.1; python_full_version >= "3.7.0" and python_version >= "3.7"
jupyter-server==1.13.4; python_version >= "3.7"
jupyter==1.0.0
jupyterlab-pygments==0.1.2; python_version >= "3.7"
@@ -111,7 +111,7 @@ jupyterlab-widgets==1.0.2; python_version >= "3.6"
jupyterlab==3.2.8; python_version >= "3.6"
keras-preprocessing==1.1.2
keras==2.7.0
kiwisolver==1.3.2; python_version >= "3.7"
kiwisolver==1.3.2; python_full_version >= "3.6.8" and python_full_version < "4.0.0" and 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"
libclang==11.1.0
@@ -119,7 +119,7 @@ lxml==4.7.1; python_full_version >= "3.6.8" and python_version >= "3.5" and pyth
m2r2==0.2.8; python_full_version >= "3.6.8" and python_full_version < "4.0.0"
markdown-it-py==1.1.0; python_version >= "3.6" and python_version < "4.0"
markdown==3.3.6; python_version >= "3.6"
markupsafe==2.0.1; python_version >= "3.6"
markupsafe==2.0.1; python_full_version >= "3.6.8" and python_full_version < "4.0.0" and python_version >= "3.7"
matplotlib-inline==0.1.3; python_version >= "3.8"
matplotlib==3.5.1; python_version >= "3.7"
mccabe==0.6.1; python_full_version >= "3.6.2"
@@ -151,7 +151,7 @@ packaging==21.3; python_full_version >= "3.6.8" and python_full_version < "4.0.0
pandas-datareader==0.10.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6"
pandas-market-calendars==3.2; python_full_version >= "3.7.0"
pandas-ta==0.3.14b
pandas==1.4.0; python_version >= "3.8"
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.3; python_version >= "3.6"
parso==0.8.3; python_version >= "3.8"
@@ -174,13 +174,13 @@ protobuf==3.19.3; python_full_version >= "3.7.1" and python_full_version < "4.0.
psaw==0.0.12; python_version >= "3"
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.6" and python_full_version < "3.0.0" and implementation_name == "pypy" or python_full_version >= "3.5.0" and python_version >= "3.6" and implementation_name == "pypy"
py==1.11.0; python_full_version >= "3.7.0" and python_version >= "3.7" and implementation_name == "pypy"
pyally==1.1.2
pyasn1-modules==0.2.8; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6"
pyasn1==0.4.8; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "4" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6") or python_full_version >= "3.6.0" and python_version >= "3.6" and python_version < "4" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6")
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"
pycparser==2.21; implementation_name == "pypy" and python_version >= "3.7" and python_full_version >= "3.7.0"
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"
@@ -191,7 +191,7 @@ pymongo==3.11.0; (python_version >= "2.7" and python_full_version < "3.0.0") or
pyobjc-core==8.1; python_version >= "3.6" and sys_platform == "darwin"
pyobjc-framework-cocoa==8.1; python_version >= "3.6" and sys_platform == "darwin"
pyotp==2.6.0; python_version >= "3"
pyparsing==3.0.7; python_version >= "3.7"
pyparsing==3.0.7; python_full_version >= "3.6.8" and python_full_version < "4.0.0" and python_version >= "3.7"
pyportfolioopt==1.5.1; 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"
@@ -200,16 +200,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.0" and python_version >= "3.8" and (python_version >= "3.8" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.8") 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")
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.5" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.5")
python-dotenv==0.19.2; python_version >= "3.5"
pytrends==4.7.3
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==2021.3; python_version >= "3.8" and python_full_version >= "3.7.0" and python_full_version < "4.0.0"
pytz==2021.3; python_full_version >= "3.7.1" and python_version >= "3.7" and python_full_version < "4.0.0" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6")
pyupgrade==2.31.0; python_full_version >= "3.6.1"
pywin32==303; sys_platform == "win32" and platform_python_implementation != "PyPy" and python_version >= "3.6"
pywinpty==1.1.6; os_name == "nt" and python_version >= "3.6"
pywin32==303; sys_platform == "win32" and platform_python_implementation != "PyPy" and python_version >= "3.7" and python_full_version >= "3.7.0"
pywinpty==1.1.6; os_name == "nt" and python_version >= "3.7"
pyyaml==6.0; python_version >= "3.6" 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.6"
qtconsole==5.2.2; python_version >= "3.6"
qtpy==2.0.0; python_version >= "3.6"
@@ -223,15 +223,15 @@ 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"
rsa==4.8; python_version >= "3.6" and python_version < "4" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6")
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.7.3; python_version >= "3.7" 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.7.3; python_version >= "3.7" 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.1.0; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.6"
seaborn==0.11.2; python_version >= "3.6"
selenium==3.141.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.6" and python_full_version < "4.0.0" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.6") and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.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.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6") and (python_version >= "3.8" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.8")
setuptools-scm==6.4.2; python_full_version >= "3.6.8" and python_full_version < "4.0.0" and 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.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.6") and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.3.0") and (python_version >= "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.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6") and (python_version >= "3.8" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.8")
smmap==5.0.0; python_version >= "3.7"
sniffio==1.2.0; python_full_version >= "3.6.2" and python_version >= "3.7"
snowballstemmer==2.2.0; python_full_version >= "3.6.8" and python_full_version < "4.0.0" and python_version >= "3.6"
@@ -263,12 +263,12 @@ terminado==0.12.1; python_version >= "3.7"
testpath==0.5.0; python_version >= "3.7"
textwrap3==0.9.2; python_version >= "3.6"
thepassiveinvestor==1.0.10
threadpoolctl==3.0.0; python_version >= "3.7"
threadpoolctl==3.0.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.1"
toml==0.10.2; python_full_version >= "3.6.2" and python_version >= "3.6" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.6")
tomli==1.2.3; python_full_version >= "3.6.2" and python_version >= "3.7"
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"
tornado==6.1; python_full_version >= "3.7.0" and python_version >= "3.7"
tqdm==4.62.3; 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"
@@ -285,14 +285,14 @@ tzlocal==4.1; python_version >= "3.6"
ujson==5.1.0; python_version >= "3.7"
unidecode==1.3.2; python_version >= "3.5"
update-checker==0.18.0; python_version >= "3.6" and python_version < "4.0"
urllib3==1.26.8; 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"
urllib3==1.26.8; python_full_version >= "3.7.1" and python_version < "4" and python_version >= "3.6" 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.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.6.0") and (python_version >= "3" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3")
user-agent==0.1.10
vadersentiment==3.3.2
valinvest==0.0.2; python_version >= "3.6"
vcrpy==4.1.1; python_version >= "3.5"
virtualenv==20.13.0; python_full_version >= "3.6.1"
voila==0.3.0; python_version >= "3.6"
wcwidth==0.2.5; python_full_version >= "3.6.2" and python_version >= "3.6"
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.2.3; python_version >= "3.8" and python_version < "4.0"
websockets==9.1; python_full_version >= "3.6.1" and python_version >= "3.6"

64
requirements.txt vendored
View File

@@ -5,32 +5,32 @@ ansiwrap==0.8.4; python_version >= "3.6"
anyio==3.5.0; python_full_version >= "3.6.2" and python_version >= "3.7"
appdirs==1.4.4; python_full_version >= "3.6.2" and python_version >= "3.6"
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"
argon2-cffi-bindings==21.2.0; python_version >= "3.7"
argon2-cffi==21.3.0; python_version >= "3.7"
asttokens==2.0.5; python_version >= "3.8"
async-timeout==3.0.1; python_full_version >= "3.5.3" and python_version >= "3.6"
attrs==21.4.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6"
attrs==21.4.0; python_full_version >= "3.7.0" and python_version >= "3.6"
babel==2.9.1; python_full_version >= "3.6.8" and python_full_version < "4.0.0" and python_version >= "3.6" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6")
backcall==0.2.0; 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")
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.5"
beautifulsoup4==4.10.0; python_full_version >= "3.6.8" and python_full_version < "4.0.0" and python_version >= "3.5"
black==21.7b0; python_full_version >= "3.6.2"
bleach==4.1.0; python_version >= "3.7"
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"
cffi==1.15.0; implementation_name == "pypy" and python_version >= "3.6"
certifi==2021.10.8; python_full_version >= "3.7.1" and python_version >= "3.6" 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.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.6.0") and (python_version >= "3" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3")
cffi==1.15.0; implementation_name == "pypy" and python_version >= "3.7" and python_full_version >= "3.7.0"
chardet==4.0.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6"
charset-normalizer==2.0.10; python_full_version >= "3.6.0" and python_version >= "3"
charset-normalizer==2.0.10; python_full_version >= "3.7.1" and python_version >= "3.6" 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.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.6.0") and (python_version >= "3" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3")
click==8.0.3; python_full_version >= "3.6.2" and python_version >= "3.6"
colorama==0.4.4; python_full_version >= "3.6.8" and python_full_version < "4.0.0" and sys_platform == "win32" and python_version >= "3.6" 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.8" and python_full_version < "4.0.0" and sys_platform == "win32" and python_version >= "3.6" 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" 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")
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"
cryptography==36.0.1; python_version >= "3.6"
cssselect==1.1.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0"
cvxpy==1.1.18; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.6"
cycler==0.11.0; python_version >= "3.7"
cycler==0.11.0; python_full_version >= "3.6.8" and python_full_version < "4.0.0" and python_version >= "3.7"
cython==0.29.26; python_version >= "3.6" and python_full_version < "3.0.0" and sys_platform == "darwin" or python_full_version >= "3.3.0" and sys_platform == "darwin" and python_version >= "3.6"
dateparser==1.1.0; python_version >= "3.5"
datetime==4.3; python_version >= "3.5"
@@ -43,7 +43,7 @@ detecta==0.0.5; python_version >= "3.6"
dnspython==2.2.0; python_version >= "3.6" and python_version < "4.0"
docutils==0.16; python_full_version >= "3.6.8" and python_full_version < "4.0.0" and python_version >= "3.6"
ecos==2.0.10; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.6"
entrypoints==0.3; python_full_version >= "3.6.1" and python_version >= "3.7"
entrypoints==0.3; python_full_version >= "3.7.0" and python_version >= "3.7"
et-xmlfile==1.1.0; python_version >= "3.6"
executing==0.8.2; python_version >= "3.8"
fear-greed-index==0.1.3; python_full_version >= "3.6.8" and python_full_version < "4.0.0"
@@ -51,7 +51,7 @@ ffn==0.3.6; python_version >= "2.7" and python_full_version < "3.0.0" or python_
financedatabase==1.0.2
finviz==1.4.3
finvizfinance==0.9.10; python_version >= "3.5"
fonttools==4.28.5; python_version >= "3.7"
fonttools==4.28.5; python_full_version >= "3.6.8" and python_full_version < "4.0.0" and python_version >= "3.7"
fred==3.1
fredapi==0.4.3
frozendict==2.2.0; python_version >= "3.6"
@@ -62,35 +62,35 @@ gitpython==3.1.26; python_version >= "3.7"
grpcio==1.43.0; python_full_version >= "3.7.1" and python_full_version < "4.0.0" and python_version >= "3.6"
hijri-converter==2.2.2; python_version >= "3.6"
holidays==0.11.3.1; python_version >= "3.6"
idna==3.3; python_full_version >= "3.6.2" and python_version >= "3.7"
idna==3.3; python_full_version >= "3.7.1" and python_version >= "3.7" 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.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.6.0") and (python_version >= "3" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3")
imagesize==1.3.0; python_full_version >= "3.6.8" and python_full_version < "4.0.0" and python_version >= "3.6"
inflection==0.5.1; python_version >= "3.6"
investpy==1.0.7; python_version >= "3"
ipykernel==6.7.0; python_version >= "3.7"
ipympl==0.8.7
ipython-genutils==0.2.0; python_version >= "3.7"
ipython-genutils==0.2.0; python_full_version >= "3.7.0" and python_version >= "3.7"
ipython==8.0.1; python_version >= "3.8"
ipywidgets==7.6.5
iso8601==0.1.16
jedi==0.18.1; python_version >= "3.8"
jinja2==3.0.3; python_full_version >= "3.6.8" and python_full_version < "4.0.0" and 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.6"
jsonschema==3.2.0
jupyter-client==7.1.2; python_full_version >= "3.7.0" and python_version >= "3.7"
jupyter-console==6.4.0; python_version >= "3.6"
jupyter-core==4.9.1; python_full_version >= "3.6.1" and python_version >= "3.7"
jupyter-core==4.9.1; python_full_version >= "3.7.0" and python_version >= "3.7"
jupyter-server==1.13.4; python_version >= "3.7"
jupyter==1.0.0
jupyterlab-pygments==0.1.2; python_version >= "3.7"
jupyterlab-server==2.10.3; python_version >= "3.6"
jupyterlab-widgets==1.0.2; python_version >= "3.6"
jupyterlab==3.2.8; python_version >= "3.6"
kiwisolver==1.3.2; python_version >= "3.7"
kiwisolver==1.3.2; python_full_version >= "3.6.8" and python_full_version < "4.0.0" and python_version >= "3.7"
korean-lunar-calendar==0.2.1; python_version >= "3.6"
lxml==4.7.1; python_full_version >= "3.6.8" and python_version >= "3.5" and python_full_version < "4.0.0" and (python_version >= "3" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3") and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6")
m2r2==0.2.8; python_full_version >= "3.6.8" and python_full_version < "4.0.0"
markupsafe==2.0.1; python_version >= "3.6"
markupsafe==2.0.1; python_full_version >= "3.6.8" and python_full_version < "4.0.0" and python_version >= "3.7"
matplotlib-inline==0.1.3; python_version >= "3.8"
matplotlib==3.5.1; python_version >= "3.7"
mistune==0.8.4; python_full_version >= "3.6.8" and python_full_version < "4.0.0" and python_version >= "3.7"
@@ -115,7 +115,7 @@ osqp==0.6.2.post5; python_full_version >= "3.6.1" and python_full_version < "4.0
packaging==21.3; python_full_version >= "3.6.8" and python_full_version < "4.0.0" and python_version >= "3.7"
pandas-datareader==0.10.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6"
pandas-ta==0.3.14b
pandas==1.4.0; python_version >= "3.8"
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.3; python_version >= "3.6"
parso==0.8.3; python_version >= "3.8"
@@ -134,10 +134,10 @@ protobuf==3.19.3; python_full_version >= "3.7.1" and python_full_version < "4.0.
psaw==0.0.12; python_version >= "3"
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.6" and python_full_version < "3.0.0" and implementation_name == "pypy" or implementation_name == "pypy" and python_version >= "3.6" and python_full_version >= "3.5.0"
py==1.11.0; implementation_name == "pypy" and python_version >= "3.7" and python_full_version >= "3.7.0"
pyally==1.1.2
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"
pycparser==2.21; implementation_name == "pypy" and python_version >= "3.7" and python_full_version >= "3.7.0"
pyex==0.5.0
pygments==2.11.2; python_version >= "3.5"
pymeeus==0.5.11; python_version >= "3.7" and python_version < "4"
@@ -145,21 +145,21 @@ pymongo==3.11.0; (python_version >= "2.7" and python_full_version < "3.0.0") or
pyobjc-core==8.1; python_version >= "3.6" and sys_platform == "darwin"
pyobjc-framework-cocoa==8.1; python_version >= "3.6" and sys_platform == "darwin"
pyotp==2.6.0; python_version >= "3"
pyparsing==3.0.7; python_version >= "3.7"
pyparsing==3.0.7; python_full_version >= "3.6.8" and python_full_version < "4.0.0" and python_version >= "3.7"
pyportfolioopt==1.5.1; 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"
python-binance==1.0.15
python-coinmarketcap==0.2
python-dateutil==2.8.2; python_full_version >= "3.6.1" and python_version >= "3.8"
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.5" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.5")
python-dotenv==0.19.2; python_version >= "3.5"
pytrends==4.7.3
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==2021.3; python_full_version >= "3.6.8" and python_full_version < "4.0.0" and python_version >= "3.8"
pywin32==303; sys_platform == "win32" and platform_python_implementation != "PyPy" and python_version >= "3.6"
pywinpty==1.1.6; os_name == "nt" and python_version >= "3.6"
pytz==2021.3; python_full_version >= "3.7.1" and python_version >= "3.6" and python_full_version < "4.0.0" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6")
pywin32==303; sys_platform == "win32" and platform_python_implementation != "PyPy" and python_version >= "3.7" and python_full_version >= "3.7.0"
pywinpty==1.1.6; os_name == "nt" and python_version >= "3.7"
pyyaml==6.0; python_version >= "3.6"
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.6"
qtconsole==5.2.2; python_version >= "3.6"
qtpy==2.0.0; python_version >= "3.6"
@@ -172,15 +172,15 @@ requests==2.27.1; (python_version >= "2.7" and python_full_version < "3.0.0") or
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"
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.7.3; python_version >= "3.7" 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.7.3; python_version >= "3.7" 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.1.0; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.6"
seaborn==0.11.2; python_version >= "3.6"
selenium==3.141.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.6" and python_full_version < "4.0.0" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.6") and (python_version >= "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")
setuptools-scm==6.4.2; python_full_version >= "3.6.8" and python_full_version < "4.0.0" and 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.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.6") and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.3.0") and (python_version >= "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")
smmap==5.0.0; python_version >= "3.7"
sniffio==1.2.0; python_full_version >= "3.6.2" and python_version >= "3.7"
snowballstemmer==2.2.0; python_full_version >= "3.6.8" and python_full_version < "4.0.0" and python_version >= "3.6"
@@ -204,9 +204,9 @@ terminado==0.12.1; python_version >= "3.7"
testpath==0.5.0; python_version >= "3.7"
textwrap3==0.9.2; python_version >= "3.6"
thepassiveinvestor==1.0.10
threadpoolctl==3.0.0; python_version >= "3.7"
threadpoolctl==3.0.0; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.7"
tomli==1.2.3; python_full_version >= "3.6.2" and python_version >= "3.7"
tornado==6.1; python_full_version >= "3.6.1" and python_version >= "3.7"
tornado==6.1; python_full_version >= "3.7.0" and python_version >= "3.7"
tqdm==4.62.3; 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"
@@ -216,12 +216,12 @@ tzlocal==4.1; python_version >= "3.6"
ujson==5.1.0; python_version >= "3.7"
unidecode==1.3.2; python_version >= "3.5"
update-checker==0.18.0; python_version >= "3.6" and python_version < "4.0"
urllib3==1.26.8; 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"
urllib3==1.26.8; python_full_version >= "3.7.1" and python_version < "4" and python_version >= "3.6" 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.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.6.0") and (python_version >= "3" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3")
user-agent==0.1.10
vadersentiment==3.3.2
valinvest==0.0.2; python_version >= "3.6"
voila==0.3.0; python_version >= "3.6"
wcwidth==0.2.5; python_full_version >= "3.6.2" and python_version >= "3.6"
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.2.3; python_version >= "3.8" and python_version < "4.0"
websockets==9.1; python_full_version >= "3.6.1" and python_version >= "3.6"

View File

@@ -0,0 +1,193 @@
import os
import pytest
from gamestonk_terminal.portfolio import portfolio_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.portfolio.portfolio_controller"
# MOCK SWITCH
mocker.patch(
target=f"{path_controller}.PortfolioController.switch",
return_value=["quit"],
)
result_menu = portfolio_controller.PortfolioController(queue=queue).menu()
assert result_menu == expected
@pytest.mark.vcr(record_mode="none")
def test_menu_without_queue_completion(mocker):
path_controller = "gamestonk_terminal.portfolio.portfolio_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=portfolio_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 = portfolio_controller.PortfolioController(queue=None).menu()
assert result_menu == []
@pytest.mark.vcr(record_mode="none")
@pytest.mark.parametrize(
"mock_input",
["help", "homee help", "home help", "mock"],
)
def test_menu_without_queue_sys_exit(mock_input, mocker):
path_controller = "gamestonk_terminal.portfolio.portfolio_controller"
# DISABLE AUTO-COMPLETION
mocker.patch.object(
target=portfolio_controller.gtff,
attribute="USE_PROMPT_TOOLKIT",
new=False,
)
mocker.patch(
target=f"{path_controller}.session",
return_value=None,
)
# MOCK USER INPUT
mocker.patch("builtins.input", return_value=mock_input)
# MOCK SWITCH
class SystemExitSideEffect:
def __init__(self):
self.first_call = True
def __call__(self, *args, **kwargs):
if self.first_call:
self.first_call = False
raise SystemExit()
return ["quit"]
mock_switch = mocker.Mock(side_effect=SystemExitSideEffect())
mocker.patch(
target=f"{path_controller}.PortfolioController.switch",
new=mock_switch,
)
result_menu = portfolio_controller.PortfolioController(queue=None).menu()
assert result_menu == []
@pytest.mark.vcr(record_mode="none")
@pytest.mark.record_stdout
def test_print_help():
controller = portfolio_controller.PortfolioController(queue=None)
controller.print_help()
@pytest.mark.vcr(record_mode="none")
@pytest.mark.parametrize(
"an_input, expected_queue",
[
("", []),
("/help", ["quit", "help"]),
("help/help", ["help"]),
("q", ["quit"]),
("h", []),
(
"r",
[
"quit",
"reset",
"portfolio",
],
),
],
)
def test_switch(an_input, expected_queue):
controller = portfolio_controller.PortfolioController(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 = portfolio_controller.PortfolioController(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"],
),
("call_exit", ["help"], ["quit", "quit", "help"]),
("call_home", [], ["quit"]),
("call_help", [], []),
("call_quit", [], ["quit"]),
("call_quit", ["help"], ["quit", "help"]),
(
"call_reset",
[],
[
"quit",
"reset",
"portfolio",
],
),
(
"call_reset",
["help"],
[
"quit",
"reset",
"portfolio",
"help",
],
),
],
)
def test_call_func_expect_queue(expected_queue, func, queue):
controller = portfolio_controller.PortfolioController(queue=queue)
result = getattr(controller, func)([])
assert result is None
assert controller.queue == expected_queue

View File

@@ -0,0 +1,20 @@
> bro brokers holdings, supports: robinhood, ally, degiro, coinbase
> po portfolio optimization, optimal portfolio weights from pyportfolioopt
> pa portfolio analysis, analyse portfolios
Portfolio:
load load data into the portfolio
save save your portfolio for future use
show show existing transactions
add add a security to your portfolio
rmv remove a security from your portfolio
Reports:
ar annual report for performance of a given portfolio
Graphs:
rmr graph your returns versus the market's returns
al displays the allocation of the portfolio
mdd display portfolio drawdown

10
website/content/portfolio/mdd/_index.md vendored Normal file
View File

@@ -0,0 +1,10 @@
```
usage: mdd [-h] [--export {png,jpg,pdf,svg}]
```
Show portfolio drawdown
```optional arguments:
-h, --help show this help message (default: False)
--export {png,jpg,pdf,svg}
Export figure into png, jpg, pdf, svg (default: )
```

View File

@@ -1126,6 +1126,8 @@ main:
ref: "/portfolio/ar"
- name: rmr
ref: "/portfolio/rmr"
- name: mdd
ref: "portfolio/mdd"
- name: forex
ref: "/forex"
sub: