Source code for frds.measures._srisk

import numpy as np
from typing import Union

from frds.measures import LongRunMarginalExpectedShortfall


[docs] class SRISK: """:doc:`/measures/srisk` of firm(s) or market at a given time"""
[docs] def __init__( self, firm_returns: np.ndarray, market_returns: np.ndarray, W: Union[float, np.ndarray], D: Union[float, np.ndarray], ) -> None: """__init__ Args: firm_returns (np.ndarray): ``(n_days,)`` array of firm log returns. Can also be ``(n_day,n_firms)`` array of multiple firms' log returns. market_returns (np.ndarray): ``(n_days,)`` array of market log returns W (float | np.ndarray): market value of equity. It can be either a single float value for a firm or a ``(n_firms,)`` array for multiple firms. D (float | np.ndarray): book value of debt. It can be either a single float value for a firm or a ``(n_firms,)`` array for multiple firms. .. note:: If ``firm_returns`` is a ``(n_day,n_firms)``, then ``W`` and ``D`` must be of shape ``(n_firms,)``. """ if len(firm_returns.shape) == 1: # Single firm n_firms = 1 n_days = len(firm_returns) assert firm_returns.shape == market_returns.shape assert isinstance(D, float) and isinstance(W, float) else: # Multple firms n_days, n_firms = firm_returns.shape assert n_firms > 1 assert market_returns.shape[0] == n_days assert isinstance(D, np.ndarray) and isinstance(W, np.ndarray) assert D.shape == W.shape assert D.shape == np.zeros((n_firms,)).shape self.firm_returns = firm_returns self.market_returns = market_returns self.W = W self.D = D self.n_firms = n_firms self.n_days = n_days
[docs] def estimate( self, k=0.08, lrmes_h=22, lrmes_S=10000, lrmes_C=-0.1, lrmes_random_seed=42, aggregate_srisk=False, ) -> Union[np.ndarray, float]: """estimate Args: k (float, optional): prudential capital factor. Defaults to 8%. lrmes_h (int, optional): parameter used to estimate :func:`lrmes`. Prediction horizon. Defaults to 22. lrmes_S (int, optional): parameter used to estimate `LRMES`. The number of simulations. Defaults to 10_000. lrmes_C (float, optional): parameter used to estimate `LRMES`. The markdown decline that defines a systemic event. Defaults to -0.1. lrmes_random_seed (int, optional): random seed in estimating `LRMES`. Defaults to 42. aggregate_srisk (bool, optional): whether to compute the aggregate SRISK. Defaults to False. Returns: np.ndarray | float: If ``aggregate_srisk=False``, ``(n_firms,)`` array of firm-level SRISK measures. Otherwise, a single float value for aggregate SRISK. """ market_returns = self.market_returns if self.n_firms == 1: lrmes = LongRunMarginalExpectedShortfall( self.firm_returns, market_returns ).estimate(lrmes_h, lrmes_S, lrmes_C, lrmes_random_seed) else: lrmes = np.empty(self.n_firms) for i in range(self.n_firms): firm_returns = self.firm_returns[:, i] lrmes[i] = LongRunMarginalExpectedShortfall( firm_returns, market_returns ).estimate(lrmes_h, lrmes_S, lrmes_C, lrmes_random_seed) lvg = (self.D + self.W) / self.W srisk = self.W * (k * lvg + (1 - k) * lrmes - 1) if not aggregate_srisk: return srisk else: return np.sum(srisk.clip(min=0.0))