o
    0GfL                     @   s$  d Z ddlZddlmZ ddlmZ dd Zd1dd	Zd2d
dZ	d3ddZ
d4ddZdd Zdd ZG dd dZG dd dZedkreddgddggddgddgggZeddgddggddgddgggZeddgddggddgddgggZe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d dddddf d!ed dddddf  f Zeg d"g d#g d$gg d%g d&g d'ggZejd(d)Ze	eeZejjeeded*d+Z e d !dd)d)Z"ee"Z#eeZ$e$%d e$&  e$&d,d-d  eddgddggddgddggddgddgggZ'eddgddggd.dgdd/gggZ(eddgddggd0dgd.dggd/dgddgggZ)ee'e(Z*e+e,e* e+e*-  e+e*-e e+e*.  e+e*/  e+e*0  ee)Z1e+e1/  e+e10  dS dS )5a9   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           	      C   s^  t | } t |}| jdkr| dddf } | jdkr td| jd }|jd }|d }|jdkrAtj| |dddf ddS |jdkrt|jdkrUtj| |ddS t | jd | d |f}t	|D ]}tj| dd|f |dd|f dd|dd|f< qg|S |jdkrt| dddddf |}||| |jd d ddf }|S dS )	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   Zvalid)mode   )
npZasarrayndim
ValueErrorshaper   Zconvolveminzerosrange)	xanvarnlagsZntrimresultiZyfZyvalid r   =lib/python3.10/site-packages/statsmodels/tsa/varma_process.py	varfilter$   s.   
9






6
"r   r   c           
      C   sJ  | j \}}}||krtd t|d ||f}| d |dddddf< | dd  |d|ddddf< |dkrutd|d D ]2}t||f}td|D ]}	|t| |	  |||	 ddddf 7 }qP|||ddddf< qB|dkrt|d |d D ] }t| dd j ||d || 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nvarsexZarinvr   tmppr   r   r   varinversefilter   s"   $.6r$   c                 C   s   | j \}}}|d }|j d }||krtd |j d |kr"td|du r2t|| |f}|}	nt||j d }	t||	 |f}|||	|j d  |	< |||	d< t|	|	| D ]!}
td|D ]}||
  t||
| ddf | |  7  < qbq[|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!   Znlagsm1r   Zsarstartr   r#   r   r   r   vargenerate   s&   %
0r)   c           	         s   t | j}||  || 7  < t | j}t |}|| t | j||< |   fddtt D }| |t	|< |S )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]])
    c                       g | ]}t |  | qS r   slice.0kZendindZstartindr   r   
<listcomp>      zpadone.<locals>.<listcomp>)
r   arrayr   emptyfillr   r	   r   lentuple)	r   frontbackaxis	fillvaluer   shapearroutmyslicer   r0   r   padone   s   

r?   c                    sp   t | j}||  || 8  < t | j}t | j||< |   fddtt D }| t| S )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.]])
    c                    r*   r   r+   r-   r0   r   r   r1   ,  r2   ztrimone.<locals>.<listcomp>)r   r3   r   r   r	   r   r6   r7   )r   r8   r9   r:   r   r<   r>   r   r0   r   trimone  s   r@   c                 C   s6   | j \}}}tjt||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   Znvarexr   r   r   ar2full3  s   *rC   c                 C   s   | dd  S )zconvert full (rhs) lagpolynomial into a reduced, left side lagpoly array

    this is mainly a reminder about the definition
    r   Nr   )r   r   r   r   ar2lhs:  s   rD   c                   @   s:   e Zd ZdZdd Zdd Zdd Zdd	 ZdddZdS )_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                 C   s   || _ |j\| _| _d S N)yr   r   r    )selfrG   r   r   r   __init__T  s   z_Var.__init__c                 C   s   || _ | j}t| j|ddd}|ddd|f | _|dd|df | _tjj| j| jdd}|| _	|d 
|||| _t| j| _|d | _|d	 | _dS )
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


        Zbothin)ZtrimZoriginalNr   Zrcondr   r   r   )r   r    r   rG   Zyredxredr   linalglstsqZ
estresultsreshapeZarlhsrC   arhatrssZxredrank)rH   r   r    Zlmatresr   r   r   fitX  s   
z_Var.fitc                 C   s    t | dst| j| j| _| jS )z:calculate estimated timeseries (yhat) for sample

        yhat)hasattrr   rG   rP   rT   rH   r   r   r   predict  s   
z_Var.predictc                 C   sF   | j ddddf tjt| jj| jdddddf  | _dS )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)rQ   r   rM   invr   rL   TZparamcovrV   r   r   r   covmat  s   *
z_Var.covmatr   Nc                 C   s*   |du rt || jf}t| j|| jd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
        N)r'   )r   r   r    r)   rP   rG   )rH   Zhorizr&   r   r   r   forecast  s   z_Var.forecast)r   N)	__name__
__module____qualname____doc__rI   rS   rW   rZ   r[   r   r   r   r   rE   B  s    )	rE   c                   @   sd   e Zd ZdZdddZdddZddd	ZdddZdd Zdd Z	dddZ
dddZdd ZdS )	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                 C   s   || _ || _|j\}}}|||| _| _| _|dd |f t|k  | _	| jd u r9t|d | _d| _
n|d t|k  | _
|jd | _||k| _|dd   | _d S )Nr   )N.Tr   )r   mar   r   nvarallr    r   rB   allisstructuredisindependentZmalagsZhasexogZarm1)rH   r   ra   r   rb   r    r   r   r   rI     s   "

zVarmaPoly.__init__r   c                 C   sD   |dur|}n|dkr| j }n|dkr| j}ntd|d| jS )z4stack lagpolynomial vertically in 2d array

        Nr   ra   no array or name givenr   )r   ra   r
   rO   rb   rH   r   namer   r   r   vstack  s   zVarmaPoly.vstackc                 C   sN   |dur|}n|dkr| j }n|dkr| j}ntd|ddd| jjS )z6stack lagpolynomial horizontally in 2d array

        Nr   ra   rf   r   r   r   )r   ra   r
   swapaxesrO   rb   rY   rg   r   r   r   hstack  s   zVarmaPoly.hstackverticalc                 C   st   |dur|}n|dkr| j }n|dkr| j}ntd|d| j}|j\}}tj||d}||ddd|f< |S )zDstack lagpolynomial vertically in 2d square array with eye

        Nr   ra   rf   r   )r/   )r   ra   r
   rO   rb   r   r   rB   )rH   r   rh   ZorientationZastackedZlenpkr    amatr   r   r   stacksquare  s   
zVarmaPoly.stacksquarec                 C   s2   t | jdd | jdd fd}|d| jS )z;stack ar and lagpolynomial vertically in 2d array

        r   Nr   r   )r   concatenater   ra   rO   rb   rH   r   r   r   r   vstackarma_minus1  s   $zVarmaPoly.vstackarma_minus1c                 C   s:   t | jdd | jdd fd}|ddd| jS )zustack ar and lagpolynomial vertically in 2d array

        this is the Kalman Filter representation, I think
        r   Nr   r   r   )r   ro   r   ra   rj   rO   rb   rp   r   r   r   hstackarma_minus1  s   $zVarmaPoly.hstackarma_minus1c                 C   sz   |dur|}n| j r| | jdd  }n| jdd  }| |}ttj|ddd }|| _t	|dk 
 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   )rd   
reduceformr   rn   r   sortrM   eigvalsZareigenvaluesabsrc   rH   r   rm   Zevr   r   r   getisstationary  s   
zVarmaPoly.getisstationaryc                 C   s   |dur|}n| j r| | jdd }n| jdd }|jd dkr-tg tj| _dS | |}t	tj
|ddd }|| _t|dk  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   )re   rs   ra   r   r   r3   complexZmaeigenvaluesrn   rt   rM   ru   rv   rc   rw   r   r   r   getisinvertible;  s   
zVarmaPoly.getisinvertiblec                 C   s   |j dkr	td|j\}}}t|}ztj|dd|ddf }W n tjjy3   tddw t|D ]}t	||| ||< q8|S )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   Z
empty_likerM   rX   ZLinAlgErrorr   r   )rH   Zapolyr   r!   r    r   Za0invZlagr   r   r   rs   ]  s   

"zVarmaPoly.reduceformrF   )Nr   )Nr   rl   )r\   r]   r^   r_   rI   ri   rk   rn   rq   rr   rx   rz   rs   r   r   r   r   r`     s    





"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   rK      ig?g333333?gffffff)r   rF   )r   r   r   r   )r   r   r   )2r_   Znumpyr   Zscipyr   Zstatsmodels.tsa.tsatoolsr   r   r$   r)   r?   r@   rC   rD   rE   r`   r\   r3   Za21Za22Za23Za24rA   rB   Za31Za32ZrandomZrandnutZar2srM   rN   rR   rO   ZbhatrP   vrS   r[   Zar23Zma22Zar23nsZvpr   varsri   rr   rx   rz   Zvp2r   r   r   r   <module>   s    
_
4
=
#s 
@



B	
	



	

	