
    !gL                        d Z ddlZddlmZ ddlmZ d Zd*dZd+dZ	d,d	Z
d-d
Zd Zd Z G d d      Z G d d      Zedk(  r ej"                  ddgddggddgddggg      Z ej"                  ddgddggddgddggg      Z ej"                  ddgddggddgddggg      Z ej"                  ddgddggddgddggddgddggg      Zej,                   ej.                  d      dddddf   d ej.                  d      dddddf   z  f   Z ej"                  g dg dg dgg dg dg d gg      Zej4                  j7                  d!d"      Z e	ee      Zej<                  j?                   eed      ed#$      Z e d   jC                  dd"d"      Z" ee"      Z# ee      Z$e$jK                  d       e$jM                          e$jM                  d%      d&d   ej"                  ddgddggddgddggddgddggg      Z' ej"                  ddgddggd'dgdd(ggg      Z( ej"                  ddgddggd)dgd'dggd(dgddggg      Z) ee'e(      Z* e+ e,e*              e+e*j[                                 e+e*j[                  e              e+e*j]                                 e+e*j_                                 e+e*ja                                 ee)      Z1 e+e1j_                                 e+e1ja                                yy).a9   Helper and filter functions for VAR and VARMA, and basic VAR class

Created on Mon Jan 11 11:04:23 2010
Author: josef-pktd
License: BSD

This is a new version, I did not look at the old version again, but similar
ideas.

not copied/cleaned yet:
 * fftn based filtering, creating samples with fft
 * Tests: I ran examples but did not convert them to tests
   examples look good for parameter estimate and forecast, and filter functions

main TODOs:
* result statistics
* see whether Bayesian dummy observation can be included without changing
  the single call to linalg.lstsq
* impulse response function does not treat correlation, see Hamilton and jplv

Extensions
* constraints, Bayesian priors/penalization
* Error Correction Form and Cointegration
* Factor Models Stock-Watson,  ???


see also VAR section in Notes.txt

    N)signal)lagmatc                 J   t        j                  |       } t        j                  |      }| j                  dk(  r	| dddf   } | j                  dkD  rt        d      | j                  d   }|j                  d   }|dz  }|j                  dk(  rt        j                  | |dddf   d      S |j                  dk(  rt        |j                        dk(  rt        j                  | |d      S t        j                  | j                  d   |z
  dz   |f      }t        |      D ]/  }t        j                  | dd|f   |dd|f   d      |dd|f<   1 |S |j                  dk(  r?t        j                  | dddddf   |      }||| |j                  d   dz  ddf   }|S y)	a  apply an autoregressive filter to a series x

    Warning: I just found out that convolve does not work as I
       thought, this likely does not work correctly for
       nvars>3


    x can be 2d, a can be 1d, 2d, or 3d

    Parameters
    ----------
    x : array_like
        data array, 1d or 2d, if 2d then observations in rows
    a : array_like
        autoregressive filter coefficients, ar lag polynomial
        see Notes

    Returns
    -------
    y : ndarray, 2d
        filtered array, number of columns determined by x and a

    Notes
    -----

    In general form this uses the linear filter ::

        y = a(L)x

    where
    x : nobs, nvars
    a : nlags, nvars, npoly

    Depending on the shape and dimension of a this uses different
    Lag polynomial arrays

    case 1 : a is 1d or (nlags,1)
        one lag polynomial is applied to all variables (columns of x)
    case 2 : a is 2d, (nlags, nvars)
        each series is independently filtered with its own
        lag polynomial, uses loop over nvar
    case 3 : a is 3d, (nlags, nvars, npoly)
        the ith column of the output array is given by the linear filter
        defined by the 2d array a[:,:,i], i.e. ::

            y[:,i] = a(.,.,i)(L) * x
            y[t,i] = sum_p sum_j a(p,j,i)*x(t-p,j)
                     for p = 0,...nlags-1, j = 0,...nvars-1,
                     for all t >= nlags


    Note: maybe convert to axis=1, Not

    TODO: initial conditions

       N   zx array has to be 1d or 2dr   valid)mode   )
npasarrayndim
ValueErrorshaper   convolveminzerosrange)	xanvarnlagsntrimresultiyfyvalids	            Z/var/www/dash_apps/app1/venv/lib/python3.12/site-packages/statsmodels/tsa/varma_process.py	varfilterr   $   s   r 	

1A


1Avv{afIvvz566771:DGGAJE1HE 	vv{q!AdF)':: 
1qww<1??1ag66
 1771:e+A-t45t 	HA //!AaC&!AaC&wGF1Q3K	H 	
1 __Qq4x[!,E5&L"((1+q.23 
    r   c                 d   | j                   \  }}}||k7  rt        d       t        j                  |dz   ||f      }| d   |dddddf<   | dd  |d|ddddf<   |dk(  rrt	        d|dz         D ]`  }t        j                  ||f      }t	        d|      D ],  }	|t        j
                  | |	    |||	z
  ddddf         z  }. |||ddddf<   b |dk(  rWt	        |dz   |dz         D ]B  }t        | dd j                   ||dz
  ||z
  dddddf   j                          t        d       |S )a  creates inverse ar filter (MA representation) recursively

    The VAR lag polynomial is defined by ::

        ar(L) y_t = u_t  or
        y_t = -ar_{-1}(L) y_{t-1} + u_t

    the returned lagpolynomial is arinv(L)=ar^{-1}(L) in ::

        y_t = arinv(L) u_t



    Parameters
    ----------
    ar : ndarray, (nlags,nvars,nvars)
        matrix lagpolynomial, currently no exog
        first row should be identity

    Returns
    -------
    arinv : ndarray, (nobs,nvars,nvars)


    Notes
    -----

    .exogenous variables not implemented not testedr   r   Nr   z+waiting for generalized ufuncs or something)r   printr   r   r   dotNotImplementedError)
arnobsversionr   nvarsnvarsexarinvr   tmpps
             r   varinversefilterr.      s^   : HHE5'>?HHd1fgu-.Ea5E!Aa%LQR&E!E'!A+!|qa 	A((E%=)C1U^ 5rvvr!ufU1Q3q7^445E!Aa%L		
 !|uQwtAv& 	UA"QR&,,ac!E'"nQq&8 9 ? ?@ &&STT	U Lr   c                 (   | j                   \  }}}|dz
  }|j                   d   }||k7  rt        d       |j                   d   |k7  rt        d      |t        j                  ||z   |f      }|}	nHt        ||j                   d         }	t        j                  ||	z   |f      }|||	|j                   d   z
  |	 |||	d t        |	|	|z         D ]B  }
t        d|      D ]1  }||
xx   t        j                  ||
|z
  ddf   | |          z  cc<   3 D |S )aE  generate an VAR process with errors u

    similar to gauss
    uses loop

    Parameters
    ----------
    ar : array (nlags,nvars,nvars)
        matrix lagpolynomial
    u : array (nobs,nvars)
        exogenous variable, error term for VAR

    Returns
    -------
    sar : array (1+nobs,nvars)
        sample of var process, inverse filtered u
        does not trim initial condition y_0 = 0

    Examples
    --------
    # generate random sample of VAR
    nobs, nvars = 10, 2
    u = numpy.random.randn(nobs,nvars)
    a21 = np.array([[[ 1. ,  0. ],
                     [ 0. ,  1. ]],

                    [[-0.8,  0. ],
                     [ 0.,  -0.6]]])
    vargenerate(a21,u)

    # Impulse Response to an initial shock to the first variable
    imp = np.zeros((nobs, nvars))
    imp[0,0] = 1
    vargenerate(a21,imp)

    r   r   r!   zu needs to have nvars columnsN)r   r#   r   r   r   maxr   r$   )r&   u
initvaluesr   r)   r*   nlagsm1r'   sarstartr   r-   s               r   vargenerater6      s0   J HHE5'aiG771:D>?wwqzU899hhWe,-GZ--a01hhU
E*+/9E*""1%%e,CK5t$ 0q 	0AFbffS1QZA//F	00 Jr   c                    t        j                  | j                        }||xx   ||z   z  cc<   t        j                  | j                        }t        j                  |      }|j	                  |       t        j
                  | j                        }|||<   ||z   }	t        t        |	            D 
cg c]  }
t        ||
   |	|
          }}
| |t        |      <   |S c c}
w )a  pad with zeros along one axis, currently only axis=0


    can be used sequentially to pad several axis

    Examples
    --------
    >>> padone(np.ones((2,3)),1,3,axis=1)
    array([[ 0.,  1.,  1.,  1.,  0.,  0.,  0.],
           [ 0.,  1.,  1.,  1.,  0.,  0.,  0.]])

    >>> padone(np.ones((2,3)),1,1, fillvalue=np.nan)
    array([[ NaN,  NaN,  NaN],
           [  1.,   1.,   1.],
           [  1.,   1.,   1.],
           [ NaN,  NaN,  NaN]])
    )r   arrayr   emptyfillr   r   r   lenslicetuple)r   frontbackaxis	fillvaluer   shapearroutstartindendindkmyslices               r   padonerH      s    & HHQWWE	$KEDL!Kxx H
((5/CHHYxxHHTN F6;CK6HIuXa[&),IGI CgJ Js   4Cc                 x   t        j                  | j                        }||xx   ||z   z  cc<   t        j                  | j                        }t        j                  | j                        }|||<   ||z   }t        t        |            D cg c]  }t        ||   ||          }	}| t        |	         S c c}w )a;  trim number of array elements along one axis


    Examples
    --------
    >>> xp = padone(np.ones((2,3)),1,3,axis=1)
    >>> xp
    array([[ 0.,  1.,  1.,  1.,  0.,  0.,  0.],
           [ 0.,  1.,  1.,  1.,  0.,  0.,  0.]])
    >>> trimone(xp,1,3,1)
    array([[ 1.,  1.,  1.],
           [ 1.,  1.,  1.]])
    )	r   r8   r   r   r   r   r;   r<   r=   )
r   r>   r?   r@   r   rB   rD   rE   rF   rG   s
             r   trimonerJ     s     HHQWWE	$KEDL!Kxx HxxHHTNF6;CK6HIuXa[&),IGI U7^	 Js   B7c                     | j                   \  }}}t        j                  t        j                  ||      dddddf   |  f   S )z?make reduced lagpolynomial into a right side lagpoly array
    N)r   r   r_eye)r&   r   r   nvarexs       r   ar2fullrO   3  s@     E455V$T!AX.s233r   c                     | dd  S )zconvert full (rhs) lagpolynomial into a reduced, left side lagpoly array

    this is mainly a reminder about the definition
    r   N )r&   s    r   ar2lhsrR   :  s    
 qrF7Nr   c                   0    e Zd ZdZd Zd Zd Zd ZddZy)	_Vara<  obsolete VAR class, use tsa.VAR instead, for internal use only


    Examples
    --------

    >>> v = Var(ar2s)
    >>> v.fit(1)
    >>> v.arhat
    array([[[ 1.        ,  0.        ],
            [ 0.        ,  1.        ]],

           [[-0.77784898,  0.01726193],
            [ 0.10733009, -0.78665335]]])

    c                 D    || _         |j                  \  | _        | _        y N)yr   r'   r)   )selfrW   s     r   __init__z_Var.__init__T  s     !	4:r   c                    || _         | j                  }t        | j                  |dd      }|ddd|f   | _        |dd|df   | _        t        j                  j                  | j
                  | j                  d      }|| _	        |d   j                  |||      | _        t        | j                        | _        |d   | _        |d	   | _        y)
a  estimate parameters using ols

        Parameters
        ----------
        nlags : int
            number of lags to include in regression, same for all variables

        Returns
        -------
        None, but attaches

        arhat : array (nlags, nvar, nvar)
            full lag polynomial array
        arlhs : array (nlags-1, nvar, nvar)
            reduced lag polynomial for left hand side
        other statistics as returned by linalg.lstsq : need to be completed



        This currently assumes all parameters are estimated without restrictions.
        In this case SUR is identical to OLS

        estimation results are attached to the class instance


        bothin)trimoriginalNr"   rcondr   r   r   )r   r)   r   rW   yredxredr   linalglstsq
estresultsreshapearlhsrO   arhatrssxredrank)rX   r   r)   lmatress        r   fitz_Var.fitX  s    6 


 dffe&4@6E6N	56N	iioodii"o=V^^E5%8
TZZ(
q6Ar   c                 |    t        | d      s%t        | j                  | j                        | _        | j                  S )z:calculate estimated timeseries (yhat) for sample

        yhat)hasattrr   rW   rh   ro   rX   s    r   predictz_Var.predict  s.    
 tV$!$&&$**5DIyyr   c                     | j                   ddddf   t        j                  j                  t        j                  | j
                  j                  | j
                              dddddf   z  | _        y)a   covariance matrix of estimate
        # not sure it's correct, need to check orientation everywhere
        # looks ok, display needs getting used to
        >>> v.rss[None,None,:]*np.linalg.inv(np.dot(v.xred.T,v.xred))[:,:,None]
        array([[[ 0.37247445,  0.32210609],
                [ 0.1002642 ,  0.08670584]],

               [[ 0.1002642 ,  0.08670584],
                [ 0.45903637,  0.39696255]]])
        >>>
        >>> v.rss[0]*np.linalg.inv(np.dot(v.xred.T,v.xred))
        array([[ 0.37247445,  0.1002642 ],
               [ 0.1002642 ,  0.45903637]])
        >>> v.rss[1]*np.linalg.inv(np.dot(v.xred.T,v.xred))
        array([[ 0.32210609,  0.08670584],
               [ 0.08670584,  0.39696255]])
       N)ri   r   rc   invr$   rb   Tparamcovrq   s    r   covmatz_Var.covmat  sR    ( $tA+.IIMM"&&dii89!Ad(CDr   Nc                     |!t        j                  || j                  f      }t        | j                  || j
                        S )a  calculates forcast for horiz number of periods at end of sample

        Parameters
        ----------
        horiz : int (optional, default=1)
            forecast horizon
        u : array (horiz, nvars)
            error term for forecast periods. If None, then u is zero.

        Returns
        -------
        yforecast : array (nobs+horiz, nvars)
            this includes the sample and the forecasts
        )r2   )r   r   r)   r6   rh   rW   )rX   horizr1   s      r   forecastz_Var.forecast  s7     9%,-A4::qTVV<<r   )r   N)	__name__
__module____qualname____doc__rY   rm   rr   rw   rz   rQ   r   r   rT   rT   B  s"    "('RE.=r   rT   c                   R    e Zd ZdZddZddZddZddZd Zd Z	dd	Z
dd
Zd Zy)	VarmaPolya  class to keep track of Varma polynomial format


    Examples
    --------

    ar23 = np.array([[[ 1. ,  0. ],
                     [ 0. ,  1. ]],

                    [[-0.6,  0. ],
                     [ 0.2, -0.6]],

                    [[-0.1,  0. ],
                     [ 0.1, -0.1]]])

    ma22 = np.array([[[ 1. ,  0. ],
                     [ 0. ,  1. ]],

                    [[ 0.4,  0. ],
                     [ 0.2, 0.3]]])


    Nc                    || _         || _        |j                  \  }}}|||c| _        | _        | _        |dd |f   t        j                  |      k(  j                          | _	        | j                  %t        j                  |      d   | _        d| _
        n/|d   t        j                  |      k(  j                          | _
        |j                  d   | _        ||kD  | _        |dd   | _        y )Nr   )N.Tr   )r&   mar   r   nvarallr)   r   rM   allisstructuredisindependentmalagshasexogarm1)rX   r&   r   r   r   r)   s         r   rY   zVarmaPoly.__init__  s     "w/4gu,
DL$*!#AfufH!> C C EE77?ffUmH-DG!%D&(ervve}&<%A%A%C!CDhhqkVG	r   c                     ||}n/|dk(  r| j                   }n|dk(  r| j                  }nt        d      |j                  d| j                        S )z4stack lagpolynomial vertically in 2d array

        r&   r   no array or name givenr"   )r&   r   r   rf   r   rX   r   names      r   vstackzVarmaPoly.vstack  sO     =AT\AT\A566yyT\\**r   c                     ||}n/|dk(  r| j                   }n|dk(  r| j                  }nt        d      |j                  dd      j	                  d| j
                        j                  S )z6stack lagpolynomial horizontally in 2d array

        r&   r   r   r   r   r"   )r&   r   r   swapaxesrf   r   ru   r   s      r   hstackzVarmaPoly.hstack  sa     =AT\AT\A566zz!A&&r4<<8:::r   c                    ||}n/|dk(  r| j                   }n|dk(  r| j                  }nt        d      |j                  d| j                        }|j
                  \  }}t        j                  ||      }||ddd|f<   |S )zDstack lagpolynomial vertically in 2d square array with eye

        Nr&   r   r   r"   )rF   )r&   r   r   rf   r   r   r   rM   )rX   r   r   orientationastackedlenpkr)   amats           r   stacksquarezVarmaPoly.stacksquare  s     =AT\AT\A56699R.~~uvveu%!QvvXr   c                     t        j                  | j                  dd | j                  dd fd      }|j	                  d| j
                        S )z;stack ar and lagpolynomial vertically in 2d array

        r   Nr   r"   )r   concatenater&   r   rf   r   rX   r   s     r   vstackarma_minus1zVarmaPoly.vstackarma_minus1  sB     NNDGGABK5a8yyT\\**r   c                     t        j                  | j                  dd | j                  dd fd      }|j	                  dd      j                  d| j                        S )zustack ar and lagpolynomial vertically in 2d array

        this is the Kalman Filter representation, I think
        r   Nr   r   r"   )r   r   r&   r   r   rf   r   r   s     r   hstackarma_minus1zVarmaPoly.hstackarma_minus1  sN    
 NNDGGABK5a8zz!A&&r4<<88r   c                 p   ||}n<| j                   r | j                  | j                        dd  }n| j                  dd  }| j                  |      }t	        j
                  t        j                  j                  |            ddd   }|| _        t	        j                  |      dk  j                         S )a>  check whether the auto-regressive lag-polynomial is stationary

        Returns
        -------
        isstationary : bool

        *attaches*

        areigenvalues : complex array
            eigenvalues sorted by absolute value

        References
        ----------
        formula taken from NAG manual

        Nr   r"   )r   
reduceformr&   r   r   sortrc   eigvalsareigenvaluesabsr   rX   r   r   evs       r   getisstationaryzVarmaPoly.getisstationary  s    " =A  __TWW-ab11WWQR[L"WWRYY&&t,-dd3r
Q##%%r   c                    ||}n:| j                   r| j                  | j                        dd }n| j                  dd }|j                  d   dk(  r*t	        j
                  g t        j                        | _        y| j                  |      }t	        j                  t        j                  j                  |            ddd   }|| _        t	        j                  |      dk  j                         S )a>  check whether the auto-regressive lag-polynomial is stationary

        Returns
        -------
        isinvertible : bool

        *attaches*

        maeigenvalues : complex array
            eigenvalues sorted by absolute value

        References
        ----------
        formula taken from NAG manual

        Nr   r   Tr"   )r   r   r   r   r   r8   complexmaeigenvaluesr   r   rc   r   r   r   r   s       r   getisinvertiblezVarmaPoly.getisinvertible;  s    " =A!!OODGG,QR0GGABK771:?!#"bjj!9D"WWRYY&&t,-dd3r
Q##%%r   c                    |j                   dk7  rt        d      |j                  \  }}}t        j                  |      }	 t        j
                  j                  |dd|ddf         }t        |      D ]  }t        j                  |||         ||<     |S # t        j
                  j                  $ r t        dd      w xY w)z.

        this assumes no exog, todo

        r
   zapoly needs to be 3dr   Nzmatrix not invertiblezask for implementation of pinv)
r   r   r   r   
empty_likerc   rt   LinAlgErrorr   r$   )rX   apolyr   r*   r)   r   a0invlags           r   r   zVarmaPoly.reduceform]  s     ::?344 %wMM% 	?IIMM!AfufaK.1E
 < 	/CVVE5:.AcF	/  yy$$ 	?4=? ?	?s   )B *CrV   )Nr&   )Nr&   vertical)r{   r|   r}   r~   rY   r   r   r   r   r   r   r   r   rQ   r   r   r   r     s5    . +;&+9&: &Dr   r   __main__      ?        gg333333皙?g?gr
   皙?)r   r   r   )r   r   r   )r   r   r   )r   r   r   )r   g333333?r   )r   r   g?i  r   r"   r_      ig?g333333?gffffff)r   rV   )r   r   r   r   )r   r   r   )2r~   numpyr   scipyr   statsmodels.tsa.tsatoolsr   r   r.   r6   rH   rJ   rO   rR   rT   r   r{   r8   a21a22a23a24rL   rM   a31a32randomrandnutar2src   rd   rl   rf   bhatrh   vrm   rz   ar23ma22ar23nsvpr#   varsr   r   r   r   vp2rQ   r   r   <module>r      s  :   +\~1h:z F84p= p=f| |~ z
"((rR\R\# R\D\#$ %C "((rR\R\# R\D\#$ %C "((rR\R\# S\D\#$ %C "((rR\R\# R\D\# R\D\#$ %C %%q	$q(#S4!8)<%<<
=C
"((''') ('')	* +C 
a	 Bs2D
))//&a.$b/
9Cq6>>!Aa DDME 	T
AEE!HJJLJJrN34288blR\# R\D\# R\D\#$ %D 288blR\# R\C["# $D RXX"R\# R\D\# R\D\#$ %F 
4	B	$r(O	"))+	"))C.	"


 !	"


	"



F
C	#


 	#


 m r   