forked from je-suis-tm/quant-trading
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRSI Oscillator backtest.py
156 lines (108 loc) · 4.29 KB
/
RSI Oscillator backtest.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# coding: utf-8
# In[1]:
#relative strength index(rsi) is another popular indicator for technical analysis
#actually i believe its kinda bull shit
#normally i read stuff on trading view wiki
#its not like i work there and try to promote it
#trading view wiki is a very detailed encyclopedia for different indicators
#plz refer to the following link for more details
# https://www.tradingview.com/wiki/Relative_Strength_Index_(RSI)
#on trading view wiki, there are a couple of strategies to use rsi
#the simplest one is overbought/oversold
#that is what this script is about
#we just set upper/lower boundaries capped at 30/70 for rsi
#if rsi exceeds the bound, we bet the stock would go under price correction
#another one is called divergence
#rsi goes up and price actually goes down
#the inventor of rsi called wilder believes bearish rsi divergence creates a selling opportunity
#but his protege cardwell believes bearish divergence only occurs in a bullish trend
#so their ideas basically contradict to each other
#i would undoubtedly give up on this bs divergence strategy
#the last one is called failure swing
#its kinda like a double bottom pattern in price itself
#except this strategy is a pattern recognition on rsi
#as i have written similar strategy for bollinger bands
#plz refer to that script for more details
# https://github.com/tattooday/quant-trading/blob/master/Bollinger%20Bands%20Pattern%20Recognition%20backtest.py
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import fix_yahoo_finance as yf
# In[2]:
#smoothed moving average
#for details plz refer to wikipedia
# https://en.wikipedia.org/wiki/Moving_average#Modified_moving_average
def smma(series,n):
output=[series[0]]
for i in range(1,len(series)):
temp=output[-1]*(n-1)+series[i]
output.append(temp/n)
return output
# In[3]:
#calculating rsi is very simple
#except there are several versions of moving average for rsi
#simple moving average, exponentially weighted moving average, etc
#in this script, we use smoothed moving average(the authentic way)
def rsi(data,n=14):
delta=data.diff().dropna()
up=np.where(delta>0,delta,0)
down=np.where(delta<0,-delta,0)
rs=np.divide(smma(up,n),smma(down,n))
output=100-100/(1+rs)
return output[n-1:]
# In[4]:
#signal generation
#it is really easy
#when rsi goes above 70, we short the stock
#we bet the stock price would fall
#vice versa
def signal_generation(df,method,n=14):
df['rsi']=0.0
df['rsi'][n:]=rsi(df['Close'],n=14)
df['positions']=np.select([df['rsi']<30,df['rsi']>70], \
[1,-1],default=0)
df['signals']=df['positions'].diff()
return df[n:]
# In[5]:
#plotting
def plot(new,ticker):
#the first plot is the actual close price with long/short positions
fig=plt.figure(figsize=(10,10))
ax=fig.add_subplot(211)
new['Close'].plot(label=ticker)
ax.plot(new.loc[new['signals']==1].index,
new['Close'][new['signals']==1],
label='LONG',lw=0,marker='^',c='g')
ax.plot(new.loc[new['signals']==-1].index,
new['Close'][new['signals']==-1],
label='SHORT',lw=0,marker='v',c='r')
plt.legend(loc='best')
plt.grid(True)
plt.title('Positions')
plt.xlabel('Date')
plt.ylabel('price')
plt.show()
#the second plot is rsi with overbought/oversold interval capped at 30/70
bx=plt.figure(figsize=(10,10)).add_subplot(212,sharex=ax)
new['rsi'].plot(label='relative strength index',c='#522e75')
bx.fill_between(new.index,30,70,alpha=0.5,color='#f22f08')
bx.text(new.index[-45],75,'overbought',color='#594346',size=12.5)
bx.text(new.index[-45],25,'oversold',color='#594346',size=12.5)
plt.xlabel('Date')
plt.ylabel('value')
plt.title('RSI')
plt.legend(loc='best')
plt.grid(True)
plt.show()
# In[6]:
def main():
ticker='FCAU'
startdate='2016-01-01'
enddate='2018-01-01'
df=yf.download(ticker,start=startdate,end=enddate)
new=signal_generation(df,rsi,n=14)
plot(new,ticker)
#how to calculate stats could be found from my other code called Heikin-Ashi
# https://github.com/tattooday/quant-trading/blob/master/heikin%20ashi%20backtest.py
if __name__ == '__main__':
main()