示例#1
0
    def factors_stats(self, method_mu="hist", method_cov="hist", **kwargs):
        r"""
        Calculate the inputs that will be use by the optimization method when 
        we select the input model='FM'.
        
        Parameters
        ----------
        **kwargs : dict
            All aditional parameters of risk_factors function.

        See Also
        --------
        riskfolio.ParamsEstimation.forward_regression
        riskfolio.ParamsEstimation.backward_regression
        riskfolio.ParamsEstimation.loadings_matrix
        riskfolio.ParamsEstimation.risk_factors

        """
        X = self.factors
        Y = self.returns
        mu, cov, returns, nav = pe.risk_factors(
            X, Y, method_mu=method_mu, method_cov=method_cov, **kwargs
        )

        self.mu_fm = mu
        self.cov_fm = cov
        self.returns_fm = returns
        self.nav_fm = nav

        value = af.is_pos_def(self.cov_fm, threshold=1e-8)
        if value == False:
            print("You must convert self.cov_fm to a positive definite matrix")
示例#2
0
    def assets_stats(self, method_mu="hist", method_cov="hist", **kwargs):
        r"""
        Calculate the inputs that will be use by the optimization method when 
        we select the input model='Classic'.

        Parameters
        ----------
        **kwargs : dict
            All aditional parameters of mean_vector and covar_matrix functions.

        See Also
        --------
        riskfolio.ParamsEstimation.mean_vector
        riskfolio.ParamsEstimation.covar_matrix

        """

        self.mu = pe.mean_vector(self.returns, method=method_mu, **kwargs)
        self.cov = pe.covar_matrix(self.returns, method=method_cov, **kwargs)
        value = af.is_pos_def(self.cov, threshold=1e-8)
        if value == False:
            print("You must convert self.cov to a positive definite matrix")
示例#3
0
    def blacklitterman_stats(
        self,
        P,
        Q,
        rf=0,
        w=None,
        delta=None,
        eq=True,
        method_mu="hist",
        method_cov="hist",
        **kwargs
    ):
        r"""
        Calculate the inputs that will be use by the optimization method when 
        we select the input model='BL'.
        
        Parameters
        ----------
        P : DataFrame of shape (n_views, n_assets)
            Analyst's views matrix, can be relative or absolute.
        Q: DataFrame of shape (n_views, 1)
            Expected returns of analyst's views.    
        delta: float
            Risk aversion factor. The default value is 1.      
        rf: scalar, optional
            Risk free rate. The default is 0.
        w : DataFrame of shape (n_assets, 1)
            Weights matrix, where n_assets is the number of assets.
            The default is None.
        eq: bool, optional
            Indicates if use equilibrum or historical excess returns. 
            The default is True.
        **kwargs : dict
            Other variables related to the mean and covariance estimation.
        
        See Also
        --------
        riskfolio.ParamsEstimation.black_litterman

        """
        X = self.returns
        if w is None:
            w = self.benchweights

        if delta is None:
            a = np.matrix(self.mu) * np.matrix(w)
            delta = (a - rf) / (np.matrix(w).T * np.matrix(self.cov) * np.matrix(w))
            delta = delta.item()

        mu, cov, w = pe.black_litterman(
            X=X,
            w=w,
            P=P,
            Q=Q,
            delta=delta,
            rf=rf,
            eq=eq,
            method_mu=method_mu,
            method_cov=method_cov,
            **kwargs
        )
        self.mu_bl = mu
        self.cov_bl = cov

        value = af.is_pos_def(self.cov_bl, threshold=1e-8)
        if value == False:
            print("You must convert self.cov_bl to a positive definite matrix")
示例#4
0
def bootstrapping(X, kind='stationary', q=0.05, n_sim=3000, window=3, seed=0):
    r"""
    Estimates the uncertainty sets of mean and covariance matrix through the selected
    bootstrapping method.
    
    Parameters
    ----------
    X : DataFrame of shape (n_samples, n_features)
        Features matrix, where n_samples is the number of samples and 
        n_features is the number of features.    
    kind : str
        The bootstrapping method. The default value is 'stationary'. Posible values are:
        
        - 'stationary': stationary bootstrapping method, see `StationaryBootstrap <https://bashtage.github.io/arch/bootstrap/generated/arch.bootstrap.StationaryBootstrap.html#arch.bootstrap.StationaryBootstrap>`_ for more details.
        - 'circular': circular bootstrapping method, see `CircularBlockBootstrap <https://bashtage.github.io/arch/bootstrap/generated/arch.bootstrap.CircularBlockBootstrap.html#arch.bootstrap.CircularBlockBootstrap>`_ for more details.
        - 'moving': moving bootstrapping method, see `MovingBlockBootstrap <https://bashtage.github.io/arch/bootstrap/generated/arch.bootstrap.MovingBlockBootstrap.html#arch.bootstrap.MovingBlockBootstrap>`_ for more details.
    q : scalar
        Significance level of the selected bootstrapping method.
        The default is 0.05.
    n_sim : scalar
        Number of simulations of the bootstrapping method.
        The default is 3000.
    window:
        Block size of the bootstrapping method. Must be greather than 1
        and lower than the n_samples - n_features + 1
        The default is 3.  
    seed:
        Seed used to generate random numbers for bootstrapping method.
        The default is 0. 
    
    Returns
    -------
    mu_l : DataFrame    
        The q/2 percentile of mean vector obtained through the selected bootstrapping method.
    mu_u : DataFrame
        The 1-q/2 percentile of mean vector obtained through the selected bootstrapping method.
    cov_l : DataFrame
        The q/2 percentile of covariance matrix obtained through the selected bootstrapping method.
    cov_u : DataFrame
        The 1-q/2 percentile of covariance matrix obtained through the selected bootstrapping method.
    cov_mu : DataFrame
        The covariance matrix of estimation errors of mean vector obtained through the selected bootstrapping method.
        We take the diagonal of this matrix following :cite:`b-fabozzi2007robust`.
        
    Raises
    ------
    ValueError
        When the value cannot be calculated.
        
    """

    if not isinstance(X, pd.DataFrame):
        raise ValueError("X must be a DataFrame")

    if window >= X.shape[0] - window + 1:
        raise ValueError("block must be lower than  n_samples - window + 1")
    elif window <= 1:
        raise ValueError("block must be greather than 1")

    rs = np.random.RandomState(seed)

    cols = X.columns.tolist()
    m = len(cols)
    mus = np.zeros((n_sim, 1, m))
    covs = np.zeros((n_sim, m, m))

    if kind == 'stationary':
        gen = bs.StationaryBootstrap(window, X, random_state=rs)
    elif kind == 'circular':
        gen = bs.CircularBlockBootstrap(window, X, random_state=rs)
    elif kind == 'moving':
        gen = bs.MovingBlockBootstrap(window, X, random_state=rs)
    else:
        raise ValueError(
            "kind only can be 'stationary', 'circular' or 'moving'")

    i = 0
    for data in gen.bootstrap(n_sim):
        A = data[0][0]
        mus[i] = A.mean().to_numpy().reshape(1, m)
        covs[i] = A.cov().to_numpy()
        i += 1

    mu_l = np.percentile(mus, q / 2 * 100, axis=0, keepdims=True).reshape(1, m)
    mu_u = np.percentile(mus, 100 - q / 2 * 100, axis=0,
                         keepdims=True).reshape(1, m)

    cov_l = np.percentile(covs, q / 2 * 100, axis=0,
                          keepdims=True).reshape(m, m)
    cov_u = np.percentile(covs, 100 - q / 2 * 100, axis=0,
                          keepdims=True).reshape(m, m)

    cov_mu = mus.reshape(n_sim, m) - X.mean().to_numpy().reshape(1, m)
    cov_mu = np.cov(cov_mu.T)

    mu_l = pd.DataFrame(mu_l, index=[0], columns=cols)
    mu_u = pd.DataFrame(mu_u, index=[0], columns=cols)

    cov_l = pd.DataFrame(cov_l, index=cols, columns=cols)
    cov_u = pd.DataFrame(cov_u, index=cols, columns=cols)

    cov_mu = np.diag(np.diag(cov_mu))
    cov_mu = pd.DataFrame(cov_mu, index=cols, columns=cols)

    if au.is_pos_def(cov_l) == False:
        cov_l = au.cov_fix(cov_l, method="clipped", threshold=1e-3)

    if au.is_pos_def(cov_u) == False:
        cov_u = au.cov_fix(cov_u, method="clipped", threshold=1e-3)

    return mu_l, mu_u, cov_l, cov_u, cov_mu