mergeron 2025.739319.3__py3-none-any.whl → 2025.739341.9__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.

@@ -1,8 +1,7 @@
1
1
  """
2
- Methods to parse FTC Merger Investigations Data, downloading source documents
3
- as necessary
2
+ Methods to parse FTC Merger Investigations Data, downloading source documents as needed.
4
3
 
5
- NOTES
4
+ Notes
6
5
  -----
7
6
  Reported row and column totals from source data are not stored.
8
7
 
@@ -19,7 +18,6 @@ from types import MappingProxyType
19
18
  from typing import Any
20
19
  from zipfile import ZIP_DEFLATED, ZipFile
21
20
 
22
- import msgpack_numpy as m # type: ignore
23
21
  import numpy as np
24
22
  import urllib3
25
23
  from bs4 import BeautifulSoup
@@ -38,8 +36,6 @@ from . import (
38
36
 
39
37
  __version__ = VERSION
40
38
 
41
- m.patch()
42
-
43
39
  WORK_DIR = globals().get("WORK_DIR", PKG_WORK_DIR)
44
40
  """Redefined, in case the user defines WORK_DIR betweeen module imports."""
45
41
 
@@ -49,7 +45,7 @@ if not FID_WORK_DIR.is_dir():
49
45
 
50
46
  INVDATA_ARCHIVE_PATH = WORK_DIR / mdat.FTC_MERGER_INVESTIGATIONS_DATA.name
51
47
  if not INVDATA_ARCHIVE_PATH.is_file():
52
- shutil.copy2(mdat.FTC_MERGER_INVESTIGATIONS_DATA, INVDATA_ARCHIVE_PATH)
48
+ shutil.copy2(mdat.FTC_MERGER_INVESTIGATIONS_DATA, INVDATA_ARCHIVE_PATH) # type: ignore
53
49
 
54
50
  TABLE_NO_RE = re.compile(r"Table \d+\.\d+")
55
51
  TABLE_TYPES = ("ByHHIandDelta", "ByFirmCount")
@@ -95,6 +91,7 @@ CNT_FCOUNT_DICT = {
95
91
 
96
92
 
97
93
  def reverse_map(_dict: Mapping[Any, Any]) -> Mapping[Any, Any]:
94
+ """Reverse a mapping."""
98
95
  return {_v: _k for _k, _v in _dict.items()}
99
96
 
100
97
 
@@ -105,8 +102,7 @@ def construct_data(
105
102
  flag_pharma_for_exclusion: bool = True,
106
103
  rebuild_data: bool = False,
107
104
  ) -> INVData:
108
- """Construct FTC merger investigations data for non-overlapping periods,
109
- from reported data on cumulative periods.
105
+ """Construct FTC merger investigations data for added non-overlapping periods.
110
106
 
111
107
  FTC merger investigations data are reported in cumulative periods,
112
108
  e.g., 1996-2003 and 1996-2011, but the analyst may want data reported in
@@ -114,10 +110,7 @@ def construct_data(
114
110
  reported merger investigations data, the above example is the only instance
115
111
  in which the 1996-2003 data can be subtracted from the cumulative data to
116
112
  extract merger investigations data for the later period.
117
- See also, Kwoka [1]_, Sec. 2.3.3.
118
-
119
- .. [1] Kwoka, J., Greenfield, D., & Gu, C. (2015). Mergers, merger control,
120
- and remedies: A retrospective analysis of U.S. policy. MIT Press.
113
+ See also, Kwoka, Sec. 2.3.3. [#]_
121
114
 
122
115
  Parameters
123
116
  ----------
@@ -133,8 +126,13 @@ def construct_data(
133
126
  -------
134
127
  A dictionary of merger investigations data keyed to reporting periods
135
128
 
136
- """
129
+ References
130
+ ----------
137
131
 
132
+ .. [#] Kwoka, J., Greenfield, D., & Gu, C. (2015). Mergers, merger control,
133
+ and remedies: A retrospective analysis of U.S. policy. MIT Press.
134
+
135
+ """
138
136
  if _archive_path.is_file() and not rebuild_data:
139
137
  with (
140
138
  ZipFile(_archive_path, "r") as _yzh,
@@ -256,7 +254,7 @@ def _construct_no_evidence_data(_invdata: INVData_in, _data_period: str, /) -> N
256
254
 
257
255
 
258
256
  def _construct_new_period_data(
259
- _invdata: INVData,
257
+ _invdata: INVData_in,
260
258
  _data_period: str,
261
259
  /,
262
260
  *,
@@ -396,6 +394,7 @@ def _construct_new_period_data(
396
394
  def invdata_build_aggregate_table(
397
395
  _data_typesub: dict[str, INVTableData], _aggr_table_list: Sequence[str]
398
396
  ) -> INVTableData:
397
+ """Aggregate selected FTC merger investigations data tables within a given time period."""
399
398
  hdr_table_no = _aggr_table_list[0]
400
399
 
401
400
  return INVTableData(
@@ -424,16 +423,16 @@ def _parse_invdata() -> INVData:
424
423
  by range of HHI and ∆HHI.
425
424
 
426
425
  """
427
- # raise ValueError(
428
- # "This function is defined here as documentation.\n"
429
- # "NOTE: License for `pymupdf`, upon which this function depends,"
430
- # " may be incompatible with the MIT license,"
431
- # " under which this pacakge is distributed."
432
- # " Making this fumction operable requires the user to modify"
433
- # " the source code as well as to install an additional package"
434
- # " not distributed with this package or identified as a requirement."
435
- # )
436
- import pymupdf # type: ignore # noqa: PLC0415
426
+ raise ValueError(
427
+ "This function is defined here as documentation.\n"
428
+ "NOTE: License for `pymupdf`, upon which this function depends,"
429
+ " may be incompatible with the MIT license,"
430
+ " under which this pacakge is distributed."
431
+ " Making this fumction operable requires the user to modify"
432
+ " the source code as well as to install an additional package"
433
+ " not distributed with this package or identified as a requirement."
434
+ )
435
+ import pymupdf # type: ignore
437
436
 
438
437
  invdata_docnames = _download_invdata(FID_WORK_DIR)
439
438
 
@@ -591,7 +590,7 @@ def _parse_table_blocks(
591
590
  )
592
591
 
593
592
  table_array = process_table_func(_table_blocks)
594
- if not isinstance(table_array, np.ndarray) or table_array.dtype != np.uint64:
593
+ if not isinstance(table_array, np.ndarray) or table_array.dtype != int:
595
594
  print(table_num)
596
595
  print(_table_blocks)
597
596
  raise ValueError
@@ -612,7 +611,7 @@ def _process_table_blks_conc_type(
612
611
  conc_row_pat = re.compile(r"((?:0|\d,\d{3}) (?:- \d+,\d{3}|\+)|TOTAL)")
613
612
 
614
613
  col_titles_array = tuple(CONC_DELTA_DICT.values())
615
- col_totals: ArrayBIGINT = np.zeros(len(col_titles_array), np.uint64)
614
+ col_totals: ArrayBIGINT = np.zeros(len(col_titles_array), int)
616
615
  invdata_array: ArrayBIGINT = np.array(None)
617
616
 
618
617
  for tbl_blk in _table_blocks:
@@ -620,7 +619,7 @@ def _process_table_blks_conc_type(
620
619
  row_list: list[str] = _blk_str.strip().split("\n")
621
620
  row_title: str = row_list.pop(0)
622
621
  row_key: int = CONC_HHI_DICT[row_title]
623
- row_total = np.array(row_list.pop().replace(",", "").split("/"), np.uint64)
622
+ row_total = np.array(row_list.pop().replace(",", "").split("/"), int)
624
623
  row_array_list: list[list[int]] = []
625
624
  while row_list:
626
625
  enfd_val, clsd_val = row_list.pop(0).split("/")
@@ -633,7 +632,7 @@ def _process_table_blks_conc_type(
633
632
  int(enfd_val) + int(clsd_val),
634
633
  ]
635
634
  ]
636
- row_array = np.array(row_array_list, np.uint64)
635
+ row_array = np.array(row_array_list, int)
637
636
  # Check row totals
638
637
  assert_array_equal(row_total, np.einsum("ij->j", row_array[:, 2:4]))
639
638
 
@@ -669,14 +668,12 @@ def _process_table_blks_cnt_type(
669
668
  cnt_row_pat = re.compile(r"(\d+ (?:to \d+|\+)|TOTAL)")
670
669
 
671
670
  invdata_array: ArrayBIGINT = np.array(None)
672
- col_totals: ArrayBIGINT = np.zeros(3, np.uint64) # "enforced", "closed", "total"
671
+ col_totals: ArrayBIGINT = np.zeros(3, int) # "enforced", "closed", "total"
673
672
 
674
673
  for _tbl_blk in _table_blocks:
675
674
  if cnt_row_pat.match(_blk_str := _tbl_blk[-3]):
676
675
  row_list_s = _blk_str.strip().replace(",", "").split("\n")
677
- row_list = np.array(
678
- [CNT_FCOUNT_DICT[row_list_s[0]], *row_list_s[1:]], np.uint64
679
- )
676
+ row_list = np.array([CNT_FCOUNT_DICT[row_list_s[0]], *row_list_s[1:]], int)
680
677
  del row_list_s
681
678
  if row_list[3] != row_list[1] + row_list[2]:
682
679
  raise ValueError(
@@ -694,8 +691,7 @@ def _process_table_blks_cnt_type(
694
691
  continue
695
692
 
696
693
  if not np.array_equal(
697
- np.array(list(col_totals[1:]), np.uint64),
698
- np.einsum("ij->j", invdata_array[:, 1:]),
694
+ np.array(list(col_totals[1:]), int), np.einsum("ij->j", invdata_array[:, 1:])
699
695
  ):
700
696
  raise ValueError("Column totals don't compute.")
701
697
 
@@ -1,6 +1,8 @@
1
1
  """
2
- Methods for defining and analyzing boundaries for Guidelines standards,
3
- with a canvas on which to draw boundaries for Guidelines standards.
2
+ Methods for defining and analyzing boundaries for Guidelines standards.
3
+
4
+ Includes function to create a canvas on which to draw boundaries for
5
+ Guidelines standards.
4
6
 
5
7
  """
6
8
 
@@ -34,6 +36,8 @@ mp.trap_complex = True
34
36
 
35
37
  @frozen
36
38
  class HMGThresholds:
39
+ """Thresholds for Guidelines standards."""
40
+
37
41
  delta: float
38
42
  fc: float
39
43
  rec: float
@@ -47,53 +51,55 @@ class HMGThresholds:
47
51
  @frozen
48
52
  class GuidelinesThresholds:
49
53
  """
50
- Guidelines threholds by Guidelines publication year
54
+ Guidelines thresholds by Guidelines publication year.
51
55
 
52
56
  ΔHHI, Recapture Ratio, GUPPI, Diversion ratio, CMCR, and IPR thresholds
53
57
  constructed from concentration standards in Guidelines published in
54
58
  1992, 2010, and 2023.
55
-
56
59
  """
57
60
 
58
61
  pub_year: HMGPubYear = field(
59
62
  kw_only=False, default=2023, validator=validators.in_([1992, 2010, 2023])
60
63
  )
61
64
  """
62
- Year of publication of the Guidelines
65
+ Year of publication of the Guidelines.
63
66
  """
64
-
65
67
  safeharbor: HMGThresholds = field(kw_only=True, default=None, init=False)
66
68
  """
67
- Negative presumption quantified on various measures
69
+ Negative presumption quantified on various measures.
68
70
 
69
71
  ΔHHI safeharbor bound, default recapture ratio, GUPPI bound,
70
- diversion ratio limit, CMCR, and IPR
72
+ diversion ratio limit, CMCR, and IPR.
71
73
  """
72
74
 
73
75
  presumption: HMGThresholds = field(kw_only=True, default=None, init=False)
74
76
  """
75
- Presumption of harm defined in HMG
77
+ Presumption of harm defined in HMG.
76
78
 
77
79
  ΔHHI bound and corresponding default recapture ratio, GUPPI bound,
78
- diversion ratio limit, CMCR, and IPR
80
+ diversion ratio limit, CMCR, and IPR.
79
81
  """
80
82
 
81
83
  imputed_presumption: HMGThresholds = field(kw_only=True, default=None, init=False)
82
84
  """
83
- Presumption of harm imputed from guidelines
85
+ Presumption of harm imputed from Guidelines.
84
86
 
85
87
  ΔHHI bound inferred from strict numbers-equivalent
86
88
  of (post-merger) HHI presumption, and corresponding default recapture ratio,
87
- GUPPI bound, diversion ratio limit, CMCR, and IPR
89
+ GUPPI bound, diversion ratio limit, CMCR, and IPR.
88
90
  """
89
91
 
90
92
  def __attrs_post_init__(self, /) -> None:
91
- # In the 2023 Guidelines, the agencies do not define a
92
- # negative presumption, or safeharbor. Practically speaking,
93
- # given resource constraints and loss aversion, it is likely
94
- # that staff only investigates mergers that meet the presumption;
95
- # thus, here, the tentative delta safeharbor under
96
- # the 2023 Guidelines is 100 points
93
+ """
94
+ Initialize Guidelines thresholds, based on Guidelines publication year.
95
+
96
+ In the 2023 Guidelines, the agencies do not define a
97
+ negative presumption, or safeharbor. Practically speaking,
98
+ given resource constraints and loss aversion, it is likely
99
+ that staff only investigates mergers that meet the presumption;
100
+ thus, here, the tentative delta safeharbor under
101
+ the 2023 Guidelines is 100 points.
102
+ """
97
103
  hhi_p, dh_s, dh_p = {
98
104
  1992: (0.18, 0.005, 0.01),
99
105
  2010: (0.25, 0.01, 0.02),
@@ -120,7 +126,7 @@ class GuidelinesThresholds:
120
126
 
121
127
  # imputed_presumption is relevant for presumptions implicating
122
128
  # mergers *to* symmetry in numbers-equivalent of post-merger HHI
123
- # as in 2010 U.S.Guidelines
129
+ # as in 2010 U.S.Guidelines.
124
130
  object.__setattr__(
125
131
  self,
126
132
  "imputed_presumption",
@@ -185,6 +191,7 @@ class ConcentrationBoundary:
185
191
  """Market-share pairs as Cartesian coordinates of points on the concentration boundary."""
186
192
 
187
193
  def __attrs_post_init__(self, /) -> None:
194
+ """Initialize boundary and area based on other attributes."""
188
195
  match self.measure_name:
189
196
  case "ΔHHI":
190
197
  conc_fn = gbfn.hhi_delta_boundary
@@ -316,6 +323,7 @@ class DiversionRatioBoundary:
316
323
  """Market-share pairs as Cartesian coordinates of points on the diversion ratio boundary."""
317
324
 
318
325
  def __attrs_post_init__(self, /) -> None:
326
+ """Initialize boundary and area based on other attributes."""
319
327
  share_ratio = critical_share_ratio(
320
328
  self.diversion_ratio, r_bar=self.recapture_ratio
321
329
  )
@@ -448,7 +456,6 @@ def share_from_guppi(
448
456
  recapture ratio.
449
457
 
450
458
  """
451
-
452
459
  return gbfn.round_cust(
453
460
  (_d0 := critical_share_ratio(_guppi_bound, m_star=m_star, r_bar=r_bar))
454
461
  / (1 + _d0)
@@ -1,3 +1,5 @@
1
+ """Helper functions for defining and analyzing boundaries for Guidelines standards."""
2
+
1
3
  import decimal
2
4
  from collections.abc import Callable
3
5
  from typing import Literal, TypedDict
@@ -44,7 +46,7 @@ def dh_area(_delta_bound: float | MPFloat = 0.01, /, *, dps: int = 9) -> float:
44
46
 
45
47
  .. math::
46
48
 
47
- 2 s1 s_2 &= ΔHHI\\
49
+ 2 s1 s_2 &= ΔHHI \\
48
50
  s_1 + s_2 &= 1
49
51
 
50
52
  Parameters
@@ -59,7 +61,6 @@ def dh_area(_delta_bound: float | MPFloat = 0.01, /, *, dps: int = 9) -> float:
59
61
  Area under ΔHHI boundary.
60
62
 
61
63
  """
62
-
63
64
  _delta_bound = mpf(f"{_delta_bound}")
64
65
  _s_naught = (1 - mp.sqrt(1 - 2 * _delta_bound)) / 2
65
66
 
@@ -89,7 +90,6 @@ def hhi_delta_boundary(
89
90
  Array of share-pairs, area under boundary.
90
91
 
91
92
  """
92
-
93
93
  _delta_bound = mpf(f"{_delta_bound}")
94
94
  _s_naught = 1 / 2 * (1 - mp.sqrt(1 - 2 * _delta_bound))
95
95
  _s_mid = mp.sqrt(_delta_bound / 2)
@@ -202,7 +202,7 @@ def hhi_post_contrib_boundary(
202
202
 
203
203
 
204
204
  # hand-rolled root finding
205
- def shrratio_boundary_wtd_avg( # noqa: PLR0914
205
+ def shrratio_boundary_wtd_avg(
206
206
  _delta_star: float = 0.075,
207
207
  _r_val: float = DEFAULT_REC_RATIO,
208
208
  /,
@@ -214,13 +214,13 @@ def shrratio_boundary_wtd_avg( # noqa: PLR0914
214
214
  recapture_form: Literal["inside-out", "proportional"] = "inside-out",
215
215
  dps: int = 5,
216
216
  ) -> GuidelinesBoundary:
217
- """
217
+ R"""
218
218
  Share combinations on the share-weighted average diversion ratio boundary.
219
219
 
220
220
  Parameters
221
221
  ----------
222
222
  _delta_star
223
- Share ratio (:math:`\\overline{d} / \\overline{r}`)
223
+ Share ratio (:math:`\overline{d} / \overline{r}`)
224
224
  _r_val
225
225
  recapture ratio
226
226
  agg_method
@@ -299,7 +299,6 @@ def shrratio_boundary_wtd_avg( # noqa: PLR0914
299
299
 
300
300
 
301
301
  """
302
-
303
302
  _delta_star, _r_val = (mpf(f"{_v}") for _v in (_delta_star, _r_val))
304
303
  _s_mid = mp.fdiv(_delta_star, 1 + _delta_star)
305
304
 
@@ -407,7 +406,7 @@ def shrratio_boundary_wtd_avg( # noqa: PLR0914
407
406
  )
408
407
 
409
408
 
410
- def shrratio_boundary_xact_avg( # noqa: PLR0914
409
+ def shrratio_boundary_xact_avg(
411
410
  _delta_star: float = 0.075,
412
411
  _r_val: float = DEFAULT_REC_RATIO,
413
412
  /,
@@ -415,9 +414,8 @@ def shrratio_boundary_xact_avg( # noqa: PLR0914
415
414
  recapture_form: Literal["inside-out", "proportional"] = "inside-out",
416
415
  dps: int = 5,
417
416
  ) -> GuidelinesBoundary:
418
- """
419
- Share combinations for the simple average GUPPI boundary with symmetric
420
- merging-firm margins.
417
+ R"""
418
+ Share combinations for the exact average diversion/share-ratio boundary.
421
419
 
422
420
  Notes
423
421
  -----
@@ -455,7 +453,7 @@ def shrratio_boundary_xact_avg( # noqa: PLR0914
455
453
  Parameters
456
454
  ----------
457
455
  _delta_star
458
- Share ratio (:math:`\\overline{d} / \\overline{r}`).
456
+ Share ratio (:math:`\overline{d} / \overline{r}`).
459
457
  _r_val
460
458
  Recapture ratio
461
459
  recapture_form
@@ -469,7 +467,6 @@ def shrratio_boundary_xact_avg( # noqa: PLR0914
469
467
  Array of share-pairs, area under boundary, area under boundary.
470
468
 
471
469
  """
472
-
473
470
  _delta_star, _r_val = (mpf(f"{_v}") for _v in (_delta_star, _r_val))
474
471
  _s_mid = _delta_star / (1 + _delta_star)
475
472
  _step_size = mp.power(10, -dps)
@@ -570,9 +567,8 @@ def shrratio_boundary_min(
570
567
  recapture_form: str = "inside-out",
571
568
  dps: int = 10,
572
569
  ) -> GuidelinesBoundary:
573
- """
574
- Share combinations on the minimum GUPPI boundary, with symmetric
575
- merging-firm margins.
570
+ R"""
571
+ Share combinations on the minimum diversion-ratio/share-ratio boundary.
576
572
 
577
573
  Notes
578
574
  -----
@@ -584,7 +580,7 @@ def shrratio_boundary_min(
584
580
  Parameters
585
581
  ----------
586
582
  _delta_star
587
- Share ratio (:math:`\\overline{d} / \\overline{r}`).
583
+ Share ratio (:math:`\overline{d} / \overline{r}`).
588
584
  _r_val
589
585
  Recapture ratio.
590
586
  recapture_form
@@ -598,7 +594,6 @@ def shrratio_boundary_min(
598
594
  Array of share-pairs, area under boundary.
599
595
 
600
596
  """
601
-
602
597
  _delta_star, _r_val = (mpf(f"{_v}") for _v in (_delta_star, _r_val))
603
598
  _s_intcpt = mpf("1.00")
604
599
  _s_mid = _delta_star / (1 + _delta_star)
@@ -623,14 +618,13 @@ def shrratio_boundary_min(
623
618
  def shrratio_boundary_max(
624
619
  _delta_star: float = 0.075, _: float = DEFAULT_REC_RATIO, /, *, dps: int = 10
625
620
  ) -> GuidelinesBoundary:
626
- """
627
- Share combinations on the minimum GUPPI boundary with symmetric
628
- merging-firm margins.
621
+ R"""
622
+ Share combinations on the minimum diversion-ratio/share-ratio boundary.
629
623
 
630
624
  Parameters
631
625
  ----------
632
626
  _delta_star
633
- Share ratio (:math:`\\overline{d} / \\overline{r}`).
627
+ Share ratio (:math:`\overline{d} / \overline{r}`).
634
628
  _
635
629
  Placeholder for recapture ratio included for consistency with other
636
630
  share-ratio boundary functions.
@@ -642,7 +636,6 @@ def shrratio_boundary_max(
642
636
  Array of share-pairs, area under boundary.
643
637
 
644
638
  """
645
-
646
639
  _delta_star = mpf(f"{_delta_star}")
647
640
  _s_intcpt = _delta_star
648
641
  _s_mid = _delta_star / (1 + _delta_star)
@@ -691,8 +684,8 @@ def _shrratio_boundary_intcpt(
691
684
  def lerp[LerpT: (float, MPFloat, ArrayDouble, ArrayBIGINT)](
692
685
  _x1: LerpT, _x2: LerpT, _r: float | MPFloat = 0.25, /
693
686
  ) -> LerpT:
694
- """
695
- From the function of the same name in the C++ standard [2]_
687
+ R"""
688
+ From the function of the same name in the C++ standard [#]_.
696
689
 
697
690
  Constructs the weighted average, :math:`w_1 x_1 + w_2 x_2`, where
698
691
  :math:`w_1 = 1 - r` and :math:`w_2 = r`.
@@ -707,7 +700,7 @@ def lerp[LerpT: (float, MPFloat, ArrayDouble, ArrayBIGINT)](
707
700
  Returns
708
701
  -------
709
702
  The linear interpolation, or weighted average,
710
- :math:`x_1 + r \\cdot (x_1 - x_2) \\equiv (1 - r) \\cdot x_1 + r \\cdot x_2`.
703
+ :math:`x_1 + r \cdot (x_1 - x_2) \equiv (1 - r) \cdot x_1 + r \cdot x_2`.
711
704
 
712
705
  Raises
713
706
  ------
@@ -717,10 +710,9 @@ def lerp[LerpT: (float, MPFloat, ArrayDouble, ArrayBIGINT)](
717
710
  References
718
711
  ----------
719
712
 
720
- .. [2] C++ Reference, https://en.cppreference.com/w/cpp/numeric/lerp
713
+ .. [#] C++ Reference, https://en.cppreference.com/w/cpp/numeric/lerp
721
714
 
722
715
  """
723
-
724
716
  if not 0 <= _r <= 1:
725
717
  raise ValueError("Specified interpolation weight must lie in [0, 1].")
726
718
  elif _r == 0:
@@ -739,7 +731,7 @@ def round_cust(
739
731
  rounding_mode: str = "ROUND_HALF_UP",
740
732
  ) -> float:
741
733
  """
742
- Custom rounding, to the nearest 0.5% by default.
734
+ Round to given fraction; the nearest 0.5% by default.
743
735
 
744
736
  Parameters
745
737
  ----------
@@ -766,7 +758,6 @@ def round_cust(
766
758
  the specified precision, :code:`frac`.
767
759
 
768
760
  """
769
-
770
761
  if rounding_mode not in {
771
762
  decimal.ROUND_05UP,
772
763
  decimal.ROUND_CEILING,
@@ -793,11 +784,10 @@ def boundary_plot(
793
784
  mktshare_axes_flag: bool = True,
794
785
  backend: Literal["pgf"] | str | None = "pgf",
795
786
  ) -> tuple[mpl.pyplot, mpl.pyplot.Figure, mpl.axes.Axes, Callable[..., mpl.axes.Axes]]:
796
- """Setup basic figure and axes for plots of safe harbor boundaries.
787
+ """Set up basic figure and axes for plots of safe harbor boundaries.
797
788
 
798
789
  See, https://matplotlib.org/stable/tutorials/text/pgf.html
799
790
  """
800
-
801
791
  if backend == "pgf":
802
792
  mpl.use("pgf")
803
793
 
@@ -16,8 +16,8 @@ from mpmath import mp, mpf # type: ignore
16
16
  from scipy.spatial.distance import minkowski as distance_function # type: ignore
17
17
  from sympy import lambdify, simplify, solve, symbols # type: ignore
18
18
 
19
- from .. import DEFAULT_REC_RATIO, VERSION, ArrayDouble # noqa: TID252
20
- from . import GuidelinesBoundary, MPFloat
19
+ from .. import DEFAULT_REC_RATIO, VERSION # noqa: TID252
20
+ from . import GuidelinesBoundary, GuidelinesBoundaryCallable, MPFloat
21
21
  from . import guidelines_boundary_functions as gbf
22
22
 
23
23
  __version__ = VERSION
@@ -27,13 +27,6 @@ mp.dps = 32
27
27
  mp.trap_complex = True
28
28
 
29
29
 
30
- @frozen
31
- class GuidelinesBoundaryCallable:
32
- boundary_function: Callable[[ArrayDouble], ArrayDouble]
33
- area: float
34
- s_naught: float = 0
35
-
36
-
37
30
  def dh_area_quad(_dh_val: float = 0.01, /) -> float:
38
31
  """
39
32
  Area under the ΔHHI boundary.
@@ -52,7 +45,6 @@ def dh_area_quad(_dh_val: float = 0.01, /) -> float:
52
45
  Area under ΔHHI boundary.
53
46
 
54
47
  """
55
-
56
48
  _dh_val = mpf(f"{_dh_val}")
57
49
  _s_naught = (1 - mp.sqrt(1 - 2 * _dh_val)) / 2
58
50
 
@@ -79,7 +71,6 @@ def hhi_delta_boundary_qdtr(_dh_val: float = 0.01, /) -> GuidelinesBoundaryCalla
79
71
  Callable to generate array of share-pairs, area under boundary.
80
72
 
81
73
  """
82
-
83
74
  _dh_val = mpf(f"{_dh_val}")
84
75
 
85
76
  _s_1, _s_2 = symbols("s_1, s_2", positive=True)
@@ -113,14 +104,13 @@ def shrratio_boundary_qdtr_wtd_avg(
113
104
  weighting: Literal["own-share", "cross-product-share"] | None = "own-share",
114
105
  recapture_form: Literal["inside-out", "proportional"] = "inside-out",
115
106
  ) -> GuidelinesBoundaryCallable:
116
- """
117
- Share combinations for the share-weighted average GUPPI boundary with symmetric
118
- merging-firm margins.
107
+ R"""
108
+ Share combinations for the share-weighted average share-ratio boundary.
119
109
 
120
110
  Parameters
121
111
  ----------
122
112
  _delta_star
123
- corollary to GUPPI bound (:math:`\\overline{g} / (m^* \\cdot \\overline{r})`)
113
+ corollary to GUPPI bound (:math:`\overline{g} / (m^* \cdot \overline{r})`)
124
114
  _r_val
125
115
  recapture ratio
126
116
  weighting
@@ -134,7 +124,6 @@ def shrratio_boundary_qdtr_wtd_avg(
134
124
  Array of share-pairs, area under boundary.
135
125
 
136
126
  """
137
-
138
127
  _delta_star = mpf(f"{_delta_star}")
139
128
  _s_mid = _delta_star / (1 + _delta_star)
140
129
  s_naught = 0
@@ -222,7 +211,7 @@ def shrratio_boundary_qdtr_wtd_avg(
222
211
  )
223
212
 
224
213
 
225
- def shrratio_boundary_distance( # noqa: PLR0914
214
+ def shrratio_boundary_distance(
226
215
  _delta_star: float = 0.075,
227
216
  _r_val: float = DEFAULT_REC_RATIO,
228
217
  /,
@@ -232,9 +221,8 @@ def shrratio_boundary_distance( # noqa: PLR0914
232
221
  recapture_form: Literal["inside-out", "proportional"] = "inside-out",
233
222
  dps: int = 5,
234
223
  ) -> gbf.GuidelinesBoundary:
235
- """
236
- Share combinations for the GUPPI boundaries using various aggregators with
237
- symmetric merging-firm margins.
224
+ R"""
225
+ Share combinations for the share-ratio boundaries using various aggregators.
238
226
 
239
227
  Reimplements the arithmetic-averages and distance estimations from function,
240
228
  `shrratio_boundary_wtd_avg` but uses the Minkowski-distance function,
@@ -245,7 +233,7 @@ def shrratio_boundary_distance( # noqa: PLR0914
245
233
  Parameters
246
234
  ----------
247
235
  _delta_star
248
- corollary to GUPPI bound (:math:`\\overline{g} / (m^* \\cdot \\overline{r})`)
236
+ corollary to GUPPI bound (:math:`\overline{g} / (m^* \cdot \overline{r})`)
249
237
  _r_val
250
238
  recapture ratio
251
239
  agg_method
@@ -263,7 +251,6 @@ def shrratio_boundary_distance( # noqa: PLR0914
263
251
  Array of share-pairs, area under boundary.
264
252
 
265
253
  """
266
-
267
254
  _delta_star = mpf(f"{_delta_star}")
268
255
 
269
256
  # parameters for iteration
@@ -379,7 +366,7 @@ def shrratio_boundary_distance( # noqa: PLR0914
379
366
  )
380
367
 
381
368
 
382
- def shrratio_boundary_xact_avg_mp( # noqa: PLR0914
369
+ def shrratio_boundary_xact_avg_mp(
383
370
  _delta_star: float = 0.075,
384
371
  _r_val: float = DEFAULT_REC_RATIO,
385
372
  /,
@@ -387,7 +374,7 @@ def shrratio_boundary_xact_avg_mp( # noqa: PLR0914
387
374
  recapture_form: Literal["inside-out", "proportional"] = "inside-out",
388
375
  dps: int = 5,
389
376
  ) -> gbf.GuidelinesBoundary:
390
- """
377
+ R"""
391
378
  Share combinations along the simple average diversion-ratio boundary.
392
379
 
393
380
  Notes
@@ -426,7 +413,7 @@ def shrratio_boundary_xact_avg_mp( # noqa: PLR0914
426
413
  Parameters
427
414
  ----------
428
415
  _delta_star
429
- Share ratio (:math:`\\overline{d} / \\overline{r}`).
416
+ Share ratio (:math:`\overline{d} / \overline{r}`).
430
417
  _r_val
431
418
  Recapture ratio
432
419
  recapture_form
@@ -440,7 +427,6 @@ def shrratio_boundary_xact_avg_mp( # noqa: PLR0914
440
427
  Array of share-pairs, area under boundary, area under boundary.
441
428
 
442
429
  """
443
-
444
430
  _delta_star = mpf(f"{_delta_star}")
445
431
  _s_mid = _delta_star / (1 + _delta_star)
446
432
  _bdry_step_sz = 10**-dps
@@ -534,7 +520,7 @@ def shrratio_boundary_xact_avg_mp( # noqa: PLR0914
534
520
 
535
521
  # shrratio_boundary_wtd_avg_autoroot
536
522
  # this function is about half as fast as the manual one! ... and a touch less precise
537
- def _shrratio_boundary_wtd_avg_autoroot( # noqa: PLR0914
523
+ def _shrratio_boundary_wtd_avg_autoroot(
538
524
  _delta_star: float = 0.075,
539
525
  _r_val: float = DEFAULT_REC_RATIO,
540
526
  /,
@@ -546,13 +532,13 @@ def _shrratio_boundary_wtd_avg_autoroot( # noqa: PLR0914
546
532
  recapture_form: Literal["inside-out", "proportional"] = "inside-out",
547
533
  dps: int = 5,
548
534
  ) -> GuidelinesBoundary:
549
- """
535
+ R"""
550
536
  Share combinations on the share-weighted average diversion ratio boundary.
551
537
 
552
538
  Parameters
553
539
  ----------
554
540
  _delta_star
555
- Share ratio (:math:`\\overline{d} / \\overline{r}`)
541
+ Share ratio (:math:`\overline{d} / \overline{r}`)
556
542
  _r_val
557
543
  recapture ratio
558
544
  agg_method
@@ -631,7 +617,6 @@ def _shrratio_boundary_wtd_avg_autoroot( # noqa: PLR0914
631
617
 
632
618
 
633
619
  """
634
-
635
620
  _delta_star, _r_val = (mpf(f"{_v}") for _v in (_delta_star, _r_val))
636
621
  _s_mid = mp.fdiv(_delta_star, 1 + _delta_star)
637
622