mergeron 2025.739439.10__py3-none-any.whl → 2025.739439.12__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/__init__.py CHANGED
@@ -15,7 +15,7 @@ from ruamel import yaml
15
15
 
16
16
  _PKG_NAME: str = Path(__file__).parent.name
17
17
 
18
- VERSION = "2025.739439.10"
18
+ VERSION = "2025.739439.12"
19
19
 
20
20
  __version__ = VERSION
21
21
 
@@ -30,7 +30,7 @@ created/reused.
30
30
  if not WORK_DIR.is_dir():
31
31
  WORK_DIR.mkdir(parents=False)
32
32
 
33
- DEFAULT_REC_RATIO = 0.85
33
+ DEFAULT_REC = 0.85
34
34
 
35
35
  EMPTY_ARRAYDOUBLE = np.array([], float)
36
36
  EMPTY_ARRAYINT = np.array([], int)
@@ -172,19 +172,19 @@ class Enameled(enum.Enum):
172
172
  @this_yaml.register_class
173
173
  @enum.unique
174
174
  class RECForm(str, Enameled):
175
- R"""For derivation of recapture ratio from market shares.
175
+ R"""For derivation of recapture rate from market shares.
176
176
 
177
177
  With :math:`\mathscr{N}` a set of firms, each supplying a
178
178
  single differentiated product, and :math:`\mathscr{M} \subset \mathscr{N}`
179
179
  a putative relevant product market, with
180
180
  :math:`d_{ij}` denoting diversion ratio from good :math:`i` to good :math:`j`,
181
181
  :math:`s_i` denoting market shares, and
182
- :math:`\overline{r}` the default market recapture ratio,
183
- market recapture ratios for the respective products may be specified
182
+ :math:`\overline{r}` the default market recapture rate,
183
+ market recapture rates for the respective products may be specified
184
184
  as having one of the following forms:
185
185
  """
186
186
 
187
- FIXED = "proportional"
187
+ FIXED = "fixed"
188
188
  R"""Given, :math:`\overline{r}`,
189
189
 
190
190
  .. math::
@@ -16,7 +16,7 @@ from attrs import Attribute, field, frozen, validators
16
16
  from mpmath import mp # type: ignore
17
17
 
18
18
  from .. import ( # noqa: TID252
19
- DEFAULT_REC_RATIO,
19
+ DEFAULT_REC,
20
20
  VERSION,
21
21
  ArrayDouble,
22
22
  HMGPubYear,
@@ -53,7 +53,7 @@ class GuidelinesThresholds:
53
53
  """
54
54
  Guidelines thresholds by Guidelines publication year.
55
55
 
56
- ΔHHI, Recapture Ratio, GUPPI, Diversion ratio, CMCR, and IPR thresholds
56
+ ΔHHI, Recapture Rate, GUPPI, Diversion ratio, CMCR, and IPR thresholds
57
57
  constructed from concentration standards in Guidelines published in
58
58
  1992, 2010, and 2023.
59
59
  """
@@ -68,7 +68,7 @@ class GuidelinesThresholds:
68
68
  """
69
69
  Negative presumption quantified on various measures.
70
70
 
71
- ΔHHI safeharbor bound, default recapture ratio, GUPPI bound,
71
+ ΔHHI safeharbor bound, default recapture rate, GUPPI bound,
72
72
  diversion ratio limit, CMCR, and IPR.
73
73
  """
74
74
 
@@ -76,7 +76,7 @@ class GuidelinesThresholds:
76
76
  """
77
77
  Presumption of harm defined in HMG.
78
78
 
79
- ΔHHI bound and corresponding default recapture ratio, GUPPI bound,
79
+ ΔHHI bound and corresponding default recapture rate, GUPPI bound,
80
80
  diversion ratio limit, CMCR, and IPR.
81
81
  """
82
82
 
@@ -85,7 +85,7 @@ class GuidelinesThresholds:
85
85
  Presumption of harm imputed from Guidelines.
86
86
 
87
87
  ΔHHI bound inferred from strict numbers-equivalent
88
- of (post-merger) HHI presumption, and corresponding default recapture ratio,
88
+ of (post-merger) HHI presumption, and corresponding default recapture rate,
89
89
  GUPPI bound, diversion ratio limit, CMCR, and IPR.
90
90
  """
91
91
 
@@ -208,13 +208,13 @@ class ConcentrationBoundary:
208
208
 
209
209
 
210
210
  @frozen
211
- class DiversionRatioBoundary:
211
+ class DiversionBoundary:
212
212
  """
213
213
  Diversion ratio specification, boundary coordinates, and area under boundary.
214
214
 
215
- Along with the default diversion ratio and recapture ratio,
215
+ Along with the default diversion ratio and recapture rate,
216
216
  a diversion ratio boundary specification includes the recapture form --
217
- whether fixed for both merging firms' products ("proportional") or
217
+ whether fixed for both merging firms' products ("fixed") or
218
218
  consistent with share-proportionality, i.e., "inside-out";
219
219
  the method of aggregating diversion ratios for the two products, and
220
220
  the precision for the estimate of area under the divertion ratio boundary
@@ -226,7 +226,7 @@ class DiversionRatioBoundary:
226
226
 
227
227
  @diversion_ratio.validator
228
228
  def _dvv(
229
- _instance: DiversionRatioBoundary,
229
+ _instance: DiversionBoundary,
230
230
  _attribute: Attribute[float],
231
231
  _value: float,
232
232
  /,
@@ -236,21 +236,21 @@ class DiversionRatioBoundary:
236
236
  "Margin-adjusted benchmark diversion share must lie between 0 and 1."
237
237
  )
238
238
 
239
- recapture_ratio: float = field(
239
+ recapture_rate: float = field(
240
240
  kw_only=False,
241
- default=DEFAULT_REC_RATIO,
241
+ default=DEFAULT_REC,
242
242
  validator=validators.instance_of(float),
243
243
  )
244
244
 
245
245
  recapture_form: RECForm | None = field(kw_only=True, default=RECForm.INOUT)
246
246
  R"""
247
- The form of the recapture ratio.
247
+ The form of the recapture rate.
248
248
 
249
- When :attr:`mergeron.RECForm.INOUT`, the recapture ratio for
249
+ When :attr:`mergeron.RECForm.INOUT`, the recapture rate for
250
250
  he product having the smaller market-share is assumed to equal the default,
251
- and the recapture ratio for the product with the larger market-share is
252
- computed assuming MNL demand. Fixed recapture ratios are specified as
253
- :attr:`mergeron.RECForm.FIXED`. (To specify that recapture ratios be
251
+ and the recapture rate for the product with the larger market-share is
252
+ computed assuming MNL demand. Fixed recapture rates are specified as
253
+ :attr:`mergeron.RECForm.FIXED`. (To specify that recapture rates be
254
254
  constructed from the generated purchase-probabilities for products in
255
255
  the market and for the outside good, specify :attr:`mergeron.RECForm.OUTIN`.)
256
256
 
@@ -270,19 +270,19 @@ class DiversionRatioBoundary:
270
270
 
271
271
  @recapture_form.validator
272
272
  def _rsv(
273
- _instance: DiversionRatioBoundary,
273
+ _instance: DiversionBoundary,
274
274
  _attribute: Attribute[RECForm],
275
275
  _value: RECForm,
276
276
  /,
277
277
  ) -> None:
278
278
  if _value and not (isinstance(_value, RECForm)):
279
279
  raise ValueError(f"Invalid recapture specification, {_value!r}.")
280
- if _value == RECForm.OUTIN and _instance.recapture_ratio:
280
+ if _value == RECForm.OUTIN and _instance.recapture_rate:
281
281
  raise ValueError(
282
282
  f"Invalid recapture specification, {_value!r}. "
283
283
  "You may consider specifying `mergeron.RECForm.INOUT` here, and "
284
- 'assigning the default recapture ratio as attribute, "recapture_ratio" of '
285
- "this `DiversionRatioBoundarySpec` object."
284
+ 'assigning the default recapture rate as attribute, "recapture_rate" of '
285
+ "this `DiversionBoundarySpec` object."
286
286
  )
287
287
  if _value is None and _instance.agg_method != UPPAggrSelector.MAX:
288
288
  raise ValueError(
@@ -325,7 +325,7 @@ class DiversionRatioBoundary:
325
325
  def __attrs_post_init__(self, /) -> None:
326
326
  """Initialize boundary and area based on other attributes."""
327
327
  share_ratio = critical_diversion_share(
328
- self.diversion_ratio, r_bar=self.recapture_ratio
328
+ self.diversion_ratio, r_bar=self.recapture_rate
329
329
  )
330
330
 
331
331
  upp_agg_kwargs: gbfn.DiversionShareBoundaryKeywords = {"dps": self.precision}
@@ -367,7 +367,7 @@ class DiversionRatioBoundary:
367
367
 
368
368
  upp_agg_kwargs |= {"agg_method": aggregator_, "weighting": wgt_type}
369
369
 
370
- boundary_ = upp_agg_fn(share_ratio, self.recapture_ratio, **upp_agg_kwargs) # type: ignore
370
+ boundary_ = upp_agg_fn(share_ratio, self.recapture_rate, **upp_agg_kwargs) # type: ignore
371
371
  object.__setattr__(self, "area", boundary_.area)
372
372
  object.__setattr__(self, "coordinates", boundary_.coordinates)
373
373
 
@@ -377,7 +377,7 @@ def guppi_from_delta(
377
377
  /,
378
378
  *,
379
379
  m_star: float = 1.00,
380
- r_bar: float = DEFAULT_REC_RATIO,
380
+ r_bar: float = DEFAULT_REC,
381
381
  ) -> float:
382
382
  """
383
383
  Translate ∆HHI bound to GUPPI bound.
@@ -389,11 +389,11 @@ def guppi_from_delta(
389
389
  m_star
390
390
  Parametric price-cost margin.
391
391
  r_bar
392
- Default recapture ratio.
392
+ Default recapture rate.
393
393
 
394
394
  Returns
395
395
  -------
396
- GUPPI bound corresponding to ∆HHI bound, at given margin and recapture ratio.
396
+ GUPPI bound corresponding to ∆HHI bound, at given margin and recapture rate.
397
397
 
398
398
  """
399
399
  return gbfn.round_cust(
@@ -421,12 +421,12 @@ def critical_diversion_share(
421
421
  m_star
422
422
  Parametric price-cost margin.
423
423
  r_bar
424
- Default recapture ratio.
424
+ Default recapture rate.
425
425
 
426
426
  Returns
427
427
  -------
428
428
  Critical diversion share (diversion share bound) corresponding to the GUPPI bound
429
- for given margin and recapture ratio.
429
+ for given margin and recapture rate.
430
430
 
431
431
  """
432
432
  return gbfn.round_cust(_guppi_bound / (m_star * r_bar), frac=frac)
@@ -437,10 +437,10 @@ def share_from_guppi(
437
437
  /,
438
438
  *,
439
439
  m_star: float = 1.00,
440
- r_bar: float = DEFAULT_REC_RATIO,
440
+ r_bar: float = DEFAULT_REC,
441
441
  ) -> float:
442
442
  """
443
- Symmetric-firm share for given GUPPI, margin, and recapture ratio.
443
+ Symmetric-firm share for given GUPPI, margin, and recapture rate.
444
444
 
445
445
  Parameters
446
446
  ----------
@@ -449,13 +449,13 @@ def share_from_guppi(
449
449
  m_star
450
450
  Parametric price-cost margin.
451
451
  r_bar
452
- Default recapture ratio.
452
+ Default recapture rate.
453
453
 
454
454
  Returns
455
455
  -------
456
456
  float
457
457
  Symmetric firm market share on GUPPI boundary, for given margin and
458
- recapture ratio.
458
+ recapture rate.
459
459
 
460
460
  """
461
461
  return gbfn.round_cust(
@@ -472,7 +472,7 @@ if __name__ == "__main__":
472
472
 
473
473
  for _typ in (
474
474
  ConcentrationBoundary,
475
- DiversionRatioBoundary,
475
+ DiversionBoundary,
476
476
  GuidelinesThresholds,
477
477
  HMGThresholds,
478
478
  ):
@@ -15,13 +15,7 @@ import matplotlib.ticker as mpt
15
15
  import numpy as np
16
16
  from mpmath import mp, mpf # type: ignore
17
17
 
18
- from .. import ( # noqa: TID252
19
- _PKG_NAME,
20
- DEFAULT_REC_RATIO,
21
- VERSION,
22
- ArrayBIGINT,
23
- ArrayDouble,
24
- )
18
+ from .. import _PKG_NAME, DEFAULT_REC, VERSION, ArrayDouble # noqa: TID252
25
19
  from . import GuidelinesBoundary, MPFloat
26
20
 
27
21
  __version__ = VERSION
@@ -33,7 +27,7 @@ mp.trap_complex = True
33
27
  class DiversionShareBoundaryKeywords(TypedDict, total=False):
34
28
  """Keyword arguments for functions generating share ratio boundaries."""
35
29
 
36
- recapture_form: Literal["inside-out", "proportional"]
30
+ recapture_form: Literal["inside-out", "fixed"]
37
31
  dps: int
38
32
  agg_method: Literal["arithmetic mean", "geometric mean", "distance"]
39
33
  weighting: Literal["own-share", "cross-product-share", None]
@@ -211,16 +205,16 @@ def hhi_post_contrib_boundary(
211
205
 
212
206
 
213
207
  # hand-rolled root finding
214
- def diversion_share_boundary_wtd_avg(
208
+ def diversion_share_boundary_wtd_avg( # noqa: PLR0914
215
209
  _delta_star: float = 0.075,
216
- _r_val: float = DEFAULT_REC_RATIO,
210
+ _r_val: float = DEFAULT_REC,
217
211
  /,
218
212
  *,
219
213
  agg_method: Literal[
220
214
  "arithmetic mean", "geometric mean", "distance"
221
215
  ] = "arithmetic mean",
222
216
  weighting: Literal["own-share", "cross-product-share", None] = "own-share",
223
- recapture_form: Literal["inside-out", "proportional"] = "inside-out",
217
+ recapture_form: Literal["inside-out", "fixed"] = "inside-out",
224
218
  dps: int = 5,
225
219
  ) -> GuidelinesBoundary:
226
220
  R"""
@@ -231,14 +225,14 @@ def diversion_share_boundary_wtd_avg(
231
225
  _delta_star
232
226
  Diversion share, :math:`\overline{d} / \overline{r}` or :math:`\overline{g} / (m^* \cdot \overline{r})`.
233
227
  _r_val
234
- Recapture ratio.
228
+ Recapture rate.
235
229
  agg_method
236
230
  Whether "arithmetic mean", "geometric mean", or "distance".
237
231
  weighting
238
232
  Whether "own-share" or "cross-product-share" (or None for simple, unweighted average).
239
233
  recapture_form
240
- Whether recapture-ratio is MNL-consistent ("inside-out") or has fixed
241
- value for both merging firms ("proportional").
234
+ Whether recapture rate is share-proportional ("inside-out") or has fixed
235
+ value for both merging firms ("fixed").
242
236
  dps
243
237
  Number of decimal places for rounding returned shares and area.
244
238
 
@@ -281,7 +275,7 @@ def diversion_share_boundary_wtd_avg(
281
275
  (s_1, 0.0, d_hat / (1 + d_hat)), ylabel=s_2
282
276
  )
283
277
 
284
- # recapture_form == "proportional"
278
+ # recapture_form == "fixed"
285
279
  oswag = solve(
286
280
  s_1 * s_2 / (1 - s_1)
287
281
  + s_2 * s_1 / (1 - s_2)
@@ -415,12 +409,12 @@ def diversion_share_boundary_wtd_avg(
415
409
  )
416
410
 
417
411
 
418
- def diversion_share_boundary_xact_avg(
412
+ def diversion_share_boundary_xact_avg( # noqa: PLR0914
419
413
  _delta_star: float = 0.075,
420
- _r_val: float = DEFAULT_REC_RATIO,
414
+ _r_val: float = DEFAULT_REC,
421
415
  /,
422
416
  *,
423
- recapture_form: Literal["inside-out", "proportional"] = "inside-out",
417
+ recapture_form: Literal["inside-out", "fixed"] = "inside-out",
424
418
  dps: int = 5,
425
419
  ) -> GuidelinesBoundary:
426
420
  R"""
@@ -451,7 +445,7 @@ def diversion_share_boundary_xact_avg(
451
445
  ylabel=s_2
452
446
  )
453
447
 
454
- # recapture_form = "proportional"
448
+ # recapture_form = "fixed"
455
449
  sag = solve((s_2/(1 - s_1)) + (s_1/(1 - s_2)) - 2 * d_hat, s_2)[0]
456
450
  symplot(
457
451
  sag,
@@ -464,10 +458,10 @@ def diversion_share_boundary_xact_avg(
464
458
  _delta_star
465
459
  Diversion share, :math:`\overline{d} / \overline{r}` or :math:`\overline{g} / (m^* \cdot \overline{r})`.
466
460
  _r_val
467
- Recapture ratio.
461
+ Recapture rate.
468
462
  recapture_form
469
- Whether recapture-ratio is MNL-consistent ("inside-out") or has fixed
470
- value for both merging firms ("proportional").
463
+ Whether recapture rate is share-proportional ("inside-out") or has fixed
464
+ value for both merging firms ("fixed").
471
465
  dps
472
466
  Number of decimal places for rounding returned shares.
473
467
 
@@ -572,10 +566,10 @@ def diversion_share_boundary_xact_avg(
572
566
 
573
567
  def diversion_share_boundary_min(
574
568
  _delta_star: float = 0.075,
575
- _r_val: float = DEFAULT_REC_RATIO,
569
+ _r_val: float = DEFAULT_REC,
576
570
  /,
577
571
  *,
578
- recapture_form: str = "inside-out",
572
+ recapture_form: Literal["inside-out", "fixed"] = "inside-out",
579
573
  dps: int = 10,
580
574
  ) -> GuidelinesBoundary:
581
575
  R"""
@@ -593,10 +587,10 @@ def diversion_share_boundary_min(
593
587
  _delta_star
594
588
  Diversion share, :math:`\overline{d} / \overline{r}` or :math:`\overline{g} / (m^* \cdot \overline{r})`.
595
589
  _r_val
596
- Recapture ratio.
590
+ Recapture rate.
597
591
  recapture_form
598
- Whether recapture-ratio is MNL-consistent ("inside-out") or has fixed
599
- value for both merging firms ("proportional").
592
+ Whether recapture rate is share-proportional ("inside-out") or has fixed
593
+ value for both merging firms ("fixed").
600
594
  dps
601
595
  Number of decimal places for rounding returned shares.
602
596
 
@@ -627,7 +621,7 @@ def diversion_share_boundary_min(
627
621
 
628
622
 
629
623
  def diversion_share_boundary_max(
630
- _delta_star: float = 0.075, _: float = DEFAULT_REC_RATIO, /, *, dps: int = 10
624
+ _delta_star: float = 0.075, _: float = DEFAULT_REC, /, *, dps: int = 10
631
625
  ) -> GuidelinesBoundary:
632
626
  R"""
633
627
  Share combinations on the minimum diversion-ratio/share-ratio boundary.
@@ -637,7 +631,7 @@ def diversion_share_boundary_max(
637
631
  _delta_star
638
632
  Diversion share, :math:`\overline{d} / \overline{r}` or :math:`\overline{g} / (m^* \cdot \overline{r})`.
639
633
  _
640
- Placeholder for recapture ratio included for consistency with other
634
+ Placeholder for recapture rate included for consistency with other
641
635
  share-ratio boundary functions.
642
636
  dps
643
637
  Number of decimal places for rounding returned shares.
@@ -664,7 +658,7 @@ def _diversion_share_boundary_intcpt(
664
658
  _r_val: MPFloat,
665
659
  /,
666
660
  *,
667
- recapture_form: Literal["inside-out", "proportional"],
661
+ recapture_form: Literal["inside-out", "fixed"],
668
662
  agg_method: Literal["arithmetic mean", "geometric mean", "distance"],
669
663
  weighting: Literal["cross-product-share", "own-share", None],
670
664
  ) -> float:
@@ -683,7 +677,7 @@ def _diversion_share_boundary_intcpt(
683
677
  2 * mpf(f"{_r_val}"),
684
678
  )
685
679
  case None if (
686
- agg_method == "arithmetic mean" and recapture_form == "proportional"
680
+ agg_method == "arithmetic mean" and recapture_form == "fixed"
687
681
  ):
688
682
  _s_intcpt = mp.fsub(_delta_star + 1 / 2, mp.fabs(_delta_star - 1 / 2))
689
683
  case _:
@@ -692,7 +686,7 @@ def _diversion_share_boundary_intcpt(
692
686
  return _s_intcpt
693
687
 
694
688
 
695
- def lerp[LerpT: (float, MPFloat, ArrayDouble, ArrayBIGINT)](
689
+ def lerp[LerpT: (float, MPFloat, ArrayDouble)](
696
690
  _x1: LerpT, _x2: LerpT, _r: float | MPFloat = 0.25, /
697
691
  ) -> LerpT:
698
692
  R"""
@@ -66,7 +66,7 @@ def prng(_s: SeedSequence | None = None, /) -> np.random.Generator:
66
66
  )
67
67
 
68
68
 
69
- def gen_seed_seq_list_default(
69
+ def seed_sequencer(
70
70
  _len: int = 3, /, *, generated_entropy: Sequence[int] | None = None
71
71
  ) -> tuple[SeedSequence, ...]:
72
72
  R"""