@@ -16,11 +16,13 @@ def rsi(
16
16
data (Union[pd.DataFrame, pl.DataFrame]): The input data.
17
17
source_column (str): The name of the series.
18
18
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}".
21
22
22
23
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.
24
26
"""
25
27
26
28
if result_column is None :
@@ -53,8 +55,8 @@ def rsi(
53
55
delta = data [source_column ].diff ().fill_null (0 )
54
56
55
57
# 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 )
58
60
59
61
# Compute rolling averages of gains and losses
60
62
avg_gain = gain .rolling_mean (window_size = period , min_periods = period )
@@ -65,7 +67,7 @@ def rsi(
65
67
rsi_values = 100 - (100 / (1 + rs ))
66
68
67
69
# 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 )
69
71
70
72
# Add column to DataFrame
71
73
data = data .with_columns (rsi_values .alias (result_column ))
@@ -110,8 +112,12 @@ def wilders_rsi(
110
112
111
113
# Apply Wilder's Smoothing for the remaining values
112
114
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
115
121
116
122
rs = avg_gain / avg_loss
117
123
data [result_column ] = 100 - (100 / (1 + rs ))
@@ -121,26 +127,32 @@ def wilders_rsi(
121
127
122
128
elif isinstance (data , pl .DataFrame ):
123
129
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 )
126
132
127
133
# Compute initial SMA (first `period` rows)
128
134
avg_gain = gain .rolling_mean (window_size = period , min_periods = period )
129
135
avg_loss = loss .rolling_mean (window_size = period , min_periods = period )
130
136
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
+
131
141
# Apply Wilder's Smoothing
132
- smoothed_gain = [None ] * period
133
- smoothed_loss = [None ] * period
134
142
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
+ )
137
149
138
150
# Compute RSI
139
151
rs = pl .Series (smoothed_gain ) / pl .Series (smoothed_loss )
140
152
rsi_values = 100 - (100 / (1 + rs ))
141
153
142
154
# 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 )
144
156
145
157
# Add column to DataFrame
146
158
data = data .with_columns (rsi_values .alias (result_column ))
0 commit comments