U
    md                     @   s  d dl mZmZmZ d dlmZmZ d dlZd dl	m
Z
mZmZmZmZmZmZmZ d dlZd dlZd dlmZ d dlmZ d dlmZmZmZmZ d dlm Z  eejej!ej"f Z#ee$ej%f Z&d	Z'G d
d deZ(G dd de(eZ)G dd de)Z*G dd de(Z+G dd de(eZ,G dd de,Z-G dd de(eZ.G dd de.e,Z/G dd de.Z0G dd de.e)Z1G dd dZ2dS )     )Appenderis_int_indexto_numpy)ABCabstractmethodN)HashableListOptionalSequenceSetTupleTypeUnion)qr)d_or_f)	bool_like
float_likerequired_int_likestring_like)freq_to_periodzstart is less than the first observation in the index. Values can only be created for observations after the start of the index.
c                   @   s  e Zd ZdZdZeedddZee	e
 ejdddZedee	e
 ee	e
  ejd
ddZeedddZedddZeeee
df dddZee	e
 ejdddZedejeee	e
  ejdddZedddZeedddZd	S ) DeterministicTermz/Abstract Base Class for all Deterministic TermsFreturnc                 C   s   | j S )z?Flag indicating whether the values produced are dummy variables)	_is_dummyself r   V/home/sam/Atlas/atlas_env/lib/python3.8/site-packages/statsmodels/tsa/deterministic.pyis_dummy$   s    zDeterministicTerm.is_dummyindexr   c                 C   s   dS )aR  
        Produce deterministic trends for in-sample fitting.

        Parameters
        ----------
        index : index_like
            An index-like object. If not an index, it is converted to an
            index.

        Returns
        -------
        DataFrame
            A DataFrame containing the deterministic terms.
        Nr   r   r    r   r   r   	in_sample)   s    zDeterministicTerm.in_sampleNstepsr    forecast_indexr   c                 C   s   dS )a1  
        Produce deterministic trends for out-of-sample forecasts

        Parameters
        ----------
        steps : int
            The number of steps to forecast
        index : index_like
            An index-like object. If not an index, it is converted to an
            index.
        forecast_index : index_like
            An Index or index-like object to use for the forecasts. If
            provided must have steps elements.

        Returns
        -------
        DataFrame
            A DataFrame containing the deterministic terms.
        Nr   )r   r$   r    r%   r   r   r   out_of_sample:   s    zDeterministicTerm.out_of_samplec                 C   s   dS )z.A meaningful string representation of the termNr   r   r   r   r   __str__U   s    zDeterministicTerm.__str__c                 C   s   t | jf}t|| j S N)type__name__hash_eq_attr)r   namer   r   r   __hash__Y   s    zDeterministicTerm.__hash__.c                 C   s   dS )z9tuple of attributes that are used for equality comparisonNr   r   r   r   r   r,   ]   s    zDeterministicTerm._eq_attrc                 C   s>   t | tjr| S zt| W S  tk
r8   tdY nX d S )Nz*index must be a pandas Index or index-like)
isinstancepdIndex	Exception	TypeErrorr    r   r   r   _index_likeb   s    zDeterministicTerm._index_like)r    r$   r%   r   c           
      C   s  |dk	rPt |}t|tjs"t|jd |krLtd|jd  d| d|S t| tjrvtj	| d d || j
dS t| tjr| j
dk	rtj| d | j
d	d
d }tj|| j
|d
S t| tjrHt| tjstz| j}| j}W nD tk
r*   t| dkr| d | d  nd}| d | }Y nX |||  }tj|||dS t| rtt| dkrt| d d | d | d }t|S ddl}|jdtd	d | jd }	t|	d |	| d S )zExtend the forecast indexNr   z(The number of values in forecast_index (z) must match steps (z).   periodsfreq   r:   r9   stepzOnly PeriodIndexes, DatetimeIndexes with a frequency set, RangesIndexes, and Index with a unit increment support extending. The index is set will contain the position relative to the data length.)
stacklevel)r   r5   r/   r0   r1   AssertionErrorshape
ValueErrorPeriodIndexperiod_ranger:   DatetimeIndex
date_range
RangeIndexr?   stopAttributeErrorlenr   npalldiffarangewarningswarnUserWarning)
r    r$   r%   Znext_obsr?   startrI   Zidx_arrrP   nobsr   r   r   _extend_indexk   sL    

  
"  

zDeterministicTerm._extend_indexc                 C   s   |   dt| d S )Nz at 0x0x)r'   idr   r   r   r   __repr__   s    zDeterministicTerm.__repr__)otherr   c                 C   sN   t |t| rF| j}|j}t|t|kr.dS tdd t||D S dS d S )NFc                 S   s   g | ]\}}||kqS r   r   ).0abr   r   r   
<listcomp>   s     z,DeterministicTerm.__eq__.<locals>.<listcomp>)r/   r)   r,   rK   rM   zip)r   rY   Zown_attrZoth_attrr   r   r   __eq__   s    zDeterministicTerm.__eq__)N)N)r*   
__module____qualname____doc__r   propertyboolr   r   r
   r   r0   	DataFramer"   intr	   r&   strr'   r.   r   r,   staticmethodr1   r5   rU   rX   objectr_   r   r   r   r   r      s@    
 
2r   c                   @   s   e Zd ZdZdeeddddZeedd	d
ZeedddZ	ee
e dddZejejdddZedddZdS )TimeTrendDeterministicTermz:Abstract Base Class for all Time Trend Deterministic TermsTr   Nconstantorderr   c                 C   s   t |d| _t|d| _d S )Nrl   rm   )r   	_constantr   _orderr   rl   rm   r   r   r   __init__   s    z#TimeTrendDeterministicTerm.__init__r   c                 C   s   | j S )z+Flag indicating that a constant is included)rn   r   r   r   r   rl      s    z#TimeTrendDeterministicTerm.constantc                 C   s   | j S )zOrder of the time trendro   r   r   r   r   rm      s    z TimeTrendDeterministicTerm.orderc                 C   sb   g }dddd}| j r |d td| jd D ],}||krL|||  q0|d|  q0|S )NtrendZtrend_squaredZtrend_cubed)r7   r;      constr7   ztrend**)rn   appendrangero   )r   columnsZtrend_namespowerr   r   r   _columns   s    
z#TimeTrendDeterministicTerm._columnslocsr   c                 C   sb   t | j| j }t|d|f}tjd|ft d}td| jd |dt | jd f< ||C }|S )Nr7   Zdtyper   )rf   rn   ro   rL   ZtilezerosrO   )r   r|   Zntermstermsry   r   r   r   
_get_terms   s    $z%TimeTrendDeterministicTerm._get_termsc                 C   sP   g }| j r|d | jr0|d| jd   |s:dg}d|}d| dS )NConstantzPowers 1 to r7   Empty,z
TimeTrend())rn   rv   ro   join)r   r   Z	terms_strr   r   r   r'      s    

z"TimeTrendDeterministicTerm.__str__)Tr   )r*   r`   ra   rb   rd   rf   rq   rc   rl   rm   r   rg   rz   rL   ndarrayr   r'   r   r   r   r   rj      s   rj   c                       s   e Zd ZdZdeedd fddZeed dd	d
Z	e
ejjeee ejf ejdddZe
ejjdeeee ejf eee  ejdddZeeedf dddZ  ZS )	TimeTrendao  
    Constant and time trend determinstic terms

    Parameters
    ----------
    constant : bool
        Flag indicating whether a constant should be included.
    order : int
        A non-negative int containing the powers to include (1, 2, ..., order).

    See Also
    --------
    DeterministicProcess
    Seasonality
    Fourier
    CalendarTimeTrend

    Examples
    --------
    >>> from statsmodels.datasets import sunspots
    >>> from statsmodels.tsa.deterministic import TimeTrend
    >>> data = sunspots.load_pandas().data
    >>> trend_gen = TimeTrend(True, 3)
    >>> trend_gen.in_sample(data.index)
    Tr   Nrk   c                    s   t  || d S r(   )superrq   rp   	__class__r   r   rq      s    zTimeTrend.__init__)rs   r   c                 C   s4   | d}d}d|krd}nd|kr(d}| ||dS )aY  
        Create a TimeTrend from a string description.

        Provided for compatibility with common string names.

        Parameters
        ----------
        trend : {"n", "c", "t", "ct", "ctt"}
            The string representation of the time trend. The terms are:

            * "n": No trend terms
            * "c": A constant only
            * "t": Linear time trend only
            * "ct": A constant and a time trend
            * "ctt": A constant, a time trend and a quadratic time trend

        Returns
        -------
        TimeTrend
            The TimeTrend instance.
        cr   ttr;   tr7   rl   rm   
startswith)clsrs   rl   rm   r   r   r   from_string   s    
zTimeTrend.from_stringr   c                 C   sR   |  |}|jd }tjd|d tjdd d d f }| |}tj|| j|dS Nr   r7   r}   rx   r    )	r5   rB   rL   rO   doubler   r0   re   rz   )r   r    rT   r|   r   r   r   r   r"     s
    

"
zTimeTrend.in_sampler#   c                 C   sh   |  |}|jd }| |||}tj|d || d tjdd d d f }| |}tj|| j	|dS r   )
r5   rB   rU   rL   rO   r   r   r0   re   rz   )r   r$   r    r%   rT   fcast_indexr|   r   r   r   r   r&   %  s    

*
zTimeTrend.out_of_sample.r   c                 C   s   | j | jfS r(   )rn   ro   r   r   r   r   r,   3  s    zTimeTrend._eq_attr)Tr   )N)r*   r`   ra   rb   rd   rf   rq   classmethodrg   r   r   r   r"   r   r
   r   r0   r1   re   r&   r	   rc   r   r,   __classcell__r   r   r   r   r      s$   
	
 
r   c                   @   s  e Zd ZdZdZdeeddddZeedd	d
ZeedddZ	e
eee ejejf d dddZeeedf dddZedddZeee dddZeejjeee ejf ejdddZeejjdeeee ejf eee  ejdddZdS )Seasonalitya   
    Seasonal dummy deterministic terms

    Parameters
    ----------
    period : int
        The length of a full cycle. Must be >= 2.
    initial_period : int
        The seasonal index of the first observation. 1-indexed so must
        be in {1, 2, ..., period}.

    See Also
    --------
    DeterministicProcess
    TimeTrend
    Fourier
    CalendarSeasonality

    Examples
    --------
    Solar data has an 11-year cycle

    >>> from statsmodels.datasets import sunspots
    >>> from statsmodels.tsa.deterministic import Seasonality
    >>> data = sunspots.load_pandas().data
    >>> seas_gen = Seasonality(11)
    >>> seas_gen.in_sample(data.index)

    To start at a season other than 1

    >>> seas_gen = Seasonality(11, initial_period=4)
    >>> seas_gen.in_sample(data.index)
    Tr7   N)periodinitial_periodr   c                 C   sL   t |d| _t |d| _|dk r(tdd| j  kr>|ksHn tdd S )Nr   r   r;   zperiod must be >= 2r7   z-initial_period must be in {1, 2, ..., period})r   _period_initial_periodrC   )r   r   r   r   r   r   rq   ]  s     zSeasonality.__init__r   c                 C   s   | j S )zThe period of the seasonalityr   r   r   r   r   r   g  s    zSeasonality.periodc                 C   s   | j S )z+The seasonal index of the first observation)r   r   r   r   r   r   l  s    zSeasonality.initial_periodr   c                 C   sh   |  |}t|tjr|j}n(t|tjr>|jr6|jn|j}ntd|dkrVtdt	|}| |dS )aF  
        Construct a seasonality directly from an index using its frequency.

        Parameters
        ----------
        index : {DatetimeIndex, PeriodIndex}
            An index with its frequency (`freq`) set.

        Returns
        -------
        Seasonality
            The initialized Seasonality instance.
        z,index must be a DatetimeIndex or PeriodIndexNz+index must have a freq or inferred_freq set)r   )
r5   r/   r0   rD   r:   rF   inferred_freqr3   rC   r   )r   r    r:   r   r   r   r   
from_indexq  s    
zSeasonality.from_index.c                 C   s   | j | jfS r(   )r   r   r   r   r   r   r,     s    zSeasonality._eq_attrc                 C   s   d| j  dS )NzSeasonality(period=r   r   r   r   r   r   r'     s    zSeasonality.__str__c                 C   s:   | j }g }td|d D ]}|d| d| d q|S )Nr7   s(r   r   )r   rw   rv   )r   r   rx   ir   r   r   rz     s
    zSeasonality._columnsc                 C   sp   |  |}|jd }| j}t||f}| jd }t|D ]"}|| | }d||d ||f< q:tj|| j	|dS Nr   r7   r   )
r5   rB   r   rL   r~   r   rw   r0   re   rz   )r   r    rT   r   termoffsetr   colr   r   r   r"     s    


zSeasonality.in_sampler#   c                 C   s   |  |}| |||}|jd }| j}t||f}| jd }t|D ]&}	|| |	 | }
d||	d ||
f< qHtj	|| j
|dS r   )r5   rU   rB   r   rL   r~   r   rw   r0   re   rz   )r   r$   r    r%   r   rT   r   r   r   r   Zcol_locr   r   r   r&     s    


zSeasonality.out_of_sample)r7   )N)r*   r`   ra   rb   r   rf   rq   rc   r   r   r   r   r
   r   r0   rF   rD   r   r   r,   rg   r'   r   rz   r   r   r"   r1   re   r&   r	   r   r   r   r   r   8  s8   "


 
r   c                   @   sF   e Zd ZdZeddddZeedddZej	ej	d	d
dZ
dS )FourierDeterministicTermz7Abstract Base Class for all Fourier Deterministic TermsN)rm   r   c                 C   s   t |d| _d S Nr   )r   ro   )r   rm   r   r   r   rq     s    z!FourierDeterministicTerm.__init__r   c                 C   s   | j S )z'The order of the Fourier terms includedrr   r   r   r   r   rm     s    zFourierDeterministicTerm.orderr{   c                 C   s   dt j |t j }t |jd d| j f}t| jD ]B}tt j	t j
fD ],\}}||d | |d d d| | f< qNq:|S )Nr;   r   r7   )rL   piastyper   emptyrB   ro   rw   	enumeratesincos)r   r|   r   r   jfuncr   r   r   r     s    (z#FourierDeterministicTerm._get_terms)r*   r`   ra   rb   rf   rq   rc   rm   rL   r   r   r   r   r   r   r     s
   r   c                       s   e Zd ZdZdZeed fddZeedddZ	ee
e dd	d
Zeejjeee ejf ejdddZeejjdeeee ejf eee  ejdddZeeedf dddZedddZ  ZS )Fouriera  
    Fourier series deterministic terms

    Parameters
    ----------
    period : int
        The length of a full cycle. Must be >= 2.
    order : int
        The number of Fourier components to include. Must be <= 2*period.

    See Also
    --------
    DeterministicProcess
    TimeTrend
    Seasonality
    CalendarFourier

    Notes
    -----
    Both a sine and a cosine term are included for each i=1, ..., order

    .. math::

       f_{i,s,t} & = \sin\left(2 \pi i \times \frac{t}{m} \right)  \\
       f_{i,c,t} & = \cos\left(2 \pi i \times \frac{t}{m} \right)

    where m is the length of the period.

    Examples
    --------
    Solar data has an 11-year cycle

    >>> from statsmodels.datasets import sunspots
    >>> from statsmodels.tsa.deterministic import Fourier
    >>> data = sunspots.load_pandas().data
    >>> fourier_gen = Fourier(11, order=2)
    >>> fourier_gen.in_sample(data.index)
    F)r   rm   c                    s4   t  | t|d| _d| j | jkr0tdd S )Nr   r;   z2 * order must be <= period)r   rq   r   r   ro   rC   )r   r   rm   r   r   r   rq     s    zFourier.__init__r   c                 C   s   | j S )zThe period of the Fourier termsr   r   r   r   r   r     s    zFourier.periodc              
   C   sV   | j }t| }g }td| jd D ]*}dD ] }|| d| d| d q.q&|S )Nr7   r   r   (r   r   )r   r   striprw   ro   rv   )r   r   Z
fmt_periodrx   r   typr   r   r   rz     s     zFourier._columnsr   c                 C   s<   |  |}|jd }| t|| j }tj||| jdS Nr   r    rx   )	r5   rB   r   rL   rO   r   r0   re   rz   )r   r    rT   r   r   r   r   r"     s    

zFourier.in_sampleNr#   c                 C   sP   |  |}| |||}|jd }| t||| | j }tj||| j	dS r   )
r5   rU   rB   r   rL   rO   r   r0   re   rz   )r   r$   r    r%   r   rT   r   r   r   r   r&     s
    

zFourier.out_of_sample.c                 C   s   | j | jfS r(   r   ro   r   r   r   r   r,   &  s    zFourier._eq_attrc                 C   s   d| j  d| j dS )NzFourier(period=, order=r   r   r   r   r   r   r'   *  s    zFourier.__str__)N)r*   r`   ra   rb   r   floatrf   rq   rc   r   r   rg   rz   r   r   r"   r   r
   r   r0   r1   re   r&   r	   r   r,   r'   r   r   r   r   r   r     s,   &	

 
r   c                   @   s   e Zd ZdZeddddZeedddZee	j
e	jf ejd	d
dZe	j
e	jffe	jeeeedf f ee	j
e	jf dddZdS )CalendarDeterministicTermz4Abstract Base Class for calendar deterministic termsN)r:   r   c                 C   s>   zt jd|dd}|j| _W n tk
r8   tdY nX d S )Nz
2020-01-01r7   r<   z freq is not understood by pandas)r0   rG   r:   _freqrC   )r   r:   r    r   r   r   rq   1  s
    z"CalendarDeterministicTerm.__init__r   c                 C   s   | j jS z(The frequency of the deterministic termsr   freqstrr   r   r   r   r:   8  s    zCalendarDeterministicTerm.freqr   c                 C   sX   t |tjr| }||| j  }|| j}|d  |  }t|t| S )Nr7   )r/   r0   rD   to_timestamp	to_periodr   r   )r   r    deltar   gapr   r   r   _compute_ratio=  s    z(CalendarDeterministicTerm._compute_ratio.)r    allowedr   c                 C   s   t |tr|f}t ||st|dkr6d|d j }nBddd |d d D }t|dkrf|d	7 }|d
|d j 7 }t| j d| }t|t |tjtjfst	|S )Nr7   za r   z, c                 s   s   | ]}|j V  qd S r(   )r*   )rZ   r[   r   r   r   	<genexpr>U  s     z>CalendarDeterministicTerm._check_index_type.<locals>.<genexpr>r6   r;   r   z and z! terms can only be computed from )
r/   r)   rK   r*   r   r3   r0   rF   rD   rA   )r   r    r   Zallowed_typesmsgr   r   r   _check_index_typeG  s    

z+CalendarDeterministicTerm._check_index_type)r*   r`   ra   rb   rg   rq   rc   r:   r   r0   rF   rD   rL   r   r   r1   r   r   r   r   r   r   r   r   .  s   r   c                       s   e Zd ZdZeedd fddZeee dddZ	e
ejjeee ejf ejd	d
dZe
ejjdeeee ejf eee  ejdddZeeedf dddZedddZ  ZS )CalendarFouriera  
    Fourier series deterministic terms based on calendar time

    Parameters
    ----------
    freq : str
        A string convertible to a pandas frequency.
    order : int
        The number of Fourier components to include. Must be <= 2*period.

    See Also
    --------
    DeterministicProcess
    CalendarTimeTrend
    CalendarSeasonality
    Fourier

    Notes
    -----
    Both a sine and a cosine term are included for each i=1, ..., order

    .. math::

       f_{i,s,t} & = \sin\left(2 \pi i \tau_t \right)  \\
       f_{i,c,t} & = \cos\left(2 \pi i \tau_t \right)

    where m is the length of the period and :math:`\tau_t` is the frequency
    normalized time.  For example, when freq is "D" then an observation with
    a timestamp of 12:00:00 would have :math:`\tau_t=0.5`.

    Examples
    --------
    Here we simulate irregularly spaced hourly data and construct the calendar
    Fourier terms for the data.

    >>> import numpy as np
    >>> import pandas as pd
    >>> base = pd.Timestamp("2020-1-1")
    >>> gen = np.random.default_rng()
    >>> gaps = np.cumsum(gen.integers(0, 1800, size=1000))
    >>> times = [base + pd.Timedelta(gap, unit="s") for gap in gaps]
    >>> index = pd.DatetimeIndex(pd.to_datetime(times))

    >>> from statsmodels.tsa.deterministic import CalendarFourier
    >>> cal_fourier_gen = CalendarFourier("D", 2)
    >>> cal_fourier_gen.in_sample(index)
    N)r:   rm   r   c                    s(   t  | t| | t|d| _d S r   )r   rq   r   r   ro   )r   r:   rm   r   r   r   rq     s    zCalendarFourier.__init__r   c              
   C   sH   g }t d| jd D ].}dD ]$}|| d| d| jj d qq|S )Nr7   r   r   z,freq=r   )rw   ro   rv   r   r   )r   rx   r   r   r   r   r   rz     s
    $zCalendarFourier._columnsr   c                 C   s:   |  |}| |}| |}| |}tj||| jdS Nr   )r5   r   r   r   r0   re   rz   )r   r    ratior   r   r   r   r"     s
    



zCalendarFourier.in_sampler#   c                 C   s^   |  |}| |||}| | t|tjtjfs8t| |}| 	|}tj
||| jdS r   )r5   rU   r   r/   r0   rF   rD   rA   r   r   re   rz   )r   r$   r    r%   r   r   r   r   r   r   r&     s    



zCalendarFourier.out_of_sample.c                 C   s   | j j| jfS r(   r   r   ro   r   r   r   r   r,     s    zCalendarFourier._eq_attrc                 C   s   d| j j d| j dS )NzFourier(freq=r   r   r   r   r   r   r   r'     s    zCalendarFourier.__str__)N)r*   r`   ra   rb   rg   rf   rq   rc   r   rz   r   r   r"   r   r
   r   r0   r1   re   r&   r	   r   r,   r'   r   r   r   r   r   r   b  s&   0


 
r   c                       s  e Zd ZdZdZddddddid	d
iddddZeedd fddZeedddZ	eedddZ
eejejf ejdddZeejejf ejdddZeejejf ejdddZeejejf ejddd Zeejejf ejdd!d"Zeee dd#d$Zeejjeee ejf ejdd%d&Zeejjd/e eee ejf e!ee  ejd'd(d)Zee"ed*f dd+d,Z#edd-d.Z$  Z%S )0CalendarSeasonalitya  
    Seasonal dummy deterministic terms based on calendar time

    Parameters
    ----------
    freq : str
        The frequency of the seasonal effect.
    period : str
        The pandas frequency string describing the full period.

    See Also
    --------
    DeterministicProcess
    CalendarTimeTrend
    CalendarFourier
    Seasonality

    Examples
    --------
    Here we simulate irregularly spaced data (in time) and hourly seasonal
    dummies for the data.

    >>> import numpy as np
    >>> import pandas as pd
    >>> base = pd.Timestamp("2020-1-1")
    >>> gen = np.random.default_rng()
    >>> gaps = np.cumsum(gen.integers(0, 1800, size=1000))
    >>> times = [base + pd.Timedelta(gap, unit="s") for gap in gaps]
    >>> index = pd.DatetimeIndex(pd.to_datetime(times))

    >>> from statsmodels.tsa.deterministic import CalendarSeasonality
    >>> cal_seas_gen = CalendarSeasonality("H", "D")
    >>> cal_seas_gen.in_sample(index)
    T         )HBDr      Mrt         )r   Q)Wr   r   AN)r:   r   r   c                    s   t  }|jdd | j D   t| j }t|dt|dd}t|d|dd}|| j| krvtd| d| d	t	 
| || _| jjd
d | _d S )Nc                 S   s   g | ]}t | qS r   )listkeys)rZ   valr   r   r   r]     s     z0CalendarSeasonality.__init__.<locals>.<listcomp>r:   F)optionslowerr   zThe combination of freq=z and period=z is not supported.-r   )setupdate
_supportedvaluesr   r   r   tuplerC   r   rq   r   r   r   split	_freq_str)r   r:   r   Zfreq_optionsZperiod_optionsr   r   r   rq     s0          zCalendarSeasonality.__init__r   c                 C   s   | j jS r   r   r   r   r   r   r:     s    zCalendarSeasonality.freqc                 C   s   | j S )zThe full periodr   r   r   r   r   r     s    zCalendarSeasonality.periodr   c                 C   sf   | j jdkr|jd|j  S | j jdkr.|jS tjdddj }|j}|| s^t	d|S d S )Nr   r   r   z2000-1-1
   )r9   z=freq is B but index contains days that are not business days.)
r   r   hourZ	dayofweekr0   Zbdate_rangeuniqueisinrM   rC   )r   r    Zbdayslocr   r   r   _weekly_to_loc  s    z"CalendarSeasonality._weekly_to_locc                 C   s   |j S r(   )r   r!   r   r   r   _daily_to_loc!  s    z!CalendarSeasonality._daily_to_locc                 C   s   |j d d S )Nr7   rt   )monthr!   r   r   r   _quarterly_to_loc&  s    z%CalendarSeasonality._quarterly_to_locc                 C   s$   | j jdkr|jd S |jd S d S )Nr   r7   )r   r   r   Zquarterr!   r   r   r   _annual_to_loc+  s    
z"CalendarSeasonality._annual_to_locc                 C   s   | j dkr| |}n6| j dkr,| |}n | j dkrB| |}n
| |}| j| j  | j }t|j	d |f}d|t
|j	d |f< |S )Nr   r   r   r   r7   )r   r   r   r   r   r   r   rL   r~   rB   rO   )r   r    r|   Z
full_cycler   r   r   r   r   3  s    



zCalendarSeasonality._get_termsc              
   C   sN   g }| j | j | j }t|D ]*}|d| j d|d  d| j d q|S )Nr   =r7   z	, period=r   )r   r   r   rw   rv   )r   rx   countr   r   r   r   rz   C  s    zCalendarSeasonality._columnsc                 C   s0   |  |}| |}| |}tj||| jdS r   )r5   r   r   r0   re   rz   )r   r    r   r   r   r   r"   M  s    


zCalendarSeasonality.in_sampler#   c                 C   sT   |  |}| |||}| | t|tjtjfs8t| |}tj	||| j
dS r   )r5   rU   r   r/   r0   rF   rD   rA   r   re   rz   )r   r$   r    r%   r   r   r   r   r   r&   W  s    


z!CalendarSeasonality.out_of_sample.c                 C   s   | j | jfS r(   )r   r   r   r   r   r   r,   e  s    zCalendarSeasonality._eq_attrc                 C   s   d| j  dS )NzSeasonal(freq=r   )r   r   r   r   r   r'   i  s    zCalendarSeasonality.__str__)N)&r*   r`   ra   rb   r   r   rg   rq   rc   r:   r   r   r0   rF   rD   rL   r   r   r   r   r   r   r   rz   r   r   r"   r
   r   r1   re   r&   rf   r	   r   r,   r'   r   r   r   r   r   r     sX   #
		
	
 
r   c                	       s.  e Zd ZdZdddeeeeeee	f  dd fddZ
eee d	d
dZedeeeeee	f  d dddZeejejf ejejdddZeejjeee ejf ejdddZeejjdeeee ejf eee  ejdddZeeedf d	ddZed	ddZ  Z S ) CalendarTimeTrenda
  
    Constant and time trend determinstic terms based on calendar time

    Parameters
    ----------
    freq : str
        A string convertible to a pandas frequency.
    constant : bool
        Flag indicating whether a constant should be included.
    order : int
        A non-negative int containing the powers to include (1, 2, ..., order).
    base_period : {str, pd.Timestamp}, default None
        The base period to use when computing the time stamps. This value is
        treated as 1 and so all other time indices are defined as the number
        of periods since or before this time stamp. If not provided, defaults
        to pandas base period for a PeriodIndex.

    See Also
    --------
    DeterministicProcess
    CalendarFourier
    CalendarSeasonality
    TimeTrend

    Notes
    -----
    The time stamp, :math:`\tau_t`, is the number of periods that have elapsed
    since the base_period. :math:`\tau_t` may be fractional.

    Examples
    --------
    Here we simulate irregularly spaced hourly data and construct the calendar
    time trend terms for the data.

    >>> import numpy as np
    >>> import pandas as pd
    >>> base = pd.Timestamp("2020-1-1")
    >>> gen = np.random.default_rng()
    >>> gaps = np.cumsum(gen.integers(0, 1800, size=1000))
    >>> times = [base + pd.Timedelta(gap, unit="s") for gap in gaps]
    >>> index = pd.DatetimeIndex(pd.to_datetime(times))

    >>> from statsmodels.tsa.deterministic import CalendarTimeTrend
    >>> cal_trend_gen = CalendarTimeTrend("D", True, order=1)
    >>> cal_trend_gen.in_sample(index)

    Next, we normalize using the first time stamp

    >>> cal_trend_gen = CalendarTimeTrend("D", True, order=1,
    ...                                   base_period=index[0])
    >>> cal_trend_gen.in_sample(index)
    Tr   Nbase_period)r:   rl   rm   r   r   c                   sb   t  | tj| ||d d| _|d k	rHtj|d| jd}|jd | _|d krTd nt|| _	d S )Nr   r   r7   r8   )
r   rq   rj   _ref_i8r0   rE   r   asi8rg   _base_period)r   r:   rl   rm   r   prr   r   r   rq     s      zCalendarTimeTrend.__init__r   c                 C   s   | j S )zThe base period)r   r   r   r   r   r     s    zCalendarTimeTrend.base_period)r:   rs   r   r   c                 C   s8   | d}d}d|krd}nd|kr(d}| ||||dS )a  
        Create a TimeTrend from a string description.

        Provided for compatibility with common string names.

        Parameters
        ----------
        freq : str
            A string convertible to a pandas frequency.
        trend : {"n", "c", "t", "ct", "ctt"}
            The string representation of the time trend. The terms are:

            * "n": No trend terms
            * "c": A constant only
            * "t": Linear time trend only
            * "ct": A constant and a time trend
            * "ctt": A constant, a time trend and a quadratic time trend
        base_period : {str, pd.Timestamp}, default None
            The base period to use when computing the time stamps. This value
            is treated as 1 and so all other time indices are defined as the
            number of periods since or before this time stamp. If not
            provided, defaults to pandas base period for a PeriodIndex.

        Returns
        -------
        TimeTrend
            The TimeTrend instance.
        r   r   r   r;   r   r7   r   r   )r   r:   rs   r   rl   rm   r   r   r   r     s    #
zCalendarTimeTrend.from_string)r    r   r   c                 C   sh   t |tjr|| j}|j}|| j d }|tj	| }|d d d f }| 
|}tj|| j|dS )Nr7   r   )r/   r0   rF   r   r   r   r   r   rL   r   r   re   rz   )r   r    r   Zindex_i8timer   r   r   r   _terms  s    
zCalendarTimeTrend._termsr   c                 C   s*   |  |}| |}| |}| ||S r(   )r5   r   r   r   )r   r    r   r   r   r   r"     s    


zCalendarTimeTrend.in_sampler#   c                 C   sN   |  |}| |||}| | t|tjtjfs8t| |}| 	||S r(   )
r5   rU   r   r/   r0   rD   rF   rA   r   r   )r   r$   r    r%   r   r   r   r   r   r&     s    


zCalendarTimeTrend.out_of_sample.c                 C   s,   | j | j| jjf}| jd k	r(|| jf7 }|S r(   )rn   ro   r   r   r   )r   attrr   r   r   r,   	  s    
zCalendarTimeTrend._eq_attrc                 C   sR   t | }d|d d  d| jj d }| jd k	rN|d d d| j d }|S )NCalendarr6   z, freq=r   zbase_period=)rj   r'   r   r   r   )r   valuer   r   r   r'     s
    
 
zCalendarTimeTrend.__str__)Tr   )N)N)!r*   r`   ra   rb   rg   rd   rf   r	   r   DateLikerq   rc   r   r   r   r0   rF   rD   rL   r   re   r   r   r   r"   r
   r   r1   r&   r   r,   r'   r   r   r   r   r   r   m  sR   8   + 

 

r   c                
   @   s  e Zd ZdZddddddddeee ejf e	ee
ef  eeeeee eddd	Zeejd
ddZeee d
ddZeej eej dddZejejdddZeejjejd
ddZeejjd*ee	eee ejf  ejdddZejeejejf dddZeeejdddZejejejddd Zeeejd!d"d#Z ee!e"ef ee!e"ef ejdd$d%Z#dd
d&d'Z$d(d) Z%dS )+DeterministicProcessa  
    Container class for deterministic terms.

    Directly supports constants, time trends, and either seasonal dummies or
    fourier terms for a single cycle. Additional deterministic terms beyond
    the set that can be directly initialized through the constructor can be
    added.

    Parameters
    ----------
    index : {Sequence[Hashable], pd.Index}
        The index of the process. Should usually be the "in-sample" index when
        used in forecasting applications.
    period : {float, int}, default None
        The period of the seasonal or fourier components. Must be an int for
        seasonal dummies. If not provided, freq is read from index if
        available.
    constant : bool, default False
        Whether to include a constant.
    order : int, default 0
        The order of the tim trend to include. For example, 2 will include
        both linear and quadratic terms. 0 exclude time trend terms.
    seasonal : bool = False
        Whether to include seasonal dummies
    fourier : int = 0
        The order of the fourier terms to included.
    additional_terms : Sequence[DeterministicTerm]
        A sequence of additional deterministic terms to include in the process.
    drop : bool, default False
        A flag indicating to check for perfect collinearity and to drop any
        linearly dependent terms.

    See Also
    --------
    TimeTrend
    Seasonality
    Fourier
    CalendarTimeTrend
    CalendarSeasonality
    CalendarFourier

    Notes
    -----
    See the notebook `Deterministic Terms in Time Series Models
    <../examples/notebooks/generated/deterministics.html>`__ for an overview.

    Examples
    --------
    >>> from statsmodels.tsa.deterministic import DeterministicProcess
    >>> from pandas import date_range
    >>> index = date_range("2000-1-1", freq="M", periods=240)

    First a determinstic process with a constant and quadratic time trend.

    >>> dp = DeterministicProcess(index, constant=True, order=2)
    >>> dp.in_sample().head(3)
                const  trend  trend_squared
    2000-01-31    1.0    1.0            1.0
    2000-02-29    1.0    2.0            4.0
    2000-03-31    1.0    3.0            9.0

    Seasonal dummies are included by setting seasonal to True.

    >>> dp = DeterministicProcess(index, constant=True, seasonal=True)
    >>> dp.in_sample().iloc[:3,:5]
                const  s(2,12)  s(3,12)  s(4,12)  s(5,12)
    2000-01-31    1.0      0.0      0.0      0.0      0.0
    2000-02-29    1.0      1.0      0.0      0.0      0.0
    2000-03-31    1.0      0.0      1.0      0.0      0.0

    Fourier components can be used to alternatively capture seasonal patterns,

    >>> dp = DeterministicProcess(index, constant=True, fourier=2)
    >>> dp.in_sample().head(3)
                const  sin(1,12)  cos(1,12)  sin(2,12)  cos(2,12)
    2000-01-31    1.0   0.000000   1.000000   0.000000        1.0
    2000-02-29    1.0   0.500000   0.866025   0.866025        0.5
    2000-03-31    1.0   0.866025   0.500000   0.866025       -0.5

    Multiple Seasonalities can be captured using additional terms.

    >>> from statsmodels.tsa.deterministic import Fourier
    >>> index = date_range("2000-1-1", freq="D", periods=5000)
    >>> fourier = Fourier(period=365.25, order=1)
    >>> dp = DeterministicProcess(index, period=3, constant=True,
    ...                           seasonal=True, additional_terms=[fourier])
    >>> dp.in_sample().head(3)
                const  s(2,3)  s(3,3)  sin(1,365.25)  cos(1,365.25)
    2000-01-01    1.0     0.0     0.0       0.000000       1.000000
    2000-01-02    1.0     1.0     0.0       0.017202       0.999852
    2000-01-03    1.0     0.0     1.0       0.034398       0.999408
    NFr   r   r   rl   rm   seasonalfourieradditional_termsdrop)r    r   rl   rm   r  r  r  r  c          
      C   s  t |tjst|}|| _g | _d| _d | _|   t|ddd}t	|d | _
}t|d| _t	|d | _}t|d| _t|}d | _t	|d	| _|| _|s|r| jt|| |r|rtd
|s|r|d kr|d krt| j | _}|rt|d}| jt| n2|rBt|d}|d k	s.t| jt||d |D ]<}	t |	ts^td|	| jkrx| j|	 ntdqF|| _d | _d S )NFr   T)optionalrl   rm   r  r  r  zseasonal and fourier can be initialized through the constructor since these will be necessarily perfectly collinear. Instead, you can pass additional components using the additional_terms input.)rm   zJAll additional terms must be instances of subsclasses of DeterministicTermzuOne or more terms in additional_terms has been added through the parameters of the constructor. Terms must be unique.)r/   r0   r1   _index_deterministic_terms_extendable_index_freq_validate_indexr   r   rn   r   ro   	_seasonal_fourierr   _cached_in_sample_drop_additional_termsrv   r   rC   r   r   r   rA   r   r   r3   _retain_cols)
r   r    r   rl   rm   r  r  r  r  r   r   r   r   rq   z  sX    


zDeterministicProcess.__init__r   c                 C   s   | j S )zThe index of the process)r  r   r   r   r   r      s    zDeterministicProcess.indexc                 C   s   | j S )z/The deterministic terms included in the process)r	  r   r   r   r   r     s    zDeterministicProcess.terms)r   r   c           	      C   s   d }| j D ]}t|ttfr
|p$|j}q
|d krjd}|D ]0}||jd k |jd dk@ }|pf| }q8|}t| j D ]<\}}|j	}|r|r|| jd d dd f ||< |p|}qx|S )NFr   r7   )
r	  r/   r   r   rl   ilocrM   anyr   r   )	r   r   Z	has_constZdtermr   Z	const_colZ
drop_firstr   r   r   r   r   _adjust_dummies  s     
 
z$DeterministicProcess._adjust_dummiesc                 C   s   t j|dkdd}t |r0|jd d | f }|jdd|jddk}t |dkrt |d }d||d d < |jd d | f }|S )Nr   Zaxisr7   F)rL   rM   r  r   maxminsumwhere)r   r   Zall_zeroZis_constantZ
const_locsr   r   r   _remove_zeros_ones  s    
z'DeterministicProcess._remove_zeros_onesc                 C   s  | j d k	r| j S | j}| js:tjt|jd df|dS g }| jD ]}||	| qD| 
|}tj|dd}| |}| jrt|}t|ddd}|d }|d }tt|}	|	d |jd  ttj }
tt|	|
k}|j| }dg}d}td|jd D ]R}tj|d |d d |d f }||krN|| |}||kr qbqt||kr|jd d |f }n |jd d t|d | f }|j| _|| _ |S )	Nr   r4   r7   r  rT)modeZpivotingr6   ) r  r  r	  r0   re   rL   r   rB   rv   r"   r  concatr  r  r   r   absZdiagZfinfor   Zepsrf   r  Trw   ZlinalgZmatrix_rankrK   r  sortrx   r  )r   r    	raw_termsr   r   Z	terms_arrresr  pZabs_diagZtolZrankZrpxZkeepZ	last_rankr   Z	curr_rankr   r   r   r"     sF    




$



 zDeterministicProcess.in_sample)r$   r%   r   c                 C   s   t |d}| jr"| jd kr"|   | j}| jsLtjt	|j
d df|dS g }| jD ]}||||| qVtj|dd}| jd k	st|j
d t| jkr|| j }|S )Nr$   r   r4   r7   r  )r   r  r  r"   r  r	  r0   re   rL   r   rB   rv   r&   r  rA   rK   )r   r$   r%   r    r"  r   r   r   r   r   r&     s    


z"DeterministicProcess.out_of_sample)rI   r   c                 C   s>   | j }t|tjr(tj|d ||jdS tj|d || jdS )Nr   )endr:   )rS   r%  r:   )r  r/   r0   rD   rE   r:   rG   r  )r   rI   r    r   r   r   _extend_time_index   s    z'DeterministicProcess._extend_time_index)rS   rI   r   c                 C   s  | j }t|}t|tjs"|s"t||d k r6ttt|tjrJ|j}nt	|dkrdt
| nd}|dkr||d  | dkrtd| d|rtt
||}ntj|||d}|d | j d kr|  }|j| }|S |d | j d krT|d | }|d |kr@tj|||d}	| j|	jd |	d}
|
j| S | j|jd |dS || j d k}|| }||  }|  j| }| j|jd |d}tj||gdd	S )
Nr   r7   z,The step of the index is not 1 (actual step=zM). start must be in the sequence that would have been generated by the index.r>   r6   )r%   )r$   r%   r  )r  r   r/   r0   rH   rA   rC   START_BEFORE_INDEX_ERRr?   rK   rL   rN   r  r1   rO   r"   r   r&   rB   r  )r   rS   rI   r    Zis_int64_indexZidx_stepnew_idxr"   Z
next_valuetmpoosZin_sample_locZin_sample_idxZout_of_sample_idxZin_sample_exogZoos_exogr   r   r   _range_from_range_index)  sF    



 z,DeterministicProcess._range_from_range_indexc                 C   s   | j }t| j tjrHt|tjr.|j| jd}t|tjrH|j| jd}||d k r\tt|| j d kr|| 	 j
|| S | |}|||d k }| |jd |}||d kr|j
|| S tj| 	 |gdd}|j
|| S )N)r:   r   r6   r  )r  r/   r0   rD   	Timestampr   r  rC   r'  r"   r   r&  r&   rB   r  )r   rS   rI   r    r(  Zoos_idxr*  Zbothr   r   r   _range_from_time_indexT  s"    
z+DeterministicProcess._range_from_time_index)r   r-   r   c                 C   s   |dk rt | d|| jjd k r0| j| S || jjd d  d }| j}t| jtjr~tj|d | j|d}|d  S tj	|d | j|d}|d S )Nr   z must be non-negative.r7   r6   r<   )
rC   r  rB   r/   r0   rD   rE   r  r   rG   )r   r   r-   Zadd_periodsr    r   Zdrr   r   r   _int_to_timestampi  s&    
    z&DeterministicProcess._int_to_timestampc                 C   s   | j stdt| jtjfks*t| jrRt|d}t|d}|d7 }| ||S t	|t
tjfrp| |d}n
t|}t	|t
tjfr| |d}n
t|}| ||S )a  
        Deterministic terms spanning a range of observations

        Parameters
        ----------
        start : {int, str, dt.datetime, pd.Timestamp, np.datetime64}
            The first observation.
        stop : {int, str, dt.datetime, pd.Timestamp, np.datetime64}
            The final observation. Inclusive to match most prediction
            function in statsmodels.

        Returns
        -------
        DataFrame
            A data frame of deterministic terms
        zThe index in the deterministic process does not support extension. Only PeriodIndex, DatetimeIndex with a frequency, RangeIndex, and integral Indexes that start at 0 and have only unit differences can be extended when producing out-of-sample forecasts.
rS   rI   r7   )r
  r3   r)   r  r0   rH   r   r   r+  r/   rf   rL   integerr.  r,  r-  )r   rS   rI   r   r   r   rw   z  s     



zDeterministicProcess.rangec                 C   s   t | jtjr | jj| _d| _ntt | jtjrN| jjp<| jj| _| jd k	| _nFt | jtj	rdd| _n0t
| jr| jd dkott| jdk| _d S )NTr   r7   )r/   r  r0   rD   r:   r  r
  rF   r   rH   r   rL   rM   rN   r   r   r   r   r    s    

z$DeterministicProcess._validate_indexc              
   C   s&   t || j| j| j| j| j| j| jdS )ap  
        Create an identical determinstic process with a different index

        Parameters
        ----------
        index : index_like
            An index-like object. If not an index, it is converted to an
            index.

        Returns
        -------
        DeterministicProcess
            The deterministic process applied to a different index
        r  )r  r   rn   ro   r  r  r  r  r!   r   r   r   apply  s    zDeterministicProcess.apply)N)&r*   r`   ra   rb   r   r
   r   r0   r1   r	   r   rf   rd   r   rq   rc   r    r   r   re   r  r  r   r"   r&   r,  rF   rD   r&  r+  r-  rg   r.  IntLiker   rw   r  r0  r   r   r   r   r    s`   a?
(
 	, -r  )3Zstatsmodels.compat.pandasr   r   r   abcr   r   datetimedttypingr   r   r	   r
   r   r   r   r   numpyrL   Zpandasr0   Zscipy.linalgr   Zstatsmodels.iolib.summaryr   Zstatsmodels.tools.validationr   r   r   r   Zstatsmodels.tsa.tsatoolsr   r,  Z
datetime64r   rf   r/  r1  r'  r   rj   r   r   r   r   r   r   r   r   r  r   r   r   r   <module>   s6   ( 2Z \4` , 0