funcsim 0.2.8__tar.gz → 0.2.9__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 (38) hide show
  1. {funcsim-0.2.8/funcsim.egg-info → funcsim-0.2.9}/PKG-INFO +2 -2
  2. {funcsim-0.2.8 → funcsim-0.2.9}/README.md +1 -1
  3. {funcsim-0.2.8 → funcsim-0.2.9}/funcsim/__init__.py +4 -2
  4. funcsim-0.2.9/funcsim/rteu.py +222 -0
  5. {funcsim-0.2.8 → funcsim-0.2.9/funcsim.egg-info}/PKG-INFO +2 -2
  6. {funcsim-0.2.8 → funcsim-0.2.9}/funcsim.egg-info/SOURCES.txt +1 -0
  7. {funcsim-0.2.8 → funcsim-0.2.9}/setup.py +1 -1
  8. {funcsim-0.2.8 → funcsim-0.2.9}/LICENSE +0 -0
  9. {funcsim-0.2.8 → funcsim-0.2.9}/MANIFEST.in +0 -0
  10. {funcsim-0.2.8 → funcsim-0.2.9}/funcsim/addist.py +0 -0
  11. {funcsim-0.2.8 → funcsim-0.2.9}/funcsim/conversions.py +0 -0
  12. {funcsim-0.2.8 → funcsim-0.2.9}/funcsim/copcompare.py +0 -0
  13. {funcsim-0.2.8 → funcsim-0.2.9}/funcsim/copfit.py +0 -0
  14. {funcsim-0.2.8 → funcsim-0.2.9}/funcsim/core.py +0 -0
  15. {funcsim-0.2.8 → funcsim-0.2.9}/funcsim/cpt.py +0 -0
  16. {funcsim-0.2.8 → funcsim-0.2.9}/funcsim/cvmdist.py +0 -0
  17. {funcsim-0.2.8 → funcsim-0.2.9}/funcsim/dependence.py +0 -0
  18. {funcsim-0.2.8 → funcsim-0.2.9}/funcsim/distfit.py +0 -0
  19. {funcsim-0.2.8 → funcsim-0.2.9}/funcsim/ecdfgof.py +0 -0
  20. {funcsim-0.2.8 → funcsim-0.2.9}/funcsim/edf.py +0 -0
  21. {funcsim-0.2.8 → funcsim-0.2.9}/funcsim/eut.py +0 -0
  22. {funcsim-0.2.8 → funcsim-0.2.9}/funcsim/imanconover.py +0 -0
  23. {funcsim-0.2.8 → funcsim-0.2.9}/funcsim/kde.py +0 -0
  24. {funcsim-0.2.8 → funcsim-0.2.9}/funcsim/ksdist.py +0 -0
  25. {funcsim-0.2.8 → funcsim-0.2.9}/funcsim/multicore.py +0 -0
  26. {funcsim-0.2.8 → funcsim-0.2.9}/funcsim/nearby.py +0 -0
  27. {funcsim-0.2.8 → funcsim-0.2.9}/funcsim/plotting.py +0 -0
  28. {funcsim-0.2.8 → funcsim-0.2.9}/funcsim/rdarrays.py +0 -0
  29. {funcsim-0.2.8 → funcsim-0.2.9}/funcsim/screen.py +0 -0
  30. {funcsim-0.2.8 → funcsim-0.2.9}/funcsim/shapiro.py +0 -0
  31. {funcsim-0.2.8 → funcsim-0.2.9}/funcsim/shrinkage.py +0 -0
  32. {funcsim-0.2.8 → funcsim-0.2.9}/funcsim/testsim.py +0 -0
  33. {funcsim-0.2.8 → funcsim-0.2.9}/funcsim/utests.py +0 -0
  34. {funcsim-0.2.8 → funcsim-0.2.9}/funcsim/vect.py +0 -0
  35. {funcsim-0.2.8 → funcsim-0.2.9}/funcsim.egg-info/dependency_links.txt +0 -0
  36. {funcsim-0.2.8 → funcsim-0.2.9}/funcsim.egg-info/requires.txt +0 -0
  37. {funcsim-0.2.8 → funcsim-0.2.9}/funcsim.egg-info/top_level.txt +0 -0
  38. {funcsim-0.2.8 → funcsim-0.2.9}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: funcsim
3
- Version: 0.2.8
3
+ Version: 0.2.9
4
4
  Summary: functional, simple stochastic simulation
5
5
  Home-page: https://github.com/h-bryant/funcsim
6
6
  Author: Henry Bryant
@@ -55,7 +55,7 @@ Features:
55
55
  - painless multi-core simulations
56
56
  - fitting and comparison of univariate distributions, kernel density estimates, and goodness-of-fit tests
57
57
  - multivariate normal (fitted to data or specified by a mean vector and covariance matrix) and multivariate KDE distributions; Gaussian, Student's t, Clayton, Gumbel, and Frank copulas, fitted to pseudo-observations or specified by their parameters (implemented natively, no additional packages required); information-criterion comparison of copula families; Iman-Conover; covariance shrinkage
58
- - expected utility and cumulative prospect theory calculations
58
+ - expected utility, cumulative prospect theory, and regret-theoretical expected utility calculations
59
59
  - plotly-based fan charts and diagnostic plots
60
60
  - highly flexible, and as simple as possible (but no more)
61
61
  - functional paradigm
@@ -10,7 +10,7 @@ Features:
10
10
  - painless multi-core simulations
11
11
  - fitting and comparison of univariate distributions, kernel density estimates, and goodness-of-fit tests
12
12
  - multivariate normal (fitted to data or specified by a mean vector and covariance matrix) and multivariate KDE distributions; Gaussian, Student's t, Clayton, Gumbel, and Frank copulas, fitted to pseudo-observations or specified by their parameters (implemented natively, no additional packages required); information-criterion comparison of copula families; Iman-Conover; covariance shrinkage
13
- - expected utility and cumulative prospect theory calculations
13
+ - expected utility, cumulative prospect theory, and regret-theoretical expected utility calculations
14
14
  - plotly-based fan charts and diagnostic plots
15
15
  - highly flexible, and as simple as possible (but no more)
16
16
  - functional paradigm
@@ -39,6 +39,8 @@ from .cpt import weightPrelec2, cptBV
39
39
 
40
40
  from .eut import eut, utilIsoelastic, eutIsoelastic
41
41
 
42
+ from .rteu import rteu, regretPower
43
+
42
44
  from .plotting import fan, twofuncs, histpdf, dblscat, qqplot, show
43
45
 
44
46
  def version():
@@ -48,6 +50,6 @@ def version():
48
50
  Returns
49
51
  -------
50
52
  str
51
- The version string of the package (e.g., '0.2.8').
53
+ The version string of the package (e.g., '0.2.9').
52
54
  """
53
- return "0.2.8"
55
+ return "0.2.9"
@@ -0,0 +1,222 @@
1
+ """regret-theoretical expected utility (RTEU) and certainty equivalents"""
2
+
3
+ import math
4
+ from collections import namedtuple
5
+ from typing import Callable, Union
6
+ import numpy as np
7
+ from numpy.typing import NDArray
8
+ import scipy
9
+ from . import conversions
10
+
11
+
12
+ # container for results
13
+ RteuResult = namedtuple("RteuResult", "ExpectedValue CertaintyEquiv")
14
+
15
+
16
+ def regretPower(x: Union[float, NDArray],
17
+ exponent: float,
18
+ ) -> Union[float, NDArray]:
19
+ """
20
+ Compute power regret for a utility gap.
21
+
22
+ Parameters
23
+ ----------
24
+ x : float or numpy.ndarray
25
+ The utility gap psi(y_max) - psi(y), non-negative; an array is
26
+ evaluated elementwise.
27
+ exponent : float
28
+ Curvature of regret, at least 1.0. Values above one make the regret
29
+ function strictly convex, so a few large regrets weigh more than
30
+ many small ones; at exactly one, regret is linear in the gap and the
31
+ choice between scenarios coincides with expected utility's, although
32
+ the certainty equivalents do not.
33
+
34
+ Returns
35
+ -------
36
+ float or numpy.ndarray
37
+ ``x ** exponent``, a float for a float and an array for an array.
38
+
39
+ Raises
40
+ ------
41
+ ValueError
42
+ If ``x`` (or any element of it) is negative or ``exponent`` is below
43
+ 1.0.
44
+
45
+ Notes
46
+ -----
47
+ This is the one ready-made regret function; any function of one
48
+ non-negative float with g(0) = 0 may be passed as ``regretFunc``. It
49
+ accepts arrays as well as floats so that a user's own per-state code can
50
+ call it on whole vectors; ``rteu`` evaluates it through
51
+ ``numpy.vectorize`` like any other ``regretFunc``. There is no
52
+ canonical parameterization in the literature comparable to Tversky and
53
+ Kahneman's for cumulative prospect theory, so no preset analogous to
54
+ ``cptBV`` is provided.
55
+ """
56
+ if exponent < 1.0:
57
+ raise ValueError(f"exponent (={exponent}) must be at least 1.0")
58
+ xa = np.asarray(x, dtype=float)
59
+ if np.any(xa < 0.0):
60
+ raise ValueError(f"x (={x}) must be non-negative: the argument of "
61
+ "a regret function is a utility gap")
62
+ powered = xa ** exponent
63
+ return float(powered) if powered.ndim == 0 else powered
64
+
65
+
66
+ def _rtu(psiY, psiBest, vg, k):
67
+ # psi(y) - k g(psi(best) - psi(y)), elementwise, from utilities that
68
+ # have already been evaluated; vg is the vectorized regret function.
69
+ # psiY may be a scalar (a sure amount), in which case it broadcasts
70
+ return psiY - k * vg(psiBest - psiY)
71
+
72
+
73
+ def _finite_or_raise(values, where, label):
74
+ # raise if any evaluated utility is not finite, naming the first culprit
75
+ bad = ~np.isfinite(values)
76
+ if np.any(bad):
77
+ i = int(np.argmax(bad))
78
+ raise ValueError(f"utilFunc is not finite at {label} {where[i]} "
79
+ f"(position {i})")
80
+
81
+
82
+ def rteu(utilFunc: Callable[[float], float],
83
+ regretFunc: Callable[[float], float],
84
+ regretCoeff: float,
85
+ outcomes: conversions.VectorLike,
86
+ best: conversions.VectorLike,
87
+ ) -> RteuResult:
88
+ """
89
+ Compute regret-theoretical expected utility (RTEU) and the certainty
90
+ equivalent of one scenario, given the best attainable outcome in each
91
+ state of nature across the decision maker's menu.
92
+
93
+ Parameters
94
+ ----------
95
+ utilFunc : Callable
96
+ Utility function of the monetary outcome, psi, taking a float and
97
+ returning a float. It must be strictly increasing; the theory also
98
+ assumes it concave. See ``utilIsoelastic``.
99
+ regretFunc : Callable
100
+ Regret function of the utility gap, g, taking a non-negative float
101
+ and returning a float, with g(0) = 0, g' > 0, and g'' > 0. See
102
+ ``regretPower``.
103
+ regretCoeff : float
104
+ Regret coefficient k, non-negative. At zero the results are those
105
+ of expected utility theory.
106
+ outcomes : VectorLike
107
+ The scenario's outcome in each state of nature (one value per
108
+ simulation trial).
109
+ best : VectorLike
110
+ The best attainable outcome in the same state of nature across every
111
+ scenario in the menu, the same length as ``outcomes`` and no smaller
112
+ than it in any state: typically the row-wise maximum across the
113
+ scenario columns, which includes this scenario's own outcome.
114
+ Element n of ``outcomes`` and of ``best`` must belong to the same
115
+ state of nature, which ``simulate`` delivers when every scenario is
116
+ run at the same seed and number of trials.
117
+
118
+ Returns
119
+ -------
120
+ RteuResult
121
+ Named tuple with fields:
122
+
123
+ ExpectedValue : float
124
+ The regret-theoretical expected utility of the scenario, the
125
+ mean over states of psi(y) - k g(psi(best) - psi(y)).
126
+ CertaintyEquiv : float
127
+ The certainty equivalent of the scenario within the menu: the
128
+ sure amount c such that the decision maker is indifferent
129
+ between c and the scenario when both are in the menu, each
130
+ evaluated against the best attainable outcome max(best, c) in
131
+ every state.
132
+
133
+ Raises
134
+ ------
135
+ ValueError
136
+ If ``outcomes`` and ``best`` differ in length, ``best`` is smaller
137
+ than ``outcomes`` in any state, ``regretCoeff`` is negative,
138
+ ``regretFunc(0.0)`` is not zero, or ``utilFunc`` is not finite at
139
+ every outcome (for example a logarithmic psi applied to a
140
+ non-positive outcome).
141
+
142
+ Notes
143
+ -----
144
+ The per-state index follows Braun and Muermann (2004); measuring regret
145
+ against the best attainable outcome in each state is the form implied
146
+ by Quiggin's (1994) irrelevance of statewise dominated alternatives,
147
+ and it is why the rest of the menu enters only through ``best``. The
148
+ certainty equivalent is the menu-based definition of the regret theory
149
+ literature (Loomes and Sugden, 1983; Diecidue and Somasundaram, 2017;
150
+ Gollier, 2020). It is found by Brent's method between the scenario's
151
+ smallest outcome and the largest value of ``best``, where the
152
+ indifference condition has opposite signs; the sure-amount side is
153
+ strictly increasing in c and the scenario side non-increasing, so the
154
+ root is unique. At ``regretCoeff`` = 0 the certainty equivalent is the
155
+ expected utility certainty equivalent, psi^-1(E[psi(y)]), and
156
+ ``ExpectedValue`` is E[psi(y)]. States are equally likely. Passing the
157
+ scenario's own outcomes as ``best`` describes a menu of the scenario
158
+ and the sure amount alone, the two-element setting of Loomes and Sugden
159
+ (1983). Because a sure amount is itself regret-prone within the menu,
160
+ the gap between a scenario's expected outcome and its certainty
161
+ equivalent is not the risk premium of expected utility theory (Gollier,
162
+ 2020), and the certainty equivalents can order two scenarios
163
+ differently from the choice between them; the choice rests on
164
+ ``ExpectedValue``. The scale of ``utilFunc`` matters: k weights regret
165
+ measured in utility units, so k is not comparable across differently
166
+ scaled psi. The utility and regret functions are evaluated through
167
+ ``numpy.vectorize``, so any function of one float works.
168
+ """
169
+ if regretCoeff < 0.0:
170
+ raise ValueError(f"regretCoeff (={regretCoeff}) must be non-negative")
171
+ g0 = float(regretFunc(0.0))
172
+ if not math.isclose(g0, 0.0, abs_tol=1e-12):
173
+ raise ValueError(f"regretFunc(0.0) must be zero (got {g0})")
174
+
175
+ y = conversions.vlToArray(outcomes).astype(float)
176
+ b = conversions.vlToArray(best).astype(float)
177
+ if len(y) != len(b):
178
+ raise ValueError(f"outcomes (length {len(y)}) and best (length "
179
+ f"{len(b)}) must have the same length")
180
+ below = b < y
181
+ if np.any(below):
182
+ i = int(np.argmax(below))
183
+ raise ValueError("best must be the best attainable outcome in each "
184
+ "state, so no smaller than outcomes; at position "
185
+ f"{i} best={b[i]} is below outcomes={y[i]}")
186
+
187
+ vpsi = np.vectorize(utilFunc, otypes=[float])
188
+ vg = np.vectorize(regretFunc, otypes=[float])
189
+ with np.errstate(invalid="ignore", divide="ignore"):
190
+ psiY = vpsi(y)
191
+ psiB = vpsi(b)
192
+ _finite_or_raise(psiY, y, "outcome")
193
+ _finite_or_raise(psiB, b, "best")
194
+ k = float(regretCoeff)
195
+
196
+ expected = float(np.mean(_rtu(psiY, psiB, vg, k)))
197
+
198
+ # certainty equivalent: the sure amount c at which the decision maker is
199
+ # indifferent between c and the scenario, both in the menu, so that the
200
+ # best attainable outcome is max(best, c) in every state. Because psi
201
+ # is increasing, psi(max(best, c)) = max(psi(best), psi(c)), so psi is
202
+ # evaluated on one scalar per iteration and g on the vector
203
+ def gap(c):
204
+ psiC = float(utilFunc(c))
205
+ psiBC = np.maximum(psiB, psiC)
206
+ sure = np.mean(_rtu(psiC, psiBC, vg, k))
207
+ scenario = np.mean(_rtu(psiY, psiBC, vg, k))
208
+ return float(sure - scenario)
209
+
210
+ # the gap is <= 0 at the scenario's worst outcome and >= 0 at the menu's
211
+ # best, so the root lies between them; a sure scenario (constant
212
+ # outcomes) has gap(lo) == 0 exactly, which brentq would reject
213
+ lo = float(np.min(y))
214
+ hi = float(np.max(b))
215
+ if gap(lo) >= 0.0:
216
+ certequiv = lo
217
+ elif gap(hi) <= 0.0:
218
+ certequiv = hi
219
+ else:
220
+ certequiv = scipy.optimize.brentq(f=gap, a=lo, b=hi, maxiter=200)
221
+
222
+ return RteuResult(expected, float(certequiv))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: funcsim
3
- Version: 0.2.8
3
+ Version: 0.2.9
4
4
  Summary: functional, simple stochastic simulation
5
5
  Home-page: https://github.com/h-bryant/funcsim
6
6
  Author: Henry Bryant
@@ -55,7 +55,7 @@ Features:
55
55
  - painless multi-core simulations
56
56
  - fitting and comparison of univariate distributions, kernel density estimates, and goodness-of-fit tests
57
57
  - multivariate normal (fitted to data or specified by a mean vector and covariance matrix) and multivariate KDE distributions; Gaussian, Student's t, Clayton, Gumbel, and Frank copulas, fitted to pseudo-observations or specified by their parameters (implemented natively, no additional packages required); information-criterion comparison of copula families; Iman-Conover; covariance shrinkage
58
- - expected utility and cumulative prospect theory calculations
58
+ - expected utility, cumulative prospect theory, and regret-theoretical expected utility calculations
59
59
  - plotly-based fan charts and diagnostic plots
60
60
  - highly flexible, and as simple as possible (but no more)
61
61
  - functional paradigm
@@ -23,6 +23,7 @@ funcsim/multicore.py
23
23
  funcsim/nearby.py
24
24
  funcsim/plotting.py
25
25
  funcsim/rdarrays.py
26
+ funcsim/rteu.py
26
27
  funcsim/screen.py
27
28
  funcsim/shapiro.py
28
29
  funcsim/shrinkage.py
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
5
5
 
6
6
  setuptools.setup(
7
7
  name="funcsim",
8
- version="0.2.8",
8
+ version="0.2.9",
9
9
  license="bsd-3-clause",
10
10
  author="Henry Bryant",
11
11
  author_email="henry@tamu.edu",
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes