
    i                       d Z ddlmZ ddlmZ ddlZddlZdddd	 	 	 	 	 	 	 	 	 dd	Z	e G d
 d             Z
edk(  rej                  j                  d      Z ej                  ddd      Zd ej"                   ej$                  ej'                  dd ee                        z  Z ej,                  ee      Z e	eddd      Z eej5                  d              eej7                  d             yy)uf  
Macro regime filter: time-series momentum on daily data.

Combines a long moving average (trend) with a medium-term rate of change (momentum).

Regime coding (default rules):
  +1  Bullish — price above SMA and ROC positive (both agree uptrend)
  -1  Bearish — price below SMA and ROC negative
   0  Flat / mixed — contradictory or not enough history
    )annotations)	dataclassN         
sma_windowaqr_lookbackaqr_skipc                  | j                  t        j                        }|j                  ||      j	                         }|j                  t        |            |j                  t        |            z  dz
  }||kD  |dkD  z  }||k  |dk  z  }t        j                  t        j                  d      |j                        }	|	j                  |t        j                  d            }	|	j                  |t        j                  d            }	|	j                  ||z  t        j                  d            }	|	j                  t        j                        S )a  
    Vectorized daily regime indicator.

    Parameters
    ----------
    close
        Daily close levels (DatetimeIndex).
    sma_window
        Simple moving average length (default 200 trading days).
    aqr_lookback
        AQR lookback in trading days (default 252 = ~12 months).
    aqr_skip
        AQR skip in trading days to exclude the most recent momentum window
        (default 21 = ~1 month).

    Returns
    -------
    Series of int8 in {-1, 0, 1}, index aligned to `close`.
    )windowmin_periods      ?g        r   index   )astypenpfloat64rollingmeanshiftintpdSeriesint8r   mask)
closer	   r
   r   csmaaqr_mombullishbearishregimes
             B/opt/rentech/trading_bot/RenTech/strategy_stack/momentum_filter.pycompute_regime_seriesr'      s    4 	RZZ A
))::)
>
C
C
EC ggc(m$qwws</@'AACGG3w7S=)G3w7S=)GYYrwwqz1F[["''!*-F[["''"+.F[[7*BGGAJ7F==!!    c                  R    e Zd ZU dZdZded<   dZded<   dZded<   dd
Zd	dddZ	y)MomentumFiltera5  
    Configurable wrapper around :func:`compute_regime_series`.

    Typical use with :class:`RenTech.strategy_stack.data_loader.DataLoader`:

        loader = DataLoader()
        spy = loader.fetch_daily("SPY", period="10y")
        filt = MomentumFilter()
        regime = filt.transform(spy["close"])
    r   r   r	   r   r
   r   r   r   c                \    t        || j                  | j                  | j                        S )z Return regime Series {-1, 0, 1}.r   )r'   r	   r
   r   )selfr   s     r&   	transformzMomentumFilter.transformP   s)    $**]]	
 	
r(   )	price_colc                  ||j                   vr#t        | dt        |j                                |j                         }||   }|j	                  | j
                  | j
                        j                         |d| j
                   <   |j                  t        | j                              |j                  t        | j                              z  dz
  |d| j                   d| j                   <   | j                  |      |d<   |S )z
        Append regime columns to an OHLCV DataFrame.

        Adds: `sma_{window}`, `aqr_mom_{aqr_lookback}_{aqr_skip}`, `regime`.
        z not in frame columns: )r   sma_r   aqr_mom__r%   )columnsKeyErrorlistcopyr   r	   r   r   r   r   r
   r-   )r,   ohlcvr.   outr    s        r&   transform_framezMomentumFilter.transform_frameY   s     EMM)i[(?U]]@S?TUVVjjl	N()		$//t	(_(d(d(fd4??#$%GGC&'!''#d6G6G2H*IICO 	ht(()4==/:; q)H
r(   N)r   	pd.Seriesreturnr:   )r7   pd.DataFramer.   strr;   r<   )
__name__
__module____qualname____doc__r	   __annotations__r
   r   r-   r9    r(   r&   r*   r*   ?   s8    	 JL#Hc
 HO r(   r*   __main__*   z
2015-01-01i,  B)periodsfreqd   gMb?)sizer   2         F)dropna
   )
r   r:   r	   r   r
   r   r   r   r;   r:   )rA   
__future__r   dataclassesr   numpyr   pandasr   r'   r*   r>   randomdefault_rngrng
date_rangeidxexpcumsumnormallenpxr   sregprintvalue_countstailrC   r(   r&   <module>rc      s%  	 # !   ("(" (" 	("
 (" ("V ( ( (V z
))


#C
"--c
<C	vrvvibii

1e#c(
 CDE	EB		"C A
brA
NC	#

%

()	#((2, r(   