# 【Quant(13)】RSI Indicator

Use common technical indicators to backtesting

# Highlights

• Difficulty：★★☆☆☆
• Backtesting by RSI indicator and relative performance of this strategy
• Advice: This article adopts TEJ database to calculate RSI indicators, create signals and form the return. Before reading this, 【Quant(2)】Technical Analysis is recommended to explore to better understand the basic procedure of backtesting.

# Preface

Relative strength index (RSI) is the momentum technical indicator. It is usually used as an oscillator interval to evaluate overbought or oversold condition by measuring recent trend of price movements. Following is the way to calculate this indicator:

1. Based on daily spread of price, separately calculate average gain or loss in past N days. (Note: Convert the loss to positive value.)
2. Calculate Relative Strength(RS): Average Gain in past N days / Average Loss in past N days.(Note: In the calculation of average gain, loss is counted as 0, vice versa.)
3. Calculate Relative Strength Index: RS / (1 + RS) × 100

Criterion of RSI:

1. RSI < 30 is oversold, RSI > 70 is overbought. (Note: Another conservative interval pair is (20, 80))
2. RSI Divergence: Trend of RSI is opposite to trend of price, which implies market would become reversal.
3. Golden Cross: Short-term RSI exceeds long-term RSI upwards, which implies the long position.
4. Death Cross: Short-term RSI exceeds long-term RSI downwards, which implies the short position.

RSI’s Deactivation: Gain and loss is separately calculated in RSI. Therefore, if short-term trend of price is almost gain, the reference data of loss would be too few to be considered, which further causes that RSI loses the reference value, vice versa. This situation is specifically frequent during the high or low-level area. We would try to synthesize RSI interval, golden cross and death cross to lower the impact of deactivation.

# The Editing Environment and Modules Required

MacOS and Jupyter Notebook

`#Basic functionimport pandas as pdimport numpy as npimport copy#Visualizationimport plotly.graph_objects as goimport plotly.express as px#TEJimport tejapitejapi.ApiConfig.api_key = 'Your Key'tejapi.ApiConfig.ignoretz = True`

# Data Processing

Step 1. Obtain the stock price

`stock_data = tejapi.get('TWN/APRCD',           coid= '2324', # Compal Electronics, Inc.           mdate={'gte': '2020-01-01', 'lte':'2021-12-14'},           opts={'columns': ['coid', 'mdate', 'open_d', 'close_d']},           chinese_column_name=True,           paginate=True)`

We choose Compal Electronics (2324) as the target. Time interval is ranged from 2020 to today (2021–12–14). With above circumstances, we would know the fluctuation of stock price of largest notebook OEM under the pandemic situation. On top of that, determine the buy and sell signal with RSI.

Step 2. Calculate 14-day RSI & 7-day RSI

`# Calculate daily spread and categorize gain & lossstock_data['隔日差價'] = stock_data['收盤價(元)'].diff()stock_data['上漲'] = stock_data['隔日差價'].clip(lower = 0)stock_data['下跌'] = (-1) * stock_data['隔日差價'].clip( upper = 0)# 14-day RSIstock_data['14日上漲均值'] = stock_data['上漲'].ewm(com = 14, adjust = False).mean()stock_data['14日下跌均值'] = stock_data['下跌'].ewm(com = 14, adjust = False).mean()stock_data['14日相對強弱值'] = stock_data['14日上漲均值'] / stock_data['14日下跌均值']stock_data['14日相對強弱指標'] = stock_data['14日相對強弱值'].apply(lambda rs : rs/(1+rs)*100)# 7-day RSIstock_data['7日上漲均值'] = stock_data['上漲'].ewm(com = 7, adjust = False).mean()stock_data['7日下跌均值'] = stock_data['下跌'].ewm(com = 7, adjust = False).mean()stock_data['7日相對強弱值'] = stock_data['7日上漲均值'] / stock_data['7日下跌均值']stock_data['7日相對強弱指標'] = stock_data['7日相對強弱值'].apply(lambda rs : rs/(1+rs)*100)`

Step 3. RSI Trending Chart & Interval (30,70)(See the details in source code)

Comparing RSI trending and overbought, oversold interval, we find the Golden Cross and Death Cross. What we should notice is that deactivation remains serious at the high-level area. However, we should sell at the first death cross, since it is impossible to predict market accurately.

Step 4. Find Buy and Sell Signal & Visualize Trading Action(See the details in source code)

Over-sold Condition: RSI < 30. To boot, consider that 7-day RSI exceeds 14-day RSI upwards so as to lower impact of low-level deactivation.

Over-bought Condition: RSI > 70. To boot, consider that 7-day RSI exceeds 14-day RSI downwards so as to lower impact of high-level deactivation.

`signal = []trade = 0for i in range(len(stock_data)):    if stock_data.loc[i, '14日相對強弱指標']  <= 30 and stock_data.loc[i-1, '14日相對強弱指標'] > stock_data.loc[i-1, '7日相對強弱指標'] and stock_data.loc[i, '14日相對強弱指標'] <= stock_data.loc[i, '7日相對強弱指標'] and trade == 0:        signal.append(1000)        trade = trade + 1    elif stock_data.loc[i, '14日相對強弱指標'] >= 70 and stock_data.loc[i-1, '14日相對強弱指標'] < stock_data.loc[i-1, '7日相對強弱指標'] and stock_data.loc[i, '14日相對強弱指標'] >= stock_data.loc[i, '7日相對強弱指標'] and trade == 1:        signal.append(-1000)        trade = trade - 1    else:        signal.append(0)stock_data['買賣股數'] = signal`

# Calculate the return

In 【Quant(8)】Backtesting by MACD Indicator, we have discussed the details in the calculation of frictions cost and the method to calculate return with initial principal. In this article, we use function to achieve all of it.

`def target_return(data, principal):        #計算成本    data['手續費'] = data['開盤價(元)']* abs(data['買賣股數'])*0.001425    data['手續費'] = np.where((data['手續費']>0)&(data['手續費'] <20), 20, data['手續費'])    data['證交稅'] = np.where(data['買賣股數']<0, data['開盤價(元)']* abs(data['買賣股數'])*0.003, 0)    data['摩擦成本'] = (data['手續費'] + data['證交稅']).apply(np.floor)        #計算資產價值    data['股票價值'] = data['買賣股數'].cumsum() * data['收盤價(元)']    data['現金價值'] = principal - data['摩擦成本'] + (data['開盤價(元)']* -data['買賣股數']).cumsum()     data['資產價值'] = data['股票價值'] + data['現金價值']        #計算報酬率    data['當日價值變動(%)'] = (data['資產價值']/data['資產價值'].shift(1) - 1)*100    data['累計報酬(%)'] = (data['資產價值']/principal - 1)*100        return data`

We only consider the trading of common stock. There is no margin buy or margin sell situation, so we do not have to calculate premium. With the data containing trading shares and initial principal, we can quickly get the transaction costs and return. In this article, we set 20,000 as our principal

`RSI_return = target_return(data = stock_data, principal = 20000)`

Besides, to demonstrate whether RSI strategy performs relatively well, we add buy-and-hold strategy and market performance as our benchmarks.

`bh_data = copy.deepcopy(stock_data)bh_data['買賣股數'] = 0bh_data.loc[0, '買賣股數'] = 1000bh_data.loc[len(bh_data)-1, '買賣股數'] = -1000# Drop the columns useless for buy-and-hold calculation.bh_data = bh_data.drop(['隔日差價', '上漲', '下跌', '14日上漲均值', '14日下跌均值', '14日相對強弱值','14日相對強弱指標','7日上漲均值', '7日下跌均值', '7日相對強弱值', '7日相對強弱指標'], axis = 1)bh_return = target_return(data=bh_data, principal = 20000)`

Here we also use `deepcopy()` to get stock price, and choose to buy at the beginning and sell at the end during the same period with initial principal of 20000 as well.

• Market Performance
`market = tejapi.get('TWN/APRCD',                   coid = 'Y9997',                   mdate = {'gte':'2020-01-01', 'lte':'2021-12-14'},                   opts = {'columns':['coid','mdate',   'close_d','roi']},                   chinese_column_name = True)market['累計報酬(%)'] = (market['報酬率％'].apply(lambda x:0.01*x +1).cumprod() - 1)*100`

Obtain return of market return index (Y9997) to stands for market performance and calculate the cumulative return

# Performance comparison

Step 1. Comparison of cumulative return (See the details in source code)

With the chart of cumulative return, We tell that RSI strategy made us long after the pandemic. As for the short position, RSI made us sell right at the point that electronic-related stocks were shorted, which was caused by the rise of Commodity’s price and market, therefore, focused on traditional stocks. Besides, fortunately, we avoid the impact of abruptly Covid’s intensification in Taiwan. However, due to the standard of signal trigger is strict, we cannot accurately handle every fluctuation period, like the drop during Aug 2020.

Step 2. Performance table (See the details in source code)

Above chart shows that RSI strategy outperforms buy-and-hold on both return and volatility, which means that RSI helps us find adequate long and short point and improve the efficiency of investment. As for the comparison with market, return of RSI does not outperform market return significantly, but the volatility of RSI is relatively stable. Resulting from avoiding pandemic crash in 2020 and local crash in Taiwan in 2021, sharpe ratio of RSI is better than market performance.

# Conclusion

With the above content, we believe readers understand the influence of deactivation, especially during high or low-level area. Hence, we add another condition, cross of long-term and short-term RSI, making RSI strategy more steady. Of course, on the other hand, this sacrifices some trading opportunities. The balance between risk and trading opportunities is what investors should evaluate and strike. After all, the application of technical indicator varies from person to person. As a result, if readers are interested in diverse trading backtesting, welcome to purchase the plan offered in TEJ E-Shop. Construct trading strategies fitting you with high quality database.

# Source Code

You could give us encouragement by …
We will share financial database applications every week.
If you think today’s article is good, you can click on the
applause icononce.
If you think it is awesome, you can hold the
applause icon until 50 times.