Welcome to Quant Risk’s documentation!¶
Statistics¶
statistics.VaR module¶
Value at risk functions here/ no need for class
-
quant_risk.statistics.VaR.conditional_value_at_risk(price: pandas.core.series.Series, threshold: float = 0.05) → float[source]¶ Calculates Conditional Value at Risk for given price series
- Parameters
price (pd.Series) – historical prices of a given security
- Returns
Conditional Value at Risk (VaR value) for given price
- Return type
float
-
quant_risk.statistics.VaR.value_at_risk(price: pandas.core.series.Series, threshold: float = 0.05) → float[source]¶ Calculates Value at Risk for given price series
- Parameters
price (pd.Series) – historical prices of a given security
- Returns
Value at Risk (VaR value) for given price
- Return type
float
statistics.annualize module¶
This file implements different functions for annualising volatility and returns from a given dataframe of returns
-
quant_risk.statistics.annualize.annualised_returns(returns: pandas.core.frame.DataFrame, periodsPerYear: int = 252)[source]¶ This function returns the annualised returns of a given dataframe of returns. If the freq of the data is not daily, the annualisation factor must be specified. The function returns nan if the value computed is too small
- Parameters
returns (pd.DataFrame) – dataframe of returns
periodsPerYear (int, optional) – freq of returns in a year, by default 252
- Returns
Returns the annualised return for each column in the dataframe
- Return type
Annualised Returns
-
quant_risk.statistics.annualize.annualised_volatility(returns: pandas.core.frame.DataFrame, periodsPerYear: int = 252)[source]¶ This function returns the annualised volatility of a given dataframe of returns. If the freq of the data is not daily, the annualisation factor must be specified
- Parameters
returns (pd.DataFrame) – dataframe of returns
periodsPerYear (int, optional) – freq of returns in a year, by default 252
- Returns
Returns the annualised volatility for each column in the dataframe
- Return type
Annualised Returns
statistics.financial_ratios module¶
Put all financial ratios here, no need for class I think
-
quant_risk.statistics.financial_ratios.calmar_ratio(price: Union[pandas.core.frame.DataFrame, pandas.core.series.Series], periodsPerYear: Union[float, int] = 252, riskFreeRate: float = 0.0) → float[source]¶ Calculates annualised calmar ratio for given set of prices and risk free rate
- Parameters
price (Union[pd.DataFrame, pd.Series]) – historical prices of a given security
periodsPerYear (Union[float, int]) – periodicity of the returns data for purposes of annualising
- Returns
annualised calmar ratio
- Return type
float
-
quant_risk.statistics.financial_ratios.omega_ratio(price: Union[pandas.core.frame.DataFrame, pandas.core.series.Series], riskFreeRate: float = 0.0, periodsPerYear: Union[float, int] = 252) → float[source]¶ Calculates annualised omega ratio for given set of prices and risk free rate
- Parameters
price (Union[pd.DataFrame, pd.Series]) – historical prices of a given security
riskFreeRate (float) – given constant risk free rate throughout the period
periodsPerYear (Union[float, int]) – periodicity of the returns data for purposes of annualising
- Returns
annualised omega ratio
- Return type
float
-
quant_risk.statistics.financial_ratios.sharpe_ratio(price: Union[pandas.core.frame.DataFrame, pandas.core.series.Series], riskFreeRate: float = 0.0, periodsPerYear: Union[float, int] = 252) → float[source]¶ Calculates annualised sharpe ratio for given set of prices and risk free rate
- Parameters
price (Union[pd.DataFrame, pd.Series]) – historical prices of a given security
riskFreeRate (float) – given constant risk free rate throughout the period
periodsPerYear (Union[float, int]) – periodicity of the returns data for purposes of annualising
- Returns
annualised sharpe ratio
- Return type
float
-
quant_risk.statistics.financial_ratios.sortino_ratio(price: Union[pandas.core.frame.DataFrame, pandas.core.series.Series], periodsPerYear: Union[float, int] = 252, reqReturn: float = 0) → float[source]¶ Calculates annualised sortino ratio for given set of prices and risk free rate
- Parameters
price (Union[pd.DataFrame, pd.Series]) – historical prices of a given security
periodsPerYear (Union[float, int]) – periodicity of the returns data for purposes of annualising
reqReturn (float, optional) – the minimum acceptable return by investors, by default 0
- Returns
annualised sortino ratio
- Return type
float
-
quant_risk.statistics.financial_ratios.tail_ratio(price: Union[pandas.core.frame.DataFrame, pandas.core.series.Series]) → float[source]¶ Calculates annualised tail ratio for given set of prices and risk free rate
- Parameters
price (Union[pd.DataFrame, pd.Series]) – historical prices of a given security
- Returns
annualised tail ratio
- Return type
float
statistics.stats module¶
Put summary function here that prints or returns a dataframe
-
quant_risk.statistics.stats.calculate_kurtosis(price: Union[pandas.core.series.Series, pandas.core.frame.DataFrame], test: bool = False, **kwargs) → Union[float, pandas.core.series.Series][source]¶ Calculates the kurtosis for a given set of prices
- Parameters
price (Union[pd.DataFrame,pd.Series]) – historical prices of a given security
- Returns
kurtosis for a given set of prices
- Return type
Union[float,pd.Series]
-
quant_risk.statistics.stats.calculate_skewness(price: Union[pandas.core.frame.DataFrame, pandas.core.series.Series], test: bool = False, **kwargs) → Union[float, pandas.core.series.Series][source]¶ Calculates the skewness for a given set of prices
- Parameters
price (Union[pd.DataFrame,pd.Series]) – historical prices of a given security
- Returns
skewness for a given set of prices
- Return type
Union[float,pd.Series]
-
quant_risk.statistics.stats.covariance_shrinkage(price: pandas.core.frame.DataFrame, delta: float = 0.5, **kwargs)[source]¶ This function computes the covariance matrix using the Ledoit-Wolf covariance shrinkage method taking a linear combination of the Constant Correlation matrix, acting as our prior and the Sample covariance matrix. The posterior covariance matrix is then computed.
- Parameters
price (pd.DataFrame) – Historical prices of a given security
delta (float, optional) – Constant by which to weigh the priori matrix, by default 0.5
- Returns
Returns a covariance matrix
- Return type
pd.DataFrame
-
quant_risk.statistics.stats.cumulative_returns(price: Union[pandas.core.frame.DataFrame, pandas.core.series.Series]) → float[source]¶ Calculates cumulative returns for a given set of prices
- Parameters
price (Union[pd.DataFrame, pd.Series]) – historical prices of a given security
- Returns
cumulative returns for a given set of prices
- Return type
float
-
quant_risk.statistics.stats.elton_gruber_covariance(price: pandas.core.frame.DataFrame, **kwargs)[source]¶ This function estimates the covariance matrix by assuming an implicit structure as defined by the Elton-Gruber Constant Correlation model.
- Parameters
price (pd.DataFrame) – Historical prices of a given security
- Returns
Returns a covariance matrix
- Return type
pd.DataFrame
-
quant_risk.statistics.stats.is_stable(price: pandas.core.series.Series) → float[source]¶ Calculates stability for a given set of prices
- Parameters
price (pd.Series) – historical prices of a given security
- Returns
stability for a given set of prices
- Return type
float
-
quant_risk.statistics.stats.maximum_drawdown(price: pandas.core.series.Series) → float[source]¶ Calculates maximum drawdown for a given set of prices
- Parameters
price (pd.Series) – historical prices of a given security
- Returns
maximum drawdown for a given set of prices
- Return type
float
-
quant_risk.statistics.stats.risk_contribution(portfolioWeights: Union[numpy.array, pandas.core.frame.DataFrame], covarianceMatrix: pandas.core.frame.DataFrame)[source]¶ This function computes the contributions to the risk/variance of the constituents of a portfolio, given a set of portfolio weights and a covariance matrix
- Parameters
portfolioWeights (Union[np.array, pd.DataFrame]) – weights of our assets in our portfolio
covarianceMatrix (pd.DataFrame) – the covariance matrix of our assets computed by any method
- Returns
Returns the risk contribution of each asset
- Return type
pd.DataFrame
statistics.summarize module¶
-
quant_risk.statistics.summarize.print_summary(price: pandas.core.series.Series, **kwargs)[source]¶ This function returns a dataframe with the following characteristics: Financial Ratios: 1. Sharpe ratio 2. Sortino ratio 3. Calmar ratio 4. Omega ratio 5. Tail Ratio
Statistics: 1. Skewness 2. Kurtosis 3. Stability 4. Max Drawdown 5. Cumulative returns
Annualise: 1. Returns 2. Vol
Value at Risk 1. VaR 2. cVaR
statistics.tests module¶
Statistical tests
-
quant_risk.statistics.tests.ACF(series: pandas.core.series.Series, adjusted: bool = False, nLags: int = 20, qStat: bool = False, fft: bool = True, alpha: float = None, missing: str = 'none', plot: bool = True) → Union[numpy.ndarray, tuple][source]¶ Calculates the ACF, and optionally the confidence intervals, Ljung-Box Q-Statistic, and its associated p-values for a given series Check documentation here: https://www.statsmodels.org/stable/generated/statsmodels.tsa.stattools.acf.html#statsmodels.tsa.stattools.acf Note: series is only for one security
- Parameters
series (pd.Series) – time series data
adjusted (bool, optional) – If True, then denominators for autocovariance are n-k, otherwise n, by default False
nLags (int, optional) – Number of lags to return autocorrelation for, by default None
qStat (bool, optional) – If True, returns the Ljung-Box q statistic for each autocorrelation coefficient, by default False
fft (bool, optional) – If True, computes the ACF via FFT, by default None
alpha (float, optional) – If a number is given, the confidence intervals for the given level are returned, by default None
missing (str, optional) – A string in [“none”, “raise”, “conservative”, “drop”] specifying how the NaNs are to be treated, by default ‘none’
- Returns
- Returns the autocorrelation function of type np.ndarray, and
Confidence intervals for the ACF, if alpha is not None, of type np.ndarray The Ljung-Box Q-Statistic, if qStat is True, of type np.ndarray The p-values associated with the Q-statistics, if qStat is True, of type np.ndarray
- Return type
Union[np.ndarray,tuple]
-
quant_risk.statistics.tests.PACF(series: pandas.core.series.Series, nLags: int = 20, method: str = 'ywadjusted', alpha: float = None, plot: bool = True) → Union[numpy.ndarray, tuple][source]¶ Calculates the PACF, and optionally the confidence intervals, for the returns of a given series Documentation: https://www.statsmodels.org/stable/generated/statsmodels.tsa.stattools.pacf.html#statsmodels.tsa.stattools.pacf Note: series is only for one security
- Parameters
series (pd.Series) – time series data
nLags (int, optional) – The largest lag for which the PACF is returned, by default None
method (str, optional) – Specifies which method for the calculations to use, full list in documentation, by default ‘ywadjusted’
alpha (float, optional) – If a number is given, the confidence intervals for the given level are returned, by default None
- Returns
- Partial autocorrelations, nlags elements, including lag zero, of type np.ndarray and
Confidence intervals for the PACF if alpha is not None, of type np.ndarray
- Return type
Union[np.ndarray,tuple]
-
quant_risk.statistics.tests.granger_causality(series: pandas.core.frame.DataFrame, maxLags: Union[int, list], addConst: bool = True, verbose: bool = True, testToUse: str = 'ssr_ftest') → dict[source]¶ Performs the Granger Causality Test for the given series Note: pd.DataFrame should contain two columns Note: series data must be stationary, difference before passing if needed
- Parameters
series (pd.DataFrame) – data for testing whether the time series in the second column Granger causes the time series in the first column (missing values not supported)
maxLags (int) – If an integer, computes the test for all lags up to maxlag. If a list, computes the tests only for the lags in maxlag
addConst (bool) – Add a constant to the model, by default True
verbose (bool, optional) – True if debugging information is to be printed, by default True
- Returns
- All test results, dictionary keys are the number of lags. For each lag the values are a tuple,
First element: a dictionary with test statistic, p-values, degrees of freedom, keys: ‘lrtest’, ‘params_ftest’, ‘ssr_chi2test’, ‘ssr_ftest’ Second element: the OLS estimation results for the restricted model, the unrestricted model and the restriction (contrast) matrix for the parameter f_test For example: to get p-value for ssr_ftest for ith lag: res[i][0][‘ssr_ftest’][1]
- Return type
dict
-
quant_risk.statistics.tests.granger_causality_matrix(data: pandas.core.frame.DataFrame, testToUse: str = 'ssr_ftest', verbose: bool = False, maxlag: int = 10)[source]¶ The function returns a NxN matrix where N is the number of columns in our time series dataframe(should be the same as the number of variables in variables). The matrix is just the minimum p-value of the Johansen Cointegration test that is performed for each lag till maxlag for each series pair. The function also returns a dataframe that contains the lag value where the minimum pvalue was found. The variables in the columns are the predictors and the variables in the rows are reponses. The value in each cell of the matrix can be interpreted as the whether we can assume(<0.05) if our column causes our row variable.
- Parameters
data (pd.DataFrame) –
of Multivariate time series (Dataframe) –
testToUse (str, optional) – Which test statistic to use for our Granger Causality test, by default ‘ssr_ftest’
verbose (boolean, optional) – Should the computation be shown for each lag value for each pair computed, by default False
maxlag (int, optional) – The maximum lag that the test checks causality for, by default 6
- Returns
Returns two dataframes that contain the pvalues and the value of the lag at which the minimum pvalue was found.
- Return type
[pd.DataFrame, pd.DataFrame]
-
quant_risk.statistics.tests.hurst_exponent(series: pandas.core.series.Series, maxlag: int) → float[source]¶ Returns the Hurst Exponent value for a given time series Source: https://towardsdatascience.com/introduction-to-the-hurst-exponent-with-code-in-python-4da0414ca52e
- Parameters
series (pd.Series) – time series
maxLags (int) – maximum number of lags
- Returns
Hurst Exponent
- Return type
float
-
quant_risk.statistics.tests.stationary_test_adf(series: pandas.core.series.Series, verbose: bool = True, stationaritySignifiance: float = 0.05) → tuple[source]¶ Runs the Augmented Dickey-Fuller test on the series, with the Null Hypothesis of non-stationarity i.e data has a unit root
- Parameters
series (pd.Series) – Time series data that we want to test for stationarity
verbose (bool, optional) – True if the ADF statistic, p-value and critical values are to be printed, by default True
stationaritySignificance (float, optional) – The level of signifiance at which stationarity is checked, by default 0.05 (5%)
- Returns
Returns the relevant values in the format (p-value, ADF statistic, stationaryBool)
- Return type
tuple
Models¶
models.regression module¶
-
quant_risk.models.regression.regress(endogenousSeries: pandas.core.series.Series, exogenousSeries: Union[pandas.core.series.Series, pandas.core.frame.DataFrame], method: str = 'OLS', **kwargs)[source]¶ This function implements regression for a given set of endogeneous and exogeneous variables. Note: summary() function is not available for any method except ‘OLS’
- Parameters
endogenousSeries (pd.Series) – Endogenous series for our regression
exogenousSeries (Union[pd.Series, pd.DataFrame]) – Exogenous covariates for our regression
method (str, optional) – Type of regression to be conducted Possible inputs include: 1. OLS 2. Ridge 3. Lasso , by default ‘OLS’
- Returns
Returns a fitted instance of the regression model
- Return type
RegressionResults
- Raises
NameError – Incase an invalid method is selected, a NameError is raised
models.time_series module¶
-
quant_risk.models.time_series.auto_arima(endogenousSeries: Union[pandas.core.series.Series, numpy.array], exogenousSeries: Union[pandas.core.frame.DataFrame, numpy.array], pRange: int = 5, dRange: int = 1, qRange: int = 5, metric: str = 'BIC', **kwargs)[source]¶ This function implements an auto-arima model by utilising a grid search over the parameter ranges for the autoregressive, differencing, moving average parameters for each model. Each model is then evaluated based on the specifed metric and the model with the lowest metric statistic is chosen as the best model. The order params for the best model are saved and another model is fitted with those params.
- Parameters
endogenousSeries (Union[pd.Series, np.array]) – The endogenous variable for our ARIMA model
exogenousSeries (Union[pd.DataFrame, np.array]) – The exogeneous variables for our ARIMA model
pRange (int, optional) – The maximum value of the autogressive component till where we want to search, by default 5
dRange (int, optional) – The maximum value of the differencing/integrated order component till where we want to search, by default 1
qRange (int, optional) – The maximum value of the moving average component till where we want to search, by default 5
metric (str, optional) – The metric by which we want to search and choose our model, by default ‘BIC’
- Returns
Returns a fitted arima model with the best chosen order of components
- Return type
Fitted ARIMA Result
- Raises
RuntimeWarning – If the model fails to converge on any order, a RuntimeWarning is engaged
Portfolio¶
portfolio.mean_variance module¶
This module implements classes for various portfolio optimization methods.
-
class
quant_risk.portfolio.mean_variance.MeanVariance(historicalPrices: pandas.core.frame.DataFrame, frequency: int = 252, bounds: Union[tuple, list] = (0, 1), riskFreeRate: float = None, solver: str = None, solverOptions: dict = None, verbose: bool = False)[source]¶ Bases:
objectConstructor to instantiate the class based on the input parameters.
- Parameters
historicalPrices (pd.DataFrame) – DataFrame of historical prices for each ticker, with column name as name of ticker and index as timestamps
tickers (list, optional) – List of tickers of the assets in the portfolio, by default None
frequency (int, optional) – Frequency of the data passed, default is daily, i.e., 252 days
bounds (Union[tuple,list]) – Minimum and maximum weight of each asset or a single pair if all weights are identical, (-1,1) if shorting is allowed, by default (0,1)
riskFreeRate (float, optional) – Risk free rate, by default None
solver (str, optional) – Name of solver, by default None. List of solvers: cp.installed_solvers()
solverOptions (dict, optional) – Parameters for the given solver in the format {parameter:value}, by default None
verbose (bool, optional) – Whether performance and debugging information should be printed, by default False
-
fit(method: str = 'max_sharpe', **kwargs) → dict[source]¶ Optimize the portfolio by maxizing the Sharpe Ratio, and return the tickers and their respective weights.
- Parameters
method (str, optional) –
Different methods by which one can maximise the portfolio. Please have a look at the following link for the available methods that are available for optimisation : https://pyportfolioopt.readthedocs.io/en/latest/MeanVariance.html
#TODO: We can always add more objectives to the solver so that we can get a better estimate of our weights. # We can take some lower or upper bounds from the investment team as an input and use that as a contraint in our optimization by default ‘max_sharpe’
- Returns
Returns a dictionary with format {ticker:weight}
- Return type
dict
-
getCovarianceMatrix() → pandas.core.frame.DataFrame[source]¶ Returns the historical prices
- Returns
DataFrame of covariance between tickers
- Return type
pd.DataFrame
-
getExpectedReturns() → pandas.core.frame.DataFrame[source]¶ Returns the expected returns
- Returns
DataFrame of expected returns, with index as ticker names
- Return type
pd.DataFrame
-
getHistoricalPrices() → pandas.core.frame.DataFrame[source]¶ Returns the historical prices
- Returns
DataFrame of historical prices for each ticker, with column name as name of ticker and index as timestamps
- Return type
pd.DataFrame
-
getRiskFreeRate() → float[source]¶ Returns the risk free rate
- Returns
Risk free rate
- Return type
float
-
stats(verbose: bool = True) → tuple[source]¶ Generate the expected annual return, annual volatility and Sharpe Ratio of the portfolio.
- Parameters
verbose (bool, optional) – Print the statistics, by default True
- Returns
Calculated statistics in the format (expected annual return, annual volatility, Sharpe Ratio)
- Return type
tuple
portfolio.regime_signal module¶
Implements the regime signal model
-
class
quant_risk.portfolio.regime_signal.RegimeSignalModel(regimeSignals: pandas.core.series.Series, historicalPrices: pandas.core.frame.DataFrame, frequency: int = 252, bounds: Union[tuple, list] = (0, 1), riskFreeRate: float = None, solver: str = None, solverOptions: dict = None, verbose: bool = False, constraint: bool = True, LOOKBACKMONTHS: int = 3, CUSTOM_CEILING_RISK: float = 0.15)[source]¶ Bases:
objectConstructor to instantiate the class based on the input parameters.
- Parameters
regimeSignals (pd.Series) – Series of integers representing the regime signal, i.e. -1, 0, +1, with the index as timestamps
historicalPrices (pd.DataFrame) – DataFrame of historical prices for each ticker, with column name as name of ticker and index as timestamps
tickers (list, optional) – List of tickers of the assets in the portfolio, by default None
frequency (int, optional) – Frequency of the data passed, default is daily, i.e., 252 days
bounds (Union[tuple,list]) – Minimum and maximum weight of each asset or a single pair if all weights are identical, (-1,1) if shorting is allowed, by default (0,1)
riskFreeRate (float, optional) – Risk free rate, by default None
solver (str, optional) – Name of solver, by default None. List of solvers: cp.installed_solvers()
solverOptions (dict, optional) – Parameters for the given solver in the format {parameter:value}, by default None
verbose (bool, optional) – Whether performance and debugging information should be printed, by default False
constraint (bool) – True if you want to be invested in all tickers, will set minimum weight to 1/n**2 where n is number of tickers, else False
-
get_portfolio(verbose: bool = True)[source]¶ Computes the portfolio value from the weights matrix calculated in get_weights function. If Verbose: prints out the summary statistics of the portfolio
- Parameters
verbose (bool, optional) – prints out the portfolio statistics, by default True
- Returns
Returns a pandas dataframe of the Portfolio indexed by date
- Return type
DataFrame
-
get_weights(verbose: bool = False) → dict[source]¶ Get the average weights for each regime type.
- Parameters
verbose (bool, optional) – Print the performance and debugging information, default False
- Returns
A dictionary with the average regime weights for each regime, of form {regimeType:setOfWeights}
- Return type
dict
portfolio.risk_parity module¶
This module has functions related to risk parity and risk contributions
-
quant_risk.portfolio.risk_parity.risk_parity_portfolio(covarianceMatrix: pandas.core.frame.DataFrame, bounds: tuple = (0, 1))[source]¶ Returns the weights of the portfolio that equalizes the contributions of the constituents based on the given covariance matrix
- Parameters
covarianceMatrix (pd.DataFrame) – The covariance matrix of our asset returns computed by any method
bounds (tuple) – The bound that each of our weights will follow, by default (0, 1)
- Returns
Returns the portfolio weights of the desired portfolio
- Return type
np.array
-
quant_risk.portfolio.risk_parity.target_risk_contribution(targetRisk: numpy.array, covarianceMatrix: pandas.core.frame.DataFrame, bounds: tuple = (0, 1))[source]¶ This function computes the portfolio weights of each of our assets given a target risk contribution and the covariance matrix by minimising the MSE between target and optimised risk contribution
- Parameters
targetRisk (np.array) – The risk contributions we want for each asset
covarianceMatrix (pd.DataFrame) – The covariance matrix of our asset returns computed by any method
bounds (tuple, optional) – The bound that each of our weights will follow, by default (0, 1)
- Returns
Returns the portfolio weights of the desired portfolio
- Return type
np.array