
    iXT                     `   S SK Jr  S SKJr  S SKJr  S SKJr  S SK	J
r  S SKJrJrJrJrJrJrJrJrJrJrJrJrJrJrJrJrJrJrJrJ r J!r!J"r"J#r#J$r$  S SKJ%r&  S SKJ'r(  S S	K)J*r*  S S
K+J,r,J-r-  S SK.J/r/  S SK0J1r1J2r2J3r3J4r4J5r5J6r6  S SK7J8r8  S SK9J:r:J;r;J<r<J=r=J>r>J?r?J@r@JArAJBrB  / SQrC  SBS\4S\4S\DS\DS\44
S jjrES\1S\14S jrF  SCS\-S\5S\4S\4S\2S\,4S jjrGS\5S\34S jrH\/" S S!9SDS\4S"\DS\14S# jj5       rIS\-S\34S$ jrJS\1S%\5S\34S& jrK  SCS\-S'\5S\4S\4S\2S\,4S( jjrLS\-S\34S) jrM SES\4S*\DS"\DS\14S+ jjrNS\-S,\OS\-4S- jrP   SFS\-S.\5S/\5S0\5S1\5S\4S\2S\-4S2 jjrQS\1S,\4S\14S3 jrR SGS4\-S5\-S,\4S6\DS\-4
S7 jjrS SHS\4S"\DS\6\5   4S8 jjrTS9\1S\4S: jrUS\5S\54S; jrV  SIS<\,S=\,S>\DS?\DS@\WS\,4SA jjrXg)J    )Callable)reduce)floor)mul)
float_info)allarraybroadcast_toconcatenatediffdotexpfabsfullisnanloglogical_andnannanmeannansumndarraynewaxisonespadsignsqrtsumtriuzeros)max)min)sliding_window_view)	DataFrameSeries)njit)ArrayDictLikeFloatIntIntFloatList)Imports)	v_arrayv_dataframev_floatv_intv_lowerboundv_offsetv_pos_defaultv_scalarv_series)combinationcubeconsecutive_streakdf_error_analysiserf	fibonaccigeometric_meanhpolyifisherlog_geometric_meanpascals_trianglepercent_rankremapstrided_windowsum_signed_rolling_deltassymmetric_triangleweightszeronr
repetitionmultichoosereturnc                 $   [        [        U 5      5      [        [        U5      5      pU(       d  U(       a  X-   S-
  n [        X U-
  5      nUS:X  a  g[        [        [        X U-
  S5      S5      n[        [        [        SUS-   5      S5      nXE-  $ )a{  Combination

Combination computation.

Sources:
    * [stackoverflow](https://stackoverflow.com/questions/4941753/is-there-a-math-ncr-function-in-python)

Parameters:
    n (Int): ```n```
    r (Int): ```r```
    repetition (bool): Apply repetition.
    multichoose (bool): Apply multichoose.

Returns:
    (Int): Combination value

Note:
    ```n``` Choose ```r```: ```(n r)```
   r   )intr   r!   r   r   range)rH   rI   rJ   rK   	numeratordenominators         P/var/www/html/trading/venv/lib/python3.13/site-packages/pandas_ta/utils/_math.pyr6   r6   ?   s~    . tAw<T!Wq[EAI 	A1uAAvsE!UB/3IeAq1uoq1K##    xc                 B    [        S/[        [        U 5      5      45      $ )a8  Consecutive Streak

Computes the streak of consecutive value increases or decreases.

Parameters:
    x (Array): Numpy array.

Returns:
    (Array): Streak array of element changes.

Note: Logic
    Yield an array where each value represents the streak value
    for that bar.

    1. Computes the difference between consecutive values.
    2. Assigns 1 for each positive change, -1 for each negative
       change -1 and 0 for no change.

Note: Streaks
    * Positive: Consecutive bars of value increases
    * Negative: Consecutive bars of value decreases
    * Zero: When direction of the value change reverses

Example:
    ```py
    x = np.array([100, 101, 102, 100, 100, 101, 102, 103])
    result = consecutive_streak(x)
    expected = np.array([0, 1, 1, -1, 0, 1, 1, 1])
    np.array_equal(result, expected)
    ```
r   )r   r   r   rV   s    rT   r8   r8   f   s    @ T$q']+,,rU   Nsrcpwrsignal_offsetoffsetkwargsc                    [        U 5      n [        USSSS9n[        USS5      n[        U5      nX-  n[	        XPR
                  S9n[	        XPR
                  S9nUS:w  a"  UR                  U5      nUR                  U5      nUS:w  a"  UR                  U5      nUR                  U5      n[        [        U5      5      (       a  [        [        U5      5      (       a  gSU;   a&  UR                  US   S	S
9  UR                  US   S	S
9  SU SU 3nSU 3Ul
        SU 3Ul
        S=Ul        Ul        UR                  XgR                  U0n	[        XR
                  S9n
SU 3U
l
        UR                  U
l        U
$ )a  Cube Transform

This transform, by John Ehlers, is used to compress Svalues near zero for
a normalized oscillator like the Inverse Fisher Transform.

In other words, a Power Transform/Function: ```result = src ^ pwr```

Sources:
    * [rengel8](https://github.com/rengel8) based on Markus K.
      (cryptocoinserver)'s source
    * "Cycle Analytics for Traders", 2014, by John Ehlers, page 200

Parameters:
    src (Series): Source
    pwr (float): The transform power. Default: ```3```
    signal_offset (int): Signal offset. Default: ```-1```
    offset (int): Post shift. Default: ```0```

Other Parameters:
    fillna (value): ```pd.DataFrame.fillna(value)```

Returns:
    (DataFrame): 2 columns

Note:
    * Values near ```-1``` and ```1``` are nearly unchanged, whereas
      values near zero are reduced.
    * Input effects of spectral dilation should have been removed
      (i.e. roofing filter).

g      @F)strictrO   r   indexNfillnaTinplace_CUBECUBEs	transform)r5   r1   r0   r2   r$   ra   shiftr   r   rb   namecategoryr#   )rY   rZ   r[   r\   r]   resultct	ct_signal_propsdatadfs              rT   r7   r7      sw   H 3-C
sCU
3C-Q/MfF ZF	ii	(BvYY/I {XXfOOF+	XXm$OOM2	
59~~#eI.// 6
		&"D	1)48 Q}o&FVHoBGVH%IN'22BK)$GGR3D	4yy	)BVHoBG++BKIrU   c                     [        U 5      n[        U 5      n SnSnSnSnSnSnSSXp-  -   -  nSXh-  U-   U-  U-   U-  U-   U-  U-   U-  [        U * U -  5      -  -
  n	X-  $ )a9  Error Function

Computes the erf(x)

Sources:
    * Handbook of Mathematical Functions, formula 7.1.26.
    * [stackoverflow](https://stackoverflow.com/questions/457408/is-there-an-easily-available-implementation-of-erf-for-python)

Parameters:
    x (IntFloat): ```x``` value.

Returns:
    (Float): Error value
g~Z O?gi<15ҿgWU?g9LW@g-UB?g{=@?      ?)r   absr   )
rV   x_signa1a2a3a4a5ptys
             rT   r:   r:      s     !WFAA 
B	B	B	B	BA 	sQU{A26B;!#r)Q.3"A26{+ 	+A:rU   T)cacheweightedc                     U S:  a  U OSn [        S5      nSSU-   -  SSU-
  -  pC[        U 5      n[        SU 5       H   n[        X6S-   -  XFS-   -  -
  5      U-  XV'   M"     U(       a  XUR	                  5       -  $ U$ )zFibonacci

Computes closed form Fibonacci values.

Parameters:
    n (Int): Number of terms (n >= 2). Default: ```2```
    weighted (bool): Return weighted values. Default: ```False```

Returns:
    (Array): Numpy array results
rN      g      @      ?rs   r   )r   r   rQ   floatr   )rH   r   sqrt5phipsirl   is          rT   r;   r;      s     UAIEcEk"C3;$71XF1a[#a%.3q5>9:UB	  

$$MrU   c                    U R                   nUS:  a  U R                  S   $ SU R                  5       ;   nU(       a  U R                  S5      S-   n [	        U S:  5      (       a$  U R                  5       SU-  -  nU(       d  U$ US-
  $ g)zGeometric Mean

Computes the Geometric Mean of positive values.

Parameters:
    x (Series): Values

Returns:
    (Float): Geometric Mean
rN   r   )sizeilocto_numpyrb   r   prod)rV   rH   	has_zerosmeans       rT   r<   r<     s{     	
A1uvvayQZZ\!IHHQK!O
1q5zzvvxAE"$t2$(2rU   vc                     [        U [        5      (       d  [        U 5      n U R                  U S   p2[	        SU5       H  nX   X-  -   nM     U$ )a  Horner's Polynomial

Evaluates a polynomial with an array of polynomial coefficients, ```x```,
and a value, ```v```, using Horner's Calculation for Polynomial
Evaluation.

Parameters:
    x (Array): Polynomial coefficients as ```np.array```
    v (IntFloat): Value

Returns:
    (Float): Polynomial value.

Tip: Performance
    Use a ```np.array``` for best performance.

Example:
    ```py
    coeffs_0 = [4, -3, 0, 1] # 4x^3 - 3x^2 + 0x + 1
    coeffs_1 = np.array(coeffs_0) # Faster
    coeffs_2 = pd.Series(coeffs_0).to_numpy()
    x = -6.5

    hpoly(coeffs_0, x) => -1224.25
    hpoly(coeffs_1, x) or hpoly(coeffs_2, x) => -1224.25 # Faster
    ```
r   rN   )
isinstancer   r	   r   rQ   )rV   r   mr}   r   s        rT   r=   r=   -  sK    8 a!!!H661Q4q1a[D15L HrU   ampc                    [        U 5      n [        US5      n[        USS5      n[        U5      nU R	                  5       n[        US:  US:*  5      n[        U5      (       d\  [        U5      [        U5      p[        U XSSS9n	U	b'  [        [        U	R	                  5       5      5      (       a  gU	R	                  5       n[        X-  5      n
U
S-
  U
S-   -  n[        XR                  S9n[        XR                  S9nUS:w  a"  UR                  U5      nUR                  U5      nUS:w  a"  UR                  U5      nUR                  U5      nSU;   a&  UR                  US   S	S
9  UR                  US   S	S
9  SU 3nSU 3Ul        SU 3Ul        UR                   XR                   U0n[#        XR                  S9nSU 3Ul        U$ )a  Inverse Fisher Transform

This transform function, by John Ehlers, attempts to create clearer
signals by changing the Probability Distribution Function (pdf) for the
results of known oscillator-indicators.

Sources:
    * [rengel8](https://github.com/rengel8) based on Markus K.
      (cryptocoinserver)'s source
    * "Cycle Analytics for Traders", 2014, by John Ehlers, page 198
    * [mesasoftware](https://www.mesasoftware.com/papers/TheInverseFisherTransform.pdf)

Parameters:
    x (Series): Normalized to range ```[-1, 1]```
    amp (float): Amplifier. Default: ```1```
    signal_offset (int): Signal line offset. Default: ```-1```
    offset (int): Post shift. Default: ```0```

Other Parameters:
    fillna (value): ```pd.DataFrame.fillna(value)```

Returns:
    (DataFrame): 2 columns

Note:
    * Normalized input, ```x```, with range ```[-1, 1]```
    * Data range of ```[-0.5, 0.5]``` would not have a significant impact

Example: Preparation Examples
    Or use _ta.remap()_ function to prep

    (RSI - 50) * 0.1        RSI [0 to 100] -> -5 to 5

    (RSI - 50) * 0.02       RSI [0 to 100] -> -1 to 1 (use amp of 5 to match input of example above)
rs   rO   r   rN   )from_minfrom_maxto_minto_maxNr`   rb   Trc   re   	INVFISHER
INVFISHERs)r5   r4   r0   r2   r   r   r   np_maxnp_minrB   r   r   r$   ra   ri   rb   rj   r#   )rV   r   r[   r\   r]   np_xis_remapped_np_max_np_minx_mapampedrl   
inv_fishersignalro   rp   rq   s                    rT   r>   r>   T  s   R 	A
3
C-Q/MfF ::<Ddbj$!)4K{!$<aa
 =Cenn&6 788~~
OEaiEAI&Fgg.JF''*F {%%f-
f%%%f-
f% 6&*D9fX&5 YF!&*JOvh'FKOOZf=D	4ww	'B&"BGIrU   c                     U R                   nUS:  aO  U R                  S5      S-   n [        U S:  5      (       a(  [        [	        U 5      R                  5       U-  5      S-
  $ g)zLogarithmic Geometric Mean

Computes the Logarithmic Geometric Mean of positive values.

Parameters:
    x (Series): Values

Returns:
    (Float): LogGeometric Mean or zero
rN   r   )r   rb   r   r   r   r   )rV   rH   s     rT   r?   r?     sT     	
A1uHHQK!Oq1u::s1vzz|a'(1,,rU   inversec           
         U b  [        [        U 5      5      OSn [        [        SU S-   5       Vs/ s H  n[	        XS9PM     sn5      n[        U5      nXE-  nSU-
  nU(       a	  U(       a  U$ U(       a  U$ U(       a  gU$ s  snf )aI  Pascal's Triangle

The ```n```th row of Pascal's Triangle.

Parameters:
    n (Int): ```n^th``` row of Pascal' Triange
    inverse (bool): Return Inverse weighted.
    weighted (bool): Return weighted.

Returns:
    (Array): Classical, Weighted, or Inversely

Example:
    ```py
    # Classical
    pt4 = pascals_triangle(4)
    # pt4 = [1, 4, 6, 4, 1]

    # Inverse
    invpt4 = pascals_triangle(4, inverse=True)
    # invpt4 = [0.9375, 0.75, 0.625, 0.75, 0.9375]

    # Weighted
    wpt4 = pascals_triangle(4, weighted=True)
    # wpt4 = [0.0625, 0.25, 0.375, 0.25, 0.0625]
    ```
Nr   rN   )rH   rI   )rP   r   r	   rQ   r6   r   )rH   r   r   r   triangletriangle_sumtriangle_weightsinverse_weightss           rT   r@   r@     s    < DG1A U1a!e_E_kA+_EFHx=L.**OGO Fs   Blengthc                     U R                  5       R                  5       n[        X!S-   4S9nUSS2SS24   USS2S[        4   :  nS[	        USS9-  n[        [        U 5      [        5      nXVUS& U$ )a  Percent Rank

Percent Rank of values over a specified length.

Parameters:
    x (Series): ```x``` values
    length (int): The period.

Returns:
    (Series): Percent Rank values.

Note: Logic
    Yield a Series where the initial part (up to ```length - 1```) is
    padded with NaNs, and the rest contains the Percent Rank values.

    1. Computes the daily percentage returns.
    2. Creates a rolling window of these returns.
    3. Compares each value in the window to the current value (the
       last value in each window).
    4. Percent Rank is calculated as the percentage of values in each
       window that are less than the current value.

Example:
    ```py
    x = Series([100, 80, 75, 123, 140, 80, 70, 40, 100, 120]).to_numpy()
    result = percent_rank(x, 3)
    expected_result = Series([np.nan, np.nan, np.nan, 66.666667, 66.666667, 0.0, 33.333333, 0.0, 100.0, 66.666667])
    np.allclose(result, expected_result, rtol=1e-6, equal_nan=True)
    ```
rN   window_shapeNrO   d   axis)
pct_changer   r"   r   r   r   lenr   )rV   r   	np_pctchgrwscomparison_matrixprsrl   s          rT   rA   rA     s|    > '')I
izm
DCAssFc!R.&99
)2
2C#a&#F67O MrU   r   r   r   r   c                    [        U 5      n [        USS5      n[        USS5      n[        USS5      n[        USS5      n[        U5      nX!-
  XC-
  pUS::  d  US::  a  gX8U-  U R                  5       U-
  -  -   n	[	        XR
                  S9n	US:w  a  U	R                  U5      n	SU;   a  U	R                  US   S	S
9  SU SU SU SU 3U	l        U	$ )a  remap

The standard method of transforming from a source range to a target range
using Max-Min. Useful for bounded sources; not unbounded sources
like _ohlcv_ data.

Sources:
    * Linear (Max-Min) Normalization

Parameters:
    x (Series): Series of 'x's
    from_min (IntFloat): Input minimum. Default: ```0.0```
    from_max (IntFloat): Input maximum. Default: ```100.0```
    to_min (IntFloat): Output minimum. Default: ```0.0```
    to_max (IntFloat): Output maximum. Default: ```100.0```
    offset (Int): Post shift. Default: ```0```

Other Parameters:
    fillna (value): ```pd.DataFrame.fillna(value)```

Returns:
    (Series): 1 column
g        g      Y@g      rs   r   Nr`   rb   Trc   REMAP_re   )	r5   r/   r2   r   r$   ra   ri   rb   rj   )
rV   r   r   r   r   r\   r]   frangetrangerl   s
             rT   rB   rB   "  s    : 	Axc*Hx,HVT3'FVS#&FfF (&/F{fk1::<(+BCCFF''*F {f% 6fX&5 8*AhZq&BFK MrU   c                     SSK Jn  U R                  U R                  S   4-   nU R                  SS U R                  S   U-
  S-   U4-   nU" XUSS9$ )a  Strided Window

Creates a strided window view.

Source:
    * [numpy](https://numpy.org/devdocs/reference/generated/numpy.lib.stride_tricks.as_strided.html)
    * [Issue #285](https://github.com/twopirllc/pandas-ta/issues/285)

Parameters:
    x (Array): Source
    length (Int): Window period.

Returns:
    (Array): Numpy Array of Strided Window Arrays

Warning:
    Use if necessary, otherwise avoid when possible!
r   )
as_stridedrO   NrN   F)shapestrides	writeable)numpy.lib.stride_tricksr   r   r   )rV   r   r   r   r   s        rT   rC   rC   ]  sZ    & 3ii199R=**GGGCRLAGGBK&014f==EagGGrU   open_close	exclusivec           	      F   [        US5      nU(       d  US-  n[        XS9SS n[        XS R                  5       SS2[        4   UR
                  5      n[        XT-
  5      n[        USS9R                  [        5      n[        [        XrS4S[        S	9UR                  S
9$ )a<  Sum of Signed Rolling Series Deltas

Calculates the sum of signed differences between the current closing bar
and a rolling window of preceding opening bars. This sum is then padded
to match the original series length.

Parameters:
    open_ (Series): ```open``` Series
    close (Series): ```close``` Series
    length (Int): Window length. Default: ```4```
    exclusive (bool): Exclusive rolling window. Inclusive rolling window
        when ```False```.  Default: ```True```

Returns:
    (Series): 1 column

Notes: Mode
    **Exclusive**: Rolling window excludes the current bar in the
    lookback period.

    **Inclusive**: Rolling window includes the current bar in the
    lookback period.

Example:
    ```py
    open_ = Series([95, 83,  71, 132, 129, 145, 133, 101, 68, 96])
    close = Series([100, 110, 140,  80,  90,  60,  50,  40, 90, 110])

    result = sum_signed_rolling_deltas(close, open_, 4, exclusive=True)
    expected_result = Series([np.nan, np.nan, np.nan, np.nan, 0.0, -4.0, -4.0, -4.0, -4.0, 0.0])
    np.allclose(result, expected_result, rtol=1e-6, equal_nan=True)

    result = sum_signed_rolling_deltas(close, open_, 4, exclusive=False)
    expected_result = Series([np.nan, np.nan, np.nan, -1.0, 1.0, -3.0, -3.0, -3.0, -3.0, 1.0])
    np.allclose(result, expected_result, rtol=1e-6, equal_nan=True)
    ```
   rN   r   NrO   r   r   constant)modeconstant_valuesr`   )r3   r"   r
   r   r   r   r   r   astyper   r$   r   r   ra   )r   r   r   r   rolling_openclose_broadcastedsigned_deltassum_signed_deltass           rT   rD   rD   w  s    P 61%F!&uB3BGL$g!!W*-|/A/A *9:M}15<<UC{SQkk rU   c                    U b  [        [        U 5      5      OSn SnU S:X  a  SS/nU S:  a  U S-  S:X  a5  [        S[        U S-  5      5       Vs/ s H  o3S-   PM	     nnXDSSS2   -   nOW[        S[        SU S-   -  5      5       Vs/ s H  o3S-   PM	     nnUR	                  5       nUR                  5         X$SSS2   -  nU(       a#  [        U[        5      (       a  U[        U5      -  $ U$ s  snf s  snf )a  Symmetric Triangle

Creates a Symmetric Triangle of given length.

Parameters:
    n (Int): Array return size
    weighted (bool): Return weighted.

Returns:
    (List[IntFloat]): List of Symmetric Triangle values.

Example:
    ```py
    # Default
    symt4 = ta.symmetric_triangle(4)
    # symt4 = [1, 2, 2, 1]

    # Weighted
    wsymt4 = ta.symmetric_triangle(4, weighted=True)
    # wsymt4 = [0.16666667 0.33333333 0.33333333 0.16666667]
    ```
Nr   rN   r   rO   r   )	rP   r   rQ   mfloorcopypopr   listr   )rH   r   r   r   fronts        rT   rE   rE     s    2 DG1AHAvq61uq5A:$)!VAE]$;<$;qU$;E<TrT{*H$)!VC1q5M-B$CD$CqU$CEDzz|HIIKdd#HJx..#h-''O = Es   C-C2wc                    ^  U 4S jnU$ )zWeights

Prepares weights for the dot product

Parameters:
    w (Array): Input

Returns:
    (Callable): Weights function for dot product.
c                    > [        TU 5      $ )N)r   )rV   r   s    rT   _dotweights.<locals>._dot  s    1ayrU    )r   r   s   ` rT   rF   rF     s    KrU   c                 D    [        U 5      [        R                  :  a  S$ U $ )zZero

Zeros inputs near zero.

Parameters:
    x (IntFloat): Value to attempt to zero

Returns:
    (IntFloat): ```0``` or ```x```
r   )rt   sfltepsilonrX   s    rT   rG   rG     s     A%1,1,rU   ABplot
triangularmethodc                 ^   / SQnXE;   a  UOUS   nX-
  nU R                  XS9nU(       a;  UR                  " 5         XwS:     R                  5       (       a  UR                  " SS9  U(       a@  UR	                  [        [        UR                  5      5      R                  [        5      5      $ U$ )a'  DataFrame Correlation Analysis

Compares two DataFrames using both their difference and their correlations.

Parameters:
    A (DataFrame): DataFrame A
    B (DataFrame): DataFrame B
    plot (bool): Create a KDE plot of differences. Default: ```False```
    triangular (bool): Return a Triangular Correlation DataFrame.
        Default: ```False```
    method (str): Correlation methods: ```"pearson"```, ```"kendall"```,
        or ```"spearman"```. Default: ```"pearson"```

Returns:
    (DataFrame): Correlation DataFrame or a KDE Difference plot
)pearsonkendallspearmanr   )r   kde)kind)
corrhistanyr   wherer   r   r   r   bool)	r   r   r   r   r   	_r_methodcorr_methodr   rl   s	            rT   r9   r9     s    * 3I"/&Yq\K 5DVVAV*F 		q>II5!||Dfll!34;;DABBMrU   )rN   r   FF)NNN)r   F)NFF)NNNNN)T)NF)FFr   )Ycollections.abcr   	functoolsr   mathr   r   operatorr   sysr   r   numpyr   r	   r
   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r   r!   r   r   r"   pandasr#   r$   numbar%   pandas_ta._typingr&   r'   r(   r)   r*   r+   pandas_ta.mapsr,   pandas_ta.utils._validater-   r.   r/   r0   r1   r2   r3   r4   r5   __all__r   r6   r8   r7   r:   r;   r<   r=   r>   r?   r@   rP   rA   rB   rC   rD   rE   rF   rG   strr9   r   rU   rT   <module>r      sP   $     "      
    7 $   #
 
 
0 27#$
#$#$#$+/#$ 	#$N -%  -E  -J =AI	II69II"*I IZ8  D D D U  4f  2#U #x #E #R 04XX	X),X X #+X 	Xx& U * <A-
- -48-
-b)F )C )F )\ @D0477!74<77%-7 7 #+7 	7vHe HS HU H6 BF88 8*-8:>88x %*,
,!,	(^,`u  "-H - -* ,1%%%
%$(% % 	%rU   