mergeron 2025.739265.0__tar.gz → 2025.739265.2__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.
Potentially problematic release.
This version of mergeron might be problematic. Click here for more details.
- {mergeron-2025.739265.0 → mergeron-2025.739265.2}/PKG-INFO +1 -1
- {mergeron-2025.739265.0 → mergeron-2025.739265.2}/pyproject.toml +3 -3
- {mergeron-2025.739265.0 → mergeron-2025.739265.2}/src/mergeron/__init__.py +1 -1
- {mergeron-2025.739265.0 → mergeron-2025.739265.2}/src/mergeron/core/__init__.py +2 -2
- {mergeron-2025.739265.0 → mergeron-2025.739265.2}/src/mergeron/core/empirical_margin_distribution.py +2 -2
- {mergeron-2025.739265.0 → mergeron-2025.739265.2}/src/mergeron/core/ftc_merger_investigations_data.py +1 -1
- {mergeron-2025.739265.0 → mergeron-2025.739265.2}/src/mergeron/core/guidelines_boundaries.py +2 -2
- {mergeron-2025.739265.0 → mergeron-2025.739265.2}/src/mergeron/core/guidelines_boundary_functions.py +1 -1
- {mergeron-2025.739265.0 → mergeron-2025.739265.2}/src/mergeron/core/guidelines_boundary_functions_extra.py +4 -4
- {mergeron-2025.739265.0 → mergeron-2025.739265.2}/src/mergeron/core/pseudorandom_numbers.py +115 -103
- {mergeron-2025.739265.0 → mergeron-2025.739265.2}/src/mergeron/demo/visualize_empirical_margin_distribution.py +1 -1
- {mergeron-2025.739265.0 → mergeron-2025.739265.2}/src/mergeron/gen/__init__.py +5 -5
- {mergeron-2025.739265.0 → mergeron-2025.739265.2}/src/mergeron/gen/data_generation.py +3 -3
- {mergeron-2025.739265.0 → mergeron-2025.739265.2}/src/mergeron/gen/data_generation_functions.py +6 -5
- {mergeron-2025.739265.0 → mergeron-2025.739265.2}/src/mergeron/gen/upp_tests.py +3 -3
- {mergeron-2025.739265.0 → mergeron-2025.739265.2}/README.rst +0 -0
- {mergeron-2025.739265.0 → mergeron-2025.739265.2}/src/mergeron/data/__init__.py +0 -0
- {mergeron-2025.739265.0 → mergeron-2025.739265.2}/src/mergeron/data/damodaran_margin_data.xls +0 -0
- {mergeron-2025.739265.0 → mergeron-2025.739265.2}/src/mergeron/data/damodaran_margin_data_dict.msgpack +0 -0
- {mergeron-2025.739265.0 → mergeron-2025.739265.2}/src/mergeron/data/ftc_invdata.msgpack +0 -0
- {mergeron-2025.739265.0 → mergeron-2025.739265.2}/src/mergeron/demo/__init__.py +0 -0
- {mergeron-2025.739265.0 → mergeron-2025.739265.2}/src/mergeron/gen/enforcement_stats.py +0 -0
- {mergeron-2025.739265.0 → mergeron-2025.739265.2}/src/mergeron/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: mergeron
|
|
3
|
-
Version: 2025.739265.
|
|
3
|
+
Version: 2025.739265.2
|
|
4
4
|
Summary: Analyze merger enforcement policy using Python
|
|
5
5
|
License: MIT
|
|
6
6
|
Keywords: merger policy analysis,merger guidelines,merger screening,policy presumptions,concentration standards,upward pricing pressure,GUPPI
|
|
@@ -13,7 +13,7 @@ keywords = [
|
|
|
13
13
|
"upward pricing pressure",
|
|
14
14
|
"GUPPI",
|
|
15
15
|
]
|
|
16
|
-
version = "2025.739265.
|
|
16
|
+
version = "2025.739265.2"
|
|
17
17
|
|
|
18
18
|
# Classifiers list: https://pypi.org/classifiers/
|
|
19
19
|
classifiers = [
|
|
@@ -61,6 +61,7 @@ urllib3 = "^2.2.2"
|
|
|
61
61
|
|
|
62
62
|
[tool.poetry.group.dev.dependencies]
|
|
63
63
|
icecream = ">=2.1.0"
|
|
64
|
+
jinja2 = ">=3.1.5"
|
|
64
65
|
mypy = ">=1.8"
|
|
65
66
|
openpyxl = ">=3.1.2"
|
|
66
67
|
pendulum = ">=3.0.0"
|
|
@@ -74,8 +75,7 @@ sphinx-autoapi = ">=3.0"
|
|
|
74
75
|
sphinx-immaterial = ">=0.11"
|
|
75
76
|
pipdeptree = ">=2.15.1"
|
|
76
77
|
types-openpyxl = ">=3.0.0"
|
|
77
|
-
|
|
78
|
-
|
|
78
|
+
virtualenv = ">=20.28.0"
|
|
79
79
|
[tool.ruff]
|
|
80
80
|
|
|
81
81
|
# Exclude a variety of commonly ignored directories.
|
{mergeron-2025.739265.0 → mergeron-2025.739265.2}/src/mergeron/core/empirical_margin_distribution.py
RENAMED
|
@@ -132,7 +132,7 @@ def mgn_data_getter( # noqa: PLR0912
|
|
|
132
132
|
_xl_row[1] = int(_xl_row[1])
|
|
133
133
|
_mgn_dict[_xl_row[0]] = dict(zip(_mgn_row_keys[1:], _xl_row[1:], strict=True))
|
|
134
134
|
|
|
135
|
-
_ = _data_archive_path.write_bytes(msgpack.packb(_mgn_dict))
|
|
135
|
+
_ = _data_archive_path.write_bytes(msgpack.packb(_mgn_dict))
|
|
136
136
|
|
|
137
137
|
return MappingProxyType(_mgn_dict)
|
|
138
138
|
|
|
@@ -221,7 +221,7 @@ def mgn_data_resampler(
|
|
|
221
221
|
_x, _w, _ = mgn_data_builder(mgn_data_getter())
|
|
222
222
|
|
|
223
223
|
_mgn_kde = stats.gaussian_kde(_x, weights=_w, bw_method="silverman")
|
|
224
|
-
_mgn_kde.set_bandwidth(bw_method=_mgn_kde.factor / 3.0)
|
|
224
|
+
_mgn_kde.set_bandwidth(bw_method=_mgn_kde.factor / 3.0)
|
|
225
225
|
|
|
226
226
|
if isinstance(_sample_size, int):
|
|
227
227
|
return np.array(
|
{mergeron-2025.739265.0 → mergeron-2025.739265.2}/src/mergeron/core/guidelines_boundaries.py
RENAMED
|
@@ -156,7 +156,7 @@ class ConcentrationBoundary:
|
|
|
156
156
|
"ΔHHI", "Combined share", "Pre-merger HHI", "Post-merger HHI"
|
|
157
157
|
] = field(kw_only=False, default="ΔHHI")
|
|
158
158
|
|
|
159
|
-
@measure_name.validator
|
|
159
|
+
@measure_name.validator
|
|
160
160
|
def __mnv(
|
|
161
161
|
_instance: ConcentrationBoundary, _attribute: Attribute[str], _value: str, /
|
|
162
162
|
) -> None:
|
|
@@ -170,7 +170,7 @@ class ConcentrationBoundary:
|
|
|
170
170
|
|
|
171
171
|
threshold: float = field(kw_only=False, default=0.01)
|
|
172
172
|
|
|
173
|
-
@threshold.validator
|
|
173
|
+
@threshold.validator
|
|
174
174
|
def __tv(
|
|
175
175
|
_instance: ConcentrationBoundary, _attribute: Attribute[float], _value: float, /
|
|
176
176
|
) -> None:
|
|
@@ -91,7 +91,7 @@ def hhi_delta_boundary_qdtr(_dh_val: float = 0.01, /) -> GuidelinesBoundaryCalla
|
|
|
91
91
|
|
|
92
92
|
_hhi_bdry_area = 2 * (
|
|
93
93
|
_s_nought
|
|
94
|
-
+ mp.quad(lambdify(_s_1, _hhi_bdry, "mpmath"), (_s_nought, 1 - _s_nought))
|
|
94
|
+
+ mp.quad(lambdify(_s_1, _hhi_bdry, "mpmath"), (_s_nought, 1 - _s_nought))
|
|
95
95
|
)
|
|
96
96
|
|
|
97
97
|
return GuidelinesBoundaryCallable(
|
|
@@ -159,7 +159,7 @@ def shrratio_boundary_qdtr_wtd_avg(
|
|
|
159
159
|
2
|
|
160
160
|
* (
|
|
161
161
|
_s_naught
|
|
162
|
-
+ mp.quad(lambdify(_s_1, _bdry_func, "mpmath"), (_s_naught, _s_mid))
|
|
162
|
+
+ mp.quad(lambdify(_s_1, _bdry_func, "mpmath"), (_s_naught, _s_mid))
|
|
163
163
|
)
|
|
164
164
|
- (_s_mid**2 + _s_naught**2)
|
|
165
165
|
)
|
|
@@ -189,7 +189,7 @@ def shrratio_boundary_qdtr_wtd_avg(
|
|
|
189
189
|
),
|
|
190
190
|
(0, _s_mid),
|
|
191
191
|
)
|
|
192
|
-
).real
|
|
192
|
+
).real
|
|
193
193
|
- _s_mid**2
|
|
194
194
|
)
|
|
195
195
|
|
|
@@ -209,7 +209,7 @@ def shrratio_boundary_qdtr_wtd_avg(
|
|
|
209
209
|
|
|
210
210
|
_bdry_func = solve(_bdry_eqn, _s_2)[0]
|
|
211
211
|
_bdry_area = float(
|
|
212
|
-
2 * (mp.quad(lambdify(_s_1, _bdry_func, "mpmath"), (0, _s_mid)))
|
|
212
|
+
2 * (mp.quad(lambdify(_s_1, _bdry_func, "mpmath"), (0, _s_mid)))
|
|
213
213
|
- _s_mid**2
|
|
214
214
|
)
|
|
215
215
|
|
|
@@ -6,12 +6,15 @@ https://github.com/numpy/numpy/issues/16313.
|
|
|
6
6
|
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
9
11
|
import concurrent.futures
|
|
10
12
|
from collections.abc import Sequence
|
|
11
13
|
from multiprocessing import cpu_count
|
|
12
14
|
from typing import Literal
|
|
13
15
|
|
|
14
16
|
import numpy as np
|
|
17
|
+
from attrs import Attribute, define, field
|
|
15
18
|
from numpy.random import PCG64DXSM, Generator, SeedSequence
|
|
16
19
|
|
|
17
20
|
from .. import VERSION, ArrayDouble # noqa: TID252
|
|
@@ -19,7 +22,8 @@ from .. import VERSION, ArrayDouble # noqa: TID252
|
|
|
19
22
|
__version__ = VERSION
|
|
20
23
|
|
|
21
24
|
NTHREADS = 2 * cpu_count()
|
|
22
|
-
DEFAULT_DIST_PARMS = np.array([0.0, 1.0],
|
|
25
|
+
DEFAULT_DIST_PARMS: ArrayDouble = np.array([0.0, 1.0], float)
|
|
26
|
+
DEFAULT_BETA_DIST_PARMS: ArrayDouble = np.array([1.0, 1.0], float)
|
|
23
27
|
|
|
24
28
|
|
|
25
29
|
def prng(_s: SeedSequence | None = None, /) -> np.random.Generator:
|
|
@@ -106,6 +110,7 @@ def gen_seed_seq_list_default(
|
|
|
106
110
|
return [SeedSequence(_s, pool_size=8) for _s in generated_entropy[:_sseq_list_len]]
|
|
107
111
|
|
|
108
112
|
|
|
113
|
+
@define
|
|
109
114
|
class MultithreadedRNG:
|
|
110
115
|
"""Fill given array on demand with pseudo-random numbers as specified.
|
|
111
116
|
|
|
@@ -114,93 +119,102 @@ class MultithreadedRNG:
|
|
|
114
119
|
If a seed sequence is provided, it is used in a thread-safe way
|
|
115
120
|
to generate repeatable i.i.d. draws. All arguments are validated
|
|
116
121
|
before commencing multithreaded random number generation.
|
|
122
|
+
"""
|
|
117
123
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
__out_array
|
|
121
|
-
The output array to which generated data are written.
|
|
122
|
-
Its dimensions define the size of the sample.
|
|
123
|
-
dist_type
|
|
124
|
-
Distribution for the generated random numbers
|
|
125
|
-
dist_parms
|
|
126
|
-
Parameters, if any, for tailoring random number generation
|
|
127
|
-
seed_sequence
|
|
128
|
-
SeedSequence object for generating repeatable draws.
|
|
129
|
-
nthreads
|
|
130
|
-
Number of threads to spawn for random number generation.
|
|
124
|
+
values: ArrayDouble = field(kw_only=False, default=None)
|
|
125
|
+
"""Output array to which generated data are over-written
|
|
131
126
|
|
|
127
|
+
Array-length defines the number of i.i.d. (vector) draws.
|
|
132
128
|
"""
|
|
133
129
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
):
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
if dist_type not in (_rdts := ("Beta", "Dirichlet", "Normal", "Uniform")):
|
|
156
|
-
raise ValueError("Specified distribution must be one of {_rdts}")
|
|
157
|
-
|
|
158
|
-
if not (dist_parms is None or isinstance(dist_parms, Sequence | np.ndarray)):
|
|
159
|
-
raise ValueError(
|
|
160
|
-
"When specified, distribution parameters must be a list, tuple or Numpy array"
|
|
161
|
-
)
|
|
162
|
-
if isinstance(dist_parms, Sequence):
|
|
163
|
-
dist_parms = np.array(dist_parms)
|
|
164
|
-
elif not dist_parms.any():
|
|
165
|
-
dist_parms = None
|
|
166
|
-
|
|
167
|
-
self.dist_type = dist_type
|
|
168
|
-
|
|
169
|
-
if dist_parms is None or np.array_equal(dist_parms, DEFAULT_DIST_PARMS):
|
|
170
|
-
match dist_type:
|
|
171
|
-
case "Uniform":
|
|
172
|
-
self.dist_type = "Random"
|
|
173
|
-
case "Normal":
|
|
174
|
-
self.dist_type = "Gaussian"
|
|
175
|
-
case "Beta" | "Dirichlet":
|
|
176
|
-
raise ValueError(
|
|
177
|
-
f"parameter specification, {f'"{dist_parms}"'} "
|
|
178
|
-
f"is invalid for specified distribution, f{'"{dist_type}"'}."
|
|
179
|
-
)
|
|
180
|
-
case _:
|
|
181
|
-
raise ValueError(
|
|
182
|
-
f"Invalid distributions specified, {f'"{dist_type}"'}."
|
|
183
|
-
)
|
|
130
|
+
dist_type: Literal[
|
|
131
|
+
"Beta", "Dirichlet", "Gaussian", "Normal", "Random", "Uniform"
|
|
132
|
+
] = field(kw_only=True, default="Uniform")
|
|
133
|
+
"""Distribution for the generated random numbers.
|
|
134
|
+
|
|
135
|
+
Default is "Uniform".
|
|
136
|
+
"""
|
|
137
|
+
|
|
138
|
+
@dist_type.validator
|
|
139
|
+
def __dtv(
|
|
140
|
+
_instance: MultithreadedRNG, _attribute: Attribute[str], _value: str, /
|
|
141
|
+
) -> None:
|
|
142
|
+
if _value not in (
|
|
143
|
+
_rdts := ("Beta", "Dirichlet", "Gaussian", "Normal", "Random", "Uniform")
|
|
144
|
+
):
|
|
145
|
+
raise ValueError(f"Specified distribution must be one of {_rdts}")
|
|
146
|
+
|
|
147
|
+
dist_parms: ArrayDouble | None = field(kw_only=True, default=DEFAULT_DIST_PARMS)
|
|
148
|
+
"""Parameters, if any, for tailoring random number generation
|
|
149
|
+
"""
|
|
184
150
|
|
|
185
|
-
|
|
186
|
-
|
|
151
|
+
@dist_parms.validator
|
|
152
|
+
def __dpv(
|
|
153
|
+
_instance: MultithreadedRNG, _attribute: Attribute[str], _value: ArrayDouble, /
|
|
154
|
+
) -> None:
|
|
155
|
+
if _value is not None:
|
|
156
|
+
if not isinstance(_value, Sequence | np.ndarray):
|
|
187
157
|
raise ValueError(
|
|
188
|
-
|
|
189
|
-
f"of size, {__out_array.shape}"
|
|
158
|
+
"When specified, distribution parameters must be a list, tuple or Numpy array"
|
|
190
159
|
)
|
|
191
160
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
161
|
+
elif (
|
|
162
|
+
_instance.dist_type != "Dirichlet"
|
|
163
|
+
and (_lrdp := len(_value)) != (_trdp := 2)
|
|
164
|
+
) or (
|
|
165
|
+
_instance.dist_type == "Dirichlet"
|
|
166
|
+
and (_lrdp := len(_value)) != (_trdp := _instance.values.shape[1])
|
|
167
|
+
):
|
|
168
|
+
raise ValueError(f"Expected {_trdp} parameters, got, {_lrdp}")
|
|
169
|
+
|
|
170
|
+
elif (
|
|
171
|
+
_instance.dist_type in ("Beta", "Dirichlet")
|
|
172
|
+
and (np.array(_value) <= 0.0).any()
|
|
173
|
+
):
|
|
174
|
+
raise ValueError(
|
|
175
|
+
"Shape and location parameters must be strictly positive"
|
|
176
|
+
)
|
|
196
177
|
|
|
197
|
-
|
|
198
|
-
|
|
178
|
+
seed_sequence: SeedSequence | None = field(kw_only=True, default=None)
|
|
179
|
+
"""Seed sequence for generating random numbers."""
|
|
199
180
|
|
|
200
|
-
|
|
181
|
+
nthreads: int = field(kw_only=True, default=NTHREADS)
|
|
182
|
+
"""Number of threads to spawn for random number generation."""
|
|
201
183
|
|
|
202
184
|
def fill(self) -> None:
|
|
203
|
-
"""Fill the provided output array with random
|
|
185
|
+
"""Fill the provided output array with random number draws as specified."""
|
|
186
|
+
|
|
187
|
+
if (
|
|
188
|
+
self.dist_parms is None
|
|
189
|
+
or not (
|
|
190
|
+
_dist_parms := np.array(self.dist_parms) # one-shot conversion
|
|
191
|
+
).any()
|
|
192
|
+
):
|
|
193
|
+
if self.dist_type == "Beta":
|
|
194
|
+
_dist_parms = DEFAULT_BETA_DIST_PARMS
|
|
195
|
+
elif self.dist_type == "Dirichlet":
|
|
196
|
+
_dist_parms = np.ones(self.values.shape[1], float)
|
|
197
|
+
else:
|
|
198
|
+
_dist_parms = DEFAULT_DIST_PARMS
|
|
199
|
+
|
|
200
|
+
if self.dist_parms is None or np.array_equal(
|
|
201
|
+
self.dist_parms, DEFAULT_DIST_PARMS
|
|
202
|
+
):
|
|
203
|
+
if self.dist_type == "Uniform":
|
|
204
|
+
_dist_type = "Random"
|
|
205
|
+
elif self.dist_type == "Normal":
|
|
206
|
+
_dist_type = "Gaussian"
|
|
207
|
+
else:
|
|
208
|
+
_dist_type = self.dist_type
|
|
209
|
+
|
|
210
|
+
_step_size = (len(self.values) / self.nthreads).__ceil__()
|
|
211
|
+
# int; function gives float unsuitable for slicing
|
|
212
|
+
|
|
213
|
+
_seed_sequence = self.seed_sequence or SeedSequence(pool_size=8)
|
|
214
|
+
|
|
215
|
+
_random_generators = tuple(
|
|
216
|
+
prng(_t) for _t in _seed_sequence.spawn(self.nthreads)
|
|
217
|
+
)
|
|
204
218
|
|
|
205
219
|
def _fill(
|
|
206
220
|
_rng: np.random.Generator,
|
|
@@ -213,37 +227,35 @@ class MultithreadedRNG:
|
|
|
213
227
|
) -> None:
|
|
214
228
|
_sz: tuple[int, ...] = _out[_first:_last].shape
|
|
215
229
|
match _dist_type:
|
|
216
|
-
case "Random":
|
|
217
|
-
_rng.random(out=_out[_first:_last])
|
|
218
|
-
case "Uniform":
|
|
219
|
-
_uni_l, _uni_h = _dist_parms
|
|
220
|
-
_out[_first:_last] = _rng.uniform(_uni_l, _uni_h, size=_sz)
|
|
221
|
-
case "Dirichlet":
|
|
222
|
-
_out[_first:_last] = _rng.dirichlet(_dist_parms, size=_sz[:-1])
|
|
223
230
|
case "Beta":
|
|
224
231
|
_shape_a, _shape_b = _dist_parms
|
|
225
232
|
_out[_first:_last] = _rng.beta(_shape_a, _shape_b, size=_sz)
|
|
233
|
+
case "Dirichlet":
|
|
234
|
+
_out[_first:_last] = _rng.dirichlet(_dist_parms, size=_sz[:-1])
|
|
235
|
+
case "Gaussian":
|
|
236
|
+
_rng.standard_normal(out=_out[_first:_last])
|
|
226
237
|
case "Normal":
|
|
227
238
|
_mu, _sigma = _dist_parms
|
|
228
239
|
_out[_first:_last] = _rng.normal(_mu, _sigma, size=_sz)
|
|
240
|
+
case "Random":
|
|
241
|
+
_rng.random(out=_out[_first:_last])
|
|
242
|
+
case "Uniform":
|
|
243
|
+
_uni_l, _uni_h = _dist_parms
|
|
244
|
+
_out[_first:_last] = _rng.uniform(_uni_l, _uni_h, size=_sz)
|
|
229
245
|
case _:
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
futures
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
concurrent.futures.wait(futures)
|
|
247
|
-
|
|
248
|
-
def __del__(self) -> None:
|
|
249
|
-
self.executor.shutdown(False)
|
|
246
|
+
"Unreachable. The validator would have rejected this as invalid."
|
|
247
|
+
|
|
248
|
+
with concurrent.futures.ThreadPoolExecutor(self.nthreads) as _executor:
|
|
249
|
+
for i in range(self.nthreads):
|
|
250
|
+
_range_first = i * _step_size
|
|
251
|
+
_range_last = min(len(self.values), (i + 1) * _step_size)
|
|
252
|
+
|
|
253
|
+
_executor.submit(
|
|
254
|
+
_fill,
|
|
255
|
+
_random_generators[i],
|
|
256
|
+
_dist_type,
|
|
257
|
+
_dist_parms,
|
|
258
|
+
self.values,
|
|
259
|
+
_range_first,
|
|
260
|
+
_range_last,
|
|
261
|
+
)
|
|
@@ -45,7 +45,7 @@ with warnings.catch_warnings():
|
|
|
45
45
|
])
|
|
46
46
|
|
|
47
47
|
mgn_kde = stats.gaussian_kde(mgn_data_obs, weights=mgn_data_wts, bw_method="silverman")
|
|
48
|
-
mgn_kde.set_bandwidth(bw_method=mgn_kde.factor / 3.0)
|
|
48
|
+
mgn_kde.set_bandwidth(bw_method=mgn_kde.factor / 3.0)
|
|
49
49
|
|
|
50
50
|
mgn_ax.plot(
|
|
51
51
|
(_xv := np.linspace(0, BIN_COUNT, 10**5) / BIN_COUNT),
|
|
@@ -70,7 +70,7 @@ class SHRDistribution(enum.StrEnum):
|
|
|
70
70
|
DIR_FLAT_CONSTR = "Flat Dirichlet - Constrained"
|
|
71
71
|
"""Impose minimum probablility weight on each firm-count
|
|
72
72
|
|
|
73
|
-
Only firm-counts with probability weight of
|
|
73
|
+
Only firm-counts with probability weight of 3% or more
|
|
74
74
|
are included for data generation.
|
|
75
75
|
"""
|
|
76
76
|
|
|
@@ -119,7 +119,7 @@ class ShareSpec:
|
|
|
119
119
|
dist_type: SHRDistribution = field(default=SHRDistribution.DIR_FLAT)
|
|
120
120
|
"""See :class:`SHRDistribution`"""
|
|
121
121
|
|
|
122
|
-
@dist_type.validator
|
|
122
|
+
@dist_type.validator
|
|
123
123
|
def __dtv(
|
|
124
124
|
_i: ShareSpec, _a: Attribute[SHRDistribution], _v: SHRDistribution
|
|
125
125
|
) -> None:
|
|
@@ -152,7 +152,7 @@ class ShareSpec:
|
|
|
152
152
|
|
|
153
153
|
"""
|
|
154
154
|
|
|
155
|
-
@dist_parms.validator
|
|
155
|
+
@dist_parms.validator
|
|
156
156
|
def __dpv(
|
|
157
157
|
_i: ShareSpec,
|
|
158
158
|
_a: Attribute[ArrayFloat | ArrayINT | None],
|
|
@@ -205,7 +205,7 @@ class ShareSpec:
|
|
|
205
205
|
|
|
206
206
|
"""
|
|
207
207
|
|
|
208
|
-
@recapture_ratio.validator
|
|
208
|
+
@recapture_ratio.validator
|
|
209
209
|
def __rrv(_i: ShareSpec, _a: Attribute[float], _v: float) -> None:
|
|
210
210
|
if _v and not (0 < _v <= 1):
|
|
211
211
|
raise ValueError("Recapture ratio must lie in the interval, [0, 1).")
|
|
@@ -265,7 +265,7 @@ class PCMSpec:
|
|
|
265
265
|
|
|
266
266
|
"""
|
|
267
267
|
|
|
268
|
-
@dist_parms.validator
|
|
268
|
+
@dist_parms.validator
|
|
269
269
|
def __dpv(
|
|
270
270
|
_i: PCMSpec, _a: Attribute[ArrayDouble | None], _v: ArrayDouble | None
|
|
271
271
|
) -> None:
|
|
@@ -85,7 +85,7 @@ class MarketSample:
|
|
|
85
85
|
)
|
|
86
86
|
"""Margin specification, see :class:`PCMSpec`"""
|
|
87
87
|
|
|
88
|
-
@pcm_spec.validator
|
|
88
|
+
@pcm_spec.validator
|
|
89
89
|
def __psv(self, _a: Attribute[PCMSpec], _v: PCMSpec, /) -> None:
|
|
90
90
|
if (
|
|
91
91
|
self.share_spec.recapture_form == RECForm.FIXED
|
|
@@ -437,8 +437,8 @@ class MarketSample:
|
|
|
437
437
|
_enf_parm_vec,
|
|
438
438
|
_sim_test_regime,
|
|
439
439
|
**_sim_enf_cnts_kwargs,
|
|
440
|
-
saved_array_name_suffix=f"{saved_array_name_suffix}_{_iter_id:0{2 + int(np.ceil(np.log10(_iter_count)))}d}",
|
|
441
|
-
seed_seq_list=_rng_seed_seq_list_ch,
|
|
440
|
+
saved_array_name_suffix=f"{saved_array_name_suffix}_{_iter_id:0{2 + int(np.ceil(np.log10(_iter_count)))}d}",
|
|
441
|
+
seed_seq_list=_rng_seed_seq_list_ch,
|
|
442
442
|
)
|
|
443
443
|
for _iter_id, _rng_seed_seq_list_ch in enumerate(_rng_seed_seq_list)
|
|
444
444
|
)
|
{mergeron-2025.739265.0 → mergeron-2025.739265.2}/src/mergeron/gen/data_generation_functions.py
RENAMED
|
@@ -138,7 +138,7 @@ def gen_market_shares_uniform(
|
|
|
138
138
|
|
|
139
139
|
"""
|
|
140
140
|
|
|
141
|
-
_frmshr_array = np.empty((_s_size, 2), dtype=np.float64)
|
|
141
|
+
_frmshr_array: ArrayDouble = np.empty((_s_size, 2), dtype=np.float64)
|
|
142
142
|
|
|
143
143
|
_dist_parms_mktshr = _dist_parms_mktshr or DEFAULT_DIST_PARMS
|
|
144
144
|
_mrng = MultithreadedRNG(
|
|
@@ -151,10 +151,11 @@ def gen_market_shares_uniform(
|
|
|
151
151
|
_mrng.fill()
|
|
152
152
|
# Convert draws on U[0, 1] to Uniformly-distributed draws on simplex, s_1 + s_2 <= 1
|
|
153
153
|
_frmshr_array.sort(axis=1)
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
_frmshr_array[:, 1] - _frmshr_array[:, 0],
|
|
157
|
-
|
|
154
|
+
|
|
155
|
+
_frmshr_array = np.array(
|
|
156
|
+
(_frmshr_array[:, 0], _frmshr_array[:, 1] - _frmshr_array[:, 0]),
|
|
157
|
+
_frmshr_array.dtype,
|
|
158
|
+
).T # faster than np.stack() and variants
|
|
158
159
|
|
|
159
160
|
# Keep only share combinations representing feasible mergers
|
|
160
161
|
# This is a no-op for 64-bit floats, but is necessary for 32-bit floats
|
|
@@ -331,11 +331,11 @@ def initialize_hd5(
|
|
|
331
331
|
_h5_title = f"HMG version: {_hmg_pub_year}; Test regime: {_test_regime}"
|
|
332
332
|
if _h5_path.is_file():
|
|
333
333
|
_h5_path.unlink()
|
|
334
|
-
_h5_file = ptb.open_file(_h5_path, mode="w", title=_h5_title)
|
|
334
|
+
_h5_file = ptb.open_file(_h5_path, mode="w", title=_h5_title)
|
|
335
335
|
_save_data_to_file: SaveData = (True, _h5_file, _h5_file.root)
|
|
336
336
|
_next_subgroup_name_root = "enf_{}_{}_{}_{}".format(
|
|
337
337
|
_hmg_pub_year,
|
|
338
|
-
*(getattr(_test_regime, _f.name).name for _f in _test_regime.__attrs_attrs__),
|
|
338
|
+
*(getattr(_test_regime, _f.name).name for _f in _test_regime.__attrs_attrs__),
|
|
339
339
|
)
|
|
340
340
|
return _save_data_to_file, _next_subgroup_name_root
|
|
341
341
|
|
|
@@ -383,7 +383,7 @@ def save_array_to_hdf5(
|
|
|
383
383
|
_h5_array_name,
|
|
384
384
|
atom=ptb.Atom.from_dtype(_array_obj.dtype),
|
|
385
385
|
shape=_array_obj.shape,
|
|
386
|
-
filters=ptb.Filters(complevel=3, complib="blosc:lz4hc", fletcher32=True),
|
|
386
|
+
filters=ptb.Filters(complevel=3, complib="blosc:lz4hc", fletcher32=True),
|
|
387
387
|
)
|
|
388
388
|
_h5_array[:] = _array_obj
|
|
389
389
|
|
|
File without changes
|
|
File without changes
|
{mergeron-2025.739265.0 → mergeron-2025.739265.2}/src/mergeron/data/damodaran_margin_data.xls
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|