B
    W0dr                 @  s  d dl mZ d dlZd dlmZ d dlmZ d dlZd dlZ	d dl
mZ d dlm  m  mZ d dlmZmZmZmZ d dlmZ d dlmZ d d	lmZ d d
lmZ d dlm   m!Z! d dl"m#Z# d dl$m%Z% d dl&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/ d dl0m1Z1m2Z2m3Z3 d dl4m5Z5 d dl6m7Z7m8Z8 d dl9m:Z:m;Z; ddddddddZ<ddddddZ=G dd de:Z>G dd  d e;e>Z?G d!d" d"e>Z@dS )#    )annotationsN)partial)dedent)	Timedelta)AxisFrameOrSeriesFrameOrSeriesUnionTimedeltaConvertibleTypes)function)doc)is_datetime64_ns_dtype)isna)maybe_use_numba)zsqrt)	_shared_docsargs_compatcreate_section_headerkwargs_compatnumba_notestemplate_headertemplate_returnstemplate_see_alsowindow_agg_numba_parameters)BaseIndexerExponentialMovingWindowIndexerGroupbyIndexer)generate_numba_ewma_func)EWMMeanStategenerate_online_numba_ewma_func)
BaseWindowBaseWindowGroupbyzfloat | Nonefloat)comassspanhalflifealphareturnc             C  s   t | |||}|dkr td| d k	r:| dk rtdn|d k	r`|dk rRtd|d d } nt|d k	r|dkrxtddttd|  }d| d } n6|d k	r|dks|dkrtd	d| | } ntd
t| S )N   z8comass, span, halflife, and alpha are mutually exclusiver   z comass must satisfy: comass >= 0zspan must satisfy: span >= 1   z#halflife must satisfy: halflife > 0g      ?z"alpha must satisfy: 0 < alpha <= 1z1Must pass one of comass, span, halflife, or alpha)commoncount_not_none
ValueErrornpexplogr!   )r"   r#   r$   r%   Zvalid_countZdecay r/   H/var/www/html/venv/lib/python3.7/site-packages/pandas/core/window/ewm.pyget_center_of_mass6   s*    
r1   z'str | np.ndarray | FrameOrSeries | Nonez(float | TimedeltaConvertibleTypes | Nonez
np.ndarray)timesr$   r&   c             C  s4   t j| t jt jd}tt|j}t || S )a  
    Return the diff of the times divided by the half-life. These values are used in
    the calculation of the ewm mean.

    Parameters
    ----------
    times : str, np.ndarray, Series, default None
        Times corresponding to the observations. Must be monotonically increasing
        and ``datetime64[ns]`` dtype.
    halflife : float, str, timedelta, optional
        Half-life specifying the decay

    Returns
    -------
    np.ndarray
        Diff of the times divided by the half-life
    )dtype)	r,   ZasarrayviewZint64float64r!   r   valuediff)r2   r$   Z_timesZ	_halflifer/   r/   r0   _calculate_deltasW   s    r8   c                  sD  e Zd ZdZdddddddd	d
g	ZdQddddddddddddd
 fddZddddZdRdd Zee	d! e
d"e
d#d$d%d& fd'd(ZeZeeed)eeeed*eed+eed,ed-d%d.d/d0d1d2ddd3d4d5Zeeed)e
d6d-d%d.eeed*eed+edd7 d/d8d9d2dSdd:d;d<ZdTdd:d=d>Zeeed)e
d6d-d%d.eeed*eed+edd7 d/d?d@d2dUdd:dAdBZeeed)e
dCd-d%d.eed*eed+edd7 d/dDdEd2dVdFdGddHdIdJZeeed)e
dKd-d%d.eed*eed+edd7 d/dLdMd2dWdFdGdNdOdPZ  ZS )XExponentialMovingWindowa  
    Provide exponential weighted (EW) functions.

    Available EW functions: ``mean()``, ``var()``, ``std()``, ``corr()``, ``cov()``.

    Exactly one parameter: ``com``, ``span``, ``halflife``, or ``alpha`` must be
    provided.

    Parameters
    ----------
    com : float, optional
        Specify decay in terms of center of mass,
        :math:`\alpha = 1 / (1 + com)`, for :math:`com \geq 0`.
    span : float, optional
        Specify decay in terms of span,
        :math:`\alpha = 2 / (span + 1)`, for :math:`span \geq 1`.
    halflife : float, str, timedelta, optional
        Specify decay in terms of half-life,
        :math:`\alpha = 1 - \exp\left(-\ln(2) / halflife\right)`, for
        :math:`halflife > 0`.

        If ``times`` is specified, the time unit (str or timedelta) over which an
        observation decays to half its value. Only applicable to ``mean()``
        and halflife value will not apply to the other functions.

        .. versionadded:: 1.1.0

    alpha : float, optional
        Specify smoothing factor :math:`\alpha` directly,
        :math:`0 < \alpha \leq 1`.
    min_periods : int, default 0
        Minimum number of observations in window required to have a value
        (otherwise result is NA).
    adjust : bool, default True
        Divide by decaying adjustment factor in beginning periods to account
        for imbalance in relative weightings (viewing EWMA as a moving average).

        - When ``adjust=True`` (default), the EW function is calculated using weights
          :math:`w_i = (1 - \alpha)^i`. For example, the EW moving average of the series
          [:math:`x_0, x_1, ..., x_t`] would be:

        .. math::
            y_t = \frac{x_t + (1 - \alpha)x_{t-1} + (1 - \alpha)^2 x_{t-2} + ... + (1 -
            \alpha)^t x_0}{1 + (1 - \alpha) + (1 - \alpha)^2 + ... + (1 - \alpha)^t}

        - When ``adjust=False``, the exponentially weighted function is calculated
          recursively:

        .. math::
            \begin{split}
                y_0 &= x_0\\
                y_t &= (1 - \alpha) y_{t-1} + \alpha x_t,
            \end{split}
    ignore_na : bool, default False
        Ignore missing values when calculating weights; specify ``True`` to reproduce
        pre-0.15.0 behavior.

        - When ``ignore_na=False`` (default), weights are based on absolute positions.
          For example, the weights of :math:`x_0` and :math:`x_2` used in calculating
          the final weighted average of [:math:`x_0`, None, :math:`x_2`] are
          :math:`(1-\alpha)^2` and :math:`1` if ``adjust=True``, and
          :math:`(1-\alpha)^2` and :math:`\alpha` if ``adjust=False``.

        - When ``ignore_na=True`` (reproducing pre-0.15.0 behavior), weights are based
          on relative positions. For example, the weights of :math:`x_0` and :math:`x_2`
          used in calculating the final weighted average of
          [:math:`x_0`, None, :math:`x_2`] are :math:`1-\alpha` and :math:`1` if
          ``adjust=True``, and :math:`1-\alpha` and :math:`\alpha` if ``adjust=False``.
    axis : {0, 1}, default 0
        The axis to use. The value 0 identifies the rows, and 1
        identifies the columns.
    times : str, np.ndarray, Series, default None

        .. versionadded:: 1.1.0

        Times corresponding to the observations. Must be monotonically increasing and
        ``datetime64[ns]`` dtype.

        If str, the name of the column in the DataFrame representing the times.

        If 1-D array like, a sequence with the same shape as the observations.

        Only applicable to ``mean()``.

    Returns
    -------
    DataFrame
        A Window sub-classed for the particular operation.

    See Also
    --------
    rolling : Provides rolling window calculations.
    expanding : Provides expanding transformations.

    Notes
    -----

    More details can be found at:
    :ref:`Exponentially weighted windows <window.exponentially_weighted>`.

    Examples
    --------
    >>> df = pd.DataFrame({'B': [0, 1, 2, np.nan, 4]})
    >>> df
         B
    0  0.0
    1  1.0
    2  2.0
    3  NaN
    4  4.0

    >>> df.ewm(com=0.5).mean()
              B
    0  0.000000
    1  0.750000
    2  1.615385
    3  1.615385
    4  3.670213

    Specifying ``times`` with a timedelta ``halflife`` when computing mean.

    >>> times = ['2020-01-01', '2020-01-03', '2020-01-10', '2020-01-15', '2020-01-17']
    >>> df.ewm(halflife='4 days', times=pd.DatetimeIndex(times)).mean()
              B
    0  0.000000
    1  0.585786
    2  1.523889
    3  1.523889
    4  3.233686
    comr#   r$   r%   min_periodsadjust	ignore_naaxisr2   Nr   TF)	selectionr   zfloat | Nonez(float | TimedeltaConvertibleTypes | Nonez
int | Noneboolr   z'str | np.ndarray | FrameOrSeries | None)
objr:   r#   r$   r%   r;   r<   r=   r>   r2   c         
     s  t  j||d krdntt|dd dd d|	|d || _|| _|| _|| _|| _|| _	|
| _
| j
d k	r6| jsvtdt| j
tr| j| j
 | _
t| j
stdt| j
t|krtdt| jttjfstdt| j
 rtd	t| j
| j| _t| j| j| jd
kr.t| j| jd | j| _nd| _nb| jd k	r^t| jttjfr^tdtjtt| jd d
tjd| _t| j| j| j| j| _d S )Nr'   FZsingle)rA   r;   oncenterclosedmethodr>   r?   z)times is not supported with adjust=False.z#times must be datetime64[ns] dtype.z,times must be the same length as the object.z6halflife must be a string or datetime.timedelta objectz$Cannot convert NaT values to integerr   g      ?zKhalflife can only be a timedelta convertible argument if times is not None.)r3   ) super__init__maxintr:   r#   r$   r%   r<   r=   r2   NotImplementedError
isinstancestr_selected_objr   r+   lendatetime	timedeltar   anyr8   _deltasr)   r*   r1   _comr,   onesrA   r5   )selfrA   r:   r#   r$   r%   r;   r<   r=   r>   r2   r?   )	__class__r/   r0   rG     sX    
"z ExponentialMovingWindow.__init__r   )r&   c             C  s   t  S )z[
        Return an indexer class that will compute the window start and end bounds
        )r   )rU   r/   r/   r0   _get_window_indexerS  s    z+ExponentialMovingWindow._get_window_indexernumbac             C  s8   t | j| j| j| j| j| j| j| j| j	| j
||| jdS )a  
        Return an ``OnlineExponentialMovingWindow`` object to calculate
        exponentially moving window aggregations in an online method.

        .. versionadded:: 1.3.0

        Parameters
        ----------
        engine: str, default ``'numba'``
            Execution engine to calculate online aggregations.
            Applies to all supported aggregation methods.

        engine_kwargs : dict, default None
            Applies to all supported aggregation methods.

            * For ``'numba'`` engine, the engine can accept ``nopython``, ``nogil``
              and ``parallel`` dictionary keys. The values must either be ``True`` or
              ``False``. The default ``engine_kwargs`` for the ``'numba'`` engine is
              ``{{'nopython': True, 'nogil': False, 'parallel': False}}`` and will be
              applied to the function

        Returns
        -------
        OnlineExponentialMovingWindow
        )rA   r:   r#   r$   r%   r;   r<   r=   r>   r2   engineengine_kwargsr?   )OnlineExponentialMovingWindowrA   r:   r#   r$   r%   r;   r<   r=   r>   r2   Z
_selection)rU   rY   rZ   r/   r/   r0   onlineY  s    zExponentialMovingWindow.online	aggregatezV
        See Also
        --------
        pandas.DataFrame.rolling.aggregate
        a  
        Examples
        --------
        >>> df = pd.DataFrame({"A": [1, 2, 3], "B": [4, 5, 6], "C": [7, 8, 9]})
        >>> df
           A  B  C
        0  1  4  7
        1  2  5  8
        2  3  6  9

        >>> df.ewm(alpha=0.5).mean()
                  A         B         C
        0  1.000000  4.000000  7.000000
        1  1.666667  4.666667  7.666667
        2  2.428571  5.428571  8.428571
        zSeries/Dataframe )Zsee_alsoZexamplesklassr>   c               s   t  j|f||S )N)rF   r]   )rU   funcargskwargs)rV   r/   r0   r]     s    z!ExponentialMovingWindow.aggregateZ
ParametersZReturnszSee AlsoZNotes
r'   Zewmz"(exponential weighted moment) meanmean)Zwindow_methodZaggregation_descriptionZ
agg_method)rY   rZ   c            O  s   t |r6t|| j| j| j| j}| j|dd dfdS |dkr|d k	rNtdt	d|| | j
d krjd n| j}ttj| j| j| j|d}| |S td	d S )
Nc             S  s   | S )Nr/   )xr/   r/   r0   <lambda>      z.ExponentialMovingWindow.mean.<locals>.<lambda>ewma)Znumba_cache_key)cythonNz+cython engine does not accept engine_kwargsrd   )r:   r<   r=   deltasz)engine must be either 'numba' or 'cython')r   r   rS   r<   r=   rR   _applyr+   nvvalidate_window_funcr2   r   window_aggregationsrh   )rU   rY   rZ   ra   rb   	ewma_funcrj   window_funcr/   r/   r0   rd     s&    
zExponentialMovingWindow.meanzc
        bias : bool, default False
            Use a standard estimation bias correction.
        z0(exponential weighted moment) standard deviationstd)biasc             O  s&   t d|| t| jf d|i|S )Nrr   rs   )rl   rm   r   var)rU   rs   ra   rb   r/   r/   r0   rr     s    zExponentialMovingWindow.stdc             O  s"   t jdtdd | j|f||S )NzGvol is deprecated will be removed in a future version. Use std instead.r(   )
stacklevel)warningswarnFutureWarningrr   )rU   rs   ra   rb   r/   r/   r0   vol  s
    zExponentialMovingWindow.volz&(exponential weighted moment) variancert   c               sB   t d|| tj}t|| j| j| j|d  fdd}| |S )Nrt   )r:   r<   r=   rs   c               s    | |||| S )Nr/   )valuesbeginendr;   )wfuncr/   r0   var_func  s    z-ExponentialMovingWindow.var.<locals>.var_func)	rl   rm   rn   ewmcovr   rS   r<   r=   rk   )rU   rs   ra   rb   rp   r~   r/   )r}   r0   rt     s    zExponentialMovingWindow.vara  
        other : Series or DataFrame , optional
            If not supplied then will default to self and produce pairwise
            output.
        pairwise : bool, default None
            If False then only matching columns between self and other will be
            used and the output will be a DataFrame.
            If True then all pairwise combinations will be calculated and the
            output will be a MultiIndex DataFrame in the case of DataFrame
            inputs. In the case of missing elements, only complete pairwise
            observations will be used.
        bias : bool, default False
            Use a standard estimation bias correction.
        z/(exponential weighted moment) sample covariancecovzFrameOrSeriesUnion | Nonezbool | None)otherpairwisers   c               s.   ddl m   fdd}j|||S )Nr   )Seriesc       	        s    | } |} }jd k	r,jn|j}|jt||jjd\}}t	|||j|j
jj	} || j| jdS )N)
num_valuesr;   rC   rD   )indexname)_prep_valuesrW   r;   window_sizeget_window_boundsrN   rC   rD   rn   r   rS   r<   r=   r   r   )	re   yx_arrayy_arraywindow_indexerr;   startr|   result)r   rs   rU   r/   r0   cov_func:  s*    

z-ExponentialMovingWindow.cov.<locals>.cov_func)pandasr   _apply_pairwiserM   )rU   r   r   rs   rb   r   r/   )r   rs   rU   r0   r     s    #zExponentialMovingWindow.covaL  
        other : Series or DataFrame, optional
            If not supplied then will default to self and produce pairwise
            output.
        pairwise : bool, default None
            If False then only matching columns between self and other will be
            used and the output will be a DataFrame.
            If True then all pairwise combinations will be calculated and the
            output will be a MultiIndex DataFrame in the case of DataFrame
            inputs. In the case of missing elements, only complete pairwise
            observations will be used.
        z0(exponential weighted moment) sample correlationcorr)r   r   c               s,   ddl m   fdd}j|||S )Nr   )r   c       
   	     s    | } |} }jd k	r,jn|j|jt|jjd\  fdd}tj	dd4 |||}|||}|||}|t
||  }	W d Q R X |	| j| jdS )N)r   r;   rC   rD   c               s    t |  |jjjd	S )NT)rn   r   rS   r<   r=   )XY)r|   r;   rU   r   r/   r0   _cov  s    z<ExponentialMovingWindow.corr.<locals>.cov_func.<locals>._covignore)all)r   r   )r   rW   r;   r   r   rN   rC   rD   r,   Zerrstater   r   r   )
re   r   r   r   r   r   r   Zx_varZy_varr   )r   rU   )r|   r;   r   r0   r   |  s"    




z.ExponentialMovingWindow.corr.<locals>.cov_func)r   r   r   rM   )rU   r   r   rb   r   r/   )r   rU   r0   r   Z  s     $zExponentialMovingWindow.corr)	NNNNr   TFr   N)rX   N)F)F)F)NNF)NN)__name__
__module____qualname____doc___attributesrG   rW   r\   r   r   r   r]   Zaggr   r   r   r   r   r   r   r   replacerd   rr   ry   rt   r   r   __classcell__r/   r/   )rV   r0   r9   w   s            *?
*


  %
 r9   c                  s@   e Zd ZdZejej Zdd fdd
Zdddd	Z  Z	S )
ExponentialMovingWindowGroupbyzF
    Provide an exponential moving window groupby implementation.
    N)_grouperc              s\   t  j|f|d|i| |jsX| jd k	rXtt| jj	 }t
| j|| j| _d S )Nr   )rF   rG   emptyr2   r,   concatenatelistr   indicesrz   r8   Ztaker$   rR   )rU   rA   r   ra   rb   Zgroupby_order)rV   r/   r0   rG     s    
z'ExponentialMovingWindowGroupby.__init__r   )r&   c             C  s   t | jjtd}|S )z
        Return an indexer class that will compute the window start and end bounds

        Returns
        -------
        GroupbyIndexer
        )Zgroupby_indicesr   )r   r   r   r   )rU   r   r/   r/   r0   rW     s    z2ExponentialMovingWindowGroupby._get_window_indexer)
r   r   r   r   r9   r   r    rG   rW   r   r/   r/   )rV   r0   r     s   r   c                  s   e Zd Zd'dddddd	dd
ddddddd fddZdd Zdd Zd(ddddZd)dddddZd*ddddd d!Zd+ddd"d#Z	ddd$d%d&Z
  ZS ),r[   Nr   TFrX   )r?   r   zfloat | Nonez(float | TimedeltaConvertibleTypes | Nonez
int | Noner@   r   z'str | np.ndarray | FrameOrSeries | NonerL   zdict[str, bool] | None)rA   r:   r#   r$   r%   r;   r<   r=   r>   r2   rY   rZ   c              sp   |
d k	rt dt j|||||||||	|
|d t| j| j| j| j|j| _	t
|rd|| _|| _ntdd S )Nz0times is not implemented with online operations.)rA   r:   r#   r$   r%   r;   r<   r=   r>   r2   r?   z$'numba' is the only supported engine)rJ   rF   rG   r   rS   r<   r=   r>   shape_meanr   rY   rZ   r+   )rU   rA   r:   r#   r$   r%   r;   r<   r=   r>   r2   rY   rZ   r?   )rV   r/   r0   rG     s*    z&OnlineExponentialMovingWindow.__init__c             C  s   | j   dS )z=
        Reset the state captured by `update` calls.
        N)r   reset)rU   r/   r/   r0   r     s    z#OnlineExponentialMovingWindow.resetc             O  s   t S )N)rJ   )rU   r`   ra   rb   r/   r/   r0   r]     s    z'OnlineExponentialMovingWindow.aggregate)rs   c             O  s   t S )N)rJ   )rU   rs   ra   rb   r/   r/   r0   rr     s    z!OnlineExponentialMovingWindow.stdzFrameOrSeriesUnion | Nonezbool | None)r   r   c             K  s   t S )N)rJ   )rU   r   r   rb   r/   r/   r0   r     s    z"OnlineExponentialMovingWindow.corr)r   r   rs   c             K  s   t S )N)rJ   )rU   r   r   rs   rb   r/   r/   r0   r     s    z!OnlineExponentialMovingWindow.covc             O  s   t S )N)rJ   )rU   rs   ra   rb   r/   r/   r0   rt     s    z!OnlineExponentialMovingWindow.var)updateupdate_timesc            O  sl  i }| j jdkrdnd}|dk	r*tdn(tjt| j j| jd  d dtjd}|dk	r| j	j
dkrntd	d}|j|d
< |r| j	j
tjddf }	|j|d< n| j	j
}	|j|d< t|	| f}
n@d}| j j|d
< |r| j j|d< n| j j|d< | j tj }
t| j}| j	|r"|
n|
ddtjf || j|}|sL| }||d }| j j|f|}|S )a[  
        Calculate an online exponentially weighted mean.

        Parameters
        ----------
        update: DataFrame or Series, default None
            New values to continue calculating the
            exponentially weighted mean from the last values and weights.
            Values should be float64 dtype.

            ``update`` needs to be ``None`` the first time the
            exponentially weighted mean is calculated.

        update_times: Series or 1-D np.ndarray, default None
            New times to continue calculating the
            exponentially weighted mean from the last values and weights.
            If ``None``, values are assumed to be evenly spaced
            in time.
            This feature is currently unsupported.

        Returns
        -------
        DataFrame or Series

        Examples
        --------
        >>> df = pd.DataFrame({"a": range(5), "b": range(5, 10)})
        >>> online_ewm = df.head(2).ewm(0.5).online()
        >>> online_ewm.mean()
              a     b
        0  0.00  5.00
        1  0.75  5.75
        >>> online_ewm.mean(update=df.tail(3))
                  a         b
        2  1.615385  6.615385
        3  2.550000  7.550000
        4  3.520661  8.520661
        >>> online_ewm.reset()
        >>> online_ewm.mean()
              a     b
        0  0.00  5.00
        1  0.75  5.75
        r(   TFNz update_times is not implemented.r'   r   )r3   z;Must call mean with update=None first before passing updater   columnsr   )rM   ndimrJ   r,   rT   rH   r   r>   r5   r   Zlast_ewmr+   r   Znewaxisr   r   r   Zto_numpyZastyper   rZ   Zrun_ewmr;   ZsqueezeZ_constructor)rU   r   r   ra   rb   Zresult_kwargsZis_frameZupdate_deltasZresult_from
last_valueZnp_arrayro   r   r/   r/   r0   rd     sF    ,
$


z"OnlineExponentialMovingWindow.mean)NNNNr   TFr   NrX   N)F)NN)NNF)F)r   r   r   rG   r   r]   rr   r   r   rt   rd   r   r/   r/   )rV   r0   r[     s,             .   r[   )A
__future__r   rO   	functoolsr   textwrapr   rv   numpyr,   Zpandas._libs.tslibsr   Z pandas._libs.window.aggregationsZ_libsZwindowZaggregationsrn   Zpandas._typingr   r   r   r	   Zpandas.compat.numpyr
   rl   Zpandas.util._decoratorsr   Zpandas.core.dtypes.commonr   Zpandas.core.dtypes.missingr   Zpandas.core.commoncorer)   Zpandas.core.util.numba_r   Zpandas.core.window.commonr   Zpandas.core.window.docr   r   r   r   r   r   r   r   r   Zpandas.core.window.indexersr   r   r   Zpandas.core.window.numba_r   Zpandas.core.window.onliner   r   Zpandas.core.window.rollingr   r    r1   r8   r9   r   r[   r/   r/   r/   r0   <module>   s:   ,!     0!