mergeron 2024.738936.0__py3-none-any.whl → 2024.738936.2__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/guidelines_standards.py +236 -45
- mergeron/core/proportions_tests.py +9 -9
- mergeron/core/pseudorandom_numbers.py +1 -2
- mergeron/examples/concentration_as_diversion.py +71 -84
- mergeron/gen/data_generation.py +5 -8
- {mergeron-2024.738936.0.dist-info → mergeron-2024.738936.2.dist-info}/METADATA +1 -1
- {mergeron-2024.738936.0.dist-info → mergeron-2024.738936.2.dist-info}/RECORD +8 -8
- {mergeron-2024.738936.0.dist-info → mergeron-2024.738936.2.dist-info}/WHEEL +0 -0
|
@@ -17,6 +17,7 @@ from typing import Any, Literal, TypeAlias
|
|
|
17
17
|
import numpy as np
|
|
18
18
|
from mpmath import mp, mpf # type: ignore
|
|
19
19
|
from numpy.typing import NDArray
|
|
20
|
+
from scipy.spatial.distance import minkowski as distance_function
|
|
20
21
|
|
|
21
22
|
mp.prec = 80
|
|
22
23
|
mp.trap_complex = True
|
|
@@ -168,7 +169,7 @@ def lerp(
|
|
|
168
169
|
/,
|
|
169
170
|
) -> float | mpf | NDArray[np.float64]:
|
|
170
171
|
"""
|
|
171
|
-
From the
|
|
172
|
+
From the function of the same name in the C++ standard [2]_
|
|
172
173
|
|
|
173
174
|
Constructs the weighted average, :math:`w_1 x_1 + w_2 x_2`, where
|
|
174
175
|
:math:`w_1 = 1 - r` and :math:`w_2 = r`.
|
|
@@ -178,21 +179,35 @@ def lerp(
|
|
|
178
179
|
_x1, _x2
|
|
179
180
|
bounds :math:`x_1, x_2` to interpolate between.
|
|
180
181
|
_r
|
|
181
|
-
interpolation weight :math:`r` assigned to :math:`x_2
|
|
182
|
+
interpolation weight :math:`r` assigned to :math:`x_2`
|
|
182
183
|
|
|
183
184
|
Returns
|
|
184
185
|
-------
|
|
185
|
-
The linear interpolation, or weighted average,
|
|
186
|
+
The linear interpolation, or weighted average,
|
|
187
|
+
:math:`x_1 + r \\cdot (x_1 - x_2) \\equiv (1 - r) \\cdot x_1 + r \\cdot x_2`.
|
|
186
188
|
|
|
187
189
|
Raises
|
|
188
190
|
------
|
|
189
191
|
ValueError
|
|
190
192
|
If the interpolation weight is not in the interval, :math:`[0, 1]`.
|
|
191
193
|
|
|
194
|
+
References
|
|
195
|
+
----------
|
|
196
|
+
|
|
197
|
+
.. [2] C++ Reference, https://en.cppreference.com/w/cpp/numeric/lerp
|
|
198
|
+
|
|
192
199
|
"""
|
|
200
|
+
|
|
193
201
|
if not 0 <= _r <= 1:
|
|
194
202
|
raise ValueError("Specified interpolation weight must lie in [0, 1].")
|
|
195
|
-
|
|
203
|
+
elif _r == 0:
|
|
204
|
+
return _x1
|
|
205
|
+
elif _r == 1:
|
|
206
|
+
return _x2
|
|
207
|
+
elif _r == 0.5:
|
|
208
|
+
return 1 / 2 * (_x1 + _x2)
|
|
209
|
+
else:
|
|
210
|
+
return _r * _x2 + (1 - _r) * _x1
|
|
196
211
|
|
|
197
212
|
|
|
198
213
|
def gbd_from_dsf(
|
|
@@ -552,7 +567,7 @@ def delta_hhi_boundary(
|
|
|
552
567
|
|
|
553
568
|
|
|
554
569
|
def combined_share_boundary(
|
|
555
|
-
|
|
570
|
+
_s_intcpt: float = 0.0625, /, *, bdry_dps: int = 10
|
|
556
571
|
) -> tuple[NDArray[np.float64], float]:
|
|
557
572
|
"""
|
|
558
573
|
Share combinations on the merging-firms' combined share boundary.
|
|
@@ -563,7 +578,7 @@ def combined_share_boundary(
|
|
|
563
578
|
|
|
564
579
|
Parameters
|
|
565
580
|
----------
|
|
566
|
-
|
|
581
|
+
_s_intcpt:
|
|
567
582
|
Merging-firms' combined share.
|
|
568
583
|
bdry_dps
|
|
569
584
|
Number of decimal places for rounding reported shares.
|
|
@@ -573,16 +588,16 @@ def combined_share_boundary(
|
|
|
573
588
|
Array of share-pairs, area under boundary.
|
|
574
589
|
|
|
575
590
|
"""
|
|
576
|
-
|
|
577
|
-
_s_mid =
|
|
591
|
+
_s_intcpt = mpf(f"{_s_intcpt}")
|
|
592
|
+
_s_mid = _s_intcpt / 2
|
|
578
593
|
|
|
579
|
-
_s1_pts = (0, _s_mid,
|
|
594
|
+
_s1_pts = (0, _s_mid, _s_intcpt)
|
|
580
595
|
return (
|
|
581
596
|
np.column_stack((
|
|
582
597
|
np.array(_s1_pts, np.float64),
|
|
583
598
|
np.array(_s1_pts[::-1], np.float64),
|
|
584
599
|
)),
|
|
585
|
-
round(float(
|
|
600
|
+
round(float(_s_intcpt * _s_mid), bdry_dps),
|
|
586
601
|
)
|
|
587
602
|
|
|
588
603
|
|
|
@@ -650,17 +665,17 @@ def shrratio_mgnsym_boundary_max(
|
|
|
650
665
|
# of function call with other shrratio_mgnsym_boundary functions
|
|
651
666
|
del _r_val
|
|
652
667
|
_delta_star = mpf(f"{_delta_star}")
|
|
653
|
-
|
|
668
|
+
_s_intcpt = _delta_star
|
|
654
669
|
_s_mid = _delta_star / (1 + _delta_star)
|
|
655
670
|
|
|
656
|
-
_s1_pts = (0, _s_mid,
|
|
671
|
+
_s1_pts = (0, _s_mid, _s_intcpt)
|
|
657
672
|
|
|
658
673
|
return (
|
|
659
674
|
np.column_stack((
|
|
660
675
|
np.array(_s1_pts, np.float64),
|
|
661
676
|
np.array(_s1_pts[::-1], np.float64),
|
|
662
677
|
)),
|
|
663
|
-
round(float(
|
|
678
|
+
round(float(_s_intcpt * _s_mid), gbd_dps), # simplified calculation
|
|
664
679
|
)
|
|
665
680
|
|
|
666
681
|
|
|
@@ -710,7 +725,7 @@ def shrratio_mgnsym_boundary_min(
|
|
|
710
725
|
)
|
|
711
726
|
|
|
712
727
|
_delta_star = mpf(f"{_delta_star}")
|
|
713
|
-
|
|
728
|
+
_s_intcpt = mpf("1.00")
|
|
714
729
|
_s_mid = _delta_star / (1 + _delta_star)
|
|
715
730
|
|
|
716
731
|
if recapture_spec == "inside-out":
|
|
@@ -725,14 +740,14 @@ def shrratio_mgnsym_boundary_min(
|
|
|
725
740
|
_smin_nr / _guppi_bdry_env_dr,
|
|
726
741
|
_s_mid,
|
|
727
742
|
_smax_nr / _guppi_bdry_env_dr,
|
|
728
|
-
|
|
743
|
+
_s_intcpt,
|
|
729
744
|
),
|
|
730
745
|
np.float64,
|
|
731
746
|
)
|
|
732
747
|
|
|
733
748
|
_gbd_area = (_smin_nr + (_smax_nr - _smin_nr) * _s_mid) / _guppi_bdry_env_dr
|
|
734
749
|
else:
|
|
735
|
-
_s1_pts, _gbd_area = np.array((0, _s_mid,
|
|
750
|
+
_s1_pts, _gbd_area = np.array((0, _s_mid, _s_intcpt), np.float64), _s_mid
|
|
736
751
|
|
|
737
752
|
return np.column_stack((_s1_pts, _s1_pts[::-1])), round(float(_gbd_area), gbd_dps)
|
|
738
753
|
|
|
@@ -842,10 +857,12 @@ def shrratio_mgnsym_boundary_wtd_avg(
|
|
|
842
857
|
_delta_star = mpf(f"{_delta_star}")
|
|
843
858
|
_s_mid = _delta_star / (1 + _delta_star)
|
|
844
859
|
|
|
860
|
+
# initial conditions
|
|
845
861
|
_gbdry_points = [(_s_mid, _s_mid)]
|
|
846
862
|
_s_1_pre, _s_2_pre = _s_mid, _s_mid
|
|
847
863
|
_s_2_oddval, _s_2_oddsum, _s_2_evnsum = True, 0, 0
|
|
848
864
|
|
|
865
|
+
# parameters for iteration
|
|
849
866
|
_gbd_step_sz = mp.power(10, -gbd_dps)
|
|
850
867
|
_theta = _gbd_step_sz * (10 if wgtng_policy == "cross-product-share" else 1)
|
|
851
868
|
for _s_1 in mp.arange(_s_mid - _gbd_step_sz, 0, -_gbd_step_sz):
|
|
@@ -883,12 +900,12 @@ def shrratio_mgnsym_boundary_wtd_avg(
|
|
|
883
900
|
_delta_test = lerp(_de_1, _de_2, _r)
|
|
884
901
|
|
|
885
902
|
if wgtng_policy == "cross-product-share":
|
|
886
|
-
|
|
903
|
+
_test_flag, _incr_decr = (_delta_test > _delta_star, -1)
|
|
887
904
|
else:
|
|
888
|
-
|
|
905
|
+
_test_flag, _incr_decr = (_delta_test < _delta_star, 1)
|
|
889
906
|
|
|
890
|
-
if
|
|
891
|
-
_s_2 +=
|
|
907
|
+
if _test_flag:
|
|
908
|
+
_s_2 += _incr_decr * _gbd_step_sz
|
|
892
909
|
else:
|
|
893
910
|
break
|
|
894
911
|
|
|
@@ -916,13 +933,19 @@ def shrratio_mgnsym_boundary_wtd_avg(
|
|
|
916
933
|
# Area under boundary
|
|
917
934
|
_gbdry_area_total = 2 * _gbd_prtlarea - mp.power(_s_mid, 2)
|
|
918
935
|
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
936
|
+
match wgtng_policy:
|
|
937
|
+
case "cross-product-share":
|
|
938
|
+
_s_intcpt = _delta_star
|
|
939
|
+
case "own-product-share":
|
|
940
|
+
_s_intcpt = mpf("1.0")
|
|
941
|
+
case None if avg_method == "distance":
|
|
942
|
+
_s_intcpt = _delta_star * mp.sqrt("2")
|
|
943
|
+
case _:
|
|
944
|
+
_s_intcpt = _s_2_pre
|
|
945
|
+
|
|
946
|
+
_gbdry_points = np.row_stack((_gbdry_points, (mpf("0.0"), _s_intcpt))).astype(
|
|
947
|
+
np.float64
|
|
948
|
+
)
|
|
926
949
|
# Points defining boundary to point-of-symmetry
|
|
927
950
|
return (
|
|
928
951
|
np.row_stack((np.flip(_gbdry_points, 0), np.flip(_gbdry_points[1:], 1))),
|
|
@@ -1009,13 +1032,13 @@ def shrratio_mgnsym_boundary_xact_avg(
|
|
|
1009
1032
|
_gbdry_points_start = np.array([(_s_mid, _s_mid)])
|
|
1010
1033
|
_s_1 = np.array(mp.arange(_s_mid - _gbd_step_sz, 0, -_gbd_step_sz), np.float64)
|
|
1011
1034
|
if recapture_spec == "inside-out":
|
|
1012
|
-
|
|
1035
|
+
_s_intcpt = mp.fdiv(
|
|
1013
1036
|
mp.fsub(
|
|
1014
1037
|
2 * _delta_star * _r_val + 1, mp.fabs(2 * _delta_star * _r_val - 1)
|
|
1015
1038
|
),
|
|
1016
1039
|
2 * mpf(f"{_r_val}"),
|
|
1017
1040
|
)
|
|
1018
|
-
_nr_t1 = 1 + 2 * _delta_star * _r_val * (1 - _s_1) - _s_1 * (1 - _r_val)
|
|
1041
|
+
_nr_t1 = 1 + 2 * _delta_star * _r_val * (1 - _s_1) - _s_1 * (1 - _r_val) # type: ignore
|
|
1019
1042
|
|
|
1020
1043
|
_nr_sqrt_mdr = 4 * _delta_star * _r_val
|
|
1021
1044
|
_nr_sqrt_mdr2 = _nr_sqrt_mdr * _r_val
|
|
@@ -1040,9 +1063,9 @@ def shrratio_mgnsym_boundary_xact_avg(
|
|
|
1040
1063
|
|
|
1041
1064
|
_nr_t2_s1 = _nr_sqrt_s1sq + _nr_sqrt_s1 + _nr_sqrt_nos1
|
|
1042
1065
|
|
|
1043
|
-
if not np.isclose(
|
|
1044
|
-
np.einsum("i->", _nr_t2_mdr.astype(np.float64)), # from mpf to float64
|
|
1045
|
-
np.einsum("i->", _nr_t2_s1.astype(np.float64)),
|
|
1066
|
+
if not np.isclose( # type: ignore
|
|
1067
|
+
np.einsum("i->", _nr_t2_mdr.astype(np.float64)), # type: ignore from mpf to float64
|
|
1068
|
+
np.einsum("i->", _nr_t2_s1.astype(np.float64)), # type: ignore from mpf to float64
|
|
1046
1069
|
rtol=0,
|
|
1047
1070
|
atol=0.5 * gbd_dps,
|
|
1048
1071
|
):
|
|
@@ -1054,7 +1077,7 @@ def shrratio_mgnsym_boundary_xact_avg(
|
|
|
1054
1077
|
_s_2 = (_nr_t1 - np.sqrt(_nr_t2_s1)) / (2 * _r_val)
|
|
1055
1078
|
|
|
1056
1079
|
else:
|
|
1057
|
-
|
|
1080
|
+
_s_intcpt = mp.fsub(_delta_star + 1 / 2, mp.fabs(_delta_star - 1 / 2))
|
|
1058
1081
|
_s_2 = (
|
|
1059
1082
|
(1 / 2)
|
|
1060
1083
|
+ _delta_star
|
|
@@ -1069,7 +1092,7 @@ def shrratio_mgnsym_boundary_xact_avg(
|
|
|
1069
1092
|
)
|
|
1070
1093
|
|
|
1071
1094
|
_gbdry_points_inner = np.column_stack((_s_1, _s_2))
|
|
1072
|
-
_gbdry_points_end = np.array([(mpf("0.0"),
|
|
1095
|
+
_gbdry_points_end = np.array([(mpf("0.0"), _s_intcpt)], np.float64)
|
|
1073
1096
|
|
|
1074
1097
|
_gbdry_points = np.row_stack((
|
|
1075
1098
|
_gbdry_points_end,
|
|
@@ -1111,6 +1134,8 @@ def shrratio_mgnsym_boundary_avg(
|
|
|
1111
1134
|
Share combinations along the average GUPPI boundary, with
|
|
1112
1135
|
symmetric merging-firm margins.
|
|
1113
1136
|
|
|
1137
|
+
Faster than calling shrratio_mgnsym_boundary_avg(wgtng_policy=None).
|
|
1138
|
+
|
|
1114
1139
|
Parameters
|
|
1115
1140
|
----------
|
|
1116
1141
|
_delta_star
|
|
@@ -1118,7 +1143,7 @@ def shrratio_mgnsym_boundary_avg(
|
|
|
1118
1143
|
_r_val
|
|
1119
1144
|
Recapture ratio.
|
|
1120
1145
|
avg_method
|
|
1121
|
-
Whether "arithmetic", "geometric", or "
|
|
1146
|
+
Whether "arithmetic", "geometric", or "distance".
|
|
1122
1147
|
recapture_spec
|
|
1123
1148
|
Whether recapture-ratio is MNL-consistent ("inside-out") or has fixed
|
|
1124
1149
|
value for both merging firms ("proportional").
|
|
@@ -1137,7 +1162,7 @@ def shrratio_mgnsym_boundary_avg(
|
|
|
1137
1162
|
"Margin-adjusted benchmark share ratio cannot exceed 1."
|
|
1138
1163
|
)
|
|
1139
1164
|
|
|
1140
|
-
if avg_method not in (_avgmthds := ("arithmetic", "geometric", "
|
|
1165
|
+
if avg_method not in (_avgmthds := ("arithmetic", "geometric", "distance")):
|
|
1141
1166
|
raise ValueError(
|
|
1142
1167
|
f"Averarging method, {f'"{avg_method}"'} is invalid. "
|
|
1143
1168
|
f"Must be one of, {_avgmthds!r}."
|
|
@@ -1151,18 +1176,21 @@ def shrratio_mgnsym_boundary_avg(
|
|
|
1151
1176
|
|
|
1152
1177
|
_delta_star = mpf(f"{_delta_star}")
|
|
1153
1178
|
_s_mid = _delta_star / (1 + _delta_star)
|
|
1154
|
-
_gbd_step_sz = mp.power(10, -gbd_dps)
|
|
1155
1179
|
|
|
1180
|
+
# initial conditions
|
|
1156
1181
|
_s_2 = _s_mid
|
|
1157
1182
|
_s_2_oddval = True
|
|
1158
1183
|
_s_2_oddsum = 0
|
|
1159
1184
|
_s_2_evnsum = 0
|
|
1160
1185
|
_gbdry_points = [(_s_mid, _s_mid)]
|
|
1186
|
+
|
|
1187
|
+
# parameters for iteration
|
|
1188
|
+
_gbd_step_sz = mp.power(10, -gbd_dps)
|
|
1161
1189
|
for _s_1 in mp.arange(_s_mid, 0, -_gbd_step_sz):
|
|
1162
1190
|
_s_1 -= _gbd_step_sz
|
|
1163
1191
|
while True:
|
|
1164
|
-
|
|
1165
|
-
|
|
1192
|
+
_delta_12 = _s_2 / (1 - _s_1)
|
|
1193
|
+
_delta_21 = (
|
|
1166
1194
|
_s_1 / (1 - _s_2)
|
|
1167
1195
|
if recapture_spec == "proportional"
|
|
1168
1196
|
else _s_1 / (1 - lerp(_s_1, _s_2, _r_val))
|
|
@@ -1170,13 +1198,21 @@ def shrratio_mgnsym_boundary_avg(
|
|
|
1170
1198
|
|
|
1171
1199
|
match avg_method:
|
|
1172
1200
|
case "geometric":
|
|
1173
|
-
|
|
1201
|
+
_delta_test = mp.sqrt(_delta_12 * _delta_21)
|
|
1174
1202
|
case "distance":
|
|
1175
|
-
|
|
1203
|
+
# _delta_test = mp.sqrt(mp.fdiv((_delta_12**2 + _delta_21**2), "2"))
|
|
1204
|
+
_delta_test = mp.sqrt(
|
|
1205
|
+
mp.fdiv(
|
|
1206
|
+
mp.fsum(
|
|
1207
|
+
mp.power(f"{_g}", "2") for _g in (_delta_12, _delta_21)
|
|
1208
|
+
),
|
|
1209
|
+
"2",
|
|
1210
|
+
)
|
|
1211
|
+
)
|
|
1176
1212
|
case _:
|
|
1177
|
-
|
|
1213
|
+
_delta_test = mp.fdiv(_delta_12 + _delta_21, "2")
|
|
1178
1214
|
|
|
1179
|
-
if
|
|
1215
|
+
if _delta_test < _delta_star:
|
|
1180
1216
|
_s_2 += _gbd_step_sz
|
|
1181
1217
|
else:
|
|
1182
1218
|
break
|
|
@@ -1189,12 +1225,12 @@ def shrratio_mgnsym_boundary_avg(
|
|
|
1189
1225
|
|
|
1190
1226
|
# Starting at _s_id - _gbd_step_sz means _s_1 is not always
|
|
1191
1227
|
# an even multiple of _gbd_step_sz
|
|
1192
|
-
|
|
1228
|
+
_s_intcpt = _s_2
|
|
1193
1229
|
|
|
1194
1230
|
_gbd_prtlarea = 2 * _gbd_step_sz * (
|
|
1195
1231
|
mp.fmul(4 / 3, _s_2_oddsum)
|
|
1196
1232
|
+ mp.fmul(2 / 3, _s_2_evnsum)
|
|
1197
|
-
+ mp.fmul(1 / 3, _s_mid +
|
|
1233
|
+
+ mp.fmul(1 / 3, _s_mid + _s_intcpt)
|
|
1198
1234
|
) - mp.power(_s_mid, 2)
|
|
1199
1235
|
|
|
1200
1236
|
_gbdry_points = np.array(_gbdry_points, np.float64)
|
|
@@ -1202,3 +1238,158 @@ def shrratio_mgnsym_boundary_avg(
|
|
|
1202
1238
|
np.row_stack((np.flip(_gbdry_points, 0), np.flip(_gbdry_points[1:], 1))),
|
|
1203
1239
|
round(float(_gbd_prtlarea), gbd_dps),
|
|
1204
1240
|
)
|
|
1241
|
+
|
|
1242
|
+
|
|
1243
|
+
def shrratio_mgnsym_boundary_distance(
|
|
1244
|
+
_delta_star: float = 0.075,
|
|
1245
|
+
_r_val: float = 0.80,
|
|
1246
|
+
/,
|
|
1247
|
+
*,
|
|
1248
|
+
avg_method: Literal["arithmetic", "distance"] = "arithmetic",
|
|
1249
|
+
wgtng_policy: Literal["own-share", "cross-product-share"] | None = "own-share",
|
|
1250
|
+
recapture_spec: Literal["inside-out", "proportional"] = "inside-out",
|
|
1251
|
+
gbd_dps: int = 5,
|
|
1252
|
+
) -> tuple[NDArray[np.float64], float]:
|
|
1253
|
+
"""
|
|
1254
|
+
Share combinations for the GUPPI boundaries using various aggregators with symmetric merging-firm margins.
|
|
1255
|
+
|
|
1256
|
+
Parameters
|
|
1257
|
+
----------
|
|
1258
|
+
_delta_star
|
|
1259
|
+
corollary to GUPPI bound (:math:`\\overline{g} / (m^* \\cdot \\overline{r})`)
|
|
1260
|
+
_r_val
|
|
1261
|
+
recapture ratio
|
|
1262
|
+
avg_method
|
|
1263
|
+
Whether "arithmetic", "geometric", or "distance".
|
|
1264
|
+
wgtng_policy
|
|
1265
|
+
Whether "own-share" or "cross-product-share".
|
|
1266
|
+
recapture_spec
|
|
1267
|
+
Whether recapture-ratio is MNL-consistent ("inside-out") or has fixed
|
|
1268
|
+
value for both merging firms ("proportional").
|
|
1269
|
+
gbd_dps
|
|
1270
|
+
Number of decimal places for rounding returned shares and area.
|
|
1271
|
+
|
|
1272
|
+
Returns
|
|
1273
|
+
-------
|
|
1274
|
+
Array of share-pairs, area under boundary.
|
|
1275
|
+
|
|
1276
|
+
"""
|
|
1277
|
+
|
|
1278
|
+
if _delta_star > 1:
|
|
1279
|
+
raise ValueError(
|
|
1280
|
+
"Margin-adjusted benchmark share ratio, `_delta_star` cannot exceed 1."
|
|
1281
|
+
)
|
|
1282
|
+
|
|
1283
|
+
_delta_star = mpf(f"{_delta_star}")
|
|
1284
|
+
_s_mid = _delta_star / (1 + _delta_star)
|
|
1285
|
+
|
|
1286
|
+
# initial conditions
|
|
1287
|
+
_gbdry_points = [(_s_mid, _s_mid)]
|
|
1288
|
+
_s_1_pre, _s_2_pre = _s_mid, _s_mid
|
|
1289
|
+
_s_2_oddval, _s_2_oddsum, _s_2_evnsum = True, 0, 0
|
|
1290
|
+
|
|
1291
|
+
# parameters for iteration
|
|
1292
|
+
_weights_base = (mpf("0.5"),) * 2
|
|
1293
|
+
_gbd_step_sz = mp.power(10, -gbd_dps)
|
|
1294
|
+
_theta = _gbd_step_sz * (10 if wgtng_policy == "cross-product-share" else 1)
|
|
1295
|
+
for _s_1 in mp.arange(_s_mid - _gbd_step_sz, 0, -_gbd_step_sz):
|
|
1296
|
+
# The wtd. avg. GUPPI is not always convex to the origin, so we
|
|
1297
|
+
# increment _s_2 after each iteration in which our algorithm
|
|
1298
|
+
# finds (s1, s2) on the boundary
|
|
1299
|
+
_s_2 = _s_2_pre * (1 + _theta)
|
|
1300
|
+
|
|
1301
|
+
if (_s_1 + _s_2) > mpf("0.99875"):
|
|
1302
|
+
# 1: # We lose accuracy at 3-9s and up
|
|
1303
|
+
break
|
|
1304
|
+
|
|
1305
|
+
while True:
|
|
1306
|
+
_de_1 = _s_2 / (1 - _s_1)
|
|
1307
|
+
_de_2 = (
|
|
1308
|
+
_s_1 / (1 - lerp(_s_1, _s_2, _r_val))
|
|
1309
|
+
if recapture_spec == "inside-out"
|
|
1310
|
+
else _s_1 / (1 - _s_2)
|
|
1311
|
+
)
|
|
1312
|
+
|
|
1313
|
+
_weights_i = (
|
|
1314
|
+
(
|
|
1315
|
+
_w1 := mp.fdiv(
|
|
1316
|
+
_s_2 if wgtng_policy == "cross-product-share" else _s_1,
|
|
1317
|
+
_s_1 + _s_2,
|
|
1318
|
+
),
|
|
1319
|
+
1 - _w1,
|
|
1320
|
+
)
|
|
1321
|
+
if wgtng_policy
|
|
1322
|
+
else _weights_base
|
|
1323
|
+
)
|
|
1324
|
+
|
|
1325
|
+
match avg_method:
|
|
1326
|
+
case "arithmetic":
|
|
1327
|
+
_delta_test = distance_function(
|
|
1328
|
+
(_de_1, _de_2), (0.0, 0.0), p=1, w=_weights_i
|
|
1329
|
+
)
|
|
1330
|
+
case "distance":
|
|
1331
|
+
_delta_test = distance_function(
|
|
1332
|
+
(_de_1, _de_2), (0.0, 0.0), p=2, w=_weights_i
|
|
1333
|
+
)
|
|
1334
|
+
|
|
1335
|
+
if wgtng_policy == "cross-product-share":
|
|
1336
|
+
_test_flag, _incr_decr = (_delta_test > _delta_star, -1)
|
|
1337
|
+
else:
|
|
1338
|
+
_test_flag, _incr_decr = (_delta_test < _delta_star, 1)
|
|
1339
|
+
|
|
1340
|
+
if _test_flag:
|
|
1341
|
+
_s_2 += _incr_decr * _gbd_step_sz
|
|
1342
|
+
else:
|
|
1343
|
+
break
|
|
1344
|
+
|
|
1345
|
+
# Build-up boundary points
|
|
1346
|
+
_gbdry_points.append((_s_1, _s_2))
|
|
1347
|
+
|
|
1348
|
+
# Build up area terms
|
|
1349
|
+
_s_2_oddsum += _s_2 if _s_2_oddval else 0
|
|
1350
|
+
_s_2_evnsum += _s_2 if not _s_2_oddval else 0
|
|
1351
|
+
_s_2_oddval = not _s_2_oddval
|
|
1352
|
+
|
|
1353
|
+
# Hold share points
|
|
1354
|
+
_s_2_pre = _s_2
|
|
1355
|
+
_s_1_pre = _s_1
|
|
1356
|
+
|
|
1357
|
+
_gbd_prtlarea = _gbd_step_sz * (
|
|
1358
|
+
(4 * _s_2_oddsum + 2 * _s_2_evnsum + _s_mid + _delta_star) / 3
|
|
1359
|
+
if wgtng_policy == "cross-product-share"
|
|
1360
|
+
else (
|
|
1361
|
+
(4 * _s_2_oddsum + 2 * _s_2_evnsum + _s_mid + _s_2_pre) / 3
|
|
1362
|
+
+ _s_1_pre * (1 + _s_2_pre) / 2
|
|
1363
|
+
)
|
|
1364
|
+
)
|
|
1365
|
+
|
|
1366
|
+
# Area under boundary
|
|
1367
|
+
_gbdry_area_total = 2 * _gbd_prtlarea - mp.power(_s_mid, 2)
|
|
1368
|
+
|
|
1369
|
+
match wgtng_policy:
|
|
1370
|
+
case "cross-product-share":
|
|
1371
|
+
_s_intcpt = _delta_star
|
|
1372
|
+
case "own-product-share":
|
|
1373
|
+
_s_intcpt = mpf("1.0")
|
|
1374
|
+
case None if avg_method == "distance":
|
|
1375
|
+
_s_intcpt = _delta_star * mp.sqrt("2")
|
|
1376
|
+
case None if avg_method == "arithmetic" and recapture_spec == "inside-out":
|
|
1377
|
+
_s_intcpt = mp.fdiv(
|
|
1378
|
+
mp.fsub(
|
|
1379
|
+
2 * _delta_star * _r_val + 1, mp.fabs(2 * _delta_star * _r_val - 1)
|
|
1380
|
+
),
|
|
1381
|
+
2 * mpf(f"{_r_val}"),
|
|
1382
|
+
)
|
|
1383
|
+
case None if avg_method == "arithmetic":
|
|
1384
|
+
_s_intcpt = mp.fsub(_delta_star + 1 / 2, mp.fabs(_delta_star - 1 / 2))
|
|
1385
|
+
case _:
|
|
1386
|
+
_s_intcpt = _s_2_pre
|
|
1387
|
+
|
|
1388
|
+
_gbdry_points = np.row_stack((_gbdry_points, (mpf("0.0"), _s_intcpt))).astype(
|
|
1389
|
+
np.float64
|
|
1390
|
+
)
|
|
1391
|
+
# Points defining boundary to point-of-symmetry
|
|
1392
|
+
return (
|
|
1393
|
+
np.row_stack((np.flip(_gbdry_points, 0), np.flip(_gbdry_points[1:], 1))),
|
|
1394
|
+
round(float(_gbdry_area_total), gbd_dps),
|
|
1395
|
+
)
|
|
@@ -41,7 +41,7 @@ def propn_ci(
|
|
|
41
41
|
]:
|
|
42
42
|
"""Returns point estimates and confidence interval for a proportion
|
|
43
43
|
|
|
44
|
-
Methods "Clopper-Pearson" and "Exact" are synoymous [
|
|
44
|
+
Methods "Clopper-Pearson" and "Exact" are synoymous [3]_. Similarly,
|
|
45
45
|
"Wilson" and "Score" are synonyms here.
|
|
46
46
|
|
|
47
47
|
Parameters
|
|
@@ -66,7 +66,7 @@ def propn_ci(
|
|
|
66
66
|
References
|
|
67
67
|
----------
|
|
68
68
|
|
|
69
|
-
.. [
|
|
69
|
+
.. [3] Alan Agresti & Brent A. Coull (1998) Approximate is Better
|
|
70
70
|
than “Exact” for Interval Estimation of Binomial Proportions,
|
|
71
71
|
The American Statistician, 52:2, 119-126,
|
|
72
72
|
https://doi.org/10.1080/00031305.1998.10480550
|
|
@@ -200,9 +200,9 @@ def propn_diff_ci(
|
|
|
200
200
|
) -> tuple[float, float, float, float]:
|
|
201
201
|
R"""Confidence intervals for differences in binomial proportions.
|
|
202
202
|
|
|
203
|
-
Methods available are Agresti-Caffo [
|
|
204
|
-
and Newcombe (aka, Score method) [
|
|
205
|
-
R-language function BinomDiffCI, in the module StatsAndCIs [
|
|
203
|
+
Methods available are Agresti-Caffo [4]_, Mee [5]_, Meitinen-Nurminen [5]_ [6]_
|
|
204
|
+
and Newcombe (aka, Score method) [5]_. See also, source code for the
|
|
205
|
+
R-language function BinomDiffCI, in the module StatsAndCIs [7]_.
|
|
206
206
|
|
|
207
207
|
Parameters
|
|
208
208
|
----------
|
|
@@ -222,19 +222,19 @@ def propn_diff_ci(
|
|
|
222
222
|
References
|
|
223
223
|
----------
|
|
224
224
|
|
|
225
|
-
.. [
|
|
225
|
+
.. [4] Agresti, A., & Caffo, T. (2000). Simple and Effective
|
|
226
226
|
Confidence Intervals for Proportions and Differences of Proportions
|
|
227
227
|
Result from Adding Two Successes and Two Failures.
|
|
228
228
|
The American Statistician, 54(4), 280--288. https://doi.org/10.2307/2685779
|
|
229
229
|
|
|
230
|
-
.. [
|
|
230
|
+
.. [5] Newcombe, R.G. (1998). Two-sided confidence intervals for
|
|
231
231
|
the single proportion: comparison of seven methods. Statist. Med., 17: 857-872.
|
|
232
232
|
https://doi.org/10.1002/(SICI)1097-0258(19980430)17:8%3C857::AID-SIM777%3E3.0.CO;2-E
|
|
233
233
|
|
|
234
|
-
.. [
|
|
234
|
+
.. [6] Miettinen, O. and Nurminen, M. (1985). Comparative analysis of two rates.
|
|
235
235
|
Statist. Med., 4: 213-226. https://doi.org/10.1002/sim.4780040211; Appendix I
|
|
236
236
|
|
|
237
|
-
.. [
|
|
237
|
+
.. [7] StatsAndCIs.r, function BinomDiffCI, method, "mn"
|
|
238
238
|
https://github.com/cran/DescTools/blob/master/R/StatsAndCIs.r
|
|
239
239
|
(R source code is distributed under the CC-BY license.)
|
|
240
240
|
|
|
@@ -20,7 +20,6 @@ systems.
|
|
|
20
20
|
|
|
21
21
|
from __future__ import annotations
|
|
22
22
|
|
|
23
|
-
from collections import OrderedDict
|
|
24
23
|
from collections.abc import Mapping, Sequence
|
|
25
24
|
from datetime import datetime
|
|
26
25
|
from math import sqrt
|
|
@@ -39,97 +38,95 @@ from mergeron import DATA_DIR
|
|
|
39
38
|
|
|
40
39
|
PROG_PATH = Path(__file__)
|
|
41
40
|
|
|
42
|
-
|
|
41
|
+
RECAPTURE_SPEC = "inside-out"
|
|
43
42
|
# Map boundary forms to titles and generating-function names, with
|
|
44
43
|
# additional parameters as relevant
|
|
45
|
-
|
|
44
|
+
BDRY_SPECS_DICT: Mapping[str, Mapping[str, Any]] = {
|
|
46
45
|
"ΔHHI": {
|
|
47
|
-
"title_str": "ΔHHI boundary
|
|
46
|
+
"title_str": "ΔHHI boundary",
|
|
47
|
+
"sheet_name": "ΔHHI",
|
|
48
48
|
"func_str": R"\Delta HHI",
|
|
49
49
|
"func": gsf.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
|
+
"sheet_name": "OSWAG, wtd avg",
|
|
53
54
|
"func_str": R"(s_1 d_{12} + s_2 d_{21}) / s_M",
|
|
54
55
|
"func": gsf.shrratio_mgnsym_boundary_wtd_avg,
|
|
55
|
-
"func_kwargs": {"wgtng_policy": "own-share", "recapture_spec":
|
|
56
|
+
"func_kwargs": {"wgtng_policy": "own-share", "recapture_spec": RECAPTURE_SPEC},
|
|
56
57
|
},
|
|
57
58
|
"OSWAG Own-shr-wtd Div Ratio Distance": {
|
|
58
59
|
"title_str": "Aggregated-diversion-ratio boundary, own-shr. wtd. distance",
|
|
60
|
+
"sheet_name": "OSWAG, distance",
|
|
59
61
|
"func_str": R"\surd (s_1 d_{12}^2 / s_M + s_2 d_{21}^2 / s_M)",
|
|
60
62
|
"func": gsf.shrratio_mgnsym_boundary_wtd_avg,
|
|
61
63
|
"func_kwargs": {
|
|
62
64
|
"wgtng_policy": "own-share",
|
|
63
|
-
"recapture_spec":
|
|
64
|
-
"avg_method": "root-mean-square",
|
|
65
|
-
},
|
|
66
|
-
},
|
|
67
|
-
"OSWAG Own-shr-wtd Div Ratio Real Distance": {
|
|
68
|
-
"title_str": "Aggregated-diversion-ratio boundary, own-shr. wtd. (really) distance ",
|
|
69
|
-
"func_str": R"\surd (d_{12}^{s_1 / s_M} + d_{21}^{s_2 / s_M})",
|
|
70
|
-
"func": gsf.shrratio_mgnsym_boundary_wtd_avg,
|
|
71
|
-
"func_kwargs": {
|
|
72
|
-
"wgtng_policy": "own-share",
|
|
73
|
-
"recapture_spec": recapture_spec,
|
|
65
|
+
"recapture_spec": RECAPTURE_SPEC,
|
|
74
66
|
"avg_method": "distance",
|
|
75
67
|
},
|
|
76
68
|
},
|
|
77
69
|
"OSWAG Min Div Ratio": {
|
|
78
70
|
"title_str": "Aggregated-diversion-ratio boundary, minimum",
|
|
71
|
+
"sheet_name": "OSWAG, minimum",
|
|
79
72
|
"func_str": R"\min (d_{12}, d_{21})",
|
|
80
73
|
"func": gsf.shrratio_mgnsym_boundary_min,
|
|
81
|
-
"func_kwargs": {"recapture_spec":
|
|
74
|
+
"func_kwargs": {"recapture_spec": RECAPTURE_SPEC},
|
|
82
75
|
},
|
|
83
76
|
"SAG Combined Share": {
|
|
84
77
|
"title_str": "Combined Share boundary",
|
|
78
|
+
"sheet_name": "SAG, combined-share",
|
|
85
79
|
"func_str": R"s_M",
|
|
86
80
|
"func": gsf.combined_share_boundary,
|
|
87
81
|
},
|
|
88
82
|
"SAG Div Ratio Distance": {
|
|
89
83
|
"title_str": "Aggregated-diversion-ratio boundary, distance",
|
|
84
|
+
"sheet_name": "SAG, distance",
|
|
90
85
|
"func_str": R"\surd (d_{12}^2 / 2 + d_{21}^2 / 2)",
|
|
91
86
|
"func": gsf.shrratio_mgnsym_boundary_avg,
|
|
92
|
-
"func_kwargs": {
|
|
93
|
-
"recapture_spec": recapture_spec,
|
|
94
|
-
"avg_method": "root-mean-square",
|
|
95
|
-
},
|
|
87
|
+
"func_kwargs": {"recapture_spec": RECAPTURE_SPEC, "avg_method": "distance"},
|
|
96
88
|
},
|
|
97
89
|
"SAG Average Div Ratio": {
|
|
98
90
|
"title_str": "Aggregated-diversion-ratio boundary, simple average",
|
|
91
|
+
"sheet_name": "SAG, average",
|
|
99
92
|
"func_str": R"(d_{12} + d_{21}) / 2",
|
|
100
93
|
"func": gsf.shrratio_mgnsym_boundary_xact_avg,
|
|
101
|
-
"func_kwargs": {"recapture_spec":
|
|
94
|
+
"func_kwargs": {"recapture_spec": RECAPTURE_SPEC},
|
|
102
95
|
},
|
|
103
96
|
"CPSWAG Premerger HHI-contribution": {
|
|
104
97
|
"title_str": "Premerger HHI-contribution boundary",
|
|
98
|
+
"sheet_name": "CPSWAG, HHI-contrib-pre",
|
|
105
99
|
"func_str": R"HHI_M^{pre}",
|
|
106
100
|
"func": gsf.hhi_pre_contrib_boundary,
|
|
107
101
|
},
|
|
108
102
|
"CPSWAG Cross-product-shr-wtd Div Ratio Index": {
|
|
109
103
|
"title_str": "Aggregated-diversion-ratio boundary, cross-product-share wtd. avg.",
|
|
104
|
+
"sheet_name": "CPSWAG, wtd avg",
|
|
110
105
|
"func_str": R"(s_2 d_{12} / s_M + s_1 d_{21} / s_M)",
|
|
111
106
|
"func": gsf.shrratio_mgnsym_boundary_wtd_avg,
|
|
112
107
|
"func_kwargs": {
|
|
113
108
|
"wgtng_policy": "cross-product-share",
|
|
114
|
-
"recapture_spec":
|
|
109
|
+
"recapture_spec": RECAPTURE_SPEC,
|
|
115
110
|
},
|
|
116
111
|
},
|
|
117
112
|
"CPSWAG Cross-product-shr-wtd Div Ratio Distance": {
|
|
118
113
|
"title_str": "Aggregated-diversion-ratio boundary, cross-prod-shr. wtd. distance",
|
|
114
|
+
"sheet_name": "CPSWAG, distance",
|
|
119
115
|
"func_str": R"\surd (s_2 d_{12}^2 / s_M + s_1 d_{21}^2 / s_M)",
|
|
120
116
|
"func": gsf.shrratio_mgnsym_boundary_wtd_avg,
|
|
121
117
|
"func_kwargs": {
|
|
122
118
|
"wgtng_policy": "cross-product-share",
|
|
123
|
-
"recapture_spec":
|
|
124
|
-
"avg_method": "
|
|
119
|
+
"recapture_spec": RECAPTURE_SPEC,
|
|
120
|
+
"avg_method": "distance",
|
|
125
121
|
},
|
|
126
122
|
},
|
|
127
123
|
"CPSWAG Max Div Ratio": {
|
|
128
124
|
"title_str": "Aggregated-diversion-ratio boundary, maximum",
|
|
125
|
+
"sheet_name": "CPSWAG, maximum",
|
|
129
126
|
"func_str": R"\max (d_{12}, d_{21})",
|
|
130
127
|
"func": gsf.shrratio_mgnsym_boundary_max,
|
|
131
128
|
},
|
|
132
|
-
}
|
|
129
|
+
}
|
|
133
130
|
|
|
134
131
|
|
|
135
132
|
def tabulate_boundary_stats(_gpubyr: Literal[1992, 2010, 2023], /) -> None:
|
|
@@ -142,7 +139,9 @@ def tabulate_boundary_stats(_gpubyr: Literal[1992, 2010, 2023], /) -> None:
|
|
|
142
139
|
|
|
143
140
|
"""
|
|
144
141
|
gso = gsf.GuidelinesStandards(_gpubyr)
|
|
145
|
-
_dhhi_val,
|
|
142
|
+
_dhhi_val, _r_val, _g_val = (
|
|
143
|
+
getattr(gso.presumption, _f) for _f in ("delta", "rec", "guppi")
|
|
144
|
+
)
|
|
146
145
|
|
|
147
146
|
_dhhi_seq = (
|
|
148
147
|
(0.01, 0.02, 0.03125, 0.05, _dhhi_val)
|
|
@@ -153,7 +152,7 @@ def tabulate_boundary_stats(_gpubyr: Literal[1992, 2010, 2023], /) -> None:
|
|
|
153
152
|
_bdry_approx_data_dict = {
|
|
154
153
|
"Criterion": {
|
|
155
154
|
_k: R"\({} < {}\)".format(
|
|
156
|
-
|
|
155
|
+
BDRY_SPECS_DICT[_k]["func_str"],
|
|
157
156
|
R"\safeharb{d}"
|
|
158
157
|
if "Div Ratio" in _k
|
|
159
158
|
else (
|
|
@@ -162,7 +161,7 @@ def tabulate_boundary_stats(_gpubyr: Literal[1992, 2010, 2023], /) -> None:
|
|
|
162
161
|
else R"\safeharb{H}"
|
|
163
162
|
),
|
|
164
163
|
)
|
|
165
|
-
for _k in
|
|
164
|
+
for _k in BDRY_SPECS_DICT
|
|
166
165
|
if not _k.endswith("Distance")
|
|
167
166
|
}
|
|
168
167
|
}
|
|
@@ -209,7 +208,7 @@ def _dhhi_stats(
|
|
|
209
208
|
|
|
210
209
|
_bdry_stats = Parallel(n_jobs=cpu_count() // 2)(
|
|
211
210
|
delayed(_bdry_stats_col)(_bdry_spec, _dhhi_val, _delta_val, _r_val)
|
|
212
|
-
for _bdry_spec in
|
|
211
|
+
for _bdry_spec in BDRY_SPECS_DICT
|
|
213
212
|
)
|
|
214
213
|
|
|
215
214
|
_bounds_string = R"{{ {} \\ {} }}".format(
|
|
@@ -234,9 +233,9 @@ def _bdry_stats_col(
|
|
|
234
233
|
case "CPSWAG Premerger HHI-contribution":
|
|
235
234
|
return _bdry_spec, f"{_hhi_m_pre_prob:6.5f}"
|
|
236
235
|
case _ if "Div Ratio" in _bdry_spec:
|
|
237
|
-
_gbd_func =
|
|
236
|
+
_gbd_func = BDRY_SPECS_DICT[_bdry_spec]["func"]
|
|
238
237
|
_, _within_bdry_area = _gbd_func(
|
|
239
|
-
_delta_val, _r_val, **
|
|
238
|
+
_delta_val, _r_val, **BDRY_SPECS_DICT[_bdry_spec].get("func_kwargs", {})
|
|
240
239
|
)
|
|
241
240
|
_within_bdry_prob = 2 * _within_bdry_area
|
|
242
241
|
_within_conc_bdry_prob = (
|
|
@@ -261,10 +260,11 @@ def plot_and_save_boundary_coords(
|
|
|
261
260
|
) -> None:
|
|
262
261
|
gso = gsf.GuidelinesStandards(_gpubyr)
|
|
263
262
|
|
|
264
|
-
|
|
263
|
+
_hmg_standards_strings_dict = {
|
|
265
264
|
"distributed": ("presumption", "inferred presumption", "safeharbor"),
|
|
266
265
|
"collected": ("safeharbor", "inferred_presumption", "presumption"),
|
|
267
|
-
}
|
|
266
|
+
}
|
|
267
|
+
_hmg_standards_strings = _hmg_standards_strings_dict.get(layout, ())
|
|
268
268
|
if not _hmg_standards_strings:
|
|
269
269
|
raise ValueError(
|
|
270
270
|
f"Layout parameter value, {layout!r} is invalid. "
|
|
@@ -279,7 +279,7 @@ def plot_and_save_boundary_coords(
|
|
|
279
279
|
for _divr_agg_method, _hmg_standards_str in zip(
|
|
280
280
|
_divr_agg_methods, _hmg_standards_strings, strict=True
|
|
281
281
|
):
|
|
282
|
-
_r_bar, _g_bar = gso.presumption
|
|
282
|
+
_r_bar, _g_bar = (getattr(gso.presumption, _f) for _f in ("rec", "guppi"))
|
|
283
283
|
_dhhi_val = getattr(gso, _hmg_standards_str)[0]
|
|
284
284
|
_divr_val = (
|
|
285
285
|
_g_bar
|
|
@@ -301,36 +301,22 @@ def plot_and_save_boundary_coords(
|
|
|
301
301
|
str, Sequence[tuple[float]]
|
|
302
302
|
] = {} #: Container for boundary coordinates data, by boundary
|
|
303
303
|
|
|
304
|
-
for _bdry_spec_key in
|
|
305
|
-
_bdry_spec = (_bdry_spec_key,
|
|
304
|
+
for _bdry_spec_key in BDRY_SPECS_DICT:
|
|
305
|
+
_bdry_spec = (_bdry_spec_key, BDRY_SPECS_DICT[_bdry_spec_key])
|
|
306
306
|
|
|
307
307
|
if _bdry_spec_key == "ΔHHI":
|
|
308
|
-
if
|
|
309
|
-
_hmg_standards_str == "inferred_presumption",
|
|
310
|
-
_hmg_standards_str == "safeharbor" and layout == "collected",
|
|
311
|
-
_hmg_standards_str == "presumption" and _divr_agg_method != "OSWAG",
|
|
312
|
-
)):
|
|
308
|
+
if _hmg_standards_str != _hmg_standards_strings_dict[layout][0]:
|
|
313
309
|
continue
|
|
314
310
|
|
|
315
311
|
_dh_s1, _dh_s2 = gen_plot_boundary(
|
|
316
312
|
_bndry_data_dict, gso, _hmg_standards_str, _bdry_spec, _ax1
|
|
317
313
|
)
|
|
318
314
|
|
|
319
|
-
if _hmg_standards_str == "safeharbor":
|
|
320
|
-
_ax1.fill_between(
|
|
321
|
-
(0, *tuple(_dh_s1), 1),
|
|
322
|
-
(1, *tuple(_dh_s2), 0),
|
|
323
|
-
edgecolor=None,
|
|
324
|
-
facecolor="#64bb64", # "#64ff64"
|
|
325
|
-
alpha=0.7,
|
|
326
|
-
rasterized=True,
|
|
327
|
-
)
|
|
328
|
-
|
|
329
315
|
del _dh_s1, _dh_s2
|
|
330
316
|
|
|
331
317
|
elif _bdry_spec_key.startswith(
|
|
332
318
|
_divr_agg_method
|
|
333
|
-
) and not _bdry_spec_key.endswith("Distance"):
|
|
319
|
+
): # and not _bdry_spec_key.endswith("Distance"):
|
|
334
320
|
gen_plot_boundary(
|
|
335
321
|
_bndry_data_dict, gso, _hmg_standards_str, _bdry_spec, _ax1
|
|
336
322
|
)
|
|
@@ -346,8 +332,8 @@ def plot_and_save_boundary_coords(
|
|
|
346
332
|
_fig_leg.set_in_layout(False)
|
|
347
333
|
|
|
348
334
|
for _bndry_name in _bndry_data_dict:
|
|
349
|
-
if _bndry_name == "ΔHHI": # _divr_agg_method != "OSWAG" and
|
|
350
|
-
|
|
335
|
+
# if _bndry_name == "ΔHHI": # and _divr_agg_method != "OSWAG" and
|
|
336
|
+
# continue
|
|
351
337
|
|
|
352
338
|
boundary_data_to_worksheet(
|
|
353
339
|
_bndry_name,
|
|
@@ -406,10 +392,14 @@ def gen_plot_boundary(
|
|
|
406
392
|
_pt_mdco: ptcolor.Mcset = ptcolor.tol_cset("medium-contrast") # type: ignore
|
|
407
393
|
|
|
408
394
|
_plot_line_width = 1.0
|
|
395
|
+
_plot_line_alpha = 0.8
|
|
409
396
|
_plot_line_color = _pt_mdco.black
|
|
410
397
|
_plot_line_style = {"OSWAG": "-", "SAG": "-.", "CPSWAG": "--"}.get(
|
|
411
398
|
_bdry_spec_str.split(" ")[0], "-"
|
|
412
399
|
)
|
|
400
|
+
if _bdry_spec_str.startswith("ΔHHI"):
|
|
401
|
+
_plot_line_width = 0.5
|
|
402
|
+
_plot_line_alpha = 1.0
|
|
413
403
|
_zrdr = 5
|
|
414
404
|
|
|
415
405
|
if not _bdry_spec_str.startswith("ΔHHI"):
|
|
@@ -425,12 +415,12 @@ def gen_plot_boundary(
|
|
|
425
415
|
case _:
|
|
426
416
|
_plot_line_color = _pt_mdco.dark_red
|
|
427
417
|
|
|
428
|
-
_dh_bar = _gso.safeharbor
|
|
429
|
-
_g_val = _gso.safeharbor
|
|
418
|
+
_dh_bar = _gso.safeharbor.divr
|
|
419
|
+
_g_val = _gso.safeharbor.guppi
|
|
430
420
|
|
|
431
|
-
_r_bar = _gso.presumption
|
|
421
|
+
_r_bar = _gso.presumption.rec
|
|
432
422
|
|
|
433
|
-
_dhhi_val = getattr(_gso, _gs_str)
|
|
423
|
+
_dhhi_val = getattr(_gso, _gs_str).delta
|
|
434
424
|
_s_mid = sqrt(_dhhi_val / 2)
|
|
435
425
|
_delta_val = _g_val / _r_bar if _gs_str == "safeharbor" else _s_mid / (1 - _s_mid)
|
|
436
426
|
|
|
@@ -456,7 +446,9 @@ def gen_plot_boundary(
|
|
|
456
446
|
_plot_label_uom,
|
|
457
447
|
)
|
|
458
448
|
|
|
459
|
-
_bndry_data_dict |= {
|
|
449
|
+
_bndry_data_dict |= {
|
|
450
|
+
_bdry_spec_str: (_bdry_spec_dict["sheet_name"], _bdry_data, _bdry_area)
|
|
451
|
+
} # type: ignore
|
|
460
452
|
_bdry_s1, _bdry_s2 = zip(*_bdry_data, strict=True)
|
|
461
453
|
|
|
462
454
|
_ax1.plot(
|
|
@@ -466,30 +458,26 @@ def gen_plot_boundary(
|
|
|
466
458
|
color=_plot_line_color,
|
|
467
459
|
linestyle=_plot_line_style,
|
|
468
460
|
linewidth=_plot_line_width,
|
|
461
|
+
alpha=_plot_line_alpha,
|
|
469
462
|
zorder=_zrdr,
|
|
470
463
|
)
|
|
471
464
|
|
|
472
465
|
print("\t", _bdry_spec_str, f"{_bdry_s2[0]:.1%}")
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
f"{_bdry_s2[0]:.1%}",
|
|
489
|
-
(_bdry_s1[0], _bdry_s2[0]),
|
|
490
|
-
(-0.005, 0),
|
|
491
|
-
"right",
|
|
492
|
-
)
|
|
466
|
+
if _bdry_spec_str.startswith(("ΔHHI", "OSWAG Min")):
|
|
467
|
+
_plot_annotator(
|
|
468
|
+
_ax1,
|
|
469
|
+
f"({_bdry_s1[1]:.1%}, {_bdry_s2[1]:.1%})",
|
|
470
|
+
(_bdry_s1[1], _bdry_s2[1]),
|
|
471
|
+
(0.005, 0),
|
|
472
|
+
"left",
|
|
473
|
+
)
|
|
474
|
+
elif _bdry_spec_str.startswith("SAG") or _bdry_spec_str in (
|
|
475
|
+
"CPSWAG Premerger HHI-contribution",
|
|
476
|
+
"CPSWAG Max Div Ratio",
|
|
477
|
+
):
|
|
478
|
+
_plot_annotator(
|
|
479
|
+
_ax1, f"{_bdry_s2[0]:.1%}", (_bdry_s1[0], _bdry_s2[0]), (-0.005, 0), "right"
|
|
480
|
+
)
|
|
493
481
|
|
|
494
482
|
return _bdry_s1, _bdry_s2
|
|
495
483
|
|
|
@@ -546,9 +534,9 @@ def boundary_data_to_worksheet(
|
|
|
546
534
|
Specified Excel Workbook
|
|
547
535
|
|
|
548
536
|
"""
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
)
|
|
537
|
+
_sheet_name, _bndry_points, _bndry_area = _bndry_data_dict[_bndry_name]
|
|
538
|
+
|
|
539
|
+
_xl_sheet = _xl_book.add_worksheet(_sheet_name)
|
|
552
540
|
|
|
553
541
|
_xl_sheet.write("A1", "Sound GUPPI Safeharbor")
|
|
554
542
|
_xl_sheet.write("A2", "Merger Screens for Unilateral Effects")
|
|
@@ -574,7 +562,6 @@ def boundary_data_to_worksheet(
|
|
|
574
562
|
)
|
|
575
563
|
_xl_sheet.set_footer(f"&L{_left_footer}")
|
|
576
564
|
|
|
577
|
-
_bndry_points, _bndry_area = _bndry_data_dict[_bndry_name]
|
|
578
565
|
xlh.scalar_to_sheet(_xl_book, _xl_sheet, "B7", _bndry_area, xlh.CFmt.AREA_NUM)
|
|
579
566
|
|
|
580
567
|
_results_header_row = 9
|
mergeron/gen/data_generation.py
CHANGED
|
@@ -1178,7 +1178,7 @@ def _beta_located(
|
|
|
1178
1178
|
"""
|
|
1179
1179
|
Given mean and stddev, return shape parameters for corresponding Beta distribution
|
|
1180
1180
|
|
|
1181
|
-
Solve the first two moments of the standard Beta to get the shape parameters.
|
|
1181
|
+
Solve the first two moments of the standard Beta to get the shape parameters.
|
|
1182
1182
|
|
|
1183
1183
|
Parameters
|
|
1184
1184
|
----------
|
|
@@ -1191,12 +1191,9 @@ def _beta_located(
|
|
|
1191
1191
|
-------
|
|
1192
1192
|
shape parameters for Beta distribution
|
|
1193
1193
|
|
|
1194
|
-
References
|
|
1195
|
-
----------
|
|
1196
|
-
.. [1] NIST. https://www.itl.nist.gov/div898/handbook/eda/section3/eda366h.htm
|
|
1197
|
-
|
|
1198
1194
|
"""
|
|
1199
|
-
|
|
1195
|
+
|
|
1196
|
+
_mul = -1 + _mu * (1 - _mu) / _sigma**2
|
|
1200
1197
|
return np.array([_mu * _mul, (1 - _mu) * _mul], dtype=np.float64)
|
|
1201
1198
|
|
|
1202
1199
|
|
|
@@ -1208,7 +1205,7 @@ def beta_located_bound(_dist_parms: NDArray[np.floating[TF]], /) -> NDArray[np.f
|
|
|
1208
1205
|
Recover the r.v.s as
|
|
1209
1206
|
:math:`\min + (\max - \min) \cdot \symup{Β}(a, b)`,
|
|
1210
1207
|
with `a` and `b` calculated from the specified mean (:math:`\mu`) and
|
|
1211
|
-
variance (:math:`\sigma`). [
|
|
1208
|
+
variance (:math:`\sigma`). [8]_
|
|
1212
1209
|
|
|
1213
1210
|
Parameters
|
|
1214
1211
|
----------
|
|
@@ -1225,7 +1222,7 @@ def beta_located_bound(_dist_parms: NDArray[np.floating[TF]], /) -> NDArray[np.f
|
|
|
1225
1222
|
|
|
1226
1223
|
References
|
|
1227
1224
|
----------
|
|
1228
|
-
.. [
|
|
1225
|
+
.. [8] NIST, Beta Distribution. https://www.itl.nist.gov/div898/handbook/eda/section3/eda366h.htm
|
|
1229
1226
|
""" # noqa: RUF002
|
|
1230
1227
|
|
|
1231
1228
|
_bmu, _bsigma, _bmin, _bmax = _dist_parms
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: mergeron
|
|
3
|
-
Version: 2024.738936.
|
|
3
|
+
Version: 2024.738936.2
|
|
4
4
|
Summary: Analysis of standards defined in Horizontal Merger Guidelines
|
|
5
5
|
License: MIT
|
|
6
6
|
Keywords: merger policy analysis,merger guidelines,merger screening,policy presumptions,concentration standards,upward pricing pressure,GUPPI
|
|
@@ -5,11 +5,11 @@ mergeron/core/__init__.py,sha256=iyfxkX3-SoMS4ZQZKHKPn8JEMN536vpty9oSZf0LHv8,115
|
|
|
5
5
|
mergeron/core/damodaran_margin_data.py,sha256=N1SU_PDjFMoCzCqone-If-gR4PpcG-MK5TfayusOJLs,8166
|
|
6
6
|
mergeron/core/excel_helper.py,sha256=Zx2pZVjrCV3y0IlpX-_18K3-gbvXxJgnJqPnST7Fg8E,7471
|
|
7
7
|
mergeron/core/ftc_merger_investigations_data.py,sha256=C37gFwSSgUFu98FW8ZDlUTgEaz4qYa1aKPC3SPtXChU,26553
|
|
8
|
-
mergeron/core/guidelines_standards.py,sha256=
|
|
9
|
-
mergeron/core/proportions_tests.py,sha256=
|
|
10
|
-
mergeron/core/pseudorandom_numbers.py,sha256=
|
|
8
|
+
mergeron/core/guidelines_standards.py,sha256=VrPH-WApl7o0AolomnJwx4UqZO1rEzEUiIRT8TRb4_c,43316
|
|
9
|
+
mergeron/core/proportions_tests.py,sha256=zALaWNrGOltsCp2ZSP4pcUfrOCaOoR5YDavqxQHADKA,15275
|
|
10
|
+
mergeron/core/pseudorandom_numbers.py,sha256=ZnIE1ixp3JcgJjlulgMsIcWFVAxeyjC9lsiMIk7OHlM,9430
|
|
11
11
|
mergeron/examples/__init__.py,sha256=iyfxkX3-SoMS4ZQZKHKPn8JEMN536vpty9oSZf0LHv8,115
|
|
12
|
-
mergeron/examples/concentration_as_diversion.py,sha256=
|
|
12
|
+
mergeron/examples/concentration_as_diversion.py,sha256=3re3GKMbV0_g2DFb9_1DXmQZpJeoedAbo2s39GFld_o,20692
|
|
13
13
|
mergeron/examples/example_parameterizations.py,sha256=VP-hi7L0j30ffcEzmJ3P8mOj1VjwEWKCTZSx_CaVQxA,4197
|
|
14
14
|
mergeron/examples/guidelines_enforcement_patterns.py,sha256=gpAW9jLLg3bbf4ueCu71QUKIca_eb3tTtAuTwY14m3c,2235
|
|
15
15
|
mergeron/examples/investigations_stats_obs_tables.py,sha256=IDUZqZHiNvyO05d-yaYUJ_3-G_tchA4Z4MTaEICV9g0,17801
|
|
@@ -25,7 +25,7 @@ mergeron/examples/visualize_guidelines_tests.py,sha256=CDnDT8fIu2Ibed4NsUamzamLt
|
|
|
25
25
|
mergeron/ext/__init__.py,sha256=iyfxkX3-SoMS4ZQZKHKPn8JEMN536vpty9oSZf0LHv8,115
|
|
26
26
|
mergeron/ext/tol_colors.py,sha256=wFOHZXWZonbp9mhmSGu9mVujBYhdTsvx9_WikMpoCmo,22229
|
|
27
27
|
mergeron/gen/__init__.py,sha256=iyfxkX3-SoMS4ZQZKHKPn8JEMN536vpty9oSZf0LHv8,115
|
|
28
|
-
mergeron/gen/data_generation.py,sha256=
|
|
28
|
+
mergeron/gen/data_generation.py,sha256=9D-ieJU6oYXf6vMckRRqjz-qdoA7w_3Y4BamlfLCUUU,41348
|
|
29
29
|
mergeron/gen/guidelines_tests.py,sha256=eoDQFIi6CZzSIyxZsaK5pdtwuIXHt8QwBQSV4VGpKs8,15164
|
|
30
30
|
mergeron/gen/investigations_stats.py,sha256=evm8bwaNUPRe9V-RR_DgsumoUYNLGKmkrhSpaBNXXfA,23005
|
|
31
31
|
mergeron/jinja_LaTex_templates/clrrate_cis_summary_table_template.tex.jinja2,sha256=m1fVYQC4Ra3OLk2W_EFeCzwYZ_Ihy9wZbAHs8rBfs00,4836
|
|
@@ -36,6 +36,6 @@ mergeron/jinja_LaTex_templates/mergeron.cls,sha256=AV2mk4-uERvAuMkE95Ka7el6LZsb0
|
|
|
36
36
|
mergeron/jinja_LaTex_templates/mergeron_table_collection_template.tex.jinja2,sha256=nr6xUI0_2KHG4Sz9k1JFVQjs2h9qS9BGt1MeE6Tygs8,2429
|
|
37
37
|
mergeron/jinja_LaTex_templates/setup_tikz_tables.tex.jinja2,sha256=WKVxtp3eoMchfGliQAJMj4w2FtBkWG5z2V3-hBYUYUQ,3292
|
|
38
38
|
mergeron/py.typed,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
|
|
39
|
-
mergeron-2024.738936.
|
|
40
|
-
mergeron-2024.738936.
|
|
41
|
-
mergeron-2024.738936.
|
|
39
|
+
mergeron-2024.738936.2.dist-info/METADATA,sha256=Ths3nxJp21K9_EB460S3yb88-mF7-VZtTEmITNze86s,6452
|
|
40
|
+
mergeron-2024.738936.2.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
|
41
|
+
mergeron-2024.738936.2.dist-info/RECORD,,
|
|
File without changes
|