Giampaolo Levorato
Giampaolo Levorato

Reputation: 1622

How to calculate Relative Strength Index (RSI) and Exponential Moving Average (EMA) from a list in pandas

I have created a pandas dataframe (called df) as follows:

import pandas as pd
import numpy as np

ds = {'col1' : [[10,23,45],[54,67,65],[76,43,21]]}

df = pd.DataFrame(data=ds)

The dataframe looks like this:

print(df)

           col1
0  [10, 23, 45]
1  [54, 67, 65]
2  [76, 43, 21]

I need to create two new columns:

Upvotes: 1

Views: 272

Answers (1)

One possible way to do this is to define two functions. One for computing the RSI and one to calculate the EMA (note that in this one I chose the preiod 2, as you required, but it can be changed if needed).

A word of advice. In the future, do put a little bit of context and possibly explanations of what you are aiming for. That will increase your chances for a reply. Not everybody is used to stock markets.

Given you data, this would be:

import pandas as pd
import numpy as np

ds = {'col1': [[10, 23, 45], [54, 67, 65], [76, 43, 21]]}
df = pd.DataFrame(data=ds)

def calculate_rsi(values):
    gains = []
    losses = []
    for i in range(1, len(values)):
        difference = values[i] - values[i-1]
        if difference > 0:
            gains.append(difference)
        else:
            losses.append(abs(difference))
    
    average_gain = np.mean(gains) if gains else 0
    average_loss = np.mean(losses) if losses else 0
    
    if average_loss == 0:  
        return 100
    else:
        rs = average_gain / average_loss
        rsi = 100 - (100 / (1 + rs))
        return rsi

def calculate_ema(values, periods=2):
    weights = np.exp(np.linspace(-1., 0., periods))
    weights /= weights.sum()
    ema = np.convolve(values, weights, mode='full')[:len(values)]
    ema[:periods] = ema[periods]  
    return ema[-1]

df['RSI_2'] = df['col1'].apply(calculate_rsi)
df['EMA_2'] = df['col1'].apply(lambda x: calculate_ema(x, 2))

print(df)

Which retunrs:

           col1       RSI_2      EMA_2
0  [10, 23, 45]  100.000000  28.916711
1  [54, 67, 65]   86.666667  66.462117
2  [76, 43, 21]    0.000000  37.083289

Upvotes: 1

Related Questions