Coverage for /home/martinb/.local/share/virtualenvs/camcops/lib/python3.6/site-packages/statsmodels/tsa/arima_process.py : 27%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""ARMA process and estimation with scipy.signal.lfilter
3Notes
4-----
5* written without textbook, works but not sure about everything
6 briefly checked and it looks to be standard least squares, see below
8* theoretical autocorrelation function of general ARMA
9 Done, relatively easy to guess solution, time consuming to get
10 theoretical test cases, example file contains explicit formulas for
11 acovf of MA(1), MA(2) and ARMA(1,1)
13Properties:
14Judge, ... (1985): The Theory and Practise of Econometrics
16Author: josefpktd
17License: BSD
18"""
19from statsmodels.compat.pandas import deprecate_kwarg
21import numpy as np
22from scipy import signal, optimize, linalg
24from statsmodels.compat.pandas import Appender
25from statsmodels.tools.docstring import remove_parameters, Docstring
26from statsmodels.tools.validation import array_like
28__all__ = ['arma_acf', 'arma_acovf', 'arma_generate_sample',
29 'arma_impulse_response', 'arma2ar', 'arma2ma', 'deconvolve',
30 'lpol2index', 'index2lpol']
33# Remove after 0.11
34@deprecate_kwarg('sigma', 'scale')
35def arma_generate_sample(ar, ma, nsample, scale=1, distrvs=None,
36 axis=0, burnin=0):
37 """
38 Simulate data from an ARMA.
40 Parameters
41 ----------
42 ar : array_like
43 The coefficient for autoregressive lag polynomial, including zero lag.
44 ma : array_like
45 The coefficient for moving-average lag polynomial, including zero lag.
46 nsample : int or tuple of ints
47 If nsample is an integer, then this creates a 1d timeseries of
48 length size. If nsample is a tuple, creates a len(nsample)
49 dimensional time series where time is indexed along the input
50 variable ``axis``. All series are unless ``distrvs`` generates
51 dependent data.
52 scale : float
53 The standard deviation of noise.
54 distrvs : function, random number generator
55 A function that generates the random numbers, and takes sample size
56 as argument. The default is np.random.randn.
57 axis : int
58 See nsample for details.
59 burnin : int
60 Number of observation at the beginning of the sample to drop.
61 Used to reduce dependence on initial values.
63 Returns
64 -------
65 ndarray
66 Random sample(s) from an ARMA process.
68 Notes
69 -----
70 As mentioned above, both the AR and MA components should include the
71 coefficient on the zero-lag. This is typically 1. Further, due to the
72 conventions used in signal processing used in signal.lfilter vs.
73 conventions in statistics for ARMA processes, the AR parameters should
74 have the opposite sign of what you might expect. See the examples below.
76 Examples
77 --------
78 >>> import numpy as np
79 >>> np.random.seed(12345)
80 >>> arparams = np.array([.75, -.25])
81 >>> maparams = np.array([.65, .35])
82 >>> ar = np.r_[1, -arparams] # add zero-lag and negate
83 >>> ma = np.r_[1, maparams] # add zero-lag
84 >>> y = sm.tsa.arma_generate_sample(ar, ma, 250)
85 >>> model = sm.tsa.ARMA(y, (2, 2)).fit(trend='nc', disp=0)
86 >>> model.params
87 array([ 0.79044189, -0.23140636, 0.70072904, 0.40608028])
88 """
89 distrvs = np.random.normal if distrvs is None else distrvs
90 if np.ndim(nsample) == 0:
91 nsample = [nsample]
92 if burnin:
93 # handle burin time for nd arrays
94 # maybe there is a better trick in scipy.fft code
95 newsize = list(nsample)
96 newsize[axis] += burnin
97 newsize = tuple(newsize)
98 fslice = [slice(None)] * len(newsize)
99 fslice[axis] = slice(burnin, None, None)
100 fslice = tuple(fslice)
101 else:
102 newsize = tuple(nsample)
103 fslice = tuple([slice(None)] * np.ndim(newsize))
104 eta = scale * distrvs(size=newsize)
105 return signal.lfilter(ma, ar, eta, axis=axis)[fslice]
108def arma_acovf(ar, ma, nobs=10, sigma2=1, dtype=None):
109 """
110 Theoretical autocovariance function of ARMA process.
112 Parameters
113 ----------
114 ar : array_like, 1d
115 The coefficients for autoregressive lag polynomial, including zero lag.
116 ma : array_like, 1d
117 The coefficients for moving-average lag polynomial, including zero lag.
118 nobs : int
119 The number of terms (lags plus zero lag) to include in returned acovf.
120 sigma2 : float
121 Variance of the innovation term.
123 Returns
124 -------
125 ndarray
126 The autocovariance of ARMA process given by ar, ma.
128 See Also
129 --------
130 arma_acf : Autocorrelation function for ARMA processes.
131 acovf : Sample autocovariance estimation.
133 References
134 ----------
135 .. [*] Brockwell, Peter J., and Richard A. Davis. 2009. Time Series:
136 Theory and Methods. 2nd ed. 1991. New York, NY: Springer.
137 """
138 if dtype is None:
139 dtype = np.common_type(np.array(ar), np.array(ma), np.array(sigma2))
141 p = len(ar) - 1
142 q = len(ma) - 1
143 m = max(p, q) + 1
145 if sigma2.real < 0:
146 raise ValueError('Must have positive innovation variance.')
148 # Short-circuit for trivial corner-case
149 if p == q == 0:
150 out = np.zeros(nobs, dtype=dtype)
151 out[0] = sigma2
152 return out
154 # Get the moving average representation coefficients that we need
155 ma_coeffs = arma2ma(ar, ma, lags=m)
157 # Solve for the first m autocovariances via the linear system
158 # described by (BD, eq. 3.3.8)
159 A = np.zeros((m, m), dtype=dtype)
160 b = np.zeros((m, 1), dtype=dtype)
161 # We need a zero-right-padded version of ar params
162 tmp_ar = np.zeros(m, dtype=dtype)
163 tmp_ar[:p + 1] = ar
164 for k in range(m):
165 A[k, :(k + 1)] = tmp_ar[:(k + 1)][::-1]
166 A[k, 1:m - k] += tmp_ar[(k + 1):m]
167 b[k] = sigma2 * np.dot(ma[k:q + 1], ma_coeffs[:max((q + 1 - k), 0)])
168 acovf = np.zeros(max(nobs, m), dtype=dtype)
169 acovf[:m] = np.linalg.solve(A, b)[:, 0]
171 # Iteratively apply (BD, eq. 3.3.9) to solve for remaining autocovariances
172 if nobs > m:
173 zi = signal.lfiltic([1], ar, acovf[:m:][::-1])
174 acovf[m:] = signal.lfilter([1], ar, np.zeros(nobs - m, dtype=dtype),
175 zi=zi)[0]
177 return acovf[:nobs]
180# Remove after 0.11
181@deprecate_kwarg('nobs', 'lags')
182def arma_acf(ar, ma, lags=10):
183 """
184 Theoretical autocorrelation function of an ARMA process.
186 Parameters
187 ----------
188 ar : array_like
189 Coefficients for autoregressive lag polynomial, including zero lag.
190 ma : array_like
191 Coefficients for moving-average lag polynomial, including zero lag.
192 lags : int
193 The number of terms (lags plus zero lag) to include in returned acf.
195 Returns
196 -------
197 ndarray
198 The autocorrelations of ARMA process given by ar and ma.
200 See Also
201 --------
202 arma_acovf : Autocovariances from ARMA processes.
203 acf : Sample autocorrelation function estimation.
204 acovf : Sample autocovariance function estimation.
205 """
206 acovf = arma_acovf(ar, ma, lags)
207 return acovf / acovf[0]
210# Remove after 0.11
211@deprecate_kwarg('nobs', 'lags')
212def arma_pacf(ar, ma, lags=10):
213 """
214 Theoretical partial autocorrelation function of an ARMA process.
216 Parameters
217 ----------
218 ar : array_like, 1d
219 The coefficients for autoregressive lag polynomial, including zero lag.
220 ma : array_like, 1d
221 The coefficients for moving-average lag polynomial, including zero lag.
222 lags : int
223 The number of terms (lags plus zero lag) to include in returned pacf.
225 Returns
226 -------
227 ndarrray
228 The partial autocorrelation of ARMA process given by ar and ma.
230 Notes
231 -----
232 Solves yule-walker equation for each lag order up to nobs lags.
234 not tested/checked yet
235 """
236 # TODO: Should use rank 1 inverse update
237 apacf = np.zeros(lags)
238 acov = arma_acf(ar, ma, lags=lags + 1)
240 apacf[0] = 1.
241 for k in range(2, lags + 1):
242 r = acov[:k]
243 apacf[k - 1] = linalg.solve(linalg.toeplitz(r[:-1]), r[1:])[-1]
244 return apacf
247def arma_periodogram(ar, ma, worN=None, whole=0):
248 """
249 Periodogram for ARMA process given by lag-polynomials ar and ma.
251 Parameters
252 ----------
253 ar : array_like
254 The autoregressive lag-polynomial with leading 1 and lhs sign.
255 ma : array_like
256 The moving average lag-polynomial with leading 1.
257 worN : {None, int}, optional
258 An option for scipy.signal.freqz (read "w or N").
259 If None, then compute at 512 frequencies around the unit circle.
260 If a single integer, the compute at that many frequencies.
261 Otherwise, compute the response at frequencies given in worN.
262 whole : {0,1}, optional
263 An options for scipy.signal.freqz/
264 Normally, frequencies are computed from 0 to pi (upper-half of
265 unit-circle. If whole is non-zero compute frequencies from 0 to 2*pi.
267 Returns
268 -------
269 w : ndarray
270 The frequencies.
271 sd : ndarray
272 The periodogram, also known as the spectral density.
274 Notes
275 -----
276 Normalization ?
278 This uses signal.freqz, which does not use fft. There is a fft version
279 somewhere.
280 """
281 w, h = signal.freqz(ma, ar, worN=worN, whole=whole)
282 sd = np.abs(h) ** 2 / np.sqrt(2 * np.pi)
283 if np.any(np.isnan(h)):
284 # this happens with unit root or seasonal unit root'
285 import warnings
286 warnings.warn('Warning: nan in frequency response h, maybe a unit '
287 'root', RuntimeWarning)
288 return w, sd
291# Remove after 0.11
292@deprecate_kwarg('nobs', 'leads')
293def arma_impulse_response(ar, ma, leads=100):
294 """
295 Compute the impulse response function (MA representation) for ARMA process.
297 Parameters
298 ----------
299 ar : array_like, 1d
300 The auto regressive lag polynomial.
301 ma : array_like, 1d
302 The moving average lag polynomial.
303 leads : int
304 The number of observations to calculate.
306 Returns
307 -------
308 ndarray
309 The impulse response function with nobs elements.
311 Notes
312 -----
313 This is the same as finding the MA representation of an ARMA(p,q).
314 By reversing the role of ar and ma in the function arguments, the
315 returned result is the AR representation of an ARMA(p,q), i.e
317 ma_representation = arma_impulse_response(ar, ma, leads=100)
318 ar_representation = arma_impulse_response(ma, ar, leads=100)
320 Fully tested against matlab
322 Examples
323 --------
324 AR(1)
326 >>> arma_impulse_response([1.0, -0.8], [1.], leads=10)
327 array([ 1. , 0.8 , 0.64 , 0.512 , 0.4096 ,
328 0.32768 , 0.262144 , 0.2097152 , 0.16777216, 0.13421773])
330 this is the same as
332 >>> 0.8**np.arange(10)
333 array([ 1. , 0.8 , 0.64 , 0.512 , 0.4096 ,
334 0.32768 , 0.262144 , 0.2097152 , 0.16777216, 0.13421773])
336 MA(2)
338 >>> arma_impulse_response([1.0], [1., 0.5, 0.2], leads=10)
339 array([ 1. , 0.5, 0.2, 0. , 0. , 0. , 0. , 0. , 0. , 0. ])
341 ARMA(1,2)
343 >>> arma_impulse_response([1.0, -0.8], [1., 0.5, 0.2], leads=10)
344 array([ 1. , 1.3 , 1.24 , 0.992 , 0.7936 ,
345 0.63488 , 0.507904 , 0.4063232 , 0.32505856, 0.26004685])
346 """
347 impulse = np.zeros(leads)
348 impulse[0] = 1.
349 return signal.lfilter(ma, ar, impulse)
352# Remove after 0.11
353@deprecate_kwarg('nobs', 'lags')
354def arma2ma(ar, ma, lags=100):
355 """
356 A finite-lag approximate MA representation of an ARMA process.
358 Parameters
359 ----------
360 ar : ndarray
361 The auto regressive lag polynomial.
362 ma : ndarray
363 The moving average lag polynomial.
364 lags : int
365 The number of coefficients to calculate.
367 Returns
368 -------
369 ndarray
370 The coefficients of AR lag polynomial with nobs elements.
372 Notes
373 -----
374 Equivalent to ``arma_impulse_response(ma, ar, leads=100)``
375 """
376 return arma_impulse_response(ar, ma, leads=lags)
379# Remove after 0.11
380@deprecate_kwarg('nobs', 'lags')
381def arma2ar(ar, ma, lags=100):
382 """
383 A finite-lag AR approximation of an ARMA process.
385 Parameters
386 ----------
387 ar : array_like
388 The auto regressive lag polynomial.
389 ma : array_like
390 The moving average lag polynomial.
391 lags : int
392 The number of coefficients to calculate.
394 Returns
395 -------
396 ndarray
397 The coefficients of AR lag polynomial with nobs elements.
399 Notes
400 -----
401 Equivalent to ``arma_impulse_response(ma, ar, leads=100)``
402 """
403 return arma_impulse_response(ma, ar, leads=lags)
406# moved from sandbox.tsa.try_fi
407def ar2arma(ar_des, p, q, n=20, mse='ar', start=None):
408 """
409 Find arma approximation to ar process.
411 This finds the ARMA(p,q) coefficients that minimize the integrated
412 squared difference between the impulse_response functions (MA
413 representation) of the AR and the ARMA process. This does not check
414 whether the MA lag polynomial of the ARMA process is invertible, neither
415 does it check the roots of the AR lag polynomial.
417 Parameters
418 ----------
419 ar_des : array_like
420 The coefficients of original AR lag polynomial, including lag zero.
421 p : int
422 The length of desired AR lag polynomials.
423 q : int
424 The length of desired MA lag polynomials.
425 n : int
426 The number of terms of the impulse_response function to include in the
427 objective function for the approximation.
428 mse : str, 'ar'
429 Not used.
430 start : ndarray
431 Initial values to use when finding the approximation.
433 Returns
434 -------
435 ar_app : ndarray
436 The coefficients of the AR lag polynomials of the approximation.
437 ma_app : ndarray
438 The coefficients of the MA lag polynomials of the approximation.
439 res : tuple
440 The result of optimize.leastsq.
442 Notes
443 -----
444 Extension is possible if we want to match autocovariance instead
445 of impulse response function.
446 """
448 # TODO: convert MA lag polynomial, ma_app, to be invertible, by mirroring
449 # TODO: roots outside the unit interval to ones that are inside. How to do
450 # TODO: this?
452 # p,q = pq
453 def msear_err(arma, ar_des):
454 ar, ma = np.r_[1, arma[:p - 1]], np.r_[1, arma[p - 1:]]
455 ar_approx = arma_impulse_response(ma, ar, n)
456 return (ar_des - ar_approx) # ((ar - ar_approx)**2).sum()
458 if start is None:
459 arma0 = np.r_[-0.9 * np.ones(p - 1), np.zeros(q - 1)]
460 else:
461 arma0 = start
462 res = optimize.leastsq(msear_err, arma0, ar_des, maxfev=5000)
463 arma_app = np.atleast_1d(res[0])
464 ar_app = np.r_[1, arma_app[:p - 1]],
465 ma_app = np.r_[1, arma_app[p - 1:]]
466 return ar_app, ma_app, res
469_arma_docs = {'ar': arma2ar.__doc__,
470 'ma': arma2ma.__doc__}
473def lpol2index(ar):
474 """
475 Remove zeros from lag polynomial
477 Parameters
478 ----------
479 ar : array_like
480 coefficients of lag polynomial
482 Returns
483 -------
484 coeffs : ndarray
485 non-zero coefficients of lag polynomial
486 index : ndarray
487 index (lags) of lag polynomial with non-zero elements
488 """
489 ar = array_like(ar, 'ar')
490 index = np.nonzero(ar)[0]
491 coeffs = ar[index]
492 return coeffs, index
495def index2lpol(coeffs, index):
496 """
497 Expand coefficients to lag poly
499 Parameters
500 ----------
501 coeffs : ndarray
502 non-zero coefficients of lag polynomial
503 index : ndarray
504 index (lags) of lag polynomial with non-zero elements
506 Returns
507 -------
508 ar : array_like
509 coefficients of lag polynomial
510 """
511 n = max(index)
512 ar = np.zeros(n + 1)
513 ar[index] = coeffs
514 return ar
517def lpol_fima(d, n=20):
518 """MA representation of fractional integration
520 .. math:: (1-L)^{-d} for |d|<0.5 or |d|<1 (?)
522 Parameters
523 ----------
524 d : float
525 fractional power
526 n : int
527 number of terms to calculate, including lag zero
529 Returns
530 -------
531 ma : ndarray
532 coefficients of lag polynomial
533 """
534 # hide import inside function until we use this heavily
535 from scipy.special import gammaln
536 j = np.arange(n)
537 return np.exp(gammaln(d + j) - gammaln(j + 1) - gammaln(d))
540# moved from sandbox.tsa.try_fi
541def lpol_fiar(d, n=20):
542 """AR representation of fractional integration
544 .. math:: (1-L)^{d} for |d|<0.5 or |d|<1 (?)
546 Parameters
547 ----------
548 d : float
549 fractional power
550 n : int
551 number of terms to calculate, including lag zero
553 Returns
554 -------
555 ar : ndarray
556 coefficients of lag polynomial
558 Notes:
559 first coefficient is 1, negative signs except for first term,
560 ar(L)*x_t
561 """
562 # hide import inside function until we use this heavily
563 from scipy.special import gammaln
564 j = np.arange(n)
565 ar = - np.exp(gammaln(-d + j) - gammaln(j + 1) - gammaln(-d))
566 ar[0] = 1
567 return ar
570# moved from sandbox.tsa.try_fi
571def lpol_sdiff(s):
572 """return coefficients for seasonal difference (1-L^s)
574 just a trivial convenience function
576 Parameters
577 ----------
578 s : int
579 number of periods in season
581 Returns
582 -------
583 sdiff : list, length s+1
584 """
585 return [1] + [0] * (s - 1) + [-1]
588def deconvolve(num, den, n=None):
589 """Deconvolves divisor out of signal, division of polynomials for n terms
591 calculates den^{-1} * num
593 Parameters
594 ----------
595 num : array_like
596 signal or lag polynomial
597 denom : array_like
598 coefficients of lag polynomial (linear filter)
599 n : None or int
600 number of terms of quotient
602 Returns
603 -------
604 quot : ndarray
605 quotient or filtered series
606 rem : ndarray
607 remainder
609 Notes
610 -----
611 If num is a time series, then this applies the linear filter den^{-1}.
612 If both num and den are both lag polynomials, then this calculates the
613 quotient polynomial for n terms and also returns the remainder.
615 This is copied from scipy.signal.signaltools and added n as optional
616 parameter.
617 """
618 num = np.atleast_1d(num)
619 den = np.atleast_1d(den)
620 N = len(num)
621 D = len(den)
622 if D > N and n is None:
623 quot = []
624 rem = num
625 else:
626 if n is None:
627 n = N - D + 1
628 input = np.zeros(n, float)
629 input[0] = 1
630 quot = signal.lfilter(num, den, input)
631 num_approx = signal.convolve(den, quot, mode='full')
632 if len(num) < len(num_approx): # 1d only ?
633 num = np.concatenate((num, np.zeros(len(num_approx) - len(num))))
634 rem = num - num_approx
635 return quot, rem
638_generate_sample_doc = Docstring(arma_generate_sample.__doc__)
639_generate_sample_doc.remove_parameters(['ar', 'ma'])
640_generate_sample_doc.replace_block('Notes', [])
641_generate_sample_doc.replace_block('Examples', [])
644class ArmaProcess(object):
645 r"""
646 Theoretical properties of an ARMA process for specified lag-polynomials.
648 Parameters
649 ----------
650 ar : array_like
651 Coefficient for autoregressive lag polynomial, including zero lag.
652 Must be entered using the signs from the lag polynomial representation.
653 See the notes for more information about the sign.
654 ma : array_like
655 Coefficient for moving-average lag polynomial, including zero lag.
656 nobs : int, optional
657 Length of simulated time series. Used, for example, if a sample is
658 generated. See example.
660 Notes
661 -----
662 Both the AR and MA components must include the coefficient on the
663 zero-lag. In almost all cases these values should be 1. Further, due to
664 using the lag-polynomial representation, the AR parameters should
665 have the opposite sign of what one would write in the ARMA representation.
666 See the examples below.
668 The ARMA(p,q) process is described by
670 .. math::
672 y_{t}=\phi_{1}y_{t-1}+\ldots+\phi_{p}y_{t-p}+\theta_{1}\epsilon_{t-1}
673 +\ldots+\theta_{q}\epsilon_{t-q}+\epsilon_{t}
675 and the parameterization used in this function uses the lag-polynomial
676 representation,
678 .. math::
680 \left(1-\phi_{1}L-\ldots-\phi_{p}L^{p}\right)y_{t} =
681 \left(1+\theta_{1}L+\ldots+\theta_{q}L^{q}\right)\epsilon_{t}
683 Examples
684 --------
685 ARMA(2,2) with AR coefficients 0.75 and -0.25, and MA coefficients 0.65 and 0.35
687 >>> import statsmodels.api as sm
688 >>> import numpy as np
689 >>> np.random.seed(12345)
690 >>> arparams = np.array([.75, -.25])
691 >>> maparams = np.array([.65, .35])
692 >>> ar = np.r_[1, -arparams] # add zero-lag and negate
693 >>> ma = np.r_[1, maparams] # add zero-lag
694 >>> arma_process = sm.tsa.ArmaProcess(ar, ma)
695 >>> arma_process.isstationary
696 True
697 >>> arma_process.isinvertible
698 True
699 >>> arma_process.arroots
700 array([1.5-1.32287566j, 1.5+1.32287566j])
701 >>> y = arma_process.generate_sample(250)
702 >>> model = sm.tsa.ARMA(y, (2, 2)).fit(trend='nc', disp=0)
703 >>> model.params
704 array([ 0.79044189, -0.23140636, 0.70072904, 0.40608028])
706 The same ARMA(2,2) Using the from_coeffs class method
708 >>> arma_process = sm.tsa.ArmaProcess.from_coeffs(arparams, maparams)
709 >>> arma_process.arroots
710 array([1.5-1.32287566j, 1.5+1.32287566j])
711 """
713 # TODO: Check unit root behavior
714 def __init__(self, ar=None, ma=None, nobs=100):
715 if ar is None:
716 ar = np.array([1.])
717 if ma is None:
718 ma = np.array([1.])
719 self.ar = array_like(ar, 'ar')
720 self.ma = array_like(ma, 'ma')
721 self.arcoefs = -self.ar[1:]
722 self.macoefs = self.ma[1:]
723 self.arpoly = np.polynomial.Polynomial(self.ar)
724 self.mapoly = np.polynomial.Polynomial(self.ma)
725 self.nobs = nobs
727 @classmethod
728 def from_coeffs(cls, arcoefs=None, macoefs=None, nobs=100):
729 """
730 Create ArmaProcess from an ARMA representation.
732 Parameters
733 ----------
734 arcoefs : array_like
735 Coefficient for autoregressive lag polynomial, not including zero
736 lag. The sign is inverted to conform to the usual time series
737 representation of an ARMA process in statistics. See the class
738 docstring for more information.
739 macoefs : array_like
740 Coefficient for moving-average lag polynomial, excluding zero lag.
741 nobs : int, optional
742 Length of simulated time series. Used, for example, if a sample
743 is generated.
745 Returns
746 -------
747 ArmaProcess
748 Class instance initialized with arcoefs and macoefs.
750 Examples
751 --------
752 >>> arparams = [.75, -.25]
753 >>> maparams = [.65, .35]
754 >>> arma_process = sm.tsa.ArmaProcess.from_coeffs(ar, ma)
755 >>> arma_process.isstationary
756 True
757 >>> arma_process.isinvertible
758 True
759 """
760 arcoefs = [] if arcoefs is None else arcoefs
761 macoefs = [] if macoefs is None else macoefs
762 return cls(np.r_[1, -np.asarray(arcoefs)],
763 np.r_[1, np.asarray(macoefs)],
764 nobs=nobs)
766 @classmethod
767 def from_estimation(cls, model_results, nobs=None):
768 """
769 Create an ArmaProcess from the results of an ARMA estimation.
771 Parameters
772 ----------
773 model_results : ARMAResults instance
774 A fitted model.
775 nobs : int, optional
776 If None, nobs is taken from the results.
778 Returns
779 -------
780 ArmaProcess
781 Class instance initialized from model_results.
782 """
783 arcoefs = model_results.arparams
784 macoefs = model_results.maparams
785 nobs = nobs or model_results.nobs
786 return cls(np.r_[1, -arcoefs], np.r_[1, macoefs], nobs=nobs)
788 def __mul__(self, oth):
789 if isinstance(oth, self.__class__):
790 ar = (self.arpoly * oth.arpoly).coef
791 ma = (self.mapoly * oth.mapoly).coef
792 else:
793 try:
794 aroth, maoth = oth
795 arpolyoth = np.polynomial.Polynomial(aroth)
796 mapolyoth = np.polynomial.Polynomial(maoth)
797 ar = (self.arpoly * arpolyoth).coef
798 ma = (self.mapoly * mapolyoth).coef
799 except:
800 raise TypeError('Other type is not a valid type')
801 return self.__class__(ar, ma, nobs=self.nobs)
803 def __repr__(self):
804 msg = 'ArmaProcess({0}, {1}, nobs={2}) at {3}'
805 return msg.format(self.ar.tolist(), self.ma.tolist(),
806 self.nobs, hex(id(self)))
808 def __str__(self):
809 return 'ArmaProcess\nAR: {0}\nMA: {1}'.format(self.ar.tolist(),
810 self.ma.tolist())
812 @Appender(remove_parameters(arma_acovf.__doc__, ['ar', 'ma', 'sigma2']))
813 def acovf(self, nobs=None):
814 nobs = nobs or self.nobs
815 return arma_acovf(self.ar, self.ma, nobs=nobs)
817 @Appender(remove_parameters(arma_acf.__doc__, ['ar', 'ma']))
818 def acf(self, lags=None):
819 lags = lags or self.nobs
820 return arma_acf(self.ar, self.ma, lags=lags)
822 @Appender(remove_parameters(arma_pacf.__doc__, ['ar', 'ma']))
823 def pacf(self, lags=None):
824 lags = lags or self.nobs
825 return arma_pacf(self.ar, self.ma, lags=lags)
827 @Appender(remove_parameters(arma_periodogram.__doc__, ['ar', 'ma', 'worN',
828 'whole']))
829 def periodogram(self, nobs=None):
830 nobs = nobs or self.nobs
831 return arma_periodogram(self.ar, self.ma, worN=nobs)
833 @Appender(remove_parameters(arma_impulse_response.__doc__, ['ar', 'ma']))
834 def impulse_response(self, leads=None):
835 leads = leads or self.nobs
836 return arma_impulse_response(self.ar, self.ma, leads=leads)
838 @Appender(remove_parameters(arma2ma.__doc__, ['ar', 'ma']))
839 def arma2ma(self, lags=None):
840 lags = lags or self.lags
841 return arma2ma(self.ar, self.ma, lags=lags)
843 @Appender(remove_parameters(arma2ar.__doc__, ['ar', 'ma']))
844 def arma2ar(self, lags=None):
845 lags = lags or self.lags
846 return arma2ar(self.ar, self.ma, lags=lags)
848 @property
849 def arroots(self):
850 """Roots of autoregressive lag-polynomial"""
851 return self.arpoly.roots()
853 @property
854 def maroots(self):
855 """Roots of moving average lag-polynomial"""
856 return self.mapoly.roots()
858 @property
859 def isstationary(self):
860 """
861 Arma process is stationary if AR roots are outside unit circle.
863 Returns
864 -------
865 bool
866 True if autoregressive roots are outside unit circle.
867 """
868 if np.all(np.abs(self.arroots) > 1.0):
869 return True
870 else:
871 return False
873 @property
874 def isinvertible(self):
875 """
876 Arma process is invertible if MA roots are outside unit circle.
878 Returns
879 -------
880 bool
881 True if moving average roots are outside unit circle.
882 """
883 if np.all(np.abs(self.maroots) > 1):
884 return True
885 else:
886 return False
888 def invertroots(self, retnew=False):
889 """
890 Make MA polynomial invertible by inverting roots inside unit circle.
892 Parameters
893 ----------
894 retnew : bool
895 If False (default), then return the lag-polynomial as array.
896 If True, then return a new instance with invertible MA-polynomial.
898 Returns
899 -------
900 manew : ndarray
901 A new invertible MA lag-polynomial, returned if retnew is false.
902 wasinvertible : bool
903 True if the MA lag-polynomial was already invertible, returned if
904 retnew is false.
905 armaprocess : new instance of class
906 If retnew is true, then return a new instance with invertible
907 MA-polynomial.
908 """
909 # TODO: variable returns like this?
910 pr = self.maroots
911 mainv = self.ma
912 invertible = self.isinvertible
913 if not invertible:
914 pr[np.abs(pr) < 1] = 1. / pr[np.abs(pr) < 1]
915 pnew = np.polynomial.Polynomial.fromroots(pr)
916 mainv = pnew.coef / pnew.coef[0]
918 if retnew:
919 return self.__class__(self.ar, mainv, nobs=self.nobs)
920 else:
921 return mainv, invertible
923 @Appender(str(_generate_sample_doc))
924 def generate_sample(self, nsample=100, scale=1., distrvs=None, axis=0,
925 burnin=0):
926 return arma_generate_sample(self.ar, self.ma, nsample, scale, distrvs,
927 axis=axis, burnin=burnin)