dycw-utilities 0.109.20__py3-none-any.whl → 0.109.22__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.
- {dycw_utilities-0.109.20.dist-info → dycw_utilities-0.109.22.dist-info}/METADATA +3 -3
- {dycw_utilities-0.109.20.dist-info → dycw_utilities-0.109.22.dist-info}/RECORD +7 -6
- utilities/__init__.py +1 -1
- utilities/polars.py +112 -0
- utilities/statsmodels.py +150 -0
- {dycw_utilities-0.109.20.dist-info → dycw_utilities-0.109.22.dist-info}/WHEEL +0 -0
- {dycw_utilities-0.109.20.dist-info → dycw_utilities-0.109.22.dist-info}/licenses/LICENSE +0 -0
@@ -1,12 +1,12 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: dycw-utilities
|
3
|
-
Version: 0.109.
|
3
|
+
Version: 0.109.22
|
4
4
|
Author-email: Derek Wan <d.wan@icloud.com>
|
5
5
|
License-File: LICENSE
|
6
6
|
Requires-Python: >=3.12
|
7
7
|
Requires-Dist: typing-extensions<4.14,>=4.13.1
|
8
8
|
Provides-Extra: test
|
9
|
-
Requires-Dist: hypothesis<6.132,>=6.131.
|
9
|
+
Requires-Dist: hypothesis<6.132,>=6.131.9; extra == 'test'
|
10
10
|
Requires-Dist: pytest-asyncio<0.27,>=0.26.0; extra == 'test'
|
11
11
|
Requires-Dist: pytest-cov<6.2,>=6.1.1; extra == 'test'
|
12
12
|
Requires-Dist: pytest-instafail<0.6,>=0.5.0; extra == 'test'
|
@@ -80,7 +80,7 @@ Provides-Extra: zzz-test-hypothesis
|
|
80
80
|
Requires-Dist: aiosqlite<0.22,>=0.21.0; extra == 'zzz-test-hypothesis'
|
81
81
|
Requires-Dist: asyncpg<0.31,>=0.30.0; extra == 'zzz-test-hypothesis'
|
82
82
|
Requires-Dist: greenlet<3.3,>=3.2.0; extra == 'zzz-test-hypothesis'
|
83
|
-
Requires-Dist: hypothesis<6.132,>=6.131.
|
83
|
+
Requires-Dist: hypothesis<6.132,>=6.131.9; extra == 'zzz-test-hypothesis'
|
84
84
|
Requires-Dist: luigi<3.7,>=3.6.0; extra == 'zzz-test-hypothesis'
|
85
85
|
Requires-Dist: numpy<2.3,>=2.2.5; extra == 'zzz-test-hypothesis'
|
86
86
|
Requires-Dist: pathvalidate<3.3,>=3.2.3; extra == 'zzz-test-hypothesis'
|
@@ -1,4 +1,4 @@
|
|
1
|
-
utilities/__init__.py,sha256=
|
1
|
+
utilities/__init__.py,sha256=8f1PKZxzDeABQ7A4zZsmHKuHRkJKy1jboB_m42AXKxw,61
|
2
2
|
utilities/altair.py,sha256=Gpja-flOo-Db0PIPJLJsgzAlXWoKUjPU1qY-DQ829ek,9156
|
3
3
|
utilities/astor.py,sha256=xuDUkjq0-b6fhtwjhbnebzbqQZAjMSHR1IIS5uOodVg,777
|
4
4
|
utilities/asyncio.py,sha256=41oQUurWMvadFK5gFnaG21hMM0Vmfn2WS6OpC0R9mas,14757
|
@@ -46,7 +46,7 @@ utilities/pathlib.py,sha256=31WPMXdLIyXgYOMMl_HOI2wlo66MGSE-cgeelk-Lias,1410
|
|
46
46
|
utilities/period.py,sha256=ikHXsWtDLr553cfH6p9mMaiCnIAP69B7q84ckWV3HaA,10884
|
47
47
|
utilities/pickle.py,sha256=Bhvd7cZl-zQKQDFjUerqGuSKlHvnW1K2QXeU5UZibtg,657
|
48
48
|
utilities/platform.py,sha256=NU7ycTvAXAG-fdYmDXaM1m4EOml2cGiaYwaUzfzSqyU,1767
|
49
|
-
utilities/polars.py,sha256=
|
49
|
+
utilities/polars.py,sha256=pFUEkCzHh01M84fm4upFc4UKrUFMKz6WeWYvAlFLAPw,58009
|
50
50
|
utilities/polars_ols.py,sha256=efhXf0gjrHUpQrvS6a7g8yJQJWf_ATKtJnqqF2inCOU,5680
|
51
51
|
utilities/pqdm.py,sha256=foRytQybmOQ05pjt5LF7ANyzrIa--4ScDE3T2wd31a4,3118
|
52
52
|
utilities/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -68,6 +68,7 @@ utilities/slack_sdk.py,sha256=SeDNMh24IPiEBWoGMdgvrflUaFa9TGlTS03H9-NKaQw,4132
|
|
68
68
|
utilities/socket.py,sha256=K77vfREvzoVTrpYKo6MZakol0EYu2q1sWJnnZqL0So0,118
|
69
69
|
utilities/sqlalchemy.py,sha256=GWzp54TP3F2mGhxPTn0c56KxxDeN9VKLMagcRSELhf4,35453
|
70
70
|
utilities/sqlalchemy_polars.py,sha256=oGyMX5gSxuLI3N8mtz_-ml3UdWKcZuj6aFRW6ifI0Kc,15617
|
71
|
+
utilities/statsmodels.py,sha256=koyiBHvpMcSiBfh99wFUfSggLNx7cuAw3rwyfAhoKpQ,3410
|
71
72
|
utilities/streamlit.py,sha256=U9PJBaKP1IdSykKhPZhIzSPTZsmLsnwbEPZWzNhJPKk,2955
|
72
73
|
utilities/sys.py,sha256=h0Xr7Vj86wNalvwJVP1wj5Y0kD_VWm1vzuXZ_jw94mE,2743
|
73
74
|
utilities/tempfile.py,sha256=VqmZJAhTJ1OaVywFzk5eqROV8iJbW9XQ_QYAV0bpdRo,1384
|
@@ -86,7 +87,7 @@ utilities/warnings.py,sha256=yUgjnmkCRf6QhdyAXzl7u0qQFejhQG3PrjoSwxpbHrs,1819
|
|
86
87
|
utilities/whenever.py,sha256=TjoTAJ1R27-rKXiXzdE4GzPidmYqm0W58XydDXp-QZM,17786
|
87
88
|
utilities/zipfile.py,sha256=24lQc9ATcJxHXBPc_tBDiJk48pWyRrlxO2fIsFxU0A8,699
|
88
89
|
utilities/zoneinfo.py,sha256=-DQz5a0Ikw9jfSZtL0BEQkXOMC9yGn_xiJYNCLMiqEc,1989
|
89
|
-
dycw_utilities-0.109.
|
90
|
-
dycw_utilities-0.109.
|
91
|
-
dycw_utilities-0.109.
|
92
|
-
dycw_utilities-0.109.
|
90
|
+
dycw_utilities-0.109.22.dist-info/METADATA,sha256=Q17jtIGlAaCIIt5pD-cHWOB9Uvq8i9yRQtNP0q8NmLI,13005
|
91
|
+
dycw_utilities-0.109.22.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
92
|
+
dycw_utilities-0.109.22.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
|
93
|
+
dycw_utilities-0.109.22.dist-info/RECORD,,
|
utilities/__init__.py
CHANGED
utilities/polars.py
CHANGED
@@ -121,6 +121,7 @@ if TYPE_CHECKING:
|
|
121
121
|
)
|
122
122
|
|
123
123
|
from utilities.numpy import NDArrayB, NDArrayF
|
124
|
+
from utilities.statsmodels import ACFMissing
|
124
125
|
from utilities.types import (
|
125
126
|
Dataclass,
|
126
127
|
MaybeIterable,
|
@@ -139,6 +140,116 @@ DatetimeUSEastern = Datetime(time_zone="US/Eastern")
|
|
139
140
|
DatetimeUTC = Datetime(time_zone="UTC")
|
140
141
|
_FINITE_EWM_MIN_WEIGHT = 0.9999
|
141
142
|
|
143
|
+
##
|
144
|
+
|
145
|
+
|
146
|
+
def ac_halflife(
|
147
|
+
series: Series,
|
148
|
+
/,
|
149
|
+
*,
|
150
|
+
adjusted: bool = False,
|
151
|
+
fft: bool = True,
|
152
|
+
bartlett_confint: bool = True,
|
153
|
+
missing: ACFMissing = "none",
|
154
|
+
step: float = 0.01,
|
155
|
+
) -> float:
|
156
|
+
"""Compute the autocorrelation halflife."""
|
157
|
+
import utilities.statsmodels
|
158
|
+
|
159
|
+
array = series.to_numpy()
|
160
|
+
return utilities.statsmodels.ac_halflife(
|
161
|
+
array,
|
162
|
+
adjusted=adjusted,
|
163
|
+
fft=fft,
|
164
|
+
bartlett_confint=bartlett_confint,
|
165
|
+
missing=missing,
|
166
|
+
step=step,
|
167
|
+
)
|
168
|
+
|
169
|
+
|
170
|
+
##
|
171
|
+
|
172
|
+
|
173
|
+
def acf(
|
174
|
+
series: Series,
|
175
|
+
/,
|
176
|
+
*,
|
177
|
+
adjusted: bool = False,
|
178
|
+
nlags: int | None = None,
|
179
|
+
qstat: bool = False,
|
180
|
+
fft: bool = True,
|
181
|
+
alpha: float | None = None,
|
182
|
+
bartlett_confint: bool = True,
|
183
|
+
missing: ACFMissing = "none",
|
184
|
+
) -> DataFrame:
|
185
|
+
"""Compute the autocorrelations of a series."""
|
186
|
+
from numpy import ndarray
|
187
|
+
|
188
|
+
import utilities.statsmodels
|
189
|
+
|
190
|
+
array = series.to_numpy()
|
191
|
+
result = utilities.statsmodels.acf(
|
192
|
+
array,
|
193
|
+
adjusted=adjusted,
|
194
|
+
nlags=nlags,
|
195
|
+
qstat=qstat,
|
196
|
+
fft=fft,
|
197
|
+
alpha=alpha,
|
198
|
+
bartlett_confint=bartlett_confint,
|
199
|
+
missing=missing,
|
200
|
+
)
|
201
|
+
match result:
|
202
|
+
case ndarray() as acfs:
|
203
|
+
return _acf_process_acfs(acfs)
|
204
|
+
case ndarray() as acfs, ndarray() as confints:
|
205
|
+
df_acfs = _acf_process_acfs(acfs)
|
206
|
+
df_confints = _acf_process_confints(confints)
|
207
|
+
return df_acfs.join(df_confints, on=["lag"])
|
208
|
+
case ndarray() as acfs, ndarray() as qstats, ndarray() as pvalues:
|
209
|
+
df_acfs = _acf_process_acfs(acfs)
|
210
|
+
df_qstats_pvalues = _acf_process_qstats_pvalues(qstats, pvalues)
|
211
|
+
return df_acfs.join(df_qstats_pvalues, on=["lag"], how="left")
|
212
|
+
case (
|
213
|
+
ndarray() as acfs,
|
214
|
+
ndarray() as confints,
|
215
|
+
ndarray() as qstats,
|
216
|
+
ndarray() as pvalues,
|
217
|
+
):
|
218
|
+
df_acfs = _acf_process_acfs(acfs)
|
219
|
+
df_confints = _acf_process_confints(confints)
|
220
|
+
df_qstats_pvalues = _acf_process_qstats_pvalues(qstats, pvalues)
|
221
|
+
return join(df_acfs, df_confints, df_qstats_pvalues, on=["lag"], how="left")
|
222
|
+
case _ as never:
|
223
|
+
assert_never(never)
|
224
|
+
|
225
|
+
|
226
|
+
def _acf_process_acfs(acfs: NDArrayF, /) -> DataFrame:
|
227
|
+
return (
|
228
|
+
Series(name="autocorrelation", values=acfs, dtype=Float64)
|
229
|
+
.to_frame()
|
230
|
+
.with_row_index(name="lag")
|
231
|
+
)
|
232
|
+
|
233
|
+
|
234
|
+
def _acf_process_confints(confints: NDArrayF, /) -> DataFrame:
|
235
|
+
return DataFrame(
|
236
|
+
data=confints, schema={"lower": Float64, "upper": Float64}
|
237
|
+
).with_row_index(name="lag")
|
238
|
+
|
239
|
+
|
240
|
+
def _acf_process_qstats_pvalues(qstats: NDArrayF, pvalues: NDArrayF, /) -> DataFrame:
|
241
|
+
from numpy import hstack
|
242
|
+
|
243
|
+
data = hstack([qstats.reshape(-1, 1), pvalues.reshape(-1, 1)])
|
244
|
+
return DataFrame(
|
245
|
+
data=data, schema={"qstat": Float64, "pvalue": Float64}
|
246
|
+
).with_row_index(name="lag", offset=1)
|
247
|
+
|
248
|
+
|
249
|
+
##
|
250
|
+
|
251
|
+
|
252
|
+
# def acf_halflife(series: Series,/)
|
142
253
|
|
143
254
|
##
|
144
255
|
|
@@ -1840,6 +1951,7 @@ __all__ = [
|
|
1840
1951
|
"SetFirstRowAsColumnsError",
|
1841
1952
|
"StructFromDataClassError",
|
1842
1953
|
"YieldStructSeriesElementsError",
|
1954
|
+
"acf",
|
1843
1955
|
"adjust_frequencies",
|
1844
1956
|
"append_dataclass",
|
1845
1957
|
"are_frames_equal",
|
utilities/statsmodels.py
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from typing import TYPE_CHECKING, Any, Literal, cast, overload
|
4
|
+
|
5
|
+
import numpy as np
|
6
|
+
import statsmodels.tsa.stattools
|
7
|
+
from numpy import arange, argmax, interp, nan
|
8
|
+
|
9
|
+
from utilities.numpy import shift
|
10
|
+
|
11
|
+
if TYPE_CHECKING:
|
12
|
+
from utilities.numpy import NDArrayF
|
13
|
+
|
14
|
+
|
15
|
+
def ac_halflife(
|
16
|
+
array: NDArrayF,
|
17
|
+
/,
|
18
|
+
*,
|
19
|
+
adjusted: bool = False,
|
20
|
+
fft: bool = True,
|
21
|
+
bartlett_confint: bool = True,
|
22
|
+
missing: ACFMissing = "none",
|
23
|
+
step: float = 0.01,
|
24
|
+
) -> float:
|
25
|
+
"""Compute the autocorrelation halflife."""
|
26
|
+
(n,) = array.shape
|
27
|
+
acfs = acf(
|
28
|
+
array,
|
29
|
+
adjusted=adjusted,
|
30
|
+
nlags=n,
|
31
|
+
fft=fft,
|
32
|
+
bartlett_confint=bartlett_confint,
|
33
|
+
missing=missing,
|
34
|
+
)
|
35
|
+
lags = arange(0, n, step=step)
|
36
|
+
interp_acfs = interp(lags, arange(n), acfs)
|
37
|
+
is_half = (shift(interp_acfs) > 0.5) & (interp_acfs <= 0.5)
|
38
|
+
return lags[argmax(is_half)].item() if np.any(is_half) else nan
|
39
|
+
|
40
|
+
|
41
|
+
##
|
42
|
+
|
43
|
+
|
44
|
+
type ACFMissing = Literal["none", "raise", "conservative", "drop"]
|
45
|
+
|
46
|
+
|
47
|
+
@overload
|
48
|
+
def acf(
|
49
|
+
array: NDArrayF,
|
50
|
+
/,
|
51
|
+
*,
|
52
|
+
adjusted: bool = False,
|
53
|
+
nlags: int | None = None,
|
54
|
+
qstat: Literal[False] = False,
|
55
|
+
fft: bool = True,
|
56
|
+
alpha: None = None,
|
57
|
+
bartlett_confint: bool = True,
|
58
|
+
missing: ACFMissing = "none",
|
59
|
+
) -> NDArrayF: ...
|
60
|
+
@overload
|
61
|
+
def acf(
|
62
|
+
array: NDArrayF,
|
63
|
+
/,
|
64
|
+
*,
|
65
|
+
adjusted: bool = False,
|
66
|
+
nlags: int | None = None,
|
67
|
+
qstat: Literal[False] = False,
|
68
|
+
fft: bool = True,
|
69
|
+
alpha: float,
|
70
|
+
bartlett_confint: bool = True,
|
71
|
+
missing: ACFMissing = "none",
|
72
|
+
) -> tuple[NDArrayF, NDArrayF]: ...
|
73
|
+
@overload
|
74
|
+
def acf(
|
75
|
+
array: NDArrayF,
|
76
|
+
/,
|
77
|
+
*,
|
78
|
+
adjusted: bool = False,
|
79
|
+
nlags: int | None = None,
|
80
|
+
qstat: Literal[True],
|
81
|
+
fft: bool = True,
|
82
|
+
alpha: float,
|
83
|
+
bartlett_confint: bool = True,
|
84
|
+
missing: ACFMissing = "none",
|
85
|
+
) -> tuple[NDArrayF, NDArrayF, NDArrayF, NDArrayF]: ...
|
86
|
+
@overload
|
87
|
+
def acf(
|
88
|
+
array: NDArrayF,
|
89
|
+
/,
|
90
|
+
*,
|
91
|
+
adjusted: bool = False,
|
92
|
+
nlags: int | None = None,
|
93
|
+
qstat: Literal[True],
|
94
|
+
fft: bool = True,
|
95
|
+
alpha: None = None,
|
96
|
+
bartlett_confint: bool = True,
|
97
|
+
missing: ACFMissing = "none",
|
98
|
+
) -> tuple[NDArrayF, NDArrayF, NDArrayF]: ...
|
99
|
+
@overload
|
100
|
+
def acf(
|
101
|
+
array: NDArrayF,
|
102
|
+
/,
|
103
|
+
*,
|
104
|
+
adjusted: bool = False,
|
105
|
+
nlags: int | None = None,
|
106
|
+
qstat: bool = False,
|
107
|
+
fft: bool = True,
|
108
|
+
alpha: float | None = None,
|
109
|
+
bartlett_confint: bool = True,
|
110
|
+
missing: ACFMissing = "none",
|
111
|
+
) -> (
|
112
|
+
NDArrayF
|
113
|
+
| tuple[NDArrayF, NDArrayF]
|
114
|
+
| tuple[NDArrayF, NDArrayF, NDArrayF]
|
115
|
+
| tuple[NDArrayF, NDArrayF, NDArrayF, NDArrayF]
|
116
|
+
): ...
|
117
|
+
def acf(
|
118
|
+
array: NDArrayF,
|
119
|
+
/,
|
120
|
+
*,
|
121
|
+
adjusted: bool = False,
|
122
|
+
nlags: int | None = None,
|
123
|
+
qstat: bool = False,
|
124
|
+
fft: bool = True,
|
125
|
+
alpha: float | None = None,
|
126
|
+
bartlett_confint: bool = True,
|
127
|
+
missing: ACFMissing = "none",
|
128
|
+
) -> (
|
129
|
+
NDArrayF
|
130
|
+
| tuple[NDArrayF, NDArrayF]
|
131
|
+
| tuple[NDArrayF, NDArrayF, NDArrayF]
|
132
|
+
| tuple[NDArrayF, NDArrayF, NDArrayF, NDArrayF]
|
133
|
+
):
|
134
|
+
"""Typed version of `acf`."""
|
135
|
+
return cast(
|
136
|
+
"Any",
|
137
|
+
statsmodels.tsa.stattools.acf(
|
138
|
+
array,
|
139
|
+
adjusted=adjusted,
|
140
|
+
nlags=nlags,
|
141
|
+
qstat=qstat,
|
142
|
+
fft=fft,
|
143
|
+
alpha=alpha,
|
144
|
+
bartlett_confint=bartlett_confint,
|
145
|
+
missing=missing,
|
146
|
+
),
|
147
|
+
)
|
148
|
+
|
149
|
+
|
150
|
+
__all__ = ["ACFMissing", "ac_halflife", "acf"]
|
File without changes
|
File without changes
|