mergeron 2025.739290.5__py3-none-any.whl → 2025.739290.6__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/__init__.py CHANGED
@@ -12,18 +12,20 @@ from ruamel import yaml
12
12
 
13
13
  _PKG_NAME: str = Path(__file__).parent.stem
14
14
 
15
- VERSION = "2025.739290.5"
15
+ VERSION = "2025.739290.6"
16
16
 
17
17
  __version__ = VERSION
18
18
 
19
- DATA_DIR: Path = Path.home() / _PKG_NAME
19
+ WORK_DIR = globals().get("WORK_DIR", Path.home() / _PKG_NAME)
20
20
  """
21
- Defines a subdirectory named for this package in the user's home path.
21
+ If defined, the global variable WORK_DIR is used as a data store.
22
22
 
23
- If the subdirectory doesn't exist, it is created on package invocation.
23
+ If the user does not define WORK_DIR, a subdirectory in
24
+ the user's home directory, named for this package, is
25
+ created/reused.
24
26
  """
25
- if not DATA_DIR.is_dir():
26
- DATA_DIR.mkdir(parents=False)
27
+ if not WORK_DIR.is_dir():
28
+ WORK_DIR.mkdir(parents=False)
27
29
 
28
30
  DEFAULT_REC_RATIO = 0.85
29
31
 
@@ -36,14 +38,14 @@ PKG_ATTRS_MAP: dict[str, object] = {}
36
38
 
37
39
  np.set_printoptions(precision=24, floatmode="fixed")
38
40
 
39
- type HMGPubYear = Literal[1982, 1984, 1992, 2010, 2023]
41
+ type HMGPubYear = Literal[1992, 2010, 2023]
40
42
 
41
43
  type ArrayBoolean = NDArray[np.bool_]
42
44
  type ArrayFloat = NDArray[np.floating]
43
- type ArrayINT = NDArray[np.unsignedinteger]
45
+ type ArrayINT = NDArray[np.integer]
44
46
 
45
47
  type ArrayDouble = NDArray[np.float64]
46
- type ArrayBIGINT = NDArray[np.uint64]
48
+ type ArrayBIGINT = NDArray[np.int64]
47
49
 
48
50
 
49
51
  this_yaml = yaml.YAML(typ="rt")
@@ -131,35 +133,47 @@ class Enameled(enum.Enum):
131
133
  @this_yaml.register_class
132
134
  @enum.unique
133
135
  class RECForm(str, Enameled):
134
- """For derivation of recapture ratio from market shares."""
136
+ R"""For derivation of recapture ratio from market shares.
137
+
138
+ With :math:`\mathscr{N}` a set of firms, each supplying a
139
+ single differentiated product, and :math:`\mathscr{M} \subset \mathscr{N}`
140
+ a putative relevant product market, with
141
+ :math:`d_{ij}` denoting diversion ratio from good :math:`i` to good :math:`j`,
142
+ :math:`s_i` denoting market shares, and
143
+ :math:`\overline{r}` the default market recapture ratio,
144
+ market recapture ratios for the respective products may be specified
145
+ as having one of the following forms:
146
+ """
135
147
 
136
- INOUT = "inside-out"
137
- R"""
138
- Given, :math:`\overline{r}, s_i {\ } \forall {\ } i \in \set{1, 2, \ldots, m}`, with
139
- :math:`s_{min} = \min(s_1, s_2)`,
148
+ FIXED = "proportional"
149
+ R"""Given, :math:`\overline{r}`,
140
150
 
141
151
  .. math::
142
152
 
143
- REC_i = \frac{(1 - s_i) \overline{r}}{(1 - s_{min}) - (s_i - s_{min}) \overline{r}}
153
+ REC_i = \overline{r} {\ } \forall {\ } i \in \mathscr{M}
144
154
 
145
155
  """
146
156
 
147
- OUTIN = "outside-in"
157
+ INOUT = "inside-out"
148
158
  R"""
149
- Given, :math:`\pi_i {\ } \forall {\ } i \in N`,
159
+ Given, :math:`\overline{r}, s_i {\ } \forall {\ } i \in \mathscr{M}`, with
160
+ :math:`s_{min} = \min(s_1, s_2)`,
150
161
 
151
162
  .. math::
152
163
 
153
- REC_i = \frac{\sum_{i \in M} \pi_i}{\sum_{j \in N} \pi_j}
164
+ REC_i = \frac{\overline{r} (1 - s_i)}{1 - (1 - \overline{r}) s_{min} - \overline{r} s_i}
165
+ {\ } \forall {\ } i \in \mathscr{M}
154
166
 
155
167
  """
156
168
 
157
- FIXED = "proportional"
158
- R"""Given, :math:`\overline{r}`,
169
+ OUTIN = "outside-in"
170
+ R"""
171
+ Given, :math:`d_{ij} {\ } \forall {\ } i, j \in \mathscr{M}, i \neq j`,
159
172
 
160
173
  .. math::
161
174
 
162
- REC_i = \overline{r} {\ } \forall {\ } i \in M
175
+ REC_i = {\sum_{j \in \mathscr{M}}^{j \neq i} d_{ij}}
176
+ {\ } \forall {\ } i \in \mathscr{M}
163
177
 
164
178
  """
165
179
 
mergeron/core/__init__.py CHANGED
@@ -61,14 +61,14 @@ type INVData_in = Mapping[str, Mapping[str, Mapping[str, INVTableData]]]
61
61
 
62
62
 
63
63
  def _dict_from_mapping(_p: Mapping[Any, Any], /) -> dict[Any, Any]:
64
- retval = {}
64
+ retval: dict[Any, Any] = {}
65
65
  for _k, _v in _p.items(): # for subit in it:
66
66
  retval |= {_k: _dict_from_mapping(_v)} if isinstance(_v, Mapping) else {_k: _v}
67
67
  return retval
68
68
 
69
69
 
70
70
  def _mappingproxy_from_mapping(_p: Mapping[Any, Any], /) -> MappingProxyType[Any, Any]:
71
- retval = {}
71
+ retval: dict[Any, Any] = {}
72
72
  for _k, _v in _p.items(): # for subit in it:
73
73
  retval |= (
74
74
  {_k: _mappingproxy_from_mapping(_v)}
@@ -39,7 +39,6 @@ price-cost margins fall in the interval :math:`[0, 1]`.
39
39
  import shutil
40
40
  import zipfile
41
41
  from collections.abc import Mapping
42
- from importlib import resources
43
42
  from pathlib import Path
44
43
  from types import MappingProxyType
45
44
 
@@ -49,12 +48,17 @@ from numpy.random import PCG64DXSM, Generator, SeedSequence
49
48
  from scipy import stats # type: ignore
50
49
  from xlrd import open_workbook # type: ignore
51
50
 
52
- from .. import _PKG_NAME, DATA_DIR, VERSION, ArrayDouble, this_yaml # noqa: TID252
51
+ from .. import VERSION, ArrayDouble, this_yaml # noqa: TID252
52
+ from .. import WORK_DIR as PKG_WORK_DIR # noqa: TID252
53
+ from .. import data as mdat # noqa: TID252
53
54
  from . import _mappingproxy_from_mapping
54
55
 
55
56
  __version__ = VERSION
56
57
 
57
- MGNDATA_ARCHIVE_PATH = DATA_DIR / "damodaran_margin_data_serialized.zip"
58
+ WORK_DIR = globals().get("WORK_DIR", PKG_WORK_DIR)
59
+ """Redefined, in case the user defines WORK_DIR betweeen module imports."""
60
+
61
+ MGNDATA_ARCHIVE_PATH = WORK_DIR / "damodaran_margin_data_serialized.zip"
58
62
 
59
63
 
60
64
  u3pm = urllib3.PoolManager()
@@ -74,14 +78,14 @@ def margin_data_getter( # noqa: PLR0912
74
78
  data_archive_path = data_archive_path or MGNDATA_ARCHIVE_PATH
75
79
  workbook_path = data_archive_path.parent / f"damodaran_{_table_name}_data.xls"
76
80
  if data_archive_path.is_file() and not data_download_flag:
77
- # with data_archive_path_.open("r") as _yfh:
78
- # margin_data_dict: dict[str, dict[str, float | int]] = this_yaml.load(_yfh)
79
81
  with (
80
82
  zipfile.ZipFile(data_archive_path) as _yzip,
81
83
  _yzip.open(f"{data_archive_path.stem}.yaml") as _yfh,
82
84
  ):
83
- margin_data_dict: dict[str, dict[str, float | int]] = this_yaml.load(_yfh)
84
- return _mappingproxy_from_mapping(margin_data_dict)
85
+ margin_data_dict: MappingProxyType[
86
+ str, MappingProxyType[str, float | int]
87
+ ] = this_yaml.load(_yfh)
88
+ return margin_data_dict
85
89
  elif workbook_path.is_file():
86
90
  workbook_path.unlink()
87
91
  if data_archive_path.is_file():
@@ -116,19 +120,14 @@ def margin_data_getter( # noqa: PLR0912
116
120
  "Using bundled copy."
117
121
  )
118
122
  if not workbook_path.is_file():
119
- with resources.as_file(
120
- resources.files(f"{_PKG_NAME}.data").joinpath(
121
- "empirical_margin_distribution.xls"
122
- )
123
- ) as margin_data_archive_path:
124
- shutil.copy2(margin_data_archive_path, workbook_path)
123
+ shutil.copy2(mdat.DAMODARAN_MARGIN_WORKBOOK, workbook_path)
125
124
  else:
126
125
  raise error_
127
126
 
128
127
  xl_book = open_workbook(workbook_path, ragged_rows=True, on_demand=True)
129
128
  xl_sheet = xl_book.sheet_by_name("Industry Averages")
130
129
 
131
- margin_dict: dict[str, dict[str, float | int]] = {}
130
+ margin_dict_in: dict[str, dict[str, float | int]] = {}
132
131
  row_keys: list[str] = []
133
132
  read_row_flag = False
134
133
  for _ridx in range(xl_sheet.nrows):
@@ -142,15 +141,16 @@ def margin_data_getter( # noqa: PLR0912
142
141
  continue
143
142
 
144
143
  xl_row[1] = int(xl_row[1])
145
- margin_dict[xl_row[0]] = dict(zip(row_keys[1:], xl_row[1:], strict=True))
144
+ margin_dict_in[xl_row[0]] = dict(zip(row_keys[1:], xl_row[1:], strict=True))
146
145
 
146
+ margin_dict = _mappingproxy_from_mapping(margin_dict_in)
147
147
  with (
148
148
  zipfile.ZipFile(data_archive_path, "w") as _yzip,
149
149
  _yzip.open(f"{data_archive_path.stem}.yaml", "w") as _yfh,
150
150
  ):
151
151
  this_yaml.dump(margin_dict, _yfh)
152
152
 
153
- return _mappingproxy_from_mapping(margin_dict)
153
+ return margin_dict
154
154
 
155
155
 
156
156
  def margin_data_builder(
@@ -13,7 +13,6 @@ from __future__ import annotations
13
13
  import re
14
14
  import shutil
15
15
  from collections.abc import Sequence
16
- from importlib import resources
17
16
  from operator import itemgetter
18
17
  from pathlib import Path
19
18
  from types import MappingProxyType
@@ -26,14 +25,9 @@ import urllib3
26
25
  from bs4 import BeautifulSoup
27
26
  from numpy.testing import assert_array_equal
28
27
 
29
- from .. import ( # noqa: TID252
30
- _PKG_NAME,
31
- DATA_DIR,
32
- EMPTY_ARRAYINT,
33
- VERSION,
34
- ArrayBIGINT,
35
- this_yaml,
36
- )
28
+ from .. import EMPTY_ARRAYINT, VERSION, ArrayBIGINT, this_yaml # noqa: TID252
29
+ from .. import WORK_DIR as PKG_WORK_DIR # noqa: TID252
30
+ from .. import data as mdat # noqa: TID252
37
31
  from . import (
38
32
  INVData,
39
33
  INVData_in,
@@ -46,21 +40,16 @@ __version__ = VERSION
46
40
 
47
41
  m.patch()
48
42
 
49
- FTCDATA_DIR = DATA_DIR / "FTCData"
50
- if not FTCDATA_DIR.is_dir():
51
- FTCDATA_DIR.mkdir(parents=True)
43
+ WORK_DIR = globals().get("WORK_DIR", PKG_WORK_DIR)
44
+ """Redefined, in case the user defines WORK_DIR betweeen module imports."""
52
45
 
53
- INVDATA_ARCHIVE_PATH = DATA_DIR / "ftc_invdata.zip"
54
- if (
55
- not INVDATA_ARCHIVE_PATH.is_file()
56
- and (
57
- _bundled_copy := resources.files(f"{_PKG_NAME}.data").joinpath(
58
- INVDATA_ARCHIVE_PATH.name
59
- )
60
- ).is_file()
61
- ):
62
- with resources.as_file(_bundled_copy) as _bundled_copy_path:
63
- shutil.copy2(_bundled_copy_path, INVDATA_ARCHIVE_PATH)
46
+ FID_WORK_DIR = WORK_DIR / "FTCData"
47
+ if not FID_WORK_DIR.is_dir():
48
+ FID_WORK_DIR.mkdir(parents=True)
49
+
50
+ INVDATA_ARCHIVE_PATH = WORK_DIR / mdat.FTC_MERGER_INVESTIGATIONS_DATA.name
51
+ if not INVDATA_ARCHIVE_PATH.is_file():
52
+ shutil.copy2(mdat.FTC_MERGER_INVESTIGATIONS_DATA, INVDATA_ARCHIVE_PATH)
64
53
 
65
54
  TABLE_NO_RE = re.compile(r"Table \d+\.\d+")
66
55
  TABLE_TYPES = ("ByHHIandDelta", "ByFirmCount")
@@ -442,12 +431,12 @@ def _parse_invdata() -> INVData:
442
431
  # )
443
432
  import pymupdf # type: ignore # noqa: PLC0415
444
433
 
445
- invdata_docnames = _download_invdata(FTCDATA_DIR)
434
+ invdata_docnames = _download_invdata(FID_WORK_DIR)
446
435
 
447
436
  invdata: INVData_in = {}
448
437
 
449
438
  for invdata_docname in invdata_docnames:
450
- invdata_pdf_path = FTCDATA_DIR.joinpath(invdata_docname)
439
+ invdata_pdf_path = FID_WORK_DIR.joinpath(invdata_docname)
451
440
 
452
441
  invdata_doc = pymupdf.open(invdata_pdf_path)
453
442
  invdata_meta = invdata_doc.metadata
@@ -709,7 +698,7 @@ def _process_table_blks_cnt_type(
709
698
  return invdata_array[np.argsort(invdata_array[:, 0])]
710
699
 
711
700
 
712
- def _download_invdata(_dl_path: Path = FTCDATA_DIR) -> tuple[str, ...]:
701
+ def _download_invdata(_dl_path: Path = FID_WORK_DIR) -> tuple[str, ...]:
713
702
  if not _dl_path.is_dir():
714
703
  _dl_path.mkdir(parents=True)
715
704
 
@@ -51,14 +51,12 @@ class GuidelinesThresholds:
51
51
 
52
52
  ΔHHI, Recapture Ratio, GUPPI, Diversion ratio, CMCR, and IPR thresholds
53
53
  constructed from concentration standards in Guidelines published in
54
- 1982, 1984, 1992, 2010, and 2023.
54
+ 1992, 2010, and 2023.
55
55
 
56
56
  """
57
57
 
58
58
  pub_year: HMGPubYear = field(
59
- kw_only=False,
60
- default=2023,
61
- validator=validators.in_([1982, 1984, 1992, 2010, 2023]),
59
+ kw_only=False, default=2023, validator=validators.in_([1992, 2010, 2023])
62
60
  )
63
61
  """
64
62
  Year of publication of the Guidelines
@@ -97,9 +95,7 @@ class GuidelinesThresholds:
97
95
  # thus, here, the tentative delta safeharbor under
98
96
  # the 2023 Guidelines is 100 points
99
97
  hhi_p, dh_s, dh_p = {
100
- 1982: (_s1982 := (0.18, 0.005, 0.01)),
101
- 1984: _s1982,
102
- 1992: _s1982,
98
+ 1992: (0.18, 0.005, 0.01),
103
99
  2010: (0.25, 0.01, 0.02),
104
100
  2023: (0.18, 0.01, 0.01),
105
101
  }[self.pub_year]
@@ -240,7 +236,7 @@ class DiversionRatioBoundary:
240
236
  )
241
237
 
242
238
  recapture_form: RECForm | None = field(kw_only=True, default=RECForm.INOUT)
243
- """
239
+ R"""
244
240
  The form of the recapture ratio.
245
241
 
246
242
  When :attr:`mergeron.RECForm.INOUT`, the recapture ratio for
@@ -251,12 +247,17 @@ class DiversionRatioBoundary:
251
247
  constructed from the generated purchase-probabilities for products in
252
248
  the market and for the outside good, specify :attr:`mergeron.RECForm.OUTIN`.)
253
249
 
254
- The GUPPI boundary is a continuum of diversion ratio boundaries conditional on
255
- price-cost margins, :math:`d_{ij} = g_i * p_i / (m_j * p_j)`,
256
- with :math:`d_{ij}` the diverion ratio from product :math:`i` to product :math:`j`;
250
+ The GUPPI boundary is a continuum of conditional diversion ratio boundaries,
251
+
252
+ .. math::
253
+
254
+ d_{ij} \vert_{p_i, p_j, m_j} \triangleq \frac{g_i p_i}{m_j p_j} = \overline{d}
255
+
256
+ with :math:`d_{ij}` the diversion ratio from product :math:`i` to product :math:`j`;
257
257
  :math:`g_i` the GUPPI for product :math:`i`;
258
- :math:`m_j` the margin for product :math:`j`; and
259
- :math:`p_i, p_j` the prices of goods :math:`i, j`, respectively.
258
+ :math:`m_j` the price-cost margin on product :math:`j`;
259
+ :math:`p_i, p_j` the prices of goods :math:`i, j`, respectively; and
260
+ :math:`\overline{d}` the diversion ratio threshold (i.e., bound).
260
261
 
261
262
  """
262
263
 
mergeron/data/__init__.py CHANGED
@@ -1,3 +1,57 @@
1
- from .. import VERSION # noqa: TID252
1
+ """
2
+ Data useful for empirical analysis of merger enforcement policy
3
+
4
+ These data are processed for further analysis within relevant
5
+ submodules of the parent package. Thus, direct access is
6
+ unnecessary in routine use of this package.
7
+ """
8
+
9
+ from importlib import resources
10
+
11
+ from .. import _PKG_NAME, VERSION # noqa: TID252
2
12
 
3
13
  __version__ = VERSION
14
+
15
+
16
+ DAMODARAN_MARGIN_WORKBOOK = resources.files(f"{_PKG_NAME}.data").joinpath(
17
+ "damodaran_margin_data.xls"
18
+ )
19
+ """
20
+ Python object pointing to included copy of Prof. Damodaran's margin data
21
+
22
+ Only used as a fallback, in case direct download from source fails.
23
+
24
+ NOTES
25
+ -----
26
+ Source data are from Prof. Aswath Damodaran, Stern School of Business, NYU; available online
27
+ at https://pages.stern.nyu.edu/~adamodar/pc/datasets/margin.xls
28
+
29
+
30
+ Use as, for example:
31
+
32
+ .. code-block:: python
33
+
34
+ from mergeron.data import DAMODARAN_MARGIN_WORKBOOK
35
+
36
+ shutil.copy2(DAMODARAN_MARGIN_WORKBOOK, Path.home() / f"{DAMODARAN_MARGIN_WORKBOOK.name}")
37
+ """
38
+
39
+ FTC_MERGER_INVESTIGATIONS_DATA = resources.files(f"{_PKG_NAME}.data").joinpath(
40
+ "ftc_merger_investigations_data.zip"
41
+ )
42
+ """
43
+ FTC merger investigtions data published in 2004, 2007, 2008, and 2013
44
+
45
+ NOTES
46
+ -----
47
+ Raw data tables published by the FTC are loaded into a nested distionary, organized by
48
+ data period, table type, and table number. Each table is stored as a numerical array
49
+ (:module:`numpy` arrray), with additonal attrubutes for the industry group and additonal
50
+ evidence noted in the source data.
51
+
52
+ Data for additonal data periods (time spans) not reported in the source data,
53
+ e.g., 2004-2011, are constructed by subtracting counts in the base data from counts
54
+ in the cumulative data, by table, for "enforced" mergers and "closed" mergers, when
55
+ the cumulative data for the longer period are consistent with the base data for
56
+ a sub-period.
57
+ """
@@ -13,9 +13,12 @@ from numpy.random import PCG64DXSM, Generator, SeedSequence
13
13
  from scipy import stats # type: ignore
14
14
 
15
15
  import mergeron.core.empirical_margin_distribution as emd
16
- from mergeron import DATA_DIR
16
+ from mergeron import WORK_DIR as PKG_WORK_DIR
17
17
  from mergeron.core.guidelines_boundary_functions import boundary_plot
18
18
 
19
+ WORK_DIR = globals().get("WORK_DIR", PKG_WORK_DIR)
20
+ """Redefined, in case the user defines WORK_DIR betweeen module imports."""
21
+
19
22
  SAMPLE_SIZE = 10**6
20
23
  BIN_COUNT = 25
21
24
  margin_data_obs, margin_data_wts, margin_data_stats = emd.margin_data_builder()
@@ -85,4 +88,4 @@ mgn_ax.set_xlabel("Price Cost Margin", fontsize=10)
85
88
  mgn_ax.set_ylabel("Relative Frequency", fontsize=10)
86
89
 
87
90
  mgn_fig.tight_layout()
88
- plt.savefig(DATA_DIR / f"{Path(__file__).stem}.pdf")
91
+ plt.savefig(WORK_DIR / f"{Path(__file__).stem}.pdf")
mergeron/gen/__init__.py CHANGED
@@ -11,7 +11,7 @@ import io
11
11
  from collections.abc import Sequence
12
12
  from operator import attrgetter
13
13
 
14
- import h5py
14
+ import h5py # type: ignore
15
15
  import numpy as np
16
16
  from attrs import Attribute, Converter, cmp_using, field, frozen, validators
17
17
  from numpy.random import SeedSequence
@@ -255,7 +255,7 @@ class ShareSpec:
255
255
  in published merger guidelines. Accordingly, the recapture ratio rounded to
256
256
  the nearest 5% is:
257
257
 
258
- * 0.85, **7-to-6 merger from symmetry**; US Guidelines, 1982, 1984, 1992, 2023
258
+ * 0.85, **7-to-6 merger from symmetry**; US Guidelines, 1992, 2023
259
259
  * 0.80, 5-to-4 merger from symmetry
260
260
  * 0.80, **5-to-4 merger to symmetry**; US Guidelines, 2010
261
261
 
@@ -470,7 +470,9 @@ class MarketSampleData:
470
470
 
471
471
  @aggregate_purchase_prob.default
472
472
  def __appd(_i: MarketSampleData) -> ArrayDouble:
473
- return np.nan * np.empty_like(_i.frmshr_array[:, :1], float)
473
+ retval: ArrayDouble = np.empty_like(_i.frmshr_array[:, :1], float)
474
+ retval.fill(np.nan)
475
+ return retval
474
476
 
475
477
  fcounts: ArrayINT = field(eq=cmp_using(np.array_equal))
476
478
  """Number of firms in market"""
@@ -488,14 +490,18 @@ class MarketSampleData:
488
490
 
489
491
  @nth_firm_share.default
490
492
  def __nfsd(_i: MarketSampleData) -> ArrayDouble:
491
- return np.nan * np.empty_like(_i.frmshr_array[:, :1], float)
493
+ retval: ArrayDouble = np.empty_like(_i.frmshr_array[:, :1], float)
494
+ retval.fill(np.nan)
495
+ return retval
492
496
 
493
497
  hhi_post: ArrayDouble = field(eq=cmp_using(np.array_equal))
494
498
  """Post-merger change in Herfindahl-Hirschmann Index (HHI)"""
495
499
 
496
500
  @hhi_post.default
497
501
  def __hpd(_i: MarketSampleData) -> ArrayDouble:
498
- return np.nan * np.empty_like(_i.frmshr_array[:, :1], float)
502
+ retval: ArrayDouble = np.empty_like(_i.frmshr_array[:, :1], float)
503
+ retval.fill(np.nan)
504
+ return retval
499
505
 
500
506
  def to_h5bin(self) -> bytes:
501
507
  """Save market sample data to HDF5 file."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: mergeron
3
- Version: 2025.739290.5
3
+ Version: 2025.739290.6
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
@@ -0,0 +1,22 @@
1
+ mergeron/__init__.py,sha256=RecBYFEM4d7Kue2c34rgPYJwoqZ13ectby7vKzdnKjs,5549
2
+ mergeron/core/__init__.py,sha256=liYBlatU39hpdJijSzCDzZwRB90QqeQ2pYRdAb674UM,3113
3
+ mergeron/core/empirical_margin_distribution.py,sha256=ktX0r5EHooXFkTed6iTzqkHw0DRv7KIDIcX3h2ukm2I,9313
4
+ mergeron/core/ftc_merger_investigations_data.py,sha256=LCh9lTLeMcW_akL9cWU1qJm0kiYdD8UUnQKcvrBIMug,28461
5
+ mergeron/core/guidelines_boundaries.py,sha256=yMFyI3RZg0UwBFpUmL6Qk1nUX7lI97dbz9I9a3Pxvdo,15247
6
+ mergeron/core/guidelines_boundary_functions.py,sha256=Mxw9OE-pwMbTRNaJLVtx7AYfJeFJgAvFM1LrPuZrzpM,28877
7
+ mergeron/core/guidelines_boundary_functions_extra.py,sha256=TnQcBVABvJulDIue3jUlVOaKmwu0EAME6z8RCf-W3Tc,16099
8
+ mergeron/core/pseudorandom_numbers.py,sha256=YqcVwU-Pgc0F_pKzG9Osn14RnIuYOwE-q7GVDpCUtpI,9998
9
+ mergeron/data/__init__.py,sha256=0JkbzzmzN5mgaLv76gdbcU-GYNizdIqhqxkMB6a-6Cs,1827
10
+ mergeron/data/damodaran_margin_data.xls,sha256=Qggl1p5nkOMJI8YUXhkwXQRz-OhRSqBTzz57N0JQyYA,79360
11
+ mergeron/data/ftc_merger_investigations_data.zip,sha256=5vqqYFb9iULON4SA1XA0M37N6EblyIYMltgnxELY8yA,15126
12
+ mergeron/demo/__init__.py,sha256=KtjBlZOl7jwBCAUhrTJB9PdrN39YLYytNiSUSM_gRmA,62
13
+ mergeron/demo/visualize_empirical_margin_distribution.py,sha256=17awsa188r7uVDJuHuCWTYwlQbfaq4n8HEHF5jK-0Ic,2532
14
+ mergeron/gen/__init__.py,sha256=9z2aLgsD9g5NZt7-jMZbb-nThIOXuAzyw4M5rCFVpOo,22620
15
+ mergeron/gen/data_generation.py,sha256=LbtNg-3DKyqqzPDMFI2_cFIof3JdaVHwFqwifIH_AWc,17644
16
+ mergeron/gen/data_generation_functions.py,sha256=UDh3B4FPwh4SxTdJs7-faLouf7cWUUjHarRkfJc9gjI,26408
17
+ mergeron/gen/enforcement_stats.py,sha256=CsO5pk9lKV2xsdINukWL2DjEpt4Asq0YHHJw6zAziCc,10776
18
+ mergeron/gen/upp_tests.py,sha256=tsQJYOE6CahyChq_y_LKtq6P3n3exlBiYncB1GYx0Hg,9986
19
+ mergeron/py.typed,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
20
+ mergeron-2025.739290.6.dist-info/METADATA,sha256=VMQfZraRGyjQQFIdLPSk34C6ADlOAx54wPqhx1ul560,14512
21
+ mergeron-2025.739290.6.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
22
+ mergeron-2025.739290.6.dist-info/RECORD,,
Binary file
Binary file
@@ -1,24 +0,0 @@
1
- mergeron/__init__.py,sha256=Semlg7F-RfPXPDzYmfDX7UkULEY5p5Rq5s2obV44Ia4,4892
2
- mergeron/core/__init__.py,sha256=e62LHGyvz9zUPQbU4nos8JxydraCQrJJa-2qApY2KXQ,3081
3
- mergeron/core/empirical_margin_distribution.py,sha256=828H1UqJZK6dARS1V75fsP6FlKsGMAkBXZO-sw6WJdI,9449
4
- mergeron/core/ftc_merger_investigations_data.py,sha256=pAM5WMTw8znZn9vN_-AW5A8kH-IRwMwMFA5F_fRNaYQ,28492
5
- mergeron/core/guidelines_boundaries.py,sha256=Avtnbo2iPhhUu8JLjP7mFQo8xVZvPvNCZU9GSsVkReM,15234
6
- mergeron/core/guidelines_boundary_functions.py,sha256=Mxw9OE-pwMbTRNaJLVtx7AYfJeFJgAvFM1LrPuZrzpM,28877
7
- mergeron/core/guidelines_boundary_functions_extra.py,sha256=TnQcBVABvJulDIue3jUlVOaKmwu0EAME6z8RCf-W3Tc,16099
8
- mergeron/core/pseudorandom_numbers.py,sha256=YqcVwU-Pgc0F_pKzG9Osn14RnIuYOwE-q7GVDpCUtpI,9998
9
- mergeron/data/__init__.py,sha256=KtjBlZOl7jwBCAUhrTJB9PdrN39YLYytNiSUSM_gRmA,62
10
- mergeron/data/damodaran_margin_data.xls,sha256=Qggl1p5nkOMJI8YUXhkwXQRz-OhRSqBTzz57N0JQyYA,79360
11
- mergeron/data/damodaran_margin_data_serialized.zip,sha256=_oCVHI2YpG762WN5-KM5vnAS4OoAGkhP7Vd8KSWuiG8,20384
12
- mergeron/data/ftc_invdata.msgpack,sha256=WBFHgi7Ld4R-h2zL2Zc3TOIlKqVrbVFMH1LoI4-T-M0,264664
13
- mergeron/data/ftc_invdata.zip,sha256=1J74iTM1RVHTcvqv2v7H3yqeYN3vEvp4ZUszDk1oHQc,15686
14
- mergeron/demo/__init__.py,sha256=KtjBlZOl7jwBCAUhrTJB9PdrN39YLYytNiSUSM_gRmA,62
15
- mergeron/demo/visualize_empirical_margin_distribution.py,sha256=U40SYsSSghJrDgLHu91A2uRd1dqv5yDkkFM8NFYMGHM,2388
16
- mergeron/gen/__init__.py,sha256=S2Snd5QSgbGj7EQ2eVc9vDwy8vUYQQo38gjYuWuYOr8,22448
17
- mergeron/gen/data_generation.py,sha256=LbtNg-3DKyqqzPDMFI2_cFIof3JdaVHwFqwifIH_AWc,17644
18
- mergeron/gen/data_generation_functions.py,sha256=UDh3B4FPwh4SxTdJs7-faLouf7cWUUjHarRkfJc9gjI,26408
19
- mergeron/gen/enforcement_stats.py,sha256=CsO5pk9lKV2xsdINukWL2DjEpt4Asq0YHHJw6zAziCc,10776
20
- mergeron/gen/upp_tests.py,sha256=tsQJYOE6CahyChq_y_LKtq6P3n3exlBiYncB1GYx0Hg,9986
21
- mergeron/py.typed,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
22
- mergeron-2025.739290.5.dist-info/METADATA,sha256=F4X5U0u7nlHGtBtZSKydwd0jRzFc1s5ooWFpPCJ0zVQ,14512
23
- mergeron-2025.739290.5.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
24
- mergeron-2025.739290.5.dist-info/RECORD,,