Skip to content

Commit e5dded4

Browse files
committed
Stochastic RSI calculation
1 parent e2a86e3 commit e5dded4

File tree

3 files changed

+203
-5
lines changed

3 files changed

+203
-5
lines changed

SofienKaabar.py

+155
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
import numpy as np
2+
3+
def rsi(Data, rsi_lookback, what1, what2):
4+
5+
# From exponential to smoothed
6+
rsi_lookback = (rsi_lookback * 2) - 1
7+
8+
# Get the difference in price from previous step
9+
delta = []
10+
11+
for i in range(len(Data)):
12+
try:
13+
diff = Data[i, what1] - Data[i - 1, what1]
14+
delta = np.append(delta, diff)
15+
except IndexError:
16+
pass
17+
18+
delta = np.insert(delta, 0, 0, axis = 0)
19+
delta = delta[1:]
20+
21+
# Make the positive gains (up) and negative gains (down) Series
22+
up, down = delta.copy(), delta.copy()
23+
up[up < 0] = 0
24+
down[down > 0] = 0
25+
26+
up = np.array(up)
27+
down = np.array(down)
28+
29+
roll_up = up
30+
roll_down = down
31+
32+
roll_up = np.reshape(roll_up, (-1, 1))
33+
roll_down = np.reshape(roll_down, (-1, 1))
34+
35+
roll_up = adder(roll_up, 3)
36+
roll_down = adder(roll_down, 3)
37+
38+
roll_up = ema(roll_up, 2, rsi_lookback, what2, 1)
39+
roll_down = ema(abs(roll_down), 2, rsi_lookback, what2, 1)
40+
41+
roll_up = roll_up[rsi_lookback:, 1:2]
42+
roll_down = roll_down[rsi_lookback:, 1:2]
43+
Data = Data[rsi_lookback + 1:,]
44+
45+
# Calculate the RS & RSI
46+
RS = roll_up / roll_down
47+
RSI = (100.0 - (100.0 / (1.0 + RS)))
48+
RSI = np.array(RSI)
49+
RSI = np.reshape(RSI, (-1, 1))
50+
RSI = RSI[1:,]
51+
52+
Data = np.concatenate((Data, RSI), axis = 1)
53+
return Data
54+
55+
def ma(Data, lookback, what, where):
56+
57+
for i in range(len(Data)):
58+
try:
59+
Data[i, where] = (Data[i - lookback + 1:i + 1, what].mean())
60+
except IndexError:
61+
pass
62+
63+
return Data
64+
65+
def ema(Data, alpha, lookback, what, where):
66+
67+
# alpha is the smoothing factor
68+
# window is the lookback period
69+
# what is the column that needs to have its average calculated
70+
# where is where to put the exponential moving average
71+
72+
alpha = alpha / (lookback + 1.0)
73+
beta = 1 - alpha
74+
75+
# First value is a simple SMA
76+
Data = ma(Data, lookback, what, where)
77+
78+
# Calculating first EMA
79+
Data[lookback + 1, where] = (Data[lookback + 1, what] * alpha) + (Data[lookback, where] * beta)
80+
# Calculating the rest of EMA
81+
for i in range(lookback + 2, len(Data)):
82+
try:
83+
Data[i, where] = (Data[i, what] * alpha) + (Data[i - 1, where] * beta)
84+
85+
except IndexError:
86+
pass
87+
return Data
88+
89+
# The function to add a certain number of columns
90+
def adder(Data, times):
91+
92+
for i in range(1, times + 1):
93+
94+
z = np.zeros((len(Data), 1), dtype = float)
95+
Data = np.append(Data, z, axis = 1)
96+
return Data
97+
# The function to deleter a certain number of columns
98+
def deleter(Data, index, times):
99+
100+
for i in range(1, times + 1):
101+
102+
Data = np.delete(Data, index, axis = 1)
103+
return Data
104+
# The function to delete a certain number of rows from the beginning
105+
def jump(Data, jump):
106+
107+
Data = Data[jump:, ]
108+
109+
return Data
110+
111+
112+
def stochastic(Data, lookback, what, high, low, where):
113+
114+
for i in range(len(Data)):
115+
116+
try:
117+
Data[i, where] = (Data[i, what] - min(Data[i - lookback + 1:i + 1, low])) / (max(Data[i - lookback + 1:i + 1, high]) - min(Data[i - lookback + 1:i + 1, low]))
118+
119+
except ValueError:
120+
pass
121+
122+
Data[:, where] = Data[:, where] * 100
123+
return Data
124+
125+
# The Data variable refers to the OHLC array
126+
# The lookback variable refers to the period (5, 14, 21, etc.)
127+
# The what variable refers to the closing price
128+
# The high variable refers to the high price
129+
# The low variable refers to the low price
130+
# The where variable refers to where to put the Oscillator
131+
def stoch_rsi(Data, lookback, where):
132+
133+
# Calculating RSI of the Closing prices
134+
Data = rsi(Data, lookback, 3, 0)
135+
136+
# Adding two columns
137+
Data = adder(Data, 2)
138+
139+
for i in range(len(Data)):
140+
141+
try:
142+
Data[i, where + 1] = (Data[i, where] - min(Data[i - lookback + 1:i + 1, where])) / (max(Data[i - lookback + 1:i + 1, where]) - min(Data[i - lookback + 1:i + 1, where]))
143+
144+
except ValueError:
145+
pass
146+
147+
Data[:, where + 1] = Data[:, where + 1] * 100
148+
149+
# Signal Line using a 3-period moving average
150+
Data = ma(Data, 3, where + 1, where + 2)
151+
152+
Data = deleter(Data, where, 2)
153+
Data = jump(Data, lookback)
154+
155+
return Data

common.py

+43
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#!/usr/bin/env python3
2+
import numpy as np
23

34
from math import nan
45

@@ -76,3 +77,45 @@ def calc_stochasticRsi_oscillator(df, n=14, m=3, smooth=3):
7677
k = 100 * (df.Close-lo) / (hi-lo)
7778
d = k.rolling(m).mean()
7879
return k, d
80+
81+
82+
# calculating RSI (gives the same values as TradingView)
83+
# https://stackoverflow.com/questions/20526414/relative-strength-index-in-python-pandas
84+
def RSI(series, period=14):
85+
delta = series.diff().dropna()
86+
ups = delta * 0
87+
downs = ups.copy()
88+
ups[delta > 0] = delta[delta > 0]
89+
downs[delta < 0] = -delta[delta < 0]
90+
ups[ups.index[period-1]] = np.mean( ups[:period] ) #first value is sum of avg gains
91+
ups = ups.drop(ups.index[:(period-1)])
92+
downs[downs.index[period-1]] = np.mean( downs[:period] ) #first value is sum of avg losses
93+
downs = downs.drop(downs.index[:(period-1)])
94+
rs = ups.ewm(com=period-1,min_periods=0,adjust=False,ignore_na=False).mean() / \
95+
downs.ewm(com=period-1,min_periods=0,adjust=False,ignore_na=False).mean()
96+
return 100 - 100 / (1 + rs)
97+
98+
99+
# calculating Stoch RSI (gives the same values as TradingView)
100+
# https://www.tradingview.com/wiki/Stochastic_RSI_(STOCH_RSI)
101+
def StochRSI(series, period=14, smoothK=3, smoothD=3):
102+
# Calculate RSI
103+
delta = series.diff().dropna()
104+
ups = delta * 0
105+
downs = ups.copy()
106+
ups[delta > 0] = delta[delta > 0]
107+
downs[delta < 0] = -delta[delta < 0]
108+
ups[ups.index[period-1]] = np.mean( ups[:period] ) #first value is sum of avg gains
109+
ups = ups.drop(ups.index[:(period-1)])
110+
downs[downs.index[period-1]] = np.mean( downs[:period] ) #first value is sum of avg losses
111+
downs = downs.drop(downs.index[:(period-1)])
112+
rs = ups.ewm(com=period-1,min_periods=0,adjust=False,ignore_na=False).mean() / \
113+
downs.ewm(com=period-1,min_periods=0,adjust=False,ignore_na=False).mean()
114+
rsi = 100 - 100 / (1 + rs)
115+
116+
# Calculate StochRSI
117+
stochrsi = (rsi - rsi.rolling(period).min()) / (rsi.rolling(period).max() - rsi.rolling(period).min())
118+
stochrsi_K = stochrsi.rolling(smoothK).mean()
119+
stochrsi_D = stochrsi_K.rolling(smoothD).mean()
120+
121+
return stochrsi, stochrsi_K, stochrsi_D

indicators/stochasticRsi.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,17 @@
44
sys.path.append('../finplot')
55
import finplot as fplt
66

7-
from common import calc_stochasticRsi_oscillator
7+
from common import StochRSI
88

99
class StochasticRsi():
1010

11-
def __init__(self, dataFrames, stochasticRsi_periods=14, stochasticRsi_quick=3, stochasticRsi_smooth = 3):
12-
self.stochasticRsi_df, self.stochasticRsi_quick_df = calc_stochasticRsi_oscillator(dataFrames, stochasticRsi_periods, stochasticRsi_quick, stochasticRsi_smooth)
11+
def __init__(self, dataFrames, period=14, smoothK=3, smoothD = 3):
12+
self.stochrsi, self.stochrsi_K, self.stochrsi_D = StochRSI(dataFrames, period, smoothK, smoothD)
1313
pass
1414

1515
def draw(self, ax, stochasticRsi_color = "red", stochasticRsi_quick_color="green"):
16-
self.stochasticRsi_plot = fplt.plot(self.stochasticRsi_df, ax = ax, color=stochasticRsi_color, width=1 )
17-
self.stochasticRsi_quick_plot = fplt.plot(self.stochasticRsi_quick_df, ax = ax, color=stochasticRsi_quick_color, width=1 )
16+
self.stochrsi_K_plot = fplt.plot(self.stochrsi_K, ax = ax, color=stochasticRsi_color, width=1 )
17+
self.stochrsi_D_plot = fplt.plot(self.stochrsi_D, ax = ax, color=stochasticRsi_quick_color, width=1 )
1818
pass
1919

2020
def clear(self):

0 commit comments

Comments
 (0)