mergeron 2025.739319.1__py3-none-any.whl → 2025.739319.3__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
@@ -12,7 +12,7 @@ from ruamel import yaml
12
12
 
13
13
  _PKG_NAME: str = Path(__file__).parent.stem
14
14
 
15
- VERSION = "2025.739319.1"
15
+ VERSION = "2025.739319.3"
16
16
 
17
17
  __version__ = VERSION
18
18
 
@@ -43,11 +43,12 @@ from types import MappingProxyType
43
43
 
44
44
  import numpy as np
45
45
  import urllib3
46
+ from joblib import Parallel, delayed
46
47
  from numpy.random import PCG64DXSM, Generator, SeedSequence
47
48
  from scipy import stats # type: ignore
48
49
  from xlrd import open_workbook # type: ignore
49
50
 
50
- from .. import VERSION, ArrayDouble, this_yaml # noqa: TID252
51
+ from .. import NTHREADS, VERSION, ArrayDouble, this_yaml # noqa: TID252
51
52
  from .. import WORK_DIR as PKG_WORK_DIR # noqa: TID252
52
53
  from .. import data as mdat # noqa: TID252
53
54
  from . import _mappingproxy_from_mapping
@@ -67,7 +68,7 @@ u3pm = urllib3.PoolManager()
67
68
  def margin_data_getter( # noqa: PLR0912
68
69
  _table_name: str = "margin",
69
70
  *,
70
- data_archive_path: Path | None = None,
71
+ data_archive_path: Path = MGNDATA_ARCHIVE_PATH,
71
72
  data_download_flag: bool = False,
72
73
  ) -> DamodaranMarginData:
73
74
  if _table_name != "margin": # Not validated for other tables
@@ -203,11 +204,12 @@ def margin_data_builder(
203
204
 
204
205
 
205
206
  def margin_data_resampler(
206
- _dist_parms: tuple[ArrayDouble, ArrayDouble] | None = None,
207
+ _dist_parms: ArrayDouble,
207
208
  /,
208
209
  *,
209
- sample_size: int | tuple[int, ...] = (10**6, 2),
210
+ sample_size: int | tuple[int, ...],
210
211
  seed_sequence: SeedSequence | None = None,
212
+ nthreads: int = NTHREADS,
211
213
  ) -> ArrayDouble:
212
214
  """
213
215
  Generate draws from the empirical distribution bassed on Prof. Damodaran's margin data.
@@ -231,6 +233,8 @@ def margin_data_resampler(
231
233
  SeedSequence for seeding random-number generator when results
232
234
  are to be repeatable
233
235
 
236
+ nthreads
237
+ Number of threads to use in generating margin data.
234
238
  Returns
235
239
  -------
236
240
  Array of margin values
@@ -241,22 +245,26 @@ def margin_data_resampler(
241
245
 
242
246
  _seed = seed_sequence or SeedSequence(pool_size=8)
243
247
 
244
- _x, _w = _dist_parms[:, 0], _dist_parms[:, 1]
248
+ _x, _w = _dist_parms[:, 0], _dist_parms[:, 1]
245
249
 
246
250
  margin_kde = stats.gaussian_kde(_x, weights=_w, bw_method="silverman")
247
251
  margin_kde.set_bandwidth(bw_method=margin_kde.factor / 3.0)
248
252
 
249
253
  if isinstance(sample_size, int):
250
- return np.array(
251
- margin_kde.resample(sample_size, seed=Generator(PCG64DXSM(_seed)))[0]
252
- )
254
+ return margin_kde.resample(sample_size, seed=Generator(PCG64DXSM(_seed))).T
255
+
253
256
  elif isinstance(sample_size, tuple) and len(sample_size) == 2:
254
- _ssz, _ncol = sample_size
255
257
  ret_array = np.empty(sample_size, float)
256
- for idx, _col_seed in enumerate(_seed.spawn(_ncol)):
257
- ret_array[:, idx] = margin_kde.resample(
258
- _ssz, seed=Generator(PCG64DXSM(_col_seed))
259
- )[0]
258
+
259
+ _ssz, _ncol = sample_size
260
+ dat_list = Parallel(n_jobs=min(nthreads, _ncol), prefer="threads")(
261
+ delayed(margin_kde.resample)(_ssz, seed=Generator(PCG64DXSM(_col_seed)))
262
+ for _col_seed in _seed.spawn(_ncol)
263
+ )
264
+
265
+ for _i in range(_ncol):
266
+ ret_array[:, [_i]] = dat_list[_i].T
267
+
260
268
  return ret_array
261
269
  else:
262
270
  raise ValueError(f"Invalid sample size: {sample_size!r}")
@@ -109,7 +109,7 @@ class GuidelinesThresholds:
109
109
  _r := gbfn.round_cust(_fc / (_fc + 1), frac=0.05),
110
110
  _g := guppi_from_delta(dh_s, m_star=1.0, r_bar=_r),
111
111
  _dr := 1 - _r,
112
- _cmcr := 0.03, # Not strictly a Guidelines standard
112
+ _cmcr := _g, # Not strictly a Guidelines standard
113
113
  _ipr := _g, # Not strictly a Guidelines standard
114
114
  ),
115
115
  )
@@ -132,7 +132,7 @@ class GuidelinesThresholds:
132
132
  _g,
133
133
  (1 - _r_i) / 2,
134
134
  _cmcr,
135
- _ipr := _g,
135
+ _ipr,
136
136
  )
137
137
  if self.pub_year == 2010
138
138
  else HMGThresholds(
@@ -21,11 +21,14 @@ WORK_DIR = globals().get("WORK_DIR", PKG_WORK_DIR)
21
21
 
22
22
  SAMPLE_SIZE = 10**6
23
23
  BIN_COUNT = 25
24
- margin_data_obs, margin_data_wts, margin_data_stats = emd.margin_data_builder()
24
+ margin_data, margin_data_stats = emd.margin_data_builder()
25
+
26
+ margin_data_obs, margin_data_wts = margin_data[:, 0], margin_data[:, 1]
27
+
25
28
  print(repr(margin_data_obs))
26
29
  print(repr(margin_data_stats))
27
30
 
28
- plt, mgn_fig, mgn_ax, set_axis_def = boundary_plot(mktshares_plot_flag=False)
31
+ plt, mgn_fig, mgn_ax, set_axis_def = boundary_plot(mktshare_plot_flag=False)
29
32
  mgn_fig.set_figheight(6.5)
30
33
  mgn_fig.set_figwidth(9.0)
31
34
 
mergeron/gen/__init__.py CHANGED
@@ -299,7 +299,7 @@ class PCMDistribution(str, Enameled):
299
299
 
300
300
  @this_yaml.register_class
301
301
  @enum.unique
302
- class FM2Constraint(str, Enameled):
302
+ class PCMRestriction(str, Enameled):
303
303
  """Firm 2 margins - derivation methods."""
304
304
 
305
305
  IID = "i.i.d"
@@ -307,9 +307,7 @@ class FM2Constraint(str, Enameled):
307
307
  SYM = "symmetric"
308
308
 
309
309
 
310
- def _pcm_dp_conv(
311
- _v: ArrayFloat | Sequence[float] | None, _i: PCMSpec
312
- ) -> ArrayFloat:
310
+ def _pcm_dp_conv(_v: ArrayFloat | Sequence[float] | None, _i: PCMSpec) -> ArrayFloat:
313
311
  if _v is None or len(_v) == 0 or np.array_equal(_v, DEFAULT_DIST_PARMS):
314
312
  if _i.dist_type == PCMDistribution.EMPR:
315
313
  return margin_data_builder()[0]
@@ -320,10 +318,10 @@ def _pcm_dp_conv(
320
318
  return DEFAULT_BETA_BND_DIST_PARMS
321
319
  case _:
322
320
  return DEFAULT_DIST_PARMS
323
- elif (_i.dist_type == PCMDistribution.EMPR and not isinstance(_v, np.ndarray)):
324
- raise ValueError(
325
- "Invalid specification; use output of mergeron.core.empriical_margin_distribution.margin_data_builider()."
326
- )
321
+ elif _i.dist_type == PCMDistribution.EMPR and not isinstance(_v, np.ndarray):
322
+ raise ValueError(
323
+ "Invalid specification; use ..core.empriical_margin_distribution.margin_data_builider()[0]."
324
+ )
327
325
  elif isinstance(_v, Sequence | np.ndarray):
328
326
  return np.asarray(_v, float)
329
327
  else:
@@ -332,8 +330,6 @@ def _pcm_dp_conv(
332
330
  "sequence of Numpy arrays, or Numpy ndarray."
333
331
  )
334
332
 
335
- return _v
336
-
337
333
 
338
334
  @frozen
339
335
  class PCMSpec:
@@ -373,9 +369,7 @@ class PCMSpec:
373
369
  """
374
370
 
375
371
  @dist_parms.default
376
- def __dpwd(
377
- _i: PCMSpec,
378
- ) -> ArrayFloat:
372
+ def __dpwd(_i: PCMSpec) -> ArrayFloat:
379
373
  return _pcm_dp_conv(None, _i)
380
374
 
381
375
  @dist_parms.validator
@@ -403,16 +397,22 @@ class PCMSpec:
403
397
  f'for PCM with distribution, "{_i.dist_type}" is incorrect.'
404
398
  )
405
399
 
406
- elif (
407
- _i.dist_type == PCMDistribution.EMPR
408
- and not isinstance(_v, np.ndarray)
409
- ):
400
+ elif _i.dist_type == PCMDistribution.EMPR and not isinstance(_v, np.ndarray):
410
401
  raise ValueError(
411
402
  "Empirical distribution requires deserialzed margin data from Prof. Damodaran, NYU"
412
403
  )
413
404
 
414
- firm2_pcm_constraint: FM2Constraint = field(kw_only=True, default=FM2Constraint.IID)
415
- """See :class:`FM2Constraint`"""
405
+ pcm_restriction: PCMRestriction = field(kw_only=True, default=PCMRestriction.IID)
406
+ """See :class:`PCMRestriction`"""
407
+
408
+ @pcm_restriction.validator
409
+ def __prv(_i: PCMSpec, _a: Attribute[PCMRestriction], _v: PCMRestriction) -> None:
410
+ if _v == PCMRestriction.MNL and _i.dist_type == PCMDistribution.EMPR:
411
+ print(
412
+ "NOTE: Estimated Firm 2 parameters will not be consistent with "
413
+ "the empirical distribution of margins in the source data. For "
414
+ "consistency, respecify pcm_spec.pcm_restriction = PCMRestriction.IID."
415
+ )
416
416
 
417
417
 
418
418
  @this_yaml.register_class
@@ -26,10 +26,10 @@ from .. import ( # noqa: TID252 # noqa
26
26
  from ..core import guidelines_boundaries as gbl # noqa: TID252
27
27
  from ..core.guidelines_boundaries import HMGThresholds # noqa: TID252
28
28
  from . import (
29
- FM2Constraint,
30
29
  INVResolution, # noqa: F401
31
30
  MarketSampleData,
32
31
  PCMDistribution,
32
+ PCMRestriction,
33
33
  PCMSpec,
34
34
  PriceSpec,
35
35
  SeedSequenceData,
@@ -44,7 +44,7 @@ from .data_generation_functions import (
44
44
  gen_margin_price_data,
45
45
  gen_share_data,
46
46
  )
47
- from .upp_tests import compute_upp_test_counts # type: ignore # has pytypes marker ...
47
+ from .upp_tests import compute_upp_test_counts
48
48
 
49
49
  __version__ = VERSION
50
50
 
@@ -100,10 +100,10 @@ class MarketSample:
100
100
  def _psv(self, _a: Attribute[PCMSpec], _v: PCMSpec, /) -> None:
101
101
  if (
102
102
  self.share_spec.recapture_form == RECForm.FIXED
103
- and _v.firm2_pcm_constraint == FM2Constraint.MNL
103
+ and _v.pcm_restriction == PCMRestriction.MNL
104
104
  ):
105
105
  raise ValueError(
106
- f'Specification of "PCMSpec.firm2_pcm_constraint", as {FM2Constraint.MNL!r} '
106
+ f'Specification of "PCMSpec.pcm_restriction", as {PCMRestriction.MNL!r} '
107
107
  f'requires that "ShareSpec.recapture_form" be {RECForm.INOUT!r} '
108
108
  f"or {RECForm.OUTIN!r}, not {RECForm.FIXED!r} as presently specified"
109
109
  )
@@ -179,7 +179,7 @@ class MarketSample:
179
179
  shr_sample_size = sample_size * self.hsr_filing_test_type
180
180
  shr_sample_size *= (
181
181
  SSZConstant.MNL_DEP
182
- if self.pcm_spec.firm2_pcm_constraint == FM2Constraint.MNL
182
+ if self.pcm_spec.pcm_restriction == PCMRestriction.MNL
183
183
  else 1
184
184
  )
185
185
  shr_sample_size = int(shr_sample_size)
@@ -379,28 +379,33 @@ class MarketSample:
379
379
 
380
380
  sim_enf_cnts_kwargs: SamplingFunctionKWArgs = SamplingFunctionKWArgs({
381
381
  "sample_size": subsample_sz,
382
- "nthreads": self.nthreads,
382
+ "nthreads": thread_count,
383
383
  })
384
384
 
385
- res_list = Parallel(n_jobs=thread_count, prefer="threads")(
385
+ res_list = Parallel(n_jobs=min(thread_count, iter_count), prefer="threads")(
386
386
  delayed(self.__sim_enf_cnts)(
387
387
  _enf_parm_vec,
388
388
  _sim_test_regime,
389
389
  **sim_enf_cnts_kwargs,
390
390
  seed_data=_rng_seed_data_ch,
391
391
  )
392
- for _iter_id, _rng_seed_data_ch in enumerate(rng_seed_data)
392
+ for _rng_seed_data_ch in rng_seed_data
393
393
  )
394
394
 
395
395
  res_list_stacks = UPPTestsCounts(*[
396
396
  np.stack([getattr(_j, _k) for _j in res_list])
397
397
  for _k in ("by_firm_count", "by_delta", "by_conczone")
398
398
  ])
399
+
399
400
  upp_test_results = UPPTestsCounts(*[
400
- np.hstack((
401
- (_gv := getattr(res_list_stacks, _g.name))[0, :, :_h],
402
- np.einsum("ijk->jk", _gv[:, :, _h:], dtype=np.int64),
403
- ))
401
+ (
402
+ np.array([], int)
403
+ if not (_gv := getattr(res_list_stacks, _g.name)).any()
404
+ else np.hstack((
405
+ _gv[0, :, :_h],
406
+ np.einsum("ijk->jk", _gv[:, :, _h:], dtype=int),
407
+ ))
408
+ )
404
409
  for _g, _h in zip(res_list_stacks.__attrs_attrs__, [1, 1, 3], strict=True)
405
410
  ])
406
411
  del res_list, res_list_stacks
@@ -28,9 +28,9 @@ from ..core.pseudorandom_numbers import ( # noqa: TID252
28
28
  from . import (
29
29
  DEFAULT_BETA_BND_DIST_PARMS,
30
30
  DEFAULT_FCOUNT_WTS,
31
- FM2Constraint,
32
31
  MarginDataSample,
33
32
  PCMDistribution,
33
+ PCMRestriction,
34
34
  PCMSpec,
35
35
  PriceDataSample,
36
36
  PriceSpec,
@@ -549,11 +549,11 @@ def gen_margin_price_data( # noqa: PLR0914
549
549
  # del _price_array_gen
550
550
  case PriceSpec.CSY:
551
551
  # TODO:
552
- # evolve FM2Constraint (save running MNL test twice); evolve copy of _mkt_sample_spec=1q
552
+ # evolve PCMRestriction (save running MNL test twice); evolve copy of _mkt_sample_spec=1q
553
553
  # generate the margin data
554
554
  # generate price and margin data
555
555
  frmshr_array_plus = np.hstack((_frmshr_array, _nth_firm_share))
556
- pcm_spec_here = evolve(_pcm_spec, firm2_pcm_constraint=FM2Constraint.IID)
556
+ pcm_spec_here = evolve(_pcm_spec, pcm_restriction=PCMRestriction.IID)
557
557
  margin_data = _gen_margin_data(
558
558
  frmshr_array_plus,
559
559
  np.ones_like(frmshr_array_plus, np.float64),
@@ -570,7 +570,7 @@ def gen_margin_price_data( # noqa: PLR0914
570
570
  price_array_here = 1 / (1 - pcm_array)
571
571
  price_array = price_array_here[:, :2]
572
572
  nth_firm_price = price_array_here[:, [-1]]
573
- if _pcm_spec.firm2_pcm_constraint == FM2Constraint.MNL:
573
+ if _pcm_spec.pcm_restriction == PCMRestriction.MNL:
574
574
  # Generate i.i.d. PCMs then take PCM0 and construct PCM1
575
575
  # Regenerate MNL test
576
576
  purchase_prob_array = _aggregate_purchase_prob * _frmshr_array
@@ -665,14 +665,13 @@ def _gen_margin_data(
665
665
  _nthreads: int,
666
666
  /,
667
667
  ) -> MarginDataSample:
668
- dist_type_pcm, dist_parms_pcm, dist_firm2_pcm = (
669
- getattr(_pcm_spec, _f)
670
- for _f in ("dist_type", "dist_parms", "firm2_pcm_constraint")
668
+ dist_type_pcm, dist_parms_pcm, pcm_restriction_ = (
669
+ getattr(_pcm_spec, _f) for _f in ("dist_type", "dist_parms", "pcm_restriction")
671
670
  )
672
671
 
673
672
  pcm_array = (
674
673
  np.empty_like(_frmshr_array[:, :1])
675
- if _pcm_spec.firm2_pcm_constraint == FM2Constraint.SYM
674
+ if _pcm_spec.pcm_restriction == PCMRestriction.SYM
676
675
  else np.empty_like(_frmshr_array)
677
676
  )
678
677
 
@@ -680,7 +679,10 @@ def _gen_margin_data(
680
679
  beta_min, beta_max = [0.0] * 2 # placeholder
681
680
  if dist_type_pcm == PCMDistribution.EMPR:
682
681
  pcm_array = margin_data_resampler(
683
- dist_parms_pcm, sample_size=pcm_array.shape, seed_sequence=_pcm_rng_seed_seq
682
+ dist_parms_pcm,
683
+ sample_size=pcm_array.shape,
684
+ seed_sequence=_pcm_rng_seed_seq,
685
+ nthreads=_nthreads,
684
686
  )
685
687
  else:
686
688
  dist_type_: Literal["Beta", "Uniform"]
@@ -721,16 +723,10 @@ def _gen_margin_data(
721
723
  pcm_array = (beta_max - beta_min) * pcm_array + beta_min
722
724
  del beta_min, beta_max
723
725
 
724
- if dist_firm2_pcm == FM2Constraint.SYM:
726
+ if pcm_restriction_ == PCMRestriction.SYM:
725
727
  pcm_array = np.hstack((pcm_array,) * _frmshr_array.shape[1])
726
- if dist_firm2_pcm == FM2Constraint.MNL:
728
+ if pcm_restriction_ == PCMRestriction.MNL:
727
729
  # Impose FOCs from profit-maximization with MNL demand
728
- if dist_type_pcm == PCMDistribution.EMPR:
729
- print(
730
- "NOTE: Estimated Firm 2 parameters will not be consistent with "
731
- "the empirical distribution of margins in the source data. For "
732
- "consistency, respecify pcm_spec.firm2_pcm_constraint = FM2Constraint.IID."
733
- )
734
730
  purchase_prob_array = _aggregate_purchase_prob * _frmshr_array
735
731
 
736
732
  pcm_array[:, [1]] = np.divide(
@@ -335,10 +335,13 @@ def enf_cnts_byconczone(_cnts_array: ArrayBIGINT, /) -> ArrayBIGINT:
335
335
  # Logical-and of multiple vectors:
336
336
  hhi_zone_test = (
337
337
  1
338
- * np.stack([
339
- cnts_byhhipostanddelta[:, _idx] == _val
340
- for _idx, _val in enumerate(zone_val)
341
- ], axis=1)
338
+ * np.stack(
339
+ [
340
+ cnts_byhhipostanddelta[:, _idx] == _val
341
+ for _idx, _val in enumerate(zone_val)
342
+ ],
343
+ axis=1,
344
+ )
342
345
  ).prod(axis=1) == 1
343
346
 
344
347
  cnts_byconczone = np.vstack((
mergeron/gen/upp_tests.py CHANGED
@@ -142,10 +142,6 @@ def compute_upp_test_counts( # noqa: PLR0914
142
142
  hhi_delta_ranged,
143
143
  np.ones_like(hhi_delta_ranged),
144
144
  upp_test_arrays,
145
- # *[
146
- # 1 * getattr(upp_test_arrays, _a.name)
147
- # for _a in upp_test_arrays.__attrs_attrs__
148
- # ],
149
145
  ),
150
146
  dtype=int,
151
147
  )
@@ -194,11 +190,23 @@ def _compute_test_array_seq(
194
190
  np.sqrt(np.einsum("ij,ij,ij->i", _wt_array[:, ::-1], _g, _g))[:, None]
195
191
  for _g in _test_measure_seq
196
192
  )
193
+ case UPPAggrSelector.CPG:
194
+ test_array_seq = (
195
+ np.expm1(
196
+ np.einsum("ij,ij->i", _wt_array[:, ::-1], np.log1p(_g))[:, None]
197
+ )
198
+ for _g in _test_measure_seq
199
+ )
197
200
  case UPPAggrSelector.DIS:
198
201
  test_array_seq = (
199
202
  np.sqrt(1 / 2 * np.einsum("ij,ij->i", _g, _g))[:, None]
200
203
  for _g in _test_measure_seq
201
204
  )
205
+ case UPPAggrSelector.GMN:
206
+ test_array_seq = (
207
+ np.expm1(np.einsum("ij->i", np.log1p(_g))[:, None] / _g.shape[1])
208
+ for _g in _test_measure_seq
209
+ )
202
210
  case UPPAggrSelector.MAX:
203
211
  test_array_seq = (_g.max(axis=1, keepdims=True) for _g in _test_measure_seq)
204
212
  case UPPAggrSelector.MIN:
@@ -210,7 +218,12 @@ def _compute_test_array_seq(
210
218
  )
211
219
  case UPPAggrSelector.OSD:
212
220
  test_array_seq = (
213
- np.sqrt(np.einsum("ij,ij,ij->i", _wt_array, _g, _g))[:, None]
221
+ np.sqrt(np.einsum("ij,ij,ij->i", _wt_array, _g, _g)[:, None])
222
+ for _g in _test_measure_seq
223
+ )
224
+ case UPPAggrSelector.OSG:
225
+ test_array_seq = (
226
+ np.expm1(np.einsum("ij,ij->i", _wt_array, np.log1p(_g))[:, None])
214
227
  for _g in _test_measure_seq
215
228
  )
216
229
  case _:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: mergeron
3
- Version: 2025.739319.1
3
+ Version: 2025.739319.3
4
4
  Summary: Analyze merger enforcement policy using Python
5
5
  License: MIT
6
6
  Keywords: merger policy analysis,merger guidelines,merger screening,policy presumptions,concentration standards,upward pricing pressure,GUPPI
@@ -93,10 +93,6 @@ backend to ``None`` to skip fine-tuning plots for PDF generation.
93
93
  _ = fig.legend(loc=(0.4, 0.7), frameon=False)
94
94
 
95
95
 
96
-
97
- .. image:: ./docs/readme_content/output_5_0.png
98
-
99
-
100
96
  *Analyzing FTC Merger Investigations Data*
101
97
 
102
98
  .. code:: python
@@ -1,8 +1,8 @@
1
- mergeron/__init__.py,sha256=2uFd57yjWZNN8bmBnyXA4IqfvoFWvvJqw0OzYqptntY,5549
1
+ mergeron/__init__.py,sha256=28Yan2f3uiw5fugxpGMd8mwr0JyWS9tYjkoDXTiAE-U,5549
2
2
  mergeron/core/__init__.py,sha256=BzL_bXHyOQG8cvo76OP3K48LkeHQCJQN7ZFPRhoOdcE,2850
3
- mergeron/core/empirical_margin_distribution.py,sha256=8YpoSBOfmMaMLB0Vi_UByQXy4oP-aY_6LI2kYdJWFXc,9336
3
+ mergeron/core/empirical_margin_distribution.py,sha256=PwAxOLc7zgL4OHVH1kQRtxP7m5XAVUPtMVomM2uvnKM,9527
4
4
  mergeron/core/ftc_merger_investigations_data.py,sha256=DYqtyxGPnpGyaWbQ8dPHmHmQBOeHbmU5h9snk-YwSN4,28575
5
- mergeron/core/guidelines_boundaries.py,sha256=srCEWzSuv7cDFCf-ity-9C0NtFCdZznn5dgiUS9Ndpo,15246
5
+ mergeron/core/guidelines_boundaries.py,sha256=hZ3Fiobb9KXCBybQjb_xJj4q_-r8ClmxRjd6Scv7Km4,15238
6
6
  mergeron/core/guidelines_boundary_functions.py,sha256=wQdIQcEga888vVe3cAwYsDa7HTaxgqe3RbV48UklmzQ,29064
7
7
  mergeron/core/guidelines_boundary_functions_extra.py,sha256=i2CmEpYRUVnMbPakSjlyWodMP11JW-rkVImhKOQlV6g,22355
8
8
  mergeron/core/pseudorandom_numbers.py,sha256=YqcVwU-Pgc0F_pKzG9Osn14RnIuYOwE-q7GVDpCUtpI,9998
@@ -10,13 +10,13 @@ mergeron/data/__init__.py,sha256=4yOOvERJ28JIT5KRkIa_t2y9aYmuFdStPM4P38BsufM,180
10
10
  mergeron/data/damodaran_margin_data.xls,sha256=Qggl1p5nkOMJI8YUXhkwXQRz-OhRSqBTzz57N0JQyYA,79360
11
11
  mergeron/data/ftc_merger_investigations_data.zip,sha256=tiB2TLFyS9LMSFIv8DBA_oEEx12DU4MyjHni4NlsRMU,24002
12
12
  mergeron/demo/__init__.py,sha256=KtjBlZOl7jwBCAUhrTJB9PdrN39YLYytNiSUSM_gRmA,62
13
- mergeron/demo/visualize_empirical_margin_distribution.py,sha256=17awsa188r7uVDJuHuCWTYwlQbfaq4n8HEHF5jK-0Ic,2532
14
- mergeron/gen/__init__.py,sha256=JD8hP5QVgNTlGTwBnozN0xHg97mXn99WckCuFfVcCNQ,23071
15
- mergeron/gen/data_generation.py,sha256=ED0ShgPL0sgJceLzJu1BcNs8yC-EBzNGHW1oj8_g_so,17092
16
- mergeron/gen/data_generation_functions.py,sha256=VySWh-Jvnj0zSVvkq12ck3SUFJ-42udODKzeop2ZWvs,26418
17
- mergeron/gen/enforcement_stats.py,sha256=UrsZWZNYy7DXWsCu96qmOQINipFbf9qLX0W8iNGgE_Y,11073
18
- mergeron/gen/upp_tests.py,sha256=Czub4njLESkV5LRwb1lByEI4nHBK0AwT96LYp_bG12s,6968
13
+ mergeron/demo/visualize_empirical_margin_distribution.py,sha256=N8pYTl11ngG-W5WOjjYDigCIZs5LPVrUNxdgEHLwTHE,2584
14
+ mergeron/gen/__init__.py,sha256=6UZ7u1a2rw9iSaGjnpNf1E9IXukHPU9iIDaauruQ7-g,23450
15
+ mergeron/gen/data_generation.py,sha256=a9RZxlcwN7jInxSTomCZUVKPsIE_YUMSfRabizYN62U,17147
16
+ mergeron/gen/data_generation_functions.py,sha256=8UkO3GBqTTrfFSsxiJ9Z-AbxR7XiKv6QJBkd07sx1f0,26123
17
+ mergeron/gen/enforcement_stats.py,sha256=wtWMbMHK_G3yw4zaNQR9fdmu8crbzeFKjBvY-b1mom4,11132
18
+ mergeron/gen/upp_tests.py,sha256=qCyIMY8fuaRqGobwlcu3SPpIlD-dDNdM53qC8CTx59k,7480
19
19
  mergeron/py.typed,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
20
- mergeron-2025.739319.1.dist-info/METADATA,sha256=wt7lPUlkdvuv3UPFRALI6gVt9fSXnGxM5-asEu-Mf9c,6107
21
- mergeron-2025.739319.1.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
22
- mergeron-2025.739319.1.dist-info/RECORD,,
20
+ mergeron-2025.739319.3.dist-info/METADATA,sha256=yoBYK3tulJtDDc4oFIYM93okbyqEN73Kiv97hk1JVKc,6056
21
+ mergeron-2025.739319.3.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
22
+ mergeron-2025.739319.3.dist-info/RECORD,,