pyelw 0.9.0__tar.gz

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.
pyelw-0.9.0/LICENSE ADDED
@@ -0,0 +1,27 @@
1
+ Copyright (c) 2025 Jason R. Blevins
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+
7
+ 1. Redistributions of source code must retain the above copyright notice, this
8
+ list of conditions and the following disclaimer.
9
+
10
+ 2. Redistributions in binary form must reproduce the above copyright notice,
11
+ this list of conditions and the following disclaimer in the documentation
12
+ and/or other materials provided with the distribution.
13
+
14
+ 3. Neither the names of the copyright holders nor the names of any
15
+ contributors may be used to endorse or promote products derived from
16
+ this software without specific prior written permission.
17
+
18
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
pyelw-0.9.0/PKG-INFO ADDED
@@ -0,0 +1,402 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyelw
3
+ Version: 0.9.0
4
+ Summary: Exact Local Whittle Estimation for Long Memory Time Series
5
+ Author-email: "Jason R. Blevins" <blevins.141@osu.edu>
6
+ License: BSD-3-Clause
7
+ Project-URL: Homepage, https://github.com/jrblevin/pyelw
8
+ Project-URL: Repository, https://github.com/jrblevin/pyelw.git
9
+ Project-URL: Documentation, https://github.com/jrblevin/pyelw#readme
10
+ Project-URL: Bug Tracker, https://github.com/jrblevin/pyelw/issues
11
+ Keywords: fractional integration,long memory,exact local Whittle estimation,ARFIMA,econometrics,time-series
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: License :: OSI Approved :: BSD License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
18
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
19
+ Requires-Python: >=3.13
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: numpy
23
+ Provides-Extra: test
24
+ Requires-Dist: pytest~=8.4.1; extra == "test"
25
+ Requires-Dist: scipy~=1.16.1; extra == "test"
26
+ Requires-Dist: pandas~=2.3.1; extra == "test"
27
+ Requires-Dist: pandas-datareader~=0.10.0; extra == "test"
28
+ Provides-Extra: dev
29
+ Requires-Dist: pytest~=8.4.1; extra == "dev"
30
+ Requires-Dist: scipy~=1.16.1; extra == "dev"
31
+ Requires-Dist: pandas~=2.3.1; extra == "dev"
32
+ Requires-Dist: pandas-datareader~=0.10.0; extra == "dev"
33
+ Dynamic: license-file
34
+
35
+ # PyELW
36
+
37
+ This is a Python library for local Whittle and Exact Local Whittle estimation
38
+ of the memory parameter of fractionally integrated time series.
39
+
40
+ ## Installation
41
+
42
+ ```shell
43
+ pip install pyelw
44
+ ```
45
+
46
+ PyELW requires:
47
+
48
+ - Python (>= 3.13)
49
+ - NumPy (tested with 2.3.2)
50
+
51
+ You can check the latest sources with the command
52
+
53
+ ```shell
54
+ git clone https://github.com/jrblevin/pyelw.git
55
+ ```
56
+
57
+ ### Quick Start Examples
58
+
59
+ ```python
60
+ from pyelw import LW, ELW, TwoStepELW
61
+
62
+ series = load_data() # Replace with your data loading code
63
+ n = len(series) # Length of time series
64
+ m = n**0.65 # Number of frequencies to use
65
+
66
+ # Local Whittle (Robinson, 1995)
67
+ lw = LW()
68
+ result = lw.estimate(series, m=m)
69
+ print(f"d_LW = {result['d_hat']}")
70
+
71
+ # Local Whittle with Hurvich-Chen taper
72
+ hc = LW(taper='hc')
73
+ result = hc.estimate(series, m=m)
74
+ print(f"d_HC = {result['d_hat']}")
75
+
76
+ # Exact local Whittle (Shimotsu and Phillips, 2005)
77
+ elw = ELW()
78
+ result = elw.estimate(series, m=m)
79
+ print(f"d_ELW = {result['d_hat']}")
80
+
81
+ # Two step ELW (Shimotsu, 2010)
82
+ elw2s = TwoStepELW()
83
+ result = elw2s.estimate(series, m=m, detrend_order=1)
84
+ print(f"d_2ELW = {result['d_hat']}")
85
+ ```
86
+
87
+ ## Citing the Package and Methods
88
+
89
+ The recommended practice is to cite both the specific method used and the PyELW
90
+ package. For example:
91
+
92
+ > We use the exact local Whittle estimator of Shimotsu and Phillips (2005)
93
+ > implemented in the PyELW package (Blevins, 2025).
94
+
95
+ See the references section below for full citations for each of the methods and
96
+ the PyELW package. Here is a BibTeX entry for the PyELW paper:
97
+
98
+ ```bibtex
99
+ @TechReport{pyelw,
100
+ title = {{PyELW}: Exact Local {Whittle} Estimation for Long Memory Time Series in Python},
101
+ author = {Jason R. Blevins},
102
+ institution = {The Ohio State University},
103
+ year = 2025,
104
+ type = {Working Paper}
105
+ }
106
+ ```
107
+
108
+ ## Methods Implemented
109
+
110
+ - `LW` - Untapered and tapered local Whittle estimators
111
+ - Untapered local Whittle estimator of Robinson (1995)
112
+ (`taper='none'`, default)
113
+ - Tapered local Whittle estimators of Velasco (1999)
114
+ (`taper='kolmogorov'`, `taper='cosine'`, or `taper='bartlett'`)
115
+ - Complex tapered local Whittle estimator of Hurvich and Chen (2000)
116
+ (`taper='hc'`)
117
+ - `ELW` - Exact local Whittle estimator of Shimotsu and Phillips (2005).
118
+ - `TwoStepELW` - Two-step exact local Whittle estimator of Shimotsu (2010).
119
+
120
+ Each of these classes provides an `estimate()` method which requires
121
+ the data (a NumPy ndarray) and the number of frequencies to use.
122
+ See the PyELW paper or the examples below for details.
123
+
124
+ ### LW taper Options
125
+
126
+ By default the `LW` estimator implements the standard (untapered) estimator of
127
+ Robinson (1995). However, it also supports several taper options.
128
+
129
+ You can specify the taper at initialization:
130
+
131
+ ```python
132
+ from pyelw import LW
133
+ import numpy as np
134
+
135
+ # Sample data
136
+ x = np.random.randn(500)
137
+
138
+ # Standard untapered local Whittle (Robinson, 1995) - default
139
+ lw = LW()
140
+ result = lw.estimate(x)
141
+
142
+ # Kolmogorov taper (Velasco, 1999)
143
+ lw_kol = LW(taper='kolmogorov')
144
+ result = lw_kol.estimate(x)
145
+
146
+ # Cosine bell taper (Velasco, 1999)
147
+ lw_cos = LW(taper='cosine')
148
+ result = lw_cos.estimate(x)
149
+
150
+ # Triangular Bartlett window taper (Velasco, 1999)
151
+ lw_bart = LW(taper='bartlett')
152
+ result = lw_bart.estimate(x)
153
+
154
+ # Hurvich-Chen complex taper (Hurvich and Chen, 2000)
155
+ # Note: diff parameter specifies number of times to difference the data
156
+ lw_hc = LW(taper='hc')
157
+ result = lw_hc.estimate(x, diff=1)
158
+ ```
159
+
160
+ You can also override the taper on a per-call basis:
161
+
162
+ ```python
163
+ # LW instance with default taper
164
+ lw = LW(taper='hc')
165
+
166
+ # Use the default taper
167
+ result = lw.estimate(x)
168
+
169
+ # Override with a different taper for this call
170
+ result = lw.estimate(x, taper='none')
171
+ ```
172
+
173
+ ### Helper Functions
174
+
175
+ The library also includes the following helper functions which may be useful:
176
+
177
+ - `fracdiff` - Fast O(n log n) fractional differencing, following Jensen and Nielsen (2014).
178
+ - `arfima` - Simulation of ARFIMA(1,d,0) processes, including ARFIMA(0,d,0) as a special case.
179
+
180
+ #### Fractional Differencing
181
+
182
+ ```python
183
+ from pyelw.fracdiff import fracdiff
184
+ import numpy as np
185
+
186
+ # Generate sample data
187
+ x = np.random.randn(100)
188
+
189
+ # Apply fractional differencing with d=0.3
190
+ dx = fracdiff(x, 0.3)
191
+ ```
192
+
193
+ #### ARFIMA Simulation
194
+
195
+ ```python
196
+ from pyelw.simulate import arfima
197
+
198
+ # Simulate ARFIMA(1,0.4,0) with phi=0.5
199
+ data = arfima(n=1000, d=0.4, phi=0.5, sigma=1.0, seed=123)
200
+ ```
201
+
202
+ ## Examples
203
+
204
+ ### Example 1: Nile River Level Data
205
+
206
+ The following example uses Pandas to load a CSV dataset containing
207
+ observations on the level of the Nile river and estimates d via LW and ELW.
208
+
209
+ ```python
210
+ import pandas as pd
211
+ from pyelw import LW, ELW
212
+
213
+ # Load time series from 'nile' column of data/nile.csv
214
+ df = pd.read_csv('data/nile.csv')
215
+ nile = pd.to_numeric(df['nile']).values
216
+ print(f"Loaded {len(nile)} observations")
217
+
218
+ # Estimate d using local Whittle estimator
219
+ # Use default number of frequencies m
220
+ lw = LW()
221
+ result = lw.estimate(nile)
222
+ print(f"LW estimate of d: {result['d_hat']}")
223
+
224
+ # Estimate d using exact local Whittle estimator
225
+ # Use default number of frequencies m
226
+ elw = ELW()
227
+ result = elw.estimate(nile)
228
+
229
+ # Print results
230
+ print(f"ELW estimate of d: {result['d_hat']}")
231
+ ```
232
+
233
+ Output:
234
+
235
+ ```
236
+ Loaded 663 observations
237
+ LW estimate of d: 0.40904431255796164
238
+ ELW estimate of d: 0.8859171843580865
239
+ ```
240
+
241
+ ### Example 2: ARFIMA(0,d,0) Process
242
+
243
+ Here we simulate an ARFIMA(0, 0.3, 0) process and use the simulated data to
244
+ estimate d via ELW.
245
+
246
+ ```python
247
+ from pyelw import ELW
248
+ from pyelw.simulate import arfima
249
+
250
+ # Set simulation parameters
251
+ n = 5000 # Sample size
252
+ d_true = 0.3 # True memory parameter
253
+ sigma = 1.0 # Innovation standard deviation
254
+ seed = 42 # Random seed
255
+
256
+ # Simulate ARFIMA(0,d,0) process
257
+ print(f"Simulating ARFIMA(0,{d_true},0) with n={n} observations...")
258
+ x = arfima(n, d_true, sigma=sigma, seed=seed)
259
+
260
+ # Initialize ELW estimator
261
+ elw = ELW()
262
+
263
+ # Estimate the memory parameter
264
+ # Use m = n^0.65 frequencies
265
+ m = int(n**0.65)
266
+ result = elw.estimate(x, m=m)
267
+
268
+ # Display results
269
+ print(f"True d: {d_true}")
270
+ print(f"Estimated d: {result['d_hat']:.4f}")
271
+ print(f"Standard error: {result['se']:.4f}")
272
+ print(f"Estimation error: {abs(result['d_hat'] - d_true):.4f}")
273
+
274
+ # 95% confidence interval
275
+ ci_lower = result['d_hat'] - 1.96 * result['se']
276
+ ci_upper = result['d_hat'] + 1.96 * result['se']
277
+ print(f"95% CI: [{ci_lower:.4f}, {ci_upper:.4f}]")
278
+ ```
279
+
280
+ Output:
281
+ ```
282
+ Simulating ARFIMA(0,0.3,0) with n=5000 observations...
283
+ True d: 0.3
284
+ Estimated d: 0.3315
285
+ Standard error: 0.0318
286
+ Estimation error: 0.0315
287
+ 95% CI: [0.2692, 0.3939]
288
+ ```
289
+
290
+ ### Example 3: Real GDP Data from FRED
291
+
292
+ Here we download real GDP data from FRED using `pandas_datareader` and
293
+ estimate d via Two Step ELW:
294
+
295
+ ```python
296
+ import numpy as np
297
+ import pandas_datareader as pdr
298
+ from pyelw import TwoStepELW
299
+
300
+ # Download real GDP from FRED
301
+ print("Downloading real GDP data from FRED...")
302
+ series = pdr.get_data_fred('GDPC1', start='1950-01-01', end='2024-12-31')
303
+ gdp_data = series.dropna()
304
+ gdp = gdp_data.values.flatten()
305
+ print(f"Downloaded {len(gdp)} observations")
306
+
307
+ # Take natural logarithm for growth rate interpretation
308
+ log_gdp = np.log(gdp)
309
+ print("Using log(real GDP) for analysis")
310
+
311
+ # Initialize Two-Step ELW estimator
312
+ estimator = TwoStepELW()
313
+
314
+ # Choose bandwidth/number of frequencies
315
+ n = len(log_gdp)
316
+ m = int(n**0.65)
317
+
318
+ # Estimate d via Two-Step ELW
319
+ print("\nEstimating long memory parameter...")
320
+ print(f"Sample size: {n}")
321
+ print(f"Number of frequencies: {m}")
322
+ result = estimator.estimate(log_gdp, m=m, detrend_order=1, verbose=True)
323
+
324
+ # Display results
325
+ print("\nTwo-Step ELW Results:")
326
+ print(f"Estimated d: {result['d_hat']:.4f}")
327
+ print(f"Standard error: {result['se']:.4f}")
328
+ ci_lower = result['d_hat'] - 1.96 * result['se']
329
+ ci_upper = result['d_hat'] + 1.96 * result['se']
330
+ print(f"95% CI: [{ci_lower:.4f}, {ci_upper:.4f}]")
331
+ ```
332
+
333
+ Output:
334
+
335
+ ```
336
+ Downloading real GDP data from FRED...
337
+ Downloaded 300 observations
338
+ Using log(real GDP) for analysis
339
+
340
+ Estimating long memory parameter...
341
+ Sample size: 300
342
+ Number of frequencies: 40
343
+ Detrending with polynomial order 1
344
+ Using 40 frequencies for both stages
345
+ Stage 1: hc tapered LW estimation
346
+ Stage 1 estimate: d = 1.0427
347
+ Stage 2: Exact local whittle estimation
348
+ Starting from Stage 1: d = 1.042677
349
+ Final estimate: d = 1.0096
350
+
351
+ Two-Step ELW Results:
352
+ Estimated d: 1.0096
353
+ Standard error: 0.0791
354
+ 95% CI: [0.8547, 1.1646]
355
+ ```
356
+
357
+ ## Summary of Included Replications
358
+
359
+ | Filename | Paper | Reference | Estimators | Description |
360
+ |-------------------------------------|------------------------------|--------------|-------------------------|--------------------------------------------------------|
361
+ | `hurvich_chen_table_1.py` | Hurvich and Chen (2000) | Table I | `LW('hc')` | Monte Carlo with simulated ARFIMA(1,d,0) data. |
362
+ | `hurvich_chen_table_1.R` | Hurvich and Chen (2000) | Table I | `LW('hc')` | R version of above, demonstrating corrected code. |
363
+ | `hurvich_chen_table_3.py` | Hurvich and Chen (2000) | Table III | `LW('hc')` | Application to IMF International Financial Statistics. |
364
+ | `shimotsu_phillips_2005_table_1.py` | Shimotsu and Phillips (2005) | Table 1 | `LW`, `ELW` | Monte Carlo with LW and ELW with ARFIMA(1,d,0) data |
365
+ | `shimotsu_phillips_2005_table_2.py` | Shimotsu and Phillips (2005) | Table 2 | `LW('hc', 'bartlett')` | Monte Carlo with tapered LW estimators |
366
+ | `shimotsu_2010_table_2.py` | Shimotsu (2010) | Table 2 | `TwoStepELW` | ELW Monte Carlo with ARFIMA(1,d,0) data. |
367
+ | `shimotsu_2010_table_8.py` | Shimotsu (2010) | Table 8 | `TwoStepELW` | Application to extended Nelson and Plosser data. |
368
+ | `baum_hurn_lindsay.py` | Baum, Hurn, Lindsay (2020) | pp. 576-579 | `LW`, `ELW` | Application to Nile river and sea level data. |
369
+
370
+ ## Unit Tests
371
+
372
+ A `pytest` comprehensive unit test suite with over 2,400 parametric tests is
373
+ included. To run the tests, you'll need to first install the additional test
374
+ dependencies, then run `pytest`:
375
+
376
+ ```shell
377
+ pip install -r requirements-test.txt
378
+ pytest
379
+ ```
380
+
381
+ ## References
382
+
383
+ * Blevins, J.R. (2025).
384
+ [PyELW: Exact Local Whittle Estimation for Long Memory Time Series in Python](https://jblevins.org/research/pyelw).
385
+ Working Paper, The Ohio State University.
386
+
387
+ * Hurvich, C. M., and W. W. Chen (2000). An Efficient Taper for Potentially
388
+ Overdifferenced Long-Memory Time Series. _Journal of Time Series Analysis_
389
+ 21, 155--180.
390
+
391
+ * Robinson, P. M. (1995). Gaussian Semiparametric Estimation of Long
392
+ Range Dependence. _Annals of Statistics_ 23, 1630--1661.
393
+
394
+ * Shimotsu, K. (2010). Exact Local Whittle Estimation of Fractional
395
+ Integration with Unknown Mean and Time Trend. _Econometric Theory_ 26,
396
+ 501--540.
397
+
398
+ * Shimotsu, K. and Phillips, P.C.B. (2005). Exact Local Whittle Estimation
399
+ of Fractional Integration. _Annals of Statistics_ 33, 1890--1933.
400
+
401
+ * Velasco, C. (1999). Gaussian Semiparametric Estimation for Non-Stationary
402
+ Time Series. _Journal of Time Series Analysis_ 20, 87--126.