mergeron 2025.739290.1__tar.gz → 2025.739290.3__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.1 → mergeron-2025.739290.3}/PKG-INFO +1 -1
- {mergeron-2025.739290.1 → mergeron-2025.739290.3}/pyproject.toml +1 -1
- {mergeron-2025.739290.1 → mergeron-2025.739290.3}/src/mergeron/__init__.py +1 -1
- {mergeron-2025.739290.1 → mergeron-2025.739290.3}/src/mergeron/core/ftc_merger_investigations_data.py +28 -5
- {mergeron-2025.739290.1 → mergeron-2025.739290.3}/src/mergeron/core/guidelines_boundaries.py +15 -0
- {mergeron-2025.739290.1 → mergeron-2025.739290.3}/src/mergeron/gen/__init__.py +18 -1
- {mergeron-2025.739290.1 → mergeron-2025.739290.3}/src/mergeron/gen/data_generation_functions.py +18 -19
- {mergeron-2025.739290.1 → mergeron-2025.739290.3}/README.rst +0 -0
- {mergeron-2025.739290.1 → mergeron-2025.739290.3}/src/mergeron/core/__init__.py +0 -0
- {mergeron-2025.739290.1 → mergeron-2025.739290.3}/src/mergeron/core/empirical_margin_distribution.py +0 -0
- {mergeron-2025.739290.1 → mergeron-2025.739290.3}/src/mergeron/core/guidelines_boundary_functions.py +0 -0
- {mergeron-2025.739290.1 → mergeron-2025.739290.3}/src/mergeron/core/guidelines_boundary_functions_extra.py +0 -0
- {mergeron-2025.739290.1 → mergeron-2025.739290.3}/src/mergeron/core/pseudorandom_numbers.py +0 -0
- {mergeron-2025.739290.1 → mergeron-2025.739290.3}/src/mergeron/data/__init__.py +0 -0
- {mergeron-2025.739290.1 → mergeron-2025.739290.3}/src/mergeron/data/damodaran_margin_data.xls +0 -0
- {mergeron-2025.739290.1 → mergeron-2025.739290.3}/src/mergeron/data/damodaran_margin_data_dict.msgpack +0 -0
- {mergeron-2025.739290.1 → mergeron-2025.739290.3}/src/mergeron/data/ftc_invdata.msgpack +0 -0
- {mergeron-2025.739290.1 → mergeron-2025.739290.3}/src/mergeron/demo/__init__.py +0 -0
- {mergeron-2025.739290.1 → mergeron-2025.739290.3}/src/mergeron/demo/visualize_empirical_margin_distribution.py +0 -0
- {mergeron-2025.739290.1 → mergeron-2025.739290.3}/src/mergeron/gen/data_generation.py +0 -0
- {mergeron-2025.739290.1 → mergeron-2025.739290.3}/src/mergeron/gen/enforcement_stats.py +0 -0
- {mergeron-2025.739290.1 → mergeron-2025.739290.3}/src/mergeron/gen/upp_tests.py +0 -0
- {mergeron-2025.739290.1 → mergeron-2025.739290.3}/src/mergeron/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: mergeron
|
|
3
|
-
Version: 2025.739290.
|
|
3
|
+
Version: 2025.739290.3
|
|
4
4
|
Summary: Analyze merger enforcement policy using Python
|
|
5
5
|
License: MIT
|
|
6
6
|
Keywords: merger policy analysis,merger guidelines,merger screening,policy presumptions,concentration standards,upward pricing pressure,GUPPI
|
|
@@ -8,13 +8,16 @@ Reported row and column totals from source data are not stored.
|
|
|
8
8
|
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
11
13
|
import shutil
|
|
12
14
|
from collections.abc import Mapping, Sequence
|
|
15
|
+
from dataclasses import dataclass
|
|
13
16
|
from importlib import resources
|
|
14
17
|
from operator import itemgetter
|
|
15
18
|
from pathlib import Path
|
|
16
19
|
from types import MappingProxyType
|
|
17
|
-
from typing import Any
|
|
20
|
+
from typing import Any
|
|
18
21
|
|
|
19
22
|
import msgpack # type: ignore
|
|
20
23
|
import msgpack_numpy as m # type: ignore
|
|
@@ -23,8 +26,9 @@ import re2 as re # type: ignore
|
|
|
23
26
|
import urllib3
|
|
24
27
|
from bs4 import BeautifulSoup
|
|
25
28
|
from numpy.testing import assert_array_equal
|
|
29
|
+
from ruamel import yaml
|
|
26
30
|
|
|
27
|
-
from .. import _PKG_NAME, DATA_DIR, VERSION, ArrayBIGINT # noqa: TID252
|
|
31
|
+
from .. import _PKG_NAME, DATA_DIR, EMPTY_ARRAYINT, VERSION, ArrayBIGINT # noqa: TID252
|
|
28
32
|
|
|
29
33
|
__version__ = VERSION
|
|
30
34
|
|
|
@@ -89,11 +93,27 @@ CNT_FCOUNT_DICT = {
|
|
|
89
93
|
}
|
|
90
94
|
|
|
91
95
|
|
|
92
|
-
|
|
96
|
+
@dataclass(slots=True, frozen=True)
|
|
97
|
+
class INVTableData:
|
|
93
98
|
industry_group: str
|
|
94
99
|
additional_evidence: str
|
|
95
100
|
data_array: ArrayBIGINT
|
|
96
101
|
|
|
102
|
+
@classmethod
|
|
103
|
+
def to_yaml(
|
|
104
|
+
cls, _r: yaml.representer.SafeRepresenter, _d: INVTableData
|
|
105
|
+
) -> yaml.MappingNode:
|
|
106
|
+
_ret: yaml.MappingNode = _r.represent_mapping(
|
|
107
|
+
f"!{cls.__name__}", {_a: getattr(_d, _a) for _a in _d.__dataclass_fields__}
|
|
108
|
+
)
|
|
109
|
+
return _ret
|
|
110
|
+
|
|
111
|
+
@classmethod
|
|
112
|
+
def from_yaml(
|
|
113
|
+
cls, _c: yaml.constructor.SafeConstructor, _n: yaml.MappingNode
|
|
114
|
+
) -> INVTableData:
|
|
115
|
+
return cls(**_c.construct_mapping(_n))
|
|
116
|
+
|
|
97
117
|
|
|
98
118
|
type INVData = Mapping[str, Mapping[str, Mapping[str, INVTableData]]]
|
|
99
119
|
type _INVData_in = dict[str, dict[str, dict[str, INVTableData]]]
|
|
@@ -278,10 +298,13 @@ def _construct_new_period_data(
|
|
|
278
298
|
_invdata_cuml_sub_table.data_array,
|
|
279
299
|
)
|
|
280
300
|
|
|
281
|
-
_invdata_base_sub_table = _invdata_base[_table_type].get(
|
|
301
|
+
_invdata_base_sub_table = _invdata_base[_table_type].get(
|
|
302
|
+
_table_no, INVTableData("", "", EMPTY_ARRAYINT)
|
|
303
|
+
)
|
|
282
304
|
|
|
283
305
|
(_invdata_base_ind_group, _invdata_base_evid_cond, _invdata_base_array) = (
|
|
284
|
-
_invdata_base_sub_table
|
|
306
|
+
getattr(_invdata_base_sub_table, _a)
|
|
307
|
+
for _a in ("industry_group", "additional_evidence", "data_array")
|
|
285
308
|
)
|
|
286
309
|
|
|
287
310
|
# Some tables can't be constructed due to inconsistencies in the data
|
{mergeron-2025.739290.1 → mergeron-2025.739290.3}/src/mergeron/core/guidelines_boundaries.py
RENAMED
|
@@ -43,6 +43,21 @@ class HMGThresholds:
|
|
|
43
43
|
cmcr: float
|
|
44
44
|
ipr: float
|
|
45
45
|
|
|
46
|
+
@classmethod
|
|
47
|
+
def to_yaml(
|
|
48
|
+
cls, _r: yaml.representer.SafeRepresenter, _d: HMGThresholds
|
|
49
|
+
) -> yaml.MappingNode:
|
|
50
|
+
_ret: yaml.MappingNode = _r.represent_mapping(
|
|
51
|
+
f"!{cls.__name__}", {_a: getattr(_d, _a) for _a in _d.__dataclass_fields__}
|
|
52
|
+
)
|
|
53
|
+
return _ret
|
|
54
|
+
|
|
55
|
+
@classmethod
|
|
56
|
+
def from_yaml(
|
|
57
|
+
cls, _c: yaml.constructor.SafeConstructor, _n: yaml.MappingNode
|
|
58
|
+
) -> HMGThresholds:
|
|
59
|
+
return cls(**_c.construct_mapping(_n))
|
|
60
|
+
|
|
46
61
|
|
|
47
62
|
@this_yaml.register_class
|
|
48
63
|
@frozen
|
|
@@ -40,7 +40,7 @@ __version__ = VERSION
|
|
|
40
40
|
DEFAULT_FCOUNT_WTS = np.asarray((_nr := np.arange(6, 0, -1)) / _nr.sum(), float)
|
|
41
41
|
|
|
42
42
|
|
|
43
|
-
@dataclass
|
|
43
|
+
@dataclass(slots=True, frozen=True)
|
|
44
44
|
class SeedSequenceData:
|
|
45
45
|
share: SeedSequence
|
|
46
46
|
pcm: SeedSequence
|
|
@@ -654,3 +654,20 @@ for _typ in (
|
|
|
654
654
|
),
|
|
655
655
|
),
|
|
656
656
|
)
|
|
657
|
+
|
|
658
|
+
for _typ in (MarketSampleData, SeedSequenceData, UPPTestsCounts):
|
|
659
|
+
_, _ = (
|
|
660
|
+
this_yaml.representer.add_representer(
|
|
661
|
+
_typ,
|
|
662
|
+
lambda _r, _d: _r.represent_mapping(
|
|
663
|
+
f"!{_d.__class__.__name__}",
|
|
664
|
+
{_a: getattr(_d, _a) for _a in _d.__dataclass_fields__},
|
|
665
|
+
),
|
|
666
|
+
),
|
|
667
|
+
this_yaml.constructor.add_constructor(
|
|
668
|
+
_typ,
|
|
669
|
+
lambda _c, _n: globals().get(
|
|
670
|
+
_n.tag.lstrip("!")(**_c.construct_mapping(_n))
|
|
671
|
+
),
|
|
672
|
+
),
|
|
673
|
+
)
|
{mergeron-2025.739290.1 → mergeron-2025.739290.3}/src/mergeron/gen/data_generation_functions.py
RENAMED
|
@@ -46,8 +46,8 @@ def gen_share_data(
|
|
|
46
46
|
_sample_size: int,
|
|
47
47
|
_share_spec: ShareSpec,
|
|
48
48
|
_fcount_rng_seed_seq: SeedSequence | None,
|
|
49
|
-
_mktshr_rng_seed_seq: SeedSequence
|
|
50
|
-
_nthreads: int
|
|
49
|
+
_mktshr_rng_seed_seq: SeedSequence,
|
|
50
|
+
_nthreads: int,
|
|
51
51
|
/,
|
|
52
52
|
) -> ShareDataSample:
|
|
53
53
|
"""Helper function for generating share data.
|
|
@@ -69,9 +69,9 @@ def gen_share_data(
|
|
|
69
69
|
|
|
70
70
|
"""
|
|
71
71
|
|
|
72
|
-
|
|
72
|
+
_dist_type_mktshr, _firm_count_prob_wts, _dist_parms_mktshr, _recapture_form = (
|
|
73
73
|
getattr(_share_spec, _f)
|
|
74
|
-
for _f in ("
|
|
74
|
+
for _f in ("dist_type", "firm_counts_weights", "dist_parms", "recapture_form")
|
|
75
75
|
)
|
|
76
76
|
|
|
77
77
|
_ssz = _sample_size
|
|
@@ -126,8 +126,8 @@ def gen_share_data(
|
|
|
126
126
|
def gen_market_shares_uniform(
|
|
127
127
|
_s_size: int,
|
|
128
128
|
_dist_parms_mktshr: ArrayDouble,
|
|
129
|
-
_mktshr_rng_seed_seq: SeedSequence
|
|
130
|
-
_nthreads: int
|
|
129
|
+
_mktshr_rng_seed_seq: SeedSequence,
|
|
130
|
+
_nthreads: int,
|
|
131
131
|
/,
|
|
132
132
|
) -> ShareDataSample:
|
|
133
133
|
"""Generate merging-firm shares from Uniform distribution on the 3-D simplex.
|
|
@@ -159,13 +159,12 @@ def gen_market_shares_uniform(
|
|
|
159
159
|
nthreads=_nthreads,
|
|
160
160
|
)
|
|
161
161
|
_mrng.fill()
|
|
162
|
-
# Convert draws on U[0, 1] to Uniformly-distributed draws on simplex, s_1 + s_2 <= 1
|
|
163
|
-
_frmshr_array.sort(axis=1)
|
|
164
162
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
_frmshr_array.
|
|
168
|
-
|
|
163
|
+
# Convert draws on U[0, 1] to Uniformly-distributed draws on simplex, s_1 + s_2 <= 1
|
|
164
|
+
_frmshr_array = np.hstack((
|
|
165
|
+
_frmshr_array.min(axis=1, keepdims=True),
|
|
166
|
+
np.abs(np.diff(_frmshr_array, axis=1)),
|
|
167
|
+
))
|
|
169
168
|
|
|
170
169
|
# Keep only share combinations representing feasible mergers
|
|
171
170
|
# This is a no-op for 64-bit floats, but is necessary for smaller floats
|
|
@@ -199,8 +198,8 @@ def _gen_market_shares_dirichlet_multimarket(
|
|
|
199
198
|
_dist_type_dir: SHRDistribution,
|
|
200
199
|
_dist_parms_dir: ArrayDouble,
|
|
201
200
|
_firm_count_wts: ArrayDouble,
|
|
202
|
-
_fcount_rng_seed_seq: SeedSequence | None
|
|
203
|
-
_mktshr_rng_seed_seq: SeedSequence
|
|
201
|
+
_fcount_rng_seed_seq: SeedSequence | None,
|
|
202
|
+
_mktshr_rng_seed_seq: SeedSequence,
|
|
204
203
|
_nthreads: int = NTHREADS,
|
|
205
204
|
/,
|
|
206
205
|
) -> ShareDataSample:
|
|
@@ -341,8 +340,8 @@ def gen_market_shares_dirichlet(
|
|
|
341
340
|
_dir_alphas: ArrayDouble,
|
|
342
341
|
_s_size: int,
|
|
343
342
|
_recapture_form: RECForm,
|
|
344
|
-
_mktshr_rng_seed_seq: SeedSequence
|
|
345
|
-
_nthreads: int
|
|
343
|
+
_mktshr_rng_seed_seq: SeedSequence,
|
|
344
|
+
_nthreads: int,
|
|
346
345
|
/,
|
|
347
346
|
) -> ShareDataSample:
|
|
348
347
|
"""Dirichlet-distributed shares with fixed firm-count.
|
|
@@ -497,7 +496,7 @@ def gen_margin_price_data(
|
|
|
497
496
|
_hsr_filing_test_type: SSZConstant,
|
|
498
497
|
_pcm_rng_seed_seq: SeedSequence,
|
|
499
498
|
_pr_rng_seed_seq: SeedSequence | None,
|
|
500
|
-
_nthreads: int
|
|
499
|
+
_nthreads: int,
|
|
501
500
|
/,
|
|
502
501
|
) -> tuple[MarginDataSample, PriceDataSample]:
|
|
503
502
|
"""Generate margin and price data for mergers in the sample.
|
|
@@ -680,8 +679,8 @@ def _gen_margin_data(
|
|
|
680
679
|
_price_array: ArrayDouble,
|
|
681
680
|
_aggregate_purchase_prob: ArrayDouble,
|
|
682
681
|
_pcm_spec: PCMSpec,
|
|
683
|
-
_pcm_rng_seed_seq: SeedSequence
|
|
684
|
-
_nthreads: int
|
|
682
|
+
_pcm_rng_seed_seq: SeedSequence,
|
|
683
|
+
_nthreads: int,
|
|
685
684
|
/,
|
|
686
685
|
) -> MarginDataSample:
|
|
687
686
|
_dist_type_pcm, _dist_firm2_pcm, _dist_parms_pcm = (
|
|
File without changes
|
|
File without changes
|
{mergeron-2025.739290.1 → mergeron-2025.739290.3}/src/mergeron/core/empirical_margin_distribution.py
RENAMED
|
File without changes
|
{mergeron-2025.739290.1 → mergeron-2025.739290.3}/src/mergeron/core/guidelines_boundary_functions.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mergeron-2025.739290.1 → mergeron-2025.739290.3}/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
|
|
File without changes
|
|
File without changes
|