mergeron 2025.739290.7__tar.gz → 2025.739290.9__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.739290.9/PKG-INFO +178 -0
- mergeron-2025.739290.9/README.rst +136 -0
- {mergeron-2025.739290.7 → mergeron-2025.739290.9}/pyproject.toml +1 -1
- {mergeron-2025.739290.7 → mergeron-2025.739290.9}/src/mergeron/__init__.py +1 -1
- {mergeron-2025.739290.7 → mergeron-2025.739290.9}/src/mergeron/core/empirical_margin_distribution.py +6 -8
- {mergeron-2025.739290.7 → mergeron-2025.739290.9}/src/mergeron/core/ftc_merger_investigations_data.py +4 -4
- {mergeron-2025.739290.7 → mergeron-2025.739290.9}/src/mergeron/core/guidelines_boundary_functions.py +3 -3
- {mergeron-2025.739290.7 → mergeron-2025.739290.9}/src/mergeron/core/guidelines_boundary_functions_extra.py +1 -1
- {mergeron-2025.739290.7 → mergeron-2025.739290.9}/src/mergeron/gen/data_generation.py +2 -1
- {mergeron-2025.739290.7 → mergeron-2025.739290.9}/src/mergeron/gen/data_generation_functions.py +1 -1
- {mergeron-2025.739290.7 → mergeron-2025.739290.9}/src/mergeron/gen/enforcement_stats.py +4 -4
- mergeron-2025.739290.7/PKG-INFO +0 -115
- mergeron-2025.739290.7/README.rst +0 -73
- {mergeron-2025.739290.7 → mergeron-2025.739290.9}/src/mergeron/core/__init__.py +0 -0
- {mergeron-2025.739290.7 → mergeron-2025.739290.9}/src/mergeron/core/guidelines_boundaries.py +0 -0
- {mergeron-2025.739290.7 → mergeron-2025.739290.9}/src/mergeron/core/pseudorandom_numbers.py +0 -0
- {mergeron-2025.739290.7 → mergeron-2025.739290.9}/src/mergeron/data/__init__.py +0 -0
- {mergeron-2025.739290.7 → mergeron-2025.739290.9}/src/mergeron/data/damodaran_margin_data.xls +0 -0
- {mergeron-2025.739290.7 → mergeron-2025.739290.9}/src/mergeron/data/ftc_merger_investigations_data.zip +0 -0
- {mergeron-2025.739290.7 → mergeron-2025.739290.9}/src/mergeron/demo/__init__.py +0 -0
- {mergeron-2025.739290.7 → mergeron-2025.739290.9}/src/mergeron/demo/visualize_empirical_margin_distribution.py +0 -0
- {mergeron-2025.739290.7 → mergeron-2025.739290.9}/src/mergeron/gen/__init__.py +0 -0
- {mergeron-2025.739290.7 → mergeron-2025.739290.9}/src/mergeron/gen/upp_tests.py +0 -0
- {mergeron-2025.739290.7 → mergeron-2025.739290.9}/src/mergeron/py.typed +0 -0
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: mergeron
|
|
3
|
+
Version: 2025.739290.9
|
|
4
|
+
Summary: Analyze merger enforcement policy using Python
|
|
5
|
+
License: MIT
|
|
6
|
+
Keywords: merger policy analysis,merger guidelines,merger screening,policy presumptions,concentration standards,upward pricing pressure,GUPPI
|
|
7
|
+
Author: Murthy Kambhampaty
|
|
8
|
+
Author-email: smk@capeconomics.com
|
|
9
|
+
Requires-Python: >=3.12,<4.0
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
21
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
22
|
+
Requires-Dist: aenum (>=3.1.15,<4.0.0)
|
|
23
|
+
Requires-Dist: attrs (>=23.2)
|
|
24
|
+
Requires-Dist: bs4 (>=0.0.1)
|
|
25
|
+
Requires-Dist: certifi (>=2023.11.17)
|
|
26
|
+
Requires-Dist: h5py (>=3.13.0,<4.0.0)
|
|
27
|
+
Requires-Dist: jinja2 (>=3.1)
|
|
28
|
+
Requires-Dist: joblib (>=1.3)
|
|
29
|
+
Requires-Dist: matplotlib (>=3.8)
|
|
30
|
+
Requires-Dist: mpmath (>=1.3)
|
|
31
|
+
Requires-Dist: msgpack (>=1.0)
|
|
32
|
+
Requires-Dist: msgpack-numpy (>=0.4)
|
|
33
|
+
Requires-Dist: ruamel-yaml (>=0.18.10,<0.19.0)
|
|
34
|
+
Requires-Dist: scipy (>=1.12)
|
|
35
|
+
Requires-Dist: sympy (>=1.12)
|
|
36
|
+
Requires-Dist: types-beautifulsoup4 (>=4.11.2)
|
|
37
|
+
Requires-Dist: urllib3 (>=2.2.2,<3.0.0)
|
|
38
|
+
Requires-Dist: xlrd (>=2.0.1,<3.0.0)
|
|
39
|
+
Requires-Dist: xlsxwriter (>=3.1)
|
|
40
|
+
Description-Content-Type: text/x-rst
|
|
41
|
+
|
|
42
|
+
mergeron: Merger Policy Analysis with Python
|
|
43
|
+
============================================
|
|
44
|
+
|
|
45
|
+
Usage
|
|
46
|
+
-----
|
|
47
|
+
|
|
48
|
+
*Visualizing Guidelines boundaries*
|
|
49
|
+
|
|
50
|
+
.. code:: python
|
|
51
|
+
|
|
52
|
+
%matplotlib inline
|
|
53
|
+
from mergeron.core import guidelines_boundaries as gbl
|
|
54
|
+
from mergeron.core import guidelines_boundary_functions as gbf
|
|
55
|
+
from math import sqrt
|
|
56
|
+
|
|
57
|
+
delta_bound = 0.01
|
|
58
|
+
conc_boundary = gbl.ConcentrationBoundary(delta_bound, "ΔHHI")
|
|
59
|
+
share_boundary = gbl.ConcentrationBoundary(2 * sqrt(delta_bound / 2), "Combined share")
|
|
60
|
+
|
|
61
|
+
divr_boundary_a = gbl.DiversionRatioBoundary(
|
|
62
|
+
gbl.guppi_from_delta(delta_bound, m_star=1.0, r_bar=0.85),
|
|
63
|
+
agg_method=gbl.UPPAggrSelector.AVG
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
divr_boundary_i = gbl.DiversionRatioBoundary(
|
|
67
|
+
gbl.guppi_from_delta(delta_bound, m_star=1.0, r_bar=0.85),
|
|
68
|
+
agg_method=gbl.UPPAggrSelector.MIN
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
divr_boundary_x = gbl.DiversionRatioBoundary(
|
|
72
|
+
gbl.guppi_from_delta(delta_bound, m_star=1.0, r_bar=0.85),
|
|
73
|
+
agg_method=gbl.UPPAggrSelector.MAX
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
Plots are written to PDF, typically, with ``backend="pgf"`` as the
|
|
78
|
+
default backend in the function, ``gbf.boundary_plot``. Here, we set the
|
|
79
|
+
backend to ``None`` to skip fine-tuning plots for PDF generation.
|
|
80
|
+
|
|
81
|
+
.. code:: python
|
|
82
|
+
|
|
83
|
+
plt, fig, ax, layout_axis = gbf.boundary_plot(backend=None)
|
|
84
|
+
|
|
85
|
+
ax.set_title("Concentration and Diversion Ratio Boundaries")
|
|
86
|
+
|
|
87
|
+
ax.plot(conc_boundary.coordinates[:, 0], conc_boundary.coordinates[:, 1], color="black", linestyle="-", label="ΔHHI")
|
|
88
|
+
ax.plot(share_boundary.coordinates[:, 0], share_boundary.coordinates[:, 1], color="black", linestyle=":", label="Combined share")
|
|
89
|
+
ax.plot(divr_boundary_a.coordinates[:, 0], divr_boundary_a.coordinates[:, 1], "b-", label="Average Diversion Ratio")
|
|
90
|
+
ax.plot(divr_boundary_i.coordinates[:, 0], divr_boundary_i.coordinates[:, 1], "r-", label="Minimum Diversion Ratio")
|
|
91
|
+
ax.plot(divr_boundary_x.coordinates[:, 0], divr_boundary_x.coordinates[:, 1], "g-", label="Maximum Diversion Ratio")
|
|
92
|
+
|
|
93
|
+
_ = fig.legend(loc=(0.4, 0.7), frameon=False)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
.. image:: ./docs/readme_content/output_5_0.png
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
*Analyzing FTC Merger Investigations Data*
|
|
101
|
+
|
|
102
|
+
.. code:: python
|
|
103
|
+
|
|
104
|
+
from mergeron.core import ftc_merger_investigations_data as fid
|
|
105
|
+
import tabulate
|
|
106
|
+
|
|
107
|
+
inv_data = fid.construct_data(fid.INVDATA_ARCHIVE_PATH)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
We can now analyze counts of markets reported in the source data, by
|
|
111
|
+
table number. Note that odd-numbered tables report FTC investigations
|
|
112
|
+
data organized by HHI and ΔHHI, while even-numbered tables report by
|
|
113
|
+
firm-count.
|
|
114
|
+
|
|
115
|
+
.. code:: python
|
|
116
|
+
|
|
117
|
+
from mergeron.gen import enforcement_stats as esl
|
|
118
|
+
|
|
119
|
+
print("Enforcement Rates in Markets with Entry Barriers, 1996-2003 vs 2004-2011")
|
|
120
|
+
print()
|
|
121
|
+
counts_by_delta_1 = esl.enf_cnts_bydelta(
|
|
122
|
+
inv_data["1996-2003"]["ByHHIandDelta"]["Table 9.2"].data_array
|
|
123
|
+
)
|
|
124
|
+
counts_by_delta_2 = esl.enf_cnts_bydelta(
|
|
125
|
+
inv_data["2004-2011"]["ByHHIandDelta"]["Table 9.2"].data_array
|
|
126
|
+
)
|
|
127
|
+
observed_enforcement_rates = list(zip(
|
|
128
|
+
(
|
|
129
|
+
{_v: _k for _k, _v in fid.CONC_DELTA_DICT.items()}[i]
|
|
130
|
+
for i in counts_by_delta_1[:, 0]
|
|
131
|
+
),
|
|
132
|
+
(
|
|
133
|
+
f"{_a[1] / _a[-1]: <12.2%}" if _a[-1] else "--"
|
|
134
|
+
for _a in counts_by_delta_1
|
|
135
|
+
),
|
|
136
|
+
(
|
|
137
|
+
f"{_e[1] / _e[-1]: <12.2%}" if _e[-1] else "--"
|
|
138
|
+
for _e in counts_by_delta_2
|
|
139
|
+
),
|
|
140
|
+
))
|
|
141
|
+
|
|
142
|
+
observed_enforcement_rates.append([
|
|
143
|
+
"Total",
|
|
144
|
+
f"{counts_by_delta_1[:, 1].sum() / counts_by_delta_1[:, -1].sum(): <12.2%}",
|
|
145
|
+
f"{counts_by_delta_2[:, 1].sum() / counts_by_delta_2[:, -1].sum(): <12.2%}",
|
|
146
|
+
])
|
|
147
|
+
|
|
148
|
+
print(tabulate.tabulate(
|
|
149
|
+
observed_enforcement_rates,
|
|
150
|
+
tablefmt="simple",
|
|
151
|
+
headers=("ΔHHI", "1996-2003", "2004-2011"),
|
|
152
|
+
stralign="center",
|
|
153
|
+
maxcolwidths=36,
|
|
154
|
+
maxheadercolwidths=36,
|
|
155
|
+
))
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
.. parsed-literal::
|
|
159
|
+
|
|
160
|
+
Enforcement Rates in Markets with Entry Barriers, 1996-2003 vs 2004-2011
|
|
161
|
+
|
|
162
|
+
ΔHHI 1996-2003 2004-2011
|
|
163
|
+
------------- ----------- -----------
|
|
164
|
+
0 - 100 -- 100.00%
|
|
165
|
+
100 - 200 33.33% 50.00%
|
|
166
|
+
200 - 300 33.33% 50.00%
|
|
167
|
+
300 - 500 75.00% 77.78%
|
|
168
|
+
500 - 800 59.09% 54.55%
|
|
169
|
+
800 - 1,200 93.33% 81.82%
|
|
170
|
+
1,200 - 2,500 90.91% 84.38%
|
|
171
|
+
2,500 + 96.00% 100.00%
|
|
172
|
+
Total 81.65% 82.86%
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
Generating synthetic market data and analyzing enforcement rates
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
mergeron: Merger Policy Analysis with Python
|
|
2
|
+
============================================
|
|
3
|
+
|
|
4
|
+
Usage
|
|
5
|
+
-----
|
|
6
|
+
|
|
7
|
+
*Visualizing Guidelines boundaries*
|
|
8
|
+
|
|
9
|
+
.. code:: python
|
|
10
|
+
|
|
11
|
+
%matplotlib inline
|
|
12
|
+
from mergeron.core import guidelines_boundaries as gbl
|
|
13
|
+
from mergeron.core import guidelines_boundary_functions as gbf
|
|
14
|
+
from math import sqrt
|
|
15
|
+
|
|
16
|
+
delta_bound = 0.01
|
|
17
|
+
conc_boundary = gbl.ConcentrationBoundary(delta_bound, "ΔHHI")
|
|
18
|
+
share_boundary = gbl.ConcentrationBoundary(2 * sqrt(delta_bound / 2), "Combined share")
|
|
19
|
+
|
|
20
|
+
divr_boundary_a = gbl.DiversionRatioBoundary(
|
|
21
|
+
gbl.guppi_from_delta(delta_bound, m_star=1.0, r_bar=0.85),
|
|
22
|
+
agg_method=gbl.UPPAggrSelector.AVG
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
divr_boundary_i = gbl.DiversionRatioBoundary(
|
|
26
|
+
gbl.guppi_from_delta(delta_bound, m_star=1.0, r_bar=0.85),
|
|
27
|
+
agg_method=gbl.UPPAggrSelector.MIN
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
divr_boundary_x = gbl.DiversionRatioBoundary(
|
|
31
|
+
gbl.guppi_from_delta(delta_bound, m_star=1.0, r_bar=0.85),
|
|
32
|
+
agg_method=gbl.UPPAggrSelector.MAX
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
Plots are written to PDF, typically, with ``backend="pgf"`` as the
|
|
37
|
+
default backend in the function, ``gbf.boundary_plot``. Here, we set the
|
|
38
|
+
backend to ``None`` to skip fine-tuning plots for PDF generation.
|
|
39
|
+
|
|
40
|
+
.. code:: python
|
|
41
|
+
|
|
42
|
+
plt, fig, ax, layout_axis = gbf.boundary_plot(backend=None)
|
|
43
|
+
|
|
44
|
+
ax.set_title("Concentration and Diversion Ratio Boundaries")
|
|
45
|
+
|
|
46
|
+
ax.plot(conc_boundary.coordinates[:, 0], conc_boundary.coordinates[:, 1], color="black", linestyle="-", label="ΔHHI")
|
|
47
|
+
ax.plot(share_boundary.coordinates[:, 0], share_boundary.coordinates[:, 1], color="black", linestyle=":", label="Combined share")
|
|
48
|
+
ax.plot(divr_boundary_a.coordinates[:, 0], divr_boundary_a.coordinates[:, 1], "b-", label="Average Diversion Ratio")
|
|
49
|
+
ax.plot(divr_boundary_i.coordinates[:, 0], divr_boundary_i.coordinates[:, 1], "r-", label="Minimum Diversion Ratio")
|
|
50
|
+
ax.plot(divr_boundary_x.coordinates[:, 0], divr_boundary_x.coordinates[:, 1], "g-", label="Maximum Diversion Ratio")
|
|
51
|
+
|
|
52
|
+
_ = fig.legend(loc=(0.4, 0.7), frameon=False)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
.. image:: ./docs/readme_content/output_5_0.png
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
*Analyzing FTC Merger Investigations Data*
|
|
60
|
+
|
|
61
|
+
.. code:: python
|
|
62
|
+
|
|
63
|
+
from mergeron.core import ftc_merger_investigations_data as fid
|
|
64
|
+
import tabulate
|
|
65
|
+
|
|
66
|
+
inv_data = fid.construct_data(fid.INVDATA_ARCHIVE_PATH)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
We can now analyze counts of markets reported in the source data, by
|
|
70
|
+
table number. Note that odd-numbered tables report FTC investigations
|
|
71
|
+
data organized by HHI and ΔHHI, while even-numbered tables report by
|
|
72
|
+
firm-count.
|
|
73
|
+
|
|
74
|
+
.. code:: python
|
|
75
|
+
|
|
76
|
+
from mergeron.gen import enforcement_stats as esl
|
|
77
|
+
|
|
78
|
+
print("Enforcement Rates in Markets with Entry Barriers, 1996-2003 vs 2004-2011")
|
|
79
|
+
print()
|
|
80
|
+
counts_by_delta_1 = esl.enf_cnts_bydelta(
|
|
81
|
+
inv_data["1996-2003"]["ByHHIandDelta"]["Table 9.2"].data_array
|
|
82
|
+
)
|
|
83
|
+
counts_by_delta_2 = esl.enf_cnts_bydelta(
|
|
84
|
+
inv_data["2004-2011"]["ByHHIandDelta"]["Table 9.2"].data_array
|
|
85
|
+
)
|
|
86
|
+
observed_enforcement_rates = list(zip(
|
|
87
|
+
(
|
|
88
|
+
{_v: _k for _k, _v in fid.CONC_DELTA_DICT.items()}[i]
|
|
89
|
+
for i in counts_by_delta_1[:, 0]
|
|
90
|
+
),
|
|
91
|
+
(
|
|
92
|
+
f"{_a[1] / _a[-1]: <12.2%}" if _a[-1] else "--"
|
|
93
|
+
for _a in counts_by_delta_1
|
|
94
|
+
),
|
|
95
|
+
(
|
|
96
|
+
f"{_e[1] / _e[-1]: <12.2%}" if _e[-1] else "--"
|
|
97
|
+
for _e in counts_by_delta_2
|
|
98
|
+
),
|
|
99
|
+
))
|
|
100
|
+
|
|
101
|
+
observed_enforcement_rates.append([
|
|
102
|
+
"Total",
|
|
103
|
+
f"{counts_by_delta_1[:, 1].sum() / counts_by_delta_1[:, -1].sum(): <12.2%}",
|
|
104
|
+
f"{counts_by_delta_2[:, 1].sum() / counts_by_delta_2[:, -1].sum(): <12.2%}",
|
|
105
|
+
])
|
|
106
|
+
|
|
107
|
+
print(tabulate.tabulate(
|
|
108
|
+
observed_enforcement_rates,
|
|
109
|
+
tablefmt="simple",
|
|
110
|
+
headers=("ΔHHI", "1996-2003", "2004-2011"),
|
|
111
|
+
stralign="center",
|
|
112
|
+
maxcolwidths=36,
|
|
113
|
+
maxheadercolwidths=36,
|
|
114
|
+
))
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
.. parsed-literal::
|
|
118
|
+
|
|
119
|
+
Enforcement Rates in Markets with Entry Barriers, 1996-2003 vs 2004-2011
|
|
120
|
+
|
|
121
|
+
ΔHHI 1996-2003 2004-2011
|
|
122
|
+
------------- ----------- -----------
|
|
123
|
+
0 - 100 -- 100.00%
|
|
124
|
+
100 - 200 33.33% 50.00%
|
|
125
|
+
200 - 300 33.33% 50.00%
|
|
126
|
+
300 - 500 75.00% 77.78%
|
|
127
|
+
500 - 800 59.09% 54.55%
|
|
128
|
+
800 - 1,200 93.33% 81.82%
|
|
129
|
+
1,200 - 2,500 90.91% 84.38%
|
|
130
|
+
2,500 + 96.00% 100.00%
|
|
131
|
+
Total 81.65% 82.86%
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
Generating synthetic market data and analyzing enforcement rates
|
|
135
|
+
|
|
136
|
+
|
{mergeron-2025.739290.7 → mergeron-2025.739290.9}/src/mergeron/core/empirical_margin_distribution.py
RENAMED
|
@@ -238,7 +238,7 @@ def margin_data_resampler(
|
|
|
238
238
|
|
|
239
239
|
"""
|
|
240
240
|
|
|
241
|
-
|
|
241
|
+
_seed = seed_sequence or SeedSequence(pool_size=8)
|
|
242
242
|
|
|
243
243
|
_x, _w, _ = margin_data_builder(margin_data_getter())
|
|
244
244
|
|
|
@@ -247,16 +247,14 @@ def margin_data_resampler(
|
|
|
247
247
|
|
|
248
248
|
if isinstance(_sample_size, int):
|
|
249
249
|
return np.array(
|
|
250
|
-
margin_kde.resample(
|
|
251
|
-
_sample_size, seed=Generator(PCG64DXSM(seed_sequence_))
|
|
252
|
-
)[0]
|
|
250
|
+
margin_kde.resample(_sample_size, seed=Generator(PCG64DXSM(_seed)))[0]
|
|
253
251
|
)
|
|
254
252
|
elif isinstance(_sample_size, tuple) and len(_sample_size) == 2:
|
|
255
|
-
|
|
256
|
-
ret_array = np.empty(_sample_size,
|
|
257
|
-
for idx,
|
|
253
|
+
_ssz, _ncol = _sample_size
|
|
254
|
+
ret_array = np.empty(_sample_size, float)
|
|
255
|
+
for idx, _col_seed in enumerate(_seed.spawn(_ncol)):
|
|
258
256
|
ret_array[:, idx] = margin_kde.resample(
|
|
259
|
-
|
|
257
|
+
_ssz, seed=Generator(PCG64DXSM(_col_seed))
|
|
260
258
|
)[0]
|
|
261
259
|
return ret_array
|
|
262
260
|
else:
|
|
@@ -243,7 +243,7 @@ def _construct_no_evidence_data(_invdata: INVData_in, _data_period: str, /) -> N
|
|
|
243
243
|
dtn: INVTableData(
|
|
244
244
|
invdata_ind_grp,
|
|
245
245
|
invdata_evid_cond,
|
|
246
|
-
np.
|
|
246
|
+
np.hstack((
|
|
247
247
|
invdata_sub_evid_cond_conc[stn0].data_array[:, :2],
|
|
248
248
|
(
|
|
249
249
|
invdata_sub_evid_cond_conc[stn0].data_array[:, 2:]
|
|
@@ -377,10 +377,10 @@ def _construct_new_period_data(
|
|
|
377
377
|
np.zeros_like(invdata_array_bld_enfcls),
|
|
378
378
|
)).max(axis=0)
|
|
379
379
|
|
|
380
|
-
invdata_array_bld = np.
|
|
380
|
+
invdata_array_bld = np.hstack((
|
|
381
381
|
invdata_cuml_array[:, :-3],
|
|
382
382
|
invdata_array_bld_enfcls,
|
|
383
|
-
np.einsum("ij->i", invdata_array_bld_enfcls),
|
|
383
|
+
np.einsum("ij->i", invdata_array_bld_enfcls)[:, None],
|
|
384
384
|
))
|
|
385
385
|
|
|
386
386
|
data_typesubdict[table_no] = INVTableData(
|
|
@@ -401,7 +401,7 @@ def invdata_build_aggregate_table(
|
|
|
401
401
|
return INVTableData(
|
|
402
402
|
"Industries in Common",
|
|
403
403
|
"Unrestricted on additional evidence",
|
|
404
|
-
np.
|
|
404
|
+
np.hstack((
|
|
405
405
|
_data_typesub[hdr_table_no].data_array[:, :-3],
|
|
406
406
|
np.einsum(
|
|
407
407
|
"ijk->jk",
|
{mergeron-2025.739290.7 → mergeron-2025.739290.9}/src/mergeron/core/guidelines_boundary_functions.py
RENAMED
|
@@ -99,7 +99,7 @@ def hhi_delta_boundary(
|
|
|
99
99
|
|
|
100
100
|
# Boundary points
|
|
101
101
|
half_bdry = np.vstack((
|
|
102
|
-
np.
|
|
102
|
+
np.stack((_s_1, _delta_bound / (2 * _s_1)), axis=1).astype(float),
|
|
103
103
|
np.array([(mpf("0.0"), mpf("1.0"))], float),
|
|
104
104
|
))
|
|
105
105
|
bdry = np.vstack((half_bdry[::-1], half_bdry[1:, ::-1]), dtype=float)
|
|
@@ -132,7 +132,7 @@ def hhi_pre_contrib_boundary(
|
|
|
132
132
|
# Range-limit is 0 less a step, which is -1 * step-size
|
|
133
133
|
s_1 = np.array(mp.arange(_s_mid, -step_size, -step_size))
|
|
134
134
|
s_2 = np.sqrt(_hhi_bound - s_1**2)
|
|
135
|
-
half_bdry = np.
|
|
135
|
+
half_bdry = np.stack((s_1, s_2), axis=1).astype(float)
|
|
136
136
|
|
|
137
137
|
return GuidelinesBoundary(
|
|
138
138
|
np.vstack((half_bdry[::-1], half_bdry[1:, ::-1]), dtype=float),
|
|
@@ -536,7 +536,7 @@ def shrratio_boundary_xact_avg( # noqa: PLR0914
|
|
|
536
536
|
)
|
|
537
537
|
)
|
|
538
538
|
|
|
539
|
-
bdry_inner = np.
|
|
539
|
+
bdry_inner = np.stack((_s_1, s_2), axis=1)
|
|
540
540
|
bdry_end = np.array([(mpf("0.0"), _s_intcpt)], float)
|
|
541
541
|
|
|
542
542
|
bdry = np.vstack((
|
|
@@ -27,6 +27,7 @@ from ..core import guidelines_boundaries as gbl # noqa: TID252
|
|
|
27
27
|
from ..core.guidelines_boundaries import HMGThresholds # noqa: TID252
|
|
28
28
|
from . import (
|
|
29
29
|
FM2Constraint,
|
|
30
|
+
INVResolution, # noqa: F401
|
|
30
31
|
MarketSampleData,
|
|
31
32
|
PCMDistribution,
|
|
32
33
|
PCMSpec,
|
|
@@ -396,7 +397,7 @@ class MarketSample:
|
|
|
396
397
|
for _k in ("by_firm_count", "by_delta", "by_conczone")
|
|
397
398
|
])
|
|
398
399
|
upp_test_results = UPPTestsCounts(*[
|
|
399
|
-
np.
|
|
400
|
+
np.hstack((
|
|
400
401
|
(_gv := getattr(res_list_stacks, _g.name))[0, :, :_h],
|
|
401
402
|
np.einsum("ijk->jk", _gv[:, :, _h:], dtype=np.int64),
|
|
402
403
|
))
|
{mergeron-2025.739290.7 → mergeron-2025.739290.9}/src/mergeron/gen/data_generation_functions.py
RENAMED
|
@@ -722,7 +722,7 @@ def _gen_margin_data(
|
|
|
722
722
|
del beta_min, beta_max
|
|
723
723
|
|
|
724
724
|
if dist_firm2_pcm == FM2Constraint.SYM:
|
|
725
|
-
pcm_array = np.
|
|
725
|
+
pcm_array = np.hstack((pcm_array,) * _frmshr_array.shape[1])
|
|
726
726
|
if dist_firm2_pcm == FM2Constraint.MNL:
|
|
727
727
|
# Impose FOCs from profit-maximization with MNL demand
|
|
728
728
|
if dist_type_pcm == PCMDistribution.EMPR:
|
|
@@ -193,7 +193,7 @@ def enf_cnts_obs_byfirmcount(
|
|
|
193
193
|
case INVResolution.BOTH:
|
|
194
194
|
stats_kept_indxs = [-1, -3, -2]
|
|
195
195
|
|
|
196
|
-
return np.
|
|
196
|
+
return np.hstack([cnts_array[:, :ndim_in], cnts_array[:, stats_kept_indxs]])
|
|
197
197
|
|
|
198
198
|
|
|
199
199
|
def enf_cnts_obs_byhhianddelta(
|
|
@@ -226,7 +226,7 @@ def enf_cnts_obs_byhhianddelta(
|
|
|
226
226
|
case INVResolution.BOTH:
|
|
227
227
|
stats_kept_indxs = [-1, -3, -2]
|
|
228
228
|
|
|
229
|
-
return np.
|
|
229
|
+
return np.hstack([cnts_array[:, :ndim_in], cnts_array[:, stats_kept_indxs]])
|
|
230
230
|
|
|
231
231
|
|
|
232
232
|
def table_no_lku(
|
|
@@ -335,10 +335,10 @@ def enf_cnts_byconczone(_cnts_array: ArrayBIGINT, /) -> ArrayBIGINT:
|
|
|
335
335
|
# Logical-and of multiple vectors:
|
|
336
336
|
hhi_zone_test = (
|
|
337
337
|
1
|
|
338
|
-
* np.
|
|
338
|
+
* np.stack([
|
|
339
339
|
cnts_byhhipostanddelta[:, _idx] == _val
|
|
340
340
|
for _idx, _val in enumerate(zone_val)
|
|
341
|
-
])
|
|
341
|
+
], axis=1)
|
|
342
342
|
).prod(axis=1) == 1
|
|
343
343
|
|
|
344
344
|
cnts_byconczone = np.vstack((
|
mergeron-2025.739290.7/PKG-INFO
DELETED
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.3
|
|
2
|
-
Name: mergeron
|
|
3
|
-
Version: 2025.739290.7
|
|
4
|
-
Summary: Analyze merger enforcement policy using Python
|
|
5
|
-
License: MIT
|
|
6
|
-
Keywords: merger policy analysis,merger guidelines,merger screening,policy presumptions,concentration standards,upward pricing pressure,GUPPI
|
|
7
|
-
Author: Murthy Kambhampaty
|
|
8
|
-
Author-email: smk@capeconomics.com
|
|
9
|
-
Requires-Python: >=3.12,<4.0
|
|
10
|
-
Classifier: Development Status :: 4 - Beta
|
|
11
|
-
Classifier: Environment :: Console
|
|
12
|
-
Classifier: Intended Audience :: End Users/Desktop
|
|
13
|
-
Classifier: Intended Audience :: Science/Research
|
|
14
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
-
Classifier: Operating System :: OS Independent
|
|
16
|
-
Classifier: Programming Language :: Python
|
|
17
|
-
Classifier: Programming Language :: Python :: 3
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
-
Classifier: Programming Language :: Python :: 3 :: Only
|
|
21
|
-
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
22
|
-
Requires-Dist: aenum (>=3.1.15,<4.0.0)
|
|
23
|
-
Requires-Dist: attrs (>=23.2)
|
|
24
|
-
Requires-Dist: bs4 (>=0.0.1)
|
|
25
|
-
Requires-Dist: certifi (>=2023.11.17)
|
|
26
|
-
Requires-Dist: h5py (>=3.13.0,<4.0.0)
|
|
27
|
-
Requires-Dist: jinja2 (>=3.1)
|
|
28
|
-
Requires-Dist: joblib (>=1.3)
|
|
29
|
-
Requires-Dist: matplotlib (>=3.8)
|
|
30
|
-
Requires-Dist: mpmath (>=1.3)
|
|
31
|
-
Requires-Dist: msgpack (>=1.0)
|
|
32
|
-
Requires-Dist: msgpack-numpy (>=0.4)
|
|
33
|
-
Requires-Dist: ruamel-yaml (>=0.18.10,<0.19.0)
|
|
34
|
-
Requires-Dist: scipy (>=1.12)
|
|
35
|
-
Requires-Dist: sympy (>=1.12)
|
|
36
|
-
Requires-Dist: types-beautifulsoup4 (>=4.11.2)
|
|
37
|
-
Requires-Dist: urllib3 (>=2.2.2,<3.0.0)
|
|
38
|
-
Requires-Dist: xlrd (>=2.0.1,<3.0.0)
|
|
39
|
-
Requires-Dist: xlsxwriter (>=3.1)
|
|
40
|
-
Description-Content-Type: text/x-rst
|
|
41
|
-
|
|
42
|
-
mergeron: Merger Policy Analysis using Python
|
|
43
|
-
=============================================
|
|
44
|
-
|
|
45
|
-
Visualize the sets of mergers conforming to concentration and diversion-ratio standards. Estimate intrinsic enforcement rates, and intrinsic clearance rates, under concentration, diversion ratio, GUPPI, CMCR, and IPR bounds using generated data with specified distributions of market shares, price-cost margins, firm counts, and prices, optionally imposing restrictions implied by statutory filing thresholds and/or Bertrand-Nash oligopoly with MNL demand. Download and analyze merger investigations data published by the U.S. Federal Trade Commission in various reports on extended merger investigations (Second Requests) during 1996 to 2011.
|
|
46
|
-
|
|
47
|
-
Here, enforcement rates derived with merger enforcement as being exogenous to firm conduct are defined as intrinsic enforcement rates, and similarly intrinsic clearance rates. Depending on the merger enforcement regime, or merger control regime, intrinsic enforcement rates may also not be the complement of intrinsic clearance rates, i.e, it is not necessarily true that the intrinsic clearance rate estimate for a given enforcement regime is 1 minus the intrinsic enforcement rate. In contrast, observed enforcement rates reflect the deterrent effects of merger enforcement on firm conduct as well as the effects of merger screening on the level of enforcement; and, by definition, the observed clearance rate is 1 minus the observed enforcement rate.
|
|
48
|
-
|
|
49
|
-
Introduction
|
|
50
|
-
------------
|
|
51
|
-
|
|
52
|
-
Module :code:`.core.guidelines_boundaries` includes classes for specifying concentration bounds (:code:`.core.guidelines_boundaries.ConcentrationBoundary`) and diversion-ratio bounds (:code:`.core.guidelines_boundaries.DiversionRatioBoundary`), with automatic generation of boundary, as an array of share-pairs, and area. This module also includes a function for generating plots of concentration and diversion-ratio boundaries, and functions for mapping GUPPI standards to concentration (ΔHHI) standards, and vice-versa.
|
|
53
|
-
|
|
54
|
-
Module :code:`.gen.data_generation` includes the :code:`.gen.data_generation.MarketSample` which provides for a rich specification of shares and diversion ratios (:code:`.gen.data_generation.MarketSample.share_spec`), margins (:code:`.gen.data_generation.MarketSample.pcm_spec`, prices (:code:`.gen.data_generation.MarketSample.price_spec`), and HSR filing requirements (:code:`.gen.data_generation.MarketSample.hsr_filing_test_type`), and with methods for, (i) generating sample data (:code:`.gen.data_generation.MarketSample.generate_sample`), and (ii) computing the intrinsic enforcement rate and intrinsic clearance rate for the generated sample, given a method (:code:`.UPPAggrSelector`) of aggregating diversion ratio or GUPPI estimates for the firms in a merger (:code:`.gen.data_generation.MarketSample.estimate_enf_counts`). While the latter populate the properties, :code:`.gen.data_generation.MarketSample.data`
|
|
55
|
-
and :code:`.gen.data_generation.MarketSample.enf_counts`, respectively, the underlying methods for generating standalone :code:`MarketDataSample` and :code:`UPPTestCounts` objects are included in the class definition, with helper functions defined in the modules, :code:`.gen.data_generation_functions` and :code:`.gen.upp_tests`. Notably, market shares are generated for a sample of markets with firm-count distributed as specified in :code:`.gen.data_generation.MarketSample.share_spec.firm_count_weights`, with defaults as discussed below (also see, :code:`.gen.ShareSpec.firm_count_weights`.
|
|
56
|
-
|
|
57
|
-
By default, merging-firm shares are drawn with uniform distribution over the space :math:`s_1 + s_2 \leqslant 1` for an unspecified number of firms. Alternatively, shares may be drawn from the Dirichlet distribution (see property `dist_type` of :code:`.gen.data_generation.MarketSample.share_spec`, of type, :code:`.gen.SHRDistribution`), with specified shape parameters (property `dist_parms` of :code:`.gen.data_generation.MarketSample.share_spec`. When drawing shares from the Dirichlet distribution, the user specifies the `firm_count_weights` property of :code:`.gen.data_generation.MarketSample.share_spec`, as a vector of weights specifying the frequency distribution over sequential firm counts, e.g., :code:`[133, 184, 134, 52, 32, 10, 12, 4, 3]` to specify shares drawn from Dirichlet distributions with 2 to 10 pre-merger firms distributed as in data for FTC merger investigations during 1996--2003 (See, for example, Table 4.1 of `FTC, Horizontal Merger Investigations Data, Fiscal Years 1996--2003 (Revised: August 31, 2004) <https://www.ftc.gov/sites/default/files/documents/reports/horizontal-merger-investigation-data-fiscal-years-1996-2003/040831horizmergersdata96-03.pdf>`_). If the property `firm_count_weights` is not explicitly assigned a value when defining :code:`.gen.data_generation.MarketSample.share_spec`, the default values is used, which results in a sample of markets with 2 to 7 firms with relative frequency in inverse proportion to firm-count, with 2-firm markets being 6 times as likely to be drawn as 7-firm markets.
|
|
58
|
-
|
|
59
|
-
Recapture ratios can be specified as, "proportional", "inside-out", or "outside-in" (see :code:`.RECForm`). The "inside-out" specification (assigning :code:`.RECForm.INOUT` to the `recapture_form` property of :code:`.gen.data_generation.MarketSample.share_spec`) results in recapture ratios consistent with MNL demand, given merging-firms' in-market shares and a default recapture ratio. The "outside-in" specification (assigning :code:`.RECForm.INOUT` to the `recapture_form` property of :code:`.gen.data_generation.MarketSample.share_spec`) yields diversion ratios from purchase probabilities drawn at random for :math:`N+1` goods, with market shares and recapture ratios for the :math:`N` goods in the putative market (see, :code:`.gen.ShareSpec`) computed from the simulated choice probabilities. The "outside-in" specification requires specification of the distribution of markets over firm counts (the default being uniform distirbution over markets with 2 to 7 firms pre-merger), and Dirichlet-distributed shares, with optional parameters (the default being a "flat" Dirichlet distribution, i.e., one with all parameters being 1). The parameters of the Dirichlet distribution can, for example, be specified to increase (decrease) the probability of drawing mergers to monopoly relative to that probability associated with the Flat Dirichlet specification, by setting the first 2 specified parameters at higher (lower) values relative to the others. Lastly, the "proportional" form of recapture ratio (`recapture_form` = :code:`.RECForm.FIXED`) is often used in the literature, as an approximation to the "inside-out" calibration. See, for example, Coate (2011).
|
|
60
|
-
|
|
61
|
-
Price-cost-margins may be specified as having uniform distribution, Beta distribution (including a bounded Beta distribution with specified mean and variance), or a built-in empirical distribution (see, :code:`.gen.PCMSpec`). The in-built empirical margin distribution is based on resampling margin data published by Prof. Damodaran of NYU Stern School of Business (see Notes), using an estimated Gaussian KDE. The second merging firm's margin (per the property `firm2_pcm_constraint` of :code:`.gen.data_generation.MarketSample.pcm_spec`) may be specified as symmetric, i.i.d., or subject to equilibrium conditions for (profit-maximization in) Bertrand-Nash oligopoly with MNL demand (:code:`.gen.FM2Constraint`).
|
|
62
|
-
|
|
63
|
-
Prices may be specified as symmetric or asymmetric, and in the latter case, the direction of correlation between merging firm prices, if any, can also be specified (see, :code:`.gen.PriceSpec`). Prices may also be defined by imposing cost symmetry on firms in the sample, with fixed unit marginal costs normalized to 1 unit, such that prices equal :math:`1 / (1 - \pmb{m})`, where :math:`\pmb{m}` represents the array of margins for firms in the sample.
|
|
64
|
-
|
|
65
|
-
The market sample may be restricted to mergers meeting the HSR filing requirement under two alternative approaches: in the one, the smaller of the two merging firms meets the lower HSR size threshold ($10 million, as adjusted) and the larger of the two merging firms meets the size test if it's share is no less than 10 times the share of the smaller firm. In the other, the :math:`n`-th firm's size is maintained as $10 million, as adjusted (see, :code:`.gen.SSZConstant`), and a merger meets the HSR filing test if either, (a.) the smaller merging firm is no smaller than the n-th firm and the larger merging firm is at 10-times as large as the n-th firm, or (b.) the smaller merging firm's market share is in excess of 10%; in effect this version of the test maintains that if the smaller merging firm's market share exceeds 10%, the value of the transaction exceeds $200 million, as adjusted, and the size-of-person test is eliminated (see, FTC (2008, p. 12); the above are simplifications of the statutory HSR filing requirements). The second assumption avoids the unfortunate assumption in the first that, within the resulting sample, the larger merging firm be at least 10 times as large as the smaller merging firm, as a consequence of the full definition of the HSR filing requirement.
|
|
66
|
-
|
|
67
|
-
The full specification of a market sample is given in a :code:`.gen.data_generation.MarketSample` object, including the above parameters. Data are drawn by invoking :code:`.gen.data_generation.MarketSample.generate_sample` which adds a :code:`data` property of class, :code:`.gen.MarketDataSample`. Enforcement or clearance counts are computed by invoking :code:`.gen.data_generation.MarketSample.estimate_enf_counts`, which adds an :code:`enf_counts` property of class :code:`.gen.UPPTestsCounts`. For fast, parallel generation of enforcement or clearance counts over large market data samples that ordinarily would exceed available limits on machine memory, the user can invoke the method :code:`.gen.data_generation.MarketSample.estimate_enf_counts` on a :code:`.gen.data_generation.MarketSample` object without first invoking :code:`.gen.data_generation.MarketSample.generate_sample`. Note, however, that this strategy does not retain the market sample in memory in the interests of conserving memory and maintaining high performance (the user can specify that the market sample and enforcement statistics be stored to permanent storage; when saving to current PCIe NVMe storage, the performance penalty is slight, but can be considerable if saving to SATA storage).
|
|
68
|
-
|
|
69
|
-
Enforcement statistics based on FTC investigations data and test data are tabulated using methods provided in :code:`.gen.enforcement_stats`.
|
|
70
|
-
|
|
71
|
-
Programs demonstrating the use of this package are included in the sub-package, :code:`.demo`.
|
|
72
|
-
|
|
73
|
-
This package includes a class, :code:`.core.pseudorandom_numbers.MultithreadedRNG` for generating random numbers with selected continuous distribution over specified parameters, and with CPU multithreading on machines with multiple CPU cores, be they virtual, logical, or physical cores. This class is an adaptation from the documentation for the external :code:`numpy.random` subpackage, from the discussion on, "`Multithreaded generation <https://numpy.org/doc/stable/reference/random/multithreading.html>`_"; the version included here permits selection of the distribution with pre-tests to catch and inform on common errors. To access these directly:
|
|
74
|
-
|
|
75
|
-
.. code-block:: python
|
|
76
|
-
|
|
77
|
-
import mergeron.core.pseudorandom_numbers as prng
|
|
78
|
-
|
|
79
|
-
Documentation for this package is in the form of the API Reference. Documentation for individual functions and classes is accessible within a python shell. For example:
|
|
80
|
-
|
|
81
|
-
.. code-block:: python
|
|
82
|
-
|
|
83
|
-
import mergeron.core.data_generation as dgl
|
|
84
|
-
|
|
85
|
-
help(dgl.MarketSample)
|
|
86
|
-
|
|
87
|
-
.. rubric:: References
|
|
88
|
-
|
|
89
|
-
.. _coate2011:
|
|
90
|
-
|
|
91
|
-
Coate, M. B. (2011). Benchmarking the upward pricing pressure model with Federal Trade
|
|
92
|
-
Commission evidence. Journal of Competition Law & Economics, 7(4), 825--846. URL: https://doi.org/10.1093/joclec/nhr014.
|
|
93
|
-
|
|
94
|
-
.. _ftc_premerger_guide2:
|
|
95
|
-
|
|
96
|
-
FTC Premerger Notification Office. “To File or Not to File: When You Must File a Premerger Notification Report Form”. 2008 (September, revised). URL: https://www.ftc.gov/sites/default/files/attachments/premerger-introductory-guides/guide2.pdf
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
.. image:: https://img.shields.io/endpoint?url=https://python-poetry.org/badge/v0.json
|
|
100
|
-
:alt: Poetry
|
|
101
|
-
:target: https://python-poetry.org/
|
|
102
|
-
|
|
103
|
-
.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json
|
|
104
|
-
:alt: Ruff
|
|
105
|
-
:target: https://github.com/astral-sh/ruff/
|
|
106
|
-
|
|
107
|
-
.. image:: https://www.mypy-lang.org/static/mypy_badge.svg
|
|
108
|
-
:alt: Checked with mypy
|
|
109
|
-
:target: https://mypy-lang.org/
|
|
110
|
-
|
|
111
|
-
.. image:: https://img.shields.io/badge/License-MIT-yellow.svg
|
|
112
|
-
:alt: License: MIT
|
|
113
|
-
:target: https://opensource.org/licenses/MIT/
|
|
114
|
-
|
|
115
|
-
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
mergeron: Merger Policy Analysis using Python
|
|
2
|
-
=============================================
|
|
3
|
-
|
|
4
|
-
Visualize the sets of mergers conforming to concentration and diversion-ratio standards. Estimate intrinsic enforcement rates, and intrinsic clearance rates, under concentration, diversion ratio, GUPPI, CMCR, and IPR bounds using generated data with specified distributions of market shares, price-cost margins, firm counts, and prices, optionally imposing restrictions implied by statutory filing thresholds and/or Bertrand-Nash oligopoly with MNL demand. Download and analyze merger investigations data published by the U.S. Federal Trade Commission in various reports on extended merger investigations (Second Requests) during 1996 to 2011.
|
|
5
|
-
|
|
6
|
-
Here, enforcement rates derived with merger enforcement as being exogenous to firm conduct are defined as intrinsic enforcement rates, and similarly intrinsic clearance rates. Depending on the merger enforcement regime, or merger control regime, intrinsic enforcement rates may also not be the complement of intrinsic clearance rates, i.e, it is not necessarily true that the intrinsic clearance rate estimate for a given enforcement regime is 1 minus the intrinsic enforcement rate. In contrast, observed enforcement rates reflect the deterrent effects of merger enforcement on firm conduct as well as the effects of merger screening on the level of enforcement; and, by definition, the observed clearance rate is 1 minus the observed enforcement rate.
|
|
7
|
-
|
|
8
|
-
Introduction
|
|
9
|
-
------------
|
|
10
|
-
|
|
11
|
-
Module :code:`.core.guidelines_boundaries` includes classes for specifying concentration bounds (:code:`.core.guidelines_boundaries.ConcentrationBoundary`) and diversion-ratio bounds (:code:`.core.guidelines_boundaries.DiversionRatioBoundary`), with automatic generation of boundary, as an array of share-pairs, and area. This module also includes a function for generating plots of concentration and diversion-ratio boundaries, and functions for mapping GUPPI standards to concentration (ΔHHI) standards, and vice-versa.
|
|
12
|
-
|
|
13
|
-
Module :code:`.gen.data_generation` includes the :code:`.gen.data_generation.MarketSample` which provides for a rich specification of shares and diversion ratios (:code:`.gen.data_generation.MarketSample.share_spec`), margins (:code:`.gen.data_generation.MarketSample.pcm_spec`, prices (:code:`.gen.data_generation.MarketSample.price_spec`), and HSR filing requirements (:code:`.gen.data_generation.MarketSample.hsr_filing_test_type`), and with methods for, (i) generating sample data (:code:`.gen.data_generation.MarketSample.generate_sample`), and (ii) computing the intrinsic enforcement rate and intrinsic clearance rate for the generated sample, given a method (:code:`.UPPAggrSelector`) of aggregating diversion ratio or GUPPI estimates for the firms in a merger (:code:`.gen.data_generation.MarketSample.estimate_enf_counts`). While the latter populate the properties, :code:`.gen.data_generation.MarketSample.data`
|
|
14
|
-
and :code:`.gen.data_generation.MarketSample.enf_counts`, respectively, the underlying methods for generating standalone :code:`MarketDataSample` and :code:`UPPTestCounts` objects are included in the class definition, with helper functions defined in the modules, :code:`.gen.data_generation_functions` and :code:`.gen.upp_tests`. Notably, market shares are generated for a sample of markets with firm-count distributed as specified in :code:`.gen.data_generation.MarketSample.share_spec.firm_count_weights`, with defaults as discussed below (also see, :code:`.gen.ShareSpec.firm_count_weights`.
|
|
15
|
-
|
|
16
|
-
By default, merging-firm shares are drawn with uniform distribution over the space :math:`s_1 + s_2 \leqslant 1` for an unspecified number of firms. Alternatively, shares may be drawn from the Dirichlet distribution (see property `dist_type` of :code:`.gen.data_generation.MarketSample.share_spec`, of type, :code:`.gen.SHRDistribution`), with specified shape parameters (property `dist_parms` of :code:`.gen.data_generation.MarketSample.share_spec`. When drawing shares from the Dirichlet distribution, the user specifies the `firm_count_weights` property of :code:`.gen.data_generation.MarketSample.share_spec`, as a vector of weights specifying the frequency distribution over sequential firm counts, e.g., :code:`[133, 184, 134, 52, 32, 10, 12, 4, 3]` to specify shares drawn from Dirichlet distributions with 2 to 10 pre-merger firms distributed as in data for FTC merger investigations during 1996--2003 (See, for example, Table 4.1 of `FTC, Horizontal Merger Investigations Data, Fiscal Years 1996--2003 (Revised: August 31, 2004) <https://www.ftc.gov/sites/default/files/documents/reports/horizontal-merger-investigation-data-fiscal-years-1996-2003/040831horizmergersdata96-03.pdf>`_). If the property `firm_count_weights` is not explicitly assigned a value when defining :code:`.gen.data_generation.MarketSample.share_spec`, the default values is used, which results in a sample of markets with 2 to 7 firms with relative frequency in inverse proportion to firm-count, with 2-firm markets being 6 times as likely to be drawn as 7-firm markets.
|
|
17
|
-
|
|
18
|
-
Recapture ratios can be specified as, "proportional", "inside-out", or "outside-in" (see :code:`.RECForm`). The "inside-out" specification (assigning :code:`.RECForm.INOUT` to the `recapture_form` property of :code:`.gen.data_generation.MarketSample.share_spec`) results in recapture ratios consistent with MNL demand, given merging-firms' in-market shares and a default recapture ratio. The "outside-in" specification (assigning :code:`.RECForm.INOUT` to the `recapture_form` property of :code:`.gen.data_generation.MarketSample.share_spec`) yields diversion ratios from purchase probabilities drawn at random for :math:`N+1` goods, with market shares and recapture ratios for the :math:`N` goods in the putative market (see, :code:`.gen.ShareSpec`) computed from the simulated choice probabilities. The "outside-in" specification requires specification of the distribution of markets over firm counts (the default being uniform distirbution over markets with 2 to 7 firms pre-merger), and Dirichlet-distributed shares, with optional parameters (the default being a "flat" Dirichlet distribution, i.e., one with all parameters being 1). The parameters of the Dirichlet distribution can, for example, be specified to increase (decrease) the probability of drawing mergers to monopoly relative to that probability associated with the Flat Dirichlet specification, by setting the first 2 specified parameters at higher (lower) values relative to the others. Lastly, the "proportional" form of recapture ratio (`recapture_form` = :code:`.RECForm.FIXED`) is often used in the literature, as an approximation to the "inside-out" calibration. See, for example, Coate (2011).
|
|
19
|
-
|
|
20
|
-
Price-cost-margins may be specified as having uniform distribution, Beta distribution (including a bounded Beta distribution with specified mean and variance), or a built-in empirical distribution (see, :code:`.gen.PCMSpec`). The in-built empirical margin distribution is based on resampling margin data published by Prof. Damodaran of NYU Stern School of Business (see Notes), using an estimated Gaussian KDE. The second merging firm's margin (per the property `firm2_pcm_constraint` of :code:`.gen.data_generation.MarketSample.pcm_spec`) may be specified as symmetric, i.i.d., or subject to equilibrium conditions for (profit-maximization in) Bertrand-Nash oligopoly with MNL demand (:code:`.gen.FM2Constraint`).
|
|
21
|
-
|
|
22
|
-
Prices may be specified as symmetric or asymmetric, and in the latter case, the direction of correlation between merging firm prices, if any, can also be specified (see, :code:`.gen.PriceSpec`). Prices may also be defined by imposing cost symmetry on firms in the sample, with fixed unit marginal costs normalized to 1 unit, such that prices equal :math:`1 / (1 - \pmb{m})`, where :math:`\pmb{m}` represents the array of margins for firms in the sample.
|
|
23
|
-
|
|
24
|
-
The market sample may be restricted to mergers meeting the HSR filing requirement under two alternative approaches: in the one, the smaller of the two merging firms meets the lower HSR size threshold ($10 million, as adjusted) and the larger of the two merging firms meets the size test if it's share is no less than 10 times the share of the smaller firm. In the other, the :math:`n`-th firm's size is maintained as $10 million, as adjusted (see, :code:`.gen.SSZConstant`), and a merger meets the HSR filing test if either, (a.) the smaller merging firm is no smaller than the n-th firm and the larger merging firm is at 10-times as large as the n-th firm, or (b.) the smaller merging firm's market share is in excess of 10%; in effect this version of the test maintains that if the smaller merging firm's market share exceeds 10%, the value of the transaction exceeds $200 million, as adjusted, and the size-of-person test is eliminated (see, FTC (2008, p. 12); the above are simplifications of the statutory HSR filing requirements). The second assumption avoids the unfortunate assumption in the first that, within the resulting sample, the larger merging firm be at least 10 times as large as the smaller merging firm, as a consequence of the full definition of the HSR filing requirement.
|
|
25
|
-
|
|
26
|
-
The full specification of a market sample is given in a :code:`.gen.data_generation.MarketSample` object, including the above parameters. Data are drawn by invoking :code:`.gen.data_generation.MarketSample.generate_sample` which adds a :code:`data` property of class, :code:`.gen.MarketDataSample`. Enforcement or clearance counts are computed by invoking :code:`.gen.data_generation.MarketSample.estimate_enf_counts`, which adds an :code:`enf_counts` property of class :code:`.gen.UPPTestsCounts`. For fast, parallel generation of enforcement or clearance counts over large market data samples that ordinarily would exceed available limits on machine memory, the user can invoke the method :code:`.gen.data_generation.MarketSample.estimate_enf_counts` on a :code:`.gen.data_generation.MarketSample` object without first invoking :code:`.gen.data_generation.MarketSample.generate_sample`. Note, however, that this strategy does not retain the market sample in memory in the interests of conserving memory and maintaining high performance (the user can specify that the market sample and enforcement statistics be stored to permanent storage; when saving to current PCIe NVMe storage, the performance penalty is slight, but can be considerable if saving to SATA storage).
|
|
27
|
-
|
|
28
|
-
Enforcement statistics based on FTC investigations data and test data are tabulated using methods provided in :code:`.gen.enforcement_stats`.
|
|
29
|
-
|
|
30
|
-
Programs demonstrating the use of this package are included in the sub-package, :code:`.demo`.
|
|
31
|
-
|
|
32
|
-
This package includes a class, :code:`.core.pseudorandom_numbers.MultithreadedRNG` for generating random numbers with selected continuous distribution over specified parameters, and with CPU multithreading on machines with multiple CPU cores, be they virtual, logical, or physical cores. This class is an adaptation from the documentation for the external :code:`numpy.random` subpackage, from the discussion on, "`Multithreaded generation <https://numpy.org/doc/stable/reference/random/multithreading.html>`_"; the version included here permits selection of the distribution with pre-tests to catch and inform on common errors. To access these directly:
|
|
33
|
-
|
|
34
|
-
.. code-block:: python
|
|
35
|
-
|
|
36
|
-
import mergeron.core.pseudorandom_numbers as prng
|
|
37
|
-
|
|
38
|
-
Documentation for this package is in the form of the API Reference. Documentation for individual functions and classes is accessible within a python shell. For example:
|
|
39
|
-
|
|
40
|
-
.. code-block:: python
|
|
41
|
-
|
|
42
|
-
import mergeron.core.data_generation as dgl
|
|
43
|
-
|
|
44
|
-
help(dgl.MarketSample)
|
|
45
|
-
|
|
46
|
-
.. rubric:: References
|
|
47
|
-
|
|
48
|
-
.. _coate2011:
|
|
49
|
-
|
|
50
|
-
Coate, M. B. (2011). Benchmarking the upward pricing pressure model with Federal Trade
|
|
51
|
-
Commission evidence. Journal of Competition Law & Economics, 7(4), 825--846. URL: https://doi.org/10.1093/joclec/nhr014.
|
|
52
|
-
|
|
53
|
-
.. _ftc_premerger_guide2:
|
|
54
|
-
|
|
55
|
-
FTC Premerger Notification Office. “To File or Not to File: When You Must File a Premerger Notification Report Form”. 2008 (September, revised). URL: https://www.ftc.gov/sites/default/files/attachments/premerger-introductory-guides/guide2.pdf
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
.. image:: https://img.shields.io/endpoint?url=https://python-poetry.org/badge/v0.json
|
|
59
|
-
:alt: Poetry
|
|
60
|
-
:target: https://python-poetry.org/
|
|
61
|
-
|
|
62
|
-
.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json
|
|
63
|
-
:alt: Ruff
|
|
64
|
-
:target: https://github.com/astral-sh/ruff/
|
|
65
|
-
|
|
66
|
-
.. image:: https://www.mypy-lang.org/static/mypy_badge.svg
|
|
67
|
-
:alt: Checked with mypy
|
|
68
|
-
:target: https://mypy-lang.org/
|
|
69
|
-
|
|
70
|
-
.. image:: https://img.shields.io/badge/License-MIT-yellow.svg
|
|
71
|
-
:alt: License: MIT
|
|
72
|
-
:target: https://opensource.org/licenses/MIT/
|
|
73
|
-
|
|
File without changes
|
{mergeron-2025.739290.7 → mergeron-2025.739290.9}/src/mergeron/core/guidelines_boundaries.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mergeron-2025.739290.7 → mergeron-2025.739290.9}/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
|
|
File without changes
|