"""""" #
"""
Copyright (c) 2020-2026, Dany Cajas
All rights reserved.
This work is licensed under BSD 3-Clause "New" or "Revised" License.
License available at https://github.com/dcajasn/Riskfolio-Lib/blob/master/LICENSE.txt
"""
import numpy as np
import pandas as pd
from riskfolio.external.functions import *
from itertools import product
__all__ = [
"duplication_matrix",
"duplication_elimination_matrix",
"duplication_summation_matrix",
"commutation_matrix",
"covariance_matrix",
"semi_covariance_matrix",
"coskewness_matrix",
"semi_coskewness_matrix",
"cokurtosis_matrix",
"semi_cokurtosis_matrix",
"k_eigh",
"d_corr",
"d_corr_matrix",
"residuals_coskewness_fm",
"residuals_cokurtosis_fm",
]
[docs]
def duplication_matrix(n: int, diag: bool = True):
r"""
Calculate duplication matrix of size "n" as shown in :cite:`d-Magnus1980`.
Parameters
----------
n : int
Number of assets.
Returns
-------
D: np.ndarray
Duplication matrix
"""
return cpp_duplication_matrix(n, diag)
[docs]
def duplication_elimination_matrix(n: int, diag: bool = True):
r"""
Calculate duplication elimination matrix of size "n" as shown in :cite:`d-Magnus1980`.
Parameters
----------
n : int
Number of assets.
Returns
-------
L: np.ndarray
Duplication matrix
"""
return cpp_duplication_elimination_matrix(n, diag)
[docs]
def duplication_summation_matrix(n: int, diag: bool = True):
r"""
Calculate duplication summation matrix of size "n" as shown in :cite:`d-Cajas4`.
Parameters
----------
n : int
Number of assets.
Returns
-------
S: np.ndarray
Duplication summation matrix.
"""
return cpp_duplication_summation_matrix(n, diag)
[docs]
def commutation_matrix(T: int, n: int):
r"""
Calculate commutation matrix of size T x n.
Parameters
----------
T : int
Number of rows.
n : int
Number of columns.
Returns
-------
K: np.ndarray
Duplication summation matrix.
"""
return cpp_commutation_matrix(T, n)
[docs]
def covariance_matrix(
Y: np.ndarray | pd.DataFrame, P: np.ndarray | pd.DataFrame = None
):
r"""
Calculates covariance matrix as shown in :cite:`d-Cajas4` and with probabilities
Parameters
----------
Y : ndarray or dataframe
Returns series of shape n_sample x n_features.
P : ndarray or dataframe, optional
Probability vector of shape n_samples x 1. If None, it is assumed
that all observations have the same probability of 1/n_samples.
Returns
-------
M2 : ndarray
The covariance matrix.
Raises
------
ValueError when the value cannot be calculated.
"""
flag = False
if isinstance(Y, pd.DataFrame):
assets = Y.columns.tolist()
flag = True
Y_ = np.array(Y, ndmin=2)
if P is not None:
P_ = np.array(P, ndmin=1)
M2 = cpp_covariance_matrix_prob(Y_, P_, semi=False)
else:
M2 = cpp_covariance_matrix(Y_, semi=False)
if flag:
M2 = pd.DataFrame(M2, index=assets, columns=assets)
return M2
[docs]
def semi_covariance_matrix(
Y: np.ndarray | pd.DataFrame, P: np.ndarray | pd.DataFrame = None
):
r"""
Calculates lower semi covariance matrix as shown in :cite:`d-Cajas4` and with probabilities
Parameters
----------
Y : ndarray or dataframe
Returns series of shape n_sample x n_features.
P : ndarray or dataframe, optional
Probability vector of shape n_samples x 1. If None, it is assumed
that all observations have the same probability of 1/n_samples.
Returns
-------
M2 : ndarray
The lower semi covariance matrix.
Raises
------
ValueError when the value cannot be calculated.
"""
flag = False
if isinstance(Y, pd.DataFrame):
assets = Y.columns.tolist()
cols = list(product(assets, assets))
cols = [str(y) + " - " + str(x) for x, y in cols]
flag = True
Y_ = np.array(Y, ndmin=2)
if P is not None:
P_ = np.array(P, ndmin=1)
s_M2 = cpp_covariance_matrix_prob(Y_, P_, semi=True)
else:
s_M2 = cpp_covariance_matrix(Y_, semi=True)
if flag:
s_M2 = pd.DataFrame(s_M2, index=assets, columns=cols)
return s_M2
[docs]
def coskewness_matrix(
Y: np.ndarray | pd.DataFrame, P: np.ndarray | pd.DataFrame = None
):
r"""
Calculates coskewness rectangular matrix as shown in :cite:`d-Cajas4` and with probabilities
Parameters
----------
Y : ndarray or dataframe
Returns series of shape n_sample x n_features.
P : ndarray or dataframe, optional
Probability vector of shape n_samples x 1. If None, it is assumed
that all observations have the same probability of 1/n_samples.
Returns
-------
M3 : ndarray
The coskewness rectangular matrix.
Raises
------
ValueError when the value cannot be calculated.
"""
flag = False
if isinstance(Y, pd.DataFrame):
assets = Y.columns.tolist()
cols = list(product(assets, assets))
cols = [str(y) + " - " + str(x) for x, y in cols]
flag = True
Y_ = np.array(Y, ndmin=2)
if P is not None:
P_ = np.array(P, ndmin=1)
M3 = cpp_coskewness_matrix_prob(Y_, P_, semi=False)
else:
M3 = cpp_coskewness_matrix(Y_, semi=False)
if flag:
M3 = pd.DataFrame(M3, index=assets, columns=cols)
return M3
[docs]
def semi_coskewness_matrix(
Y: np.ndarray | pd.DataFrame, P: np.ndarray | pd.DataFrame = None
):
r"""
Calculates lower semi coskewness rectangular matrix as shown in :cite:`d-Cajas4` and with probabilities.
Parameters
----------
Y : ndarray or dataframe
Returns series of shape n_samples x n_features.
P : ndarray or dataframe, optional
Probability vector of shape n_samples x 1. If None, it is assumed
that all observations have the same probability of 1/n_samples.
Returns
-------
s_M3 : ndarray
The lower semi coskewness rectangular matrix.
Raises
------
ValueError when the value cannot be calculated.
"""
flag = False
if isinstance(Y, pd.DataFrame):
assets = Y.columns.tolist()
cols = list(product(assets, assets))
cols = [str(y) + " - " + str(x) for x, y in cols]
flag = True
Y_ = np.array(Y, ndmin=2)
if P is not None:
P_ = np.array(P, ndmin=1)
s_M3 = cpp_coskewness_matrix_prob(Y_, P_, semi=True)
else:
s_M3 = cpp_coskewness_matrix(Y_, semi=True)
if flag:
s_M3 = pd.DataFrame(s_M3, index=assets, columns=cols)
return s_M3
[docs]
def cokurtosis_matrix(
Y: np.ndarray | pd.DataFrame, P: np.ndarray | pd.DataFrame = None
):
r"""
Calculates cokurtosis square matrix as shown in :cite:`d-Cajas4` and with probabilities
Parameters
----------
Y : ndarray or dataframe
Returns series of shape n_samples x n_features.
P : ndarray or dataframe, optional
Probability vector of shape n_samples x 1. If None, it is assumed
that all observations have the same probability of 1/n_samples.
Returns
-------
S4 : ndarray
The cokurtosis square matrix.
Raises
------
ValueError when the value cannot be calculated.
"""
flag = False
if isinstance(Y, pd.DataFrame):
assets = Y.columns.tolist()
cols = list(product(assets, assets))
cols = [str(y) + " - " + str(x) for x, y in cols]
flag = True
Y_ = np.array(Y, ndmin=2)
if P is not None:
P_ = np.array(P, ndmin=1)
S4 = cpp_cokurtosis_matrix_prob(Y_, P_, semi=False)
else:
S4 = cpp_cokurtosis_matrix(Y_, semi=False)
if flag:
S4 = pd.DataFrame(S4, index=cols, columns=cols)
return S4
[docs]
def semi_cokurtosis_matrix(
Y: np.ndarray | pd.DataFrame, P: np.ndarray | pd.DataFrame = None
):
r"""
Calculates lower semi cokurtosis square matrix as shown in :cite:`d-Cajas4` and with probabilities
Parameters
----------
Y : ndarray or dataframe
Returns series of shape n_sample x n_features.
P : ndarray or dataframe, optional
Probability vector of shape n_samples x 1. If None, it is assumed
that all observations have the same probability of 1/n_samples.
Returns
-------
s_S4 : ndarray
The lower semi cokurtosis square matrix.
Raises
------
ValueError when the value cannot be calculated.
"""
flag = False
if isinstance(Y, pd.DataFrame):
assets = Y.columns.tolist()
cols = list(product(assets, assets))
cols = [str(y) + " - " + str(x) for x, y in cols]
flag = True
Y_ = np.array(Y, ndmin=2)
if P is not None:
P_ = np.array(P, ndmin=1)
s_S4 = cpp_cokurtosis_matrix_prob(Y_, P_, semi=True)
else:
s_S4 = cpp_cokurtosis_matrix(Y_, semi=True)
if flag:
s_S4 = pd.DataFrame(s_S4, index=cols, columns=cols)
return s_S4
[docs]
def k_eigh(Y: np.ndarray, k: int):
r"""
Calculates lower semi cokurtosis square matrix as shown in :cite:`d-Cajas4`.
Parameters
----------
Y : ndarray or dataframe
Returns series of shape n_sample x n_features.
Returns
-------
s_S4 : ndarray
The lower semi cokurtosis square matrix.
Raises
------
ValueError when the value cannot be calculated.
"""
Y_ = np.array(Y, ndmin=2)
eigvalues, eigvectors = cpp_k_eigh(Y_, k)
return eigvalues, eigvectors
[docs]
def d_corr(X: np.ndarray, Y: np.ndarray):
r"""
Calculates the distance correlation of X and Y.
Parameters
----------
X : ndarray or dataframe
Returns series of shape n_sample x n_features.
Y : ndarray or dataframe
Returns series of shape n_sample x n_features.
Returns
-------
value : float
Distance correlation.
Raises
------
ValueError when the value cannot be calculated.
"""
X_ = np.array(X, ndmin=2)
Y_ = np.array(Y, ndmin=2)
value = cpp_dcorr(X_, Y_)
return value
[docs]
def d_corr_matrix(Y: np.ndarray):
r"""
Calculates the distance correlation matrix of matrix of variables Y.
Parameters
----------
Y : ndarray or dataframe
Returns series of shape n_sample x n_features.
Returns
-------
value : float
Distance correlation.
Raises
------
ValueError when the value cannot be calculated.
"""
Y_ = np.array(Y, ndmin=2)
value = cpp_dcorr_matrix(Y_)
return value
[docs]
def residuals_coskewness_fm(residuals: np.ndarray):
r"""
Calculates the coskewness tensor of residuals of a risk factors model.
Parameters
----------
residuals : ndarray or dataframe
Ndarray or DataFrame of residuals of the risk factors model of shape n_samples x 1.
Returns
-------
value : float
Coskewness tensor of residuals of a risk factors model.
Raises
------
ValueError when the value cannot be calculated.
"""
residuals_ = np.array(residuals, ndmin=2)
value = cpp_residuals_coskewness_fm(residuals_)
return value
[docs]
def residuals_cokurtosis_fm(B: np.ndarray, S_f: np.ndarray, residuals: np.ndarray):
r"""
Calculates the cokurtosis square matrix of residuals of a risk factors model.
Parameters
----------
B : ndarray or dataframe
The loadings matrix.
S_f : ndarray or dataframe
Covariance matrix of the risk factors.
residuals : ndarray or dataframe
Ndarray or DataFrame of residuals of the risk factors model of shape n_samples x 1.
Returns
-------
value : float
Cokurtosis square matrix of residuals of a risk factors model.
Raises
------
ValueError when the value cannot be calculated.
"""
B_ = np.array(B, ndmin=2)
S_f_ = np.array(S_f, ndmin=2)
residuals_ = np.array(residuals, ndmin=2)
value = cpp_residuals_cokurtosis_fm(B_, S_f_, residuals_)
return value