mergeron 2024.738963.0__tar.gz → 2024.738973.0__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-2024.738963.0 → mergeron-2024.738973.0}/PKG-INFO +1 -1
- {mergeron-2024.738963.0 → mergeron-2024.738973.0}/pyproject.toml +1 -1
- {mergeron-2024.738963.0 → mergeron-2024.738973.0}/src/mergeron/core/__init__.py +18 -8
- mergeron-2024.738973.0/src/mergeron/core/guidelines_boundaries.py +439 -0
- mergeron-2024.738963.0/src/mergeron/core/guidelines_boundaries.py → mergeron-2024.738973.0/src/mergeron/core/guidelines_boundary_functions.py +592 -1015
- mergeron-2024.738963.0/src/mergeron/core/guidelines_boundaries_specialized_functions.py → mergeron-2024.738973.0/src/mergeron/core/guidelines_boundary_functions_extra.py +48 -9
- {mergeron-2024.738963.0 → mergeron-2024.738973.0}/src/mergeron/gen/__init__.py +20 -37
- mergeron-2024.738963.0/src/mergeron/gen/_data_generation_functions_nonpublic.py → mergeron-2024.738973.0/src/mergeron/gen/_data_generation_functions.py +77 -19
- {mergeron-2024.738963.0 → mergeron-2024.738973.0}/src/mergeron/gen/data_generation.py +17 -14
- mergeron-2024.738973.0/src/mergeron/gen/market_sample.py +79 -0
- {mergeron-2024.738963.0 → mergeron-2024.738973.0}/src/mergeron/gen/upp_tests.py +99 -66
- {mergeron-2024.738963.0 → mergeron-2024.738973.0}/README.rst +0 -0
- {mergeron-2024.738963.0 → mergeron-2024.738973.0}/src/mergeron/License.txt +0 -0
- {mergeron-2024.738963.0 → mergeron-2024.738973.0}/src/mergeron/__init__.py +0 -0
- {mergeron-2024.738963.0 → mergeron-2024.738973.0}/src/mergeron/core/InCommon RSA Server CA cert chain.pem +0 -0
- {mergeron-2024.738963.0 → mergeron-2024.738973.0}/src/mergeron/core/damodaran_margin_data.py +0 -0
- {mergeron-2024.738963.0 → mergeron-2024.738973.0}/src/mergeron/core/excel_helper.py +0 -0
- {mergeron-2024.738963.0 → mergeron-2024.738973.0}/src/mergeron/core/ftc_invdata.msgpack +0 -0
- {mergeron-2024.738963.0 → mergeron-2024.738973.0}/src/mergeron/core/ftc_merger_investigations_data.py +0 -0
- {mergeron-2024.738963.0 → mergeron-2024.738973.0}/src/mergeron/core/proportions_tests.py +0 -0
- {mergeron-2024.738963.0 → mergeron-2024.738973.0}/src/mergeron/core/pseudorandom_numbers.py +0 -0
- {mergeron-2024.738963.0 → mergeron-2024.738973.0}/src/mergeron/ext/__init__.py +0 -0
- {mergeron-2024.738963.0 → mergeron-2024.738973.0}/src/mergeron/ext/tol_colors.py +0 -0
- {mergeron-2024.738963.0 → mergeron-2024.738973.0}/src/mergeron/gen/investigations_stats.py +0 -0
- {mergeron-2024.738963.0 → mergeron-2024.738973.0}/src/mergeron/jinja_LaTex_templates/clrrate_cis_summary_table_template.tex.jinja2 +0 -0
- {mergeron-2024.738963.0 → mergeron-2024.738973.0}/src/mergeron/jinja_LaTex_templates/ftcinvdata_byhhianddelta_table_template.tex.jinja2 +0 -0
- {mergeron-2024.738963.0 → mergeron-2024.738973.0}/src/mergeron/jinja_LaTex_templates/ftcinvdata_summary_table_template.tex.jinja2 +0 -0
- {mergeron-2024.738963.0 → mergeron-2024.738973.0}/src/mergeron/jinja_LaTex_templates/ftcinvdata_summarypaired_table_template.tex.jinja2 +0 -0
- {mergeron-2024.738963.0 → mergeron-2024.738973.0}/src/mergeron/jinja_LaTex_templates/mergeron.cls +0 -0
- {mergeron-2024.738963.0 → mergeron-2024.738973.0}/src/mergeron/jinja_LaTex_templates/mergeron_table_collection_template.tex.jinja2 +0 -0
- {mergeron-2024.738963.0 → mergeron-2024.738973.0}/src/mergeron/jinja_LaTex_templates/setup_tikz_tables.tex.jinja2 +0 -0
- {mergeron-2024.738963.0 → mergeron-2024.738973.0}/src/mergeron/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: mergeron
|
|
3
|
-
Version: 2024.
|
|
3
|
+
Version: 2024.738973.0
|
|
4
4
|
Summary: Analysis of standards defined in Horizontal Merger Guidelines
|
|
5
5
|
License: MIT
|
|
6
6
|
Keywords: merger policy analysis,merger guidelines,merger screening,policy presumptions,concentration standards,upward pricing pressure,GUPPI
|
|
@@ -1,15 +1,24 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
from dataclasses import dataclass
|
|
3
4
|
from importlib.metadata import version
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
import numpy as np
|
|
7
|
+
from attrs import Attribute, field, frozen, validators
|
|
8
|
+
from numpy.typing import NDArray
|
|
6
9
|
|
|
7
10
|
from .. import _PKG_NAME, RECConstants, UPPAggrSelector # noqa: TID252
|
|
8
11
|
|
|
9
12
|
__version__ = version(_PKG_NAME)
|
|
10
13
|
|
|
11
14
|
|
|
12
|
-
|
|
15
|
+
@dataclass(frozen=True)
|
|
16
|
+
class GuidelinesBoundary:
|
|
17
|
+
coordinates: NDArray[np.float64]
|
|
18
|
+
area: float
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _divr_value_validator(
|
|
13
22
|
_instance: UPPBoundarySpec, _attribute: Attribute[float], _value: float, /
|
|
14
23
|
) -> None:
|
|
15
24
|
if not 0 <= _value <= 1:
|
|
@@ -38,15 +47,15 @@ def _rec_spec_validator(
|
|
|
38
47
|
)
|
|
39
48
|
|
|
40
49
|
|
|
41
|
-
@
|
|
50
|
+
@frozen
|
|
42
51
|
class UPPBoundarySpec:
|
|
43
|
-
|
|
52
|
+
diversion_ratio: float = field(
|
|
44
53
|
kw_only=False,
|
|
45
|
-
default=0.
|
|
46
|
-
validator=(validators.instance_of(float),
|
|
54
|
+
default=0.045,
|
|
55
|
+
validator=(validators.instance_of(float), _divr_value_validator),
|
|
47
56
|
)
|
|
48
57
|
rec: float = field(
|
|
49
|
-
kw_only=False, default=0.
|
|
58
|
+
kw_only=False, default=0.855, validator=validators.instance_of(float)
|
|
50
59
|
)
|
|
51
60
|
|
|
52
61
|
agg_method: UPPAggrSelector = field(
|
|
@@ -54,11 +63,12 @@ class UPPBoundarySpec:
|
|
|
54
63
|
default=UPPAggrSelector.MAX,
|
|
55
64
|
validator=validators.instance_of(UPPAggrSelector),
|
|
56
65
|
)
|
|
66
|
+
|
|
57
67
|
recapture_form: RECConstants | None = field(
|
|
58
68
|
kw_only=True,
|
|
59
69
|
default=RECConstants.INOUT,
|
|
60
70
|
validator=(
|
|
61
|
-
validators.
|
|
71
|
+
validators.instance_of((type(None), RECConstants)),
|
|
62
72
|
_rec_spec_validator,
|
|
63
73
|
),
|
|
64
74
|
)
|
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Methods for defining and analyzing boundaries for Guidelines standards,
|
|
3
|
+
with a canvas on which to draw boundaries for Guidelines standards.
|
|
4
|
+
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
from importlib.metadata import version
|
|
9
|
+
from typing import Literal, TypeAlias
|
|
10
|
+
|
|
11
|
+
import numpy as np
|
|
12
|
+
from attrs import field, frozen
|
|
13
|
+
from mpmath import mp, mpf # type: ignore
|
|
14
|
+
|
|
15
|
+
from .. import _PKG_NAME, UPPAggrSelector # noqa: TID252
|
|
16
|
+
from . import GuidelinesBoundary, UPPBoundarySpec
|
|
17
|
+
from .guidelines_boundary_functions import (
|
|
18
|
+
dh_area,
|
|
19
|
+
round_cust,
|
|
20
|
+
shrratio_boundary_max,
|
|
21
|
+
shrratio_boundary_min,
|
|
22
|
+
shrratio_boundary_wtd_avg,
|
|
23
|
+
shrratio_boundary_xact_avg,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
__version__ = version(_PKG_NAME)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
mp.prec = 80
|
|
30
|
+
mp.trap_complex = True
|
|
31
|
+
|
|
32
|
+
HMGPubYear: TypeAlias = Literal[1992, 2004, 2010, 2023]
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@dataclass(frozen=True)
|
|
36
|
+
class HMGThresholds:
|
|
37
|
+
delta: float
|
|
38
|
+
fc: float
|
|
39
|
+
rec: float
|
|
40
|
+
guppi: float
|
|
41
|
+
divr: float
|
|
42
|
+
cmcr: float
|
|
43
|
+
ipr: float
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@frozen
|
|
47
|
+
class GuidelinesThresholds:
|
|
48
|
+
"""
|
|
49
|
+
Guidelines threholds by Guidelines publication year
|
|
50
|
+
|
|
51
|
+
ΔHHI, Recapture Rate, GUPPI, Diversion ratio, CMCR, and IPR thresholds
|
|
52
|
+
constructed from concentration standards in Guidelines published in
|
|
53
|
+
1992, 2004, 2010, and 2023.
|
|
54
|
+
|
|
55
|
+
The 2004 Guidelines refernced here are the EU Commission
|
|
56
|
+
guidelines on assessment of horizontal mergers. These
|
|
57
|
+
guidelines also define a presumption for mergers with
|
|
58
|
+
post-merger HHI in [1000, 2000) and ΔHHI >= 250 points,
|
|
59
|
+
whi is not modeled here.
|
|
60
|
+
|
|
61
|
+
All other Guidelines modeled here are U.S. merger guidelines.
|
|
62
|
+
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
pub_year: HMGPubYear
|
|
66
|
+
"""
|
|
67
|
+
Year of publication of the Guidelines
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
safeharbor: HMGThresholds = field(kw_only=True, default=None)
|
|
71
|
+
"""
|
|
72
|
+
Negative presumption quantified on various measures
|
|
73
|
+
|
|
74
|
+
ΔHHI safeharbor bound, default recapture rate, GUPPI bound,
|
|
75
|
+
diversion ratio limit, CMCR, and IPR
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
imputed_presumption: HMGThresholds = field(kw_only=True, default=None)
|
|
79
|
+
"""
|
|
80
|
+
Presumption of harm imputed from guidelines
|
|
81
|
+
|
|
82
|
+
ΔHHI bound inferred from strict numbers-equivalent
|
|
83
|
+
of (post-merger) HHI presumption, and corresponding default recapture rate,
|
|
84
|
+
GUPPI bound, diversion ratio limit, CMCR, and IPR
|
|
85
|
+
"""
|
|
86
|
+
|
|
87
|
+
presumption: HMGThresholds = field(kw_only=True, default=None)
|
|
88
|
+
"""
|
|
89
|
+
Presumption of harm defined in HMG
|
|
90
|
+
|
|
91
|
+
ΔHHI bound and corresponding default recapture rate, GUPPI bound,
|
|
92
|
+
diversion ratio limit, CMCR, and IPR
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
def __attrs_post_init__(self, /) -> None:
|
|
96
|
+
# In the 2023 Guidlines, the agencies do not define a
|
|
97
|
+
# negative presumption, or safeharbor. Practically speaking,
|
|
98
|
+
# given resource constraints and loss aversion, it is likely
|
|
99
|
+
# that staff only investigates mergers that meet the presumption;
|
|
100
|
+
# thus, here, the tentative delta safeharbor under
|
|
101
|
+
# the 2023 Guidelines is 100 points
|
|
102
|
+
_hhi_p, _dh_s, _dh_p = {
|
|
103
|
+
1992: (0.18, 0.005, 0.01),
|
|
104
|
+
2010: (0.25, 0.01, 0.02),
|
|
105
|
+
2004: (0.20, 0.015, 0.015),
|
|
106
|
+
2023: (0.18, 0.01, 0.01),
|
|
107
|
+
}[self.pub_year]
|
|
108
|
+
|
|
109
|
+
object.__setattr__(
|
|
110
|
+
self,
|
|
111
|
+
"safeharbor",
|
|
112
|
+
HMGThresholds(
|
|
113
|
+
_dh_s,
|
|
114
|
+
_fc := int(np.ceil(1 / _hhi_p)),
|
|
115
|
+
_r := round_cust(_fc / (_fc + 1)),
|
|
116
|
+
_g_s := guppi_from_delta(_dh_s, m_star=1.0, r_bar=_r),
|
|
117
|
+
_dr := round_cust(1 / (_fc + 1)),
|
|
118
|
+
_cmcr := 0.03, # Not strictly a Guidelines standard
|
|
119
|
+
_ipr := _g_s, # Not strictly a Guidelines standard
|
|
120
|
+
),
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
# imputed_presumption is relevant for 2010 Guidelines
|
|
124
|
+
object.__setattr__(
|
|
125
|
+
self,
|
|
126
|
+
"imputed_presumption",
|
|
127
|
+
(
|
|
128
|
+
HMGThresholds(
|
|
129
|
+
_dh_i := 2 * (0.5 / _fc) ** 2,
|
|
130
|
+
_fc,
|
|
131
|
+
_r_i := round_cust((_fc - 1 / 2) / (_fc + 1 / 2)),
|
|
132
|
+
_g_i := guppi_from_delta(_dh_i, m_star=1.0, r_bar=_r_i),
|
|
133
|
+
round_cust((1 / 2) / (_fc + 1 / 2)),
|
|
134
|
+
_cmcr,
|
|
135
|
+
_g_i,
|
|
136
|
+
)
|
|
137
|
+
if self.pub_year == 2010
|
|
138
|
+
else HMGThresholds(
|
|
139
|
+
_dh_i := 2 * (1 / (_fc + 1)) ** 2,
|
|
140
|
+
_fc,
|
|
141
|
+
_r,
|
|
142
|
+
_g_i := guppi_from_delta(_dh_i, m_star=1.0, r_bar=_r),
|
|
143
|
+
_dr,
|
|
144
|
+
_cmcr,
|
|
145
|
+
_g_i,
|
|
146
|
+
)
|
|
147
|
+
),
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
object.__setattr__(
|
|
151
|
+
self,
|
|
152
|
+
"presumption",
|
|
153
|
+
HMGThresholds(
|
|
154
|
+
_dh_p,
|
|
155
|
+
_fc,
|
|
156
|
+
_r,
|
|
157
|
+
_g_p := guppi_from_delta(_dh_p, m_star=1.0, r_bar=_r),
|
|
158
|
+
_dr,
|
|
159
|
+
_cmcr,
|
|
160
|
+
_ipr := _g_p,
|
|
161
|
+
),
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def guppi_from_delta(
|
|
166
|
+
_delta_bound: float = 0.01, /, *, m_star: float = 1.00, r_bar: float = 0.855
|
|
167
|
+
) -> float:
|
|
168
|
+
"""
|
|
169
|
+
Translate ∆HHI bound to GUPPI bound.
|
|
170
|
+
|
|
171
|
+
Parameters
|
|
172
|
+
----------
|
|
173
|
+
_deltasf
|
|
174
|
+
Specified ∆HHI bound.
|
|
175
|
+
m_star
|
|
176
|
+
Parametric price-cost margin.
|
|
177
|
+
r_bar
|
|
178
|
+
Default recapture rate.
|
|
179
|
+
|
|
180
|
+
Returns
|
|
181
|
+
-------
|
|
182
|
+
GUPPI bound corresponding to ∆HHI bound, at given margin and recapture rate.
|
|
183
|
+
|
|
184
|
+
"""
|
|
185
|
+
return round_cust(
|
|
186
|
+
m_star * r_bar * (_s_m := np.sqrt(_delta_bound / 2)) / (1 - _s_m),
|
|
187
|
+
frac=0.005,
|
|
188
|
+
rounding_mode="ROUND_HALF_DOWN",
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def critical_share_ratio(
|
|
193
|
+
_guppi_bound: float = 0.075,
|
|
194
|
+
/,
|
|
195
|
+
*,
|
|
196
|
+
m_star: float = 1.00,
|
|
197
|
+
r_bar: float = 1.00,
|
|
198
|
+
frac: float = 1e-16,
|
|
199
|
+
) -> mpf:
|
|
200
|
+
"""
|
|
201
|
+
Corollary to GUPPI bound.
|
|
202
|
+
|
|
203
|
+
Parameters
|
|
204
|
+
----------
|
|
205
|
+
_guppi_bound
|
|
206
|
+
Specified GUPPI bound.
|
|
207
|
+
m_star
|
|
208
|
+
Parametric price-cost margin.
|
|
209
|
+
r_bar
|
|
210
|
+
Default recapture rate.
|
|
211
|
+
|
|
212
|
+
Returns
|
|
213
|
+
-------
|
|
214
|
+
Critical share ratio (share ratio bound) corresponding to the GUPPI bound
|
|
215
|
+
for given margin and recapture rate.
|
|
216
|
+
|
|
217
|
+
"""
|
|
218
|
+
return round_cust(
|
|
219
|
+
mpf(f"{_guppi_bound}") / mp.fmul(f"{m_star}", f"{r_bar}"), frac=frac
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def share_from_guppi(
|
|
224
|
+
_guppi_bound: float = 0.065, /, *, m_star: float = 1.00, r_bar: float = 0.855
|
|
225
|
+
) -> float:
|
|
226
|
+
"""
|
|
227
|
+
Symmetric-firm share for given GUPPI, margin, and recapture rate.
|
|
228
|
+
|
|
229
|
+
Parameters
|
|
230
|
+
----------
|
|
231
|
+
_guppi_bound
|
|
232
|
+
GUPPI bound.
|
|
233
|
+
m_star
|
|
234
|
+
Parametric price-cost margin.
|
|
235
|
+
r_bar
|
|
236
|
+
Default recapture rate.
|
|
237
|
+
|
|
238
|
+
Returns
|
|
239
|
+
-------
|
|
240
|
+
float
|
|
241
|
+
Symmetric firm market share on GUPPI boundary, for given margin and
|
|
242
|
+
recapture rate.
|
|
243
|
+
|
|
244
|
+
"""
|
|
245
|
+
|
|
246
|
+
return round_cust(
|
|
247
|
+
(_d0 := critical_share_ratio(_guppi_bound, m_star=m_star, r_bar=r_bar))
|
|
248
|
+
/ (1 + _d0)
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
def hhi_delta_boundary(
|
|
253
|
+
_dh_val: float = 0.01, /, *, prec: int = 5
|
|
254
|
+
) -> GuidelinesBoundary:
|
|
255
|
+
"""
|
|
256
|
+
Generate the list of share combination on the ΔHHI boundary.
|
|
257
|
+
|
|
258
|
+
Parameters
|
|
259
|
+
----------
|
|
260
|
+
_dh_val:
|
|
261
|
+
Merging-firms' ΔHHI bound.
|
|
262
|
+
prec
|
|
263
|
+
Number of decimal places for rounding reported shares.
|
|
264
|
+
|
|
265
|
+
Returns
|
|
266
|
+
-------
|
|
267
|
+
Array of share-pairs, area under boundary.
|
|
268
|
+
|
|
269
|
+
"""
|
|
270
|
+
|
|
271
|
+
_dh_val = mpf(f"{_dh_val}")
|
|
272
|
+
_s_naught = 1 / 2 * (1 - mp.sqrt(1 - 2 * _dh_val))
|
|
273
|
+
_s_mid = mp.sqrt(_dh_val / 2)
|
|
274
|
+
|
|
275
|
+
_dh_step_sz = mp.power(10, -6)
|
|
276
|
+
_s_1 = np.array(mp.arange(_s_mid, _s_naught - mp.eps, -_dh_step_sz))
|
|
277
|
+
_s_2 = _dh_val / (2 * _s_1)
|
|
278
|
+
|
|
279
|
+
# Boundary points
|
|
280
|
+
_dh_half = np.row_stack((
|
|
281
|
+
np.column_stack((_s_1, _s_2)),
|
|
282
|
+
np.array([(mpf("0.0"), mpf("1.0"))]),
|
|
283
|
+
))
|
|
284
|
+
_dh_bdry_pts = np.row_stack((np.flip(_dh_half, 0), np.flip(_dh_half[1:], 1)))
|
|
285
|
+
|
|
286
|
+
_s_1_pts, _s_2_pts = np.split(_dh_bdry_pts, 2, axis=1)
|
|
287
|
+
return GuidelinesBoundary(
|
|
288
|
+
np.column_stack((
|
|
289
|
+
np.array(_s_1_pts, np.float64),
|
|
290
|
+
np.array(_s_2_pts, np.float64),
|
|
291
|
+
)),
|
|
292
|
+
dh_area(_dh_val, prec=prec),
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
def combined_share_boundary(
|
|
297
|
+
_s_intcpt: float = 0.0625, /, *, bdry_dps: int = 10
|
|
298
|
+
) -> GuidelinesBoundary:
|
|
299
|
+
"""
|
|
300
|
+
Share combinations on the merging-firms' combined share boundary.
|
|
301
|
+
|
|
302
|
+
Assumes symmetric merging-firm margins. The combined-share is
|
|
303
|
+
congruent to the post-merger HHI contribution boundary, as the
|
|
304
|
+
post-merger HHI bound is the square of the combined-share bound.
|
|
305
|
+
|
|
306
|
+
Parameters
|
|
307
|
+
----------
|
|
308
|
+
_s_intcpt:
|
|
309
|
+
Merging-firms' combined share.
|
|
310
|
+
bdry_dps
|
|
311
|
+
Number of decimal places for rounding reported shares.
|
|
312
|
+
|
|
313
|
+
Returns
|
|
314
|
+
-------
|
|
315
|
+
Array of share-pairs, area under boundary.
|
|
316
|
+
|
|
317
|
+
"""
|
|
318
|
+
_s_intcpt = mpf(f"{_s_intcpt}")
|
|
319
|
+
_s_mid = _s_intcpt / 2
|
|
320
|
+
|
|
321
|
+
_s1_pts = (0, _s_mid, _s_intcpt)
|
|
322
|
+
return GuidelinesBoundary(
|
|
323
|
+
np.column_stack((
|
|
324
|
+
np.array(_s1_pts, np.float64),
|
|
325
|
+
np.array(_s1_pts[::-1], np.float64),
|
|
326
|
+
)),
|
|
327
|
+
round(float(_s_intcpt * _s_mid), bdry_dps),
|
|
328
|
+
)
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
def hhi_pre_contrib_boundary(
|
|
332
|
+
_hhi_contrib: float = 0.03125, /, *, bdry_dps: int = 5
|
|
333
|
+
) -> GuidelinesBoundary:
|
|
334
|
+
"""
|
|
335
|
+
Share combinations on the premerger HHI contribution boundary.
|
|
336
|
+
|
|
337
|
+
Parameters
|
|
338
|
+
----------
|
|
339
|
+
_hhi_contrib:
|
|
340
|
+
Merging-firms' pre-merger HHI contribution bound.
|
|
341
|
+
bdry_dps
|
|
342
|
+
Number of decimal places for rounding reported shares.
|
|
343
|
+
|
|
344
|
+
Returns
|
|
345
|
+
-------
|
|
346
|
+
Array of share-pairs, area under boundary.
|
|
347
|
+
|
|
348
|
+
"""
|
|
349
|
+
_hhi_contrib = mpf(f"{_hhi_contrib}")
|
|
350
|
+
_s_mid = mp.sqrt(_hhi_contrib / 2)
|
|
351
|
+
|
|
352
|
+
_bdry_step_sz = mp.power(10, -bdry_dps)
|
|
353
|
+
# Range-limit is 0 less a step, which is -1 * step-size
|
|
354
|
+
_s_1 = np.array(mp.arange(_s_mid, -_bdry_step_sz, -_bdry_step_sz), np.float64)
|
|
355
|
+
_s_2 = np.sqrt(_hhi_contrib - _s_1**2).astype(np.float64)
|
|
356
|
+
_bdry_pts_mid = np.column_stack((_s_1, _s_2))
|
|
357
|
+
return GuidelinesBoundary(
|
|
358
|
+
np.row_stack((np.flip(_bdry_pts_mid, 0), np.flip(_bdry_pts_mid[1:], 1))),
|
|
359
|
+
round(float(mp.pi * _hhi_contrib / 4), bdry_dps),
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
def hhi_post_contrib_boundary(
|
|
364
|
+
_hhi_contrib: float = 0.800, /, *, bdry_dps: int = 10
|
|
365
|
+
) -> GuidelinesBoundary:
|
|
366
|
+
"""
|
|
367
|
+
Share combinations on the postmerger HHI contribution boundary.
|
|
368
|
+
|
|
369
|
+
The post-merger HHI contribution boundary is identical to the
|
|
370
|
+
combined-share boundary.
|
|
371
|
+
|
|
372
|
+
Parameters
|
|
373
|
+
----------
|
|
374
|
+
_hhi_contrib:
|
|
375
|
+
Merging-firms' pre-merger HHI contribution bound.
|
|
376
|
+
bdry_dps
|
|
377
|
+
Number of decimal places for rounding reported shares.
|
|
378
|
+
|
|
379
|
+
Returns
|
|
380
|
+
-------
|
|
381
|
+
Array of share-pairs, area under boundary.
|
|
382
|
+
|
|
383
|
+
"""
|
|
384
|
+
return combined_share_boundary(np.sqrt(_hhi_contrib), bdry_dps=bdry_dps)
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
def diversion_ratio_boundary(_bdry_spec: UPPBoundarySpec) -> GuidelinesBoundary:
|
|
388
|
+
_share_ratio = critical_share_ratio(
|
|
389
|
+
_bdry_spec.diversion_ratio, r_bar=_bdry_spec.rec
|
|
390
|
+
)
|
|
391
|
+
match _bdry_spec.agg_method:
|
|
392
|
+
case UPPAggrSelector.AVG:
|
|
393
|
+
return shrratio_boundary_xact_avg(
|
|
394
|
+
_share_ratio,
|
|
395
|
+
_bdry_spec.rec,
|
|
396
|
+
recapture_form=_bdry_spec.recapture_form.value, # type: ignore
|
|
397
|
+
prec=_bdry_spec.precision,
|
|
398
|
+
)
|
|
399
|
+
case UPPAggrSelector.MAX:
|
|
400
|
+
return shrratio_boundary_max(
|
|
401
|
+
_share_ratio, _bdry_spec.rec, prec=_bdry_spec.precision
|
|
402
|
+
)
|
|
403
|
+
case UPPAggrSelector.MIN:
|
|
404
|
+
return shrratio_boundary_min(
|
|
405
|
+
_share_ratio,
|
|
406
|
+
_bdry_spec.rec,
|
|
407
|
+
recapture_form=_bdry_spec.recapture_form.value, # type: ignore
|
|
408
|
+
prec=_bdry_spec.precision,
|
|
409
|
+
)
|
|
410
|
+
case UPPAggrSelector.DIS:
|
|
411
|
+
return shrratio_boundary_wtd_avg(
|
|
412
|
+
_share_ratio,
|
|
413
|
+
_bdry_spec.rec,
|
|
414
|
+
agg_method="distance",
|
|
415
|
+
weighting=None,
|
|
416
|
+
recapture_form=_bdry_spec.recapture_form.value, # type: ignore
|
|
417
|
+
prec=_bdry_spec.precision,
|
|
418
|
+
)
|
|
419
|
+
case _:
|
|
420
|
+
_weighting = (
|
|
421
|
+
"cross-product-share"
|
|
422
|
+
if _bdry_spec.agg_method.value.startswith("cross-product-share")
|
|
423
|
+
else "own-share"
|
|
424
|
+
)
|
|
425
|
+
|
|
426
|
+
_agg_method = (
|
|
427
|
+
"arithmetic"
|
|
428
|
+
if _bdry_spec.agg_method.value.endswith("average")
|
|
429
|
+
else "distance"
|
|
430
|
+
)
|
|
431
|
+
|
|
432
|
+
return shrratio_boundary_wtd_avg(
|
|
433
|
+
_share_ratio,
|
|
434
|
+
_bdry_spec.rec,
|
|
435
|
+
agg_method=_agg_method, # type: ignore
|
|
436
|
+
weighting=_weighting, # type: ignore
|
|
437
|
+
recapture_form=_bdry_spec.recapture_form.value, # type: ignore
|
|
438
|
+
prec=_bdry_spec.precision,
|
|
439
|
+
)
|