mergeron 2024.738949.0__py3-none-any.whl → 2024.738949.5__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/damodaran_margin_data.py +6 -6
- mergeron/core/excel_helper.py +6 -7
- mergeron/core/ftc_merger_investigations_data.py +5 -6
- mergeron/core/guidelines_boundaries.py +315 -100
- mergeron/core/proportions_tests.py +6 -6
- mergeron/core/pseudorandom_numbers.py +6 -6
- mergeron/examples/concentration_as_diversion.py +60 -41
- mergeron/gen/_data_generation_functions_nonpublic.py +3 -5
- mergeron/gen/data_generation.py +3 -4
- mergeron/gen/investigations_stats.py +5 -8
- mergeron/gen/upp_tests.py +6 -7
- {mergeron-2024.738949.0.dist-info → mergeron-2024.738949.5.dist-info}/METADATA +1 -1
- {mergeron-2024.738949.0.dist-info → mergeron-2024.738949.5.dist-info}/RECORD +14 -14
- {mergeron-2024.738949.0.dist-info → mergeron-2024.738949.5.dist-info}/WHEEL +0 -0
|
@@ -32,13 +32,8 @@ price-cost margins fall in the interval :math:`[0, 1]`.
|
|
|
32
32
|
|
|
33
33
|
"""
|
|
34
34
|
|
|
35
|
-
from importlib.metadata import version
|
|
36
|
-
|
|
37
|
-
from .. import _PKG_NAME, DATA_DIR # noqa: TID252
|
|
38
|
-
|
|
39
|
-
__version__ = version(_PKG_NAME)
|
|
40
|
-
|
|
41
35
|
from collections.abc import Mapping
|
|
36
|
+
from importlib.metadata import version
|
|
42
37
|
from pathlib import Path
|
|
43
38
|
from types import MappingProxyType
|
|
44
39
|
|
|
@@ -51,6 +46,11 @@ from requests_toolbelt.downloadutils import stream # type: ignore
|
|
|
51
46
|
from scipy import stats # type: ignore
|
|
52
47
|
from xlrd import open_workbook # type: ignore
|
|
53
48
|
|
|
49
|
+
from .. import _PKG_NAME, DATA_DIR # noqa: TID252
|
|
50
|
+
|
|
51
|
+
__version__ = version(_PKG_NAME)
|
|
52
|
+
|
|
53
|
+
|
|
54
54
|
MGNDATA_ARCHIVE_PATH = DATA_DIR / "damodaran_margin_data_dict.msgpack"
|
|
55
55
|
|
|
56
56
|
|
mergeron/core/excel_helper.py
CHANGED
|
@@ -8,14 +8,9 @@ Includes a flexible system of defining cell formats.
|
|
|
8
8
|
|
|
9
9
|
from __future__ import annotations
|
|
10
10
|
|
|
11
|
-
from importlib.metadata import version
|
|
12
|
-
|
|
13
|
-
from .. import _PKG_NAME # noqa: TID252
|
|
14
|
-
|
|
15
|
-
__version__ = version(_PKG_NAME)
|
|
16
|
-
|
|
17
11
|
import enum
|
|
18
12
|
from collections.abc import Mapping, Sequence
|
|
13
|
+
from importlib.metadata import version
|
|
19
14
|
from types import MappingProxyType
|
|
20
15
|
from typing import Any
|
|
21
16
|
|
|
@@ -23,6 +18,10 @@ import numpy as np
|
|
|
23
18
|
import numpy.typing as npt
|
|
24
19
|
import xlsxwriter # type: ignore
|
|
25
20
|
|
|
21
|
+
from .. import _PKG_NAME # noqa: TID252
|
|
22
|
+
|
|
23
|
+
__version__ = version(_PKG_NAME)
|
|
24
|
+
|
|
26
25
|
|
|
27
26
|
@enum.unique
|
|
28
27
|
class CFmtParent(dict[str, Any], enum.ReprEnum):
|
|
@@ -233,7 +232,7 @@ def xl_fmt(
|
|
|
233
232
|
if isinstance(_cell_fmt, tuple):
|
|
234
233
|
ensure_cell_format_spec_tuple(_cell_fmt)
|
|
235
234
|
for _cf in _cell_fmt:
|
|
236
|
-
_cell_fmt_dict
|
|
235
|
+
_cell_fmt_dict = _cell_fmt_dict | _cf.value
|
|
237
236
|
elif isinstance(_cell_fmt, CFmt):
|
|
238
237
|
_cell_fmt_dict = _cell_fmt.value
|
|
239
238
|
else:
|
|
@@ -8,13 +8,8 @@ We drop reported row and column totals from source data for reducing stored data
|
|
|
8
8
|
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
|
-
from importlib.metadata import version
|
|
12
|
-
|
|
13
|
-
from .. import _PKG_NAME, DATA_DIR # noqa: TID252
|
|
14
|
-
|
|
15
|
-
__version__ = version(_PKG_NAME)
|
|
16
|
-
|
|
17
11
|
from collections.abc import Mapping, Sequence
|
|
12
|
+
from importlib.metadata import version
|
|
18
13
|
from operator import itemgetter
|
|
19
14
|
from pathlib import Path
|
|
20
15
|
from types import MappingProxyType
|
|
@@ -30,6 +25,10 @@ from bs4 import BeautifulSoup
|
|
|
30
25
|
from numpy.testing import assert_array_equal
|
|
31
26
|
from numpy.typing import NDArray
|
|
32
27
|
|
|
28
|
+
from .. import _PKG_NAME, DATA_DIR # noqa: TID252
|
|
29
|
+
|
|
30
|
+
__version__ = version(_PKG_NAME)
|
|
31
|
+
|
|
33
32
|
m.patch()
|
|
34
33
|
|
|
35
34
|
FTCDATA_DIR = DATA_DIR / "FTCData"
|
|
@@ -4,14 +4,10 @@ with a canvas on which to draw boundaries for Guidelines standards.
|
|
|
4
4
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
from importlib.metadata import version
|
|
8
|
-
|
|
9
|
-
from .. import _PKG_NAME # noqa: TID252
|
|
10
|
-
|
|
11
|
-
__version__ = version(_PKG_NAME)
|
|
12
|
-
|
|
13
7
|
import decimal
|
|
8
|
+
from collections.abc import Callable
|
|
14
9
|
from dataclasses import dataclass
|
|
10
|
+
from importlib.metadata import version
|
|
15
11
|
from typing import Any, Literal, TypeAlias
|
|
16
12
|
|
|
17
13
|
import numpy as np
|
|
@@ -19,6 +15,12 @@ from attrs import define, field
|
|
|
19
15
|
from mpmath import mp, mpf # type: ignore
|
|
20
16
|
from numpy.typing import NDArray
|
|
21
17
|
from scipy.spatial.distance import minkowski as distance_function
|
|
18
|
+
from sympy import lambdify, simplify, solve, symbols
|
|
19
|
+
|
|
20
|
+
from .. import _PKG_NAME # noqa: TID252
|
|
21
|
+
|
|
22
|
+
__version__ = version(_PKG_NAME)
|
|
23
|
+
|
|
22
24
|
|
|
23
25
|
mp.prec = 80
|
|
24
26
|
mp.trap_complex = True
|
|
@@ -32,6 +34,13 @@ class GuidelinesBoundary:
|
|
|
32
34
|
area: float
|
|
33
35
|
|
|
34
36
|
|
|
37
|
+
@dataclass(slots=True, frozen=True)
|
|
38
|
+
class GuidelinesBoundaryCallable:
|
|
39
|
+
boundary_function: Callable[[NDArray[np.float64]], NDArray[np.float64]]
|
|
40
|
+
area: float
|
|
41
|
+
s_naught: float = 0
|
|
42
|
+
|
|
43
|
+
|
|
35
44
|
@define(slots=True, frozen=True)
|
|
36
45
|
class HMGThresholds:
|
|
37
46
|
delta: float
|
|
@@ -278,7 +287,12 @@ def gbd_from_dsf(
|
|
|
278
287
|
|
|
279
288
|
|
|
280
289
|
def critical_shrratio(
|
|
281
|
-
_gbd: float = 0.06,
|
|
290
|
+
_gbd: float = 0.06,
|
|
291
|
+
/,
|
|
292
|
+
*,
|
|
293
|
+
m_star: float = 1.00,
|
|
294
|
+
r_bar: float = 0.80,
|
|
295
|
+
frac: float = 1e-16,
|
|
282
296
|
) -> mpf:
|
|
283
297
|
"""
|
|
284
298
|
Corollary to GUPPI bound.
|
|
@@ -298,7 +312,7 @@ def critical_shrratio(
|
|
|
298
312
|
for given margin and recapture rate.
|
|
299
313
|
|
|
300
314
|
"""
|
|
301
|
-
return mpf(f"{_gbd}") / mp.fmul(f"{m_star}", f"{r_bar}")
|
|
315
|
+
return round_cust(mpf(f"{_gbd}") / mp.fmul(f"{m_star}", f"{r_bar}"), frac=frac)
|
|
302
316
|
|
|
303
317
|
|
|
304
318
|
def shr_from_gbd(
|
|
@@ -371,18 +385,18 @@ def boundary_plot(*, mktshares_plot_flag: bool = True) -> tuple[Any, ...]:
|
|
|
371
385
|
r"\setsansfont{Fira Sans Light}",
|
|
372
386
|
R"\setmonofont[Scale=MatchLowercase,]{Fira Mono}",
|
|
373
387
|
R"\defaultfontfeatures[\rmfamily]{",
|
|
374
|
-
R"
|
|
375
|
-
R"
|
|
376
|
-
R"
|
|
388
|
+
R" Ligatures={TeX, Common},",
|
|
389
|
+
R" Numbers={Proportional, Lining},",
|
|
390
|
+
R" }",
|
|
377
391
|
R"\defaultfontfeatures[\sffamily]{",
|
|
378
|
-
R"
|
|
379
|
-
R"
|
|
380
|
-
R"
|
|
381
|
-
R"
|
|
392
|
+
R" Ligatures={TeX, Common},",
|
|
393
|
+
R" Numbers={Monospaced, Lining},",
|
|
394
|
+
R" LetterSpace=0.50,",
|
|
395
|
+
R" }",
|
|
382
396
|
R"\usepackage[",
|
|
383
|
-
R"
|
|
384
|
-
R"
|
|
385
|
-
R"
|
|
397
|
+
R" activate={true, nocompatibility},",
|
|
398
|
+
R" tracking=true,",
|
|
399
|
+
R" ]{microtype}",
|
|
386
400
|
]),
|
|
387
401
|
})
|
|
388
402
|
|
|
@@ -589,19 +603,16 @@ def delta_hhi_boundary(
|
|
|
589
603
|
_s1_zero = 1 / 2 * (1 - mp.sqrt(1 - 2 * _dh_val))
|
|
590
604
|
_s1_one = 1 - _s1_zero
|
|
591
605
|
|
|
592
|
-
_s_mid = mp.sqrt(_dh_val / 2)
|
|
593
|
-
|
|
594
606
|
_dh_step_sz = mp.power(10, -6)
|
|
595
|
-
_s_1 = np.array(mp.arange(
|
|
607
|
+
_s_1 = np.array(mp.arange(_s1_zero, _s1_one + _dh_step_sz, _dh_step_sz))
|
|
596
608
|
_s_2 = _dh_val / (2 * _s_1)
|
|
597
609
|
|
|
598
610
|
# Boundary points
|
|
599
|
-
|
|
600
|
-
np.column_stack((_s_1, _s_2)),
|
|
601
|
-
np.array([(_s1_zero, _s1_one)]),
|
|
611
|
+
_dh_bdry_pts = np.row_stack((
|
|
602
612
|
np.array([(mpf("0.0"), mpf("1.0"))]),
|
|
613
|
+
np.column_stack((_s_1, _s_2)),
|
|
614
|
+
np.array([(mpf("1.0"), mpf("0.0"))]),
|
|
603
615
|
))
|
|
604
|
-
_dh_bdry_pts = np.row_stack((np.flip(_dh_half, 0), np.flip(_dh_half[1:], 1)))
|
|
605
616
|
|
|
606
617
|
_s_1_pts, _s_2_pts = np.split(_dh_bdry_pts, 2, axis=1)
|
|
607
618
|
return GuidelinesBoundary(
|
|
@@ -613,6 +624,42 @@ def delta_hhi_boundary(
|
|
|
613
624
|
)
|
|
614
625
|
|
|
615
626
|
|
|
627
|
+
def delta_hhi_boundary_qdtr(_dh_val: float = 0.01) -> GuidelinesBoundaryCallable:
|
|
628
|
+
"""
|
|
629
|
+
Generate the list of share combination on the ΔHHI boundary.
|
|
630
|
+
|
|
631
|
+
Parameters
|
|
632
|
+
----------
|
|
633
|
+
_dh_val:
|
|
634
|
+
Merging-firms' ΔHHI bound.
|
|
635
|
+
dh_dps
|
|
636
|
+
Number of decimal places for rounding reported shares.
|
|
637
|
+
|
|
638
|
+
Returns
|
|
639
|
+
-------
|
|
640
|
+
Callable to generate array of share-pairs, area under boundary.
|
|
641
|
+
|
|
642
|
+
"""
|
|
643
|
+
|
|
644
|
+
_dh_val = mpf(f"{_dh_val}")
|
|
645
|
+
|
|
646
|
+
_s_1, _s_2 = symbols("s_1, s_2", positive=True)
|
|
647
|
+
|
|
648
|
+
_hhi_eqn = _s_2 - 0.01 / (2 * _s_1)
|
|
649
|
+
|
|
650
|
+
_hhi_bdry = solve(_hhi_eqn, _s_2)[0]
|
|
651
|
+
_s_nought = float(solve(_hhi_eqn.subs({_s_2: 1 - _s_1}), _s_1)[0])
|
|
652
|
+
|
|
653
|
+
_hhi_bdry_area = 2 * (
|
|
654
|
+
_s_nought
|
|
655
|
+
+ mp.quad(lambdify(_s_1, _hhi_bdry, "mpmath"), (_s_nought, 1 - _s_nought))
|
|
656
|
+
)
|
|
657
|
+
|
|
658
|
+
return GuidelinesBoundaryCallable(
|
|
659
|
+
lambdify(_s_1, _hhi_bdry, "numpy"), _hhi_bdry_area, _s_nought
|
|
660
|
+
)
|
|
661
|
+
|
|
662
|
+
|
|
616
663
|
def combined_share_boundary(
|
|
617
664
|
_s_intcpt: float = 0.0625, /, *, bdry_dps: int = 10
|
|
618
665
|
) -> GuidelinesBoundary:
|
|
@@ -801,6 +848,130 @@ def shrratio_boundary_min(
|
|
|
801
848
|
)
|
|
802
849
|
|
|
803
850
|
|
|
851
|
+
def shrratio_boundary_qdtr_wtd_avg(
|
|
852
|
+
_delta_star: float = 0.075,
|
|
853
|
+
_r_val: float = 0.80,
|
|
854
|
+
/,
|
|
855
|
+
*,
|
|
856
|
+
wgtng_policy: Literal["own-share", "cross-product-share"] | None = "own-share",
|
|
857
|
+
recapture_spec: Literal["inside-out", "proportional"] = "inside-out",
|
|
858
|
+
) -> GuidelinesBoundaryCallable:
|
|
859
|
+
"""
|
|
860
|
+
Share combinations for the share-weighted average GUPPI boundary with symmetric
|
|
861
|
+
merging-firm margins.
|
|
862
|
+
|
|
863
|
+
Parameters
|
|
864
|
+
----------
|
|
865
|
+
_delta_star
|
|
866
|
+
corollary to GUPPI bound (:math:`\\overline{g} / (m^* \\cdot \\overline{r})`)
|
|
867
|
+
_r_val
|
|
868
|
+
recapture ratio
|
|
869
|
+
wgtng_policy
|
|
870
|
+
Whether "own-share" or "cross-product-share" (or None for simple, unweighted average)
|
|
871
|
+
recapture_spec
|
|
872
|
+
Whether recapture-ratio is MNL-consistent ("inside-out") or has fixed
|
|
873
|
+
value for both merging firms ("proportional").
|
|
874
|
+
|
|
875
|
+
Returns
|
|
876
|
+
-------
|
|
877
|
+
Array of share-pairs, area under boundary.
|
|
878
|
+
|
|
879
|
+
"""
|
|
880
|
+
|
|
881
|
+
if _delta_star > 1:
|
|
882
|
+
raise ValueError(
|
|
883
|
+
"Margin-adjusted benchmark share ratio, `_delta_star` cannot exceed 1."
|
|
884
|
+
)
|
|
885
|
+
|
|
886
|
+
_delta_star = mpf(f"{_delta_star}")
|
|
887
|
+
_s_mid = _delta_star / (1 + _delta_star)
|
|
888
|
+
_s_naught = 0
|
|
889
|
+
|
|
890
|
+
_s_1, _s_2 = symbols("s_1:3", positive=True)
|
|
891
|
+
|
|
892
|
+
match wgtng_policy:
|
|
893
|
+
case "own-share":
|
|
894
|
+
_bdry_eqn = (
|
|
895
|
+
_s_1 * _s_2 / (1 - _s_1)
|
|
896
|
+
+ _s_2
|
|
897
|
+
* _s_1
|
|
898
|
+
/ (
|
|
899
|
+
(1 - (_r_val * _s_2 + (1 - _r_val) * _s_1))
|
|
900
|
+
if recapture_spec == "inside-out"
|
|
901
|
+
else (1 - _s_2)
|
|
902
|
+
)
|
|
903
|
+
- (_s_1 + _s_2) * _delta_star
|
|
904
|
+
)
|
|
905
|
+
|
|
906
|
+
_bdry_func = solve(_bdry_eqn, _s_2)[0]
|
|
907
|
+
_s_naught = (
|
|
908
|
+
float(solve(simplify(_bdry_eqn.subs({_s_2: 1 - _s_1})), _s_1)[0])
|
|
909
|
+
if recapture_spec == "inside-out"
|
|
910
|
+
else 0
|
|
911
|
+
)
|
|
912
|
+
_bdry_area = float(
|
|
913
|
+
2
|
|
914
|
+
* (
|
|
915
|
+
_s_naught
|
|
916
|
+
+ mp.quad(lambdify(_s_1, _bdry_func, "mpmath"), (_s_naught, _s_mid))
|
|
917
|
+
)
|
|
918
|
+
- (_s_mid**2 + _s_naught**2)
|
|
919
|
+
)
|
|
920
|
+
|
|
921
|
+
case "cross-product-share":
|
|
922
|
+
mp.trap_complex = False
|
|
923
|
+
_d_star = symbols("d", positive=True)
|
|
924
|
+
_bdry_eqn = (
|
|
925
|
+
_s_2 * _s_2 / (1 - _s_1)
|
|
926
|
+
+ _s_1
|
|
927
|
+
* _s_1
|
|
928
|
+
/ (
|
|
929
|
+
(1 - (_r_val * _s_2 + (1 - _r_val) * _s_1))
|
|
930
|
+
if recapture_spec == "inside-out"
|
|
931
|
+
else (1 - _s_2)
|
|
932
|
+
)
|
|
933
|
+
- (_s_1 + _s_2) * _d_star
|
|
934
|
+
)
|
|
935
|
+
|
|
936
|
+
_bdry_func = solve(_bdry_eqn, _s_2)[1]
|
|
937
|
+
_bdry_area = float(
|
|
938
|
+
2
|
|
939
|
+
* (
|
|
940
|
+
mp.quad(
|
|
941
|
+
lambdify(
|
|
942
|
+
_s_1, _bdry_func.subs({_d_star: _delta_star}), "mpmath"
|
|
943
|
+
),
|
|
944
|
+
(0, _s_mid),
|
|
945
|
+
)
|
|
946
|
+
).real
|
|
947
|
+
- _s_mid**2
|
|
948
|
+
)
|
|
949
|
+
|
|
950
|
+
case _:
|
|
951
|
+
_bdry_eqn = (
|
|
952
|
+
1 / 2 * _s_2 / (1 - _s_1)
|
|
953
|
+
+ 1
|
|
954
|
+
/ 2
|
|
955
|
+
* _s_1
|
|
956
|
+
/ (
|
|
957
|
+
(1 - (_r_val * _s_2 + (1 - _r_val) * _s_1))
|
|
958
|
+
if recapture_spec == "inside-out"
|
|
959
|
+
else (1 - _s_2)
|
|
960
|
+
)
|
|
961
|
+
- _delta_star
|
|
962
|
+
)
|
|
963
|
+
|
|
964
|
+
_bdry_func = solve(_bdry_eqn, _s_2)[0]
|
|
965
|
+
_bdry_area = float(
|
|
966
|
+
2 * (mp.quad(lambdify(_s_1, _bdry_func, "mpmath"), (0, _s_mid)))
|
|
967
|
+
- _s_mid**2
|
|
968
|
+
)
|
|
969
|
+
|
|
970
|
+
return GuidelinesBoundaryCallable(
|
|
971
|
+
lambdify(_s_1, _bdry_func, "numpy"), _bdry_area, _s_naught
|
|
972
|
+
)
|
|
973
|
+
|
|
974
|
+
|
|
804
975
|
def shrratio_boundary_wtd_avg(
|
|
805
976
|
_delta_star: float = 0.075,
|
|
806
977
|
_r_val: float = 0.80,
|
|
@@ -815,16 +986,36 @@ def shrratio_boundary_wtd_avg(
|
|
|
815
986
|
Share combinations for the share-weighted average GUPPI boundary with symmetric
|
|
816
987
|
merging-firm margins.
|
|
817
988
|
|
|
989
|
+
Parameters
|
|
990
|
+
----------
|
|
991
|
+
_delta_star
|
|
992
|
+
corollary to GUPPI bound (:math:`\\overline{g} / (m^* \\cdot \\overline{r})`)
|
|
993
|
+
_r_val
|
|
994
|
+
recapture ratio
|
|
995
|
+
avg_method
|
|
996
|
+
Whether "arithmetic", "geometric", or "distance".
|
|
997
|
+
wgtng_policy
|
|
998
|
+
Whether "own-share" or "cross-product-share" (or None for simple, unweighted average).
|
|
999
|
+
recapture_spec
|
|
1000
|
+
Whether recapture-ratio is MNL-consistent ("inside-out") or has fixed
|
|
1001
|
+
value for both merging firms ("proportional").
|
|
1002
|
+
gbd_dps
|
|
1003
|
+
Number of decimal places for rounding returned shares and area.
|
|
1004
|
+
|
|
1005
|
+
Returns
|
|
1006
|
+
-------
|
|
1007
|
+
Array of share-pairs, area under boundary.
|
|
1008
|
+
|
|
818
1009
|
Notes
|
|
819
1010
|
-----
|
|
820
1011
|
An analytical expression for the share-weighted arithmetic mean boundary
|
|
821
1012
|
is derived and plotted from y-intercept to the ray of symmetry as follows::
|
|
822
1013
|
|
|
823
1014
|
from sympy import plot as symplot, solve, symbols
|
|
824
|
-
s_1, s_2
|
|
1015
|
+
s_1, s_2 = symbols("s_1 s_2", positive=True)
|
|
825
1016
|
|
|
826
1017
|
g_val, r_val, m_val = 0.06, 0.80, 0.30
|
|
827
|
-
|
|
1018
|
+
delta_star = g_val / (r_val * m_val)
|
|
828
1019
|
|
|
829
1020
|
# recapture_spec == "inside-out"
|
|
830
1021
|
oswag = solve(
|
|
@@ -834,7 +1025,7 @@ def shrratio_boundary_wtd_avg(
|
|
|
834
1025
|
s_2
|
|
835
1026
|
)[0]
|
|
836
1027
|
symplot(
|
|
837
|
-
oswag
|
|
1028
|
+
oswag,
|
|
838
1029
|
(s_1, 0., d_hat / (1 + d_hat)),
|
|
839
1030
|
ylabel=s_2
|
|
840
1031
|
)
|
|
@@ -846,7 +1037,7 @@ def shrratio_boundary_wtd_avg(
|
|
|
846
1037
|
s_2
|
|
847
1038
|
)[1]
|
|
848
1039
|
symplot(
|
|
849
|
-
cpwag
|
|
1040
|
+
cpwag,
|
|
850
1041
|
(s_1, 0., d_hat / (1 + d_hat)),
|
|
851
1042
|
ylabel=s_2
|
|
852
1043
|
)
|
|
@@ -859,7 +1050,7 @@ def shrratio_boundary_wtd_avg(
|
|
|
859
1050
|
s_2
|
|
860
1051
|
)[0]
|
|
861
1052
|
symplot(
|
|
862
|
-
oswag
|
|
1053
|
+
oswag,
|
|
863
1054
|
(s_1, 0., d_hat / (1 + d_hat)),
|
|
864
1055
|
ylabel=s_2
|
|
865
1056
|
)
|
|
@@ -871,30 +1062,11 @@ def shrratio_boundary_wtd_avg(
|
|
|
871
1062
|
s_2
|
|
872
1063
|
)[1]
|
|
873
1064
|
symplot(
|
|
874
|
-
cpswag
|
|
1065
|
+
cpswag,
|
|
875
1066
|
(s_1, 0.0, d_hat / (1 + d_hat)),
|
|
876
1067
|
ylabel=s_2
|
|
877
1068
|
)
|
|
878
1069
|
|
|
879
|
-
Parameters
|
|
880
|
-
----------
|
|
881
|
-
_delta_star
|
|
882
|
-
corollary to GUPPI bound (:math:`\\overline{g} / (m^* \\cdot \\overline{r})`)
|
|
883
|
-
_r_val
|
|
884
|
-
recapture ratio
|
|
885
|
-
avg_method
|
|
886
|
-
Whether "arithmetic", "geometric", or "distance".
|
|
887
|
-
wgtng_policy
|
|
888
|
-
Whether "own-share" or "cross-product-share".
|
|
889
|
-
recapture_spec
|
|
890
|
-
Whether recapture-ratio is MNL-consistent ("inside-out") or has fixed
|
|
891
|
-
value for both merging firms ("proportional").
|
|
892
|
-
gbd_dps
|
|
893
|
-
Number of decimal places for rounding returned shares and area.
|
|
894
|
-
|
|
895
|
-
Returns
|
|
896
|
-
-------
|
|
897
|
-
Array of share-pairs, area under boundary.
|
|
898
1070
|
|
|
899
1071
|
"""
|
|
900
1072
|
|
|
@@ -921,7 +1093,7 @@ def shrratio_boundary_wtd_avg(
|
|
|
921
1093
|
_s_2 = _s_2_pre * (1 + _theta)
|
|
922
1094
|
|
|
923
1095
|
if (_s_1 + _s_2) > mpf("0.99875"):
|
|
924
|
-
#
|
|
1096
|
+
# Loss of accuracy at 3-9s and up
|
|
925
1097
|
break
|
|
926
1098
|
|
|
927
1099
|
while True:
|
|
@@ -948,10 +1120,11 @@ def shrratio_boundary_wtd_avg(
|
|
|
948
1120
|
case _:
|
|
949
1121
|
_delta_test = lerp(_de_1, _de_2, _r)
|
|
950
1122
|
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
1123
|
+
_test_flag, _incr_decr = (
|
|
1124
|
+
(_delta_test > _delta_star, -1)
|
|
1125
|
+
if wgtng_policy == "cross-product-share"
|
|
1126
|
+
else (_delta_test < _delta_star, 1)
|
|
1127
|
+
)
|
|
955
1128
|
|
|
956
1129
|
if _test_flag:
|
|
957
1130
|
_s_2 += _incr_decr * _gbd_step_sz
|
|
@@ -970,31 +1143,41 @@ def shrratio_boundary_wtd_avg(
|
|
|
970
1143
|
_s_2_pre = _s_2
|
|
971
1144
|
_s_1_pre = _s_1
|
|
972
1145
|
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
1146
|
+
if _s_2_oddval:
|
|
1147
|
+
_s_2_evnsum -= _s_2_pre
|
|
1148
|
+
else:
|
|
1149
|
+
_s_2_oddsum -= _s_1_pre
|
|
1150
|
+
|
|
1151
|
+
_s_intcpt = _shrratio_boundary_intcpt(
|
|
1152
|
+
_s_1_pre,
|
|
1153
|
+
_delta_star,
|
|
1154
|
+
_r_val,
|
|
1155
|
+
recapture_spec=recapture_spec,
|
|
1156
|
+
avg_method=avg_method,
|
|
1157
|
+
wgtng_policy=wgtng_policy,
|
|
980
1158
|
)
|
|
981
1159
|
|
|
982
|
-
|
|
983
|
-
|
|
1160
|
+
if wgtng_policy == "own-share":
|
|
1161
|
+
_gbd_prtlarea = (
|
|
1162
|
+
_gbd_step_sz * (4 * _s_2_oddsum + 2 * _s_2_evnsum + _s_mid + _s_2_pre) / 3
|
|
1163
|
+
)
|
|
1164
|
+
# Area under boundary
|
|
1165
|
+
_gbdry_area_total = float(
|
|
1166
|
+
2 * (_s_1_pre + _gbd_prtlarea)
|
|
1167
|
+
- (mp.power(_s_mid, "2") + mp.power(_s_1_pre, "2"))
|
|
1168
|
+
)
|
|
984
1169
|
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
_s_intcpt
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
_s_intcpt = _delta_star * mp.sqrt("2")
|
|
992
|
-
case _:
|
|
993
|
-
_s_intcpt = _s_2_pre
|
|
1170
|
+
else:
|
|
1171
|
+
_gbd_prtlarea = (
|
|
1172
|
+
_gbd_step_sz * (4 * _s_2_oddsum + 2 * _s_2_evnsum + _s_mid + _s_intcpt) / 3
|
|
1173
|
+
)
|
|
1174
|
+
# Area under boundary
|
|
1175
|
+
_gbdry_area_total = float(2 * _gbd_prtlarea - mp.power(_s_mid, "2"))
|
|
994
1176
|
|
|
995
1177
|
_gbdry_points = np.row_stack((_gbdry_points, (mpf("0.0"), _s_intcpt))).astype(
|
|
996
1178
|
np.float64
|
|
997
1179
|
)
|
|
1180
|
+
|
|
998
1181
|
# Points defining boundary to point-of-symmetry
|
|
999
1182
|
return GuidelinesBoundary(
|
|
1000
1183
|
np.row_stack((np.flip(_gbdry_points, 0), np.flip(_gbdry_points[1:], 1))),
|
|
@@ -1281,10 +1464,10 @@ def shrratio_boundary_avg(
|
|
|
1281
1464
|
_s_intcpt = _s_2
|
|
1282
1465
|
|
|
1283
1466
|
_gbd_prtlarea = 2 * _gbd_step_sz * (
|
|
1284
|
-
mp.fmul(4
|
|
1285
|
-
+ mp.fmul(2
|
|
1286
|
-
+ mp.fmul(1
|
|
1287
|
-
) - mp.power(_s_mid, 2)
|
|
1467
|
+
mp.fmul(4, _s_2_oddsum)
|
|
1468
|
+
+ mp.fmul(2, _s_2_evnsum)
|
|
1469
|
+
+ mp.fmul(1, _s_mid + _s_intcpt)
|
|
1470
|
+
) / 3 - mp.power(_s_mid, 2)
|
|
1288
1471
|
|
|
1289
1472
|
_gbdry_points = np.array(_gbdry_points, np.float64)
|
|
1290
1473
|
return GuidelinesBoundary(
|
|
@@ -1310,8 +1493,8 @@ def shrratio_boundary_distance(
|
|
|
1310
1493
|
Reimplements the arithmetic-averages and distance estimations from function,
|
|
1311
1494
|
`shrratio_boundary_wtd_avg`but uses the Minkowski-distance function,
|
|
1312
1495
|
`scipy.spatial.distance.minkowski` for all aggregators. This reimplementation
|
|
1313
|
-
is
|
|
1314
|
-
|
|
1496
|
+
is useful for testing the output of `shrratio_boundary_wtd_avg`
|
|
1497
|
+
but runs considerably slower.
|
|
1315
1498
|
|
|
1316
1499
|
Parameters
|
|
1317
1500
|
----------
|
|
@@ -1392,10 +1575,11 @@ def shrratio_boundary_distance(
|
|
|
1392
1575
|
(_de_1, _de_2), (0.0, 0.0), p=2, w=_weights_i
|
|
1393
1576
|
)
|
|
1394
1577
|
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1578
|
+
_test_flag, _incr_decr = (
|
|
1579
|
+
(_delta_test > _delta_star, -1)
|
|
1580
|
+
if wgtng_policy == "cross-product-share"
|
|
1581
|
+
else (_delta_test < _delta_star, 1)
|
|
1582
|
+
)
|
|
1399
1583
|
|
|
1400
1584
|
if _test_flag:
|
|
1401
1585
|
_s_2 += _incr_decr * _gbd_step_sz
|
|
@@ -1414,22 +1598,60 @@ def shrratio_boundary_distance(
|
|
|
1414
1598
|
_s_2_pre = _s_2
|
|
1415
1599
|
_s_1_pre = _s_1
|
|
1416
1600
|
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1601
|
+
if _s_2_oddval:
|
|
1602
|
+
_s_2_evnsum -= _s_2_pre
|
|
1603
|
+
else:
|
|
1604
|
+
_s_2_oddsum -= _s_1_pre
|
|
1605
|
+
|
|
1606
|
+
_s_intcpt = _shrratio_boundary_intcpt(
|
|
1607
|
+
_s_1_pre,
|
|
1608
|
+
_delta_star,
|
|
1609
|
+
_r_val,
|
|
1610
|
+
recapture_spec=recapture_spec,
|
|
1611
|
+
avg_method=avg_method,
|
|
1612
|
+
wgtng_policy=wgtng_policy,
|
|
1613
|
+
)
|
|
1614
|
+
|
|
1615
|
+
if wgtng_policy == "own-share":
|
|
1616
|
+
_gbd_prtlarea = (
|
|
1617
|
+
_gbd_step_sz * (4 * _s_2_oddsum + 2 * _s_2_evnsum + _s_mid + _s_2_pre) / 3
|
|
1618
|
+
)
|
|
1619
|
+
# Area under boundary
|
|
1620
|
+
_gbdry_area_total = 2 * (_s_1_pre + _gbd_prtlarea) - (
|
|
1621
|
+
mp.power(_s_mid, "2") + mp.power(_s_1_pre, "2")
|
|
1622
|
+
)
|
|
1623
|
+
|
|
1624
|
+
else:
|
|
1625
|
+
_gbd_prtlarea = (
|
|
1626
|
+
_gbd_step_sz * (4 * _s_2_oddsum + 2 * _s_2_evnsum + _s_mid + _s_intcpt) / 3
|
|
1423
1627
|
)
|
|
1628
|
+
# Area under boundary
|
|
1629
|
+
_gbdry_area_total = 2 * _gbd_prtlarea - mp.power(_s_mid, "2")
|
|
1630
|
+
|
|
1631
|
+
_gbdry_points = np.row_stack((_gbdry_points, (mpf("0.0"), _s_intcpt))).astype(
|
|
1632
|
+
np.float64
|
|
1633
|
+
)
|
|
1634
|
+
# Points defining boundary to point-of-symmetry
|
|
1635
|
+
return GuidelinesBoundary(
|
|
1636
|
+
np.row_stack((np.flip(_gbdry_points, 0), np.flip(_gbdry_points[1:], 1))),
|
|
1637
|
+
round(float(_gbdry_area_total), gbd_dps),
|
|
1424
1638
|
)
|
|
1425
1639
|
|
|
1426
|
-
# Area under boundary
|
|
1427
|
-
_gbdry_area_total = 2 * _gbd_prtlarea - mp.power(_s_mid, 2)
|
|
1428
1640
|
|
|
1641
|
+
def _shrratio_boundary_intcpt(
|
|
1642
|
+
_s_2_pre: float,
|
|
1643
|
+
_delta_star: mpf,
|
|
1644
|
+
_r_val: mpf,
|
|
1645
|
+
/,
|
|
1646
|
+
*,
|
|
1647
|
+
recapture_spec: Literal["inside-out", "proportional"],
|
|
1648
|
+
avg_method: Literal["arithmetic", "geometric", "distance"],
|
|
1649
|
+
wgtng_policy: Literal["cross-product-share", "own-share"] | None,
|
|
1650
|
+
) -> float:
|
|
1429
1651
|
match wgtng_policy:
|
|
1430
1652
|
case "cross-product-share":
|
|
1431
1653
|
_s_intcpt = _delta_star
|
|
1432
|
-
case "own-
|
|
1654
|
+
case "own-share":
|
|
1433
1655
|
_s_intcpt = mpf("1.0")
|
|
1434
1656
|
case None if avg_method == "distance":
|
|
1435
1657
|
_s_intcpt = _delta_star * mp.sqrt("2")
|
|
@@ -1445,11 +1667,4 @@ def shrratio_boundary_distance(
|
|
|
1445
1667
|
case _:
|
|
1446
1668
|
_s_intcpt = _s_2_pre
|
|
1447
1669
|
|
|
1448
|
-
|
|
1449
|
-
np.float64
|
|
1450
|
-
)
|
|
1451
|
-
# Points defining boundary to point-of-symmetry
|
|
1452
|
-
return GuidelinesBoundary(
|
|
1453
|
-
np.row_stack((np.flip(_gbdry_points, 0), np.flip(_gbdry_points[1:], 1))),
|
|
1454
|
-
round(float(_gbdry_area_total), gbd_dps),
|
|
1455
|
-
)
|
|
1670
|
+
return _s_intcpt
|
|
@@ -7,14 +7,9 @@ Functions to estimate confidence intervals for
|
|
|
7
7
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
|
+
from collections.abc import Sequence
|
|
10
11
|
from dataclasses import dataclass
|
|
11
12
|
from importlib.metadata import version
|
|
12
|
-
|
|
13
|
-
from .. import _PKG_NAME # noqa: TID252
|
|
14
|
-
|
|
15
|
-
__version__ = version(_PKG_NAME)
|
|
16
|
-
|
|
17
|
-
from collections.abc import Sequence
|
|
18
13
|
from typing import Literal, TypeVar
|
|
19
14
|
|
|
20
15
|
import numpy as np
|
|
@@ -22,6 +17,11 @@ from numpy.typing import NBitBase, NDArray
|
|
|
22
17
|
from scipy.optimize import OptimizeResult, root # type: ignore
|
|
23
18
|
from scipy.stats import beta, chi2, norm # type: ignore
|
|
24
19
|
|
|
20
|
+
from .. import _PKG_NAME # noqa: TID252
|
|
21
|
+
|
|
22
|
+
__version__ = version(_PKG_NAME)
|
|
23
|
+
|
|
24
|
+
|
|
25
25
|
TI = TypeVar("TI", bound=NBitBase)
|
|
26
26
|
|
|
27
27
|
|
|
@@ -6,14 +6,9 @@ https://github.com/numpy/numpy/issues/16313.
|
|
|
6
6
|
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
|
-
from importlib.metadata import version
|
|
10
|
-
|
|
11
|
-
from .. import _PKG_NAME # noqa: TID252
|
|
12
|
-
|
|
13
|
-
__version__ = version(_PKG_NAME)
|
|
14
|
-
|
|
15
9
|
import concurrent.futures
|
|
16
10
|
from collections.abc import Sequence
|
|
11
|
+
from importlib.metadata import version
|
|
17
12
|
from multiprocessing import cpu_count
|
|
18
13
|
from typing import Literal, TypeVar
|
|
19
14
|
|
|
@@ -21,6 +16,11 @@ import numpy as np
|
|
|
21
16
|
from numpy.random import PCG64DXSM, Generator, SeedSequence
|
|
22
17
|
from numpy.typing import NBitBase, NDArray
|
|
23
18
|
|
|
19
|
+
from .. import _PKG_NAME # noqa: TID252
|
|
20
|
+
|
|
21
|
+
__version__ = version(_PKG_NAME)
|
|
22
|
+
|
|
23
|
+
|
|
24
24
|
TF = TypeVar("TF", bound=NBitBase)
|
|
25
25
|
TI = TypeVar("TI", bound=NBitBase)
|
|
26
26
|
|
|
@@ -27,14 +27,15 @@ from pathlib import Path
|
|
|
27
27
|
from typing import Any, Literal
|
|
28
28
|
|
|
29
29
|
import matplotlib.axes as mpa
|
|
30
|
-
from joblib import Parallel, cpu_count, delayed
|
|
31
|
-
from numpy import pi
|
|
32
|
-
from xlsxwriter import Workbook
|
|
33
|
-
|
|
34
30
|
import mergeron.core.excel_helper as xlh
|
|
35
31
|
import mergeron.core.guidelines_boundaries as gbl
|
|
36
32
|
import mergeron.ext.tol_colors as ptcolor
|
|
33
|
+
import mergeron.gen.investigations_stats as isl
|
|
34
|
+
from jinja2 import FileSystemLoader
|
|
35
|
+
from joblib import Parallel, cpu_count, delayed
|
|
37
36
|
from mergeron import DATA_DIR
|
|
37
|
+
from numpy import pi
|
|
38
|
+
from xlsxwriter import Workbook
|
|
38
39
|
|
|
39
40
|
PROG_PATH = Path(__file__)
|
|
40
41
|
|
|
@@ -79,6 +80,13 @@ BDRY_SPECS_DICT: Mapping[str, Mapping[str, Any]] = {
|
|
|
79
80
|
"func_str": R"s_M",
|
|
80
81
|
"func": gbl.combined_share_boundary,
|
|
81
82
|
},
|
|
83
|
+
"SAG Average Div Ratio": {
|
|
84
|
+
"title_str": "Aggregated-diversion-ratio boundary, simple average",
|
|
85
|
+
"sheet_name": "SAG, average",
|
|
86
|
+
"func_str": R"(d_{12} + d_{21}) / 2",
|
|
87
|
+
"func": gbl.shrratio_boundary_wtd_avg,
|
|
88
|
+
"func_kwargs": {"wgtng_policy": None, "recapture_spec": RECAPTURE_SPEC},
|
|
89
|
+
},
|
|
82
90
|
"SAG Div Ratio Distance": {
|
|
83
91
|
"title_str": "Aggregated-diversion-ratio boundary, distance",
|
|
84
92
|
"sheet_name": "SAG, distance",
|
|
@@ -90,13 +98,6 @@ BDRY_SPECS_DICT: Mapping[str, Mapping[str, Any]] = {
|
|
|
90
98
|
"avg_method": "distance",
|
|
91
99
|
},
|
|
92
100
|
},
|
|
93
|
-
"SAG Average Div Ratio": {
|
|
94
|
-
"title_str": "Aggregated-diversion-ratio boundary, simple average",
|
|
95
|
-
"sheet_name": "SAG, average",
|
|
96
|
-
"func_str": R"(d_{12} + d_{21}) / 2",
|
|
97
|
-
"func": gbl.shrratio_boundary_xact_avg,
|
|
98
|
-
"func_kwargs": {"recapture_spec": RECAPTURE_SPEC},
|
|
99
|
-
},
|
|
100
101
|
"CPSWAG Premerger HHI-contribution": {
|
|
101
102
|
"title_str": "Premerger HHI-contribution boundary",
|
|
102
103
|
"sheet_name": "CPSWAG, HHI-contrib-pre",
|
|
@@ -133,7 +134,7 @@ BDRY_SPECS_DICT: Mapping[str, Mapping[str, Any]] = {
|
|
|
133
134
|
}
|
|
134
135
|
|
|
135
136
|
|
|
136
|
-
def tabulate_boundary_stats(_gpubyr:
|
|
137
|
+
def tabulate_boundary_stats(_gpubyr: gbl.HMGPubYear, /) -> None:
|
|
137
138
|
"""
|
|
138
139
|
Parameters
|
|
139
140
|
----------
|
|
@@ -142,15 +143,17 @@ def tabulate_boundary_stats(_gpubyr: Literal[1992, 2010, 2023], /) -> None:
|
|
|
142
143
|
are drawn
|
|
143
144
|
|
|
144
145
|
"""
|
|
146
|
+
_invres_rate_table_content = isl.StatsContainer()
|
|
147
|
+
|
|
145
148
|
gso = gbl.GuidelinesThresholds(_gpubyr)
|
|
146
149
|
_dhhi_val, _r_val, _g_val = (
|
|
147
150
|
getattr(gso.presumption, _f) for _f in ("delta", "rec", "guppi")
|
|
148
151
|
)
|
|
149
152
|
|
|
150
153
|
_dhhi_seq = (
|
|
151
|
-
(0.01, 0.02,
|
|
154
|
+
(0.005, 0.01, 0.02, gso.imputed_presumption.delta, 0.08)
|
|
152
155
|
if _gpubyr == 2010
|
|
153
|
-
else (0.005, 0.01, 0.02,
|
|
156
|
+
else (0.005, 0.01, 0.02, gso.imputed_presumption.delta, 0.08)
|
|
154
157
|
)
|
|
155
158
|
|
|
156
159
|
_bdry_approx_data_dict = {
|
|
@@ -166,7 +169,7 @@ def tabulate_boundary_stats(_gpubyr: Literal[1992, 2010, 2023], /) -> None:
|
|
|
166
169
|
),
|
|
167
170
|
)
|
|
168
171
|
for _k in BDRY_SPECS_DICT
|
|
169
|
-
if not _k.endswith("Distance")
|
|
172
|
+
# if not _k.endswith("Distance")
|
|
170
173
|
}
|
|
171
174
|
}
|
|
172
175
|
_bdry_approx_data_dict |= {
|
|
@@ -176,32 +179,46 @@ def tabulate_boundary_stats(_gpubyr: Literal[1992, 2010, 2023], /) -> None:
|
|
|
176
179
|
}
|
|
177
180
|
|
|
178
181
|
_bdry_data = Parallel(n_jobs=-1)(
|
|
179
|
-
delayed(_dhhi_stats)(_dhhi_val, _r_val
|
|
182
|
+
delayed(_dhhi_stats)(_dhhi_val, _r_val) for _dhhi_val in _dhhi_seq
|
|
180
183
|
)
|
|
181
184
|
_bdry_approx_data_dict |= dict(_bdry_data)
|
|
182
185
|
|
|
183
|
-
|
|
186
|
+
_data_str = ""
|
|
187
|
+
_data_str = "{} \\\\ \n".format(
|
|
188
|
+
" & ".join(
|
|
189
|
+
_k.replace("Criterion", R"{\text{} \\ Criterion}") # \phantom{Criterion}
|
|
190
|
+
for _k in _bdry_approx_data_dict
|
|
191
|
+
)
|
|
192
|
+
)
|
|
184
193
|
for _sk in _bdry_approx_data_dict["Criterion"]:
|
|
185
|
-
|
|
186
|
-
" & ".join(
|
|
187
|
-
_bdry_approx_data_dict[_k][_sk] for _k in _bdry_approx_data_dict
|
|
188
|
-
),
|
|
189
|
-
R"\\",
|
|
194
|
+
_data_str += "{} \\\\ \n".format(
|
|
195
|
+
" & ".join(_bdry_approx_data_dict[_k][_sk] for _k in _bdry_approx_data_dict)
|
|
190
196
|
)
|
|
197
|
+
print(_data_str)
|
|
198
|
+
|
|
199
|
+
_invres_rate_table_content.data_str = _data_str
|
|
200
|
+
|
|
201
|
+
_j2_env = isl.latex_jinja_env
|
|
202
|
+
_j2_env.loader = FileSystemLoader(str(PROG_PATH.parent / "templates"))
|
|
203
|
+
_j2_templ = _j2_env.get_template(
|
|
204
|
+
"concentration_as_diversion_intrinsic_enforcement_rates.tex.jinja2"
|
|
205
|
+
)
|
|
206
|
+
PROG_PATH.parents[1].joinpath(
|
|
207
|
+
f"{PROG_PATH.stem}_intrinsic_enforcement_rates_{_gpubyr}.tex"
|
|
208
|
+
).write_text(_j2_templ.render(tmpl_data=_invres_rate_table_content))
|
|
191
209
|
|
|
192
210
|
|
|
193
|
-
def _dhhi_stats(
|
|
194
|
-
_dhhi_val: float, _r_val: float, _g_val: float
|
|
195
|
-
) -> tuple[str, dict[str, str]]:
|
|
211
|
+
def _dhhi_stats(_dhhi_val: float, _r_val: float) -> tuple[str, dict[str, str]]:
|
|
196
212
|
_dhhi_val = round(_dhhi_val, 5)
|
|
197
213
|
|
|
198
|
-
|
|
199
|
-
|
|
214
|
+
_divr_val = gbl.gbd_from_dsf(_dhhi_val, r_bar=_r_val)
|
|
215
|
+
_delta_val = gbl.critical_shrratio(_divr_val, r_bar=_r_val)
|
|
216
|
+
# _s_mid = sqrt(_dhhi_val / 2)
|
|
200
217
|
|
|
201
|
-
_delta_val = _s_mid / (1 - _s_mid)
|
|
202
|
-
if _dhhi_val * 1e4 in (50, 100, 200):
|
|
203
|
-
|
|
204
|
-
_divr_val = _r_val * _delta_val
|
|
218
|
+
# _delta_val = _s_mid / (1 - _s_mid)
|
|
219
|
+
# if _dhhi_val * 1e4 in (50, 100, 200):
|
|
220
|
+
# _delta_val = gbl.critical_shrratio()(_r_val * _delta_val) / _r_val
|
|
221
|
+
# _divr_val = _r_val * _delta_val
|
|
205
222
|
|
|
206
223
|
print(
|
|
207
224
|
"Processing data for ΔHHI = {0:.{1}f} points;".format(
|
|
@@ -238,15 +255,16 @@ def _bdry_stats_col(
|
|
|
238
255
|
return _bdry_spec, f"{_hhi_m_pre_prob:6.5f}"
|
|
239
256
|
case _ if "Div Ratio" in _bdry_spec:
|
|
240
257
|
_gbd_func = BDRY_SPECS_DICT[_bdry_spec]["func"]
|
|
241
|
-
|
|
258
|
+
_within_bdry_area = _gbd_func(
|
|
242
259
|
_delta_val, _r_val, **BDRY_SPECS_DICT[_bdry_spec].get("func_kwargs", {})
|
|
243
|
-
)
|
|
260
|
+
).area
|
|
244
261
|
_within_bdry_prob = 2 * _within_bdry_area
|
|
245
|
-
|
|
246
|
-
_hhi_m_pre_prob
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
262
|
+
if _bdry_spec.startswith("CPSWAG"):
|
|
263
|
+
_within_conc_bdry_prob = _hhi_m_pre_prob
|
|
264
|
+
elif _bdry_spec.startswith("SAG"):
|
|
265
|
+
_within_conc_bdry_prob = _cs_prob
|
|
266
|
+
else:
|
|
267
|
+
_within_conc_bdry_prob = _dhhi_prob
|
|
250
268
|
|
|
251
269
|
return _bdry_spec, R"{{ {:6.5f} \\ {:.2f}\% }}".format(
|
|
252
270
|
_within_bdry_prob,
|
|
@@ -257,7 +275,7 @@ def _bdry_stats_col(
|
|
|
257
275
|
|
|
258
276
|
|
|
259
277
|
def plot_and_save_boundary_coords(
|
|
260
|
-
_gpubyr:
|
|
278
|
+
_gpubyr: gbl.HMGPubYear,
|
|
261
279
|
_xl_book: Workbook,
|
|
262
280
|
/,
|
|
263
281
|
layout: Literal["collected", "distributed"] = "collected",
|
|
@@ -599,8 +617,9 @@ def boundary_data_to_worksheet(
|
|
|
599
617
|
|
|
600
618
|
|
|
601
619
|
if __name__ == "__main__":
|
|
602
|
-
|
|
603
|
-
|
|
620
|
+
gpubyrs: list[gbl.HMGPubYear] = [1992, 2010, 2023]
|
|
621
|
+
for gpubyr in gpubyrs[2:][:1]:
|
|
622
|
+
tabulate_boundary_stats(gpubyr)
|
|
604
623
|
|
|
605
624
|
# Initiliaze workbook for saving boundary coordinates
|
|
606
625
|
with Workbook(
|
|
@@ -5,17 +5,13 @@ Non-public functions called in data_generation.py
|
|
|
5
5
|
from __future__ import annotations
|
|
6
6
|
|
|
7
7
|
from importlib.metadata import version
|
|
8
|
-
|
|
9
|
-
from .. import _PKG_NAME # noqa: TID252
|
|
10
|
-
|
|
11
|
-
__version__ = version(_PKG_NAME)
|
|
12
|
-
|
|
13
8
|
from typing import Literal
|
|
14
9
|
|
|
15
10
|
import numpy as np
|
|
16
11
|
from numpy.random import SeedSequence
|
|
17
12
|
from numpy.typing import NDArray
|
|
18
13
|
|
|
14
|
+
from .. import _PKG_NAME # noqa: TID252
|
|
19
15
|
from ..core.damodaran_margin_data import resample_mgn_data # noqa: TID252
|
|
20
16
|
from ..core.pseudorandom_numbers import ( # noqa: TID252
|
|
21
17
|
DIST_PARMS_DEFAULT,
|
|
@@ -37,6 +33,8 @@ from . import (
|
|
|
37
33
|
SSZConstants,
|
|
38
34
|
)
|
|
39
35
|
|
|
36
|
+
__version__ = version(_PKG_NAME)
|
|
37
|
+
|
|
40
38
|
|
|
41
39
|
def _gen_share_data(
|
|
42
40
|
_mkt_sample_spec: MarketSampleSpec,
|
mergeron/gen/data_generation.py
CHANGED
|
@@ -7,15 +7,12 @@ from __future__ import annotations
|
|
|
7
7
|
|
|
8
8
|
from importlib.metadata import version
|
|
9
9
|
|
|
10
|
-
from .. import _PKG_NAME # noqa: TID252
|
|
11
|
-
|
|
12
|
-
__version__ = version(_PKG_NAME)
|
|
13
|
-
|
|
14
10
|
import attrs
|
|
15
11
|
import numpy as np
|
|
16
12
|
from numpy.random import SeedSequence
|
|
17
13
|
from numpy.typing import NDArray
|
|
18
14
|
|
|
15
|
+
from .. import _PKG_NAME # noqa: TID252
|
|
19
16
|
from . import (
|
|
20
17
|
EMPTY_ARRAY_DEFAULT,
|
|
21
18
|
TF,
|
|
@@ -35,6 +32,8 @@ from ._data_generation_functions_nonpublic import (
|
|
|
35
32
|
_gen_share_data,
|
|
36
33
|
)
|
|
37
34
|
|
|
35
|
+
__version__ = version(_PKG_NAME)
|
|
36
|
+
|
|
38
37
|
|
|
39
38
|
def gen_market_sample(
|
|
40
39
|
_mkt_sample_spec: MarketSampleSpec,
|
|
@@ -3,16 +3,10 @@ Routines to format and print summary data on merger enforcement patterns.
|
|
|
3
3
|
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
-
import subprocess
|
|
7
|
-
from importlib.metadata import version
|
|
8
|
-
|
|
9
|
-
from .. import _PKG_NAME, DATA_DIR # noqa: TID252
|
|
10
|
-
|
|
11
|
-
__version__ = version(_PKG_NAME)
|
|
12
|
-
|
|
13
|
-
|
|
14
6
|
import enum
|
|
7
|
+
import subprocess
|
|
15
8
|
from collections.abc import Mapping, Sequence
|
|
9
|
+
from importlib.metadata import version
|
|
16
10
|
from pathlib import Path
|
|
17
11
|
from types import SimpleNamespace
|
|
18
12
|
|
|
@@ -22,10 +16,13 @@ from jinja2 import Environment, FileSystemLoader, Template, select_autoescape
|
|
|
22
16
|
from numpy.typing import NDArray
|
|
23
17
|
from scipy.interpolate import interp1d # type: ignore
|
|
24
18
|
|
|
19
|
+
from .. import _PKG_NAME, DATA_DIR # noqa: TID252
|
|
25
20
|
from ..core import ftc_merger_investigations_data as fid # noqa: TID252
|
|
26
21
|
from ..core.proportions_tests import propn_ci # noqa: TID252
|
|
27
22
|
from . import TF, TI, INVResolution
|
|
28
23
|
|
|
24
|
+
__version__ = version(_PKG_NAME)
|
|
25
|
+
|
|
29
26
|
|
|
30
27
|
@enum.unique
|
|
31
28
|
class INDGRPConstants(enum.StrEnum):
|
mergeron/gen/upp_tests.py
CHANGED
|
@@ -4,16 +4,11 @@ from generated market data.
|
|
|
4
4
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
from importlib.metadata import version
|
|
8
|
-
from pathlib import Path
|
|
9
|
-
|
|
10
|
-
from .. import _PKG_NAME # noqa: TID252
|
|
11
|
-
|
|
12
|
-
__version__ = version(_PKG_NAME)
|
|
13
|
-
|
|
14
7
|
from collections.abc import Sequence
|
|
15
8
|
from contextlib import suppress
|
|
16
9
|
from dataclasses import fields
|
|
10
|
+
from importlib.metadata import version
|
|
11
|
+
from pathlib import Path
|
|
17
12
|
from typing import Literal, TypeAlias, TypedDict
|
|
18
13
|
|
|
19
14
|
import numpy as np
|
|
@@ -24,6 +19,7 @@ from joblib import Parallel, cpu_count, delayed # type: ignore
|
|
|
24
19
|
from numpy.random import SeedSequence
|
|
25
20
|
from numpy.typing import NDArray
|
|
26
21
|
|
|
22
|
+
from .. import _PKG_NAME # noqa: TID252
|
|
27
23
|
from ..core import guidelines_boundaries as gbl # noqa: TID252
|
|
28
24
|
from . import (
|
|
29
25
|
EMPTY_ARRAY_DEFAULT,
|
|
@@ -40,6 +36,9 @@ from . import (
|
|
|
40
36
|
from . import data_generation as dgl
|
|
41
37
|
from . import investigations_stats as isl
|
|
42
38
|
|
|
39
|
+
__version__ = version(_PKG_NAME)
|
|
40
|
+
|
|
41
|
+
|
|
43
42
|
ptb.parameters.MAX_NUMEXPR_THREADS = 8
|
|
44
43
|
ptb.parameters.MAX_BLOSC_THREADS = 4
|
|
45
44
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: mergeron
|
|
3
|
-
Version: 2024.738949.
|
|
3
|
+
Version: 2024.738949.5
|
|
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
|
|
@@ -2,14 +2,14 @@ mergeron/License.txt,sha256=csSkn4lgUmJ0VEw1KAFZ3a8q0L4XccUdJ6Jj6xSNNRY,1246
|
|
|
2
2
|
mergeron/__init__.py,sha256=gk_2mS6jdui5fVmVHHfZVaEG9LyO3vfRATnES29ajRA,398
|
|
3
3
|
mergeron/core/InCommon RSA Server CA cert chain.pem,sha256=W8TqydgY8jphQ4fr6WMdT6jLwqFjHLpx8fFr3LXub4s,4292
|
|
4
4
|
mergeron/core/__init__.py,sha256=iyfxkX3-SoMS4ZQZKHKPn8JEMN536vpty9oSZf0LHv8,115
|
|
5
|
-
mergeron/core/damodaran_margin_data.py,sha256=
|
|
6
|
-
mergeron/core/excel_helper.py,sha256=
|
|
7
|
-
mergeron/core/ftc_merger_investigations_data.py,sha256=
|
|
8
|
-
mergeron/core/guidelines_boundaries.py,sha256=
|
|
9
|
-
mergeron/core/proportions_tests.py,sha256=
|
|
10
|
-
mergeron/core/pseudorandom_numbers.py,sha256=
|
|
5
|
+
mergeron/core/damodaran_margin_data.py,sha256=DHTQdFjuZ5Yl3Dbq0db0QR4FHUqJpZj4yi5zdUncLtg,8166
|
|
6
|
+
mergeron/core/excel_helper.py,sha256=wU3Y325r_YNfoyr92y605m_9ZCDJ01WiR-vahi4KGmc,8094
|
|
7
|
+
mergeron/core/ftc_merger_investigations_data.py,sha256=YYkgeF-b_2_Tk8dsy_4dMz5QpV5UQEr7tB9ORiqKmww,26760
|
|
8
|
+
mergeron/core/guidelines_boundaries.py,sha256=E38g6aonHqqFiSP0Duh_UfUGaHkZlKQt-23Q7EAEtBA,50541
|
|
9
|
+
mergeron/core/proportions_tests.py,sha256=tCrbya1el5u1OFOXphODP6yWOGywuNY6z9LBTsNRKzM,15320
|
|
10
|
+
mergeron/core/pseudorandom_numbers.py,sha256=mSAMJ1zZ58k8j9duT3Ohi_1TCjZaFG1Ud1P_JI1ryYY,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=oDo5InVGLL-pON_ror8XWOMwC6S2dnDvei7Yw_AXgFw,21620
|
|
13
13
|
mergeron/examples/enforcement_boundaries_for_mergers_with_asymmetric_shares.py,sha256=-jOHETKp788pqKTv7U25t28UzVtJNMmUn1FVH7jCiCU,16020
|
|
14
14
|
mergeron/examples/enforcement_boundaries_for_symmetric_firm_mergers.py,sha256=DAljm5NJquE56f-x4pLXzKCdhYQyVpWaM8uGlD6rIEs,5779
|
|
15
15
|
mergeron/examples/example_parameterizations.py,sha256=VP-hi7L0j30ffcEzmJ3P8mOj1VjwEWKCTZSx_CaVQxA,4197
|
|
@@ -25,10 +25,10 @@ mergeron/examples/visualize_guidelines_tests.py,sha256=VE3aotuFOsU-CSt4SymRG8_iV
|
|
|
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=MxjGj4bHklt6R-Xc-iT46pgK4XZNlcMDErnlF3jA7LU,16787
|
|
28
|
-
mergeron/gen/_data_generation_functions_nonpublic.py,sha256=
|
|
29
|
-
mergeron/gen/data_generation.py,sha256=
|
|
30
|
-
mergeron/gen/investigations_stats.py,sha256=
|
|
31
|
-
mergeron/gen/upp_tests.py,sha256=
|
|
28
|
+
mergeron/gen/_data_generation_functions_nonpublic.py,sha256=zBrgIkeaR-5pMZ5sowiM_CkGEqWsTgS7xeZNhB9m4rg,21368
|
|
29
|
+
mergeron/gen/data_generation.py,sha256=uG2-O_JNMH9acm7U91X_XXFnevGbue6sbrQ88RxzzrQ,8867
|
|
30
|
+
mergeron/gen/investigations_stats.py,sha256=cZgghfUHmyU4ZY0Fi8R4iwf21YwzAzbrNpYsNbgEq6g,22812
|
|
31
|
+
mergeron/gen/upp_tests.py,sha256=zc8DUIy66m9jnEwLaX4jSRoNnsf4KgXJL1uVpyd0xYc,16187
|
|
32
32
|
mergeron/jinja_LaTex_templates/clrrate_cis_summary_table_template.tex.jinja2,sha256=ae4JiciU-pt8YAM8mRbsmt4W6ePuN1y1NPCWD95oXIo,4833
|
|
33
33
|
mergeron/jinja_LaTex_templates/ftcinvdata_byhhianddelta_table_template.tex.jinja2,sha256=ODEurkC0UHuWpjRUiQpeW85njSeUEUJYRdYg8gqoEq0,3642
|
|
34
34
|
mergeron/jinja_LaTex_templates/ftcinvdata_summary_table_template.tex.jinja2,sha256=h8_DEE0iskT9tnga5lZtxcoevN7pY4iKF-maErt4UU4,2906
|
|
@@ -37,6 +37,6 @@ mergeron/jinja_LaTex_templates/mergeron.cls,sha256=AV2mk4-uERvAuMkE95Ka7el6LZsb0
|
|
|
37
37
|
mergeron/jinja_LaTex_templates/mergeron_table_collection_template.tex.jinja2,sha256=nr6xUI0_2KHG4Sz9k1JFVQjs2h9qS9BGt1MeE6Tygs8,2429
|
|
38
38
|
mergeron/jinja_LaTex_templates/setup_tikz_tables.tex.jinja2,sha256=WKVxtp3eoMchfGliQAJMj4w2FtBkWG5z2V3-hBYUYUQ,3292
|
|
39
39
|
mergeron/py.typed,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
|
|
40
|
-
mergeron-2024.738949.
|
|
41
|
-
mergeron-2024.738949.
|
|
42
|
-
mergeron-2024.738949.
|
|
40
|
+
mergeron-2024.738949.5.dist-info/METADATA,sha256=v_U_sf-0kwTsgcg3SpLqUv5X9iaTHBOVhuMAt4N7xb0,6362
|
|
41
|
+
mergeron-2024.738949.5.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
42
|
+
mergeron-2024.738949.5.dist-info/RECORD,,
|
|
File without changes
|