@@ -16,11 +16,13 @@ def rsi(
1616 data (Union[pd.DataFrame, pl.DataFrame]): The input data.
1717 source_column (str): The name of the series.
1818 period (int): The period for the RSI calculation.
19- result_column (str, optional): The name of the column to store the RSI values.
20- Defaults to None, which means it will be named "RSI_{period}".
19+ result_column (str, optional): The name of the column to store
20+ the RSI values. Defaults to None, which means it will
21+ be named "RSI_{period}".
2122
2223 Returns:
23- Union[pd.DataFrame, pl.DataFrame]: The DataFrame with the RSI column added.
24+ Union[pd.DataFrame, pl.DataFrame]: The DataFrame with the RSI
25+ column added.
2426 """
2527
2628 if result_column is None :
@@ -53,8 +55,8 @@ def rsi(
5355 delta = data [source_column ].diff ().fill_null (0 )
5456
5557 # Compute gains and losses
56- gain = delta .clip_min (0 )
57- loss = (- delta ).clip_min (0 )
58+ gain = delta .clip (0 )
59+ loss = (- delta ).clip (0 )
5860
5961 # Compute rolling averages of gains and losses
6062 avg_gain = gain .rolling_mean (window_size = period , min_periods = period )
@@ -65,7 +67,7 @@ def rsi(
6567 rsi_values = 100 - (100 / (1 + rs ))
6668
6769 # Replace first `period` values with nulls (polars uses `None`)
68- rsi_values = rsi_values .set_at_idx (list (range (period )), None )
70+ rsi_values = rsi_values .scatter (list (range (period )), None )
6971
7072 # Add column to DataFrame
7173 data = data .with_columns (rsi_values .alias (result_column ))
@@ -110,8 +112,12 @@ def wilders_rsi(
110112
111113 # Apply Wilder's Smoothing for the remaining values
112114 for i in range (period , len (data )):
113- avg_gain .iloc [i ] = (avg_gain .iloc [i - 1 ] * (period - 1 ) + gain .iloc [i ]) / period
114- avg_loss .iloc [i ] = (avg_loss .iloc [i - 1 ] * (period - 1 ) + loss .iloc [i ]) / period
115+ avg_gain .iloc [i ] = (
116+ avg_gain .iloc [i - 1 ] * (period - 1 ) + gain .iloc [i ]
117+ ) / period
118+ avg_loss .iloc [i ] = (
119+ avg_loss .iloc [i - 1 ] * (period - 1 ) + loss .iloc [i ]
120+ ) / period
115121
116122 rs = avg_gain / avg_loss
117123 data [result_column ] = 100 - (100 / (1 + rs ))
@@ -121,26 +127,32 @@ def wilders_rsi(
121127
122128 elif isinstance (data , pl .DataFrame ):
123129 delta = data [source_column ].diff ().fill_null (0 )
124- gain = delta .clip_min (0 )
125- loss = (- delta ).clip_min (0 )
130+ gain = delta .clip (0 )
131+ loss = (- delta ).clip (0 )
126132
127133 # Compute initial SMA (first `period` rows)
128134 avg_gain = gain .rolling_mean (window_size = period , min_periods = period )
129135 avg_loss = loss .rolling_mean (window_size = period , min_periods = period )
130136
137+ # Initialize smoothed gains/losses with the first SMA values
138+ smoothed_gain = avg_gain [:period ].to_list ()
139+ smoothed_loss = avg_loss [:period ].to_list ()
140+
131141 # Apply Wilder's Smoothing
132- smoothed_gain = [None ] * period
133- smoothed_loss = [None ] * period
134142 for i in range (period , len (data )):
135- smoothed_gain .append ((smoothed_gain [- 1 ] * (period - 1 ) + gain [i ]) / period )
136- smoothed_loss .append ((smoothed_loss [- 1 ] * (period - 1 ) + loss [i ]) / period )
143+ smoothed_gain .append (
144+ (smoothed_gain [- 1 ] * (period - 1 ) + gain [i ]) / period
145+ )
146+ smoothed_loss .append (
147+ (smoothed_loss [- 1 ] * (period - 1 ) + loss [i ]) / period
148+ )
137149
138150 # Compute RSI
139151 rs = pl .Series (smoothed_gain ) / pl .Series (smoothed_loss )
140152 rsi_values = 100 - (100 / (1 + rs ))
141153
142154 # Replace first `period` values with None
143- rsi_values = rsi_values .set_at_idx (list (range (period )), None )
155+ rsi_values = rsi_values .scatter (list (range (period )), None )
144156
145157 # Add column to DataFrame
146158 data = data .with_columns (rsi_values .alias (result_column ))
0 commit comments