funcsim 0.2.3__tar.gz → 0.2.4__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 (37) hide show
  1. {funcsim-0.2.3/funcsim.egg-info → funcsim-0.2.4}/PKG-INFO +25 -17
  2. funcsim-0.2.4/README.md +47 -0
  3. {funcsim-0.2.3 → funcsim-0.2.4}/funcsim/__init__.py +2 -2
  4. {funcsim-0.2.3 → funcsim-0.2.4}/funcsim/core.py +36 -16
  5. {funcsim-0.2.3 → funcsim-0.2.4}/funcsim/cpt.py +2 -2
  6. {funcsim-0.2.3 → funcsim-0.2.4}/funcsim/dependence.py +72 -26
  7. {funcsim-0.2.3 → funcsim-0.2.4}/funcsim/distfit.py +4 -1
  8. {funcsim-0.2.3 → funcsim-0.2.4}/funcsim/ecdfgof.py +21 -9
  9. {funcsim-0.2.3 → funcsim-0.2.4}/funcsim/eut.py +2 -2
  10. {funcsim-0.2.3 → funcsim-0.2.4}/funcsim/imanconover.py +3 -3
  11. {funcsim-0.2.3 → funcsim-0.2.4}/funcsim/plotting.py +17 -12
  12. {funcsim-0.2.3 → funcsim-0.2.4}/funcsim/rdarrays.py +15 -2
  13. {funcsim-0.2.3 → funcsim-0.2.4}/funcsim/screen.py +17 -4
  14. {funcsim-0.2.3 → funcsim-0.2.4}/funcsim/shrinkage.py +20 -6
  15. {funcsim-0.2.3 → funcsim-0.2.4/funcsim.egg-info}/PKG-INFO +25 -17
  16. {funcsim-0.2.3 → funcsim-0.2.4}/setup.py +1 -1
  17. funcsim-0.2.3/README.md +0 -39
  18. {funcsim-0.2.3 → funcsim-0.2.4}/LICENSE +0 -0
  19. {funcsim-0.2.3 → funcsim-0.2.4}/MANIFEST.in +0 -0
  20. {funcsim-0.2.3 → funcsim-0.2.4}/funcsim/addist.py +0 -0
  21. {funcsim-0.2.3 → funcsim-0.2.4}/funcsim/conversions.py +0 -0
  22. {funcsim-0.2.3 → funcsim-0.2.4}/funcsim/copfit.py +0 -0
  23. {funcsim-0.2.3 → funcsim-0.2.4}/funcsim/cvmdist.py +0 -0
  24. {funcsim-0.2.3 → funcsim-0.2.4}/funcsim/edf.py +0 -0
  25. {funcsim-0.2.3 → funcsim-0.2.4}/funcsim/kde.py +0 -0
  26. {funcsim-0.2.3 → funcsim-0.2.4}/funcsim/ksdist.py +0 -0
  27. {funcsim-0.2.3 → funcsim-0.2.4}/funcsim/multicore.py +0 -0
  28. {funcsim-0.2.3 → funcsim-0.2.4}/funcsim/nearby.py +0 -0
  29. {funcsim-0.2.3 → funcsim-0.2.4}/funcsim/shapiro.py +0 -0
  30. {funcsim-0.2.3 → funcsim-0.2.4}/funcsim/testsim.py +0 -0
  31. {funcsim-0.2.3 → funcsim-0.2.4}/funcsim/utests.py +0 -0
  32. {funcsim-0.2.3 → funcsim-0.2.4}/funcsim/vect.py +0 -0
  33. {funcsim-0.2.3 → funcsim-0.2.4}/funcsim.egg-info/SOURCES.txt +0 -0
  34. {funcsim-0.2.3 → funcsim-0.2.4}/funcsim.egg-info/dependency_links.txt +0 -0
  35. {funcsim-0.2.3 → funcsim-0.2.4}/funcsim.egg-info/requires.txt +0 -0
  36. {funcsim-0.2.3 → funcsim-0.2.4}/funcsim.egg-info/top_level.txt +0 -0
  37. {funcsim-0.2.3 → funcsim-0.2.4}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: funcsim
3
- Version: 0.2.3
3
+ Version: 0.2.4
4
4
  Summary: functional, simple stochastic simulation
5
5
  Home-page: https://github.com/h-bryant/funcsim
6
6
  Author: Henry Bryant
@@ -46,35 +46,43 @@ Dynamic: summary
46
46
  # funcsim
47
47
  Lightweight, functional stochastic simulation
48
48
 
49
+ Documentation: https://funcsim.readthedocs.io/
50
+
49
51
  Features:
50
- - cross-sectional and recursive dynamic simulations
51
- - pseudo-random numbers (so that results are comparable across multiple runs or scenarios)
52
+ - static (cross-sectional) and recursive-dynamic simulations from a single user-written function
53
+ - pseudo-random numbers with an explicit seed (so that results are reproducible and comparable across runs or scenarios)
52
54
  - stratified/Latin hypercube sampling
53
55
  - painless multi-core simulations
56
+ - fitting and comparison of univariate distributions, kernel density estimates, and goodness-of-fit tests
57
+ - multivariate normal and KDE distributions; Gaussian, Student's t, Clayton, Gumbel, and Frank copulas (implemented natively, no additional packages required); Iman-Conover
58
+ - expected utility and cumulative prospect theory calculations
59
+ - plotly-based fan charts and diagnostic plots
54
60
  - highly flexible, and as simple as possible (but no more)
55
61
  - functional paradigm
56
62
 
57
- Developed using:
58
- - python >= 3.10
59
- - numpy 2.2.0
60
- - scipy 1.16.0
61
- - pandas 2.2.0 (pandas 2.2+ and 3.x are both supported)
62
- - xarray 2025.4.0
63
-
64
- Copulas (Gaussian, Student's t, Clayton, Gumbel, and Frank) are supported
65
- natively; no additional packages are required.
63
+ Requirements:
64
+ - python >= 3.11
65
+ - numpy >= 2.2.0
66
+ - scipy >= 1.16.0
67
+ - pandas >= 2.2.0 (pandas 2.2+ and 3.x are both supported)
68
+ - xarray >= 2025.4.0
66
69
 
67
- For optional functionality, additinoal packages are needed:
68
- - plotting: plotly
70
+ For optional functionality, additional packages are needed:
71
+ - plotting: plotly (`pip install "funcsim[plotting]"`); kaleido for static image export
69
72
 
70
- Additionally, to run the demos, run tests, and build docs:
73
+ Additionally, to run the tests and build the docs:
71
74
  - pytest
72
- - sphinx, sphinx-autodoc-typehints
75
+ - sphinx, sphinx-autodoc-typehints (`pip install "funcsim[docs]"`)
76
+
77
+ ### installation
78
+ ```bash
79
+ pip install funcsim
80
+ ```
73
81
 
74
82
  ### building html docs
75
83
  From the top-level funcsim directory...
76
84
  ```bash
77
- sphinx-build -b html docs/source/ docs/build/
85
+ sphinx-build -W -b html docs/source/ docs/build/
78
86
  ```
79
87
 
80
88
  ### running tests
@@ -0,0 +1,47 @@
1
+ # funcsim
2
+ Lightweight, functional stochastic simulation
3
+
4
+ Documentation: https://funcsim.readthedocs.io/
5
+
6
+ Features:
7
+ - static (cross-sectional) and recursive-dynamic simulations from a single user-written function
8
+ - pseudo-random numbers with an explicit seed (so that results are reproducible and comparable across runs or scenarios)
9
+ - stratified/Latin hypercube sampling
10
+ - painless multi-core simulations
11
+ - fitting and comparison of univariate distributions, kernel density estimates, and goodness-of-fit tests
12
+ - multivariate normal and KDE distributions; Gaussian, Student's t, Clayton, Gumbel, and Frank copulas (implemented natively, no additional packages required); Iman-Conover
13
+ - expected utility and cumulative prospect theory calculations
14
+ - plotly-based fan charts and diagnostic plots
15
+ - highly flexible, and as simple as possible (but no more)
16
+ - functional paradigm
17
+
18
+ Requirements:
19
+ - python >= 3.11
20
+ - numpy >= 2.2.0
21
+ - scipy >= 1.16.0
22
+ - pandas >= 2.2.0 (pandas 2.2+ and 3.x are both supported)
23
+ - xarray >= 2025.4.0
24
+
25
+ For optional functionality, additional packages are needed:
26
+ - plotting: plotly (`pip install "funcsim[plotting]"`); kaleido for static image export
27
+
28
+ Additionally, to run the tests and build the docs:
29
+ - pytest
30
+ - sphinx, sphinx-autodoc-typehints (`pip install "funcsim[docs]"`)
31
+
32
+ ### installation
33
+ ```bash
34
+ pip install funcsim
35
+ ```
36
+
37
+ ### building html docs
38
+ From the top-level funcsim directory...
39
+ ```bash
40
+ sphinx-build -W -b html docs/source/ docs/build/
41
+ ```
42
+
43
+ ### running tests
44
+ From the top-level funcsim directory...
45
+ ```bash
46
+ python3 -m pytest
47
+ ```
@@ -46,6 +46,6 @@ def version():
46
46
  Returns
47
47
  -------
48
48
  str
49
- The version string of the package (e.g., '0.1.5').
49
+ The version string of the package (e.g., '0.2.4').
50
50
  """
51
- return "0.2.3"
51
+ return "0.2.4"
@@ -183,17 +183,20 @@ def simulate(f: Callable[[Generator[int, float, None],
183
183
 
184
184
  Parameters
185
185
  ----------
186
- f : function
187
- Function that performs a single trial in a static simulation or a s
188
- single step through time in a recursive dynamic simulation. Should take
189
- 'ugen' as a first argument in either case, where 'ugen' will be a
190
- generator that emits standard uniform draws (or standard normal draws,
191
- if `stdnorm` is True) that will be passed to f by ``simulate``.
192
- In the case of a recursive dynamic simulation that employs past values,
193
- f should take 'data' as a second argument, where this will be a type of
194
- array that is also provided by ``simulate.`` This function should return
195
- a dict with variable names (as strings) as keys and values for those
196
- variables (as floats) as values.
186
+ f : callable
187
+ Function that performs a single trial in a static simulation, or a
188
+ single step through time in a recursive-dynamic simulation. Its first
189
+ argument (conventionally ``ugen``) receives a generator that emits
190
+ independent standard uniform draws (or standard normal draws, if
191
+ `stdnorm` is True); obtain each draw with ``next(ugen)``. If `f`
192
+ takes a second argument (conventionally ``hist``), it receives a
193
+ per-trial history object whose ``recall(varname, lag)`` method returns
194
+ the value of a variable `lag` steps earlier; see
195
+ :class:`funcsim.rdarrays.RDdata`. `f` must return a dict with
196
+ variable names (strings) as keys and floats as values. The number of
197
+ times `f` calls ``next(ugen)`` must be the same in every trial and
198
+ step, because draws are pre-allocated across trials for stratified
199
+ sampling.
197
200
  ntrials : int, optional
198
201
  The number of trials to perform. Default is 500.
199
202
  nsteps : int, optional
@@ -207,12 +210,14 @@ def simulate(f: Callable[[Generator[int, float, None],
207
210
  Use multiple processes/cores for the simulation. Default is False.
208
211
  When True, `f` must be picklable (e.g., defined at the top level of
209
212
  a module, not inside another function), because worker processes
210
- are spawned on most platforms.
213
+ are spawned on most platforms. For the same reason, a script that
214
+ calls ``simulate(..., multi=True)`` must guard the call with
215
+ ``if __name__ == "__main__":``.
211
216
  seed : int, optional
212
217
  Seed for pseudo-random number generation. Default is 6.
213
- stdnorm : book, optional
214
- If False, ``next(draw)`` within `trialf` will return standard uniform
215
- random draws. If True, ``next(draw)`` will return standard normal draws.
218
+ stdnorm : bool, optional
219
+ If False, ``next(ugen)`` within `f` returns standard uniform random
220
+ draws. If True, ``next(ugen)`` returns standard normal draws.
216
221
  Default is False.
217
222
  sampling : {'lh', 'mc'}, optional
218
223
  If 'lh', Latin Hypercube sampling is employed. If 'mc', simple
@@ -221,7 +226,22 @@ def simulate(f: Callable[[Generator[int, float, None],
221
226
  Returns
222
227
  -------
223
228
  xarray.DataArray
224
- 3-D xarray.DataArray with dimensions 'trials', 'variables', and 'steps'.
229
+ 3-D xarray.DataArray with dimensions 'trials', 'variables', and
230
+ 'steps'. The 'steps' coordinate continues the index of `hist0` (or
231
+ counts from 0 when `hist0` is not given), and includes any historical
232
+ steps from `hist0` ahead of the `nsteps` simulated steps.
233
+
234
+ Raises
235
+ ------
236
+ ValueError
237
+ If `hist0` is malformed, `f` is not callable or takes more than two
238
+ arguments, `f` does not return a dict keyed by strings, or `sampling`
239
+ is not one of 'lh' or 'mc'.
240
+ RuntimeError
241
+ If `f` consumes a different number of draws in some trial or step
242
+ than it did when first probed.
243
+ funcsim.rdarrays.MissingValue
244
+ If `f` recalls a lagged value that is not available.
225
245
  """
226
246
  if hist0 is not None:
227
247
  _checkhist0(hist0)
@@ -315,7 +315,7 @@ def cpt(utilFunc: Callable,
315
315
  Sequence of possible stochastic outcomes.
316
316
  refOutcome : float
317
317
  Reference point for gains and losses.
318
- probabilities : float or Iterable, optional
318
+ probabilities : Iterable of float, optional
319
319
  Probabilities for each outcome. If None, outcomes are assumed
320
320
  equally likely.
321
321
  precision : float, optional
@@ -436,7 +436,7 @@ def cptBV(outcomes: Iterable,
436
436
  Sequence of possible stochastic outcomes.
437
437
  refOutcome : float
438
438
  Reference point for gains and losses.
439
- probabilities : float or Iterable, optional
439
+ probabilities : Iterable of float, optional
440
440
  Probabilities for each outcome. If None, outcomes are assumed equally
441
441
  likely.
442
442
 
@@ -191,12 +191,17 @@ class MvKde():
191
191
  Parameters
192
192
  ----------
193
193
  data : ArrayLike
194
- Input data array of with variables in columns and observations
194
+ Input data array with variables in columns and observations
195
195
  in rows.
196
196
  bw : str or ArrayLike, optional
197
197
  Bandwidth selection method ('scott' or 'silverman'), or a K-by-K
198
198
  bandwidth covariance matrix in the units of the data.
199
199
  Default is 'scott'.
200
+
201
+ Notes
202
+ -----
203
+ Each call to :meth:`draw` consumes K + 1 values from ``ugen``, where K
204
+ is the number of variables.
200
205
  """
201
206
  def __init__(self,
202
207
  data: conversions.ArrayLike,
@@ -287,8 +292,14 @@ class MvNorm():
287
292
  Parameters
288
293
  ----------
289
294
  data : ArrayLike
290
- Input data array of with variables in columns and observations
295
+ Input data array with variables in columns and observations
291
296
  in rows.
297
+
298
+ Notes
299
+ -----
300
+ Each call to :meth:`draw` consumes K values from ``ugen``, where K is
301
+ the number of variables. A warning is issued for any variable whose
302
+ Shapiro-Wilk test rejects normality at the 5% level.
292
303
  """
293
304
  def __init__(self,
294
305
  data: conversions.ArrayLike,
@@ -330,11 +341,12 @@ class MvNorm():
330
341
  Returns
331
342
  -------
332
343
  pd.Series
333
- A pandas Series representing a joint draw from the KDE. The index
334
- values are the variable names, and the values are the random
335
- values. If no variable names were provided in the input data,
344
+ A pandas Series representing a joint draw from the multivariate
345
+ normal distribution. The index values are the variable names,
346
+ and the values are the random values. If no variable names were
347
+ provided in the input data,
336
348
  the variables will be named 'v0', 'v1', ..., reflecting the
337
- oreder of the columns in the input data.
349
+ order of the columns in the input data.
338
350
  """
339
351
  uvec = [next(ugen) for i in range(self._K)]
340
352
  retA = self._mu + np.dot(self._A, stats.norm.ppf(uvec))
@@ -353,10 +365,15 @@ class CopulaGauss():
353
365
  columns and observations in rows. That is, each column
354
366
  represents the result of applying the fitted CDF of some marginal
355
367
  distribution to the raw data for that variable. The
356
- values in each column should be in the range [0, 1]. The parameters
357
- are fit using the method of moments. If the sample covariance
358
- matrix is not positive definite, the Higham method is used to
359
- calculate the nearest positive definite matrix.
368
+ values in each column should be in the range (0, 1). The correlation
369
+ matrix is fit using the method of moments on the normal scores of
370
+ the pseudo-observations. If it is not positive definite, the Higham
371
+ method is used to calculate the nearest positive definite matrix.
372
+
373
+ Notes
374
+ -----
375
+ Each call to :meth:`draw` consumes K values from ``ugen``, where K is
376
+ the number of variables.
360
377
  """
361
378
 
362
379
  def __init__(self,
@@ -412,7 +429,7 @@ class CopulaGauss():
412
429
  standard uniform draws are the values in the Series.
413
430
  If no variable names were provided in the input data,
414
431
  the variables will be named 'v0', 'v1', ..., reflecting the
415
- oreder of the columns in the input data.
432
+ order of the columns in the input data.
416
433
 
417
434
  """
418
435
  uvec = [next(ugen) for i in range(self._K)]
@@ -432,9 +449,14 @@ class CopulaStudent():
432
449
  columns and observations in rows. That is, each column
433
450
  represents the result of applying the fitted CDF of some marginal
434
451
  distribution to the raw data for that variable. The
435
- values in each column should be in the range [0, 1]. The correlation
452
+ values in each column should be in the range (0, 1). The correlation
436
453
  matrix is fit by pairwise Kendall's-tau inversion, and the degrees
437
- of freedom are then fit by profile maximum likelihood.
454
+ of freedom are then fit by profile maximum pseudo-likelihood.
455
+
456
+ Notes
457
+ -----
458
+ Each call to :meth:`draw` consumes K + 1 values from ``ugen``, where K
459
+ is the number of variables.
438
460
  """
439
461
 
440
462
  def __init__(self,
@@ -477,7 +499,7 @@ class CopulaStudent():
477
499
  standard uniform draws are the values in the Series.
478
500
  If no variable names were provided in the input data,
479
501
  the variables will be named 'v0', 'v1', ..., reflecting the
480
- oreder of the columns in the input data.
502
+ order of the columns in the input data.
481
503
 
482
504
  """
483
505
  uvec = [next(ugen) for i in range(self._K)]
@@ -500,10 +522,18 @@ class CopulaClayton():
500
522
  columns and observations in rows. That is, each column
501
523
  represents the result of applying the fitted CDF of some marginal
502
524
  distribution to the raw data for that variable. The
503
- values in each column should be in the range [0, 1]. Parameters are
504
- fit using maximum likelihood. This implementation accomodates
525
+ values in each column should be in the range (0, 1). The dependence
526
+ parameter theta is fit by maximum pseudo-likelihood, starting from
527
+ the Kendall's-tau inversion estimate. This implementation accommodates
505
528
  only positive dependence, so the fitted value for theta is
506
529
  constrained to be > 0.
530
+
531
+ Notes
532
+ -----
533
+ Each call to :meth:`draw` consumes K + 1 values from ``ugen``, where K
534
+ is the number of variables. If the data exhibit negative dependence
535
+ (mean pairwise Kendall's tau <= 0), theta is set to its minimum
536
+ (near independence) and a warning is issued.
507
537
  """
508
538
 
509
539
  def __init__(self,
@@ -525,7 +555,7 @@ class CopulaClayton():
525
555
  (self._theta, taub, clamped) = copfit.fit_clayton(self._data)
526
556
  if clamped:
527
557
  warnings.warn(f"The Clayton copula implementation in funcsim "
528
- f"accomodates only positive dependence, but the "
558
+ f"accommodates only positive dependence, but the "
529
559
  f"data exhibit negative dependence (mean pairwise "
530
560
  f"Kendall's tau = {taub:.3f}). A theta value of "
531
561
  f"{copfit.THETA_MIN_CLAYTON} is being used rather "
@@ -557,7 +587,7 @@ class CopulaClayton():
557
587
  standard uniform draws are the values in the Series.
558
588
  If no variable names were provided in the input data,
559
589
  the variables will be named 'v0', 'v1', ..., reflecting the
560
- oreder of the columns in the input data.
590
+ order of the columns in the input data.
561
591
 
562
592
  """
563
593
  # floor the gamma frailty: for large theta the shape parameter is
@@ -582,10 +612,18 @@ class CopulaGumbel():
582
612
  columns and observations in rows. That is, each column
583
613
  represents the result of applying the fitted CDF of some marginal
584
614
  distribution to the raw data for that variable. The
585
- values in each column should be in the range [0, 1]. Parameters are
586
- fit using maximum likelihood. This implementation accomodates
615
+ values in each column should be in the range (0, 1). The dependence
616
+ parameter theta is fit by maximum pseudo-likelihood, starting from
617
+ the Kendall's-tau inversion estimate. This implementation accommodates
587
618
  only positive dependence, so the fitted value for theta is
588
619
  constrained to be > 1.0.
620
+
621
+ Notes
622
+ -----
623
+ Each call to :meth:`draw` consumes K + 2 values from ``ugen``, where K
624
+ is the number of variables. If the data exhibit negative dependence
625
+ (mean pairwise Kendall's tau <= 0), theta is set to its minimum
626
+ (near independence) and a warning is issued.
589
627
  """
590
628
 
591
629
  def __init__(self,
@@ -607,7 +645,7 @@ class CopulaGumbel():
607
645
  (self._theta, taub, clamped) = copfit.fit_gumbel(self._data)
608
646
  if clamped:
609
647
  warnings.warn(f"The Gumbel copula implementation in funcsim "
610
- f"accomodates only positive dependence, but the "
648
+ f"accommodates only positive dependence, but the "
611
649
  f"data exhibit negative dependence (mean pairwise "
612
650
  f"Kendall's tau = {taub:.3f}). A theta value of "
613
651
  f"(approximately) 1.0 is being used rather than a "
@@ -639,7 +677,7 @@ class CopulaGumbel():
639
677
  standard uniform draws are the values in the Series.
640
678
  If no variable names were provided in the input data,
641
679
  the variables will be named 'v0', 'v1', ..., reflecting the
642
- oreder of the columns in the input data.
680
+ order of the columns in the input data.
643
681
 
644
682
  """
645
683
  gamma = math.cos(0.5 * math.pi / self._theta)**self._theta
@@ -662,10 +700,18 @@ class CopulaFrank():
662
700
  columns and observations in rows. That is, each column
663
701
  represents the result of applying the fitted CDF of some marginal
664
702
  distribution to the raw data for that variable. The
665
- values in each column should be in the range [0, 1]. Parameters are
666
- fit using maximum likelihood. This implementation accomodates
703
+ values in each column should be in the range (0, 1). The dependence
704
+ parameter theta is fit by maximum pseudo-likelihood, starting from
705
+ the Kendall's-tau inversion estimate. This implementation accommodates
667
706
  only positive dependence, so the fitted value for theta is
668
707
  constrained to be > 0.
708
+
709
+ Notes
710
+ -----
711
+ Each call to :meth:`draw` consumes K + 2 values from ``ugen``, where K
712
+ is the number of variables. If the data exhibit negative dependence
713
+ (mean pairwise Kendall's tau <= 0), theta is set to its minimum
714
+ (near independence) and a warning is issued.
669
715
  """
670
716
 
671
717
  def __init__(self,
@@ -687,7 +733,7 @@ class CopulaFrank():
687
733
  (self._theta, taub, clamped) = copfit.fit_frank(self._data)
688
734
  if clamped:
689
735
  warnings.warn(f"The Frank copula implementation in funcsim "
690
- f"accomodates only positive dependence, but the "
736
+ f"accommodates only positive dependence, but the "
691
737
  f"data exhibit negative dependence (mean pairwise "
692
738
  f"Kendall's tau = {taub:.3f}). A theta value of "
693
739
  f"{copfit.THETA_MIN_FRANK} is being used rather "
@@ -716,7 +762,7 @@ class CopulaFrank():
716
762
  standard uniform draws are the values in the Series.
717
763
  If no variable names were provided in the input data,
718
764
  the variables will be named 'v0', 'v1', ..., reflecting the
719
- oreder of the columns in the input data.
765
+ order of the columns in the input data.
720
766
 
721
767
  """
722
768
  # Generate d uniform random variables
@@ -414,7 +414,8 @@ def fit(data: conversions.VectorLike,
414
414
  scipydist : scipy.stats.rv_continuous
415
415
  The scipy.stats distribution object to fit (e.g., stats.norm).
416
416
  distName : str, optional
417
- Name of the distribution. If None, the distribution's name is used.
417
+ Name recorded in the ``distName`` field of the result (for example,
418
+ the label used by ``compare``). Default None.
418
419
  lowerBound : float, optional
419
420
  If given, the lower bound of the support of the fitted distribution
420
421
  is fixed at this value rather than estimated. The distribution must
@@ -446,6 +447,8 @@ def fit(data: conversions.VectorLike,
446
447
  The frozen fitted distribution object.
447
448
  distName : str
448
449
  Name of the fitted distribution.
450
+ warnings : list
451
+ Warnings captured during fitting (empty for a clean fit).
449
452
 
450
453
  Raises
451
454
  ------
@@ -118,10 +118,14 @@ def kstest(data: conversions.VectorLike,
118
118
  ----------
119
119
  data : VectorLike
120
120
  Sample data vector.
121
- dist : str or frozen distribution object
122
- Scipy distribution name or frozen distribution object.
121
+ dist : str, scipy.stats distribution, or frozen distribution
122
+ The hypothesized distribution: the name of a ``scipy.stats``
123
+ distribution (e.g., ``"norm"``), an unfrozen distribution object
124
+ (e.g., ``stats.norm``), or a frozen distribution (e.g.,
125
+ ``stats.norm(0.0, 1.0)``).
123
126
  args : tuple, optional
124
- Parameters for the distribution if it is not a string.
127
+ Shape, location, and scale parameters, applied when `dist` is a name
128
+ or an unfrozen distribution. Ignored for a frozen distribution.
125
129
  assume_sorted : bool, optional
126
130
  If True, assumes that `data` is already sorted. Defaults to False.
127
131
 
@@ -146,10 +150,14 @@ def cvmtest(data: conversions.VectorLike,
146
150
  ----------
147
151
  data : VectorLike
148
152
  Sample data vector.
149
- dist : str or frozen distribution object
150
- Scipy distribution name or frozen distribution object.
153
+ dist : str, scipy.stats distribution, or frozen distribution
154
+ The hypothesized distribution: the name of a ``scipy.stats``
155
+ distribution (e.g., ``"norm"``), an unfrozen distribution object
156
+ (e.g., ``stats.norm``), or a frozen distribution (e.g.,
157
+ ``stats.norm(0.0, 1.0)``).
151
158
  args : tuple, optional
152
- Parameters for the distribution if it is not a string.
159
+ Shape, location, and scale parameters, applied when `dist` is a name
160
+ or an unfrozen distribution. Ignored for a frozen distribution.
153
161
  assume_sorted : bool, optional
154
162
  If True, assumes that `data` is already sorted. Defaults to False.
155
163
 
@@ -173,10 +181,14 @@ def adtest(data: conversions.VectorLike,
173
181
  ----------
174
182
  data : VectorLike
175
183
  Sample data vector.
176
- dist : str or frozen distribution object
177
- Scipy distribution name or frozen distribution object.
184
+ dist : str, scipy.stats distribution, or frozen distribution
185
+ The hypothesized distribution: the name of a ``scipy.stats``
186
+ distribution (e.g., ``"norm"``), an unfrozen distribution object
187
+ (e.g., ``stats.norm``), or a frozen distribution (e.g.,
188
+ ``stats.norm(0.0, 1.0)``).
178
189
  args : tuple, optional
179
- Parameters for the distribution if it is not a string.
190
+ Shape, location, and scale parameters, applied when `dist` is a name
191
+ or an unfrozen distribution. Ignored for a frozen distribution.
180
192
  assume_sorted : bool, optional
181
193
  If True, assumes that `data` is already sorted. Defaults to False.
182
194
 
@@ -53,7 +53,7 @@ def eut(util: Callable[[float], float],
53
53
  Compute expected utility and certainty equivalent income.
54
54
 
55
55
  This can operate on an arbitrary utility function, numerically solving
56
- for the certainty equivalent. For isoelastic expected utiliy and
56
+ for the certainty equivalent. For isoelastic expected utility and
57
57
  certainty equivalents, the function "eutIsoelastic" will be less
58
58
  likely to suffer from numerical problems.
59
59
 
@@ -74,7 +74,7 @@ def eut(util: Callable[[float], float],
74
74
  Named tuple with fields:
75
75
 
76
76
  ExpectedValue : float
77
- The mean isoelastic utility of the outcomes.
77
+ The mean utility of the outcomes.
78
78
  CertaintyEquiv : float
79
79
  The certainty equivalent income.
80
80
  """
@@ -40,12 +40,12 @@ def imanconover(spear: conversions.ArrayLike,
40
40
  )-> pd.DataFrame:
41
41
 
42
42
  """
43
- Induce a Spearman correlation stucture using the Iman & Conover method.
43
+ Induce a Spearman correlation structure using the Iman & Conover method.
44
44
 
45
45
  Parameters
46
46
  ----------
47
47
  spear : ArrayLike
48
- Desired Spearman correlation matrix (must be symetric and
48
+ Desired Spearman correlation matrix (must be symmetric and
49
49
  positive definite).
50
50
  vectors : list of VectorLike
51
51
  List of vectors, each representing draws for one variable.
@@ -59,7 +59,7 @@ def imanconover(spear: conversions.ArrayLike,
59
59
  -------
60
60
  pandas.DataFrame
61
61
  DataFrame with one column for each vector/variable, where the
62
- data refelct the desired Spearman correlation structure.
62
+ data reflect the desired Spearman correlation structure.
63
63
 
64
64
  References
65
65
  ----------
@@ -51,15 +51,18 @@ def fan(da: xr.DataArray,
51
51
  varname : str
52
52
  Name of the variable to plot from the "variables" dimension.
53
53
  filepath : str, optional
54
- Path to save the chart. Supports HTML and image formats. Default None.
54
+ Path to save the chart. A ``.html`` extension writes an interactive
55
+ HTML file; ``.png``, ``.jpg``, ``.jpeg``, ``.webp``, ``.svg``, and
56
+ ``.pdf`` write a static image, which requires the optional
57
+ ``kaleido`` package. Default None (do not save).
55
58
  line_color : str, optional
56
59
  Color of the mean line. Default is 'blue'.
57
60
  title : str, optional
58
61
  Title for the figure. Default is "" (no title).
59
62
  width : int, optional
60
- Width of the chart in pixels. Default is 800.
63
+ Width of the chart in pixels. Default is 750.
61
64
  height : int, optional
62
- Height of the chart in pixels. Default is 500.
65
+ Height of the chart in pixels. Default is 400.
63
66
 
64
67
  Returns
65
68
  -------
@@ -244,12 +247,12 @@ def twofuncs(f0: Callable[[float], float],
244
247
  Label for the first function. Default is "f0".
245
248
  name1 : str, optional
246
249
  Label for the second function. Default is "f1".
247
- title : str, optinal
248
- Title for the top of the figure. Defaults to None.
250
+ title : str, optional
251
+ Title for the figure. Default is "" (no title).
249
252
  width : int, optional
250
- Width of the chart in pixels. Default is 800.
253
+ Width of the chart in pixels. Default is 750.
251
254
  height : int, optional
252
- Height of the chart in pixels. Default is 500.
255
+ Height of the chart in pixels. Default is 400.
253
256
 
254
257
  Returns
255
258
  -------
@@ -309,9 +312,9 @@ def histpdf(data: conversions.VectorLike,
309
312
  title : str, optional
310
313
  Title for the figure. Default is "" (no title).
311
314
  width : int, optional
312
- Width of the chart in pixels. Default is 800.
315
+ Width of the chart in pixels. Default is 750.
313
316
  height : int, optional
314
- Height of the chart in pixels. Default is 500.
317
+ Height of the chart in pixels. Default is 400.
315
318
 
316
319
  Returns
317
320
  -------
@@ -389,7 +392,7 @@ def dblscat(a0: conversions.ArrayLike,
389
392
  title : str, optional
390
393
  Title for the figure. Default is "" (no title).
391
394
  width : int, optional
392
- Width of the chart in pixels. Default is 800.
395
+ Width of the chart in pixels. Default is 500.
393
396
  height : int, optional
394
397
  Height of the chart in pixels. Default is 500.
395
398
 
@@ -530,8 +533,10 @@ def show(fig):
530
533
  """
531
534
  Flexibly display a plotly plot in a Jupyter notebook.
532
535
 
533
- Invokes plotly's fig.show() with a `renderer` argument set to the value
534
- in the environment variable FUNCSIM_PLOTLY_RENDERER.
536
+ Invokes plotly's ``fig.show()`` with a `renderer` argument set to the
537
+ value of the environment variable ``FUNCSIM_PLOTLY_RENDERER`` (for
538
+ example ``"notebook"``, ``"vscode"``, ``"browser"``, or ``"png"``).
539
+ If the variable is not set, plotly's default renderer is used.
535
540
 
536
541
  Parameters
537
542
  ----------
@@ -3,10 +3,21 @@ import xarray as xr
3
3
 
4
4
 
5
5
  class MissingValue(Exception):
6
+ """Raised by :meth:`RDdata.recall` when a requested value is unavailable."""
6
7
  pass
7
8
 
8
9
 
9
10
  class RDdata():
11
+ """
12
+ Per-trial history for a recursive-dynamic simulation.
13
+
14
+ ``simulate`` passes an instance of this class as the second argument
15
+ (conventionally ``hist``) to a step function that accepts two
16
+ arguments. It holds the historical values supplied via ``hist0``
17
+ followed by the values the step function has returned so far in the
18
+ current trial. Step functions should only call :meth:`recall`; the
19
+ class is not meant to be instantiated by users.
20
+ """
10
21
  # container for an np array with pre-allocated memory for future values
11
22
  # for a single trial in an RD sim
12
23
  def __init__(self, a, steps, namePositions):
@@ -48,7 +59,9 @@ class RDdata():
48
59
  varname : str
49
60
  Name of the variable to recall.
50
61
  lag : int, optional
51
- Number of steps to lag (default is 0).
62
+ Number of steps to look back. ``lag=1`` is the previous step
63
+ (the most recent value available while a step is being
64
+ computed). Default is 0.
52
65
 
53
66
  Returns
54
67
  -------
@@ -73,7 +86,7 @@ class RDdata():
73
86
  f'simulation, no (non-NaN) value for the '
74
87
  f'variable "{varname}" with {lag} lag(s) is '
75
88
  f'available. Be sure that you passed a '
76
- f'a "data0" array to "simulate" and that it '
89
+ f'"hist0" array to "simulate" and that it '
77
90
  f'contains this value.')
78
91
  else:
79
92
  raise MissingValue(f'In time step {self._currStep} in the '
@@ -351,8 +351,17 @@ def screen(data: conversions.VectorLike,
351
351
  Returns
352
352
  -------
353
353
  str
354
- A formatted string summarizing the results of stationarity,
354
+ A formatted string summarizing the results of stationarity,
355
355
  heteroskedasticity, autocorrelation, and randomness tests.
356
+
357
+ Notes
358
+ -----
359
+ Line A is an augmented Dickey-Fuller (ADF) test whose equation includes
360
+ a constant, so its alternative is stationarity around a constant
361
+ (possibly nonzero) mean. Line B adds a linear time trend, so its
362
+ alternative is trend stationarity. Lines C (White) and D (Ljung-Box)
363
+ are applied to the residuals from a regression of the series on the
364
+ observation number. Lines E and F test the overall i.i.d. null.
356
365
  """
357
366
 
358
367
  if alpha <= 0 or alpha >= 1:
@@ -369,9 +378,13 @@ def screen(data: conversions.VectorLike,
369
378
  y_hat = X @ beta
370
379
  resid = y - y_hat
371
380
 
372
- # ADF tests: line A has no deterministic terms; line B includes a
373
- # constant and linear trend, so it is a genuine trend-stationarity test
374
- p_adf = adf_test_no_const(seriesA, max_lag=2, n_sim=1000, seed=42)[1]
381
+ # ADF tests: line A includes a constant, so it tests for stationarity
382
+ # around a constant mean (a no-constant equation has zero-mean
383
+ # stationarity as its alternative, so it fails to reject the unit root,
384
+ # and the report warns, for an i.i.d. series whose mean is large
385
+ # relative to its standard deviation); line B includes a constant and
386
+ # a linear trend, so it is a genuine trend-stationarity test
387
+ p_adf = adf_test_with_const(seriesA, max_lag=2, n_sim=1000, seed=42)[1]
375
388
  p_adf_t = adf_test_const_trend(seriesA, max_lag=2, n_sim=1000, seed=42)[1]
376
389
 
377
390
  # White test for heteroskedasticity (constant is added inside
@@ -216,12 +216,19 @@ def shrink(data: conversions.ArrayLike,
216
216
  data : ArrayLike
217
217
  Data array with variables in columns and observations in rows.
218
218
  target : str
219
- Shrinkage target, one of: 'A', 'B', 'C', 'D', 'E', 'F'. These
220
- correspond to different shrinkage estimation methods as defined in
221
- Shafer & Strimmer, "A shrinkage approach to large-scale covariance
222
- matrix estimation and implications for Functional Genomics."
223
- //Statistical Applications in Genetics and Molecular Biology//,
224
- vol 4(2005), issue 1.
219
+ Shrinkage target, one of 'A' through 'F', following Table 2 of
220
+ Schafer and Strimmer (2005):
221
+
222
+ - 'A': diagonal, unit variance
223
+ - 'B': diagonal, common variance
224
+ - 'C': common variance and common covariance
225
+ - 'D': diagonal, unequal variance
226
+ - 'E': perfect positive correlation
227
+ - 'F': constant correlation
228
+
229
+ Targets 'B', 'E', and 'F' originate in Ledoit and Wolf (2003,
230
+ 2004). The shrinkage intensity is estimated analytically in each
231
+ case.
225
232
 
226
233
  Returns
227
234
  -------
@@ -232,6 +239,13 @@ def shrink(data: conversions.ArrayLike,
232
239
  ------
233
240
  ValueError
234
241
  If target is not one of: 'A', 'B', 'C', 'D', 'E', 'F'.
242
+
243
+ References
244
+ ----------
245
+ Schafer, J., & Strimmer, K. (2005). A shrinkage approach to large-scale
246
+ covariance matrix estimation and implications for functional genomics.
247
+ Statistical Applications in Genetics and Molecular Biology, 4(1),
248
+ Article 32.
235
249
  """
236
250
  if target not in ['A', 'B', 'C', 'D', 'E', 'F']:
237
251
  raise ValueError("target must be one of: A, B, C, D, E, F")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: funcsim
3
- Version: 0.2.3
3
+ Version: 0.2.4
4
4
  Summary: functional, simple stochastic simulation
5
5
  Home-page: https://github.com/h-bryant/funcsim
6
6
  Author: Henry Bryant
@@ -46,35 +46,43 @@ Dynamic: summary
46
46
  # funcsim
47
47
  Lightweight, functional stochastic simulation
48
48
 
49
+ Documentation: https://funcsim.readthedocs.io/
50
+
49
51
  Features:
50
- - cross-sectional and recursive dynamic simulations
51
- - pseudo-random numbers (so that results are comparable across multiple runs or scenarios)
52
+ - static (cross-sectional) and recursive-dynamic simulations from a single user-written function
53
+ - pseudo-random numbers with an explicit seed (so that results are reproducible and comparable across runs or scenarios)
52
54
  - stratified/Latin hypercube sampling
53
55
  - painless multi-core simulations
56
+ - fitting and comparison of univariate distributions, kernel density estimates, and goodness-of-fit tests
57
+ - multivariate normal and KDE distributions; Gaussian, Student's t, Clayton, Gumbel, and Frank copulas (implemented natively, no additional packages required); Iman-Conover
58
+ - expected utility and cumulative prospect theory calculations
59
+ - plotly-based fan charts and diagnostic plots
54
60
  - highly flexible, and as simple as possible (but no more)
55
61
  - functional paradigm
56
62
 
57
- Developed using:
58
- - python >= 3.10
59
- - numpy 2.2.0
60
- - scipy 1.16.0
61
- - pandas 2.2.0 (pandas 2.2+ and 3.x are both supported)
62
- - xarray 2025.4.0
63
-
64
- Copulas (Gaussian, Student's t, Clayton, Gumbel, and Frank) are supported
65
- natively; no additional packages are required.
63
+ Requirements:
64
+ - python >= 3.11
65
+ - numpy >= 2.2.0
66
+ - scipy >= 1.16.0
67
+ - pandas >= 2.2.0 (pandas 2.2+ and 3.x are both supported)
68
+ - xarray >= 2025.4.0
66
69
 
67
- For optional functionality, additinoal packages are needed:
68
- - plotting: plotly
70
+ For optional functionality, additional packages are needed:
71
+ - plotting: plotly (`pip install "funcsim[plotting]"`); kaleido for static image export
69
72
 
70
- Additionally, to run the demos, run tests, and build docs:
73
+ Additionally, to run the tests and build the docs:
71
74
  - pytest
72
- - sphinx, sphinx-autodoc-typehints
75
+ - sphinx, sphinx-autodoc-typehints (`pip install "funcsim[docs]"`)
76
+
77
+ ### installation
78
+ ```bash
79
+ pip install funcsim
80
+ ```
73
81
 
74
82
  ### building html docs
75
83
  From the top-level funcsim directory...
76
84
  ```bash
77
- sphinx-build -b html docs/source/ docs/build/
85
+ sphinx-build -W -b html docs/source/ docs/build/
78
86
  ```
79
87
 
80
88
  ### running tests
@@ -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.3",
8
+ version="0.2.4",
9
9
  license="bsd-3-clause",
10
10
  author="Henry Bryant",
11
11
  author_email="henry@tamu.edu",
funcsim-0.2.3/README.md DELETED
@@ -1,39 +0,0 @@
1
- # funcsim
2
- Lightweight, functional stochastic simulation
3
-
4
- Features:
5
- - cross-sectional and recursive dynamic simulations
6
- - pseudo-random numbers (so that results are comparable across multiple runs or scenarios)
7
- - stratified/Latin hypercube sampling
8
- - painless multi-core simulations
9
- - highly flexible, and as simple as possible (but no more)
10
- - functional paradigm
11
-
12
- Developed using:
13
- - python >= 3.10
14
- - numpy 2.2.0
15
- - scipy 1.16.0
16
- - pandas 2.2.0 (pandas 2.2+ and 3.x are both supported)
17
- - xarray 2025.4.0
18
-
19
- Copulas (Gaussian, Student's t, Clayton, Gumbel, and Frank) are supported
20
- natively; no additional packages are required.
21
-
22
- For optional functionality, additinoal packages are needed:
23
- - plotting: plotly
24
-
25
- Additionally, to run the demos, run tests, and build docs:
26
- - pytest
27
- - sphinx, sphinx-autodoc-typehints
28
-
29
- ### building html docs
30
- From the top-level funcsim directory...
31
- ```bash
32
- sphinx-build -b html docs/source/ docs/build/
33
- ```
34
-
35
- ### running tests
36
- From the top-level funcsim directory...
37
- ```bash
38
- python3 -m pytest
39
- ```
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