mergeron 2024.738953.1__py3-none-any.whl → 2024.738972.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/License.txt +1 -1
- mergeron/core/__init__.py +3 -3
- mergeron/core/excel_helper.py +3 -1
- mergeron/core/ftc_merger_investigations_data.py +13 -16
- mergeron/core/guidelines_boundaries.py +48 -45
- mergeron/core/guidelines_boundaries_specialized_functions.py +24 -21
- mergeron/gen/__init__.py +72 -80
- mergeron/gen/{_data_generation_functions_nonpublic.py → _data_generation_functions.py} +103 -47
- mergeron/gen/data_generation.py +42 -42
- mergeron/gen/investigations_stats.py +1 -1
- mergeron/gen/market_sample.py +79 -0
- mergeron/gen/upp_tests.py +143 -98
- {mergeron-2024.738953.1.dist-info → mergeron-2024.738972.0.dist-info}/METADATA +32 -17
- {mergeron-2024.738953.1.dist-info → mergeron-2024.738972.0.dist-info}/RECORD +15 -14
- {mergeron-2024.738953.1.dist-info → mergeron-2024.738972.0.dist-info}/WHEEL +0 -0
mergeron/gen/data_generation.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""
|
|
2
|
-
|
|
2
|
+
Methods to generate data for analyzing merger enforcement policy.
|
|
3
3
|
|
|
4
4
|
"""
|
|
5
5
|
|
|
@@ -7,7 +7,6 @@ from __future__ import annotations
|
|
|
7
7
|
|
|
8
8
|
from importlib.metadata import version
|
|
9
9
|
|
|
10
|
-
import attrs
|
|
11
10
|
import numpy as np
|
|
12
11
|
from numpy.random import SeedSequence
|
|
13
12
|
from numpy.typing import NDArray
|
|
@@ -15,19 +14,18 @@ from numpy.typing import NDArray
|
|
|
15
14
|
from .. import _PKG_NAME, RECConstants # noqa: TID252
|
|
16
15
|
from . import (
|
|
17
16
|
EMPTY_ARRAY_DEFAULT,
|
|
18
|
-
TF,
|
|
19
17
|
FM2Constants,
|
|
20
18
|
MarketDataSample,
|
|
21
|
-
|
|
19
|
+
MarketSpec,
|
|
22
20
|
PRIConstants,
|
|
23
21
|
SHRConstants,
|
|
24
22
|
SSZConstants,
|
|
25
23
|
)
|
|
26
|
-
from .
|
|
24
|
+
from ._data_generation_functions import (
|
|
27
25
|
_gen_market_shares_dirichlet, # noqa: F401 easter-egg for external modules
|
|
28
26
|
_gen_market_shares_uniform, # noqa: F401 easter-egg for external modules
|
|
29
27
|
_gen_pcm_data,
|
|
30
|
-
|
|
28
|
+
_gen_price_data,
|
|
31
29
|
_gen_share_data,
|
|
32
30
|
)
|
|
33
31
|
|
|
@@ -35,9 +33,10 @@ __version__ = version(_PKG_NAME)
|
|
|
35
33
|
|
|
36
34
|
|
|
37
35
|
def gen_market_sample(
|
|
38
|
-
_mkt_sample_spec:
|
|
36
|
+
_mkt_sample_spec: MarketSpec,
|
|
39
37
|
/,
|
|
40
38
|
*,
|
|
39
|
+
sample_size: int = 10**6,
|
|
41
40
|
seed_seq_list: list[SeedSequence] | None = None,
|
|
42
41
|
nthreads: int = 16,
|
|
43
42
|
) -> MarketDataSample:
|
|
@@ -45,7 +44,7 @@ def gen_market_sample(
|
|
|
45
44
|
Generate share, diversion ratio, price, and margin data based on supplied parameters
|
|
46
45
|
|
|
47
46
|
Diversion ratios generated assuming share-proportionality, unless
|
|
48
|
-
`
|
|
47
|
+
`recapture_form` = "proportional", in which case both firms' recapture rate
|
|
49
48
|
is set to `r_bar`.
|
|
50
49
|
|
|
51
50
|
The tuple of SeedSequences, if specified, is parsed in the following order
|
|
@@ -54,12 +53,14 @@ def gen_market_sample(
|
|
|
54
53
|
2.) price-cost margins
|
|
55
54
|
3.) firm-counts, from :code:`[2, 2 + len(firm_counts_weights)]`,
|
|
56
55
|
weighted by :code:`firm_counts_weights`, where relevant
|
|
57
|
-
4.) prices, if :code:`
|
|
56
|
+
4.) prices, if :code:`price_spec == PRIConstants.ZERO`.
|
|
58
57
|
|
|
59
58
|
Parameters
|
|
60
59
|
----------
|
|
61
60
|
_mkt_sample_spec
|
|
62
61
|
class specifying parameters for data generation
|
|
62
|
+
sample_size
|
|
63
|
+
number of draws to generate
|
|
63
64
|
seed_seq_list
|
|
64
65
|
tuple of SeedSequences to ensure replicable data generation with
|
|
65
66
|
appropriately independent random streams
|
|
@@ -73,9 +74,10 @@ def gen_market_sample(
|
|
|
73
74
|
|
|
74
75
|
"""
|
|
75
76
|
|
|
76
|
-
_mkt_sample_spec = _mkt_sample_spec or
|
|
77
|
+
_mkt_sample_spec = _mkt_sample_spec or MarketSpec()
|
|
77
78
|
|
|
78
|
-
|
|
79
|
+
_recapture_form = _mkt_sample_spec.share_spec.recapture_form
|
|
80
|
+
_recapture_rate = _mkt_sample_spec.share_spec.recapture_rate
|
|
79
81
|
_dist_type_mktshr = _mkt_sample_spec.share_spec.dist_type
|
|
80
82
|
_dist_firm2_pcm = _mkt_sample_spec.pcm_spec.firm2_pcm_constraint
|
|
81
83
|
_hsr_filing_test_type = _mkt_sample_spec.hsr_filing_test_type
|
|
@@ -86,22 +88,23 @@ def gen_market_sample(
|
|
|
86
88
|
_fcount_rng_seed_seq,
|
|
87
89
|
_pr_rng_seed_seq,
|
|
88
90
|
) = parse_seed_seq_list(
|
|
89
|
-
seed_seq_list, _dist_type_mktshr, _mkt_sample_spec.
|
|
91
|
+
seed_seq_list, _dist_type_mktshr, _mkt_sample_spec.price_spec
|
|
90
92
|
)
|
|
91
93
|
|
|
92
|
-
_shr_sample_size = 1.0 *
|
|
94
|
+
_shr_sample_size = 1.0 * sample_size
|
|
93
95
|
# Scale up sample size to offset discards based on specified criteria
|
|
94
96
|
_shr_sample_size *= _hsr_filing_test_type
|
|
95
97
|
if _dist_firm2_pcm == FM2Constants.MNL:
|
|
96
98
|
_shr_sample_size *= SSZConstants.MNL_DEP
|
|
97
|
-
|
|
98
|
-
_mkt_sample_spec, sample_size=int(_shr_sample_size)
|
|
99
|
-
)
|
|
100
|
-
del _shr_sample_size
|
|
99
|
+
_shr_sample_size = int(_shr_sample_size)
|
|
101
100
|
|
|
102
101
|
# Generate share data
|
|
103
102
|
_mktshr_data = _gen_share_data(
|
|
104
|
-
|
|
103
|
+
_shr_sample_size,
|
|
104
|
+
_mkt_sample_spec,
|
|
105
|
+
_fcount_rng_seed_seq,
|
|
106
|
+
_mktshr_rng_seed_seq,
|
|
107
|
+
nthreads,
|
|
105
108
|
)
|
|
106
109
|
|
|
107
110
|
_mktshr_array, _fcounts, _aggregate_purchase_prob, _nth_firm_share = (
|
|
@@ -115,8 +118,8 @@ def gen_market_sample(
|
|
|
115
118
|
)
|
|
116
119
|
|
|
117
120
|
# Generate merging-firm price data
|
|
118
|
-
_price_data =
|
|
119
|
-
_mktshr_array[:, :2], _nth_firm_share,
|
|
121
|
+
_price_data = _gen_price_data(
|
|
122
|
+
_mktshr_array[:, :2], _nth_firm_share, _mkt_sample_spec, _pr_rng_seed_seq
|
|
120
123
|
)
|
|
121
124
|
|
|
122
125
|
_price_array, _hsr_filing_test = (
|
|
@@ -132,16 +135,13 @@ def gen_market_sample(
|
|
|
132
135
|
|
|
133
136
|
# Calculate diversion ratios
|
|
134
137
|
_divr_array = gen_divr_array(
|
|
135
|
-
_mktshr_array[:, :2],
|
|
136
|
-
_mkt_sample_spec_here.recapture_rate or 0.8,
|
|
137
|
-
_recapture_spec,
|
|
138
|
-
_aggregate_purchase_prob,
|
|
138
|
+
_recapture_form, _recapture_rate, _mktshr_array[:, :2], _aggregate_purchase_prob
|
|
139
139
|
)
|
|
140
140
|
|
|
141
141
|
# Generate margin data
|
|
142
142
|
_pcm_data = _gen_pcm_data(
|
|
143
143
|
_mktshr_array[:, :2],
|
|
144
|
-
|
|
144
|
+
_mkt_sample_spec,
|
|
145
145
|
_price_array,
|
|
146
146
|
_aggregate_purchase_prob,
|
|
147
147
|
_pcm_rng_seed_seq,
|
|
@@ -151,7 +151,7 @@ def gen_market_sample(
|
|
|
151
151
|
getattr(_pcm_data, _f) for _f in ("pcm_array", "mnl_test_array")
|
|
152
152
|
)
|
|
153
153
|
|
|
154
|
-
_s_size =
|
|
154
|
+
_s_size = sample_size # originally-specified sample size
|
|
155
155
|
if _dist_firm2_pcm == FM2Constants.MNL:
|
|
156
156
|
_mktshr_array = _mktshr_array[_mnl_test_rows][:_s_size]
|
|
157
157
|
_pcm_array = _pcm_array[_mnl_test_rows][:_s_size]
|
|
@@ -185,18 +185,18 @@ def gen_market_sample(
|
|
|
185
185
|
|
|
186
186
|
def parse_seed_seq_list(
|
|
187
187
|
_sseq_list: list[SeedSequence] | None,
|
|
188
|
-
|
|
189
|
-
|
|
188
|
+
_mktshr_dist_type: SHRConstants,
|
|
189
|
+
_price_spec: PRIConstants,
|
|
190
190
|
/,
|
|
191
191
|
) -> tuple[SeedSequence, SeedSequence, SeedSequence | None, SeedSequence | None]:
|
|
192
192
|
"""Initialize RNG seed sequences to ensure independence of distinct random streams."""
|
|
193
193
|
_fcount_rng_seed_seq: SeedSequence | None = None
|
|
194
194
|
_pr_rng_seed_seq: SeedSequence | None = None
|
|
195
195
|
|
|
196
|
-
if
|
|
196
|
+
if _price_spec == PRIConstants.ZERO:
|
|
197
197
|
_pr_rng_seed_seq = _sseq_list.pop() if _sseq_list else SeedSequence(pool_size=8)
|
|
198
198
|
|
|
199
|
-
if
|
|
199
|
+
if _mktshr_dist_type == SHRConstants.UNI:
|
|
200
200
|
_fcount_rng_seed_seq = None
|
|
201
201
|
_seed_count = 2
|
|
202
202
|
_mktshr_rng_seed_seq, _pcm_rng_seed_seq = (
|
|
@@ -221,10 +221,10 @@ def parse_seed_seq_list(
|
|
|
221
221
|
|
|
222
222
|
|
|
223
223
|
def gen_divr_array(
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
_aggregate_purchase_prob: NDArray[np.
|
|
224
|
+
_recapture_form: RECConstants,
|
|
225
|
+
_recapture_rate: float | None,
|
|
226
|
+
_frmshr_array: NDArray[np.float64],
|
|
227
|
+
_aggregate_purchase_prob: NDArray[np.float64] = EMPTY_ARRAY_DEFAULT,
|
|
228
228
|
/,
|
|
229
229
|
) -> NDArray[np.float64]:
|
|
230
230
|
"""
|
|
@@ -235,20 +235,20 @@ def gen_divr_array(
|
|
|
235
235
|
|
|
236
236
|
Parameters
|
|
237
237
|
----------
|
|
238
|
-
|
|
239
|
-
|
|
238
|
+
_recapture_form
|
|
239
|
+
Enum specifying Fixed (proportional), Inside-out, or Outside-in
|
|
240
240
|
|
|
241
|
-
|
|
241
|
+
_recapture_rate
|
|
242
242
|
If recapture is proportional or inside-out, the recapture rate
|
|
243
243
|
for the firm with the smaller share.
|
|
244
244
|
|
|
245
|
+
_frmshr_array
|
|
246
|
+
Merging-firm shares.
|
|
247
|
+
|
|
245
248
|
_aggregate_purchase_prob
|
|
246
249
|
1 minus probability that the outside good is chosen; converts
|
|
247
250
|
market shares to choice probabilities by multiplication.
|
|
248
251
|
|
|
249
|
-
_recapture_spec
|
|
250
|
-
Enum specifying Fixed (proportional), Inside-out, or Outside-in
|
|
251
|
-
|
|
252
252
|
Returns
|
|
253
253
|
-------
|
|
254
254
|
Merging-firm diversion ratios for mergers in the sample.
|
|
@@ -256,8 +256,8 @@ def gen_divr_array(
|
|
|
256
256
|
"""
|
|
257
257
|
|
|
258
258
|
_divr_array: NDArray[np.float64]
|
|
259
|
-
if
|
|
260
|
-
_divr_array =
|
|
259
|
+
if _recapture_form == RECConstants.FIXED:
|
|
260
|
+
_divr_array = _recapture_rate * _frmshr_array[:, ::-1] / (1 - _frmshr_array) # type: ignore
|
|
261
261
|
|
|
262
262
|
else:
|
|
263
263
|
_purchprob_array = _aggregate_purchase_prob * _frmshr_array
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Methods to generate data for analyzing merger enforcement policy.
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from importlib.metadata import version
|
|
9
|
+
|
|
10
|
+
from attrs import define
|
|
11
|
+
from numpy.random import SeedSequence
|
|
12
|
+
|
|
13
|
+
from .. import _PKG_NAME # noqa: TID252
|
|
14
|
+
from ..core import guidelines_boundaries as gbl # noqa: TID252
|
|
15
|
+
from . import MarketSpec, UPPTestRegime
|
|
16
|
+
from .data_generation import gen_market_sample
|
|
17
|
+
from .upp_tests import SaveData, invres_cnts, save_data_to_hdf5, sim_invres_cnts_ll
|
|
18
|
+
|
|
19
|
+
__version__ = version(_PKG_NAME)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@define(slots=False)
|
|
23
|
+
class MarketSample(MarketSpec):
|
|
24
|
+
def generate_sample(
|
|
25
|
+
self,
|
|
26
|
+
/,
|
|
27
|
+
*,
|
|
28
|
+
sample_size: int = 10**6,
|
|
29
|
+
seed_seq_list: list[SeedSequence] | None,
|
|
30
|
+
nthreads: int,
|
|
31
|
+
save_data_to_file: SaveData = False,
|
|
32
|
+
) -> None:
|
|
33
|
+
self.data = gen_market_sample(
|
|
34
|
+
self,
|
|
35
|
+
sample_size=sample_size,
|
|
36
|
+
seed_seq_list=seed_seq_list,
|
|
37
|
+
nthreads=nthreads,
|
|
38
|
+
)
|
|
39
|
+
_invalid_array_names = (
|
|
40
|
+
("fcounts", "choice_prob_outgd", "nth_firm_share", "hhi_post")
|
|
41
|
+
if self.share_spec.dist_type == "Uniform"
|
|
42
|
+
else ()
|
|
43
|
+
)
|
|
44
|
+
if save_data_to_file:
|
|
45
|
+
save_data_to_hdf5(
|
|
46
|
+
self.data,
|
|
47
|
+
excluded_attrs=_invalid_array_names,
|
|
48
|
+
save_data_to_file=save_data_to_file,
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
def estimate_invres_counts(
|
|
52
|
+
self,
|
|
53
|
+
_invres_parm_vec: gbl.HMGThresholds,
|
|
54
|
+
_upp_test_regime: UPPTestRegime,
|
|
55
|
+
/,
|
|
56
|
+
*,
|
|
57
|
+
sample_size: int = 10**6,
|
|
58
|
+
seed_seq_list: list[SeedSequence] | None,
|
|
59
|
+
nthreads: int,
|
|
60
|
+
save_data_to_file: SaveData = False,
|
|
61
|
+
) -> None:
|
|
62
|
+
if getattr(self, "market_data_sample", None) is None:
|
|
63
|
+
self.invres_counts = sim_invres_cnts_ll(
|
|
64
|
+
self,
|
|
65
|
+
_invres_parm_vec,
|
|
66
|
+
_upp_test_regime,
|
|
67
|
+
save_data_to_file=save_data_to_file,
|
|
68
|
+
sample_size=sample_size,
|
|
69
|
+
seed_seq_list=seed_seq_list,
|
|
70
|
+
nthreads=nthreads,
|
|
71
|
+
)
|
|
72
|
+
else:
|
|
73
|
+
self.invres_counts = invres_cnts(
|
|
74
|
+
self.data, _invres_parm_vec, _upp_test_regime
|
|
75
|
+
)
|
|
76
|
+
if save_data_to_file:
|
|
77
|
+
save_data_to_hdf5(
|
|
78
|
+
self.invres_counts, save_data_to_file=save_data_to_file
|
|
79
|
+
)
|