mergeron 2024.739089.2__py3-none-any.whl → 2024.739091.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 +1 -1
- mergeron/ext/xlsxw_helper.py +111 -88
- mergeron/gen/__init__.py +35 -35
- mergeron/gen/enforcement_stats.py +7 -5
- {mergeron-2024.739089.2.dist-info → mergeron-2024.739091.2.dist-info}/METADATA +8 -7
- {mergeron-2024.739089.2.dist-info → mergeron-2024.739091.2.dist-info}/RECORD +7 -7
- {mergeron-2024.739089.2.dist-info → mergeron-2024.739091.2.dist-info}/WHEEL +0 -0
mergeron/__init__.py
CHANGED
mergeron/ext/xlsxw_helper.py
CHANGED
|
@@ -7,15 +7,15 @@ Includes a flexible system of defining cell formats.
|
|
|
7
7
|
NOTES
|
|
8
8
|
-----
|
|
9
9
|
|
|
10
|
-
This module is
|
|
10
|
+
This module is designed for producing formatted summary output. For
|
|
11
11
|
writing bulk data to Excel, facilities provided in third-party packages
|
|
12
|
-
such as `polars
|
|
12
|
+
such as `polars <https://pola.rs/>`_ likely provide better performance.
|
|
13
13
|
|
|
14
14
|
"""
|
|
15
15
|
|
|
16
16
|
from __future__ import annotations
|
|
17
17
|
|
|
18
|
-
from collections.abc import
|
|
18
|
+
from collections.abc import Sequence
|
|
19
19
|
from typing import Any, ClassVar, Literal, TypeAlias, TypedDict
|
|
20
20
|
|
|
21
21
|
import numpy as np
|
|
@@ -29,7 +29,7 @@ __version__ = VERSION
|
|
|
29
29
|
|
|
30
30
|
Workbook = xlsxwriter.Workbook
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
XLBorderType: TypeAlias = Literal[
|
|
33
33
|
"none",
|
|
34
34
|
"thin",
|
|
35
35
|
"medium",
|
|
@@ -66,13 +66,12 @@ xl_border_type: TypeAlias = Literal[
|
|
|
66
66
|
class CFmtVal(TypedDict, total=False):
|
|
67
67
|
"""Keys for xlsxwriter Format objects.
|
|
68
68
|
|
|
69
|
-
This is a partial list based on formats
|
|
69
|
+
This is a partial list based on formats of interest.
|
|
70
70
|
"""
|
|
71
71
|
|
|
72
72
|
font_name: str
|
|
73
73
|
font_size: int
|
|
74
74
|
font_color: str
|
|
75
|
-
bg_color: str # html color string, no #
|
|
76
75
|
align: Literal[
|
|
77
76
|
"left", "center", "right", "center_across", "top", "bottom", "vcenter"
|
|
78
77
|
]
|
|
@@ -100,93 +99,106 @@ class CFmtVal(TypedDict, total=False):
|
|
|
100
99
|
num_format: str
|
|
101
100
|
|
|
102
101
|
pattern: int
|
|
102
|
+
fg_color: str # html color string, no #
|
|
103
|
+
bg_color: str # html color string, no #
|
|
103
104
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
105
|
+
hidden: bool
|
|
106
|
+
locked: bool
|
|
107
|
+
|
|
108
|
+
border: XLBorderType
|
|
109
|
+
bottom: XLBorderType
|
|
110
|
+
left: XLBorderType
|
|
111
|
+
right: XLBorderType
|
|
112
|
+
top: XLBorderType
|
|
113
|
+
border_color: str # html color string, no #
|
|
109
114
|
bottom_color: str # html color string, no #
|
|
110
115
|
left_color: str # html color string, no #
|
|
111
116
|
right_color: str # html color string, no #
|
|
112
117
|
top_color: str # html color string, no #
|
|
113
118
|
|
|
119
|
+
diag_border: XLBorderType
|
|
120
|
+
diag_border_color: str # html color string, no #
|
|
121
|
+
diag_type: Literal[
|
|
122
|
+
1, 2, 3, "up", "down", "left", "right", "cross", "diagonalUp", "diagonalDown"
|
|
123
|
+
]
|
|
124
|
+
|
|
114
125
|
|
|
115
126
|
@unique
|
|
116
127
|
class CFmt(dict, Enum): # type: ignore
|
|
117
128
|
"""
|
|
118
|
-
|
|
129
|
+
Cell format enums for xlsxwriter Format objects.
|
|
119
130
|
|
|
120
|
-
The
|
|
121
|
-
and any
|
|
122
|
-
as xlsxWriter.Workbook.Format objects
|
|
123
|
-
|
|
131
|
+
The enums defined here, or sequences of (any of) them
|
|
132
|
+
and any added with :meth:`CFmt.add_new`, are
|
|
133
|
+
rendered as :code:`xlsxWriter.Workbook.Format` objects
|
|
134
|
+
with :meth:`CFmt.xl_fmt`.
|
|
124
135
|
|
|
125
136
|
NOTES
|
|
126
137
|
-----
|
|
127
138
|
|
|
128
|
-
For more information about xlsxwriter
|
|
139
|
+
For more information about xlsxwriter cell formats,
|
|
129
140
|
see, https://xlsxwriter.readthedocs.io/format.html
|
|
130
141
|
|
|
131
142
|
"""
|
|
132
143
|
|
|
133
|
-
XL_DEFAULT: ClassVar
|
|
134
|
-
XL_DEFAULT_2003: ClassVar
|
|
135
|
-
|
|
136
|
-
A_CTR: ClassVar
|
|
137
|
-
A_CTR_ACROSS: ClassVar
|
|
138
|
-
A_LEFT: ClassVar
|
|
139
|
-
A_RIGHT: ClassVar
|
|
140
|
-
V_TOP: ClassVar
|
|
141
|
-
V_BOTTOM: ClassVar
|
|
142
|
-
V_CTR: ClassVar
|
|
143
|
-
|
|
144
|
-
TEXT_WRAP: ClassVar
|
|
145
|
-
TEXT_ROTATE: ClassVar
|
|
146
|
-
IND_1: ClassVar
|
|
147
|
-
|
|
148
|
-
BOLD: ClassVar
|
|
149
|
-
BOLD_ITALIC: ClassVar
|
|
150
|
-
ITALIC: ClassVar
|
|
151
|
-
ULINE: ClassVar
|
|
152
|
-
SOUT: ClassVar
|
|
144
|
+
XL_DEFAULT: ClassVar = {"font_name": "Calibri", "font_size": 11}
|
|
145
|
+
XL_DEFAULT_2003: ClassVar = {"font_name": "Arial", "font_size": 10}
|
|
146
|
+
|
|
147
|
+
A_CTR: ClassVar = {"align": "center"}
|
|
148
|
+
A_CTR_ACROSS: ClassVar = {"align": "center_across"}
|
|
149
|
+
A_LEFT: ClassVar = {"align": "left"}
|
|
150
|
+
A_RIGHT: ClassVar = {"align": "right"}
|
|
151
|
+
V_TOP: ClassVar = {"align": "top"}
|
|
152
|
+
V_BOTTOM: ClassVar = {"align": "bottom"}
|
|
153
|
+
V_CTR: ClassVar = {"align": "vcenter"}
|
|
154
|
+
|
|
155
|
+
TEXT_WRAP: ClassVar = {"text_wrap": True}
|
|
156
|
+
TEXT_ROTATE: ClassVar = {"rotation": 90}
|
|
157
|
+
IND_1: ClassVar = {"indent": 1}
|
|
158
|
+
|
|
159
|
+
BOLD: ClassVar = {"bold": True}
|
|
160
|
+
BOLD_ITALIC: ClassVar = {"bold": True, "italic": True}
|
|
161
|
+
ITALIC: ClassVar = {"italic": True}
|
|
162
|
+
ULINE: ClassVar = {"underline": "single"}
|
|
163
|
+
SOUT: ClassVar = {"font_strikeout": True}
|
|
153
164
|
# Useful with write_rich_text()
|
|
154
|
-
SUPERSCRIPT: ClassVar
|
|
155
|
-
SUBSCRIPT: ClassVar
|
|
156
|
-
|
|
157
|
-
AREA_NUM: ClassVar
|
|
158
|
-
DOLLAR_NUM: ClassVar
|
|
159
|
-
DT_NUM: ClassVar
|
|
160
|
-
PCT_NUM: ClassVar
|
|
161
|
-
PCT2_NUM: ClassVar
|
|
162
|
-
PCT4_NUM: ClassVar
|
|
163
|
-
PCT6_NUM: ClassVar
|
|
164
|
-
PCT8_NUM: ClassVar
|
|
165
|
-
QTY_NUM: ClassVar
|
|
166
|
-
|
|
167
|
-
BAR_FILL: ClassVar
|
|
168
|
-
HDR_FILL: ClassVar
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
165
|
+
SUPERSCRIPT: ClassVar = {"font_script": 1}
|
|
166
|
+
SUBSCRIPT: ClassVar = {"font_script": 2}
|
|
167
|
+
|
|
168
|
+
AREA_NUM: ClassVar = {"num_format": "0.00000000"}
|
|
169
|
+
DOLLAR_NUM: ClassVar = {"num_format": "[$$-409]#,##0.00"}
|
|
170
|
+
DT_NUM: ClassVar = {"num_format": "mm/dd/yyyy"}
|
|
171
|
+
PCT_NUM: ClassVar = {"num_format": "##0%"}
|
|
172
|
+
PCT2_NUM: ClassVar = {"num_format": "##0.00%"}
|
|
173
|
+
PCT4_NUM: ClassVar = {"num_format": "##0.0000%"}
|
|
174
|
+
PCT6_NUM: ClassVar = {"num_format": "##0.000000%"}
|
|
175
|
+
PCT8_NUM: ClassVar = {"num_format": "##0.00000000%"}
|
|
176
|
+
QTY_NUM: ClassVar = {"num_format": "#,##0.0"}
|
|
177
|
+
|
|
178
|
+
BAR_FILL: ClassVar = {"pattern": 1, "bg_color": "dfeadf"}
|
|
179
|
+
HDR_FILL: ClassVar = {"pattern": 1, "bg_color": "bfbfbf"}
|
|
180
|
+
|
|
181
|
+
FULL_BORDER: ClassVar = {"border": 1, "border_color": "000000"}
|
|
182
|
+
BOTTOM_BORDER: ClassVar = {"bottom": 1, "bottom_color": "000000"}
|
|
183
|
+
LEFT_BORDER: ClassVar = {"left": 1, "left_color": "000000"}
|
|
184
|
+
RIGHT_BORDER: ClassVar = {"right": 1, "right_color": "000000"}
|
|
185
|
+
TOP_BORDER: ClassVar = {"top": 1, "top_color": "000000"}
|
|
186
|
+
HDR_BORDER: ClassVar = TOP_BORDER | BOTTOM_BORDER
|
|
175
187
|
|
|
176
188
|
@classmethod
|
|
177
189
|
def add_new(self, _fmt_name: str, _xlsx_fmt_dict: CFmtVal, /) -> CFmt:
|
|
178
190
|
"""
|
|
179
|
-
Add new CFmt object to instance.
|
|
191
|
+
Add new :class:`CFmt` object to instance.
|
|
180
192
|
|
|
181
193
|
Parameters
|
|
182
194
|
----------
|
|
183
195
|
_fmt_name
|
|
184
|
-
Name of new member to be added to CFmt
|
|
196
|
+
Name of new member to be added to :class:`CFmt`
|
|
185
197
|
_xlsx_fmt_dict
|
|
186
|
-
Any valid argument to xlsxwriter.Workbook.add_format()
|
|
187
|
-
same with one or more CFmt objects
|
|
188
|
-
CFmt.HDR_BORDER | CFmt.HDR_FILL or
|
|
189
|
-
CFmt.HDR_BORDER | {"pattern": 1, "bg_color": "f2f2f2"}
|
|
198
|
+
Any valid argument to :code:`xlsxwriter.Workbook.add_format()`, or union of
|
|
199
|
+
same with one or more :class:`CFmt` objects, e.g.,
|
|
200
|
+
:code:`CFmt.HDR_BORDER | CFmt.HDR_FILL` or
|
|
201
|
+
:code:`CFmt.HDR_BORDER | {"pattern": 1, "bg_color": "f2f2f2"}`
|
|
190
202
|
|
|
191
203
|
Returns
|
|
192
204
|
-------
|
|
@@ -198,20 +210,21 @@ class CFmt(dict, Enum): # type: ignore
|
|
|
198
210
|
|
|
199
211
|
@classmethod
|
|
200
212
|
def ensure_cell_format_spec_tuple(
|
|
201
|
-
self,
|
|
213
|
+
self, _cell_format: Sequence[CFmt | Sequence[CFmt]], /
|
|
202
214
|
) -> bool:
|
|
203
215
|
"""
|
|
204
|
-
Test that a given format specification is a tuple of CFmt enums
|
|
216
|
+
Test that a given format specification is a tuple of :class:`CFmt` enums
|
|
205
217
|
|
|
206
218
|
Parameters
|
|
207
219
|
----------
|
|
208
|
-
|
|
220
|
+
_cell_format
|
|
209
221
|
Format specification
|
|
210
222
|
|
|
211
223
|
Raises
|
|
212
224
|
------
|
|
213
225
|
ValueError
|
|
214
|
-
If format specification is not
|
|
226
|
+
If format specification is not a sequence of (sequences of)
|
|
227
|
+
:class:`CFmt` enums
|
|
215
228
|
|
|
216
229
|
Returns
|
|
217
230
|
-------
|
|
@@ -219,14 +232,14 @@ class CFmt(dict, Enum): # type: ignore
|
|
|
219
232
|
|
|
220
233
|
"""
|
|
221
234
|
|
|
222
|
-
for
|
|
223
|
-
if isinstance(
|
|
224
|
-
self.ensure_cell_format_spec_tuple(
|
|
235
|
+
for _cf in _cell_format:
|
|
236
|
+
if isinstance(_cf, tuple):
|
|
237
|
+
self.ensure_cell_format_spec_tuple(_cf)
|
|
225
238
|
|
|
226
|
-
if not (isinstance(
|
|
239
|
+
if not (isinstance(_cf, CFmt),):
|
|
227
240
|
raise ValueError(
|
|
228
241
|
"Improperly specified format tuple for writing array."
|
|
229
|
-
" Must be tuple of CFmt enums."
|
|
242
|
+
" Must be tuple of :class:`CFmt` enums."
|
|
230
243
|
)
|
|
231
244
|
|
|
232
245
|
return True
|
|
@@ -239,7 +252,7 @@ class CFmt(dict, Enum): # type: ignore
|
|
|
239
252
|
/,
|
|
240
253
|
) -> xlsxwriter.format.Format:
|
|
241
254
|
"""
|
|
242
|
-
Return :code:`xlsxwriter`
|
|
255
|
+
Return :code:`xlsxwriter` :code:`Format` object given a :class:`CFmt` enum, or tuple thereof.
|
|
243
256
|
|
|
244
257
|
Parameters
|
|
245
258
|
----------
|
|
@@ -247,17 +260,17 @@ class CFmt(dict, Enum): # type: ignore
|
|
|
247
260
|
:code:`xlsxwriter.Workbook` object
|
|
248
261
|
|
|
249
262
|
_cell_fmt
|
|
250
|
-
:
|
|
263
|
+
:class:`CFmt` enum object, or tuple thereof
|
|
251
264
|
|
|
252
265
|
Raises
|
|
253
266
|
------
|
|
254
267
|
ValueError
|
|
255
|
-
If format specification is not one of None, a CFmt
|
|
256
|
-
a xlsxwriter.format.Format object
|
|
268
|
+
If format specification is not one of None, a :class:`CFmt` enum, or
|
|
269
|
+
a :code:`xlsxwriter.format.Format` object
|
|
257
270
|
|
|
258
271
|
Returns
|
|
259
272
|
-------
|
|
260
|
-
:code:`xlsxwriter`
|
|
273
|
+
:code:`xlsxwriter` :code:`Format` object
|
|
261
274
|
|
|
262
275
|
"""
|
|
263
276
|
|
|
@@ -266,7 +279,7 @@ class CFmt(dict, Enum): # type: ignore
|
|
|
266
279
|
elif _cell_fmt is None:
|
|
267
280
|
return _xl_book.add_format(CFmt.XL_DEFAULT.value)
|
|
268
281
|
|
|
269
|
-
_cell_fmt_dict:
|
|
282
|
+
_cell_fmt_dict: CFmtVal = {}
|
|
270
283
|
if isinstance(_cell_fmt, Sequence):
|
|
271
284
|
self.ensure_cell_format_spec_tuple(_cell_fmt)
|
|
272
285
|
for _cf in _cell_fmt:
|
|
@@ -387,7 +400,11 @@ def array_to_sheet(
|
|
|
387
400
|
Write a 2-D array to a worksheet.
|
|
388
401
|
|
|
389
402
|
The given array is required be a two-dimensional array, whether
|
|
390
|
-
a nested list, nested tuple, or a 2-D numpy ndarray.
|
|
403
|
+
a nested list, nested tuple, or a 2-D numpy ndarray. The array is assumed
|
|
404
|
+
to be ragged by default, i.e. not all rows are the same length, and some
|
|
405
|
+
cells may contain lists, etc. For rectangular arrays, set `ragged_flag` to
|
|
406
|
+
false if you wish to provide a format tuple with distinct formats for each
|
|
407
|
+
column in the rectangular array.
|
|
391
408
|
|
|
392
409
|
|
|
393
410
|
Parameters
|
|
@@ -430,7 +447,8 @@ def array_to_sheet(
|
|
|
430
447
|
If array is not rectangular and cell_format is a Sequence
|
|
431
448
|
|
|
432
449
|
ValueError
|
|
433
|
-
If array is rectangular format tuple does not
|
|
450
|
+
If array is rectangular but length of format tuple does not
|
|
451
|
+
match row-length
|
|
434
452
|
|
|
435
453
|
|
|
436
454
|
Returns
|
|
@@ -441,12 +459,12 @@ def array_to_sheet(
|
|
|
441
459
|
Notes
|
|
442
460
|
-----
|
|
443
461
|
|
|
444
|
-
The keyword argument cell_format may be passed a tuple of CFmt enums,
|
|
462
|
+
The keyword argument cell_format may be passed a tuple of :class:`CFmt` enums,
|
|
445
463
|
if, and only if, ragged_flag is False. If cell_format is a tuple, it must
|
|
446
|
-
have length equal to the number of cells in
|
|
447
|
-
members of cell_format must each be a CFmt enum or a
|
|
448
|
-
other words,
|
|
449
|
-
any tuple `_c` passed as `cell_format`.
|
|
464
|
+
have length equal to the number of cells in each row of the passed array.
|
|
465
|
+
Further, members of cell_format must each be a :class:`CFmt` enum or a
|
|
466
|
+
tuple of :class:`CFmt` enums; in other words, :meth:`CFmt.ensure_cell_format_spec_tuple`
|
|
467
|
+
must return True for any tuple `_c` passed as `cell_format`.
|
|
450
468
|
|
|
451
469
|
"""
|
|
452
470
|
|
|
@@ -540,11 +558,11 @@ def scalar_to_sheet(
|
|
|
540
558
|
|
|
541
559
|
_cell_addr_0
|
|
542
560
|
First element of a cell address, which may be the entire address
|
|
543
|
-
in 'A1' format or the row-part in '
|
|
561
|
+
in 'A1' format or the row-part in 'Row-column' format
|
|
544
562
|
|
|
545
563
|
_s2s_args
|
|
546
564
|
Other arguments, which may be just the cell value to be written and the
|
|
547
|
-
cell format, or the column-part of the '
|
|
565
|
+
cell format, or the column-part of the 'Row-column' address along with
|
|
548
566
|
cell value and cell format.
|
|
549
567
|
|
|
550
568
|
Raises
|
|
@@ -558,6 +576,11 @@ def scalar_to_sheet(
|
|
|
558
576
|
-------
|
|
559
577
|
None
|
|
560
578
|
|
|
579
|
+
Notes
|
|
580
|
+
-----
|
|
581
|
+
For more information on xlsxwriter cell-address notation, see:
|
|
582
|
+
https://xlsxwriter.readthedocs.io/working_with_cell_notation.html
|
|
583
|
+
|
|
561
584
|
"""
|
|
562
585
|
|
|
563
586
|
_cell_addr: tuple[int | str, ...] = ()
|
mergeron/gen/__init__.py
CHANGED
|
@@ -111,7 +111,7 @@ class ShareSpec:
|
|
|
111
111
|
"""
|
|
112
112
|
|
|
113
113
|
dist_type: SHRConstants
|
|
114
|
-
"""See :class:`
|
|
114
|
+
"""See :class:`SHRConstants`"""
|
|
115
115
|
|
|
116
116
|
dist_parms: NDArray[np.float64] | None = field(
|
|
117
117
|
default=None, eq=cmp_using(eq=np.array_equal)
|
|
@@ -144,7 +144,7 @@ class PCMConstants(enum.StrEnum):
|
|
|
144
144
|
UNI = "Uniform"
|
|
145
145
|
BETA = "Beta"
|
|
146
146
|
BETA_BND = "Bounded Beta"
|
|
147
|
-
EMPR = "Damodaran margin data"
|
|
147
|
+
EMPR = "Damodaran margin data, resampled"
|
|
148
148
|
|
|
149
149
|
|
|
150
150
|
@enum.unique
|
|
@@ -173,10 +173,10 @@ class PCMSpec:
|
|
|
173
173
|
"""
|
|
174
174
|
|
|
175
175
|
firm2_pcm_constraint: FM2Constants
|
|
176
|
-
"""See :class:`
|
|
176
|
+
"""See :class:`FM2Constants`"""
|
|
177
177
|
|
|
178
178
|
dist_type: PCMConstants
|
|
179
|
-
"""See :class:`
|
|
179
|
+
"""See :class:`PCMConstants`"""
|
|
180
180
|
|
|
181
181
|
dist_parms: NDArray[np.float64] | None
|
|
182
182
|
"""Parameter specification for tailoring PCM distribution
|
|
@@ -313,55 +313,28 @@ class MarketSpec:
|
|
|
313
313
|
default=ShareSpec(RECConstants.INOUT, 0.85, SHRConstants.UNI, None, None),
|
|
314
314
|
validator=[validators.instance_of(ShareSpec), _share_spec_validator],
|
|
315
315
|
)
|
|
316
|
-
"""Market-share specification, see :class:`
|
|
316
|
+
"""Market-share specification, see :class:`ShareSpec`"""
|
|
317
317
|
|
|
318
318
|
pcm_spec: PCMSpec = field(
|
|
319
319
|
kw_only=True,
|
|
320
320
|
default=PCMSpec(FM2Constants.IID, PCMConstants.UNI, None),
|
|
321
321
|
validator=[validators.instance_of(PCMSpec), _pcm_spec_validator],
|
|
322
322
|
)
|
|
323
|
-
"""Margin specification, see :class:`
|
|
323
|
+
"""Margin specification, see :class:`PCMSpec`"""
|
|
324
324
|
|
|
325
325
|
price_spec: PriceConstants = field(
|
|
326
326
|
kw_only=True,
|
|
327
327
|
default=PriceConstants.SYM,
|
|
328
328
|
validator=validators.instance_of(PriceConstants),
|
|
329
329
|
)
|
|
330
|
-
"""Price specification, see :class:`
|
|
330
|
+
"""Price specification, see :class:`PriceConstants`"""
|
|
331
331
|
|
|
332
332
|
hsr_filing_test_type: SSZConstants = field(
|
|
333
333
|
kw_only=True,
|
|
334
334
|
default=SSZConstants.ONE,
|
|
335
335
|
validator=validators.instance_of(SSZConstants),
|
|
336
336
|
)
|
|
337
|
-
"""Method for modeling HSR filing threholds, see :class:`
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
@enum.unique
|
|
341
|
-
class INVResolution(enum.StrEnum):
|
|
342
|
-
CLRN = "clearance"
|
|
343
|
-
ENFT = "enforcement"
|
|
344
|
-
BOTH = "both"
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
@frozen
|
|
348
|
-
class UPPTestRegime:
|
|
349
|
-
resolution: INVResolution = field(
|
|
350
|
-
default=INVResolution.ENFT, validator=validators.instance_of(INVResolution)
|
|
351
|
-
)
|
|
352
|
-
guppi_aggregator: UPPAggrSelector = field(
|
|
353
|
-
default=UPPAggrSelector.MIN, validator=validators.instance_of(UPPAggrSelector)
|
|
354
|
-
)
|
|
355
|
-
divr_aggregator: UPPAggrSelector | None = field(
|
|
356
|
-
default=None, validator=validators.instance_of((UPPAggrSelector, type(None)))
|
|
357
|
-
)
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
# https://stackoverflow.com/questions/54668000
|
|
361
|
-
class DataclassInstance(Protocol):
|
|
362
|
-
"""Generic dataclass-instance"""
|
|
363
|
-
|
|
364
|
-
__dataclass_fields__: ClassVar
|
|
337
|
+
"""Method for modeling HSR filing threholds, see :class:`SSZConstants`"""
|
|
365
338
|
|
|
366
339
|
|
|
367
340
|
@dataclass(slots=True, frozen=True)
|
|
@@ -457,6 +430,26 @@ class MarginDataSample:
|
|
|
457
430
|
"""
|
|
458
431
|
|
|
459
432
|
|
|
433
|
+
@enum.unique
|
|
434
|
+
class INVResolution(enum.StrEnum):
|
|
435
|
+
CLRN = "clearance"
|
|
436
|
+
ENFT = "enforcement"
|
|
437
|
+
BOTH = "both"
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
@frozen
|
|
441
|
+
class UPPTestRegime:
|
|
442
|
+
resolution: INVResolution = field(
|
|
443
|
+
default=INVResolution.ENFT, validator=validators.instance_of(INVResolution)
|
|
444
|
+
)
|
|
445
|
+
guppi_aggregator: UPPAggrSelector = field(
|
|
446
|
+
default=UPPAggrSelector.MIN, validator=validators.instance_of(UPPAggrSelector)
|
|
447
|
+
)
|
|
448
|
+
divr_aggregator: UPPAggrSelector | None = field(
|
|
449
|
+
default=None, validator=validators.instance_of((UPPAggrSelector, type(None)))
|
|
450
|
+
)
|
|
451
|
+
|
|
452
|
+
|
|
460
453
|
@dataclass(slots=True, frozen=True)
|
|
461
454
|
class UPPTestsRaw:
|
|
462
455
|
"""Container for arrays marking test failures and successes
|
|
@@ -494,3 +487,10 @@ class UPPTestsCounts:
|
|
|
494
487
|
by_conczone: NDArray[np.int64]
|
|
495
488
|
"""Zones are "unoncentrated", "moderately concentrated", and "highly concentrated"
|
|
496
489
|
"""
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
# https://stackoverflow.com/questions/54668000
|
|
493
|
+
class DataclassInstance(Protocol):
|
|
494
|
+
"""Generic dataclass-instance"""
|
|
495
|
+
|
|
496
|
+
__dataclass_fields__: ClassVar
|
|
@@ -188,7 +188,7 @@ ZONE_STRINGS = {
|
|
|
188
188
|
0: R"Green Zone (Safeharbor)",
|
|
189
189
|
1: R"Yellow Zone",
|
|
190
190
|
2: R"Red Zone (SLC Presumption)",
|
|
191
|
-
fid.TTL_KEY:
|
|
191
|
+
fid.TTL_KEY: "TOTAL",
|
|
192
192
|
}
|
|
193
193
|
ZONE_DETAIL_STRINGS_HHI = {
|
|
194
194
|
0: Rf"HHI < {HHI_POST_ZONE_KNOTS[1]} pts.",
|
|
@@ -213,7 +213,9 @@ ZONE_STRINGS_LATEX = {
|
|
|
213
213
|
|
|
214
214
|
ZONE_DETAIL_STRINGS_HHI_LATEX = {
|
|
215
215
|
0: Rf"HHI_{{post}} < \text{{{HHI_POST_ZONE_KNOTS[1]} pts.}}",
|
|
216
|
-
1: R"HHI_{{post}}
|
|
216
|
+
1: R"HHI_{{post}} \in \text{{[{}, {}) pts. and }} ".format(
|
|
217
|
+
*HHI_POST_ZONE_KNOTS[1:3]
|
|
218
|
+
),
|
|
217
219
|
2: Rf"HHI_{{post}} \geqslant \text{{{HHI_POST_ZONE_KNOTS[2]} pts. and }} ",
|
|
218
220
|
}
|
|
219
221
|
|
|
@@ -249,9 +251,9 @@ def enf_stats_output(
|
|
|
249
251
|
case StatsGrpSelector.ZN:
|
|
250
252
|
_enf_stats_table_func = enf_stats_table_byzone
|
|
251
253
|
case StatsGrpSelector.FC:
|
|
252
|
-
_enf_stats_table_func =
|
|
254
|
+
_enf_stats_table_func = enf_stats_table_onedim
|
|
253
255
|
case StatsGrpSelector.DL:
|
|
254
|
-
_enf_stats_table_func =
|
|
256
|
+
_enf_stats_table_func = enf_stats_table_onedim
|
|
255
257
|
case _:
|
|
256
258
|
raise ValueError(
|
|
257
259
|
'Statistics formatted, "{_stats_group}" not available here.'
|
|
@@ -510,7 +512,7 @@ def enf_cnts_byconczone(_cnts_array: NDArray[np.int64], /) -> NDArray[np.int64]:
|
|
|
510
512
|
return _cnts_byconczone[1:]
|
|
511
513
|
|
|
512
514
|
|
|
513
|
-
def
|
|
515
|
+
def enf_stats_table_onedim(
|
|
514
516
|
_inparr: NDArray[np.float64 | np.int64],
|
|
515
517
|
_totals_row: int | None = None,
|
|
516
518
|
/,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: mergeron
|
|
3
|
-
Version: 2024.
|
|
3
|
+
Version: 2024.739091.2
|
|
4
4
|
Summary: Merger Policy Analysis using Python
|
|
5
5
|
License: MIT
|
|
6
6
|
Keywords: merger policy analysis,merger guidelines,merger screening,policy presumptions,concentration standards,upward pricing pressure,GUPPI
|
|
@@ -34,6 +34,7 @@ Requires-Dist: msgpack-numpy (>=0.4)
|
|
|
34
34
|
Requires-Dist: numpy (>=1.26,<2.0)
|
|
35
35
|
Requires-Dist: openpyxl (>=3.1.2)
|
|
36
36
|
Requires-Dist: pendulum (>=3.0.0)
|
|
37
|
+
Requires-Dist: poetry-plugin-export (>=1.8.0,<2.0.0)
|
|
37
38
|
Requires-Dist: requests (>=2.31)
|
|
38
39
|
Requires-Dist: requests-toolbelt (>=1.0.0)
|
|
39
40
|
Requires-Dist: scipy (>=1.12)
|
|
@@ -56,13 +57,13 @@ Intrinsic clearance and enforcement rates are distinguished from *observed* clea
|
|
|
56
57
|
Introduction
|
|
57
58
|
------------
|
|
58
59
|
|
|
59
|
-
Classes for specifying concentration standards (
|
|
60
|
+
Classes for specifying concentration standards (:code:`mergeron.core.guidelines_boundaries.ConcentrationBoundary`) and diversion-ratio standards (:code:`mergeron.core.guidelines_boundaries.DiversionRatioBoundary`), with automatic generation of boundary (as an array of share-pairs) and area, are provided in :code:`mergeron.core.guidelines_boundaries`. This module also includes a function for generating plots of concentation and diversion-ratio boundaries, and functions for mapping GUPPI standards to concentration (ΔHHI) standards, and vice-versa.
|
|
60
61
|
|
|
61
|
-
Methods for generating industry data under various distributions of shares, margins, and prices are included in,
|
|
62
|
+
Methods for generating industry data under various distributions of shares, margins, and prices are included in, :code:`mergeron.gen.data_generation`. Shares are drawn with uniform distribution with :math:`s_1 + s_2 \leqslant 1` and an unspecified number of firms. Alternatively, shares may be drawn from the Dirichlet distribution. When drawing shares from the Dirichlet distribution, the user can specify a fixed number for firms or provide a vector of weights specifying the frequency distribution over sequential firm counts, e.g., :code:`[133, 184, 134, 52, 32, 10, 12, 4, 3]` to specify shares drawn from Dirichlet distributions with 2 to 10 pre-merger firms distributed as in data for FTC merger investigations during 1996--2003 (See, for example, Table 4.1 of `FTC, Horizontal Merger Investigations Data, Fiscal Years 1996--2003 (Revised: August 31, 2004) <"https://www.ftc.gov/sites/default/files/documents/reports/horizontal-merger-investigation-data-fiscal-years-1996-2003/040831horizmergersdata96-03.pdf>`_). The user can specify recapture rates as, "proportional", "inside-out" --- i.e., consistent with merging-firms' in-market shares and a default recapture rate) --- or "outside-in" --- i.e., purchase probabilities are drawn at random for :math:`N+1` goods, from which are derived market shares and recapture rates for the :math:`N` goods in the putative market. Documentation on specifying the sampling strategy for market shares is at :code:`mergeron.gen.ShareSpec`. Price-cost-margins may be specified as symmetric, i.i.d., or subject to equilibrium conditions for (profit-mazimization in) Bertrand-Nash oligopoly with MNL demand (see, :code:`mergeron.gen.PCMSpec`). Prices may be specified as symmetric or asymmetric, and in the latter case, the direction of correlation between merging firm prices, if any, can also be specified (see, :code:`mergeron.gen.PriceSpec`). Two alternative approaches for modeling statutory filing requirements (HSR filing thresholds) are implemented (see, :code:`mergeron.gen.SSZConstants`). The full specification of a market sample is given in a :code:`mergeron.gen.market_sample.MarketSample` object. Data are drawn by invoking :code:`mergeron.gen.market_sample.MarketSample.generate_sample` which adds a :code:`data` property of class, :code:`mergeron.gen.MarketDataSample`. Enforcement or clearance counts are computed by invoking :code:`mergeron.gen.market_sample.MarketSample.estimate_invres_counts`, which adds an :code:`invres_counts` property of class :code:`mergeron.gen.UPPTestsCounts`. For fast, parallel generation of enforcement or clearance counts over large market data samples that ordinarily would exceed available limits on machine memory, the user can invoke the method :code:`estimate_invres_counts` on a :code:`mergeron.gen.market_sample.MarketSample` object without first invoking :code:`generate_sample`. Note, however, that this strategy discards the market sample in the interests of conserving memory and maintaining high performance.
|
|
62
63
|
|
|
63
|
-
Methods for printing enforcement statistics based on FTC investigations data and test data are printed to screen or rendered to LaTex files (for processing into publication-quality tables) using methods provided in
|
|
64
|
+
Methods for printing enforcement statistics based on FTC investigations data and test data are printed to screen or rendered to LaTex files (for processing into publication-quality tables) using methods provided in :code:`mergeron.gen.enforcement_stats`.
|
|
64
65
|
|
|
65
|
-
Programs demonstrating the analysis and reporting facilites provided by the sub-package,
|
|
66
|
+
Programs demonstrating the analysis and reporting facilites provided by the sub-package, :code:`mergeron.demo`.
|
|
66
67
|
|
|
67
68
|
This package exposes methods employed for generating random numbers with selected continuous distribution over specified parameters, and with CPU multithreading on machines with multiple virtual, logical, or physical CPU cores. To access these directly:
|
|
68
69
|
|
|
@@ -70,13 +71,13 @@ This package exposes methods employed for generating random numbers with selecte
|
|
|
70
71
|
|
|
71
72
|
import mergeron.core.pseudorandom_numbers as prng
|
|
72
73
|
|
|
73
|
-
Also included are methods for estimating confidence intervals for proportions and for contrasts (differences) in proportions. (Although coded from scratch using the source literature, the APIs implemented in the module included here are designed for consistency with the APIs in,
|
|
74
|
+
Also included are methods for estimating confidence intervals for proportions and for contrasts (differences) in proportions. (Although coded from scratch using the source literature, the APIs implemented in the module included here are designed for consistency with the APIs in, :code:`statsmodels.stats.proportion` from the package, :code:`statsmodels` (https://pypi.org/project/statsmodels/).) To access these directly:
|
|
74
75
|
|
|
75
76
|
.. code-block:: python
|
|
76
77
|
|
|
77
78
|
import mergeron.core.proportions_tests as prci
|
|
78
79
|
|
|
79
|
-
A recent version of Paul Tol's python module,
|
|
80
|
+
A recent version of Paul Tol's python module, :code:`tol_colors.py` is redistributed within this package. Other than re-formatting and type annotation, the :code:`mergeron.ext.tol_colors` module is re-distributed as downloaded from, https://personal.sron.nl/~pault/data/tol_colors.py. The :code:`tol_colors.py` module is distributed under the Standard 3-clause BSD license. To access the :code:`mergeron.ext.tol_colors` module directly:
|
|
80
81
|
|
|
81
82
|
.. code-block:: python
|
|
82
83
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
mergeron/License.txt,sha256=7iX-y0EyjkbVJKJLS4ZKzuuE1wd0lryfsD_IytLG8lQ,1246
|
|
2
|
-
mergeron/__init__.py,sha256=
|
|
2
|
+
mergeron/__init__.py,sha256=dQe1ZhZ4GP5p0TMy4E_chUcvo-6TpWhft70eWLQCZBY,1647
|
|
3
3
|
mergeron/core/__init__.py,sha256=KtjBlZOl7jwBCAUhrTJB9PdrN39YLYytNiSUSM_gRmA,62
|
|
4
4
|
mergeron/core/damodaran_margin_data.py,sha256=pjI1rSK_O1-3Oel5b9KXH6ctnInjX1Vii7fypt00gV8,8541
|
|
5
5
|
mergeron/core/ftc_merger_investigations_data.py,sha256=ZaV2DO7UZabV8eX0Ubq_ToIor7tIRzcvYC54ADliuTk,27931
|
|
@@ -23,14 +23,14 @@ mergeron/demo/__init__.py,sha256=KtjBlZOl7jwBCAUhrTJB9PdrN39YLYytNiSUSM_gRmA,62
|
|
|
23
23
|
mergeron/demo/visualize_empirical_margin_distribution.py,sha256=v1xFJumBX2Ooye82kSSgly-_GpFVkYSDqBwM__rcmZY,2363
|
|
24
24
|
mergeron/ext/__init__.py,sha256=KtjBlZOl7jwBCAUhrTJB9PdrN39YLYytNiSUSM_gRmA,62
|
|
25
25
|
mergeron/ext/tol_colors.py,sha256=QBw8s-ZGpUpIIYOplHbLFZSXVoa6eDDJDtzSScP954E,22303
|
|
26
|
-
mergeron/ext/xlsxw_helper.py,sha256=
|
|
27
|
-
mergeron/gen/__init__.py,sha256=
|
|
26
|
+
mergeron/ext/xlsxw_helper.py,sha256=4wAhwQjWKSm65931sR_4yO6EuoU2RnWvtW5aCSQn5Iw,17951
|
|
27
|
+
mergeron/gen/__init__.py,sha256=pAEirl5FAO9r_6f7BdvqU0LCH9lXMe1YR0SnrGMpCWI,16200
|
|
28
28
|
mergeron/gen/_data_generation_functions.py,sha256=7fP4mSVaN36FBhPKSf1y_TbxfRUe-I7fgqdBt74oaCA,21029
|
|
29
29
|
mergeron/gen/data_generation.py,sha256=gDvCZYJwGpQnokcygM7IRzHBpE5rYI2J5I8uu0_wQyE,8727
|
|
30
|
-
mergeron/gen/enforcement_stats.py,sha256=
|
|
30
|
+
mergeron/gen/enforcement_stats.py,sha256=Hr-w3LZ9SJD4A1RZS1KMhXwuKyGzPC7eeNQullWZRNU,24410
|
|
31
31
|
mergeron/gen/market_sample.py,sha256=ekMA9db2AWvrA-GDbIieu270fovFX0JyynCo5FRAGzk,2270
|
|
32
32
|
mergeron/gen/upp_tests.py,sha256=GQZcXU4vQPJRxdI2DVsY7yX6TPqhntlTH-DOAufWFmM,17197
|
|
33
33
|
mergeron/py.typed,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
|
|
34
|
-
mergeron-2024.
|
|
35
|
-
mergeron-2024.
|
|
36
|
-
mergeron-2024.
|
|
34
|
+
mergeron-2024.739091.2.dist-info/METADATA,sha256=wK0ioIu_QUYP5PLYeJgBKqM8A1wfIWJOG22beUjM8AI,8899
|
|
35
|
+
mergeron-2024.739091.2.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
36
|
+
mergeron-2024.739091.2.dist-info/RECORD,,
|
|
File without changes
|