diff --git a/gamestonk_terminal/common/quantitative_analysis/qa_model.py b/gamestonk_terminal/common/quantitative_analysis/qa_model.py index 6da7f893311..0c1a8900aad 100644 --- a/gamestonk_terminal/common/quantitative_analysis/qa_model.py +++ b/gamestonk_terminal/common/quantitative_analysis/qa_model.py @@ -3,10 +3,11 @@ __docformat__ = "numpy" import logging import warnings -from typing import Any, Tuple +from typing import Any, Tuple, Union, List import pandas as pd import statsmodels.api as sm from scipy import stats +import numpy as np from statsmodels.tsa.seasonal import seasonal_decompose from statsmodels.tsa.stattools import adfuller, kpss @@ -193,9 +194,10 @@ def calculate_adjusted_var( # Derived from Cornish-Fisher-Expansion # Formula for quantile from "Finance Compact Plus" by Zimmerman; Part 1, page 130-131 # More material/resources: - # "Numerical Methods and Optimization in Finance" by Gilli, Maringer & Schumann; - # https://www.value-at-risk.net/the-cornish-fisher-expansion/; - # "Risk Management and Financial Institutions" by John C. Hull + # - "Numerical Methods and Optimization in Finance" by Gilli, Maringer & Schumann; + # - https://www.value-at-risk.net/the-cornish-fisher-expansion/; + # - https://www.diva-portal.org/smash/get/diva2:442078/FULLTEXT01.pdf, Section 2.4.2, p.18; + # - "Risk Management and Financial Institutions" by John C. Hull skew_component = skew / 6 * (ndp**2 - 1) ** 2 - skew**2 / 36 * ndp * ( 2 * ndp**2 - 5 @@ -207,19 +209,30 @@ def calculate_adjusted_var( return real_return -def get_var(data: pd.DataFrame, use_mean: bool, adjusted_var: bool, percentile: int): +def get_var( + data: pd.DataFrame, + use_mean: bool, + adjusted_var: bool, + student_t: bool, + percentile: Union[int, float], + portfolio: bool, +): """Gets value at risk for specified stock dataframe Parameters ---------- data: pd.DataFrame - Dataframe of a stock + Dataframe of a stock/portfolio use_mean: bool If one should use the stocks mean for calculation adjusted_var: bool If one should return VaR adjusted for skew and kurtosis - percentile: int + student_t: bool + If one should use the student-t distribution + percentile: Union[int,float] VaR percentile + portfolio: bool + If the data is a portfolio Returns ------- @@ -228,8 +241,13 @@ def get_var(data: pd.DataFrame, use_mean: bool, adjusted_var: bool, percentile: list list of historical VaR """ - data = data[["adjclose"]].copy() - data.loc[:, "return"] = data.adjclose.pct_change() + if not portfolio: + data = data[["adjclose"]].copy() + data.loc[:, "return"] = data.adjclose.pct_change() + data_return = data["return"] + else: + data = data[1:].copy() + data_return = data # Distribution percentages percentile_90 = -1.282 @@ -239,22 +257,22 @@ def get_var(data: pd.DataFrame, use_mean: bool, adjusted_var: bool, percentile: # Mean if use_mean: - mean = data["return"].mean() + mean = data_return.mean() else: mean = 0 # Standard Deviation - std = data["return"].std(axis=0) + std = data_return.std(axis=0) if adjusted_var: # Kurtosis # Measures height and sharpness of the central peak relative to that of a standard bell curve - k = data["return"].kurtosis(axis=0) + k = data_return.kurtosis(axis=0) # Skewness # Measure of the asymmetry of the probability distribution of a random variable about its mean - s = data["return"].skew(axis=0) + s = data_return.skew(axis=0) # Adjusted VaR var_90 = calculate_adjusted_var(k, s, percentile_90, std, mean) @@ -262,21 +280,192 @@ def get_var(data: pd.DataFrame, use_mean: bool, adjusted_var: bool, percentile: var_99 = calculate_adjusted_var(k, s, percentile_99, std, mean) var_custom = calculate_adjusted_var(k, s, percentile_custom, std, mean) + elif student_t: + # Calculating VaR based on the Student-t distribution + + # Fitting student-t parameters to the data + v, _, _ = stats.t.fit(data_return.fillna(0)) + if not use_mean: + mean = 0 + var_90 = np.sqrt((v - 2) / v) * stats.t.ppf(0.1, v) * std + mean + var_95 = np.sqrt((v - 2) / v) * stats.t.ppf(0.05, v) * std + mean + var_99 = np.sqrt((v - 2) / v) * stats.t.ppf(0.01, v) * std + mean + var_custom = np.sqrt((v - 2) / v) * stats.t.ppf(1 - percentile, v) * std + mean + else: # Regular Var - var_90 = 2.7182818 ** (mean + percentile_90 * std) - 1 - var_95 = 2.7182818 ** (mean + percentile_95 * std) - 1 - var_99 = 2.7182818 ** (mean + percentile_99 * std) - 1 - var_custom = 2.7182818 ** (mean + percentile_custom * std) - 1 + var_90 = np.exp(mean + percentile_90 * std) - 1 + var_95 = np.exp(mean + percentile_95 * std) - 1 + var_99 = np.exp(mean + percentile_99 * std) - 1 + var_custom = np.exp(mean + percentile_custom * std) - 1 - data.sort_values("return", inplace=True, ascending=True) + if not portfolio: + data.sort_values("return", inplace=True, ascending=True) + data_return = data["return"] + else: + data.sort_values(inplace=True, ascending=True) + data_return = data # Historical VaR - hist_var_90 = data["return"].quantile(0.1) - hist_var_95 = data["return"].quantile(0.05) - hist_var_99 = data["return"].quantile(0.01) - hist_var_custom = data["return"].quantile(1 - percentile) + hist_var_90 = data_return.quantile(0.1) + hist_var_95 = data_return.quantile(0.05) + hist_var_99 = data_return.quantile(0.01) + hist_var_custom = data_return.quantile(1 - percentile) var_list = [var_90, var_95, var_99, var_custom] hist_var_list = [hist_var_90, hist_var_95, hist_var_99, hist_var_custom] return var_list, hist_var_list + + +def get_es( + data: pd.DataFrame, + use_mean: bool, + distribution: str, + percentile: Union[float, int], + portfolio: bool, +) -> Tuple[List[float], List[float]]: + """Gets Expected Shortfall for specified stock dataframe + + Parameters + ---------- + data: pd.DataFrame + Dataframe of a stock + use_mean: bool + If one should use the stocks mean for calculation + distribution: str + Type of distribution, options: laplace, student_t, normal + percentile: Union[float,int] + VaR percentile + portfolio: bool + If the data is a portfolio + + Returns + ------- + list + list of ES + list + list of historical ES + """ + if not portfolio: + data = data[["adjclose"]].copy() + data.loc[:, "return"] = data.adjclose.pct_change() + data_return = data["return"] + else: + data = data[1:].copy() + data_return = data + + # Distribution percentages + percentile_90 = -1.282 + percentile_95 = -1.645 + percentile_99 = -2.326 + percentile_custom = stats.norm.ppf(1 - percentile) + + # Mean + if use_mean: + mean = data_return.mean() + else: + mean = 0 + + # Standard Deviation + std = data_return.std(axis=0) + + if distribution == "laplace": + # Calculating ES based on Laplace distribution + # For formula see: https://en.wikipedia.org/wiki/Expected_shortfall#Laplace_distribution + + # Fitting b (scale parameter) to the variance of the data + # Since variance of the Laplace dist.: var = 2*b**2 + # Thus: + b = np.sqrt(std**2 / 2) + + # Calculation + es_90 = -b * (1 - np.log(2 * 0.1)) + mean + es_95 = -b * (1 - np.log(2 * 0.05)) + mean + es_99 = -b * (1 - np.log(2 * 0.01)) + mean + + if (1 - percentile) < 0.5: + es_custom = -b * (1 - np.log(2 * (1 - percentile))) + mean + else: + es_custom = 0 + + elif distribution == "student_t": + # Calculating ES based on the Student-t distribution + + # Fitting student-t parameters to the data + v, _, scale = stats.t.fit(data_return.fillna(0)) + if not use_mean: + mean = 0 + + # Student T Distribution percentages + percentile_90 = stats.t.ppf(0.1, v) + percentile_95 = stats.t.ppf(0.05, v) + percentile_99 = stats.t.ppf(0.01, v) + percentile_custom = stats.t.ppf(1 - percentile, v) + + # Calculation + es_90 = ( + -scale + * (v + percentile_90**2) + / (v - 1) + * stats.t.pdf(percentile_90, v) + / 0.1 + + mean + ) + es_95 = ( + -scale + * (v + percentile_95**2) + / (v - 1) + * stats.t.pdf(percentile_95, v) + / 0.05 + + mean + ) + es_99 = ( + -scale + * (v + percentile_99**2) + / (v - 1) + * stats.t.pdf(percentile_99, v) + / 0.01 + + mean + ) + es_custom = ( + -scale + * (v + percentile_custom**2) + / (v - 1) + * stats.t.pdf(percentile_custom, v) + / (1 - percentile) + + mean + ) + + elif distribution == "logistic": + # Logistic distribution + # For formula see: https://en.wikipedia.org/wiki/Expected_shortfall#Logistic_distribution + + # Fitting s (scale parameter) to the variance of the data + # Since variance of the Logistic dist.: var = s**2*pi**2/3 + # Thus: + s = np.sqrt(3 * std**2 / np.pi**2) + + # Calculation + a = 1 - percentile + es_90 = -s * np.log((0.9 ** (1 - 1 / 0.1)) / 0.1) + mean + es_95 = -s * np.log((0.95 ** (1 - 1 / 0.05)) / 0.05) + mean + es_99 = -s * np.log((0.99 ** (1 - 1 / 0.01)) / 0.01) + mean + es_custom = -s * np.log((percentile ** (1 - 1 / a)) / a) + mean + + else: + # Regular Expected Shortfall + es_90 = std * -stats.norm.pdf(percentile_90) / 0.1 + mean + es_95 = std * -stats.norm.pdf(percentile_95) / 0.05 + mean + es_99 = std * -stats.norm.pdf(percentile_99) / 0.01 + mean + es_custom = std * -stats.norm.pdf(percentile_custom) / (1 - percentile) + mean + + # Historical Expected Shortfall + _, hist_var_list = get_var(data, use_mean, False, False, percentile, portfolio) + hist_es_90 = data_return[data_return <= hist_var_list[0]].mean() + hist_es_95 = data_return[data_return <= hist_var_list[1]].mean() + hist_es_99 = data_return[data_return <= hist_var_list[2]].mean() + hist_es_custom = data_return[data_return <= hist_var_list[3]].mean() + + es_list = [es_90, es_95, es_99, es_custom] + hist_es_list = [hist_es_90, hist_es_95, hist_es_99, hist_es_custom] + return es_list, hist_es_list diff --git a/gamestonk_terminal/common/quantitative_analysis/qa_view.py b/gamestonk_terminal/common/quantitative_analysis/qa_view.py index b6f97ba6699..07284752ce4 100644 --- a/gamestonk_terminal/common/quantitative_analysis/qa_view.py +++ b/gamestonk_terminal/common/quantitative_analysis/qa_view.py @@ -1,6 +1,9 @@ """Quantitative Analysis View""" __docformat__ = "numpy" +# pylint: disable=too-many-lines + + import logging import os import warnings @@ -947,7 +950,13 @@ def display_line( def display_var( - data: pd.DataFrame, use_mean: bool, ticker: str, adjusted_var: bool, percentile: int + data: pd.DataFrame, + ticker: str = "", + use_mean: bool = False, + adjusted_var: bool = False, + student_t: bool = False, + percentile: float = 0.999, + portfolio: bool = False, ): """Displays VaR of dataframe @@ -961,20 +970,32 @@ def display_var( ticker of the stock adjusted_var: bool if one should have VaR adjusted for skew and kurtosis (Cornish-Fisher-Expansion) + student_t: bool + If one should use the student-t distribution percentile: int var percentile + portfolio: bool + If the data is a portfolio """ - var_list, hist_var_list = qa_model.get_var(data, use_mean, adjusted_var, percentile) + var_list, hist_var_list = qa_model.get_var( + data, use_mean, adjusted_var, student_t, percentile, portfolio + ) str_hist_label = "Historical VaR:" if adjusted_var: - str_var_label = "Adjusted Var:" + str_var_label = "Adjusted VaR:" str_title = "Adjusted " + elif student_t: + str_var_label = "Student-t VaR" + str_title = "Student-t " else: str_var_label = "VaR:" str_title = "" + if ticker != "": + ticker += " " + data_dictionary = {str_var_label: var_list, str_hist_label: hist_var_list} data = pd.DataFrame( data_dictionary, index=["90.0%", "95.0%", "99.0%", f"{percentile*100}%"] @@ -984,7 +1005,69 @@ def display_var( data, show_index=True, headers=list(data.columns), - title=f"[bold]{ticker} {str_title}Value at Risk[/bold]", + title=f"[bold]{ticker}{str_title}Value at Risk[/bold]", + floatfmt=".4f", + ) + console.print("") + + +def display_es( + data: pd.DataFrame, + ticker: str = "", + use_mean: bool = False, + distribution: str = "normal", + percentile: float = 0.999, + portfolio: bool = False, +): + """Displays expected shortfall + + Parameters + ---------- + data: pd.DataFrame + stock dataframe + use_mean: + if one should use the stocks mean return + ticker: str + ticker of the stock + distribution: str + choose distribution to use: logistic, laplace, normal + percentile: int + es percentile + portfolio: bool + If the data is a portfolio + """ + es_list, hist_es_list = qa_model.get_es( + data, use_mean, distribution, percentile, portfolio + ) + + str_hist_label = "Historical ES:" + + if distribution == "laplace": + str_es_label = "Laplace ES:" + str_title = "Laplace " + elif distribution == "student_t": + str_es_label = "Student-t ES" + str_title = "Student-t " + elif distribution == "logistic": + str_es_label = "Logistic ES" + str_title = "Logistic " + else: + str_es_label = "ES:" + str_title = "" + + if ticker != "": + ticker += " " + + data_dictionary = {str_es_label: es_list, str_hist_label: hist_es_list} + data = pd.DataFrame( + data_dictionary, index=["90.0%", "95.0%", "99.0%", f"{percentile*100}%"] + ) + + print_rich_table( + data, + show_index=True, + headers=list(data.columns), + title=f"[bold]{ticker}{str_title}Expected Shortfall[/bold]", floatfmt=".4f", ) console.print("") diff --git a/gamestonk_terminal/portfolio/portfolio_controller.py b/gamestonk_terminal/portfolio/portfolio_controller.py index 84f2875869d..69dfed56470 100644 --- a/gamestonk_terminal/portfolio/portfolio_controller.py +++ b/gamestonk_terminal/portfolio/portfolio_controller.py @@ -49,12 +49,15 @@ class PortfolioController(BaseController): "al", "dd", "rolling", + "var", + "es", ] CHOICES_MENUS = [ "bro", "po", "pa", ] + distributions = ["laplace", "student_t", "logistic", "normal"] PATH = "/portfolio/" def __init__(self, queue: List[str] = None): @@ -108,6 +111,10 @@ Loaded:[/info] {self.portfolio_name or None} rmr graph your returns versus the market's returns dd display portfolio drawdown al display allocation to given assets over period[/cmds] + +[info]Risk Metrics:[/info][cmds] + var display value at risk + es display expected shortfall[/cmds] """ # TODO: Clean up the reports inputs # TODO: Edit the allocation to allow the different asset classes @@ -406,6 +413,134 @@ Loaded:[/info] {self.portfolio_name or None} # else: # console.print("Please add items to the portfolio\n") + @log_start_end(log=logger) + def call_var(self, other_args: List[str]): + """Process var command""" + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="var", + description=""" + Provides value at risk (short: VaR) of the selected portfolio. + """, + ) + parser.add_argument( + "-m", + "--mean", + action="store_true", + default=False, + dest="use_mean", + help="If one should use the mean of the portfolio return", + ) + parser.add_argument( + "-a", + "--adjusted", + action="store_true", + default=False, + dest="adjusted", + help=""" + If the VaR should be adjusted for skew and kurtosis (Cornish-Fisher-Expansion) + """, + ) + parser.add_argument( + "-s", + "--student", + action="store_true", + default=False, + dest="student_t", + help=""" + If one should use the student-t distribution + """, + ) + parser.add_argument( + "-p", + "--percentile", + action="store", + dest="percentile", + type=float, + default=99.9, + help=""" + Percentile used for VaR calculations, for example input 99.9 equals a 99.9 Percent VaR + """, + ) + ns_parser = parse_known_args_and_warn(parser, other_args) + if ns_parser: + if self.portfolio.empty: + console.print("[red]No portfolio loaded.[/red]\n") + return + if ns_parser.adjusted and ns_parser.student_t: + console.print("Select the adjusted or the student_t parameter.\n") + else: + from gamestonk_terminal.common.quantitative_analysis import qa_view + + self.portfolio.generate_holdings_from_trades() + qa_view.display_var( + self.portfolio.returns, + "Portfolio", + ns_parser.use_mean, + ns_parser.adjusted, + ns_parser.student_t, + ns_parser.percentile / 100, + True, + ) + + @log_start_end(log=logger) + def call_es(self, other_args: List[str]): + """Process es command""" + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="es", + description=""" + Provides Expected Shortfall (short: ES) of the selected portfolio. + """, + ) + parser.add_argument( + "-m", + "--mean", + action="store_true", + default=False, + dest="use_mean", + help="If one should use the mean of the portfolios return", + ) + parser.add_argument( + "-d", + "--dist", + "--distributions", + dest="distributions", + type=str, + choices=self.distributions, + default="normal", + help="Distribution used for the calculations", + ) + parser.add_argument( + "-p", + "--percentile", + action="store", + dest="percentile", + type=float, + default=99.9, + help=""" + Percentile used for ES calculations, for example input 99.9 equals a 99.9 Percent Expected Shortfall + """, + ) + ns_parser = parse_known_args_and_warn(parser, other_args) + if ns_parser: + from gamestonk_terminal.common.quantitative_analysis import qa_view + + if self.portfolio.empty: + console.print("[red]No portfolio loaded.[/red]\n") + return + self.portfolio.generate_holdings_from_trades() + qa_view.display_es( + self.portfolio.returns, + "Portfolio", + ns_parser.use_mean, + ns_parser.distributions, + ns_parser.percentile / 100, + True, + ) + @log_start_end(log=logger) def call_rmr(self, other_args: List[str]): """Process rmr command""" diff --git a/gamestonk_terminal/portfolio/portfolio_model.py b/gamestonk_terminal/portfolio/portfolio_model.py index fa76bfce592..b2557e03b9f 100644 --- a/gamestonk_terminal/portfolio/portfolio_model.py +++ b/gamestonk_terminal/portfolio/portfolio_model.py @@ -449,6 +449,7 @@ class Portfolio: ] self.benchmark_returns = self.benchmark.pct_change().dropna() + # pylint:disable=no-member @classmethod @log_start_end(log=logger) def from_csv(cls, csv_path: str): @@ -468,9 +469,12 @@ class Portfolio: trades = pd.read_csv(csv_path) # Convert the date to what pandas understands trades.Date = pd.to_datetime(trades.Date) + # Sort by date to make more sense of trades + trades = trades.sort_values(by="Date") # Build the portfolio object return cls(trades) + # pylint:enable=no-member @classmethod @log_start_end(log=logger) def from_custom_inputs_and_weights( diff --git a/gamestonk_terminal/stocks/quantitative_analysis/qa_controller.py b/gamestonk_terminal/stocks/quantitative_analysis/qa_controller.py index c9913e4260b..70b5277b94a 100644 --- a/gamestonk_terminal/stocks/quantitative_analysis/qa_controller.py +++ b/gamestonk_terminal/stocks/quantitative_analysis/qa_controller.py @@ -55,10 +55,12 @@ class QaController(StockBaseController): "unitroot", "capm", "var", + "es", ] stock_interval = [1, 5, 15, 30, 60] stock_sources = ["yf", "av", "iex"] + distributions = ["laplace", "student_t", "logistic", "normal"] PATH = "/stocks/qa/" def __init__( @@ -130,7 +132,8 @@ class QaController(StockBaseController): skew rolling skewness of distribution of prices kurtosis rolling kurtosis of distribution of prices [info]Risk:[/info] - var value at risk + var display value at risk + es display expected shortfall [info]Other:[/info] raw print raw data decompose decomposition in cyclic-trend, season, and residuals of prices @@ -754,6 +757,16 @@ class QaController(StockBaseController): If the VaR should be adjusted for skew and kurtosis (Cornish-Fisher-Expansion) """, ) + parser.add_argument( + "-s", + "--student", + action="store_true", + default=False, + dest="student_t", + help=""" + If one should use the student-t distribution + """, + ) parser.add_argument( "-p", "--percentile", @@ -767,10 +780,66 @@ class QaController(StockBaseController): ) ns_parser = parse_known_args_and_warn(parser, other_args) if ns_parser: - qa_view.display_var( + if ns_parser.adjusted and ns_parser.student_t: + console.print("Select the adjusted or the student_t parameter.\n") + else: + qa_view.display_var( + self.stock, + self.ticker, + ns_parser.use_mean, + ns_parser.adjusted, + ns_parser.student_t, + ns_parser.percentile / 100, + False, + ) + + def call_es(self, other_args: List[str]): + """Process es command""" + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="es", + description=""" + Provides Expected Shortfall (short: ES) of the selected stock. + """, + ) + parser.add_argument( + "-m", + "--mean", + action="store_true", + default=False, + dest="use_mean", + help="If one should use the mean of the stocks return", + ) + parser.add_argument( + "-d", + "--dist", + "--distributions", + dest="distributions", + type=str, + choices=self.distributions, + default="normal", + help="Distribution used for the calculations", + ) + parser.add_argument( + "-p", + "--percentile", + action="store", + dest="percentile", + type=float, + default=99.9, + help=""" + Percentile used for ES calculations, for example input 99.9 equals a 99.9 Percent Expected Shortfall + """, + ) + + ns_parser = parse_known_args_and_warn(parser, other_args) + if ns_parser: + qa_view.display_es( self.stock, - ns_parser.use_mean, self.ticker, - ns_parser.adjusted, + ns_parser.use_mean, + ns_parser.distributions, ns_parser.percentile / 100, + False, ) diff --git a/scripts/test_port.gst b/scripts/test_port.gst index 7af59f0ac13..8c56f5dda23 100644 --- a/scripts/test_port.gst +++ b/scripts/test_port.gst @@ -14,4 +14,6 @@ select aapl,msft,sbux,gme add ge,tsla equal mktcap +es +var exit diff --git a/scripts/test_stocks_qa.gst b/scripts/test_stocks_qa.gst index aac79259066..78dd8fdd18a 100644 --- a/scripts/test_stocks_qa.gst +++ b/scripts/test_stocks_qa.gst @@ -27,4 +27,6 @@ raw decompose cusum capm +var +es exit \ No newline at end of file diff --git a/tests/gamestonk_terminal/portfolio/txt/test_portfolio_controller/test_print_help.txt b/tests/gamestonk_terminal/portfolio/txt/test_portfolio_controller/test_print_help.txt index 78a1402d6fb..6ae2ce98bb4 100644 --- a/tests/gamestonk_terminal/portfolio/txt/test_portfolio_controller/test_print_help.txt +++ b/tests/gamestonk_terminal/portfolio/txt/test_portfolio_controller/test_print_help.txt @@ -17,4 +17,7 @@ Graphs: rmr graph your returns versus the market's returns dd display portfolio drawdown al display allocation to given assets over period - + +Risk Metrics: + var display value at risk + es display expected shortfall \ No newline at end of file diff --git a/tests/gamestonk_terminal/stocks/quantitative_analysis/txt/test_qa_controller/test_print_help.txt b/tests/gamestonk_terminal/stocks/quantitative_analysis/txt/test_qa_controller/test_print_help.txt index c3ef1627390..bc2b6886e63 100644 --- a/tests/gamestonk_terminal/stocks/quantitative_analysis/txt/test_qa_controller/test_print_help.txt +++ b/tests/gamestonk_terminal/stocks/quantitative_analysis/txt/test_qa_controller/test_print_help.txt @@ -23,7 +23,8 @@ Rolling Metrics: skew rolling skewness of distribution of prices kurtosis rolling kurtosis of distribution of prices Risk: - var value at risk + var display value at risk + es display expected shortfall Other: raw print raw data decompose decomposition in cyclic-trend, season, and residuals of prices diff --git a/website/content/common/quantitative_analysis/es/_index.md b/website/content/common/quantitative_analysis/es/_index.md new file mode 100644 index 00000000000..1c83f400366 --- /dev/null +++ b/website/content/common/quantitative_analysis/es/_index.md @@ -0,0 +1,33 @@ +``` +usage: es [-m] [-d {laplace,student_t,logistic,normal}] [-p PERCENTILE] [-h] +``` + +Provides Expected Shortfall (short: ES) of the selected stock. + +``` +optional arguments: + -m, --mean If one should use the mean of the stocks return (default: False) + -d {laplace,student_t,logistic,normal}, --dist {laplace,student_t,logistic,normal}, --distributions {laplace,student_t,logistic,normal} + Distribution used for the calculations (default: normal) + -p PERCENTILE, --percentile PERCENTILE + Percentile used for ES calculations, for example input 99.9 equals a 99.9 Percent Expected + Shortfall (default: 99.9) + -h, --help show this help message (default: False) +``` + +Example: +``` +2022 Feb 25, 06:50 (✨) /stocks/qa/ $ es + TSLA Expected Shortfall +┏━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━┓ +┃ ┃ ES: ┃ Historical ES: ┃ +┡━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━┩ +│ 90.0% │ -0.0752 │ -0.0705 │ +├───────┼─────────┼────────────────┤ +│ 95.0% │ -0.0885 │ -0.0932 │ +├───────┼─────────┼────────────────┤ +│ 99.0% │ -0.1144 │ -0.1561 │ +├───────┼─────────┼────────────────┤ +│ 99.9% │ -0.1444 │ -0.2106 │ +└───────┴─────────┴────────────────┘ +``` diff --git a/website/content/common/quantitative_analysis/var/_index.md b/website/content/common/quantitative_analysis/var/_index.md index c518d52ae23..4a2f8728633 100644 --- a/website/content/common/quantitative_analysis/var/_index.md +++ b/website/content/common/quantitative_analysis/var/_index.md @@ -1,15 +1,18 @@ ``` -usage: var [-m] [-a] [-p PERCENTILE] [-h] +usage: var [-m] [-a] [-s] [-p PERCENTILE] [-h] ``` Provides value at risk (short: VaR) of the selected stock. ``` optional arguments: - -m, --mean If one should use the mean of the stocks return - -a, --adjusted If the VaR should be adjusted for skew and kurtosis (Cornish-Fisher-Expansion) - -p PERCENTILE, --percent PERCENTILE - Percentile used for VaR calculations, for example input 99.9 equals a 99.9% VaR + -m, --mean If one should use the mean of the stocks return (default: False) + -a, --adjusted If the VaR should be adjusted for skew and kurtosis (Cornish-Fisher-Expansion) (default: + False) + -s, --student If one should use the student-t distribution (default: False) + -p PERCENTILE, --percentile PERCENTILE + Percentile used for VaR calculations, for example input 99.9 equals a 99.9 Percent VaR + (default: 99.9) -h, --help show this help message (default: False) ``` diff --git a/website/content/portfolio/es/_index.md b/website/content/portfolio/es/_index.md new file mode 100644 index 00000000000..b4c9c800682 --- /dev/null +++ b/website/content/portfolio/es/_index.md @@ -0,0 +1,33 @@ +``` +usage: es [-m] [-d {laplace,student_t,logistic,normal}] [-p PERCENTILE] [-h] +``` + +Provides Expected Shortfall (short: ES) of the selected portfolio. + +``` +optional arguments: + -m, --mean If one should use the mean of the portfolios return (default: False) + -d {laplace,student_t,logistic,normal}, --dist {laplace,student_t,logistic,normal}, --distributions {laplace,student_t,logistic,normal} + Distribution used for the calculations (default: normal) + -p PERCENTILE, --percentile PERCENTILE + Percentile used for ES calculations, for example input 99.9 equals a 99.9 Percent Expected + Shortfall (default: 99.9) + -h, --help show this help message (default: False) +``` + +Example: +``` +2022 Feb 25, 03:09 (✨) /portfolio/ $ es + Portfolio Expected Shortfall +┏━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━┓ +┃ ┃ ES: ┃ Historical ES: ┃ +┡━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━┩ +│ 90.0% │ -0.0204 │ -0.0202 │ +├───────┼─────────┼────────────────┤ +│ 95.0% │ -0.0240 │ -0.0242 │ +├───────┼─────────┼────────────────┤ +│ 99.0% │ -0.0310 │ -0.0270 │ +├───────┼─────────┼────────────────┤ +│ 99.9% │ -0.0391 │ -0.0277 │ +└───────┴─────────┴────────────────┘ +``` diff --git a/website/content/portfolio/var/_index.md b/website/content/portfolio/var/_index.md new file mode 100644 index 00000000000..e4a270cc1db --- /dev/null +++ b/website/content/portfolio/var/_index.md @@ -0,0 +1,32 @@ +``` +usage: var [-m] [-a] [-s] [-p PERCENTILE] [-h] +``` + +Provides value at risk (short: VaR) of the selected portfolio. +``` +optional arguments: + -m, --mean If one should use the mean of the portfolio return (default: False) + -a, --adjusted If the VaR should be adjusted for skew and kurtosis (Cornish-Fisher-Expansion) (default: + False) + -s, --student If one should use the student-t distribution (default: False) + -p PERCENTILE, --percentile PERCENTILE + Percentile used for VaR calculations, for example input 99.9 equals a 99.9 Percent VaR + (default: 99.9) + -h, --help show this help message (default: False) +``` +Example: +``` +2022 Feb 25, 03:09 (✨) /portfolio/ $ var + Portfolio Value at Risk +┏━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓ +┃ ┃ VaR: ┃ Historical VaR: ┃ +┡━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩ +│ 90.0% │ -0.0148 │ -0.0135 │ +├───────┼─────────┼─────────────────┤ +│ 95.0% │ -0.0189 │ -0.0197 │ +├───────┼─────────┼─────────────────┤ +│ 99.0% │ -0.0267 │ -0.0258 │ +├───────┼─────────┼─────────────────┤ +│ 99.9% │ -0.0353 │ -0.0276 │ +└───────┴─────────┴─────────────────┘ +```