mergeron 2024.739097.3__tar.gz → 2024.739099.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.

Files changed (36) hide show
  1. {mergeron-2024.739097.3 → mergeron-2024.739099.0}/PKG-INFO +11 -39
  2. {mergeron-2024.739097.3 → mergeron-2024.739099.0}/README.rst +8 -31
  3. {mergeron-2024.739097.3 → mergeron-2024.739099.0}/pyproject.toml +10 -13
  4. {mergeron-2024.739097.3 → mergeron-2024.739099.0}/src/mergeron/__init__.py +1 -1
  5. {mergeron-2024.739097.3 → mergeron-2024.739099.0}/src/mergeron/core/damodaran_margin_data.py +1 -1
  6. {mergeron-2024.739097.3 → mergeron-2024.739099.0}/src/mergeron/core/ftc_merger_investigations_data.py +23 -16
  7. {mergeron-2024.739097.3 → mergeron-2024.739099.0}/src/mergeron/core/guidelines_boundary_functions.py +1 -1
  8. {mergeron-2024.739097.3 → mergeron-2024.739099.0}/src/mergeron/core/guidelines_boundary_functions_extra.py +6 -7
  9. mergeron-2024.739097.3/src/mergeron/ext/__init__.py +0 -3
  10. mergeron-2024.739097.3/src/mergeron/ext/proportions_tests.py +0 -518
  11. mergeron-2024.739097.3/src/mergeron/ext/tol_colors.py +0 -848
  12. mergeron-2024.739097.3/src/mergeron/ext/xlsxw_helper.py +0 -631
  13. {mergeron-2024.739097.3 → mergeron-2024.739099.0}/src/mergeron/License.txt +0 -0
  14. {mergeron-2024.739097.3 → mergeron-2024.739099.0}/src/mergeron/core/__init__.py +0 -0
  15. {mergeron-2024.739097.3 → mergeron-2024.739099.0}/src/mergeron/core/guidelines_boundaries.py +0 -0
  16. {mergeron-2024.739097.3 → mergeron-2024.739099.0}/src/mergeron/core/pseudorandom_numbers.py +0 -0
  17. {mergeron-2024.739097.3 → mergeron-2024.739099.0}/src/mergeron/data/__init__.py +0 -0
  18. {mergeron-2024.739097.3 → mergeron-2024.739099.0}/src/mergeron/data/damodaran_margin_data.xls +0 -0
  19. {mergeron-2024.739097.3 → mergeron-2024.739099.0}/src/mergeron/data/damodaran_margin_data_dict.msgpack +0 -0
  20. {mergeron-2024.739097.3 → mergeron-2024.739099.0}/src/mergeron/data/ftc_invdata.msgpack +0 -0
  21. {mergeron-2024.739097.3 → mergeron-2024.739099.0}/src/mergeron/data/jinja2_LaTeX_templates/clrrate_cis_summary_table_template.tex.jinja2 +0 -0
  22. {mergeron-2024.739097.3 → mergeron-2024.739099.0}/src/mergeron/data/jinja2_LaTeX_templates/ftcinvdata_byhhianddelta_table_template.tex.jinja2 +0 -0
  23. {mergeron-2024.739097.3 → mergeron-2024.739099.0}/src/mergeron/data/jinja2_LaTeX_templates/ftcinvdata_summary_table_template.tex.jinja2 +0 -0
  24. {mergeron-2024.739097.3 → mergeron-2024.739099.0}/src/mergeron/data/jinja2_LaTeX_templates/ftcinvdata_summarypaired_table_template.tex.jinja2 +0 -0
  25. {mergeron-2024.739097.3 → mergeron-2024.739099.0}/src/mergeron/data/jinja2_LaTeX_templates/mergeron.cls +0 -0
  26. {mergeron-2024.739097.3 → mergeron-2024.739099.0}/src/mergeron/data/jinja2_LaTeX_templates/mergeron_table_collection_template.tex.jinja2 +0 -0
  27. {mergeron-2024.739097.3 → mergeron-2024.739099.0}/src/mergeron/data/jinja2_LaTeX_templates/setup_tikz_tables.tex +0 -0
  28. {mergeron-2024.739097.3 → mergeron-2024.739099.0}/src/mergeron/demo/__init__.py +0 -0
  29. {mergeron-2024.739097.3 → mergeron-2024.739099.0}/src/mergeron/demo/visualize_empirical_margin_distribution.py +0 -0
  30. {mergeron-2024.739097.3 → mergeron-2024.739099.0}/src/mergeron/gen/__init__.py +0 -0
  31. {mergeron-2024.739097.3 → mergeron-2024.739099.0}/src/mergeron/gen/_data_generation_functions.py +0 -0
  32. {mergeron-2024.739097.3 → mergeron-2024.739099.0}/src/mergeron/gen/data_generation.py +0 -0
  33. {mergeron-2024.739097.3 → mergeron-2024.739099.0}/src/mergeron/gen/enforcement_stats.py +0 -0
  34. {mergeron-2024.739097.3 → mergeron-2024.739099.0}/src/mergeron/gen/market_sample.py +0 -0
  35. {mergeron-2024.739097.3 → mergeron-2024.739099.0}/src/mergeron/gen/upp_tests.py +0 -0
  36. {mergeron-2024.739097.3 → mergeron-2024.739099.0}/src/mergeron/py.typed +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mergeron
3
- Version: 2024.739097.3
3
+ Version: 2024.739099.0
4
4
  Summary: Merger Policy Analysis using Python
5
5
  License: MIT
6
6
  Keywords: merger policy analysis,merger guidelines,merger screening,policy presumptions,concentration standards,upward pricing pressure,GUPPI
@@ -25,21 +25,16 @@ Requires-Dist: certifi (>=2023.11.17)
25
25
  Requires-Dist: google-re2 (>=1.1)
26
26
  Requires-Dist: jinja2 (>=3.1)
27
27
  Requires-Dist: joblib (>=1.3)
28
- Requires-Dist: lxml (>=5.0)
29
28
  Requires-Dist: matplotlib (>=3.8)
30
29
  Requires-Dist: mpmath (>=1.3)
31
30
  Requires-Dist: msgpack (>=1.0)
32
31
  Requires-Dist: msgpack-numpy (>=0.4)
33
- Requires-Dist: numpy (>=1.26,<2.0)
34
- Requires-Dist: openpyxl (>=3.1.2)
35
- Requires-Dist: poetry-plugin-export (>=1.8.0,<2.0.0)
36
- Requires-Dist: requests (>=2.31)
37
- Requires-Dist: requests-toolbelt (>=1.0.0)
32
+ Requires-Dist: numpy (>=1.26,<2)
38
33
  Requires-Dist: scipy (>=1.12)
39
34
  Requires-Dist: sympy (>=1.12)
40
35
  Requires-Dist: tables (>=3.8)
41
36
  Requires-Dist: types-beautifulsoup4 (>=4.11.2)
42
- Requires-Dist: types-requests (>=2.31.0)
37
+ Requires-Dist: urllib3 (>=2.2.2,<3.0.0)
43
38
  Requires-Dist: xlrd (>=2.0.1,<3.0.0)
44
39
  Requires-Dist: xlsxwriter (>=3.1)
45
40
  Description-Content-Type: text/x-rst
@@ -47,28 +42,28 @@ Description-Content-Type: text/x-rst
47
42
  mergeron: Merger Policy Analysis using Python
48
43
  =============================================
49
44
 
50
- Analyze the sets of mergers conforming to concentration and diversion ratio bounds. Analyze 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 impled 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.
45
+ Analyze the sets of mergers conforming to concentration and diversion ratio bounds. Analyze 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.
51
46
 
52
- Intrinsic enforcement rates and intrinsice clearance rates are distinguished from *observed* clearance and enforcement rates in that the former are derived from analyzing theorectical predictions regarding firm conduct against enforcement thresholds, treating enforcement policy as exogenous to firm conduct. 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 enforement rate.
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.
53
48
 
54
49
  Introduction
55
50
  ------------
56
51
 
57
- Module :code:`mergeron.core.guidelines_boundaries` includes classes for specifying concentration bounds (:code:`mergeron.core.guidelines_boundaries.ConcentrationBoundary`) and diversion-ratio bounds (:code:`mergeron.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 concentation and diversion-ratio boundaries, and functions for mapping GUPPI standards to concentration (ΔHHI) standards, and vice-versa.
52
+ Module :code:`mergeron.core.guidelines_boundaries` includes classes for specifying concentration bounds (:code:`mergeron.core.guidelines_boundaries.ConcentrationBoundary`) and diversion-ratio bounds (:code:`mergeron.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.
58
53
 
59
- Module :code:`mergeron.gen.market_sample` includes the :code:`mergeron.gen.market_sample.MarketSample` with methods for, (i) generating sample data under a rich specification of shares, diversion ratios, margins, prices, and HSR filing requirements, and (ii) for estimating enforcement or clearance rates under specified enforcement regimes given a method of aggregating diversion ratio or GUPPI estimates for the firms in a merger. Notably. share are genarated not just for markets with a fixed number of firms, but for markets with multiple firm-count weights, which may be left unspecified or explicitly specified.
54
+ Module :code:`mergeron.gen.market_sample` includes the :code:`mergeron.gen.market_sample.MarketSample` with methods for, (i) generating sample data under a rich specification of shares, diversion ratios, margins, prices, and HSR filing requirements, and (ii) for estimating enforcement or clearance rates under specified enforcement regimes given a method of aggregating diversion ratio or GUPPI estimates for the firms in a merger. Notably. share are generated not just for markets with a fixed number of firms, but for markets with multiple firm-count weights, which may be left unspecified or explicitly specified.
60
55
 
61
- Unless otherwise specified, 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, with specified shape parameters (see :code:`mergeron.gen.ShareContants`. When drawing shares from the Dirichlet distribution, the user passes, using :code:`mergeron.gen.MarketSpec.ShareSpec.firm_count_weights`, 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 :code:`mergeron.gen.MarketSpec.ShareSpec.firm_count_weights` is not assigned a value when defining :code:`mergeron.gen.MarketSpec.ShareSpec` (which has type, :code:`mergeron.gen.ShareSpec`), the default values is used, with results in a sample of markets with 2 to 6 firms with equal relative frequency.
56
+ Unless otherwise specified, 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, with specified shape parameters (see :code:`mergeron.gen.ShareConstants`. When drawing shares from the Dirichlet distribution, the user passes, using :code:`mergeron.gen.MarketSpec.ShareSpec.firm_count_weights`, 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 :code:`mergeron.gen.MarketSpec.ShareSpec.firm_count_weights` is not assigned a value when defining :code:`mergeron.gen.MarketSpec.ShareSpec` (which has type, :code:`mergeron.gen.ShareSpec`), the default values is used, with results in a sample of markets with 2 to 6 firms with equal relative frequency.
62
57
 
63
- Recapture rates can be specifed as, "proportional", "inside-out", "outside-in" (see :code:`mergeron.RECConstants`. The "inside-out" specification results in recapture ratios consistent with merging-firms' in-market shares and a default recapture rate. The "outside-in" specification yields diversion ratios from purchase probabilities drawn at random for :math:`N+1` goods, from which are derived market shares and recapture rates for the :math:`N` goods in the putative market (see, :code:`mergeron.gen.DiversionRatioSpec`). The "outside-in" specification is invalid when the distribution of markets over firm-count is unspecified, i.e., when :code:`mergeron.gen.MarketSpec.ShareSpec.dist_type ==`:code:`mergeron.gen.ShareContants.UNI`.
58
+ Recapture rates can be specified as, "proportional", "inside-out", "outside-in" (see :code:`mergeron.RECConstants`. The "inside-out" specification results in recapture ratios consistent with merging-firms' in-market shares and a default recapture rate. The "outside-in" specification yields diversion ratios from purchase probabilities drawn at random for :math:`N+1` goods, from which are derived market shares and recapture rates for the :math:`N` goods in the putative market (see, :code:`mergeron.gen.DiversionRatioSpec`). The "outside-in" specification is invalid when the distribution of markets over firm-count is unspecified, i.e., when :code:`mergeron.gen.MarketSpec.ShareSpec.dist_type ==`:code:`mergeron.gen.ShareConstants.UNI`.
64
59
 
65
- Price-cost-margins may be specified as having uniform distribution, Beta distribution (including a bounded Beta distribution with specified mean and variance), or an empirical distribution. The 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 may be specified as symmetric, i.i.d., or subject to equilibrium conditions for (profit-mazimization in) Bertrand-Nash oligopoly with MNL demand (see, :code:`mergeron.gen.PCMSpec`).
60
+ Price-cost-margins may be specified as having uniform distribution, Beta distribution (including a bounded Beta distribution with specified mean and variance), or an empirical distribution. The 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 may be specified as symmetric, i.i.d., or subject to equilibrium conditions for (profit-maximization in) Bertrand-Nash oligopoly with MNL demand (see, :code:`mergeron.gen.PCMSpec`).
66
61
 
67
62
  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:`mergeron.gen.PriceSpec`).
68
63
 
69
64
  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 HSR filing threshold for the smaller (acquired) firm. In the other, the :math:`n`-th firm's size matches the size requirement for the smaller merging firm (see, :code:`mergeron.gen.SSZConstants`). 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.
70
65
 
71
- The full specification of a market sample is given in a :code:`mergeron.gen.market_sample.MarketSample` object, including the above parameters. Data are drawn by invoking :code:`mergeron.gen.market_sample.MarketSample.generate_sample` which adds a :code:`data` property of class, :code:`mergeron.gen.MarketDataSample`. Enforcement or clearance counts are computed by invoking :code:`mergeron.gen.market_sample.MarketSample.estimate_enf_counts`, which adds an :code:`enf_counts` property of class :code:`mergeron.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:`estimate_enf_counts` on a :code:`mergeron.gen.market_sample.MarketSample` object without first invoking :code:`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 perfomance penalty is slight, but can be considerable if saving to SATA storage).
66
+ The full specification of a market sample is given in a :code:`mergeron.gen.market_sample.MarketSample` object, including the above parameters. Data are drawn by invoking :code:`mergeron.gen.market_sample.MarketSample.generate_sample` which adds a :code:`data` property of class, :code:`mergeron.gen.MarketDataSample`. Enforcement or clearance counts are computed by invoking :code:`mergeron.gen.market_sample.MarketSample.estimate_enf_counts`, which adds an :code:`enf_counts` property of class :code:`mergeron.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:`estimate_enf_counts` on a :code:`mergeron.gen.market_sample.MarketSample` object without first invoking :code:`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).
72
67
 
73
68
  Enforcement statistics based on FTC investigations data and test data are printed to screen or rendered to LaTex files (for processing into publication-quality tables) using methods provided in :code:`mergeron.gen.enforcement_stats`.
74
69
 
@@ -88,29 +83,6 @@ Documentation for this package is in the form of the API Reference. Documentatio
88
83
 
89
84
  help(market_sample.MarketSample)
90
85
 
91
- "Extras" Subpackage
92
- ---------------------
93
-
94
- The "Extras" sub-package includes a small number of modules potentially useful to users, but which do not implement the principal functions of the package, and are hence considered "extras" or "external" modules. One of these modules is, in fact, repackaged here although published independently.
95
-
96
- On of the external modules provides methods for estimating confidence intervals for proportions and for contrasts (differences) in proportions. This module improve is coded for conformance to the literature and to results from the corresponding modules in :code:`R`. Although written from scratch, the APIs implemented in the module included here are designed for consistency with the APIs in, :code:`statsmodels.stats.proportion` from the package, :code:`statsmodels` (https://pypi.org/project/statsmodels/). To access these directly:
97
-
98
- .. code-block:: python
99
-
100
- import mergeron.ext.proportions_tests as prci
101
-
102
- Module :code:`mergeron.ext.xlsxw_helper` is useful for writing highly formatted output to spreadsheets with xlsx format. The class, :code:`mergeron.ext.xlsxw_helper.CFmt` and function, :code:`mergeron.ext.xlsxw_helper.array_to_sheet` are of particular interest, and can be accessed as :code:`xlh.CFmt` and :code:`xlh.array_to_sheet` with the following import:
103
-
104
- .. code-block:: python
105
-
106
- import mergeron.ext.xlsxw_helper as xlsxw_helper
107
-
108
- A recent version of Paul Tol's python module, :code:`tol_colors.py`, which provides high-contrast color schemes for making displays with improved visibility for individuals with color-blindness, is redistributed within this package. Other than re-formatting and type annotation, the :code:`mergeron.ext.tol_colors` module is re-distributed as downloaded from, https://personal.sron.nl/~pault/data/tol_colors.py. The :code:`tol_colors.py` module is distributed under the Standard 3-clause BSD license. To access the :code:`mergeron.ext.tol_colors` module directly:
109
-
110
- .. code-block:: python
111
-
112
- import mergeron.ext.tol_colors as ptc
113
-
114
86
  .. image:: https://img.shields.io/endpoint?url=https://python-poetry.org/badge/v0.json
115
87
  :alt: Poetry
116
88
  :target: https://python-poetry.org/
@@ -1,28 +1,28 @@
1
1
  mergeron: Merger Policy Analysis using Python
2
2
  =============================================
3
3
 
4
- Analyze the sets of mergers conforming to concentration and diversion ratio bounds. Analyze 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 impled 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.
4
+ Analyze the sets of mergers conforming to concentration and diversion ratio bounds. Analyze 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
5
 
6
- Intrinsic enforcement rates and intrinsice clearance rates are distinguished from *observed* clearance and enforcement rates in that the former are derived from analyzing theorectical predictions regarding firm conduct against enforcement thresholds, treating enforcement policy as exogenous to firm conduct. 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 enforement rate.
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
7
 
8
8
  Introduction
9
9
  ------------
10
10
 
11
- Module :code:`mergeron.core.guidelines_boundaries` includes classes for specifying concentration bounds (:code:`mergeron.core.guidelines_boundaries.ConcentrationBoundary`) and diversion-ratio bounds (:code:`mergeron.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 concentation and diversion-ratio boundaries, and functions for mapping GUPPI standards to concentration (ΔHHI) standards, and vice-versa.
11
+ Module :code:`mergeron.core.guidelines_boundaries` includes classes for specifying concentration bounds (:code:`mergeron.core.guidelines_boundaries.ConcentrationBoundary`) and diversion-ratio bounds (:code:`mergeron.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
12
 
13
- Module :code:`mergeron.gen.market_sample` includes the :code:`mergeron.gen.market_sample.MarketSample` with methods for, (i) generating sample data under a rich specification of shares, diversion ratios, margins, prices, and HSR filing requirements, and (ii) for estimating enforcement or clearance rates under specified enforcement regimes given a method of aggregating diversion ratio or GUPPI estimates for the firms in a merger. Notably. share are genarated not just for markets with a fixed number of firms, but for markets with multiple firm-count weights, which may be left unspecified or explicitly specified.
13
+ Module :code:`mergeron.gen.market_sample` includes the :code:`mergeron.gen.market_sample.MarketSample` with methods for, (i) generating sample data under a rich specification of shares, diversion ratios, margins, prices, and HSR filing requirements, and (ii) for estimating enforcement or clearance rates under specified enforcement regimes given a method of aggregating diversion ratio or GUPPI estimates for the firms in a merger. Notably. share are generated not just for markets with a fixed number of firms, but for markets with multiple firm-count weights, which may be left unspecified or explicitly specified.
14
14
 
15
- Unless otherwise specified, 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, with specified shape parameters (see :code:`mergeron.gen.ShareContants`. When drawing shares from the Dirichlet distribution, the user passes, using :code:`mergeron.gen.MarketSpec.ShareSpec.firm_count_weights`, 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 :code:`mergeron.gen.MarketSpec.ShareSpec.firm_count_weights` is not assigned a value when defining :code:`mergeron.gen.MarketSpec.ShareSpec` (which has type, :code:`mergeron.gen.ShareSpec`), the default values is used, with results in a sample of markets with 2 to 6 firms with equal relative frequency.
15
+ Unless otherwise specified, 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, with specified shape parameters (see :code:`mergeron.gen.ShareConstants`. When drawing shares from the Dirichlet distribution, the user passes, using :code:`mergeron.gen.MarketSpec.ShareSpec.firm_count_weights`, 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 :code:`mergeron.gen.MarketSpec.ShareSpec.firm_count_weights` is not assigned a value when defining :code:`mergeron.gen.MarketSpec.ShareSpec` (which has type, :code:`mergeron.gen.ShareSpec`), the default values is used, with results in a sample of markets with 2 to 6 firms with equal relative frequency.
16
16
 
17
- Recapture rates can be specifed as, "proportional", "inside-out", "outside-in" (see :code:`mergeron.RECConstants`. The "inside-out" specification results in recapture ratios consistent with merging-firms' in-market shares and a default recapture rate. The "outside-in" specification yields diversion ratios from purchase probabilities drawn at random for :math:`N+1` goods, from which are derived market shares and recapture rates for the :math:`N` goods in the putative market (see, :code:`mergeron.gen.DiversionRatioSpec`). The "outside-in" specification is invalid when the distribution of markets over firm-count is unspecified, i.e., when :code:`mergeron.gen.MarketSpec.ShareSpec.dist_type ==`:code:`mergeron.gen.ShareContants.UNI`.
17
+ Recapture rates can be specified as, "proportional", "inside-out", "outside-in" (see :code:`mergeron.RECConstants`. The "inside-out" specification results in recapture ratios consistent with merging-firms' in-market shares and a default recapture rate. The "outside-in" specification yields diversion ratios from purchase probabilities drawn at random for :math:`N+1` goods, from which are derived market shares and recapture rates for the :math:`N` goods in the putative market (see, :code:`mergeron.gen.DiversionRatioSpec`). The "outside-in" specification is invalid when the distribution of markets over firm-count is unspecified, i.e., when :code:`mergeron.gen.MarketSpec.ShareSpec.dist_type ==`:code:`mergeron.gen.ShareConstants.UNI`.
18
18
 
19
- Price-cost-margins may be specified as having uniform distribution, Beta distribution (including a bounded Beta distribution with specified mean and variance), or an empirical distribution. The 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 may be specified as symmetric, i.i.d., or subject to equilibrium conditions for (profit-mazimization in) Bertrand-Nash oligopoly with MNL demand (see, :code:`mergeron.gen.PCMSpec`).
19
+ Price-cost-margins may be specified as having uniform distribution, Beta distribution (including a bounded Beta distribution with specified mean and variance), or an empirical distribution. The 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 may be specified as symmetric, i.i.d., or subject to equilibrium conditions for (profit-maximization in) Bertrand-Nash oligopoly with MNL demand (see, :code:`mergeron.gen.PCMSpec`).
20
20
 
21
21
  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:`mergeron.gen.PriceSpec`).
22
22
 
23
23
  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 HSR filing threshold for the smaller (acquired) firm. In the other, the :math:`n`-th firm's size matches the size requirement for the smaller merging firm (see, :code:`mergeron.gen.SSZConstants`). 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.
24
24
 
25
- The full specification of a market sample is given in a :code:`mergeron.gen.market_sample.MarketSample` object, including the above parameters. Data are drawn by invoking :code:`mergeron.gen.market_sample.MarketSample.generate_sample` which adds a :code:`data` property of class, :code:`mergeron.gen.MarketDataSample`. Enforcement or clearance counts are computed by invoking :code:`mergeron.gen.market_sample.MarketSample.estimate_enf_counts`, which adds an :code:`enf_counts` property of class :code:`mergeron.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:`estimate_enf_counts` on a :code:`mergeron.gen.market_sample.MarketSample` object without first invoking :code:`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 perfomance penalty is slight, but can be considerable if saving to SATA storage).
25
+ The full specification of a market sample is given in a :code:`mergeron.gen.market_sample.MarketSample` object, including the above parameters. Data are drawn by invoking :code:`mergeron.gen.market_sample.MarketSample.generate_sample` which adds a :code:`data` property of class, :code:`mergeron.gen.MarketDataSample`. Enforcement or clearance counts are computed by invoking :code:`mergeron.gen.market_sample.MarketSample.estimate_enf_counts`, which adds an :code:`enf_counts` property of class :code:`mergeron.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:`estimate_enf_counts` on a :code:`mergeron.gen.market_sample.MarketSample` object without first invoking :code:`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).
26
26
 
27
27
  Enforcement statistics based on FTC investigations data and test data are printed to screen or rendered to LaTex files (for processing into publication-quality tables) using methods provided in :code:`mergeron.gen.enforcement_stats`.
28
28
 
@@ -42,29 +42,6 @@ Documentation for this package is in the form of the API Reference. Documentatio
42
42
 
43
43
  help(market_sample.MarketSample)
44
44
 
45
- "Extras" Subpackage
46
- ---------------------
47
-
48
- The "Extras" sub-package includes a small number of modules potentially useful to users, but which do not implement the principal functions of the package, and are hence considered "extras" or "external" modules. One of these modules is, in fact, repackaged here although published independently.
49
-
50
- On of the external modules provides methods for estimating confidence intervals for proportions and for contrasts (differences) in proportions. This module improve is coded for conformance to the literature and to results from the corresponding modules in :code:`R`. Although written from scratch, the APIs implemented in the module included here are designed for consistency with the APIs in, :code:`statsmodels.stats.proportion` from the package, :code:`statsmodels` (https://pypi.org/project/statsmodels/). To access these directly:
51
-
52
- .. code-block:: python
53
-
54
- import mergeron.ext.proportions_tests as prci
55
-
56
- Module :code:`mergeron.ext.xlsxw_helper` is useful for writing highly formatted output to spreadsheets with xlsx format. The class, :code:`mergeron.ext.xlsxw_helper.CFmt` and function, :code:`mergeron.ext.xlsxw_helper.array_to_sheet` are of particular interest, and can be accessed as :code:`xlh.CFmt` and :code:`xlh.array_to_sheet` with the following import:
57
-
58
- .. code-block:: python
59
-
60
- import mergeron.ext.xlsxw_helper as xlsxw_helper
61
-
62
- A recent version of Paul Tol's python module, :code:`tol_colors.py`, which provides high-contrast color schemes for making displays with improved visibility for individuals with color-blindness, is redistributed within this package. Other than re-formatting and type annotation, the :code:`mergeron.ext.tol_colors` module is re-distributed as downloaded from, https://personal.sron.nl/~pault/data/tol_colors.py. The :code:`tol_colors.py` module is distributed under the Standard 3-clause BSD license. To access the :code:`mergeron.ext.tol_colors` module directly:
63
-
64
- .. code-block:: python
65
-
66
- import mergeron.ext.tol_colors as ptc
67
-
68
45
  .. image:: https://img.shields.io/endpoint?url=https://python-poetry.org/badge/v0.json
69
46
  :alt: Poetry
70
47
  :target: https://python-poetry.org/
@@ -13,7 +13,7 @@ keywords = [
13
13
  "upward pricing pressure",
14
14
  "GUPPI",
15
15
  ]
16
- version = "2024.739097.3"
16
+ version = "2024.739099.0"
17
17
 
18
18
  # Classifiers list: https://pypi.org/classifiers/
19
19
  classifiers = [
@@ -30,6 +30,11 @@ classifiers = [
30
30
  "Programming Language :: Python :: Implementation :: CPython",
31
31
  ]
32
32
 
33
+ [build-system]
34
+ requires = ["poetry-core"]
35
+ build-backend = "poetry.core.masonry.api"
36
+
37
+
33
38
  [tool.poetry.dependencies]
34
39
  # You may need to apply the fixes in, https://github.com/python-poetry/poetry/issues/3365
35
40
  # if poetry dependency resolution appears to hang (read the page at link to the end)
@@ -39,32 +44,29 @@ bs4 = ">=0.0.1"
39
44
  google-re2 = ">=1.1"
40
45
  jinja2 = ">=3.1"
41
46
  joblib = ">=1.3"
42
- lxml = ">=5.0"
43
47
  matplotlib = ">=3.8"
44
48
  mpmath = ">=1.3"
45
49
  msgpack = ">=1.0"
46
50
  msgpack-numpy = ">=0.4"
47
- numpy = ">=1.26, <2.0"
48
- openpyxl = ">=3.1.2"
51
+ numpy = ">=1.26, <2"
49
52
  python = "^3.12"
50
- requests = ">=2.31"
51
53
  scipy = ">=1.12"
52
54
  sympy = ">=1.12"
53
55
  tables = ">=3.8"
54
56
  xlsxwriter = ">=3.1"
55
57
  certifi = ">=2023.11.17"
56
- requests-toolbelt = ">=1.0.0"
57
- types-requests = ">=2.31.0"
58
58
  types-beautifulsoup4 = ">=4.11.2"
59
59
  xlrd = "^2.0.1" # Needed to read margin data
60
- poetry-plugin-export = "^1.8.0"
60
+ urllib3 = "^2.2.2"
61
61
 
62
62
 
63
63
  [tool.poetry.group.dev.dependencies]
64
64
  icecream = ">=2.1.0"
65
65
  mypy = ">=1.8"
66
+ openpyxl = ">=3.1.2"
66
67
  pendulum = ">=3.0.0"
67
68
  ruff = ">=0.5"
69
+ poetry-plugin-export = "^1.8.0"
68
70
  pytest = ">=8.0"
69
71
  semver = ">=3.0"
70
72
  sphinx = ">=7.2"
@@ -74,11 +76,6 @@ sphinx-immaterial = ">=0.11"
74
76
  pipdeptree = ">=2.15.1"
75
77
  types-openpyxl = ">=3.0.0"
76
78
 
77
- [build-system]
78
- requires = ["poetry-core"]
79
- build-backend = "poetry.core.masonry.api"
80
-
81
-
82
79
  [tool.ruff]
83
80
 
84
81
  # Exclude a variety of commonly ignored directories.
@@ -7,7 +7,7 @@ import numpy as np
7
7
 
8
8
  _PKG_NAME: str = Path(__file__).parent.stem
9
9
 
10
- VERSION = "2024.739097.3"
10
+ VERSION = "2024.739099.0"
11
11
 
12
12
  __version__ = VERSION
13
13
 
@@ -56,7 +56,7 @@ MGNDATA_ARCHIVE_PATH = DATA_DIR / "damodaran_margin_data_dict.msgpack"
56
56
  u3pm = urllib3.PoolManager()
57
57
 
58
58
 
59
- def mgn_data_getter(
59
+ def mgn_data_getter( # noqa: PLR0912
60
60
  _table_name: str = "margin",
61
61
  *,
62
62
  data_archive_path: Path | None = None,
@@ -20,7 +20,7 @@ import msgpack # type: ignore
20
20
  import msgpack_numpy as m # type: ignore
21
21
  import numpy as np
22
22
  import re2 as re # type: ignore
23
- import requests
23
+ import urllib3
24
24
  from bs4 import BeautifulSoup
25
25
  from numpy.testing import assert_array_equal
26
26
  from numpy.typing import NDArray
@@ -705,25 +705,32 @@ def _download_invdata(_dl_path: Path = FTCDATA_DIR) -> tuple[str, ...]:
705
705
  return _invdata_docnames
706
706
 
707
707
  _invdata_docnames_dl: tuple[str, ...] = ()
708
+ _u3pm = urllib3.PoolManager()
709
+ _chunk_size = 1024 * 1024
708
710
  for _invdata_homepage_url in _invdata_homepage_urls:
709
- _invdata_soup = BeautifulSoup(
710
- requests.get(_invdata_homepage_url, verify=True, timeout=60).text,
711
- "html.parser",
712
- )
713
- _invdata_attrs = [
714
- (_g.get("title", ""), _g.get("href", ""))
715
- for _g in _invdata_soup.find_all("a")
716
- if _g.get("title", "") and _g.get("href", "").endswith(".pdf")
717
- ]
711
+ with _u3pm.request(
712
+ "GET", _invdata_homepage_url, preload_content=False
713
+ ) as _u3handle:
714
+ _invdata_soup = BeautifulSoup(_u3handle.data, "html.parser")
715
+ _invdata_attrs = [
716
+ (_g.get("title", ""), _g.get("href", ""))
717
+ for _g in _invdata_soup.find_all("a")
718
+ if _g.get("title", "") and _g.get("href", "").endswith(".pdf")
719
+ ]
718
720
  for _invdata_attr in _invdata_attrs:
719
721
  _invdata_docname, _invdata_link = _invdata_attr
720
722
  _invdata_docnames_dl += (_invdata_docname,)
721
- with _dl_path.joinpath(_invdata_docname).open("wb") as _invdata_fh:
722
- _invdata_fh.write(
723
- requests.get(
724
- f"https://www.ftc.gov/{_invdata_link}", verify=True, timeout=60
725
- ).content
726
- )
723
+ with (
724
+ _u3pm.request(
725
+ "GET", f"https://www.ftc.gov/{_invdata_link}", preload_content=False
726
+ ) as _urlopen_handle,
727
+ _dl_path.joinpath(_invdata_docname).open("wb") as _invdata_fh,
728
+ ):
729
+ while True:
730
+ _data = _urlopen_handle.read(_chunk_size)
731
+ if not _data:
732
+ break
733
+ _invdata_fh.write(_data)
727
734
 
728
735
  return _invdata_docnames_dl
729
736
 
@@ -315,7 +315,7 @@ def shrratio_boundary_wtd_avg(
315
315
  # initial conditions
316
316
  _gbdry_points = [(_s_mid, _s_mid)]
317
317
  _s_1_pre, _s_2_pre = _s_mid, _s_mid
318
- _s_2_oddval, _s_2_oddsum, _s_2_evnsum = True, 0, 0
318
+ _s_2_oddval, _s_2_oddsum, _s_2_evnsum = True, 0.0, 0.0
319
319
 
320
320
  # parameters for iteration
321
321
  _gbd_step_sz = mp.power(10, -prec)
@@ -91,8 +91,8 @@ def hhi_delta_boundary_qdtr(_dh_val: float = 0.01, /) -> GuidelinesBoundaryCalla
91
91
 
92
92
  _hhi_eqn = _s_2 - 0.01 / (2 * _s_1)
93
93
 
94
- _hhi_bdry = solve(_hhi_eqn, _s_2)[0] # type: ignore
95
- _s_nought = float(solve(_hhi_eqn.subs({_s_2: 1 - _s_1}), _s_1)[0]) # type: ignore
94
+ _hhi_bdry = solve(_hhi_eqn, _s_2)[0]
95
+ _s_nought = float(solve(_hhi_eqn.subs({_s_2: 1 - _s_1}), _s_1)[0])
96
96
 
97
97
  _hhi_bdry_area = 2 * (
98
98
  _s_nought
@@ -154,7 +154,7 @@ def shrratio_boundary_qdtr_wtd_avg(
154
154
  - (_s_1 + _s_2) * _delta_star
155
155
  )
156
156
 
157
- _bdry_func = solve(_bdry_eqn, _s_2)[0] # type: ignore
157
+ _bdry_func = solve(_bdry_eqn, _s_2)[0]
158
158
  _s_naught = (
159
159
  float(solve(simplify(_bdry_eqn.subs({_s_2: 1 - _s_1})), _s_1)[0]) # type: ignore
160
160
  if recapture_form == "inside-out"
@@ -184,7 +184,7 @@ def shrratio_boundary_qdtr_wtd_avg(
184
184
  - (_s_1 + _s_2) * _d_star
185
185
  )
186
186
 
187
- _bdry_func = solve(_bdry_eqn, _s_2)[1] # type: ignore
187
+ _bdry_func = solve(_bdry_eqn, _s_2)[1]
188
188
  _bdry_area = float(
189
189
  2
190
190
  * (
@@ -212,7 +212,7 @@ def shrratio_boundary_qdtr_wtd_avg(
212
212
  - _delta_star
213
213
  )
214
214
 
215
- _bdry_func = solve(_bdry_eqn, _s_2)[0] # type: ignore
215
+ _bdry_func = solve(_bdry_eqn, _s_2)[0]
216
216
  _bdry_area = float(
217
217
  2 * (mp.quad(lambdify(_s_1, _bdry_func, "mpmath"), (0, _s_mid)))
218
218
  - _s_mid**2
@@ -271,7 +271,7 @@ def shrratio_boundary_distance(
271
271
  # initial conditions
272
272
  _gbdry_points = [(_s_mid, _s_mid)]
273
273
  _s_1_pre, _s_2_pre = _s_mid, _s_mid
274
- _s_2_oddval, _s_2_oddsum, _s_2_evnsum = True, 0, 0
274
+ _s_2_oddval, _s_2_oddsum, _s_2_evnsum = True, 0.0, 0.0
275
275
 
276
276
  # parameters for iteration
277
277
  _weights_base = (mpf("0.5"),) * 2
@@ -378,4 +378,3 @@ def shrratio_boundary_distance(
378
378
  np.vstack((np.flip(_gbdry_points, 0), np.flip(_gbdry_points[1:], 1))),
379
379
  round(float(_gbdry_area_total), prec),
380
380
  )
381
-
@@ -1,3 +0,0 @@
1
- from .. import VERSION # noqa: TID252
2
-
3
- __version__ = VERSION