Skip to content

Commit 9cc979b

Browse files
author
toonyyy
committed
Implement rsi function.
1 parent ae68a78 commit 9cc979b

File tree

1 file changed

+103
-0
lines changed

1 file changed

+103
-0
lines changed
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
"""
2+
Calculate the relative strength index (RSI) on a series of stciks prices
3+
Wikipedia Reference: https://en.wikipedia.org/wiki/Relative_strength_index
4+
Other Reference: https://www.investopedia.com/terms/r/rsi.asp
5+
6+
RSI is a technical indicator used in finance to measure the speed and magnitude of
7+
recent price changes of a stock. Its value ranges from 0 to 100, where a low number
8+
indicates the stock may be oversold, and a high number indicates the stock may be
9+
overbought.
10+
"""
11+
12+
from collections.abc import Sequence
13+
14+
15+
def relative_strength_index(
16+
stock_prices: Sequence[float], window_size: int
17+
) -> list[float | None]:
18+
"""
19+
Returns the relative strength index from inputted stock prices
20+
>>> relative_strength_index([44, 44.5, 43, 45, 44.5, 46, 46.5], 3)
21+
[None, None, None, 52.631578947368425, 72.3076923076923, 77.07006369426752]
22+
23+
Formula:
24+
rsi = 100 - (100 / (1 + rs))
25+
26+
Where,
27+
rs : Relative strength which is the average gain divided by the average loss.
28+
29+
Relative strength index (RSI) returns a number between 0 and 100 and is a method
30+
of determining if a stock may be overbought (greater than 70) or oversold (less
31+
than 30). This function uses the Wilder smoothing implementation of RSI.
32+
"""
33+
34+
# Check inputs are reasonable
35+
if window_size <= 0:
36+
raise ValueError("window_size must be greater than 0")
37+
38+
if len(stock_prices) <= 1:
39+
raise ValueError("stocks_prices needs to have at least 2 entries")
40+
41+
if len(stock_prices) <= window_size:
42+
raise ValueError(
43+
"stock_prices needs to be have more entries than the value of window_size"
44+
)
45+
46+
# Calculate price changes
47+
price_changes = [
48+
stock_prices[i] - stock_prices[i - 1] for i in range(1, len(stock_prices))
49+
]
50+
51+
# Separate gains and losses
52+
gains = [max(price_change, 0) for price_change in price_changes]
53+
losses = [abs(min(price_change, 0)) for price_change in price_changes]
54+
55+
# Initialise none values for entries before the window
56+
rsi_values: list[float | None] = [None] * window_size
57+
58+
# Calculate initial average gains and losses as floats
59+
avg_gain: float = sum(gains[:window_size]) / float(window_size)
60+
avg_loss: float = sum(losses[:window_size]) / float(window_size)
61+
62+
# Compute RSI using Wilder smoothing method
63+
for i in range(window_size, len(price_changes)):
64+
gain = float(gains[i])
65+
loss = float(losses[i])
66+
67+
avg_gain = (avg_gain * (window_size - 1) + gain) / window_size
68+
avg_loss = (avg_loss * (window_size - 1) + loss) / window_size
69+
70+
if avg_loss == 0:
71+
rsi = 100.0
72+
else:
73+
rs = avg_gain / avg_loss
74+
rsi = 100.0 - (100.0 / (1.0 + rs))
75+
76+
rsi_values.append(rsi)
77+
78+
return rsi_values
79+
80+
81+
if __name__ == "__main__":
82+
stock_prices = [
83+
44,
84+
44.15,
85+
43.9,
86+
44.35,
87+
44.7,
88+
45,
89+
45.1,
90+
44.9,
91+
45.3,
92+
45.7,
93+
46.2,
94+
45.9,
95+
46.3,
96+
46.8,
97+
47.1,
98+
]
99+
window_size = 5
100+
rsi = relative_strength_index(stock_prices, window_size)
101+
print(f"Stock prices: {stock_prices}")
102+
print(f"Windows size: {window_size}")
103+
print(f"RSI: {rsi}")

0 commit comments

Comments
 (0)