mergeron 2024.738953.0__py3-none-any.whl → 2024.738953.1__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-2024.738953.0.dist-info → mergeron-2024.738953.1.dist-info}/METADATA +1 -1
- {mergeron-2024.738953.0.dist-info → mergeron-2024.738953.1.dist-info}/RECORD +3 -17
- mergeron/examples/__init__.py +0 -5
- mergeron/examples/concentration_as_diversion.py +0 -625
- mergeron/examples/enforcement_boundaries_for_mergers_with_asymmetric_shares.py +0 -493
- mergeron/examples/enforcement_boundaries_for_symmetric_firm_mergers.py +0 -206
- mergeron/examples/example_parameterizations.py +0 -143
- mergeron/examples/guidelines_enforcement_patterns.py +0 -74
- mergeron/examples/investigations_stats_obs_tables.py +0 -481
- mergeron/examples/investigations_stats_sim_tables.py +0 -425
- mergeron/examples/plotSafeHarbs_symbolically.py +0 -53
- mergeron/examples/sound_guppi_safeharbor.py +0 -181
- mergeron/examples/summarize_ftc_investigations_data.py +0 -44
- mergeron/examples/testIntrinsicClearanceRates.py +0 -135
- mergeron/examples/visualize_empirical_margin_distribution.py +0 -100
- mergeron/examples/visualize_guidelines_tests.py +0 -298
- {mergeron-2024.738953.0.dist-info → mergeron-2024.738953.1.dist-info}/WHEEL +0 -0
|
@@ -1,425 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Analyze simulated data on merger enforcement under U.S. Horizontal Merger Guidelines.
|
|
3
|
-
|
|
4
|
-
Format output as LaTeX tables (using TikZ).
|
|
5
|
-
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
import sys
|
|
9
|
-
import warnings
|
|
10
|
-
from collections.abc import Mapping, Sequence
|
|
11
|
-
from dataclasses import fields
|
|
12
|
-
from datetime import datetime, timedelta
|
|
13
|
-
from io import TextIOWrapper
|
|
14
|
-
from typing import Any
|
|
15
|
-
|
|
16
|
-
import numpy as np
|
|
17
|
-
from attrs import evolve
|
|
18
|
-
|
|
19
|
-
import mergeron.core.ftc_merger_investigations_data as fid
|
|
20
|
-
import mergeron.core.guidelines_boundaries as gbl
|
|
21
|
-
import mergeron.gen.investigations_stats as isl
|
|
22
|
-
import mergeron.gen.upp_tests as utl
|
|
23
|
-
from mergeron import DATA_DIR, RECConstants, UPPAggrSelector
|
|
24
|
-
from mergeron.core.proportions_tests import propn_ci
|
|
25
|
-
from mergeron.gen import (
|
|
26
|
-
FM2Constants,
|
|
27
|
-
INVResolution,
|
|
28
|
-
MarketSampleSpec,
|
|
29
|
-
PCMConstants,
|
|
30
|
-
PCMSpec,
|
|
31
|
-
ShareSpec,
|
|
32
|
-
SHRConstants,
|
|
33
|
-
SSZConstants,
|
|
34
|
-
UPPTestRegime,
|
|
35
|
-
)
|
|
36
|
-
|
|
37
|
-
if not sys.warnoptions:
|
|
38
|
-
warnings.simplefilter("ignore") # , category="RuntimeWarning")
|
|
39
|
-
|
|
40
|
-
dottex_format_str = "FTC{}RateCITables_{}_{}_SYM.tex"
|
|
41
|
-
stats_table_content = isl.StatsContainer()
|
|
42
|
-
stats_table_design = isl.latex_jinja_env.get_template(
|
|
43
|
-
"clrrate_cis_summary_table_template.tex.jinja2"
|
|
44
|
-
)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
def invres_stats_sim_setup(
|
|
48
|
-
_invdata: fid.INVData,
|
|
49
|
-
_data_period: str,
|
|
50
|
-
_merger_class: isl.INDGRPConstants | isl.EVIDENConstants,
|
|
51
|
-
_invres_parm_vec: gbl.HMGThresholds,
|
|
52
|
-
_sample_spec: MarketSampleSpec,
|
|
53
|
-
_invres_stats_kwargs: utl.IVNRESCntsArgs | None = None,
|
|
54
|
-
/,
|
|
55
|
-
) -> str:
|
|
56
|
-
_table_ind_group = (
|
|
57
|
-
_merger_class
|
|
58
|
-
if isinstance(_merger_class, isl.INDGRPConstants)
|
|
59
|
-
else isl.INDGRPConstants.ALL
|
|
60
|
-
)
|
|
61
|
-
_table_evid_cond = (
|
|
62
|
-
_merger_class
|
|
63
|
-
if isinstance(_merger_class, isl.EVIDENConstants)
|
|
64
|
-
else isl.EVIDENConstants.UR
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
_invres_stats_kwargs = _invres_stats_kwargs or {
|
|
68
|
-
"sim_test_regime": UPPTestRegime(INVResolution.ENFT, UPPAggrSelector.MAX, None)
|
|
69
|
-
}
|
|
70
|
-
_sim_test_regime = _invres_stats_kwargs.get("sim_test_regime")
|
|
71
|
-
|
|
72
|
-
_invres_spec, _guppi_weighting, _divr_weighting = (
|
|
73
|
-
getattr(_sim_test_regime, _f.name)
|
|
74
|
-
for _f in fields(_sim_test_regime) # type: ignore
|
|
75
|
-
)
|
|
76
|
-
|
|
77
|
-
# Get observed rates
|
|
78
|
-
(
|
|
79
|
-
_invres_cnts_obs_byfirmcount_array,
|
|
80
|
-
_invres_cnts_obs_bydelta_array,
|
|
81
|
-
_invres_cnts_obs_byconczone_array,
|
|
82
|
-
) = (
|
|
83
|
-
isl.invres_stats_cnts_by_group(
|
|
84
|
-
_invdata,
|
|
85
|
-
_data_period,
|
|
86
|
-
_table_ind_group,
|
|
87
|
-
_table_evid_cond,
|
|
88
|
-
_grp,
|
|
89
|
-
_invres_spec,
|
|
90
|
-
)
|
|
91
|
-
for _grp in (
|
|
92
|
-
isl.StatsGrpSelector.FC,
|
|
93
|
-
isl.StatsGrpSelector.DL,
|
|
94
|
-
isl.StatsGrpSelector.ZN,
|
|
95
|
-
)
|
|
96
|
-
)
|
|
97
|
-
|
|
98
|
-
_sample_spec_here = evolve(
|
|
99
|
-
_sample_spec,
|
|
100
|
-
share_spec=ShareSpec(
|
|
101
|
-
RECConstants.INOUT,
|
|
102
|
-
SHRConstants.DIR_FLAT,
|
|
103
|
-
None,
|
|
104
|
-
_invres_cnts_obs_byfirmcount_array[:-1, 1],
|
|
105
|
-
),
|
|
106
|
-
)
|
|
107
|
-
|
|
108
|
-
# Generate simulated rates
|
|
109
|
-
_start_time = datetime.now()
|
|
110
|
-
_upp_tests_counts = utl.sim_invres_cnts_ll(
|
|
111
|
-
_invres_parm_vec, _sample_spec_here, _invres_stats_kwargs
|
|
112
|
-
)
|
|
113
|
-
_total_duration = datetime.now() - _start_time
|
|
114
|
-
|
|
115
|
-
print(
|
|
116
|
-
f"estimations completed in {_total_duration / timedelta(seconds=1):.6f} secs."
|
|
117
|
-
)
|
|
118
|
-
|
|
119
|
-
# Prepare and write/print output tables
|
|
120
|
-
_stats_group_dict = {
|
|
121
|
-
isl.StatsGrpSelector.FC: {
|
|
122
|
-
"desc": f"{_invres_spec.capitalize()} rates by firm count",
|
|
123
|
-
"title_str": "By Number of Significant Competitors",
|
|
124
|
-
"hval": "Firm Count",
|
|
125
|
-
"hcol_width": 54,
|
|
126
|
-
"notewidth": 0.63,
|
|
127
|
-
"obs_array": _invres_cnts_obs_byfirmcount_array,
|
|
128
|
-
"sim_array": _upp_tests_counts.by_firm_count,
|
|
129
|
-
},
|
|
130
|
-
isl.StatsGrpSelector.DL: {
|
|
131
|
-
"desc": Rf"{_invres_spec.capitalize()} rates by range of $\Delta HHI$",
|
|
132
|
-
"title_str": R"By Change in Concentration (\Deltah{})",
|
|
133
|
-
"hval": R"$\Delta HHI$",
|
|
134
|
-
"hval_plus": R"{ $[\Delta_L, \Delta_H)$ }",
|
|
135
|
-
"hcol_width": 54,
|
|
136
|
-
"notewidth": 0.63,
|
|
137
|
-
"notestr_plus": " ".join((
|
|
138
|
-
R"\(\cdot\) Ranges of $\Delta HHI$ are defined as",
|
|
139
|
-
"half-open intervals with",
|
|
140
|
-
R"$\Delta_L \leqslant \Delta HHI < \Delta_H$, except that",
|
|
141
|
-
R"$2500 \text{ pts.} \leqslant \Delta HHI \leqslant 5000 \text{ pts.}$",
|
|
142
|
-
R"in the closed interval [2500, 5000]",
|
|
143
|
-
isl.LTX_ARRAY_LINEEND,
|
|
144
|
-
isl.LTX_ARRAY_LINEEND,
|
|
145
|
-
)),
|
|
146
|
-
"obs_array": _invres_cnts_obs_bydelta_array,
|
|
147
|
-
"sim_array": _upp_tests_counts.by_delta,
|
|
148
|
-
},
|
|
149
|
-
isl.StatsGrpSelector.ZN: {
|
|
150
|
-
"desc": f"{_invres_spec.capitalize()} rates by Approximate Presumption Zone",
|
|
151
|
-
"title_str": "{} {}".format(
|
|
152
|
-
R"By Approximate \textit{2010 Guidelines}",
|
|
153
|
-
"Concentration-Based Standards",
|
|
154
|
-
),
|
|
155
|
-
"hval": "Approximate Standard",
|
|
156
|
-
"hcol_width": 190,
|
|
157
|
-
"notewidth": 0.96,
|
|
158
|
-
"obs_array": _invres_cnts_obs_byconczone_array,
|
|
159
|
-
"sim_array": _upp_tests_counts.by_conczone,
|
|
160
|
-
},
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
_stats_table_name = dottex_format_str.format(
|
|
164
|
-
_invres_spec.capitalize(),
|
|
165
|
-
_merger_class.replace(" ", ""),
|
|
166
|
-
_data_period.split("-")[1],
|
|
167
|
-
)
|
|
168
|
-
with (DATA_DIR / _stats_table_name).open(
|
|
169
|
-
"w", encoding="UTF-8"
|
|
170
|
-
) as _stats_table_file:
|
|
171
|
-
for _stats_group_key in _stats_group_dict:
|
|
172
|
-
invres_stats_sim_render(
|
|
173
|
-
_data_period,
|
|
174
|
-
_merger_class,
|
|
175
|
-
_stats_group_key,
|
|
176
|
-
_stats_group_dict[_stats_group_key],
|
|
177
|
-
_invres_parm_vec,
|
|
178
|
-
_invres_stats_kwargs["sim_test_regime"],
|
|
179
|
-
_stats_table_file,
|
|
180
|
-
)
|
|
181
|
-
|
|
182
|
-
return _stats_table_name
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
def invres_stats_sim_render(
|
|
186
|
-
_data_period: str,
|
|
187
|
-
_merger_class: isl.INDGRPConstants | isl.EVIDENConstants,
|
|
188
|
-
_stats_group: isl.StatsGrpSelector,
|
|
189
|
-
_stats_group_dict_sub: Mapping[str, Any],
|
|
190
|
-
_invres_parm_vec: gbl.HMGThresholds,
|
|
191
|
-
_sim_test_regime: UPPTestRegime,
|
|
192
|
-
_stats_table_file: TextIOWrapper,
|
|
193
|
-
/,
|
|
194
|
-
) -> None:
|
|
195
|
-
_stats_table_content = isl.StatsContainer()
|
|
196
|
-
|
|
197
|
-
_obs_sample_sz, _sim_sample_sz = (
|
|
198
|
-
np.einsum("i->", _stats_group_dict_sub[_g][:, _h]).astype(int)
|
|
199
|
-
for _g, _h in (("obs_array", -2), ("sim_array", -5))
|
|
200
|
-
)
|
|
201
|
-
|
|
202
|
-
_invres_select = _sim_test_regime.resolution
|
|
203
|
-
(
|
|
204
|
-
_stats_table_content.test_res,
|
|
205
|
-
_stats_table_content.obs_merger_class,
|
|
206
|
-
_stats_table_content.obs_period,
|
|
207
|
-
) = (_invres_select.capitalize(), _merger_class, _data_period.split("-"))
|
|
208
|
-
|
|
209
|
-
_r_bar = _invres_parm_vec.rec
|
|
210
|
-
(
|
|
211
|
-
_stats_table_content.rbar,
|
|
212
|
-
_stats_table_content.guppi_bound,
|
|
213
|
-
_stats_table_content.dbar,
|
|
214
|
-
_stats_table_content.cmcr_bound,
|
|
215
|
-
_stats_table_content.ipr_bound,
|
|
216
|
-
) = (
|
|
217
|
-
rf"{_s * 100:.1f}\%"
|
|
218
|
-
for _s in (
|
|
219
|
-
getattr(_invres_parm_vec, _f)
|
|
220
|
-
for _f in ("rec", "guppi", "divr", "cmcr", "ipr")
|
|
221
|
-
)
|
|
222
|
-
)
|
|
223
|
-
|
|
224
|
-
# Prepare and write/print output tables
|
|
225
|
-
_stats_cis_wilson_notestr = " ".join((
|
|
226
|
-
R"Confidence intervals (95\% CI) are",
|
|
227
|
-
R"estimated by the Wilson method, given the",
|
|
228
|
-
"reported numbers of investigated mergers and cleared mergers",
|
|
229
|
-
_stats_group_dict_sub["desc"].replace(
|
|
230
|
-
f"{_stats_table_content.test_res} rates ", ""
|
|
231
|
-
),
|
|
232
|
-
isl.LTX_ARRAY_LINEEND,
|
|
233
|
-
))
|
|
234
|
-
|
|
235
|
-
_eg_count = int(_relfreq_eg := 0.01) * _sim_sample_sz
|
|
236
|
-
_stats_sim_ci_eg = 100 * np.array(
|
|
237
|
-
propn_ci(int(0.50 * _eg_count), _eg_count, method="Exact")
|
|
238
|
-
)
|
|
239
|
-
_stats_sim_notestr = " ".join((
|
|
240
|
-
Rf"\(\cdot\) Simulated {_stats_table_content.test_res} rates are estimated by",
|
|
241
|
-
"Monte Carlo integration over generated data representing",
|
|
242
|
-
Rf"{_sim_sample_sz:,d} hypothetical mergers. Thus,",
|
|
243
|
-
R"for a subset of simulations with a relative frequency",
|
|
244
|
-
Rf"of, say, {100 * _relfreq_eg:.1f}\%,",
|
|
245
|
-
R"and an estimated clearance rate of, for example, 50.0\%,",
|
|
246
|
-
Rf"the margin of error (m.o.e.) is {isl.moe_tmpl.render(rv=_stats_sim_ci_eg)}."
|
|
247
|
-
R"The m.o.e. is derived from the",
|
|
248
|
-
R"Clopper-Pearson exact 95\% confidence interval, {}.".format( # noqa: UP032
|
|
249
|
-
isl.ci_format_str.format(*_stats_sim_ci_eg).strip()
|
|
250
|
-
),
|
|
251
|
-
R"(The m.o.e. for simulated clearance rates varies",
|
|
252
|
-
R"as the reciprocal of the square root of the number",
|
|
253
|
-
R"of hypothetical mergers.)",
|
|
254
|
-
isl.LTX_ARRAY_LINEEND,
|
|
255
|
-
))
|
|
256
|
-
del _relfreq_eg, _eg_count, _stats_sim_ci_eg
|
|
257
|
-
|
|
258
|
-
print(
|
|
259
|
-
f"Observed {_invres_select} proportion [95% CI]",
|
|
260
|
-
_stats_group_dict_sub["desc"].replace(f"{_invres_select} rates ", ""),
|
|
261
|
-
)
|
|
262
|
-
print(f"\t with sample size (observed): {_obs_sample_sz:,d};")
|
|
263
|
-
|
|
264
|
-
_stats_table_content.obs_summary_type = f"{_stats_group}"
|
|
265
|
-
_stats_table_content.obs_summary_type_title = _stats_group_dict_sub["desc"]
|
|
266
|
-
_stats_table_content.stats_cis_notewidth = _stats_group_dict_sub["notewidth"]
|
|
267
|
-
_stats_cis_numobs_notestr = " ".join((
|
|
268
|
-
R"\(\cdot\) Estimates for Proportion {} are based on".format(
|
|
269
|
-
"Enforced" if _invres_select == INVResolution.ENFT else "Cleared"
|
|
270
|
-
),
|
|
271
|
-
f"{_obs_sample_sz:,d} total observations (investigated mergers).",
|
|
272
|
-
))
|
|
273
|
-
|
|
274
|
-
_spnum = 2 if _stats_group_dict_sub["notewidth"] < 0.90 else 1
|
|
275
|
-
_stats_table_content.stats_cis_notestr = " ".join((
|
|
276
|
-
_stats_cis_numobs_notestr,
|
|
277
|
-
_stats_cis_wilson_notestr,
|
|
278
|
-
*[isl.LTX_ARRAY_LINEEND] * _spnum,
|
|
279
|
-
_stats_sim_notestr,
|
|
280
|
-
*[isl.LTX_ARRAY_LINEEND] * (_spnum + 1),
|
|
281
|
-
))
|
|
282
|
-
del _spnum
|
|
283
|
-
|
|
284
|
-
if _nsp := _stats_group_dict_sub.get("notestr_plus", ""):
|
|
285
|
-
_stats_table_content.stats_cis_notestr += "".join((isl.LTX_ARRAY_LINEEND, _nsp))
|
|
286
|
-
del _nsp
|
|
287
|
-
|
|
288
|
-
_invres_stats_report_func = (
|
|
289
|
-
isl.latex_tbl_invres_stats_byzone
|
|
290
|
-
if _stats_group == isl.StatsGrpSelector.ZN
|
|
291
|
-
else isl.latex_tbl_invres_stats_1dim
|
|
292
|
-
)
|
|
293
|
-
_sort_order = (
|
|
294
|
-
isl.SortSelector.UCH
|
|
295
|
-
if _stats_group == isl.StatsGrpSelector.FC
|
|
296
|
-
else isl.SortSelector.REV
|
|
297
|
-
)
|
|
298
|
-
|
|
299
|
-
_invres_stats_hdr_list, _invres_stats_dat_list = _invres_stats_report_func(
|
|
300
|
-
_stats_group_dict_sub["obs_array"],
|
|
301
|
-
return_type_sel=isl.StatsReturnSelector.RIN,
|
|
302
|
-
sort_order=_sort_order,
|
|
303
|
-
)
|
|
304
|
-
|
|
305
|
-
if _stats_group == isl.StatsGrpSelector.FC:
|
|
306
|
-
del _invres_stats_hdr_list[-2], _invres_stats_dat_list[-2]
|
|
307
|
-
|
|
308
|
-
_stats_table_content.stats_numrows = len(_invres_stats_hdr_list)
|
|
309
|
-
_stats_table_content.hdrcol_cis_width = f'{_stats_group_dict_sub["hcol_width"]}pt'
|
|
310
|
-
|
|
311
|
-
_hs1 = _stats_group_dict_sub["hval"]
|
|
312
|
-
_hs2 = _h if (_h := _stats_group_dict_sub.get("hval_plus", "")) else _hs1
|
|
313
|
-
_stats_table_content.hdrcoldescstr = isl.latex_hrdcoldesc_format_str.format(
|
|
314
|
-
"hdrcol_cis",
|
|
315
|
-
f'{_stats_group_dict_sub["hcol_width"]}pt',
|
|
316
|
-
"hdrcoldesc_cis",
|
|
317
|
-
"center",
|
|
318
|
-
" ".join((
|
|
319
|
-
_hs1 if _hs1 != _hs2 else Rf"{{ \phantom{{{_hs1}}} }}",
|
|
320
|
-
isl.LTX_ARRAY_LINEEND,
|
|
321
|
-
_hs2,
|
|
322
|
-
isl.LTX_ARRAY_LINEEND,
|
|
323
|
-
)),
|
|
324
|
-
)
|
|
325
|
-
del _hs1, _hs2
|
|
326
|
-
|
|
327
|
-
_stats_table_content.stats_hdrstr = "".join([
|
|
328
|
-
f"{g} {isl.LTX_ARRAY_LINEEND}" for g in _invres_stats_hdr_list
|
|
329
|
-
])
|
|
330
|
-
_stats_table_content.stats_cis = "".join([
|
|
331
|
-
f"{" & ".join(g)} {isl.LTX_ARRAY_LINEEND}" for g in _invres_stats_dat_list
|
|
332
|
-
])
|
|
333
|
-
# Print to console
|
|
334
|
-
isl.stats_print_rows(_invres_stats_hdr_list, _invres_stats_dat_list)
|
|
335
|
-
del _invres_stats_hdr_list, _invres_stats_dat_list
|
|
336
|
-
|
|
337
|
-
print(f"Simulated {_invres_select} rates {_stats_group}:")
|
|
338
|
-
print(f"\t with generated data size = {_sim_sample_sz:,d}:")
|
|
339
|
-
|
|
340
|
-
_stats_sim_hdr_list, _stats_sim_dat_list = _invres_stats_report_func(
|
|
341
|
-
_stats_group_dict_sub["sim_array"],
|
|
342
|
-
return_type_sel=isl.StatsReturnSelector.RPT,
|
|
343
|
-
sort_order=_sort_order,
|
|
344
|
-
)
|
|
345
|
-
|
|
346
|
-
# Exclude results of IPR tests
|
|
347
|
-
_stats_sim_dat_list = [_f[:-1] for _f in _stats_sim_dat_list]
|
|
348
|
-
_stats_table_content.stats_sim = "".join([
|
|
349
|
-
f"{" & ".join(g)} {isl.LTX_ARRAY_LINEEND}" for g in _stats_sim_dat_list
|
|
350
|
-
])
|
|
351
|
-
# Print to console
|
|
352
|
-
isl.stats_print_rows(_stats_sim_hdr_list, _stats_sim_dat_list)
|
|
353
|
-
del _stats_sim_hdr_list, _stats_sim_dat_list
|
|
354
|
-
|
|
355
|
-
# Generate and write out LaTeX
|
|
356
|
-
_stats_table_design = isl.latex_jinja_env.get_template(
|
|
357
|
-
"clrrate_cis_summary_table_template.tex.jinja2"
|
|
358
|
-
)
|
|
359
|
-
# Write to dottex
|
|
360
|
-
_stats_table_file.write(_stats_table_design.render(tmpl_data=_stats_table_content))
|
|
361
|
-
print("\n", file=_stats_table_file)
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
if __name__ == "__main__":
|
|
365
|
-
invdata_array_dict = fid.construct_data(
|
|
366
|
-
fid.INVDATA_ARCHIVE_PATH,
|
|
367
|
-
flag_backward_compatibility=False,
|
|
368
|
-
flag_pharma_for_exclusion=True,
|
|
369
|
-
)
|
|
370
|
-
|
|
371
|
-
data_periods = ("1996-2003", "2004-2011")
|
|
372
|
-
merger_classes: Sequence[isl.INDGRPConstants | isl.EVIDENConstants] = (
|
|
373
|
-
isl.INDGRPConstants.ALL,
|
|
374
|
-
isl.EVIDENConstants.ED,
|
|
375
|
-
)
|
|
376
|
-
|
|
377
|
-
sample_sz_base = 10**7
|
|
378
|
-
pcm_dist_type, pcm_dist_parms = PCMConstants.EMPR, None
|
|
379
|
-
|
|
380
|
-
sim_test_regime = (
|
|
381
|
-
UPPTestRegime(INVResolution.CLRN, UPPAggrSelector.MAX, None),
|
|
382
|
-
UPPTestRegime(INVResolution.ENFT, UPPAggrSelector.OSD, None),
|
|
383
|
-
)[1]
|
|
384
|
-
invres_stats_kwargs = {"sim_test_regime": sim_test_regime}
|
|
385
|
-
|
|
386
|
-
table_dottex_namelist = ()
|
|
387
|
-
for merger_class in merger_classes:
|
|
388
|
-
for study_period in data_periods:
|
|
389
|
-
if study_period == data_periods[1]:
|
|
390
|
-
continue
|
|
391
|
-
|
|
392
|
-
print(
|
|
393
|
-
f"{sim_test_regime.resolution.capitalize()} rates and c.i.s",
|
|
394
|
-
f"for the class of mergers, '{merger_class}',",
|
|
395
|
-
f"for study period, {study_period}:",
|
|
396
|
-
)
|
|
397
|
-
stats_table_content.obs_period = study_period.split("-")
|
|
398
|
-
|
|
399
|
-
invres_parm_vec = (
|
|
400
|
-
gbl.GuidelinesThresholds(2010).presumption
|
|
401
|
-
if study_period.split("-")[1] == data_periods[1].split("-")[1]
|
|
402
|
-
else gbl.GuidelinesThresholds(1992).presumption
|
|
403
|
-
)
|
|
404
|
-
|
|
405
|
-
mkt_sample_spec = MarketSampleSpec(
|
|
406
|
-
sample_sz_base,
|
|
407
|
-
invres_parm_vec.rec,
|
|
408
|
-
pcm_spec=PCMSpec(pcm_dist_type, FM2Constants.MNL, pcm_dist_parms),
|
|
409
|
-
hsr_filing_test_type=SSZConstants.HSR_NTH,
|
|
410
|
-
)
|
|
411
|
-
|
|
412
|
-
table_dottex_name = invres_stats_sim_setup(
|
|
413
|
-
invdata_array_dict,
|
|
414
|
-
study_period,
|
|
415
|
-
merger_class,
|
|
416
|
-
invres_parm_vec,
|
|
417
|
-
mkt_sample_spec,
|
|
418
|
-
invres_stats_kwargs, # type: ignore
|
|
419
|
-
)
|
|
420
|
-
table_dottex_namelist += (table_dottex_name,) # type: ignore
|
|
421
|
-
|
|
422
|
-
isl.render_table_pdf(
|
|
423
|
-
table_dottex_namelist,
|
|
424
|
-
dottex_format_str.format(sim_test_regime.resolution.capitalize(), "All", "All"),
|
|
425
|
-
)
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
|
|
3
|
-
Solve for, and plot, weighted-average GUPPI boundaries using sympy,
|
|
4
|
-
as a check against the numerical solutions in mergeron.core.guidelines_boundaries
|
|
5
|
-
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
from collections.abc import Sequence
|
|
9
|
-
|
|
10
|
-
from sympy import solve, symbols
|
|
11
|
-
from sympy.plotting import plot as symplot
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def plot_safeharb_boundaries(
|
|
15
|
-
_g_bar: float, _r_bar: float, _m_vals: Sequence[float]
|
|
16
|
-
) -> None:
|
|
17
|
-
s1, s2, rbar, delta_star = symbols(r"s1 s2 \overline{r} \delta^*", real=True)
|
|
18
|
-
|
|
19
|
-
for _m_val in _m_vals:
|
|
20
|
-
s_m = round((dstar_val := _g_bar / (_r_bar * _m_val)) / (1 + dstar_val), 3)
|
|
21
|
-
|
|
22
|
-
# Own-share-weighted average GUPPI, "inside-out" recapture
|
|
23
|
-
s2_sol = solve( # type: ignore
|
|
24
|
-
s1 * s2 / (1 - s1)
|
|
25
|
-
+ s2 * s1 / (1 - s2 * _r_bar - s1 * (1 - _r_bar))
|
|
26
|
-
- (s1 + s2) * delta_star,
|
|
27
|
-
s2,
|
|
28
|
-
)
|
|
29
|
-
symplot( # type: ignore
|
|
30
|
-
s2_sol[0].subs({delta_star: dstar_val}),
|
|
31
|
-
(s1, 0, s_m),
|
|
32
|
-
ylabel=s2,
|
|
33
|
-
xlim=(0.0, 1.0),
|
|
34
|
-
ylim=(0.0, 1.0),
|
|
35
|
-
axis_center=(0.0, 0.0),
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
# Cross-product-share-weighted average GUPPI, proportional recapture
|
|
39
|
-
s2_sol = solve( # type: ignore
|
|
40
|
-
s2 * s2 / (1 - s1) + s1 * s1 / (1 - s2) - delta_star * (s1 + s2), s2
|
|
41
|
-
)
|
|
42
|
-
symplot( # type: ignore
|
|
43
|
-
s2_sol[1].subs({delta_star: dstar_val}),
|
|
44
|
-
(s1, 0, s_m),
|
|
45
|
-
ylabel=s2,
|
|
46
|
-
xlim=(0.0, 1.0),
|
|
47
|
-
ylim=(0.0, 1.0),
|
|
48
|
-
axis_center=(0.0, 0.0),
|
|
49
|
-
)
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
if __name__ == "__main__":
|
|
53
|
-
plot_safeharb_boundaries(0.06, 0.80, (1.00, 0.67, 0.30))
|
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
from datetime import datetime, timedelta
|
|
2
|
-
from itertools import product as iterprod
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
from typing import Literal
|
|
5
|
-
|
|
6
|
-
import numpy as np
|
|
7
|
-
|
|
8
|
-
import mergeron.core.guidelines_boundaries as gbl
|
|
9
|
-
import mergeron.gen.investigations_stats as isl
|
|
10
|
-
import mergeron.gen.upp_tests as utl
|
|
11
|
-
from mergeron import DATA_DIR, RECConstants, UPPAggrSelector
|
|
12
|
-
from mergeron.core.pseudorandom_numbers import DIST_PARMS_DEFAULT
|
|
13
|
-
from mergeron.gen import (
|
|
14
|
-
FM2Constants,
|
|
15
|
-
INVResolution,
|
|
16
|
-
MarketSampleSpec,
|
|
17
|
-
PCMConstants,
|
|
18
|
-
PCMSpec,
|
|
19
|
-
ShareSpec,
|
|
20
|
-
SHRConstants,
|
|
21
|
-
UPPTestRegime,
|
|
22
|
-
)
|
|
23
|
-
|
|
24
|
-
PROG_PATH = Path(__file__)
|
|
25
|
-
|
|
26
|
-
tests_of_interest: tuple[UPPTestRegime, ...] = (
|
|
27
|
-
UPPTestRegime(INVResolution.CLRN, UPPAggrSelector.MAX, UPPAggrSelector.MAX),
|
|
28
|
-
UPPTestRegime(INVResolution.ENFT, UPPAggrSelector.MIN, UPPAggrSelector.MIN),
|
|
29
|
-
)
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
def analyze_invres_data(
|
|
33
|
-
_sample_size: int = 10**6,
|
|
34
|
-
_hmg_pub_year: Literal[1992, 2010, 2023] = 1992,
|
|
35
|
-
_test_regime: UPPTestRegime = tests_of_interest[1],
|
|
36
|
-
/,
|
|
37
|
-
*,
|
|
38
|
-
save_data_to_file_flag: bool = False,
|
|
39
|
-
) -> None:
|
|
40
|
-
"""
|
|
41
|
-
Analyze intrinsic enforcement rates using a GUPPI criterion against
|
|
42
|
-
intrinsic enforcement rates by Guidelines ∆HHI standard
|
|
43
|
-
|
|
44
|
-
Parameters
|
|
45
|
-
----------
|
|
46
|
-
_sample_size
|
|
47
|
-
Number of draws (mergers) to analyze
|
|
48
|
-
|
|
49
|
-
_hmg_pub_year
|
|
50
|
-
Guidelines version for ∆HHI standard
|
|
51
|
-
|
|
52
|
-
_test_regime
|
|
53
|
-
Specifies analysis of enforcement rates or, alternatively, clearance rates
|
|
54
|
-
|
|
55
|
-
save_data_to_file_flag
|
|
56
|
-
If True, simulated data are save to file (hdf5 format)
|
|
57
|
-
|
|
58
|
-
"""
|
|
59
|
-
_invres_parm_vec = gbl.GuidelinesThresholds(_hmg_pub_year).presumption
|
|
60
|
-
|
|
61
|
-
_save_data_to_file: utl.SaveData = False
|
|
62
|
-
if save_data_to_file_flag:
|
|
63
|
-
_h5_path = DATA_DIR / PROG_PATH.with_suffix(".h5").name
|
|
64
|
-
(_, _h5_file, _h5_group), _h5_subgroup_name = utl.initialize_hd5( # type: ignore
|
|
65
|
-
_h5_path, _hmg_pub_year, _test_regime
|
|
66
|
-
) # type: ignore
|
|
67
|
-
|
|
68
|
-
_h5_group = _h5_file.create_group(
|
|
69
|
-
_h5_group, _h5_subgroup_name, f"{_invres_parm_vec}"
|
|
70
|
-
)
|
|
71
|
-
_save_data_to_file = (True, _h5_file, _h5_group)
|
|
72
|
-
|
|
73
|
-
# ##
|
|
74
|
-
# Print summaries of intrinsic clearance/enforcement rates by ∆HHI,
|
|
75
|
-
# with asymmetric margins
|
|
76
|
-
# ##
|
|
77
|
-
for _recapture_spec_test, _pcm_dist_test, _pcm_dist_firm2_test in iterprod(
|
|
78
|
-
(RECConstants.INOUT, RECConstants.FIXED),
|
|
79
|
-
[
|
|
80
|
-
tuple(
|
|
81
|
-
zip(
|
|
82
|
-
(PCMConstants.UNI, PCMConstants.BETA, PCMConstants.EMPR),
|
|
83
|
-
(
|
|
84
|
-
np.array((0, 1), dtype=np.float64),
|
|
85
|
-
np.array((10, 10), dtype=np.float64),
|
|
86
|
-
None,
|
|
87
|
-
),
|
|
88
|
-
strict=True,
|
|
89
|
-
)
|
|
90
|
-
)[_s]
|
|
91
|
-
for _s in [0, 2]
|
|
92
|
-
],
|
|
93
|
-
(FM2Constants.IID, FM2Constants.MNL),
|
|
94
|
-
):
|
|
95
|
-
if _recapture_spec_test == "proportional" and (
|
|
96
|
-
_pcm_dist_test[0] != "Uniform" or _pcm_dist_firm2_test == "MNL-dep"
|
|
97
|
-
):
|
|
98
|
-
continue
|
|
99
|
-
# When margins are specified as symmetric, then
|
|
100
|
-
# recapture_spec must be proportional and
|
|
101
|
-
# margins distributions must be iid;
|
|
102
|
-
|
|
103
|
-
_pcm_dist_type_test, _pcm_dist_parms_test = _pcm_dist_test
|
|
104
|
-
|
|
105
|
-
print()
|
|
106
|
-
print(
|
|
107
|
-
f"Simulated {_test_regime.resolution.capitalize()} rates by range of ∆HHI",
|
|
108
|
-
f'recapture-rate calibrated, "{_recapture_spec_test}"',
|
|
109
|
-
f'Firm 2 margins, "{_pcm_dist_firm2_test}"',
|
|
110
|
-
f"and margins distributed as, {_pcm_dist_type_test}{
|
|
111
|
-
_pcm_dist_parms_test if _pcm_dist_type_test.name == "BETA" else ""
|
|
112
|
-
}:",
|
|
113
|
-
sep="; ",
|
|
114
|
-
)
|
|
115
|
-
|
|
116
|
-
_mkt_sample_spec = MarketSampleSpec(
|
|
117
|
-
_sample_size,
|
|
118
|
-
_invres_parm_vec.rec,
|
|
119
|
-
share_spec=ShareSpec(
|
|
120
|
-
_recapture_spec_test, SHRConstants.UNI, DIST_PARMS_DEFAULT, None
|
|
121
|
-
),
|
|
122
|
-
pcm_spec=PCMSpec(
|
|
123
|
-
_pcm_dist_type_test, _pcm_dist_firm2_test, _pcm_dist_parms_test
|
|
124
|
-
),
|
|
125
|
-
)
|
|
126
|
-
|
|
127
|
-
if _save_data_to_file:
|
|
128
|
-
_h5_file.flush()
|
|
129
|
-
|
|
130
|
-
_h5_subgrp_name = "invres_rec{}_pcm{}_fm2res{}".format( # noqa: UP032
|
|
131
|
-
_recapture_spec_test.name,
|
|
132
|
-
_pcm_dist_type_test.name,
|
|
133
|
-
_pcm_dist_firm2_test.name,
|
|
134
|
-
)
|
|
135
|
-
|
|
136
|
-
_h5_subgroup = _h5_file.create_group(
|
|
137
|
-
_h5_group, _h5_subgrp_name, title=f"{_mkt_sample_spec}"
|
|
138
|
-
)
|
|
139
|
-
_save_data_to_file = (True, _h5_file, _h5_subgroup)
|
|
140
|
-
|
|
141
|
-
_invres_cnts_kwargs = utl.IVNRESCntsArgs(
|
|
142
|
-
sim_test_regime=_test_regime, save_data_to_file=_save_data_to_file
|
|
143
|
-
)
|
|
144
|
-
|
|
145
|
-
_start_time = datetime.now()
|
|
146
|
-
|
|
147
|
-
upp_test_counts = utl.sim_invres_cnts_ll(
|
|
148
|
-
_invres_parm_vec, _mkt_sample_spec, _invres_cnts_kwargs
|
|
149
|
-
)
|
|
150
|
-
_run_duration = datetime.now() - _start_time
|
|
151
|
-
print(
|
|
152
|
-
f"Simulation completed in {_run_duration / timedelta(seconds=1):.6f} secs.",
|
|
153
|
-
f"on {_mkt_sample_spec.sample_size:,d} draws",
|
|
154
|
-
sep=", ",
|
|
155
|
-
)
|
|
156
|
-
|
|
157
|
-
_stats_hdr_list, _stats_dat_list = isl.latex_tbl_invres_stats_1dim(
|
|
158
|
-
upp_test_counts.by_delta,
|
|
159
|
-
return_type_sel=isl.StatsReturnSelector.RPT,
|
|
160
|
-
sort_order=isl.SortSelector.REV,
|
|
161
|
-
)
|
|
162
|
-
_stats_teststr_val = "".join([
|
|
163
|
-
"{} & {} {}".format(
|
|
164
|
-
_stats_hdr_list[g],
|
|
165
|
-
" & ".join(_stats_dat_list[g][:-2]), # [:-2]
|
|
166
|
-
isl.LTX_ARRAY_LINEEND,
|
|
167
|
-
)
|
|
168
|
-
for g in range(len(_stats_hdr_list))
|
|
169
|
-
])
|
|
170
|
-
print(_stats_teststr_val)
|
|
171
|
-
del _stats_hdr_list, _stats_dat_list, _stats_teststr_val
|
|
172
|
-
del _pcm_dist_test, _pcm_dist_firm2_test, _recapture_spec_test
|
|
173
|
-
del _pcm_dist_type_test, _pcm_dist_parms_test
|
|
174
|
-
|
|
175
|
-
if _save_data_to_file:
|
|
176
|
-
_h5_file.flush()
|
|
177
|
-
_save_data_to_file[1].close() # type: ignore
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
if __name__ == "__main__":
|
|
181
|
-
analyze_invres_data(10**7, 2023, tests_of_interest[1], save_data_to_file_flag=False)
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Query FTC investigations data and display some basic statistics.
|
|
3
|
-
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
import numpy as np
|
|
7
|
-
|
|
8
|
-
import mergeron.core.ftc_merger_investigations_data as fid
|
|
9
|
-
|
|
10
|
-
invdata = fid.construct_data(fid.INVDATA_ARCHIVE_PATH)
|
|
11
|
-
|
|
12
|
-
for data_period in invdata:
|
|
13
|
-
print(data_period, "-->")
|
|
14
|
-
for table_type in (isd1 := invdata[data_period]):
|
|
15
|
-
leader_str = "\t"
|
|
16
|
-
print(leader_str, table_type, "-->")
|
|
17
|
-
leader_str += "\t"
|
|
18
|
-
for table_no in (isd11 := isd1[table_type]):
|
|
19
|
-
(invdata_ind_group, invdata_evid_cond, table_data_array) = isd11[table_no]
|
|
20
|
-
print(
|
|
21
|
-
leader_str,
|
|
22
|
-
table_no,
|
|
23
|
-
" \N{EM DASH} ",
|
|
24
|
-
invdata_ind_group,
|
|
25
|
-
f", {invdata_evid_cond or "N/A"}",
|
|
26
|
-
", ",
|
|
27
|
-
sep="",
|
|
28
|
-
end="",
|
|
29
|
-
)
|
|
30
|
-
print(
|
|
31
|
-
"Odds ratio = {}/{}".format(
|
|
32
|
-
*np.einsum("ij->j", table_data_array[:, -3:])
|
|
33
|
-
)
|
|
34
|
-
)
|
|
35
|
-
print("\n")
|
|
36
|
-
|
|
37
|
-
data_period, data_type, table_no = ("2004-2011", "HHI and Delta", "Table 3.3")
|
|
38
|
-
# data_period, data_type, table_no = "2004-2011", "Firm Count", "Table 4.1"
|
|
39
|
-
print(f"Investigations data, {data_period}, by {data_type}, {table_no}")
|
|
40
|
-
print(
|
|
41
|
-
"{}, {}\n{}".format(
|
|
42
|
-
*invdata[data_period][f"By{data_type.replace(" ", "")}"][table_no]
|
|
43
|
-
)
|
|
44
|
-
)
|