goal-based-allocation 0.2.0__tar.gz → 0.3.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 (28) hide show
  1. {goal_based_allocation-0.2.0/goal_based_allocation.egg-info → goal_based_allocation-0.3.0}/PKG-INFO +82 -64
  2. goal_based_allocation-0.2.0/PKG-INFO → goal_based_allocation-0.3.0/README.md +469 -489
  3. {goal_based_allocation-0.2.0 → goal_based_allocation-0.3.0}/pyproject.toml +15 -5
  4. {goal_based_allocation-0.2.0 → goal_based_allocation-0.3.0/src}/goal_based_allocation/__init__.py +15 -1
  5. {goal_based_allocation-0.2.0 → goal_based_allocation-0.3.0/src}/goal_based_allocation/vanilla_option_pricer.py +10 -3
  6. goal_based_allocation-0.3.0/src/goal_based_allocation/variance_swap.py +617 -0
  7. goal_based_allocation-0.2.0/README.md → goal_based_allocation-0.3.0/src/goal_based_allocation.egg-info/PKG-INFO +507 -457
  8. goal_based_allocation-0.3.0/src/goal_based_allocation.egg-info/SOURCES.txt +25 -0
  9. {goal_based_allocation-0.2.0 → goal_based_allocation-0.3.0/src}/goal_based_allocation.egg-info/requires.txt +5 -0
  10. goal_based_allocation-0.3.0/tests/test_docs.py +37 -0
  11. goal_based_allocation-0.3.0/tests/test_metadata.py +32 -0
  12. goal_based_allocation-0.3.0/tests/test_quickstart.py +20 -0
  13. goal_based_allocation-0.3.0/tests/test_repository_layout.py +54 -0
  14. goal_based_allocation-0.3.0/tests/test_variance_swap.py +233 -0
  15. goal_based_allocation-0.2.0/goal_based_allocation.egg-info/SOURCES.txt +0 -19
  16. {goal_based_allocation-0.2.0 → goal_based_allocation-0.3.0}/LICENSE +0 -0
  17. {goal_based_allocation-0.2.0 → goal_based_allocation-0.3.0}/setup.cfg +0 -0
  18. {goal_based_allocation-0.2.0 → goal_based_allocation-0.3.0/src}/goal_based_allocation/client_solver.py +0 -0
  19. {goal_based_allocation-0.2.0 → goal_based_allocation-0.3.0/src}/goal_based_allocation/laplace_inversion.py +0 -0
  20. {goal_based_allocation-0.2.0 → goal_based_allocation-0.3.0/src}/goal_based_allocation/mandate_utils.py +0 -0
  21. {goal_based_allocation-0.2.0 → goal_based_allocation-0.3.0/src}/goal_based_allocation/opportunity_set.py +0 -0
  22. {goal_based_allocation-0.2.0 → goal_based_allocation-0.3.0/src}/goal_based_allocation/regime_switch_paper.py +0 -0
  23. {goal_based_allocation-0.2.0 → goal_based_allocation-0.3.0/src}/goal_based_allocation/riccati_solver.py +0 -0
  24. {goal_based_allocation-0.2.0 → goal_based_allocation-0.3.0/src}/goal_based_allocation.egg-info/dependency_links.txt +0 -0
  25. {goal_based_allocation-0.2.0 → goal_based_allocation-0.3.0/src}/goal_based_allocation.egg-info/top_level.txt +0 -0
  26. {goal_based_allocation-0.2.0 → goal_based_allocation-0.3.0}/tests/test_framework.py +0 -0
  27. {goal_based_allocation-0.2.0 → goal_based_allocation-0.3.0}/tests/test_reference_crosschecks.py +0 -0
  28. {goal_based_allocation-0.2.0 → goal_based_allocation-0.3.0}/tests/test_vanilla_option_pricer.py +0 -0
@@ -1,17 +1,19 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: goal-based-allocation
3
- Version: 0.2.0
4
- Summary: Dynamic Mean-Variance Portfolio Allocation under Regime-Switching Jump-Diffusions with Absorbing Barriers and Distribution Matching
3
+ Version: 0.3.0
4
+ Summary: Analytical dynamic mean-variance allocation and terminal-wealth risk under regime-switching jump-diffusions
5
5
  Author: Artur Sepp
6
- License: MIT
6
+ License-Expression: MIT
7
7
  Project-URL: Homepage, https://github.com/ArturSepp/GoalBasedAllocation
8
8
  Project-URL: Repository, https://github.com/ArturSepp/GoalBasedAllocation
9
9
  Project-URL: Issues, https://github.com/ArturSepp/GoalBasedAllocation/issues
10
- Keywords: portfolio-optimization,mean-variance,regime-switching,jump-diffusion,goal-based-investing,laplace-transform,option-pricing,quantitative-finance
10
+ Project-URL: Documentation, https://artursepp.github.io/GoalBasedAllocation/
11
+ Project-URL: Changelog, https://github.com/ArturSepp/GoalBasedAllocation/blob/main/CHANGELOG.md
12
+ Project-URL: Paper, https://papers.ssrn.com/sol3/papers.cfm?abstract_id=6534579
13
+ Keywords: portfolio-optimization,mean-variance,regime-switching,jump-diffusion,goal-based-investing,laplace-transform,option-pricing,quantitative-finance,asset-allocation,wealth-management,absorbing-barrier
11
14
  Classifier: Development Status :: 4 - Beta
12
15
  Classifier: Intended Audience :: Financial and Insurance Industry
13
16
  Classifier: Intended Audience :: Science/Research
14
- Classifier: License :: OSI Approved :: MIT License
15
17
  Classifier: Programming Language :: Python :: 3
16
18
  Classifier: Programming Language :: Python :: 3.10
17
19
  Classifier: Programming Language :: Python :: 3.11
@@ -28,37 +30,30 @@ Provides-Extra: dev
28
30
  Requires-Dist: pytest; extra == "dev"
29
31
  Requires-Dist: black; extra == "dev"
30
32
  Requires-Dist: ruff; extra == "dev"
33
+ Provides-Extra: docs
34
+ Requires-Dist: sphinx>=7; extra == "docs"
35
+ Requires-Dist: myst-parser>=2; extra == "docs"
36
+ Requires-Dist: sphinx-sitemap>=2; extra == "docs"
31
37
  Dynamic: license-file
32
38
 
33
- # GoalBasedAllocation
39
+ # GoalBasedAllocation (`goal-based-allocation`)
34
40
 
35
- <p align="center">
36
- <em>Dynamic Mean-Variance Portfolio Allocation under Regime-Switching Jump-Diffusions<br>with Absorbing Barriers and Distribution Matching</em>
37
- </p>
41
+ Analytical dynamic mean-variance allocation and terminal-wealth risk under
42
+ regime-switching jump-diffusions in Python for quantitative researchers and
43
+ wealth-management model developers.
38
44
 
39
- <p align="center">
40
- <a href="https://github.com/ArturSepp/GoalBasedAllocation/actions/workflows/tests.yml">
41
- <img src="https://github.com/ArturSepp/GoalBasedAllocation/actions/workflows/tests.yml/badge.svg" alt="Tests">
42
- </a>
43
- <a href="https://github.com/ArturSepp/GoalBasedAllocation/blob/main/LICENSE">
44
- <img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License: MIT">
45
- </a>
46
- <a href="https://pypi.org/project/goal-based-allocation/">
47
- <img src="https://img.shields.io/pypi/v/goal-based-allocation.svg" alt="PyPI">
48
- </a>
49
- <a href="https://pypi.org/project/goal-based-allocation/">
50
- <img src="https://img.shields.io/pypi/pyversions/goal-based-allocation.svg" alt="Python">
51
- </a>
52
- <a href="https://pepy.tech/project/goal-based-allocation">
53
- <img src="https://pepy.tech/badge/goal-based-allocation" alt="Downloads">
54
- </a>
55
- </p>
45
+ [![PyPI](https://img.shields.io/pypi/v/goal-based-allocation?style=flat-square)](https://pypi.org/project/goal-based-allocation/)
46
+ [![Python](https://img.shields.io/pypi/pyversions/goal-based-allocation?style=flat-square)](https://pypi.org/project/goal-based-allocation/)
47
+ [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
48
+ [![Tests](https://github.com/ArturSepp/GoalBasedAllocation/actions/workflows/tests.yml/badge.svg)](https://github.com/ArturSepp/GoalBasedAllocation/actions/workflows/tests.yml)
49
+ [![Downloads](https://static.pepy.tech/badge/goal-based-allocation)](https://pepy.tech/project/goal-based-allocation)
50
+ [![Monthly](https://static.pepy.tech/badge/goal-based-allocation/month)](https://pepy.tech/project/goal-based-allocation)
51
+
52
+ **Documentation:** [artursepp.github.io/GoalBasedAllocation](https://artursepp.github.io/GoalBasedAllocation/)
56
53
 
57
- Companion code to:
54
+ **Paper:** companion code to Sepp, A. (2026), *Dynamic Mean-Variance Portfolio Allocation under Regime-Switching Jump-Diffusions with Absorbing Barriers and Distribution Matching* — [SSRN 6534579](https://papers.ssrn.com/sol3/papers.cfm?abstract_id=6534579). See [Citation](#citation) for BibTeX.
58
55
 
59
- > **Sepp, A. (2026). Dynamic Mean-Variance Portfolio Allocation under Regime-Switching
60
- > Jump-Diffusions with Absorbing Barriers and Distribution Matching.**
61
- > [SSRN: https://papers.ssrn.com/sol3/papers.cfm?abstract_id=6534579](https://papers.ssrn.com/sol3/papers.cfm?abstract_id=6534579)
56
+ ---
62
57
 
63
58
  ## Overview
64
59
 
@@ -66,12 +61,18 @@ This package provides a **fully analytical Laplace-transform framework** for dyn
66
61
  mean-variance (MV) portfolio allocation under a two-state regime-switching model
67
62
  with exponential jumps at regime transitions and an absorbing wealth floor.
68
63
 
64
+ It models two regimes and multi-asset mandates aggregated to one effective risky
65
+ asset. It is not a discrete constrained multi-asset optimiser, trading engine, or
66
+ production portfolio-management system; use
67
+ [`optimalportfolios`](https://github.com/ArturSepp/OptimalPortfolios) for rolling
68
+ multi-asset construction, constraints, transaction costs, and backtesting.
69
+
69
70
  The MV-optimal strategy takes the form
70
71
 
71
- $$\omega^*(t) = |\omega^*_a| \cdot \left(\frac{\Pi^*(t)}{\Pi_t} - 1\right)$$
72
+ $$\omega^{\ast}(t) = |\omega^{\ast}_a| \cdot \left(\frac{\Pi^{\ast}(t)}{\Pi_t} - 1\right)$$
72
73
 
73
- where $\Pi^*(t)$ is the target wealth trajectory derived from the Riccati ODE system,
74
- and $|\omega^*_a|$ is the regime-dependent allocation intensity. This produces an
74
+ where $\Pi^{\ast}(t)$ is the target wealth trajectory derived from the Riccati ODE system,
75
+ and $|\omega^{\ast}_a|$ is the regime-dependent allocation intensity. This produces an
75
76
  **endogenous de-risking glide path**: early in the horizon the funding gap is large
76
77
  and allocation is aggressive; as the portfolio approaches the target, allocation
77
78
  moderates automatically.
@@ -101,6 +102,12 @@ simulation is needed for pricing; MC is used only for validation.
101
102
  - Monte Carlo simulator for validation of all analytical results
102
103
  - Integration tests and all paper figures reproducible from a single command
103
104
 
105
+ ## When to use it — and when not
106
+
107
+ Use `goal-based-allocation` to design goal-based mandates under regime switching: survival and shortfall probabilities against a wealth floor, MV-optimal allocation intensities and glide paths, terminal wealth distributions, investment opportunity sets for client advice, and regime-switching vanilla option pricing on the same Laplace engine — all analytically, with Monte Carlo reserved for validation.
108
+
109
+ The model is deliberately parsimonious: two regimes, exponential jumps at transitions, and multi-asset mandates reduced to a single effective asset via portfolio aggregation. For discrete rolling multi-asset optimisation with weight constraints and transaction costs, use [`optimalportfolios`](https://github.com/ArturSepp/OptimalPortfolios).
110
+
104
111
  ## Model
105
112
 
106
113
  The portfolio wealth $\Pi_t$ follows a regime-switching jump-diffusion
@@ -114,7 +121,7 @@ with two states: **growth** ($i=1$) and **stress** ($i=2$).
114
121
  | $\mu^{[i]} = \bar{\mu}^{[i]} - \lambda \alpha^{[i]}$ | Diffusion drift | `mu_bar` |
115
122
  | $r_h = \max(r, c)$ | Hurdle rate | `r_h` |
116
123
  | $r_c = r_h - c = \max(0, r-c)$ | Net floor growth rate | `r_c` |
117
- | $\omega^*_a = -\tilde{a}^{[i]}/\Sigma^{[i]}$ | Risky allocation coefficient | `w_a` |
124
+ | $\omega^{\ast}_a = -\tilde{a}^{[i]}/\Sigma^{[i]}$ | Risky allocation coefficient | `w_a` |
118
125
 
119
126
  ### Process specification
120
127
 
@@ -123,7 +130,7 @@ with two states: **growth** ($i=1$) and **stress** ($i=2$).
123
130
  | Diffusion | Regime-dependent drift $\mu^{[i]}$ and volatility $\sigma^{[i]}$ |
124
131
  | Jumps | Exponential crash at growth→stress ($\eta^{[1]}$), exponential recovery at stress→growth ($\eta^{[2]}$) |
125
132
  | Regime switching | Poisson rates $\lambda^{[12]}$ (crash) and $\lambda^{[21]}$ (recovery) |
126
- | MV-optimal control | $\omega^*(t) = \|\omega_a^*\| \cdot (\Pi^*(t)/\Pi_t - 1)$, from Riccati system |
133
+ | MV-optimal control | $\omega^{\ast}(t) = \|\omega_a^{\ast}\| \cdot (\Pi^{\ast}(t)/\Pi_t - 1)$, from Riccati system |
127
134
  | Absorbing floor | Wealth stopped at $L_t = L_0 \cdot e^{r_c t}$, converting to cash |
128
135
 
129
136
  ### Asset class parameters
@@ -148,9 +155,9 @@ $w_{\text{eq}} = g(1-w)$, $w_{\text{pe}} = (1-g)(1-w)$.
148
155
  | Balanced | 35/43/22 | 11.1 / 16.7% | 4.34 / 0.70% | 0.233 |
149
156
  | Growth | 0/67/33 | 15.8 / 23.8% | 5.33 / 0.00% | 0.334 |
150
157
 
151
- ### MV-optimal results ($c=0\%$, $\omega^*(0)=1$, $q_{dd}=2$)
158
+ ### MV-optimal results ($c=0\%$, $\omega^{\ast}(0)=1$, $q_{dd}=2$)
152
159
 
153
- | Mandate | $r_{\text{impl}}$ | $\Pi^*_T$ | $\mathbb{E}[\Pi_T]$ | Std | Survival | $r^{\text{BH}}_{\text{impl}}$ | $\text{Std}^{\text{BH}}$ |
160
+ | Mandate | $r_{\text{impl}}$ | $\Pi^{\ast}_T$ | $\mathbb{E}[\Pi_T]$ | Std | Survival | $r^{\text{BH}}_{\text{impl}}$ | $\text{Std}^{\text{BH}}$ |
154
161
  |---|---|---|---|---|---|---|---|
155
162
  | Income | 2.39% | 240 | 127 | 24.7 | 85.5% | 2.46% | 30.4 |
156
163
  | Conservative | 2.92% | 200 | 134 | 33.7 | 83.2% | 3.33% | 48.3 |
@@ -181,20 +188,21 @@ Requires Python >= 3.10 with NumPy >= 1.24, SciPy >= 1.10, and Matplotlib >= 3.7
181
188
 
182
189
  ```
183
190
  GoalBasedAllocation/
184
- ├── goal_based_allocation/ # Core library
185
- │ ├── regime_switch_paper.py # Laplace framework: density, survival, overshoot, BH moments
186
- │ ├── riccati_solver.py # Riccati ODE system + MC simulator
187
- │ ├── laplace_inversion.py # Abate-Whitt & Stehfest numerical inversion
188
- │ ├── client_solver.py # Effective asset construction, portfolio eta quadrature
189
- │ ├── mandate_utils.py # Portfolio mandate construction from assets
190
- │ ├── opportunity_set.py # Investment opportunity set & advisor framework
191
- │ └── vanilla_option_pricer.py # Laplace-transform vanilla option pricing (regime switching)
191
+ ├── src/
192
+ │ └── goal_based_allocation/ # Core library
193
+ │ ├── regime_switch_paper.py # Density, survival, overshoot, BH moments
194
+ │ ├── riccati_solver.py # Riccati ODE system + MC simulator
195
+ │ ├── laplace_inversion.py # Abate-Whitt & Stehfest numerical inversion
196
+ │ ├── client_solver.py # Effective asset construction, portfolio eta quadrature
197
+ │ ├── mandate_utils.py # Portfolio mandate construction from assets
198
+ │ ├── opportunity_set.py # Investment opportunity set & advisor framework
199
+ │ └── vanilla_option_pricer.py # Regime-switching vanilla option pricing
192
200
  ├── examples/ # Minimal, self-contained illustrations
193
201
  │ ├── wealth_process_simulation.py
194
202
  │ ├── terminal_wealth_distribution.py
195
203
  │ ├── investment_opportunity_set.py
196
204
  │ └── regime_switch_smile.py # Vol smile + Fourier/MC reference pricers
197
- ├── paper_code/
205
+ ├── papers/
198
206
  │ └── goal_based_allocation_2026/ # Self-contained paper: LaTeX, PDF, figures
199
207
  │ ├── goal_based_allocation_2026.tex
200
208
  │ ├── generate_paper_figures.py # All 10 figures + integration tests
@@ -333,13 +341,17 @@ Fourier and Monte Carlo cross-checks.
333
341
 
334
342
  ## Reproducing Paper Results
335
343
 
336
- All figures and integration tests can be reproduced with a single command:
344
+ The `papers/` projects are available from a GitHub clone and are intentionally not
345
+ included in PyPI distributions. From a clone, the main paper's integration tests and
346
+ figures can be reproduced with the commands below. The current `--test` mode runs the
347
+ tests and then generates all figures; use `--outdir` to keep verification output away
348
+ from tracked figures.
337
349
 
338
350
  ```bash
339
- cd paper_code/goal_based_allocation_2026
351
+ cd papers/goal_based_allocation_2026
340
352
 
341
- # Run integration tests (9 assertions)
342
- python generate_paper_figures.py --test
353
+ # Run 9 integration assertions, then generate figures into a temporary directory
354
+ python generate_paper_figures.py --test --outdir my_verification_figures/
343
355
 
344
356
  # Generate all figures only (writes to ./figures/)
345
357
  python generate_paper_figures.py
@@ -383,8 +395,8 @@ The `--test` flag runs 7 tests with 9 assertions covering:
383
395
  ### Selected figures
384
396
 
385
397
  <p align="center">
386
- <img src="paper_code/goal_based_allocation_2026/figures/mandate_density_overlay_c0.png" width="48%" />
387
- <img src="paper_code/goal_based_allocation_2026/figures/mandate_comparison.png" width="48%" />
398
+ <img src="papers/goal_based_allocation_2026/figures/mandate_density_overlay_c0.png" width="48%" />
399
+ <img src="papers/goal_based_allocation_2026/figures/mandate_comparison.png" width="48%" />
388
400
  </p>
389
401
 
390
402
  <p align="center">
@@ -393,8 +405,8 @@ The `--test` flag runs 7 tests with 9 assertions covering:
393
405
  </p>
394
406
 
395
407
  <p align="center">
396
- <img src="paper_code/goal_based_allocation_2026/figures/path_dynamics_balanced.png" width="48%" />
397
- <img src="paper_code/goal_based_allocation_2026/figures/opportunity_set_c0.png" width="48%" />
408
+ <img src="papers/goal_based_allocation_2026/figures/path_dynamics_balanced.png" width="48%" />
409
+ <img src="papers/goal_based_allocation_2026/figures/opportunity_set_c0.png" width="48%" />
398
410
  </p>
399
411
 
400
412
  <p align="center">
@@ -409,7 +421,7 @@ The analytical framework proceeds in three steps:
409
421
  **Step 1: Riccati ODE system.** The pre-commitment MV problem reduces to a
410
422
  system of coupled Riccati ODEs for the value function coefficients
411
423
  in each regime. The solution yields the optimal allocation
412
- intensity $|\omega^*_a|$ and the target wealth trajectory $\Pi^*(t)$.
424
+ intensity $|\omega^{\ast}_a|$ and the target wealth trajectory $\Pi^{\ast}(t)$.
413
425
 
414
426
  **Step 2: Gap process.** Under the optimal policy, the log-cushion ratio
415
427
  $X_t = \ln(B_t/Z_t)$ is a regime-switching jump-diffusion with an absorbing
@@ -426,16 +438,22 @@ jump sizes via deterministic numerical integration (`portfolio_eta_quadrature`).
426
438
  Buy-and-hold benchmark moments are computed exactly via the 2×2 matrix exponential
427
439
  of Proposition B.7.
428
440
 
429
- ## Related Packages
441
+ ## Ecosystem
430
442
 
431
- | Package | Description |
443
+ This package is part of an open-source Python stack for quantitative finance — full catalogue at [github.com/ArturSepp](https://github.com/ArturSepp):
444
+
445
+ | Package | Purpose |
432
446
  |---|---|
433
- | [OptimalPortfolios](https://github.com/ArturSepp/OptimalPortfolios) | Optimal portfolio construction and backtesting |
434
- | [StochVolModels](https://github.com/ArturSepp/StochVolModels) | Stochastic volatility models for options pricing |
435
- | [QuantInvestStrats](https://github.com/ArturSepp/QuantInvestStrats) | Quantitative investment strategies and analytics |
436
- | [BloombergFetch](https://github.com/ArturSepp/BloombergFetch) | Bloomberg data API wrapper |
437
- | [VanillaOptionPricers](https://github.com/ArturSepp/VanillaOptionPricers) | Vanilla option pricing models |
438
- | [factorlasso](https://github.com/ArturSepp/factorlasso) | Factor model estimation with LASSO |
447
+ | [`qis`](https://github.com/ArturSepp/QuantInvestStrats) | Performance analytics, factsheets, and visualisation |
448
+ | [`optimalportfolios`](https://github.com/ArturSepp/OptimalPortfolios) | Portfolio construction and backtesting |
449
+ | [`factorlasso`](https://github.com/ArturSepp/factorlasso) | Sparse factor models and factor covariance estimation |
450
+ | [`bbg-fetch`](https://github.com/ArturSepp/BloombergFetch) | Bloomberg data fetching |
451
+ | [`trendfollowing`](https://github.com/ArturSepp/TrendFollowingSystems) | Trend-following systems: closed-form theory and replication |
452
+ | [`goal-based-allocation`](https://github.com/ArturSepp/GoalBasedAllocation) *(this package)* | Dynamic MV allocation under regime-switching jump-diffusions |
453
+ | [`stochvolmodels`](https://github.com/ArturSepp/StochVolModels) | Stochastic volatility pricing analytics |
454
+ | [`vanilla-option-pricers`](https://github.com/ArturSepp/VanillaOptionPricers) | Vectorised vanilla option pricers and implied volatility fitters |
455
+
456
+ Dependency links within the stack: `optimalportfolios` builds on `qis` and `factorlasso`; `trendfollowing` builds on `qis`.
439
457
 
440
458
  ## Citation
441
459
 
@@ -461,7 +479,7 @@ If you use this work in your research, please cite both the paper and the softwa
461
479
  title = {{GoalBasedAllocation}: A {Python} package for dynamic mean-variance
462
480
  portfolio allocation under regime-switching jump-diffusions},
463
481
  year = {2026},
464
- note = {Version 0.2.0},
482
+ note = {Version 0.3.0},
465
483
  howpublished = {\url{https://github.com/ArturSepp/GoalBasedAllocation}}
466
484
  }
467
485
  ```