mergeron 2024.739139.0__py3-none-any.whl → 2024.739145.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of mergeron might be problematic. Click here for more details.
- mergeron/__init__.py +4 -7
- mergeron/core/__init__.py +5 -0
- mergeron/core/{damodaran_margin_data.py → empirical_margin_distribution.py} +6 -3
- mergeron/core/ftc_merger_investigations_data.py +23 -20
- mergeron/core/guidelines_boundaries.py +69 -69
- mergeron/core/guidelines_boundary_functions.py +203 -61
- mergeron/core/guidelines_boundary_functions_extra.py +19 -25
- mergeron/core/pseudorandom_numbers.py +3 -3
- mergeron/demo/visualize_empirical_margin_distribution.py +2 -3
- mergeron/gen/__init__.py +52 -33
- mergeron/gen/data_generation.py +13 -13
- mergeron/gen/data_generation_functions.py +63 -53
- mergeron/gen/upp_tests.py +6 -9
- {mergeron-2024.739139.0.dist-info → mergeron-2024.739145.0.dist-info}/METADATA +3 -3
- mergeron-2024.739145.0.dist-info/RECORD +24 -0
- mergeron-2024.739139.0.dist-info/RECORD +0 -24
- {mergeron-2024.739139.0.dist-info → mergeron-2024.739145.0.dist-info}/WHEEL +0 -0
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
Plot the empirical distribution derived using the Gaussian KDE with
|
|
3
3
|
margin data downloaded from Prof. Damodaran's website at NYU.
|
|
4
4
|
|
|
5
|
-
|
|
6
5
|
"""
|
|
7
6
|
|
|
8
7
|
import warnings
|
|
@@ -13,7 +12,7 @@ from matplotlib.ticker import StrMethodFormatter
|
|
|
13
12
|
from numpy.random import PCG64DXSM, Generator, SeedSequence
|
|
14
13
|
from scipy import stats # type: ignore
|
|
15
14
|
|
|
16
|
-
import mergeron.core.
|
|
15
|
+
import mergeron.core.empirical_margin_distribution as dmgn
|
|
17
16
|
from mergeron import DATA_DIR
|
|
18
17
|
from mergeron.core.guidelines_boundary_functions import boundary_plot
|
|
19
18
|
|
|
@@ -46,7 +45,7 @@ with warnings.catch_warnings():
|
|
|
46
45
|
])
|
|
47
46
|
|
|
48
47
|
mgn_kde = stats.gaussian_kde(mgn_data_obs, weights=mgn_data_wts, bw_method="silverman")
|
|
49
|
-
mgn_kde.set_bandwidth(bw_method=mgn_kde.factor / 3.0)
|
|
48
|
+
mgn_kde.set_bandwidth(bw_method=mgn_kde.factor / 3.0) # pyright: ignore
|
|
50
49
|
|
|
51
50
|
mgn_ax.plot(
|
|
52
51
|
(_xv := np.linspace(0, BIN_COUNT, 10**5) / BIN_COUNT),
|
mergeron/gen/__init__.py
CHANGED
|
@@ -25,13 +25,13 @@ from .. import ( # noqa: TID252
|
|
|
25
25
|
RECForm,
|
|
26
26
|
UPPAggrSelector,
|
|
27
27
|
)
|
|
28
|
-
from ..core.pseudorandom_numbers import
|
|
28
|
+
from ..core.pseudorandom_numbers import DEFAULT_DIST_PARMS # noqa: TID252
|
|
29
29
|
|
|
30
30
|
__version__ = VERSION
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
DEFAULT_EMPTY_ARRAY = np.zeros(2)
|
|
34
|
+
DEFAULT_FCOUNT_WTS = np.divide(
|
|
35
35
|
(_nr := np.arange(1, 7)[::-1]), _nr.sum(), dtype=np.float64
|
|
36
36
|
)
|
|
37
37
|
|
|
@@ -116,10 +116,31 @@ class ShareSpec:
|
|
|
116
116
|
|
|
117
117
|
"""
|
|
118
118
|
|
|
119
|
-
dist_type: SHRDistribution
|
|
119
|
+
dist_type: SHRDistribution = field(default=SHRDistribution.DIR_FLAT)
|
|
120
120
|
"""See :class:`SHRDistribution`"""
|
|
121
121
|
|
|
122
|
-
|
|
122
|
+
@dist_type.validator # pyright: ignore
|
|
123
|
+
def __dtv(
|
|
124
|
+
_i: ShareSpec, _a: Attribute[SHRDistribution], _v: SHRDistribution
|
|
125
|
+
) -> None:
|
|
126
|
+
if _v == SHRDistribution.UNI:
|
|
127
|
+
if _i.firm_counts_weights is not None:
|
|
128
|
+
raise ValueError(
|
|
129
|
+
"The specified value is incompatible with "
|
|
130
|
+
" :code:`distypte`=:attr`:`SHRDistribution.UNI`. "
|
|
131
|
+
"Set value to None or Consider revising the "
|
|
132
|
+
r"distribution type to :attr:`SHRDistribution.DIR_FLAT`, which gives "
|
|
133
|
+
"uniformly distributed draws on the :math:`n+1` simplex "
|
|
134
|
+
"for firm-count, :math:`n`. "
|
|
135
|
+
""
|
|
136
|
+
)
|
|
137
|
+
elif _i.recapture_form == RECForm.OUTIN:
|
|
138
|
+
raise ValueError(
|
|
139
|
+
"Market share specification requires estimation of recapture ratio from "
|
|
140
|
+
"generated data. Either delete recapture ratio specification or set it to None."
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
dist_parms: ArrayFloat | ArrayINT | None = field(
|
|
123
144
|
default=None, eq=cmp_using(eq=np.array_equal)
|
|
124
145
|
)
|
|
125
146
|
"""Parameters for tailoring market-share distribution
|
|
@@ -130,40 +151,38 @@ class ShareSpec:
|
|
|
130
151
|
type of Dirichlet-distribution specified.
|
|
131
152
|
|
|
132
153
|
"""
|
|
154
|
+
|
|
155
|
+
@dist_parms.validator # pyright: ignore
|
|
156
|
+
def __dpv(
|
|
157
|
+
_i: ShareSpec,
|
|
158
|
+
_a: Attribute[ArrayFloat | ArrayINT | None],
|
|
159
|
+
_v: ArrayFloat | ArrayINT | None,
|
|
160
|
+
) -> None:
|
|
161
|
+
if (
|
|
162
|
+
_i.firm_counts_weights is not None
|
|
163
|
+
and _v is not None
|
|
164
|
+
and len(_v) < 1 + len(_i.firm_counts_weights)
|
|
165
|
+
):
|
|
166
|
+
raise ValueError(
|
|
167
|
+
"If specified, the number of distribution parameters must be at least "
|
|
168
|
+
"the maximum firm-count premerger, which is 1 plus the length of the "
|
|
169
|
+
"vector specifying firm-count weights."
|
|
170
|
+
)
|
|
171
|
+
|
|
133
172
|
firm_counts_weights: ArrayFloat | ArrayINT | None = field(
|
|
134
|
-
default=
|
|
173
|
+
default=DEFAULT_FCOUNT_WTS, eq=cmp_using(eq=np.array_equal)
|
|
135
174
|
)
|
|
136
175
|
"""Relative or absolute frequencies of firm counts
|
|
137
176
|
|
|
138
177
|
Given frequencies are exogenous to generated market data sample;
|
|
139
|
-
for Dirichlet-type distributions, defaults to
|
|
178
|
+
for Dirichlet-type distributions, defaults to DEFAULT_FCOUNT_WTS, which specifies
|
|
140
179
|
firm-counts of 2 to 6 with weights in descending order from 5 to 1.
|
|
141
180
|
|
|
142
181
|
"""
|
|
143
182
|
|
|
144
|
-
@firm_counts_weights.validator
|
|
145
|
-
def _check_fcw(_i: ShareSpec, _a: Attribute[ArrayDouble], _v: ArrayDouble) -> None:
|
|
146
|
-
if _v is not None and _i.dist_type == SHRDistribution.UNI:
|
|
147
|
-
raise ValueError(
|
|
148
|
-
"Generated data for markets with specified firm-counts or "
|
|
149
|
-
"varying firm counts are not feasible for market shares "
|
|
150
|
-
"with Uniform distribution. Consider revising the "
|
|
151
|
-
r"distribution type to {SHRDistribution.DIR_FLAT}, which gives "
|
|
152
|
-
"uniformly distributed draws on the :math:`n+1` simplex "
|
|
153
|
-
"for firm-count, :math:`n`."
|
|
154
|
-
)
|
|
155
|
-
|
|
156
183
|
recapture_form: RECForm = field(default=RECForm.INOUT)
|
|
157
184
|
"""See :class:`mergeron.RECForm`"""
|
|
158
185
|
|
|
159
|
-
@recapture_form.validator
|
|
160
|
-
def _check_rf(_i: ShareSpec, _a: Attribute[RECForm], _v: RECForm) -> None:
|
|
161
|
-
if _v == RECForm.OUTIN and _i.dist_type == SHRDistribution.UNI:
|
|
162
|
-
raise ValueError(
|
|
163
|
-
"Market share specification requires estimation of recapture ratio from "
|
|
164
|
-
"generated data. Either delete recapture ratio specification or set it to None."
|
|
165
|
-
)
|
|
166
|
-
|
|
167
186
|
recapture_ratio: float | None = field(default=DEFAULT_REC_RATE)
|
|
168
187
|
"""A value between 0 and 1.
|
|
169
188
|
|
|
@@ -187,8 +206,8 @@ class ShareSpec:
|
|
|
187
206
|
|
|
188
207
|
"""
|
|
189
208
|
|
|
190
|
-
@recapture_ratio.validator
|
|
191
|
-
def
|
|
209
|
+
@recapture_ratio.validator # pyright: ignore
|
|
210
|
+
def __rrv(_i: ShareSpec, _a: Attribute[float], _v: float) -> None:
|
|
192
211
|
if _v and not (0 < _v <= 1):
|
|
193
212
|
raise ValueError("Recapture ratio must lie in the interval, [0, 1).")
|
|
194
213
|
elif _v is None and _i.recapture_form != RECForm.OUTIN:
|
|
@@ -247,16 +266,16 @@ class PCMSpec:
|
|
|
247
266
|
|
|
248
267
|
"""
|
|
249
268
|
|
|
250
|
-
@dist_parms.validator
|
|
251
|
-
def
|
|
269
|
+
@dist_parms.validator # pyright: ignore
|
|
270
|
+
def __dpv(
|
|
252
271
|
_i: PCMSpec, _a: Attribute[ArrayDouble | None], _v: ArrayDouble | None
|
|
253
272
|
) -> None:
|
|
254
273
|
if _i.dist_type.name.startswith("BETA"):
|
|
255
274
|
if _v is None:
|
|
256
275
|
pass
|
|
257
|
-
elif np.array_equal(_v,
|
|
276
|
+
elif np.array_equal(_v, DEFAULT_DIST_PARMS):
|
|
258
277
|
raise ValueError(
|
|
259
|
-
f"The distribution parameters, {
|
|
278
|
+
f"The distribution parameters, {DEFAULT_DIST_PARMS!r} "
|
|
260
279
|
"are not valid with margin distribution, {_dist_type_pcm!r}"
|
|
261
280
|
)
|
|
262
281
|
elif (
|
mergeron/gen/data_generation.py
CHANGED
|
@@ -85,8 +85,8 @@ class MarketSample:
|
|
|
85
85
|
)
|
|
86
86
|
"""Margin specification, see :class:`PCMSpec`"""
|
|
87
87
|
|
|
88
|
-
@pcm_spec.validator
|
|
89
|
-
def
|
|
88
|
+
@pcm_spec.validator # pyright: ignore
|
|
89
|
+
def __psv(self, _a: Attribute[PCMSpec], _v: PCMSpec, /) -> None:
|
|
90
90
|
if (
|
|
91
91
|
self.share_spec.recapture_form == RECForm.FIXED
|
|
92
92
|
and _v.firm2_pcm_constraint == FM2Constraint.MNL
|
|
@@ -113,7 +113,7 @@ class MarketSample:
|
|
|
113
113
|
|
|
114
114
|
enf_counts: UPPTestsCounts = field(default=None)
|
|
115
115
|
|
|
116
|
-
def
|
|
116
|
+
def __gen_market_sample(
|
|
117
117
|
self,
|
|
118
118
|
/,
|
|
119
119
|
*,
|
|
@@ -256,7 +256,7 @@ class MarketSample:
|
|
|
256
256
|
|
|
257
257
|
"""
|
|
258
258
|
|
|
259
|
-
self.data = self.
|
|
259
|
+
self.data = self.__gen_market_sample(
|
|
260
260
|
sample_size=sample_size, seed_seq_list=seed_seq_list, nthreads=nthreads
|
|
261
261
|
)
|
|
262
262
|
|
|
@@ -273,14 +273,14 @@ class MarketSample:
|
|
|
273
273
|
save_data_to_file=save_data_to_file,
|
|
274
274
|
)
|
|
275
275
|
|
|
276
|
-
def
|
|
276
|
+
def __sim_enf_cnts(
|
|
277
277
|
self,
|
|
278
278
|
_upp_test_parms: gbl.HMGThresholds,
|
|
279
279
|
_sim_test_regime: UPPTestRegime,
|
|
280
280
|
/,
|
|
281
281
|
*,
|
|
282
282
|
sample_size: int = 10**6,
|
|
283
|
-
seed_seq_list:
|
|
283
|
+
seed_seq_list: Sequence[SeedSequence] | None = None,
|
|
284
284
|
nthreads: int = 16,
|
|
285
285
|
save_data_to_file: SaveData = False,
|
|
286
286
|
saved_array_name_suffix: str = "",
|
|
@@ -320,7 +320,7 @@ class MarketSample:
|
|
|
320
320
|
|
|
321
321
|
"""
|
|
322
322
|
|
|
323
|
-
_market_data_sample = self.
|
|
323
|
+
_market_data_sample = self.__gen_market_sample(
|
|
324
324
|
sample_size=sample_size, seed_seq_list=seed_seq_list, nthreads=nthreads
|
|
325
325
|
)
|
|
326
326
|
|
|
@@ -349,14 +349,14 @@ class MarketSample:
|
|
|
349
349
|
|
|
350
350
|
return _upp_test_arrays
|
|
351
351
|
|
|
352
|
-
def
|
|
352
|
+
def __sim_enf_cnts_ll(
|
|
353
353
|
self,
|
|
354
354
|
_enf_parm_vec: gbl.HMGThresholds,
|
|
355
355
|
_sim_test_regime: UPPTestRegime,
|
|
356
356
|
/,
|
|
357
357
|
*,
|
|
358
358
|
sample_size: int = 10**6,
|
|
359
|
-
seed_seq_list:
|
|
359
|
+
seed_seq_list: Sequence[SeedSequence] | None = None,
|
|
360
360
|
nthreads: int = 16,
|
|
361
361
|
save_data_to_file: SaveData = False,
|
|
362
362
|
saved_array_name_suffix: str = "",
|
|
@@ -433,12 +433,12 @@ class MarketSample:
|
|
|
433
433
|
})
|
|
434
434
|
|
|
435
435
|
_res_list = Parallel(n_jobs=_thread_count, prefer="threads")(
|
|
436
|
-
delayed(self.
|
|
436
|
+
delayed(self.__sim_enf_cnts)(
|
|
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}", # pyright: ignore
|
|
441
|
+
seed_seq_list=_rng_seed_seq_list_ch, # pyright: ignore
|
|
442
442
|
)
|
|
443
443
|
for _iter_id, _rng_seed_seq_list_ch in enumerate(_rng_seed_seq_list)
|
|
444
444
|
)
|
|
@@ -508,7 +508,7 @@ class MarketSample:
|
|
|
508
508
|
"""
|
|
509
509
|
|
|
510
510
|
if self.data is None:
|
|
511
|
-
self.enf_counts = self.
|
|
511
|
+
self.enf_counts = self.__sim_enf_cnts_ll(
|
|
512
512
|
_enf_parm_vec,
|
|
513
513
|
_upp_test_regime,
|
|
514
514
|
sample_size=sample_size,
|
|
@@ -11,22 +11,16 @@ import numpy as np
|
|
|
11
11
|
from attrs import evolve
|
|
12
12
|
from numpy.random import SeedSequence
|
|
13
13
|
|
|
14
|
-
from .. import
|
|
15
|
-
|
|
16
|
-
VERSION,
|
|
17
|
-
ArrayBIGINT,
|
|
18
|
-
ArrayDouble,
|
|
19
|
-
RECForm,
|
|
20
|
-
)
|
|
21
|
-
from ..core.damodaran_margin_data import mgn_data_resampler # noqa: TID252
|
|
14
|
+
from .. import DEFAULT_REC_RATE, VERSION, ArrayDouble, RECForm # noqa: TID252
|
|
15
|
+
from ..core.empirical_margin_distribution import mgn_data_resampler # noqa: TID252
|
|
22
16
|
from ..core.pseudorandom_numbers import ( # noqa: TID252
|
|
23
|
-
|
|
17
|
+
DEFAULT_DIST_PARMS,
|
|
24
18
|
MultithreadedRNG,
|
|
25
19
|
prng,
|
|
26
20
|
)
|
|
27
21
|
from . import (
|
|
28
|
-
|
|
29
|
-
|
|
22
|
+
DEFAULT_EMPTY_ARRAY,
|
|
23
|
+
DEFAULT_FCOUNT_WTS,
|
|
30
24
|
FM2Constraint,
|
|
31
25
|
MarginDataSample,
|
|
32
26
|
PCMDistribution,
|
|
@@ -120,7 +114,7 @@ def gen_share_data(
|
|
|
120
114
|
|
|
121
115
|
def gen_market_shares_uniform(
|
|
122
116
|
_s_size: int = 10**6,
|
|
123
|
-
_dist_parms_mktshr: ArrayDouble | None =
|
|
117
|
+
_dist_parms_mktshr: ArrayDouble | None = DEFAULT_DIST_PARMS,
|
|
124
118
|
_mktshr_rng_seed_seq: SeedSequence | None = None,
|
|
125
119
|
_nthreads: int = 16,
|
|
126
120
|
/,
|
|
@@ -145,9 +139,8 @@ def gen_market_shares_uniform(
|
|
|
145
139
|
"""
|
|
146
140
|
|
|
147
141
|
_frmshr_array = np.empty((_s_size, 2), dtype=np.float64)
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
)
|
|
142
|
+
|
|
143
|
+
_dist_parms_mktshr = _dist_parms_mktshr or DEFAULT_DIST_PARMS
|
|
151
144
|
_mrng = MultithreadedRNG(
|
|
152
145
|
_frmshr_array,
|
|
153
146
|
dist_type="Uniform",
|
|
@@ -164,6 +157,7 @@ def gen_market_shares_uniform(
|
|
|
164
157
|
))
|
|
165
158
|
|
|
166
159
|
# Keep only share combinations representing feasible mergers
|
|
160
|
+
# This is a no-op for 64-bit floats, but is necessary for 32-bit floats
|
|
167
161
|
_frmshr_array = _frmshr_array[_frmshr_array.min(axis=1) > 0]
|
|
168
162
|
|
|
169
163
|
# Let a third column have values of "np.nan", so HHI calculations return "np.nan"
|
|
@@ -171,11 +165,18 @@ def gen_market_shares_uniform(
|
|
|
171
165
|
_frmshr_array, ((0, 0), (0, 1)), "constant", constant_values=np.nan
|
|
172
166
|
)
|
|
173
167
|
|
|
174
|
-
_fcounts
|
|
168
|
+
_fcounts = np.empty((_s_size, 1), np.int64)
|
|
175
169
|
_nth_firm_share, _aggregate_purchase_prob = (
|
|
176
|
-
np.
|
|
170
|
+
np.empty(_fcounts.shape, np.float64)
|
|
171
|
+
for _ in ("nth_firm_share", "aggregate_purchase_prob")
|
|
177
172
|
)
|
|
178
173
|
|
|
174
|
+
# This array is meant to be ignored, so a sentinel value is fine
|
|
175
|
+
_fcounts.fill(-9999)
|
|
176
|
+
|
|
177
|
+
_nth_firm_share.fill(np.nan)
|
|
178
|
+
_aggregate_purchase_prob.fill(np.nan)
|
|
179
|
+
|
|
179
180
|
return ShareDataSample(
|
|
180
181
|
_mktshr_array, _fcounts, _nth_firm_share, _aggregate_purchase_prob
|
|
181
182
|
)
|
|
@@ -228,9 +229,10 @@ def gen_market_shares_dirichlet_multimarket(
|
|
|
228
229
|
|
|
229
230
|
"""
|
|
230
231
|
|
|
231
|
-
_firm_count_wts: ArrayDouble = (
|
|
232
|
-
|
|
233
|
-
)
|
|
232
|
+
# _firm_count_wts: ArrayDouble = (
|
|
233
|
+
# DEFAULT_FCOUNT_WTS if _firm_count_wts is None else _firm_count_wts
|
|
234
|
+
# )
|
|
235
|
+
_firm_count_wts = DEFAULT_FCOUNT_WTS if _firm_count_wts is None else _firm_count_wts
|
|
234
236
|
|
|
235
237
|
_min_choice_wt = 0.03 if _dist_type_dir == SHRDistribution.DIR_FLAT_CONSTR else 0.00
|
|
236
238
|
_fcount_keys, _choice_wts = zip(
|
|
@@ -394,7 +396,8 @@ def gen_market_shares_dirichlet(
|
|
|
394
396
|
)
|
|
395
397
|
|
|
396
398
|
# If recapture_form == 'inside_out', further calculations downstream
|
|
397
|
-
_aggregate_purchase_prob = np.
|
|
399
|
+
_aggregate_purchase_prob = np.empty((_s_size, 1), dtype=np.float64)
|
|
400
|
+
_aggregate_purchase_prob.fill(np.nan)
|
|
398
401
|
if _recapture_form == RECForm.OUTIN:
|
|
399
402
|
_aggregate_purchase_prob = 1 - _mktshr_array[:, [-1]]
|
|
400
403
|
_mktshr_array = _mktshr_array[:, :-1] / _aggregate_purchase_prob
|
|
@@ -411,7 +414,7 @@ def gen_divr_array(
|
|
|
411
414
|
_recapture_form: RECForm,
|
|
412
415
|
_recapture_ratio: float | None,
|
|
413
416
|
_frmshr_array: ArrayDouble,
|
|
414
|
-
_aggregate_purchase_prob: ArrayDouble =
|
|
417
|
+
_aggregate_purchase_prob: ArrayDouble = DEFAULT_EMPTY_ARRAY,
|
|
415
418
|
/,
|
|
416
419
|
) -> ArrayDouble:
|
|
417
420
|
"""
|
|
@@ -525,6 +528,10 @@ def gen_margin_price_data(
|
|
|
525
528
|
Simulated margin- and price-data arrays for mergers in the sample.
|
|
526
529
|
"""
|
|
527
530
|
|
|
531
|
+
_margin_data = MarginDataSample(
|
|
532
|
+
np.empty_like(_frmshr_array), np.ones(len(_frmshr_array)) == 0
|
|
533
|
+
)
|
|
534
|
+
|
|
528
535
|
_price_array, _price_ratio_array = (
|
|
529
536
|
np.ones_like(_frmshr_array, np.float64),
|
|
530
537
|
np.empty_like(_frmshr_array, np.float64),
|
|
@@ -673,7 +680,6 @@ def _gen_margin_data(
|
|
|
673
680
|
for _f in ("dist_type", "firm2_pcm_constraint", "dist_parms")
|
|
674
681
|
)
|
|
675
682
|
|
|
676
|
-
_dist_type: Literal["Beta", "Uniform"]
|
|
677
683
|
_pcm_array = (
|
|
678
684
|
np.empty((len(_frmshr_array), 1), dtype=np.float64)
|
|
679
685
|
if _pcm_spec.firm2_pcm_constraint == FM2Constraint.SYM
|
|
@@ -683,23 +689,27 @@ def _gen_margin_data(
|
|
|
683
689
|
_beta_min, _beta_max = [None] * 2 # placeholder
|
|
684
690
|
if _dist_type_pcm == PCMDistribution.EMPR:
|
|
685
691
|
_pcm_array = mgn_data_resampler(
|
|
686
|
-
_pcm_array.shape,
|
|
687
|
-
seed_sequence=_pcm_rng_seed_seq,
|
|
692
|
+
_pcm_array.shape, seed_sequence=_pcm_rng_seed_seq
|
|
688
693
|
)
|
|
689
694
|
else:
|
|
690
|
-
_dist_type
|
|
691
|
-
if _dist_type_pcm
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
695
|
+
_dist_type: Literal["Beta", "Uniform"]
|
|
696
|
+
if _dist_type_pcm in (PCMDistribution.BETA, PCMDistribution.BETA_BND):
|
|
697
|
+
_dist_type = "Beta"
|
|
698
|
+
_dist_parms_pcm = (
|
|
699
|
+
(
|
|
700
|
+
np.array([0, 1, 0, 1], np.float64)
|
|
701
|
+
if _dist_parms_pcm == PCMDistribution.BETA_BND
|
|
702
|
+
else np.ones(2, np.float64)
|
|
703
|
+
)
|
|
704
|
+
if _dist_parms_pcm is None
|
|
705
|
+
else _dist_parms_pcm
|
|
706
|
+
)
|
|
707
|
+
_dist_parms = beta_located_bound(_dist_parms_pcm)
|
|
708
|
+
|
|
699
709
|
else:
|
|
700
|
-
|
|
710
|
+
_dist_type = "Uniform"
|
|
701
711
|
_dist_parms = (
|
|
702
|
-
|
|
712
|
+
DEFAULT_DIST_PARMS if _dist_parms_pcm is None else _dist_parms_pcm
|
|
703
713
|
)
|
|
704
714
|
|
|
705
715
|
_pcm_rng = MultithreadedRNG(
|
|
@@ -838,29 +848,29 @@ def parse_seed_seq_list(
|
|
|
838
848
|
Seed sequence data
|
|
839
849
|
|
|
840
850
|
"""
|
|
851
|
+
_seed_count = 2 if _mktshr_dist_type == SHRDistribution.UNI else 3
|
|
852
|
+
_seed_count += 1 if _price_spec == PriceSpec.ZERO else 0
|
|
853
|
+
|
|
841
854
|
_fcount_rng_seed_seq: SeedSequence | None = None
|
|
842
855
|
_pr_rng_seed_seq: SeedSequence | None = None
|
|
843
856
|
|
|
844
|
-
|
|
845
|
-
_sseq_list
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
)
|
|
850
|
-
|
|
851
|
-
_seed_count = 2 if _mktshr_dist_type == SHRDistribution.UNI else 3
|
|
857
|
+
_sseq_list = (
|
|
858
|
+
_sseq_list
|
|
859
|
+
if _sseq_list
|
|
860
|
+
else tuple(SeedSequence(pool_size=8) for _ in range(_seed_count))
|
|
861
|
+
)
|
|
852
862
|
|
|
853
|
-
if _sseq_list:
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
else:
|
|
859
|
-
_sseq_list = tuple(SeedSequence(pool_size=8) for _ in range(_seed_count))
|
|
863
|
+
if (_l := len(_sseq_list)) < _seed_count:
|
|
864
|
+
raise ValueError(
|
|
865
|
+
f"Seed sequence list must contain {_seed_count} seed sequences; "
|
|
866
|
+
f"only {_l} given."
|
|
867
|
+
)
|
|
860
868
|
|
|
861
|
-
|
|
862
|
-
|
|
869
|
+
_mktshr_rng_seed_seq, _pcm_rng_seed_seq = _sseq_list[:2]
|
|
870
|
+
_fcount_rng_seed_seq = (
|
|
871
|
+
None if _mktshr_dist_type == SHRDistribution.UNI else _sseq_list[2]
|
|
863
872
|
)
|
|
873
|
+
_pr_rng_seed_seq = _sseq_list[-1] if _price_spec == PriceSpec.ZERO else None
|
|
864
874
|
|
|
865
875
|
return SeedSequenceData(
|
|
866
876
|
_mktshr_rng_seed_seq, _pcm_rng_seed_seq, _fcount_rng_seed_seq, _pr_rng_seed_seq
|
mergeron/gen/upp_tests.py
CHANGED
|
@@ -26,7 +26,7 @@ from .. import ( # noqa
|
|
|
26
26
|
)
|
|
27
27
|
from ..core import guidelines_boundaries as gbl # noqa: TID252
|
|
28
28
|
from . import (
|
|
29
|
-
|
|
29
|
+
DEFAULT_EMPTY_ARRAY,
|
|
30
30
|
DataclassInstance,
|
|
31
31
|
INVResolution,
|
|
32
32
|
MarketDataSample,
|
|
@@ -38,9 +38,6 @@ from . import enforcement_stats as esl
|
|
|
38
38
|
|
|
39
39
|
__version__ = VERSION
|
|
40
40
|
|
|
41
|
-
ptb.parameters.MAX_NUMEXPR_THREADS = 8
|
|
42
|
-
ptb.parameters.MAX_BLOSC_THREADS = 4
|
|
43
|
-
|
|
44
41
|
type SaveData = Literal[False] | tuple[Literal[True], ptb.File, ptb.Group]
|
|
45
42
|
|
|
46
43
|
|
|
@@ -48,7 +45,7 @@ class INVRESCntsArgs(TypedDict, total=False):
|
|
|
48
45
|
"Keyword arguments of function, :code:`sim_enf_cnts`"
|
|
49
46
|
|
|
50
47
|
sample_size: int
|
|
51
|
-
seed_seq_list:
|
|
48
|
+
seed_seq_list: Sequence[SeedSequence] | None
|
|
52
49
|
nthreads: int
|
|
53
50
|
save_data_to_file: SaveData
|
|
54
51
|
saved_array_name_suffix: str
|
|
@@ -282,7 +279,7 @@ def _compute_test_array_seq(
|
|
|
282
279
|
UPPAggrSelector.OSA,
|
|
283
280
|
UPPAggrSelector.OSD,
|
|
284
281
|
)
|
|
285
|
-
else
|
|
282
|
+
else DEFAULT_EMPTY_ARRAY
|
|
286
283
|
)
|
|
287
284
|
|
|
288
285
|
match _aggregator:
|
|
@@ -335,10 +332,10 @@ def initialize_hd5(
|
|
|
335
332
|
if _h5_path.is_file():
|
|
336
333
|
_h5_path.unlink()
|
|
337
334
|
_h5_file = ptb.open_file(_h5_path, mode="w", title=_h5_title)
|
|
338
|
-
_save_data_to_file:
|
|
335
|
+
_save_data_to_file: SaveData = (True, _h5_file, _h5_file.root)
|
|
339
336
|
_next_subgroup_name_root = "enf_{}_{}_{}_{}".format(
|
|
340
337
|
_hmg_pub_year,
|
|
341
|
-
*(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__), # pyright: ignore
|
|
342
339
|
)
|
|
343
340
|
return _save_data_to_file, _next_subgroup_name_root
|
|
344
341
|
|
|
@@ -386,7 +383,7 @@ def save_array_to_hdf5(
|
|
|
386
383
|
_h5_array_name,
|
|
387
384
|
atom=ptb.Atom.from_dtype(_array_obj.dtype),
|
|
388
385
|
shape=_array_obj.shape,
|
|
389
|
-
filters=ptb.Filters(complevel=3, complib="blosc:lz4hc", fletcher32=True),
|
|
386
|
+
filters=ptb.Filters(complevel=3, complib="blosc:lz4hc", fletcher32=True), # pyright: ignore
|
|
390
387
|
)
|
|
391
388
|
_h5_array[:] = _array_obj
|
|
392
389
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: mergeron
|
|
3
|
-
Version: 2024.
|
|
3
|
+
Version: 2024.739145.0
|
|
4
4
|
Summary: Merger Policy Analysis using Python
|
|
5
5
|
License: MIT
|
|
6
6
|
Keywords: merger policy analysis,merger guidelines,merger screening,policy presumptions,concentration standards,upward pricing pressure,GUPPI
|
|
@@ -101,7 +101,7 @@ FTC Premerger Notification Office. “To File or Not to File: When You Must File
|
|
|
101
101
|
|
|
102
102
|
.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json
|
|
103
103
|
:alt: Ruff
|
|
104
|
-
:target: https://github.com/astral-sh/ruff
|
|
104
|
+
:target: https://github.com/astral-sh/ruff/
|
|
105
105
|
|
|
106
106
|
.. image:: https://www.mypy-lang.org/static/mypy_badge.svg
|
|
107
107
|
:alt: Checked with mypy
|
|
@@ -109,6 +109,6 @@ FTC Premerger Notification Office. “To File or Not to File: When You Must File
|
|
|
109
109
|
|
|
110
110
|
.. image:: https://img.shields.io/badge/License-MIT-yellow.svg
|
|
111
111
|
:alt: License: MIT
|
|
112
|
-
:target: https://opensource.org/licenses/MIT
|
|
112
|
+
:target: https://opensource.org/licenses/MIT/
|
|
113
113
|
|
|
114
114
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
mergeron/License.txt,sha256=7iX-y0EyjkbVJKJLS4ZKzuuE1wd0lryfsD_IytLG8lQ,1246
|
|
2
|
+
mergeron/__init__.py,sha256=kRj4ei5H3RLxUuBxJgnj63boshupWN-hCIjFr9p20Ig,1476
|
|
3
|
+
mergeron/core/__init__.py,sha256=jPGd0okmvNOdWnTu4biR4hqnL29IERaY4Olv8mS02ko,188
|
|
4
|
+
mergeron/core/empirical_margin_distribution.py,sha256=iU72c6rPwqduH8GlvES1na2uvw5qXq0IQfsTWnL_ueQ,8726
|
|
5
|
+
mergeron/core/ftc_merger_investigations_data.py,sha256=_Qno1_oWcHmDd60j8YX6BLUSLeAn-DU6KpvMOcbCIaE,28728
|
|
6
|
+
mergeron/core/guidelines_boundaries.py,sha256=sFC4kRjH4ndINluwxBBftBWcn5g4Vfq2ezhzzbpnlGE,15765
|
|
7
|
+
mergeron/core/guidelines_boundary_functions.py,sha256=BJyZAoHK0ibiAHEdD9PJT_F0NEYMLjYdGR5lW67iQ6M,34558
|
|
8
|
+
mergeron/core/guidelines_boundary_functions_extra.py,sha256=AZKkLPjiMtBaQIKj1bFs5xgV9xSntlHkf-pc7j4OkVk,11289
|
|
9
|
+
mergeron/core/pseudorandom_numbers.py,sha256=ps5H3n7jC5iJq_ulrmGvTAFmMeNXq-7IPWQQog7q5TY,9225
|
|
10
|
+
mergeron/data/__init__.py,sha256=KtjBlZOl7jwBCAUhrTJB9PdrN39YLYytNiSUSM_gRmA,62
|
|
11
|
+
mergeron/data/damodaran_margin_data.xls,sha256=Qggl1p5nkOMJI8YUXhkwXQRz-OhRSqBTzz57N0JQyYA,79360
|
|
12
|
+
mergeron/data/damodaran_margin_data_dict.msgpack,sha256=sr6s4L69kposEpzGI7jpPb4ULz0UpY-bEYfeNi6UlRA,57621
|
|
13
|
+
mergeron/data/ftc_invdata.msgpack,sha256=WBFHgi7Ld4R-h2zL2Zc3TOIlKqVrbVFMH1LoI4-T-M0,264664
|
|
14
|
+
mergeron/demo/__init__.py,sha256=KtjBlZOl7jwBCAUhrTJB9PdrN39YLYytNiSUSM_gRmA,62
|
|
15
|
+
mergeron/demo/visualize_empirical_margin_distribution.py,sha256=_1SWKqFJNqKV_yA3v2tmzl8Th3CC3SXpb6VGiwGGuN0,2373
|
|
16
|
+
mergeron/gen/__init__.py,sha256=hrOACw-loPDXiPTP-5wjpu7cW6T5ade6eVW-CtNGEXg,17287
|
|
17
|
+
mergeron/gen/data_generation.py,sha256=wyrSfoDf3F5RVAqfzOv27R9x97_4Ciz6OmXH_w8PHbA,16870
|
|
18
|
+
mergeron/gen/data_generation_functions.py,sha256=Lr9co1qylkmAyu8OPUVwYpE3KvxU-97glqmJ04E-LTA,28977
|
|
19
|
+
mergeron/gen/enforcement_stats.py,sha256=ZjrV_VkFMF0D1myc-fj-W99M1EhJMA9-nCfyE5g9e54,10890
|
|
20
|
+
mergeron/gen/upp_tests.py,sha256=S0XUpP0t5DLR3PCNcTL9xZ_icxdS31hfNwg3LH7mctE,12529
|
|
21
|
+
mergeron/py.typed,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
|
|
22
|
+
mergeron-2024.739145.0.dist-info/METADATA,sha256=EJD8ascIdWBNCN0s3XGunNNn45_8VQayJGy1hcaEqwY,14432
|
|
23
|
+
mergeron-2024.739145.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
24
|
+
mergeron-2024.739145.0.dist-info/RECORD,,
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
mergeron/License.txt,sha256=7iX-y0EyjkbVJKJLS4ZKzuuE1wd0lryfsD_IytLG8lQ,1246
|
|
2
|
-
mergeron/__init__.py,sha256=hiOhxFInENJRReecosK422vBUnZGrOEutNkWfEs7JOs,1460
|
|
3
|
-
mergeron/core/__init__.py,sha256=KtjBlZOl7jwBCAUhrTJB9PdrN39YLYytNiSUSM_gRmA,62
|
|
4
|
-
mergeron/core/damodaran_margin_data.py,sha256=rMrgN1Qtw572a0ftY97OOj4otq8ldlLrcOi-bcE-org,8554
|
|
5
|
-
mergeron/core/ftc_merger_investigations_data.py,sha256=eldNU4hX9oKE4Rb08YE9_1LgolvNKZnhOXW6KyWSwnM,28622
|
|
6
|
-
mergeron/core/guidelines_boundaries.py,sha256=7C5hMa8vijDZbLdrSxO3XHpsXF5e7PZFpI-abDKqt90,15616
|
|
7
|
-
mergeron/core/guidelines_boundary_functions.py,sha256=GGn5mwBWmxkqcat4Ya0D-J6-7ujosgCCK3eJ9RFWASI,29749
|
|
8
|
-
mergeron/core/guidelines_boundary_functions_extra.py,sha256=HDwwKZDWlrj3Tw-I0gHm0TCSDcIyb9jDfwbuDvK55B8,11322
|
|
9
|
-
mergeron/core/pseudorandom_numbers.py,sha256=cJEWDTfy9CUTzR_di6Fm1Vl1Le6xWoU8wFHbYVMEuLI,9225
|
|
10
|
-
mergeron/data/__init__.py,sha256=KtjBlZOl7jwBCAUhrTJB9PdrN39YLYytNiSUSM_gRmA,62
|
|
11
|
-
mergeron/data/damodaran_margin_data.xls,sha256=Qggl1p5nkOMJI8YUXhkwXQRz-OhRSqBTzz57N0JQyYA,79360
|
|
12
|
-
mergeron/data/damodaran_margin_data_dict.msgpack,sha256=sr6s4L69kposEpzGI7jpPb4ULz0UpY-bEYfeNi6UlRA,57621
|
|
13
|
-
mergeron/data/ftc_invdata.msgpack,sha256=WBFHgi7Ld4R-h2zL2Zc3TOIlKqVrbVFMH1LoI4-T-M0,264664
|
|
14
|
-
mergeron/demo/__init__.py,sha256=KtjBlZOl7jwBCAUhrTJB9PdrN39YLYytNiSUSM_gRmA,62
|
|
15
|
-
mergeron/demo/visualize_empirical_margin_distribution.py,sha256=R-sGC87kVovWBqcM5U6GiNC9oLsbNaMTJgljv8ts8w0,2347
|
|
16
|
-
mergeron/gen/__init__.py,sha256=DU6uFbRwe6ng-2sKCmpymD90CDNmyelWvUnmtNu8iHM,16593
|
|
17
|
-
mergeron/gen/data_generation.py,sha256=czTZcVZnT5kWViSFdSdbo0kupq1tUKGrKH5RThXbDwk,16803
|
|
18
|
-
mergeron/gen/data_generation_functions.py,sha256=Ag6u1yZ93ikGuKhj7PWbJ2lCZHxNGTemDfhK8p5xFq0,28576
|
|
19
|
-
mergeron/gen/enforcement_stats.py,sha256=ZjrV_VkFMF0D1myc-fj-W99M1EhJMA9-nCfyE5g9e54,10890
|
|
20
|
-
mergeron/gen/upp_tests.py,sha256=uRF4RrBo3amwQQSu661Xa50xKGMUxtnM3zRtYy3nyB0,12581
|
|
21
|
-
mergeron/py.typed,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
|
|
22
|
-
mergeron-2024.739139.0.dist-info/METADATA,sha256=NrSRBKtvNhW9KFKRB4gW_YK39BmhFKiA8DNtz-nZQ7g,14430
|
|
23
|
-
mergeron-2024.739139.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
24
|
-
mergeron-2024.739139.0.dist-info/RECORD,,
|
|
File without changes
|