Adding risk metrics to portfolio and qa (#1394)

* Adding es to qa and var to portfolio

* Fixing mathematics

* Adding es command to portfolio menu

* Linting

* Fixing tests

* Lint fixes

* lint fixes

* Adding hugo, tests and small fixes

* Fixes

* Fix mypy + portfolio model

Co-authored-by: jmaslek <jmaslek11@gmail.com>
This commit is contained in:
northern-64bit
2022-02-25 19:02:01 +01:00
committed by GitHub
parent a5848af908
commit 884bb82fb5
13 changed files with 626 additions and 37 deletions

View File

@@ -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

View File

@@ -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("")

View File

@@ -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"""

View File

@@ -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(

View File

@@ -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,
)

View File

@@ -14,4 +14,6 @@ select aapl,msft,sbux,gme
add ge,tsla
equal
mktcap
es
var
exit

View File

@@ -27,4 +27,6 @@ raw
decompose
cusum
capm
var
es
exit

View File

@@ -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

View File

@@ -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

View File

@@ -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 │
└───────┴─────────┴────────────────┘
```

View File

@@ -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)
```

33
website/content/portfolio/es/_index.md vendored Normal file
View File

@@ -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 │
└───────┴─────────┴────────────────┘
```

32
website/content/portfolio/var/_index.md vendored Normal file
View File

@@ -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 │
└───────┴─────────┴─────────────────┘
```