U
    mdM                     @   s,  d Z ddlZddlmZ ddlmZ dd Zd-dd	Zd.d
dZ	d/ddZ
d0ddZdd Zdd ZG dd dZG dd dZedkr(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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dddgdddgdddggd!ddgdd"dgddd#g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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*-  e+e*-e e+e*.  e+e*/  e+e*0  ee)Z1e+e1/  e+e10  dS )1a9   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   sb  t | } t |}| jdkr.| dddf } | jdkr@td| jd }|jd }|d }|jdkrtj| |dddf ddS |jdkrt|jdkrtj| |ddS t | jd | d |f}t	|D ]8}tj| dd|f |dd|f dd|dd|f< q|S |jdkr^t| 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   V/home/sam/Atlas/atlas_env/lib/python3.8/site-packages/statsmodels/tsa/varma_process.py	varfilter%   s,    9






6"r   r   c           
      C   sP  | 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rtd|d D ]d}t||f}td|D ]0}	|t| |	  |||	 ddddf 7 }q|||ddddf< q|dkrLt|d |d D ]D}t| dd j ||d || dddddf j  tdq|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rDtd|dkrdt|| |f}|}	n8t||j d }	t||	 |f}|||	|j d  |	< |||	d< t|	|	| D ]B}
td|D ]2}||
  t||
| ddf | |  7  < qq|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$    %
2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                    s   g | ]}t |  | qS r   slice.0kZendindZstartindr   r   
<listcomp>  s     zpadone.<locals>.<listcomp>)
r   arrayr   emptyfillr   r	   r   lentuple)	r   frontbackaxis	fillvaluer   shapearroutmyslicer   r/   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                    s   g | ]}t |  | qS r   r*   r,   r/   r   r   r0   -  s     ztrimone.<locals>.<listcomp>)r   r1   r   r   r	   r   r4   r5   )r   r6   r7   r8   r   r:   r<   r   r/   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   ar2full4  s    rA   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    rB   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    )selfrD   r   r   r   __init__U  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trimoriginalNr   Zrcondr   r   r   )r   r    r   rD   Zyredxredr   linalglstsqZ
estresultsreshapeZarlhsrA   arhatrssZxredrank)rE   r   r    Zlmatresr   r   r   fitY  s    
z_Var.fitc                 C   s    t | dst| j| j| _| jS )z:calculate estimated timeseries (yhat) for sample

        yhat)hasattrr   rD   rN   rR   rE   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)rO   r   rK   invr   rJ   TZparamcovrT   r   r   r   covmat  s    *z_Var.covmatr   Nc                 C   s*   |dk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)   rN   rD   )rE   Zhorizr&   r   r   r   forecast  s    z_Var.forecast)r   N)	__name__
__module____qualname____doc__rF   rQ   rU   rX   rY   r   r   r   r   rC   C  s   )	rC   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 krrt|d | _d| _
n|d t|k  | _
|jd | _||k| _|dd   | _d S )Nr   )N.Tr   )r   mar   r   nvarallr    r   r@   allisstructuredisindependentZmalagsZhasexogZarm1)rE   r   r_   r   r`   r    r   r   r   rF     s    "

zVarmaPoly.__init__r   c                 C   sD   |dk	r|}n(|dkr| j }n|dkr.| j}ntd|d| jS )z4stack lagpolynomial vertically in 2d array

        Nr   r_   no array or name givenr   )r   r_   r
   rM   r`   rE   r   namer   r   r   vstack  s    zVarmaPoly.vstackc                 C   sN   |dk	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   r_   rd   r   r   r   )r   r_   r
   swapaxesrM   r`   rW   re   r   r   r   hstack  s    zVarmaPoly.hstackverticalc                 C   st   |dk	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   r_   rd   r   )r.   )r   r_   r
   rM   r`   r   r   r@   )rE   r   rf   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   r_   rM   r`   rE   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   rm   r   r_   rh   rM   r`   rn   r   r   r   hstackarma_minus1  s    $zVarmaPoly.hstackarma_minus1c                 C   sz   |dk	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   )rb   
reduceformr   rl   r   sortrK   eigvalsZareigenvaluesabsra   rE   r   rk   Zevr   r   r   getisstationary  s    
zVarmaPoly.getisstationaryc                 C   s   |dk	r|}n*| j r*| | jdd }n| jdd }|jd dkrZt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   )rc   rq   r_   r   r   r1   complexZmaeigenvaluesrl   rr   rK   rs   rt   ra   ru   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k
rl   tddY nX t|D ]}t	||| ||< qv|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_likerK   rV   ZLinAlgErrorr   r   )rE   Zapolyr   r!   r    r   Za0invZlagr   r   r   rq   ^  s    

"
zVarmaPoly.reduceform)N)Nr   )Nr   )Nr   rj   )N)N)rZ   r[   r\   r]   rF   rg   ri   rl   ro   rp   rv   rx   rq   r   r   r   r   r^     s   





"r^   __main__g      ?g        gg333333g?g?gr   g?g333333?g?i  r   r   rI      ig?g333333?gffffff)r   )N)r   r   r   r   )r   r   r   )2r]   numpyr   Zscipyr   Zstatsmodels.tsa.tsatoolsr   r   r$   r)   r=   r>   rA   rB   rC   r^   rZ   r1   Za21Za22Za23Za24r?   r@   Za31Za32randomZrandnutZar2srK   rL   rP   rM   ZbhatrN   vrQ   rY   Zar23Zma22Zar23nsZvpr   varsrg   rp   rv   rx   Zvp2r   r   r   r   <module>   s   _
4
=
#
s @




	B	


	

	
