fundedness 0.2.1__py3-none-any.whl → 0.2.3__py3-none-any.whl
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.
Potentially problematic release.
This version of fundedness might be problematic. Click here for more details.
- fundedness/__init__.py +1 -1
- fundedness/models/market.py +26 -15
- {fundedness-0.2.1.dist-info → fundedness-0.2.3.dist-info}/METADATA +38 -3
- {fundedness-0.2.1.dist-info → fundedness-0.2.3.dist-info}/RECORD +6 -6
- {fundedness-0.2.1.dist-info → fundedness-0.2.3.dist-info}/WHEEL +0 -0
- {fundedness-0.2.1.dist-info → fundedness-0.2.3.dist-info}/entry_points.txt +0 -0
fundedness/__init__.py
CHANGED
fundedness/models/market.py
CHANGED
|
@@ -139,22 +139,22 @@ class MarketModel(BaseModel):
|
|
|
139
139
|
|
|
140
140
|
def expected_portfolio_return(
|
|
141
141
|
self,
|
|
142
|
-
stock_weight: float,
|
|
143
|
-
bond_weight:
|
|
144
|
-
) -> float:
|
|
142
|
+
stock_weight: float | np.ndarray,
|
|
143
|
+
bond_weight: float | np.ndarray | None = None,
|
|
144
|
+
) -> float | np.ndarray:
|
|
145
145
|
"""Calculate expected return for a portfolio.
|
|
146
146
|
|
|
147
147
|
Args:
|
|
148
|
-
stock_weight: Weight in stocks (0-1)
|
|
148
|
+
stock_weight: Weight in stocks (0-1), scalar or array
|
|
149
149
|
bond_weight: Weight in bonds (remainder is cash if not specified)
|
|
150
150
|
|
|
151
151
|
Returns:
|
|
152
|
-
Expected annual real return
|
|
152
|
+
Expected annual real return (scalar or array matching input)
|
|
153
153
|
"""
|
|
154
154
|
if bond_weight is None:
|
|
155
155
|
bond_weight = 1 - stock_weight
|
|
156
156
|
|
|
157
|
-
cash_weight =
|
|
157
|
+
cash_weight = np.maximum(0, 1 - stock_weight - bond_weight)
|
|
158
158
|
|
|
159
159
|
return (
|
|
160
160
|
stock_weight * self.stock_return
|
|
@@ -164,25 +164,36 @@ class MarketModel(BaseModel):
|
|
|
164
164
|
|
|
165
165
|
def portfolio_volatility(
|
|
166
166
|
self,
|
|
167
|
-
stock_weight: float,
|
|
168
|
-
bond_weight:
|
|
169
|
-
) -> float:
|
|
167
|
+
stock_weight: float | np.ndarray,
|
|
168
|
+
bond_weight: float | np.ndarray | None = None,
|
|
169
|
+
) -> float | np.ndarray:
|
|
170
170
|
"""Calculate portfolio volatility.
|
|
171
171
|
|
|
172
172
|
Args:
|
|
173
|
-
stock_weight: Weight in stocks (0-1)
|
|
173
|
+
stock_weight: Weight in stocks (0-1), scalar or array
|
|
174
174
|
bond_weight: Weight in bonds (remainder is cash if not specified)
|
|
175
175
|
|
|
176
176
|
Returns:
|
|
177
|
-
Annual portfolio volatility
|
|
177
|
+
Annual portfolio volatility (scalar or array matching input)
|
|
178
178
|
"""
|
|
179
179
|
if bond_weight is None:
|
|
180
180
|
bond_weight = 1 - stock_weight
|
|
181
181
|
|
|
182
|
-
cash_weight =
|
|
183
|
-
weights = np.array([stock_weight, bond_weight, cash_weight, 0])
|
|
182
|
+
cash_weight = np.maximum(0, 1 - stock_weight - bond_weight)
|
|
184
183
|
|
|
185
184
|
cov = self.get_covariance_matrix()
|
|
186
|
-
portfolio_variance = weights @ cov @ weights
|
|
187
185
|
|
|
188
|
-
|
|
186
|
+
# Handle both scalar and array inputs
|
|
187
|
+
if isinstance(stock_weight, np.ndarray):
|
|
188
|
+
# Vectorized computation for array inputs
|
|
189
|
+
# weights shape: (n_samples, 4)
|
|
190
|
+
weights = np.column_stack([stock_weight, bond_weight, cash_weight, np.zeros_like(stock_weight)])
|
|
191
|
+
# cov @ weights.T has shape (4, n_samples)
|
|
192
|
+
# We want sum of weights[i] * (cov @ weights[i]) for each i
|
|
193
|
+
# This is equivalent to diag(weights @ cov @ weights.T)
|
|
194
|
+
portfolio_variance = np.einsum('ij,jk,ik->i', weights, cov, weights)
|
|
195
|
+
return np.sqrt(portfolio_variance)
|
|
196
|
+
else:
|
|
197
|
+
weights = np.array([stock_weight, bond_weight, cash_weight, 0])
|
|
198
|
+
portfolio_variance = weights @ cov @ weights
|
|
199
|
+
return np.sqrt(portfolio_variance)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fundedness
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: A Python financial planning toolkit with CEFR calculations, Monte Carlo simulations, and beautiful visualizations
|
|
5
5
|
Project-URL: Homepage, https://github.com/engineerinvestor/financial-health-calculator
|
|
6
6
|
Project-URL: Documentation, https://engineerinvestor.github.io/financial-health-calculator/
|
|
@@ -56,9 +56,8 @@ Description-Content-Type: text/markdown
|
|
|
56
56
|
|
|
57
57
|
[](https://pypi.org/project/fundedness/)
|
|
58
58
|
[](https://pypi.org/project/fundedness/)
|
|
59
|
-
[](https://github.com/engineerinvestor/financial-health-calculator/actions/workflows/ci.yml)
|
|
60
|
-
[](https://codecov.io/gh/engineerinvestor/financial-health-calculator)
|
|
61
59
|
[](https://engineerinvestor.github.io/financial-health-calculator/)
|
|
60
|
+
[](https://financial-health-calculator.streamlit.app/)
|
|
62
61
|
[](https://opensource.org/licenses/MIT)
|
|
63
62
|
[](https://colab.research.google.com/github/engineerinvestor/financial-health-calculator/blob/main/examples/01_cefr_basics.ipynb)
|
|
64
63
|
|
|
@@ -260,6 +259,42 @@ MIT License
|
|
|
260
259
|
|
|
261
260
|
2. Merton, R. C. (1969). Lifetime Portfolio Selection under Uncertainty: The Continuous-Time Case. *The Review of Economics and Statistics*, 51(3), 247-257.
|
|
262
261
|
|
|
262
|
+
## Citation
|
|
263
|
+
|
|
264
|
+
If you use this package in academic work, please cite:
|
|
265
|
+
|
|
266
|
+
```bibtex
|
|
267
|
+
@software{fundedness,
|
|
268
|
+
title = {Fundedness: A Python Financial Planning Toolkit},
|
|
269
|
+
author = {Engineer Investor},
|
|
270
|
+
year = {2024},
|
|
271
|
+
url = {https://github.com/engineerinvestor/financial-health-calculator},
|
|
272
|
+
version = {0.2.1}
|
|
273
|
+
}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
For the underlying methodology, please also cite:
|
|
277
|
+
|
|
278
|
+
```bibtex
|
|
279
|
+
@article{merton1969lifetime,
|
|
280
|
+
title = {Lifetime Portfolio Selection under Uncertainty: The Continuous-Time Case},
|
|
281
|
+
author = {Merton, Robert C.},
|
|
282
|
+
journal = {The Review of Economics and Statistics},
|
|
283
|
+
volume = {51},
|
|
284
|
+
number = {3},
|
|
285
|
+
pages = {247--257},
|
|
286
|
+
year = {1969},
|
|
287
|
+
publisher = {MIT Press}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
@book{haghani2023missing,
|
|
291
|
+
title = {The Missing Billionaires: A Guide to Better Financial Decisions},
|
|
292
|
+
author = {Haghani, Victor and White, James},
|
|
293
|
+
year = {2023},
|
|
294
|
+
publisher = {Wiley}
|
|
295
|
+
}
|
|
296
|
+
```
|
|
297
|
+
|
|
263
298
|
## Disclaimer
|
|
264
299
|
|
|
265
300
|
This tool is for educational purposes only and does not constitute financial advice. Consult a qualified financial advisor for personalized recommendations.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
fundedness/__init__.py,sha256=
|
|
1
|
+
fundedness/__init__.py,sha256=5rATL7-dfOIzb43-c3oDYImGu70ezYv2ALfbadhyR20,1678
|
|
2
2
|
fundedness/cefr.py,sha256=hCImRrjz-DCPJsuF3HShDZK5tw1vslakh-DrNBHsh2k,7728
|
|
3
3
|
fundedness/liabilities.py,sha256=uKvEV6JQnQdrd7b6VsCc2qf9S2DJdK0XhEX9qwca2Ws,6662
|
|
4
4
|
fundedness/liquidity.py,sha256=ncZF70AfgoVoYZnozpA_CHemfaHmI4KKCe3vITp5ljM,1713
|
|
@@ -16,7 +16,7 @@ fundedness/models/__init__.py,sha256=EyW6tGUI9T6QMbIfzsG3igqg5--DtZHSTAuMX6foOiA
|
|
|
16
16
|
fundedness/models/assets.py,sha256=ZKgxl4YaqdRVfDErL9weRhh4St_azo8ruN4g15T3IsQ,5013
|
|
17
17
|
fundedness/models/household.py,sha256=t64FjvO0uQJemddLtCPpK3NNYdZCXU6KjA1VZshaqEk,4671
|
|
18
18
|
fundedness/models/liabilities.py,sha256=iqGl5RU841k1clGOwnFParUvxzCJclq2JzNJoNPywuo,3416
|
|
19
|
-
fundedness/models/market.py,sha256=
|
|
19
|
+
fundedness/models/market.py,sha256=JAUt-MM__yM_v-FsgKwJj7rXC0yh6oFUv5JLoob58OE,6388
|
|
20
20
|
fundedness/models/simulation.py,sha256=0jtIJWISDL-TlKVjr6KxcRfAj5Mrbp-VNyA4Bu7IUfU,2224
|
|
21
21
|
fundedness/models/tax.py,sha256=0XhoBNZqfRqF1_acakrkYgMS5L6Pknq-TloQQBrFw1U,3859
|
|
22
22
|
fundedness/models/utility.py,sha256=0AoJdccTb2hKBrTz5LExm8SrSsaWhhBf7y2NNaUzWQ0,4678
|
|
@@ -37,7 +37,7 @@ fundedness/withdrawals/guardrails.py,sha256=rZKVojKbl9LLJLi9LlK1I2JXb537MN_AbZfn
|
|
|
37
37
|
fundedness/withdrawals/merton_optimal.py,sha256=mSxRAKGx8sr_YdlhQMtIvnojqfuG0MiYtBp18xboLHs,9269
|
|
38
38
|
fundedness/withdrawals/rmd_style.py,sha256=E5FfrUYxFJwULKxzxbtZFLoLspLzUUomTQRUWLGLDpg,6373
|
|
39
39
|
fundedness/withdrawals/vpw.py,sha256=aajHLAkHfsxh33uGRgzv0ozVuZREG-EmARJgWOU6mis,4389
|
|
40
|
-
fundedness-0.2.
|
|
41
|
-
fundedness-0.2.
|
|
42
|
-
fundedness-0.2.
|
|
43
|
-
fundedness-0.2.
|
|
40
|
+
fundedness-0.2.3.dist-info/METADATA,sha256=Ipd2Dp503muIicXo4VF4zTqpWwuUM_2OTyuAwIbuJ78,11017
|
|
41
|
+
fundedness-0.2.3.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
42
|
+
fundedness-0.2.3.dist-info/entry_points.txt,sha256=Oh-Hg08i044YHuSHViCdfoD8CenIGcKrVuUVysvN9sY,51
|
|
43
|
+
fundedness-0.2.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|