quantmod 0.0.9__tar.gz → 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. {quantmod-0.0.9 → quantmod-0.1.0}/PKG-INFO +1 -1
  2. {quantmod-0.0.9 → quantmod-0.1.0}/quantmod/derivatives/nse.py +44 -26
  3. {quantmod-0.0.9 → quantmod-0.1.0}/quantmod/models/__init__.py +3 -3
  4. {quantmod-0.0.9 → quantmod-0.1.0}/quantmod/models/binomial.py +1 -14
  5. {quantmod-0.0.9 → quantmod-0.1.0}/quantmod/models/montecarlo.py +1 -17
  6. {quantmod-0.0.9 → quantmod-0.1.0}/quantmod/models/optioninputs.py +13 -0
  7. quantmod-0.1.0/quantmod/risk/var.py +137 -0
  8. {quantmod-0.0.9 → quantmod-0.1.0}/quantmod/risk/varbacktest.py +0 -2
  9. {quantmod-0.0.9 → quantmod-0.1.0}/quantmod/risk/varinputs.py +0 -5
  10. quantmod-0.1.0/quantmod/version.py +1 -0
  11. {quantmod-0.0.9 → quantmod-0.1.0}/quantmod.egg-info/PKG-INFO +1 -1
  12. quantmod-0.0.9/quantmod/risk/var.py +0 -110
  13. quantmod-0.0.9/quantmod/version.py +0 -1
  14. {quantmod-0.0.9 → quantmod-0.1.0}/LICENSE.txt +0 -0
  15. {quantmod-0.0.9 → quantmod-0.1.0}/README.md +0 -0
  16. {quantmod-0.0.9 → quantmod-0.1.0}/quantmod/__init__.py +0 -0
  17. {quantmod-0.0.9 → quantmod-0.1.0}/quantmod/_version.py +0 -0
  18. {quantmod-0.0.9 → quantmod-0.1.0}/quantmod/charts/__init__.py +0 -0
  19. {quantmod-0.0.9 → quantmod-0.1.0}/quantmod/charts/plotting.py +0 -0
  20. {quantmod-0.0.9 → quantmod-0.1.0}/quantmod/charts/themes.py +0 -0
  21. {quantmod-0.0.9 → quantmod-0.1.0}/quantmod/datasets/__init__.py +0 -0
  22. {quantmod-0.0.9 → quantmod-0.1.0}/quantmod/datasets/data/nifty50.csv +0 -0
  23. {quantmod-0.0.9 → quantmod-0.1.0}/quantmod/datasets/data/spx.csv +0 -0
  24. {quantmod-0.0.9 → quantmod-0.1.0}/quantmod/datasets/dataloader.py +0 -0
  25. {quantmod-0.0.9 → quantmod-0.1.0}/quantmod/derivatives/__init__.py +0 -0
  26. {quantmod-0.0.9 → quantmod-0.1.0}/quantmod/indicators/__init__.py +0 -0
  27. {quantmod-0.0.9 → quantmod-0.1.0}/quantmod/indicators/indicators.py +0 -0
  28. {quantmod-0.0.9 → quantmod-0.1.0}/quantmod/main.py +0 -0
  29. {quantmod-0.0.9 → quantmod-0.1.0}/quantmod/markets/__init__.py +0 -0
  30. {quantmod-0.0.9 → quantmod-0.1.0}/quantmod/markets/bb.py +0 -0
  31. {quantmod-0.0.9 → quantmod-0.1.0}/quantmod/markets/yahoo.py +0 -0
  32. {quantmod-0.0.9 → quantmod-0.1.0}/quantmod/models/blackscholes.py +0 -0
  33. {quantmod-0.0.9 → quantmod-0.1.0}/quantmod/risk/__init__.py +0 -0
  34. {quantmod-0.0.9 → quantmod-0.1.0}/quantmod/timeseries/__init__.py +0 -0
  35. {quantmod-0.0.9 → quantmod-0.1.0}/quantmod/timeseries/performance.py +0 -0
  36. {quantmod-0.0.9 → quantmod-0.1.0}/quantmod/timeseries/timeseries.py +0 -0
  37. {quantmod-0.0.9 → quantmod-0.1.0}/quantmod/utils.py +0 -0
  38. {quantmod-0.0.9 → quantmod-0.1.0}/quantmod.egg-info/SOURCES.txt +0 -0
  39. {quantmod-0.0.9 → quantmod-0.1.0}/quantmod.egg-info/dependency_links.txt +0 -0
  40. {quantmod-0.0.9 → quantmod-0.1.0}/quantmod.egg-info/entry_points.txt +0 -0
  41. {quantmod-0.0.9 → quantmod-0.1.0}/quantmod.egg-info/not-zip-safe +0 -0
  42. {quantmod-0.0.9 → quantmod-0.1.0}/quantmod.egg-info/requires.txt +0 -0
  43. {quantmod-0.0.9 → quantmod-0.1.0}/quantmod.egg-info/top_level.txt +0 -0
  44. {quantmod-0.0.9 → quantmod-0.1.0}/setup.cfg +0 -0
  45. {quantmod-0.0.9 → quantmod-0.1.0}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: quantmod
3
- Version: 0.0.9
3
+ Version: 0.1.0
4
4
  Summary: Quantmod Python Package
5
5
  Home-page: https://kannansingaravelu.com/
6
6
  Author: Kannan Singaravelu
@@ -15,11 +15,51 @@ import urllib.parse
15
15
  # Constants
16
16
  indices = ["NIFTY", "FINNIFTY", "BANKNIFTY"]
17
17
 
18
- mode = "local"
18
+ headers = {
19
+ "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
20
+ "accept-language": "en-US,en;q=0.9,en-IN;q=0.8,en-GB;q=0.7",
21
+ "cache-control": "max-age=0",
22
+ "priority": "u=0, i",
23
+ "sec-ch-ua": '"Microsoft Edge";v="129", "Not=A?Brand";v="8", "Chromium";v="129"',
24
+ "sec-ch-ua-mobile": "?0",
25
+ "sec-ch-ua-platform": '"Windows"',
26
+ "sec-fetch-dest": "document",
27
+ "sec-fetch-mode": "navigate",
28
+ "sec-fetch-site": "none",
29
+ "sec-fetch-user": "?1",
30
+ "upgrade-insecure-requests": "1",
31
+ "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36 Edg/129.0.0.0",
32
+ }
33
+
34
+ # Curl headers
35
+ curl_headers = """ -H "authority: beta.nseindia.com" -H "cache-control: max-age=0" -H "dnt: 1" -H "upgrade-insecure-requests: 1" -H "user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36" -H "sec-fetch-user: ?1" -H "accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" -H "sec-fetch-site: none" -H "sec-fetch-mode: navigate" -H "accept-encoding: gzip, deflate, br" -H "accept-language: en-US,en;q=0.9,hi;q=0.8" --compressed"""
19
36
 
20
- if mode == "vpn":
37
+ # https://ipapi.co/json
38
+ # https://ipinfo.io/json
39
+
40
+ try:
41
+ # Try ipapi.co
42
+ response = requests.get("https://ipapi.co/json/", timeout=5)
43
+ if response.status_code == 200:
44
+ data = response.json()
45
+ country_code = data.get('country_code', '').upper()
46
+ mode = "local" if country_code == "IN" else "vpn"
47
+ else:
48
+ # Fallback to ipinfo.io
49
+ response = requests.get("https://ipinfo.io/json", timeout=5)
50
+ if response.status_code == 200:
51
+ data = response.json()
52
+ country_code = data.get('country', '').upper()
53
+ mode = "local" if country_code == "IN" else "vpn"
54
+ else:
55
+ mode = "local"
56
+
57
+ except Exception:
58
+ mode = "local"
21
59
 
22
- def nsefetch(payload):
60
+
61
+ def nsefetch(payload):
62
+ if mode == "vpn":
23
63
  if ("%26" in payload) or ("%20" in payload):
24
64
  encoded_url = payload
25
65
  else:
@@ -38,10 +78,7 @@ if mode == "vpn":
38
78
  output = json.loads(output)
39
79
  return output
40
80
 
41
-
42
- if mode == "local":
43
-
44
- def nsefetch(payload):
81
+ else: # mode == "local":
45
82
  try:
46
83
  output = requests.get(payload, headers=headers).json()
47
84
  # print(output)
@@ -58,25 +95,6 @@ if mode == "local":
58
95
  return output
59
96
 
60
97
 
61
- headers = {
62
- "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
63
- "accept-language": "en-US,en;q=0.9,en-IN;q=0.8,en-GB;q=0.7",
64
- "cache-control": "max-age=0",
65
- "priority": "u=0, i",
66
- "sec-ch-ua": '"Microsoft Edge";v="129", "Not=A?Brand";v="8", "Chromium";v="129"',
67
- "sec-ch-ua-mobile": "?0",
68
- "sec-ch-ua-platform": '"Windows"',
69
- "sec-fetch-dest": "document",
70
- "sec-fetch-mode": "navigate",
71
- "sec-fetch-site": "none",
72
- "sec-fetch-user": "?1",
73
- "upgrade-insecure-requests": "1",
74
- "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36 Edg/129.0.0.0",
75
- }
76
- # Curl headers
77
- curl_headers = """ -H "authority: beta.nseindia.com" -H "cache-control: max-age=0" -H "dnt: 1" -H "upgrade-insecure-requests: 1" -H "user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36" -H "sec-fetch-user: ?1" -H "accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" -H "sec-fetch-site: none" -H "sec-fetch-mode: navigate" -H "accept-encoding: gzip, deflate, br" -H "accept-language: en-US,en;q=0.9,hi;q=0.8" --compressed"""
78
-
79
-
80
98
  class OptionData:
81
99
  """
82
100
  A class to fetch and analyze option chain data from NSE.
@@ -16,10 +16,10 @@
16
16
  # limitations under the License.
17
17
  #
18
18
 
19
- from .optioninputs import OptionInputs
19
+ from .optioninputs import OptionInputs, OptionType, ExerciseStyle, BarrierType
20
20
  from .blackscholes import BlackScholesOptionPricing
21
- from .montecarlo import BarrierType, MonteCarloOptionPricing
22
- from .binomial import OptionType, ExerciseStyle, BinomialOptionPricing
21
+ from .montecarlo import MonteCarloOptionPricing
22
+ from .binomial import BinomialOptionPricing
23
23
 
24
24
 
25
25
  __all__ = [
@@ -1,21 +1,8 @@
1
1
  import numpy as np
2
2
  from pydantic import Field
3
- from enum import Enum
4
3
  import matplotlib.pyplot as plt
5
4
  from typing import Optional
6
- from .optioninputs import OptionInputs
7
-
8
-
9
- # Enums for option types
10
- class OptionType(str, Enum):
11
- CALL = "call"
12
- PUT = "put"
13
-
14
-
15
- # Enums for exercise styles
16
- class ExerciseStyle(str, Enum):
17
- AMERICAN = "american"
18
- EUROPEAN = "european"
5
+ from .optioninputs import OptionInputs, OptionType, ExerciseStyle
19
6
 
20
7
 
21
8
  # Class for Binomial Option Pricing
@@ -1,23 +1,7 @@
1
1
  import numpy as np
2
- from enum import Enum
3
2
  from pydantic import Field
4
3
  from typing import Optional
5
- from .optioninputs import OptionInputs
6
-
7
-
8
- class OptionType(str, Enum):
9
- CALL = "call"
10
- PUT = "put"
11
-
12
-
13
- class ExerciseStyle(str, Enum):
14
- EUROPEAN = "european"
15
- ASIAN = "asian"
16
- BARRIER = "barrier"
17
-
18
-
19
- class BarrierType(str, Enum):
20
- UP_AND_OUT = "up_and_out"
4
+ from .optioninputs import OptionInputs, OptionType, ExerciseStyle, BarrierType
21
5
 
22
6
 
23
7
  class MonteCarloOptionPricing:
@@ -1,6 +1,19 @@
1
1
  from pydantic import BaseModel, Field
2
+ from enum import Enum
2
3
  from typing import Optional
3
4
 
5
+ class OptionType(str, Enum):
6
+ CALL = "call"
7
+ PUT = "put"
8
+
9
+ class ExerciseStyle(str, Enum):
10
+ ASIAN = "asian"
11
+ BARRIER = "barrier"
12
+ EUROPEAN = "european"
13
+ AMERICAN = "american"
14
+
15
+ class BarrierType(str, Enum):
16
+ UP_AND_OUT = "up_and_out"
4
17
 
5
18
  class OptionInputs(BaseModel):
6
19
  """
@@ -0,0 +1,137 @@
1
+ import numpy as np
2
+ from scipy.stats import norm
3
+ from .varinputs import RiskInputs
4
+
5
+
6
+ # Risk Metrics
7
+ class VaRMetrics:
8
+ """
9
+ Class to calculate various Value at Risk (VaR) metrics.
10
+
11
+ Parameters
12
+ ----------
13
+ inputs : RiskInputs
14
+ Object containing the following option parameters:
15
+ - confidence_level : float
16
+ The confidence level for the VaR calculation.
17
+ - num_simulations : int
18
+ The number of Monte Carlo simulations.
19
+ - portfolio_returns : pd.DataFrame
20
+ Historical returns of portfolio assets or single stock.
21
+ - is_single_stock : bool
22
+ Flag to indicate single stock calculation.
23
+ - portfolio_weights : list of float, optional
24
+ Weights of assets in the portfolio (None for single stock).
25
+
26
+ Attributes
27
+ ----------
28
+ parametric_var : float
29
+ The parametric VaR value.
30
+ historical_var : float
31
+ The historical VaR value.
32
+ monte_carlo_var : float
33
+ The Monte Carlo VaR value.
34
+ expected_shortfall : float
35
+ The expected shortfall value.
36
+
37
+ """
38
+
39
+ def __init__(self, inputs: RiskInputs):
40
+ self.confidence_level = inputs.confidence_level
41
+ self.num_simulations = inputs.num_simulations
42
+ self.is_single_stock = inputs.is_single_stock
43
+
44
+ # Convert returns to NumPy array and ensure 2D shape
45
+ self.returns = inputs.portfolio_returns.to_numpy()
46
+ if self.is_single_stock:
47
+ self.returns = self.returns.reshape(-1, 1) # Ensure 2D for consistency
48
+ self.weights = np.array([1.0])
49
+ else:
50
+ if inputs.portfolio_weights is None:
51
+ raise ValueError("Portfolio weights must be provided for portfolio VaR")
52
+ self.weights = np.array(inputs.portfolio_weights)
53
+ if len(self.weights) != self.returns.shape[1]:
54
+ raise ValueError("Portfolio weights must match the number of assets")
55
+ if not np.all(self.weights >= 0):
56
+ raise ValueError("Portfolio weights must be non-negative")
57
+ if not np.isclose(np.sum(self.weights), 1.0, rtol=1e-3):
58
+ raise ValueError("Portfolio weights must sum to 1")
59
+
60
+ # Precompute portfolio returns for efficiency
61
+ self.portfolio_returns = (
62
+ self.returns if self.is_single_stock else self.returns @ self.weights
63
+ )
64
+
65
+ if np.any(np.isnan(self.portfolio_returns)) or np.any(np.isinf(self.portfolio_returns)):
66
+ raise ValueError("portfolio_returns contains NaN or infinite values")
67
+
68
+ # Compute risk metrics
69
+ self.parametric_var = self._parametric_var()
70
+ self.historical_var = self._historical_var()
71
+ self.monte_carlo_var = self._monte_carlo_var()
72
+ self.expected_shortfall = self._expected_shortfall()
73
+
74
+
75
+ def _parametric_var(self) -> float:
76
+ """
77
+ Calculate parametric VaR using normal distribution.
78
+
79
+ Returns
80
+ -------
81
+ float
82
+ Parametric VaR value.
83
+ """
84
+ mean_returns = np.mean(self.portfolio_returns)
85
+ std_returns = np.std(self.portfolio_returns, ddof=1) # Use sample standard deviation
86
+ return norm.ppf(1 - self.confidence_level, loc=mean_returns, scale=std_returns)
87
+
88
+ def _historical_var(self) -> float:
89
+ """
90
+ Calculate historical VaR based on empirical distribution.
91
+
92
+ Returns
93
+ -------
94
+ float
95
+ Historical VaR value.
96
+ """
97
+ return np.percentile(self.portfolio_returns, 100 * (1 - self.confidence_level))
98
+
99
+ def _monte_carlo_var(self) -> float:
100
+ """
101
+ Calculate Monte Carlo VaR using simulated returns.
102
+
103
+ Returns
104
+ -------
105
+ float
106
+ Monte Carlo VaR value.
107
+ """
108
+ mean_returns = np.mean(self.returns, axis=0)
109
+
110
+ if self.is_single_stock:
111
+ std_returns = np.std(self.returns[:, 0])
112
+ simulated_returns = np.random.normal(
113
+ mean_returns[0], std_returns, self.num_simulations
114
+ )
115
+ else:
116
+ cov_matrix = np.cov(self.returns.T)
117
+ # Regularize covariance matrix
118
+ cov_matrix += np.eye(cov_matrix.shape[0]) * 1e-6
119
+ simulated_returns = np.random.multivariate_normal(
120
+ mean_returns, cov_matrix, self.num_simulations
121
+ )
122
+ simulated_returns = simulated_returns @ self.weights
123
+
124
+ return np.percentile(simulated_returns, 100 * (1 - self.confidence_level))
125
+
126
+ def _expected_shortfall(self) -> float:
127
+ """
128
+ Calculate expected shortfall (conditional VaR).
129
+
130
+ Returns
131
+ -------
132
+ float
133
+ Expected shortfall value. Returns NaN if no returns are below VaR.
134
+ """
135
+ var = self._historical_var()
136
+ tail_returns = self.portfolio_returns[self.portfolio_returns <= var]
137
+ return np.mean(tail_returns) if tail_returns.size > 0 else np.nan
@@ -15,8 +15,6 @@ class VaRAnalyzer:
15
15
  Object containing the following option parameters:
16
16
  - confidence_level : float
17
17
  The confidence level for the VaR calculation.
18
- - lookback_period : int
19
- The number of historical days for risk estimation.
20
18
  - num_simulations : int
21
19
  The number of Monte Carlo simulations.
22
20
  - portfolio_returns : pd.DataFrame
@@ -12,8 +12,6 @@ class RiskInputs(BaseModel):
12
12
  - confidence_level : float
13
13
  The confidence level for the VaR calculation.
14
14
  Must be between 0.90 and 1.0.
15
- - lookback_period : int
16
- Number of historical days for risk estimation.
17
15
  Must be greater than or equal to 1.
18
16
  - num_simulations : int, default: 10000
19
17
  Number of Monte Carlo simulations.
@@ -41,9 +39,6 @@ class RiskInputs(BaseModel):
41
39
  confidence_level: float = Field(
42
40
  ..., ge=0.90, le=1.0, description="The confidence level for the VaR calculation"
43
41
  )
44
- lookback_period: int = Field(
45
- ..., ge=1, description="Number of historical days for risk estimation"
46
- )
47
42
  num_simulations: int = Field(
48
43
  10000, ge=1000, le=100000, description="Number of Monte Carlo simulations"
49
44
  )
@@ -0,0 +1 @@
1
+ version = "0.1.0"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: quantmod
3
- Version: 0.0.9
3
+ Version: 0.1.0
4
4
  Summary: Quantmod Python Package
5
5
  Home-page: https://kannansingaravelu.com/
6
6
  Author: Kannan Singaravelu
@@ -1,110 +0,0 @@
1
- import numpy as np
2
- from scipy.stats import norm
3
- from .varinputs import RiskInputs
4
-
5
-
6
- # Risk Metrics
7
- class VaRMetrics:
8
- """
9
- Class to calculate various Value at Risk (VaR) metrics.
10
-
11
- Parameters
12
- ----------
13
- inputs : RiskInputs
14
- Object containing the following option parameters:
15
- - confidence_level : float
16
- The confidence level for the VaR calculation.
17
- - lookback_period : int
18
- The number of historical days for risk estimation.
19
- - num_simulations : int
20
- The number of Monte Carlo simulations.
21
- - portfolio_returns : pd.DataFrame
22
- Historical returns of portfolio assets or single stock.
23
- - is_single_stock : bool
24
- Flag to indicate single stock calculation.
25
- - portfolio_weights : list of float, optional
26
- Weights of assets in the portfolio (None for single stock).
27
-
28
- Attributes
29
- ----------
30
- parametric_var : float
31
- The parametric VaR value.
32
- historical_var : float
33
- The historical VaR value.
34
- monte_carlo_var : float
35
- The Monte Carlo VaR value.
36
- expected_shortfall : float
37
- The expected shortfall value.
38
-
39
- """
40
-
41
- def __init__(self, inputs: RiskInputs):
42
- self.confidence_level = inputs.confidence_level
43
- self.lookback_period = inputs.lookback_period
44
- self.num_simulations = inputs.num_simulations
45
- self.returns = inputs.portfolio_returns
46
- self.is_single_stock = inputs.is_single_stock
47
-
48
- # Set weights before risk metric calculations
49
- if self.is_single_stock:
50
- self.weights = np.array([1.0]) # Single stock, full weight
51
- else:
52
- if inputs.portfolio_weights is None:
53
- raise ValueError(
54
- "Portfolio weights must be provided for portfolio VaR calculation"
55
- )
56
- self.weights = np.array(inputs.portfolio_weights)
57
- # Only check shape for portfolio (2D returns)
58
- if len(self.weights) != self.returns.shape[1]:
59
- raise ValueError("Portfolio weights must match the number of assets")
60
-
61
- # attributes
62
- self.parametric_var = self._parametric_var()
63
- self.historical_var = self._historical_var()
64
- self.monte_carlo_var = self._monte_carlo_var()
65
- self.expected_shortfall = self._expected_shortfall()
66
-
67
- def _parametric_var(self) -> float:
68
- mean_returns = np.mean(self.returns, axis=0)
69
- std = np.std(self.returns, axis=0)
70
- return self.weights @ norm.ppf(
71
- 1 - self.confidence_level, loc=mean_returns, scale=std
72
- )
73
-
74
- def _historical_var(self) -> float:
75
- portfolio_returns = (
76
- self.returns if self.is_single_stock else self.returns @ self.weights
77
- )
78
- return np.percentile(portfolio_returns, 100 * (1 - self.confidence_level))
79
-
80
- def _monte_carlo_var(self) -> float:
81
- mean_returns = np.mean(self.returns, axis=0)
82
- cov_matrix = (
83
- np.cov(self.returns.T)
84
- if not self.is_single_stock
85
- else np.var(self.returns, axis=0)
86
- )
87
-
88
- simulated_returns = (
89
- np.random.normal(mean_returns, np.sqrt(cov_matrix), self.num_simulations)
90
- if self.is_single_stock
91
- else np.random.multivariate_normal(
92
- mean_returns, cov_matrix, self.num_simulations
93
- )
94
- )
95
-
96
- portfolio_simulated_returns = (
97
- simulated_returns
98
- if self.is_single_stock
99
- else simulated_returns @ self.weights
100
- )
101
- return np.percentile(
102
- portfolio_simulated_returns, 100 * (1 - self.confidence_level)
103
- )
104
-
105
- def _expected_shortfall(self) -> float:
106
- portfolio_returns = (
107
- self.returns if self.is_single_stock else self.returns @ self.weights
108
- )
109
- var = self._historical_var()
110
- return np.mean(portfolio_returns[portfolio_returns <= var])
@@ -1 +0,0 @@
1
- version = "0.0.9"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes