mergeron 2025.739319.0__py3-none-any.whl → 2025.739319.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of mergeron might be problematic. Click here for more details.

mergeron/__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.0"
15
+ VERSION = "2025.739319.2"
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,29 +204,37 @@ 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.
214
216
 
215
217
  The empirical distribution is estimated using a Gaussian KDE; the bandwidth
216
218
  selected using Silverman's rule is narrowed to reflect that the margin data
217
- are multimodal. Margins for firms in finance, investment, insurance, reinsurance, and
218
- REITs are excluded from the sample used to estimate the empirical distribution.
219
+ are multimodal. Margins for firms in finance, investment, insurance,
220
+ reinsurance, and REITs are excluded from the sample used to estimate the
221
+ empirical distribution.
219
222
 
220
223
  Parameters
221
224
  ----------
222
- _sample_size
225
+
226
+ _dist_parms
227
+ Array of margins and firm counts extracted from Prof. Damodaran's margin data
228
+
229
+ sample_size
223
230
  Number of draws; if tuple, (number of draws, number of columns)
224
231
 
225
232
  seed_sequence
226
233
  SeedSequence for seeding random-number generator when results
227
234
  are to be repeatable
228
235
 
236
+ nthreads
237
+ Number of threads to use in generating margin data.
229
238
  Returns
230
239
  -------
231
240
  Array of margin values
@@ -236,22 +245,26 @@ def margin_data_resampler(
236
245
 
237
246
  _seed = seed_sequence or SeedSequence(pool_size=8)
238
247
 
239
- _x, _w = _dist_parms[:, 0], _dist_parms[:, 1]
248
+ _x, _w = _dist_parms[:, 0], _dist_parms[:, 1]
240
249
 
241
250
  margin_kde = stats.gaussian_kde(_x, weights=_w, bw_method="silverman")
242
251
  margin_kde.set_bandwidth(bw_method=margin_kde.factor / 3.0)
243
252
 
244
253
  if isinstance(sample_size, int):
245
- return np.array(
246
- margin_kde.resample(sample_size, seed=Generator(PCG64DXSM(_seed)))[0]
247
- )
254
+ return margin_kde.resample(sample_size, seed=Generator(PCG64DXSM(_seed))).T
255
+
248
256
  elif isinstance(sample_size, tuple) and len(sample_size) == 2:
249
- _ssz, _ncol = sample_size
250
257
  ret_array = np.empty(sample_size, float)
251
- for idx, _col_seed in enumerate(_seed.spawn(_ncol)):
252
- ret_array[:, idx] = margin_kde.resample(
253
- _ssz, seed=Generator(PCG64DXSM(_col_seed))
254
- )[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
+
255
268
  return ret_array
256
269
  else:
257
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,13 @@ 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`"""
416
407
 
417
408
 
418
409
  @this_yaml.register_class
@@ -26,7 +26,7 @@ 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,
29
+ PCMRestriction,
30
30
  INVResolution, # noqa: F401
31
31
  MarketSampleData,
32
32
  PCMDistribution,
@@ -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,7 +28,7 @@ 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,
31
+ PCMRestriction,
32
32
  MarginDataSample,
33
33
  PCMDistribution,
34
34
  PCMSpec,
@@ -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
@@ -667,12 +667,12 @@ def _gen_margin_data(
667
667
  ) -> MarginDataSample:
668
668
  dist_type_pcm, dist_parms_pcm, dist_firm2_pcm = (
669
669
  getattr(_pcm_spec, _f)
670
- for _f in ("dist_type", "dist_parms", "firm2_pcm_constraint")
670
+ for _f in ("dist_type", "dist_parms", "pcm_restriction")
671
671
  )
672
672
 
673
673
  pcm_array = (
674
674
  np.empty_like(_frmshr_array[:, :1])
675
- if _pcm_spec.firm2_pcm_constraint == FM2Constraint.SYM
675
+ if _pcm_spec.pcm_restriction == PCMRestriction.SYM
676
676
  else np.empty_like(_frmshr_array)
677
677
  )
678
678
 
@@ -680,7 +680,7 @@ def _gen_margin_data(
680
680
  beta_min, beta_max = [0.0] * 2 # placeholder
681
681
  if dist_type_pcm == PCMDistribution.EMPR:
682
682
  pcm_array = margin_data_resampler(
683
- dist_parms_pcm, sample_size=pcm_array.shape, seed_sequence=_pcm_rng_seed_seq
683
+ dist_parms_pcm, sample_size=pcm_array.shape, seed_sequence=_pcm_rng_seed_seq, nthreads=_nthreads
684
684
  )
685
685
  else:
686
686
  dist_type_: Literal["Beta", "Uniform"]
@@ -721,15 +721,15 @@ def _gen_margin_data(
721
721
  pcm_array = (beta_max - beta_min) * pcm_array + beta_min
722
722
  del beta_min, beta_max
723
723
 
724
- if dist_firm2_pcm == FM2Constraint.SYM:
724
+ if dist_firm2_pcm == PCMRestriction.SYM:
725
725
  pcm_array = np.hstack((pcm_array,) * _frmshr_array.shape[1])
726
- if dist_firm2_pcm == FM2Constraint.MNL:
726
+ if dist_firm2_pcm == PCMRestriction.MNL:
727
727
  # Impose FOCs from profit-maximization with MNL demand
728
728
  if dist_type_pcm == PCMDistribution.EMPR:
729
729
  print(
730
730
  "NOTE: Estimated Firm 2 parameters will not be consistent with "
731
731
  "the empirical distribution of margins in the source data. For "
732
- "consistency, respecify pcm_spec.firm2_pcm_constraint = FM2Constraint.IID."
732
+ "consistency, respecify pcm_spec.pcm_restriction = PCMRestriction.IID."
733
733
  )
734
734
  purchase_prob_array = _aggregate_purchase_prob * _frmshr_array
735
735
 
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.0
3
+ Version: 2025.739319.2
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=Wd2SFL2g3DbyGBAv7la2ELFnxs6EQBHawwDVLgqg808,5549
1
+ mergeron/__init__.py,sha256=xphVoHY19dbpym2LgjgAi5wedI5x0VsRocAy_dOqqFM,5549
2
2
  mergeron/core/__init__.py,sha256=BzL_bXHyOQG8cvo76OP3K48LkeHQCJQN7ZFPRhoOdcE,2850
3
- mergeron/core/empirical_margin_distribution.py,sha256=O-GD5X86tqf4kznELBzIcICueQxcL1igxHLJR9E7cU8,9229
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
13
+ mergeron/demo/visualize_empirical_margin_distribution.py,sha256=N8pYTl11ngG-W5WOjjYDigCIZs5LPVrUNxdgEHLwTHE,2584
14
+ mergeron/gen/__init__.py,sha256=2DqhKw1xJT20r_k9s7Hxpadnes0I6g0yWSiBhAc-cVM,22970
15
+ mergeron/gen/data_generation.py,sha256=x5hlRH0AeTHcoYszTxBKIWx8pyf-Lq9Yf0YYBcD2ofU,17147
16
+ mergeron/gen/data_generation_functions.py,sha256=ozgNg71_dYTRy-emlWafOvleiQI_479hRYrLzTp4NcE,26421
17
17
  mergeron/gen/enforcement_stats.py,sha256=UrsZWZNYy7DXWsCu96qmOQINipFbf9qLX0W8iNGgE_Y,11073
18
- mergeron/gen/upp_tests.py,sha256=Czub4njLESkV5LRwb1lByEI4nHBK0AwT96LYp_bG12s,6968
18
+ mergeron/gen/upp_tests.py,sha256=qCyIMY8fuaRqGobwlcu3SPpIlD-dDNdM53qC8CTx59k,7480
19
19
  mergeron/py.typed,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
20
- mergeron-2025.739319.0.dist-info/METADATA,sha256=7foBaEl6Nmoi5QFLnQSG45O1-JJROXXlyVxG0qfFS7E,6107
21
- mergeron-2025.739319.0.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
22
- mergeron-2025.739319.0.dist-info/RECORD,,
20
+ mergeron-2025.739319.2.dist-info/METADATA,sha256=UuxtNLK2yBiLtxInkFauiPinQehMikNg7pvaJYf1XLI,6056
21
+ mergeron-2025.739319.2.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
22
+ mergeron-2025.739319.2.dist-info/RECORD,,