mergeron 2024.738940.0__py3-none-any.whl → 2024.738949.0__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/core/excel_helper.py +38 -25
- mergeron/core/ftc_merger_investigations_data.py +33 -30
- mergeron/core/{guidelines_standards.py → guidelines_boundaries.py} +35 -29
- mergeron/core/proportions_tests.py +12 -10
- mergeron/examples/concentration_as_diversion.py +30 -26
- mergeron/examples/{safeharbor_boundaries_for_mergers_with_asymmetric_shares.py → enforcement_boundaries_for_mergers_with_asymmetric_shares.py} +84 -90
- mergeron/examples/{safeharbor_boundaries_for_symmetric_firm_mergers.py → enforcement_boundaries_for_symmetric_firm_mergers.py} +3 -3
- mergeron/examples/guidelines_enforcement_patterns.py +18 -16
- mergeron/examples/investigations_stats_obs_tables.py +15 -14
- mergeron/examples/investigations_stats_sim_tables.py +49 -54
- mergeron/examples/plotSafeHarbs_symbolically.py +1 -1
- mergeron/examples/sound_guppi_safeharbor.py +59 -54
- mergeron/examples/summarize_ftc_investigations_data.py +4 -4
- mergeron/examples/visualize_empirical_margin_distribution.py +2 -2
- mergeron/examples/visualize_guidelines_tests.py +67 -65
- mergeron/gen/__init__.py +104 -42
- mergeron/gen/_data_generation_functions_nonpublic.py +6 -6
- mergeron/gen/data_generation.py +1 -4
- mergeron/gen/investigations_stats.py +21 -27
- mergeron/gen/{guidelines_tests.py → upp_tests.py} +98 -102
- {mergeron-2024.738940.0.dist-info → mergeron-2024.738949.0.dist-info}/METADATA +2 -5
- mergeron-2024.738949.0.dist-info/RECORD +42 -0
- {mergeron-2024.738940.0.dist-info → mergeron-2024.738949.0.dist-info}/WHEEL +1 -1
- mergeron-2024.738940.0.dist-info/RECORD +0 -42
|
@@ -32,7 +32,7 @@ from numpy import pi
|
|
|
32
32
|
from xlsxwriter import Workbook
|
|
33
33
|
|
|
34
34
|
import mergeron.core.excel_helper as xlh
|
|
35
|
-
import mergeron.core.
|
|
35
|
+
import mergeron.core.guidelines_boundaries as gbl
|
|
36
36
|
import mergeron.ext.tol_colors as ptcolor
|
|
37
37
|
from mergeron import DATA_DIR
|
|
38
38
|
|
|
@@ -46,20 +46,20 @@ BDRY_SPECS_DICT: Mapping[str, Mapping[str, Any]] = {
|
|
|
46
46
|
"title_str": "ΔHHI boundary",
|
|
47
47
|
"sheet_name": "ΔHHI",
|
|
48
48
|
"func_str": R"\Delta HHI",
|
|
49
|
-
"func":
|
|
49
|
+
"func": gbl.delta_hhi_boundary,
|
|
50
50
|
},
|
|
51
51
|
"OSWAG Own-shr-wtd Div Ratio Index": {
|
|
52
52
|
"title_str": "Aggregated-diversion-ratio boundary, own-share wtd. avg.",
|
|
53
53
|
"sheet_name": "OSWAG, wtd avg",
|
|
54
54
|
"func_str": R"(s_1 d_{12} + s_2 d_{21}) / s_M",
|
|
55
|
-
"func":
|
|
55
|
+
"func": gbl.shrratio_boundary_wtd_avg,
|
|
56
56
|
"func_kwargs": {"wgtng_policy": "own-share", "recapture_spec": RECAPTURE_SPEC},
|
|
57
57
|
},
|
|
58
58
|
"OSWAG Own-shr-wtd Div Ratio Distance": {
|
|
59
59
|
"title_str": "Aggregated-diversion-ratio boundary, own-shr. wtd. distance",
|
|
60
60
|
"sheet_name": "OSWAG, distance",
|
|
61
61
|
"func_str": R"\surd (s_1 d_{12}^2 / s_M + s_2 d_{21}^2 / s_M)",
|
|
62
|
-
"func":
|
|
62
|
+
"func": gbl.shrratio_boundary_wtd_avg,
|
|
63
63
|
"func_kwargs": {
|
|
64
64
|
"wgtng_policy": "own-share",
|
|
65
65
|
"recapture_spec": RECAPTURE_SPEC,
|
|
@@ -70,20 +70,20 @@ BDRY_SPECS_DICT: Mapping[str, Mapping[str, Any]] = {
|
|
|
70
70
|
"title_str": "Aggregated-diversion-ratio boundary, minimum",
|
|
71
71
|
"sheet_name": "OSWAG, minimum",
|
|
72
72
|
"func_str": R"\min (d_{12}, d_{21})",
|
|
73
|
-
"func":
|
|
73
|
+
"func": gbl.shrratio_boundary_min,
|
|
74
74
|
"func_kwargs": {"recapture_spec": RECAPTURE_SPEC},
|
|
75
75
|
},
|
|
76
76
|
"SAG Combined Share": {
|
|
77
77
|
"title_str": "Combined Share boundary",
|
|
78
78
|
"sheet_name": "SAG, combined-share",
|
|
79
79
|
"func_str": R"s_M",
|
|
80
|
-
"func":
|
|
80
|
+
"func": gbl.combined_share_boundary,
|
|
81
81
|
},
|
|
82
82
|
"SAG Div Ratio Distance": {
|
|
83
83
|
"title_str": "Aggregated-diversion-ratio boundary, distance",
|
|
84
84
|
"sheet_name": "SAG, distance",
|
|
85
85
|
"func_str": R"\surd (d_{12}^2 / 2 + d_{21}^2 / 2)",
|
|
86
|
-
"func":
|
|
86
|
+
"func": gbl.shrratio_boundary_wtd_avg,
|
|
87
87
|
"func_kwargs": {
|
|
88
88
|
"wgtng_policy": None,
|
|
89
89
|
"recapture_spec": RECAPTURE_SPEC,
|
|
@@ -94,20 +94,20 @@ BDRY_SPECS_DICT: Mapping[str, Mapping[str, Any]] = {
|
|
|
94
94
|
"title_str": "Aggregated-diversion-ratio boundary, simple average",
|
|
95
95
|
"sheet_name": "SAG, average",
|
|
96
96
|
"func_str": R"(d_{12} + d_{21}) / 2",
|
|
97
|
-
"func":
|
|
97
|
+
"func": gbl.shrratio_boundary_xact_avg,
|
|
98
98
|
"func_kwargs": {"recapture_spec": RECAPTURE_SPEC},
|
|
99
99
|
},
|
|
100
100
|
"CPSWAG Premerger HHI-contribution": {
|
|
101
101
|
"title_str": "Premerger HHI-contribution boundary",
|
|
102
102
|
"sheet_name": "CPSWAG, HHI-contrib-pre",
|
|
103
103
|
"func_str": R"HHI_M^{pre}",
|
|
104
|
-
"func":
|
|
104
|
+
"func": gbl.hhi_pre_contrib_boundary,
|
|
105
105
|
},
|
|
106
106
|
"CPSWAG Cross-product-shr-wtd Div Ratio Index": {
|
|
107
107
|
"title_str": "Aggregated-diversion-ratio boundary, cross-product-share wtd. avg.",
|
|
108
108
|
"sheet_name": "CPSWAG, wtd avg",
|
|
109
109
|
"func_str": R"(s_2 d_{12} / s_M + s_1 d_{21} / s_M)",
|
|
110
|
-
"func":
|
|
110
|
+
"func": gbl.shrratio_boundary_wtd_avg,
|
|
111
111
|
"func_kwargs": {
|
|
112
112
|
"wgtng_policy": "cross-product-share",
|
|
113
113
|
"recapture_spec": RECAPTURE_SPEC,
|
|
@@ -117,7 +117,7 @@ BDRY_SPECS_DICT: Mapping[str, Mapping[str, Any]] = {
|
|
|
117
117
|
"title_str": "Aggregated-diversion-ratio boundary, cross-prod-shr. wtd. distance",
|
|
118
118
|
"sheet_name": "CPSWAG, distance",
|
|
119
119
|
"func_str": R"\surd (s_2 d_{12}^2 / s_M + s_1 d_{21}^2 / s_M)",
|
|
120
|
-
"func":
|
|
120
|
+
"func": gbl.shrratio_boundary_wtd_avg,
|
|
121
121
|
"func_kwargs": {
|
|
122
122
|
"wgtng_policy": "cross-product-share",
|
|
123
123
|
"recapture_spec": RECAPTURE_SPEC,
|
|
@@ -128,7 +128,7 @@ BDRY_SPECS_DICT: Mapping[str, Mapping[str, Any]] = {
|
|
|
128
128
|
"title_str": "Aggregated-diversion-ratio boundary, maximum",
|
|
129
129
|
"sheet_name": "CPSWAG, maximum",
|
|
130
130
|
"func_str": R"\max (d_{12}, d_{21})",
|
|
131
|
-
"func":
|
|
131
|
+
"func": gbl.shrratio_boundary_max,
|
|
132
132
|
},
|
|
133
133
|
}
|
|
134
134
|
|
|
@@ -142,7 +142,7 @@ def tabulate_boundary_stats(_gpubyr: Literal[1992, 2010, 2023], /) -> None:
|
|
|
142
142
|
are drawn
|
|
143
143
|
|
|
144
144
|
"""
|
|
145
|
-
gso =
|
|
145
|
+
gso = gbl.GuidelinesThresholds(_gpubyr)
|
|
146
146
|
_dhhi_val, _r_val, _g_val = (
|
|
147
147
|
getattr(gso.presumption, _f) for _f in ("delta", "rec", "guppi")
|
|
148
148
|
)
|
|
@@ -200,7 +200,7 @@ def _dhhi_stats(
|
|
|
200
200
|
|
|
201
201
|
_delta_val = _s_mid / (1 - _s_mid)
|
|
202
202
|
if _dhhi_val * 1e4 in (50, 100, 200):
|
|
203
|
-
_delta_val =
|
|
203
|
+
_delta_val = gbl.round_cust(_r_val * _delta_val) / _r_val
|
|
204
204
|
_divr_val = _r_val * _delta_val
|
|
205
205
|
|
|
206
206
|
print(
|
|
@@ -225,7 +225,7 @@ def _dhhi_stats(
|
|
|
225
225
|
def _bdry_stats_col(
|
|
226
226
|
_bdry_spec: str, _dhhi_val: float, _delta_val: float, _r_val: float, /
|
|
227
227
|
) -> tuple[str, str]:
|
|
228
|
-
_dhhi_prob = 2 *
|
|
228
|
+
_dhhi_prob = 2 * gbl.dh_area(_dhhi_val)
|
|
229
229
|
_cs_prob = 2 * _dhhi_val
|
|
230
230
|
_hhi_m_pre_prob = pi * _dhhi_val / 2
|
|
231
231
|
|
|
@@ -262,11 +262,11 @@ def plot_and_save_boundary_coords(
|
|
|
262
262
|
/,
|
|
263
263
|
layout: Literal["collected", "distributed"] = "collected",
|
|
264
264
|
) -> None:
|
|
265
|
-
gso =
|
|
265
|
+
gso = gbl.GuidelinesThresholds(_gpubyr)
|
|
266
266
|
|
|
267
267
|
_hmg_standards_strings_dict = {
|
|
268
268
|
"distributed": ("presumption", "inferred presumption", "safeharbor"),
|
|
269
|
-
"collected": ("safeharbor", "
|
|
269
|
+
"collected": ("safeharbor", "imputed_presumption", "presumption"),
|
|
270
270
|
}
|
|
271
271
|
_hmg_standards_strings = _hmg_standards_strings_dict.get(layout, ())
|
|
272
272
|
if not _hmg_standards_strings:
|
|
@@ -276,7 +276,7 @@ def plot_and_save_boundary_coords(
|
|
|
276
276
|
)
|
|
277
277
|
|
|
278
278
|
# Initialize plot area
|
|
279
|
-
_plt, _my_fig1, _ax1, _set_axis_def =
|
|
279
|
+
_plt, _my_fig1, _ax1, _set_axis_def = gbl.boundary_plot()
|
|
280
280
|
|
|
281
281
|
_divr_agg_methods = ("OSWAG", "SAG", "CPSWAG")
|
|
282
282
|
|
|
@@ -284,7 +284,7 @@ def plot_and_save_boundary_coords(
|
|
|
284
284
|
_divr_agg_methods, _hmg_standards_strings, strict=True
|
|
285
285
|
):
|
|
286
286
|
_r_bar, _g_bar = (getattr(gso.presumption, _f) for _f in ("rec", "guppi"))
|
|
287
|
-
_dhhi_val = getattr(gso, _hmg_standards_str)
|
|
287
|
+
_dhhi_val = getattr(gso, _hmg_standards_str).delta
|
|
288
288
|
_divr_val = (
|
|
289
289
|
_g_bar
|
|
290
290
|
if _hmg_standards_str == "safeharbor"
|
|
@@ -352,7 +352,7 @@ def plot_and_save_boundary_coords(
|
|
|
352
352
|
|
|
353
353
|
def gen_plot_boundary(
|
|
354
354
|
_bndry_data_dict: Mapping[str, Sequence[tuple[float]]],
|
|
355
|
-
_gso:
|
|
355
|
+
_gso: gbl.GuidelinesThresholds,
|
|
356
356
|
_gs_str: str,
|
|
357
357
|
_bdry_spec: tuple[str, Mapping[str, Any]],
|
|
358
358
|
_ax1: mpa.Axes,
|
|
@@ -366,7 +366,7 @@ def gen_plot_boundary(
|
|
|
366
366
|
_bndry_data_dict
|
|
367
367
|
mapping for storing boundary coordinates for each plotted boundary
|
|
368
368
|
_gso
|
|
369
|
-
|
|
369
|
+
gbl.GuidelinesStandards instance of tuples listing
|
|
370
370
|
concentration standard, default recapture-rate, GUPPI bound,
|
|
371
371
|
and diversion ratio bound for "safeharbor", "weak presumption",
|
|
372
372
|
and "presumption", where "weak presumption" represents an alternative
|
|
@@ -426,17 +426,17 @@ def gen_plot_boundary(
|
|
|
426
426
|
|
|
427
427
|
_bdry_func = _bdry_spec_dict["func"]
|
|
428
428
|
if "Div Ratio" in _bdry_spec_str:
|
|
429
|
-
|
|
429
|
+
_bdry_boundary = _bdry_func(
|
|
430
430
|
_delta_val,
|
|
431
431
|
_r_bar,
|
|
432
432
|
**_bdry_spec_dict.get("func_kwargs", {}), # tupe: ignore
|
|
433
433
|
)
|
|
434
434
|
_plot_label_mag, _plot_label_uom = _r_bar * _delta_val * 1e2, "%"
|
|
435
435
|
elif _bdry_spec_str.endswith("Combined Share"):
|
|
436
|
-
|
|
436
|
+
_bdry_boundary = _bdry_func(2 * _s_mid)
|
|
437
437
|
_plot_label_mag, _plot_label_uom = 2 * _s_mid * 1e2, "%"
|
|
438
438
|
else:
|
|
439
|
-
|
|
439
|
+
_bdry_boundary = _bdry_func(_dhhi_val)
|
|
440
440
|
_plot_label_mag, _plot_label_uom = _dhhi_val * 1e4, " points"
|
|
441
441
|
|
|
442
442
|
_plot_label = R"${0}$ = {1:.{2}f}{3}".format(
|
|
@@ -447,9 +447,13 @@ def gen_plot_boundary(
|
|
|
447
447
|
)
|
|
448
448
|
|
|
449
449
|
_bndry_data_dict |= {
|
|
450
|
-
_bdry_spec_str: (
|
|
450
|
+
_bdry_spec_str: (
|
|
451
|
+
_bdry_spec_dict["sheet_name"],
|
|
452
|
+
_bdry_boundary.coordinates,
|
|
453
|
+
_bdry_boundary.area,
|
|
454
|
+
)
|
|
451
455
|
} # type: ignore
|
|
452
|
-
_bdry_s1, _bdry_s2 = zip(*
|
|
456
|
+
_bdry_s1, _bdry_s2 = zip(*_bdry_boundary.coordinates, strict=True)
|
|
453
457
|
|
|
454
458
|
_ax1.plot(
|
|
455
459
|
_bdry_s1,
|
|
@@ -5,45 +5,44 @@ Draw boundaries for various standards from U.S. Horizontal Merger Guidelines.
|
|
|
5
5
|
|
|
6
6
|
from itertools import product as iterprod
|
|
7
7
|
from pathlib import Path
|
|
8
|
-
from typing import Literal
|
|
8
|
+
from typing import Literal, TypedDict
|
|
9
9
|
|
|
10
10
|
import matplotlib.axis
|
|
11
11
|
from matplotlib import cm as colormgr
|
|
12
12
|
from matplotlib import colormaps
|
|
13
13
|
from matplotlib import colors as mcolors
|
|
14
14
|
from matplotlib.ticker import StrMethodFormatter
|
|
15
|
-
from numpy import
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
array,
|
|
19
|
-
concatenate,
|
|
20
|
-
insert,
|
|
21
|
-
rad2deg,
|
|
22
|
-
round,
|
|
23
|
-
sqrt,
|
|
24
|
-
vstack,
|
|
25
|
-
)
|
|
26
|
-
|
|
27
|
-
import mergeron.core.guidelines_standards as gsl
|
|
15
|
+
from numpy import arange, arctan, array, hsplit, insert, rad2deg, round, sqrt, vstack
|
|
16
|
+
|
|
17
|
+
import mergeron.core.guidelines_boundaries as gbl
|
|
28
18
|
from mergeron import DATA_DIR
|
|
29
19
|
|
|
30
20
|
PROG_PATH = Path(__file__)
|
|
31
21
|
|
|
32
22
|
|
|
23
|
+
class _CMAPArgs(TypedDict):
|
|
24
|
+
cmap: mcolors.Colormap
|
|
25
|
+
norm: mcolors.Normalize
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
_color_kwargs = _CMAPArgs(cmap=colormaps["cividis"], norm=mcolors.Normalize(0, 1.0))
|
|
29
|
+
|
|
30
|
+
|
|
33
31
|
def plot_delta_boundaries(
|
|
34
32
|
_guppi_bench_key: str,
|
|
35
|
-
_print_guppi_max_bndry_envs_flag: bool
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
_print_guppi_max_bndry_envs_flag: bool,
|
|
34
|
+
_recapture_spec: Literal["inside-out", "proportional"],
|
|
35
|
+
_color_kwargs: _CMAPArgs = _color_kwargs,
|
|
36
|
+
/,
|
|
38
37
|
):
|
|
39
|
-
|
|
40
|
-
raise ValueError(f"Recapture specification must be one of, {_recspecs!r}")
|
|
38
|
+
_print_guppi_max_bndry_envs_flag = _print_guppi_max_bndry_envs_flag or False
|
|
41
39
|
|
|
42
40
|
print("ΔHHI safeharbor boundary")
|
|
43
|
-
_plt, _my_fig1, _ax1, _ =
|
|
41
|
+
_plt, _my_fig1, _ax1, _ = gbl.boundary_plot()
|
|
44
42
|
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
_hmg_thresholds = get_hmg_thresholds_by_key(_guppi_bench_key)
|
|
44
|
+
_dh_bar, _r_bar, _guppi_bench, _divr_bench = (
|
|
45
|
+
getattr(_hmg_thresholds, _f) for _f in ("delta", "rec", "guppi", "divr")
|
|
47
46
|
)
|
|
48
47
|
|
|
49
48
|
print("Contour map of selected ∆HHI boundaries")
|
|
@@ -52,8 +51,8 @@ def plot_delta_boundaries(
|
|
|
52
51
|
if _dh_bound in (300, 500):
|
|
53
52
|
continue
|
|
54
53
|
|
|
55
|
-
|
|
56
|
-
_dh_dat_x, _dh_dat_y =
|
|
54
|
+
_dh_boundary = gbl.delta_hhi_boundary(_dh_bound / 1e4)
|
|
55
|
+
_dh_dat_x, _dh_dat_y = (_z.T[0] for _z in hsplit(_dh_boundary.coordinates, 2))
|
|
57
56
|
if _dh_bound == 100:
|
|
58
57
|
_lwval, _lsval = 0.75, "-"
|
|
59
58
|
else:
|
|
@@ -69,13 +68,13 @@ def plot_delta_boundaries(
|
|
|
69
68
|
)
|
|
70
69
|
|
|
71
70
|
if _print_guppi_max_bndry_envs_flag:
|
|
72
|
-
_symshr =
|
|
73
|
-
_dstar =
|
|
71
|
+
_symshr = gbl.round_cust(sqrt(_dh_bound / 2e4))
|
|
72
|
+
_dstar = gbl.round_cust(_symshr / (1 - _symshr))
|
|
74
73
|
_m_star = _guppi_bench / (_dstar * _r_bar)
|
|
75
74
|
print(_symshr, _dstar, _m_star, _r_bar, _guppi_bench, "...", end="")
|
|
76
75
|
|
|
77
76
|
_guppi_bdry_env_xs = (0, _symshr, 1)
|
|
78
|
-
if
|
|
77
|
+
if _recapture_spec == "inside-out":
|
|
79
78
|
# ## Plot envelope of GUPPI boundaries with
|
|
80
79
|
# r_k = r_bar if s_k = min(_s_1, _s_2)
|
|
81
80
|
# ## See (s_i, s_j) in equation~(44), or thereabouts, in paper
|
|
@@ -98,39 +97,35 @@ def plot_delta_boundaries(
|
|
|
98
97
|
_guppi_bdry_env_xs[::-1],
|
|
99
98
|
linewidth=0.5,
|
|
100
99
|
linestyle="--",
|
|
101
|
-
color=
|
|
100
|
+
color=_color_kwargs["cmap"](_m_star),
|
|
102
101
|
zorder=3,
|
|
103
102
|
)
|
|
104
|
-
del _symshr, _dstar, _m_star
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
103
|
+
del _symshr, _dstar, _m_star
|
|
104
|
+
|
|
105
|
+
if _recapture_spec == "inside-out" and _dh_bound not in (200, 300, 500):
|
|
106
|
+
_ax1.annotate(
|
|
107
|
+
rf"$\Delta HHI$ = {_dh_bound:,d} pts.",
|
|
108
|
+
xy=(_dh_dat_x[1], _dh_dat_y[1]),
|
|
109
|
+
xytext=(_dh_dat_x[1], _dh_dat_y[1]),
|
|
110
|
+
textcoords="data",
|
|
111
|
+
ha="left",
|
|
112
|
+
va="center",
|
|
113
|
+
fontsize=5,
|
|
114
|
+
zorder=5.1,
|
|
115
|
+
)
|
|
116
|
+
del _guppi_bdry_env_xs
|
|
117
117
|
|
|
118
118
|
if _dh_bound == 100:
|
|
119
119
|
_ax1.fill_between(
|
|
120
|
-
|
|
121
|
-
|
|
120
|
+
_dh_dat_x,
|
|
121
|
+
_dh_dat_y,
|
|
122
122
|
0,
|
|
123
123
|
edgecolor=None,
|
|
124
124
|
facecolor="#64bb64",
|
|
125
125
|
alpha=0.7,
|
|
126
126
|
rasterized=True,
|
|
127
127
|
)
|
|
128
|
-
del (
|
|
129
|
-
_dh_safeharb,
|
|
130
|
-
_dh_prob,
|
|
131
|
-
_dh_dat_x,
|
|
132
|
-
_dh_dat_y,
|
|
133
|
-
) # , _dh_dat_x_pla, _dh_dat_y_pla
|
|
128
|
+
del (_dh_boundary, _dh_dat_x, _dh_dat_y) # , _dh_dat_x_pla, _dh_dat_y_pla
|
|
134
129
|
|
|
135
130
|
_my_fig1.savefig((DATA_DIR / f"{PROG_PATH.stem}_DH100_deltaHHI_only.pdf"), dpi=600)
|
|
136
131
|
|
|
@@ -140,22 +135,23 @@ def plot_delta_boundaries(
|
|
|
140
135
|
def plot_guppi_boundaries( # noqa PLR0915
|
|
141
136
|
_guppi_bench_key: str,
|
|
142
137
|
_pcm_same_flag: bool,
|
|
143
|
-
_recapture_spec: Literal["proportional", "inside-out"]
|
|
138
|
+
_recapture_spec: Literal["proportional", "inside-out"],
|
|
139
|
+
_color_kwargs: _CMAPArgs = _color_kwargs,
|
|
140
|
+
/,
|
|
144
141
|
):
|
|
145
142
|
if recapture_spec not in (_recspecs := ("inside-out", "proportional")):
|
|
146
143
|
raise ValueError(f"Recapture specification must be one of, {_recspecs!r}")
|
|
147
144
|
|
|
148
|
-
|
|
149
|
-
|
|
145
|
+
_hmg_thresholds = get_hmg_thresholds_by_key(_guppi_bench_key)
|
|
146
|
+
_dh_bar, _r_bar, _guppi_bench, _divr_bench = (
|
|
147
|
+
getattr(_hmg_thresholds, _f) for _f in ("delta", "rec", "guppi", "divr")
|
|
150
148
|
)
|
|
151
149
|
|
|
152
150
|
# First we get the data for the ΔHHI benchmark we want to plot
|
|
153
|
-
|
|
154
|
-
_dh_dat_x, _dh_dat_y =
|
|
151
|
+
_dh_boundary = gbl.delta_hhi_boundary(_dh_bar)
|
|
152
|
+
_dh_dat_x, _dh_dat_y = (_z.T[0] for _z in hsplit(_dh_boundary.coordinates, 2))
|
|
155
153
|
|
|
156
|
-
_plt,
|
|
157
|
-
_plt.delaxes(_ax1)
|
|
158
|
-
del _my_fig1, _ax1
|
|
154
|
+
_plt, _, _, _set_axis_def = gbl.boundary_plot()
|
|
159
155
|
|
|
160
156
|
_my_fig1 = _plt.figure(figsize=(5.5, 5.0))
|
|
161
157
|
|
|
@@ -168,14 +164,12 @@ def plot_guppi_boundaries( # noqa PLR0915
|
|
|
168
164
|
wspace=0.0,
|
|
169
165
|
)
|
|
170
166
|
_ax1 = _my_fig1.add_subplot(_fig1_grid[0, 0])
|
|
171
|
-
_ax1 = _set_axis_def(_ax1)
|
|
172
|
-
_ax1.set_aspect(1.0)
|
|
173
|
-
_ax1.set_facecolor("#F6F6F6")
|
|
167
|
+
_ax1 = _set_axis_def(_ax1, mktshares_plot_flag=True, mktshares_axlbls_flag=True)
|
|
174
168
|
|
|
175
169
|
_ax1.plot(_dh_dat_x, _dh_dat_y, linewidth=0.75, color="black", zorder=3)
|
|
176
170
|
_ax1.fill_between(
|
|
177
|
-
|
|
178
|
-
|
|
171
|
+
_dh_dat_x,
|
|
172
|
+
_dh_dat_y,
|
|
179
173
|
0,
|
|
180
174
|
edgecolor=None,
|
|
181
175
|
facecolor="#64bb64",
|
|
@@ -188,6 +182,8 @@ def plot_guppi_boundaries( # noqa PLR0915
|
|
|
188
182
|
_m_lim = _guppi_bench / _r_bar
|
|
189
183
|
_mst_vec = arange(_m_lim, 1.00 + _step_size, _step_size)
|
|
190
184
|
_sym_shr_vec = (_dst_vec := _m_lim / _mst_vec) / (1 + _dst_vec)
|
|
185
|
+
# _sym_shr_vec = np.arange(gbl.shr_from_gbd(g_bar), 0.5 + step_size, step_size)
|
|
186
|
+
# _mst_vec = (g_bar / r_bar) * (1 - sym_shr_vec) / sym_shr_vec
|
|
191
187
|
# https://stackoverflow.com/questions/39753282/
|
|
192
188
|
_ax1.scatter(
|
|
193
189
|
_sym_shr_vec,
|
|
@@ -197,12 +193,12 @@ def plot_guppi_boundaries( # noqa PLR0915
|
|
|
197
193
|
s=(0.25 * 72.0 / _my_fig1.dpi) ** 2,
|
|
198
194
|
edgecolor=None,
|
|
199
195
|
c=_mst_vec,
|
|
200
|
-
**
|
|
196
|
+
**_color_kwargs,
|
|
201
197
|
rasterized=True,
|
|
202
198
|
zorder=3,
|
|
203
199
|
)
|
|
204
200
|
|
|
205
|
-
for _m_star in
|
|
201
|
+
for _m_star in arange(1.00, _m_lim - 0.10, -0.10):
|
|
206
202
|
_m_star, _delta_star, _s_mid = (
|
|
207
203
|
round(_s, 4)
|
|
208
204
|
for _s in (_m_star, _m_lim / _m_star, _m_lim / (_m_star + _m_lim))
|
|
@@ -216,7 +212,7 @@ def plot_guppi_boundaries( # noqa PLR0915
|
|
|
216
212
|
_s2_vals,
|
|
217
213
|
linestyle="--",
|
|
218
214
|
linewidth=0.75,
|
|
219
|
-
color=
|
|
215
|
+
color=_color_kwargs["cmap"](_m_star),
|
|
220
216
|
zorder=3,
|
|
221
217
|
)
|
|
222
218
|
else:
|
|
@@ -316,23 +312,21 @@ def plot_guppi_boundaries( # noqa PLR0915
|
|
|
316
312
|
# print("Diversion ratio bound")
|
|
317
313
|
if _divr_bench < _r_bar:
|
|
318
314
|
_m_star_bench = _guppi_bench / _divr_bench
|
|
319
|
-
_s_mid_bench =
|
|
315
|
+
_s_mid_bench = gbl.shr_from_gbd(
|
|
320
316
|
_guppi_bench, m_star=_m_star_bench, r_bar=_r_bar
|
|
321
317
|
)
|
|
322
|
-
_delta_star =
|
|
318
|
+
_delta_star = gbl.critical_shrratio(
|
|
323
319
|
_guppi_bench, m_star=_m_star_bench, r_bar=_r_bar
|
|
324
320
|
)
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
)
|
|
328
|
-
_x_drt, _y_drt = zip(*guppi_boundary_data, strict=True)
|
|
321
|
+
guppi_boundary = gbl.shrratio_boundary_max(_delta_star)
|
|
322
|
+
_x_drt, _y_drt = zip(*guppi_boundary.coordinates, strict=True)
|
|
329
323
|
|
|
330
324
|
_ax1.plot(
|
|
331
325
|
_x_drt,
|
|
332
326
|
_y_drt,
|
|
333
327
|
linestyle="-",
|
|
334
328
|
linewidth=0.75,
|
|
335
|
-
color=
|
|
329
|
+
color=_color_kwargs["cmap"](_m_star_bench),
|
|
336
330
|
zorder=4,
|
|
337
331
|
)
|
|
338
332
|
|
|
@@ -381,7 +375,7 @@ def plot_guppi_boundaries( # noqa PLR0915
|
|
|
381
375
|
xerr=_ebar_array,
|
|
382
376
|
yerr=_ebar_array,
|
|
383
377
|
fmt=".",
|
|
384
|
-
mfc=
|
|
378
|
+
mfc=_color_kwargs["cmap"](_guppi_bench / _r_bar),
|
|
385
379
|
mec="None",
|
|
386
380
|
alpha=0.9,
|
|
387
381
|
zorder=5,
|
|
@@ -390,7 +384,7 @@ def plot_guppi_boundaries( # noqa PLR0915
|
|
|
390
384
|
# https://stackoverflow.com/questions/22995797/
|
|
391
385
|
for _ix in range(2):
|
|
392
386
|
_ebar_plot[-1][_ix].set(
|
|
393
|
-
color=
|
|
387
|
+
color=_color_kwargs["cmap"](_guppi_bench / _r_bar),
|
|
394
388
|
linestyle="--",
|
|
395
389
|
linewidth=0.5,
|
|
396
390
|
alpha=0.9,
|
|
@@ -410,7 +404,7 @@ def plot_guppi_boundaries( # noqa PLR0915
|
|
|
410
404
|
ax1_cb = _my_fig1.add_subplot(_fig1_grid[0, 1], frameon=False)
|
|
411
405
|
ax1_cb.axis("off")
|
|
412
406
|
_cm_plot = _my_fig1.colorbar(
|
|
413
|
-
colormgr.ScalarMappable(**
|
|
407
|
+
colormgr.ScalarMappable(**_color_kwargs),
|
|
414
408
|
use_gridspec=True,
|
|
415
409
|
ax=ax1_cb,
|
|
416
410
|
orientation="vertical",
|
|
@@ -447,20 +441,21 @@ def grad_est(_ax: matplotlib.axis.Axis, _pt_xs: tuple, _pt_ys: tuple) -> float:
|
|
|
447
441
|
return (_pt2[1] - _pt1[1]) / (_pt2[0] - _pt1[0])
|
|
448
442
|
|
|
449
443
|
|
|
450
|
-
def
|
|
444
|
+
def get_hmg_thresholds_by_key(_guppi_bench_key: str, /) -> gbl.HMGThresholds:
|
|
451
445
|
match _guppi_bench_key:
|
|
452
446
|
case "DOJATR":
|
|
453
|
-
return (
|
|
454
|
-
|
|
447
|
+
return gbl.HMGThresholds(
|
|
448
|
+
(_tmp := gbl.GuidelinesThresholds(2010).safeharbor).delta,
|
|
449
|
+
_tmp.rec,
|
|
455
450
|
0.05,
|
|
456
|
-
_tmp
|
|
457
|
-
|
|
458
|
-
|
|
451
|
+
_tmp.divr,
|
|
452
|
+
_tmp.cmcr,
|
|
453
|
+
_tmp.ipr,
|
|
459
454
|
)
|
|
460
455
|
case "DH100":
|
|
461
|
-
return
|
|
456
|
+
return gbl.GuidelinesThresholds(2010).safeharbor
|
|
462
457
|
case "DH50":
|
|
463
|
-
return
|
|
458
|
+
return gbl.GuidelinesThresholds(1992).safeharbor
|
|
464
459
|
case _:
|
|
465
460
|
raise ValueError(
|
|
466
461
|
f"GUPPI benchmark key must be one of, {guppi_benchmark_keys!r}"
|
|
@@ -470,17 +465,14 @@ def get_hmg_standards_by_key(_guppi_bench_key: str, /) -> tuple:
|
|
|
470
465
|
if __name__ == "__main__":
|
|
471
466
|
print("Define parameters for GUPPI safeharbor plots")
|
|
472
467
|
|
|
473
|
-
_pcm_colornorm = mcolors.Normalize(0, 1.0)
|
|
474
|
-
cmap_kwargs = {"cmap": "cividis", "norm": _pcm_colornorm}
|
|
475
|
-
|
|
476
468
|
guppi_benchmark_keys = ("DH50", "DH100", "DOJATR")
|
|
477
469
|
|
|
478
470
|
print("Plot countour-maps of ∆HHI boundaries and GUPPI safeharbor boundaries")
|
|
479
471
|
|
|
480
|
-
|
|
472
|
+
pcm_same_flag: bool = True
|
|
473
|
+
recapture_spec: Literal["inside-out", "proportional"] = "inside-out"
|
|
474
|
+
plot_delta_boundaries("DH100", pcm_same_flag, recapture_spec, _color_kwargs)
|
|
481
475
|
|
|
482
|
-
pcm_same_flag: bool
|
|
483
|
-
recapture_spec: Literal["inside-out", "proportional"]
|
|
484
476
|
print("GUPPI safeharbor boundaries, by precentage price-cost margin")
|
|
485
477
|
for pcm_same_flag, recapture_spec in iterprod(
|
|
486
478
|
(False, True), ("inside-out", "proportional")
|
|
@@ -490,4 +482,6 @@ if __name__ == "__main__":
|
|
|
490
482
|
|
|
491
483
|
print(f"Symmetric margins: {pcm_same_flag!r}; recapture: '{recapture_spec}'")
|
|
492
484
|
for guppi_bench_key in guppi_benchmark_keys:
|
|
493
|
-
plot_guppi_boundaries(
|
|
485
|
+
plot_guppi_boundaries(
|
|
486
|
+
guppi_bench_key, pcm_same_flag, recapture_spec, _color_kwargs
|
|
487
|
+
)
|
|
@@ -12,14 +12,14 @@ from matplotlib import cm as colormgr
|
|
|
12
12
|
from matplotlib import colors as mcolors
|
|
13
13
|
from matplotlib.ticker import AutoMinorLocator, MultipleLocator, StrMethodFormatter
|
|
14
14
|
|
|
15
|
-
import mergeron.core.
|
|
15
|
+
import mergeron.core.guidelines_boundaries as gbl
|
|
16
16
|
from mergeron import DATA_DIR
|
|
17
17
|
|
|
18
18
|
PROG_PATH = Path(__file__)
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
def _main() -> None:
|
|
22
|
-
plt, _, _, set_axis_def =
|
|
22
|
+
plt, _, _, set_axis_def = gbl.boundary_plot()
|
|
23
23
|
# plt.delaxes(ax1)
|
|
24
24
|
# del my_fig1, ax1
|
|
25
25
|
# del ax1
|
|
@@ -45,7 +45,7 @@ def _main() -> None:
|
|
|
45
45
|
g_bar, r_bar, dr_bar = 0.06, 0.80, 0.20
|
|
46
46
|
|
|
47
47
|
step_size = 10**-5
|
|
48
|
-
sym_shr_vec = np.arange(
|
|
48
|
+
sym_shr_vec = np.arange(gbl.shr_from_gbd(g_bar), 0.5 + step_size, step_size)
|
|
49
49
|
mst_vec = (g_bar / r_bar) * (1 - sym_shr_vec) / sym_shr_vec
|
|
50
50
|
|
|
51
51
|
print("Setup basic figure and axes for plots of safe harbor boundaries.")
|
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import numpy as np
|
|
4
4
|
|
|
5
5
|
import mergeron.core.proportions_tests as pcl
|
|
6
6
|
|
|
7
|
-
enf_counts = array(
|
|
8
|
-
(
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
)
|
|
7
|
+
enf_counts = np.array(
|
|
8
|
+
(
|
|
9
|
+
(24, 25, 33, 33),
|
|
10
|
+
(30, 33, 27, 32),
|
|
11
|
+
(14, 15, 9, 11),
|
|
12
|
+
(13, 22, 6, 11),
|
|
13
|
+
(6, 8, 7, 9),
|
|
14
|
+
(1, 3, 2, 4),
|
|
15
|
+
(1, 3, 2, 4),
|
|
16
|
+
(1e-15, 1e-15, 1, 1),
|
|
17
|
+
),
|
|
18
|
+
np.int16,
|
|
19
|
+
)
|
|
17
20
|
|
|
18
21
|
if __name__ == "__main__":
|
|
19
22
|
adj_n = len(enf_counts)
|
|
@@ -37,13 +40,12 @@ if __name__ == "__main__":
|
|
|
37
40
|
count, ic_1996_2003.sum(), alpha=0.05 / adj_n, method="Wilson"
|
|
38
41
|
)[2:]
|
|
39
42
|
)
|
|
40
|
-
del count
|
|
41
43
|
|
|
42
44
|
print("Conf. intervals for relative frequency of II Requests (Goodman, 1965)")
|
|
43
45
|
for goodman_alternative in "default", "simplified":
|
|
44
46
|
for goodman_method in "goodman", "quesenberry-hurst":
|
|
45
47
|
print(f"Method, {goodman_method!r}; alternative, {goodman_alternative!r}")
|
|
46
|
-
for _cis in column_stack([
|
|
48
|
+
for _cis in np.column_stack([
|
|
47
49
|
pcl.propn_ci_multinomial(
|
|
48
50
|
enf_counts[:, _cidx],
|
|
49
51
|
method=goodman_method,
|
|
@@ -56,11 +58,11 @@ if __name__ == "__main__":
|
|
|
56
58
|
|
|
57
59
|
print()
|
|
58
60
|
print("Conf. intervals for differences in proportions enforced (Goodman, 1964)")
|
|
59
|
-
print(repr(pcl.
|
|
61
|
+
print(repr(pcl.propn_diff_ci_multinomial(enf_counts[:, [1, 3]])))
|
|
60
62
|
|
|
61
63
|
print()
|
|
62
64
|
print("Goodman's chi-squared test for homogeneity of enforcement patterns")
|
|
63
|
-
print(repr(pcl.
|
|
65
|
+
print(repr(pcl.propn_test_multinomial(enf_counts[:, [1, 3]])))
|
|
64
66
|
|
|
65
67
|
print()
|
|
66
68
|
print(
|
|
@@ -68,5 +70,5 @@ if __name__ == "__main__":
|
|
|
68
70
|
"(Bonnferoni-adjusted Newcombe C.I.s)",
|
|
69
71
|
)
|
|
70
72
|
for counts in enf_counts:
|
|
71
|
-
print(pcl.propn_diff_ci(*counts, alpha=0.05 / adj_n, method="Newcombe")
|
|
73
|
+
print(pcl.propn_diff_ci(*counts, alpha=0.05 / adj_n, method="Newcombe"))
|
|
72
74
|
print()
|