In [45]:
import sys
sys.path.insert(0,"/home/william/Financial/financial_calcs/")
import trading_calcs.standard as std_calcs
In [46]:
import numpy as np
import pandas as pd
import pandas_datareader as pdr
import matplotlib.pyplot as plt
%matplotlib inline
In [47]:
df1 = pd.read_excel('./financial_calcs/cs-rsi.xls',index_col=0,header=1,usecols="C:K",nrows=33)
df1.columns = ['Close','Change','Gain','Loss','Avg Gain','Avg Loss', 'RS', 'RSI']
df1.head(15)
Out[47]:
Close Change Gain Loss Avg Gain Avg Loss RS RSI
Date
2009-12-14 44.3389 NaN NaN NaN NaN NaN NaN NaN
2009-12-15 44.0902 -0.2487 0.0000 0.2487 NaN NaN NaN NaN
2009-12-16 44.1497 0.0595 0.0595 0.0000 NaN NaN NaN NaN
2009-12-17 43.6124 -0.5373 0.0000 0.5373 NaN NaN NaN NaN
2009-12-18 44.3278 0.7154 0.7154 0.0000 NaN NaN NaN NaN
2009-12-21 44.8264 0.4986 0.4986 0.0000 NaN NaN NaN NaN
2009-12-22 45.0955 0.2691 0.2691 0.0000 NaN NaN NaN NaN
2009-12-23 45.4245 0.3290 0.3290 0.0000 NaN NaN NaN NaN
2009-12-24 45.8433 0.4188 0.4188 0.0000 NaN NaN NaN NaN
2009-12-28 46.0826 0.2393 0.2393 0.0000 NaN NaN NaN NaN
2009-12-29 45.8931 -0.1895 0.0000 0.1895 NaN NaN NaN NaN
2009-12-30 46.0328 0.1397 0.1397 0.0000 NaN NaN NaN NaN
2009-12-31 45.6140 -0.4188 0.0000 0.4188 NaN NaN NaN NaN
2010-01-04 46.2820 0.6680 0.6680 0.0000 NaN NaN RS RSI
2010-01-05 46.2820 0.0000 0.0000 0.0000 0.238386 0.099593 2.3936 70.5328
In [48]:
gldf = std_calcs.gain_loss_calc(df1['Close'])
In [49]:
df1.to_pickle('./financial_calcs/rsi_data.pkl')
In [50]:
# TODO: compare the results of the two data frames could use assert_frame_equal
from pandas.testing import assert_frame_equal
ref_gldf = df1[['Gain','Loss']]
ref_gldf = ref_gldf.fillna(0)
ref_gldf = ref_gldf.round(4)
gldf = gldf.round(4)
result = assert_frame_equal(ref_gldf, gldf)
pd.concat([gldf, ref_gldf], axis=1)
Out[50]:
Gain Loss Gain Loss
Date
2009-12-14 0.0000 0.0000 0.0000 0.0000
2009-12-15 0.0000 0.2487 0.0000 0.2487
2009-12-16 0.0595 0.0000 0.0595 0.0000
2009-12-17 0.0000 0.5373 0.0000 0.5373
2009-12-18 0.7154 0.0000 0.7154 0.0000
2009-12-21 0.4986 0.0000 0.4986 0.0000
2009-12-22 0.2691 0.0000 0.2691 0.0000
2009-12-23 0.3290 0.0000 0.3290 0.0000
2009-12-24 0.4188 0.0000 0.4188 0.0000
2009-12-28 0.2393 0.0000 0.2393 0.0000
2009-12-29 0.0000 0.1895 0.0000 0.1895
2009-12-30 0.1397 0.0000 0.1397 0.0000
2009-12-31 0.0000 0.4188 0.0000 0.4188
2010-01-04 0.6680 0.0000 0.6680 0.0000
2010-01-05 0.0000 0.0000 0.0000 0.0000
2010-01-06 0.0000 0.2792 0.0000 0.2792
2010-01-07 0.0300 0.0000 0.0300 0.0000
2010-01-08 0.3788 0.0000 0.3788 0.0000
2010-01-11 0.0000 0.1894 0.0000 0.1894
2010-01-12 0.0000 0.5783 0.0000 0.5783
2010-01-13 0.5683 0.0000 0.5683 0.0000
2010-01-14 0.0399 0.0000 0.0399 0.0000
2010-01-15 0.0000 0.5384 0.0000 0.5384
2010-01-19 0.7378 0.0000 0.7378 0.0000
2010-01-20 0.0000 0.6680 0.0000 0.6680
2010-01-21 0.0000 0.4287 0.0000 0.4287
2010-01-22 0.0000 1.3260 0.0000 1.3260
2010-01-25 0.1495 0.0000 0.1495 0.0000
2010-01-26 0.0398 0.0000 0.0398 0.0000
2010-01-27 0.3491 0.0000 0.3491 0.0000
2010-01-28 0.0000 1.1467 0.0000 1.1467
2010-01-29 0.0000 0.7577 0.0000 0.7577
2010-02-01 0.4686 0.0000 0.4686 0.0000
In [51]:
def gain_loss_calc(price):
    """
    Returns a DataFrame containing the Gain and Loss from a price time series.
    Usually price is closing price.
    """
    if not isinstance(price, pd.Series):
        raise TypeError()
    chg = price.diff()
    gain = np.where(chg > 0, chg, 0)
    gain = np.abs(gain)
    gain = pd.Series(gain,index=price.index)
    loss = np.where(chg < 0, chg, 0)
    loss = np.abs(loss)
    loss = pd.Series(loss,index=price.index)
    df1 = pd.DataFrame(data={'Gain':gain,'Loss':loss})
    return df1
In [52]:
gldf1 = gain_loss_calc(df1['Close'])
gldf2 = pd.concat([gldf1,ref_gldf],axis=1)
gldf2.head(20)
Out[52]:
Gain Loss Gain Loss
Date
2009-12-14 0.0000 0.0000 0.0000 0.0000
2009-12-15 0.0000 0.2487 0.0000 0.2487
2009-12-16 0.0595 0.0000 0.0595 0.0000
2009-12-17 0.0000 0.5373 0.0000 0.5373
2009-12-18 0.7154 0.0000 0.7154 0.0000
2009-12-21 0.4986 0.0000 0.4986 0.0000
2009-12-22 0.2691 0.0000 0.2691 0.0000
2009-12-23 0.3290 0.0000 0.3290 0.0000
2009-12-24 0.4188 0.0000 0.4188 0.0000
2009-12-28 0.2393 0.0000 0.2393 0.0000
2009-12-29 0.0000 0.1895 0.0000 0.1895
2009-12-30 0.1397 0.0000 0.1397 0.0000
2009-12-31 0.0000 0.4188 0.0000 0.4188
2010-01-04 0.6680 0.0000 0.6680 0.0000
2010-01-05 0.0000 0.0000 0.0000 0.0000
2010-01-06 0.0000 0.2792 0.0000 0.2792
2010-01-07 0.0300 0.0000 0.0300 0.0000
2010-01-08 0.3788 0.0000 0.3788 0.0000
2010-01-11 0.0000 0.1894 0.0000 0.1894
2010-01-12 0.0000 0.5783 0.0000 0.5783
In [53]:
#now it looks like gain and loss are the same based on difference vs percent change
#TODO: Calculate avg gain and avg loss and compare

https://school.stockcharts.com/doku.php?id=technical_indicators:relative_strength_index_rsi

The very first calculations for average gain and average loss are simple 14-period averages:

  • First Average Gain = Sum of Gains over the past 14 periods / 14.
  • First Average Loss = Sum of Losses over the past 14 periods / 14

The second, and subsequent, calculations are based on the prior averages and the current gain loss:

  • Average Gain = [(previous Average Gain) x 13 + current Gain] / 14.
  • Average Loss = [(previous Average Loss) x 13 + current Loss] / 14.
In [54]:
# try to just add the first few examples and see what happens
g1 = gldf1['Gain'].iloc[0:15].sum()/14
g1
Out[54]:
0.23838571428571445
In [55]:
g2 = (g1*13)/14
g2
Out[55]:
0.22135816326530627
In [56]:
g3 = (g2*13 + 0.03)/14
g3
Out[56]:
0.2076897230320701
In [57]:
gldf1['Gain'].iloc[1:16].sum()/14
Out[57]:
0.23838571428571445
In [58]:
gldf1['Gain'].shape
Out[58]:
(33,)
In [59]:
first_avg_gain = gldf1['Gain'].iloc[0:15].sum()/14
print("First Average Gain =",first_avg_gain)
avg_gain_arry = np.zeros(gldf1['Gain'].shape)
for i in range(14,len(avg_gain_arry)):
    if i == 14:
        avg_gain_arry[i] = first_avg_gain
    else:
        avg_gain_arry[i] = (avg_gain_arry[i-1]*13+gldf1['Gain'].iloc[i])/14
        
avg_gain = pd.Series(avg_gain_arry,name='Avg Gain',index=gldf1.index)
gldf3 = pd.concat([avg_gain,df1[['Avg Gain','Gain']]],axis=1)
gldf3.head(20)
First Average Gain = 0.23838571428571445
Out[59]:
Avg Gain Avg Gain Gain
Date
2009-12-14 0.000000 NaN NaN
2009-12-15 0.000000 NaN 0.0000
2009-12-16 0.000000 NaN 0.0595
2009-12-17 0.000000 NaN 0.0000
2009-12-18 0.000000 NaN 0.7154
2009-12-21 0.000000 NaN 0.4986
2009-12-22 0.000000 NaN 0.2691
2009-12-23 0.000000 NaN 0.3290
2009-12-24 0.000000 NaN 0.4188
2009-12-28 0.000000 NaN 0.2393
2009-12-29 0.000000 NaN 0.0000
2009-12-30 0.000000 NaN 0.1397
2009-12-31 0.000000 NaN 0.0000
2010-01-04 0.000000 NaN 0.6680
2010-01-05 0.238386 0.238386 0.0000
2010-01-06 0.221358 0.221358 0.0000
2010-01-07 0.207690 0.207690 0.0300
2010-01-08 0.219912 0.219912 0.3788
2010-01-11 0.204204 0.204204 0.0000
2010-01-12 0.189618 0.189618 0.0000
In [60]:
first_avg_loss = gldf1['Loss'].iloc[0:15].sum()/14
print("First Average Loss =",first_avg_loss)
avg_loss_arry = np.zeros(gldf1['Loss'].shape)
for i in range(14,len(avg_loss_arry)):
    if i == 14:
        avg_loss_arry[i] = first_avg_loss
    else:
        avg_loss_arry[i] = (avg_loss_arry[i-1]*13+gldf1['Loss'].iloc[i])/14
        
avg_loss = pd.Series(avg_loss_arry,name='Avg Loss',index=gldf1.index)
gldf3 = pd.concat([avg_loss,df1[['Avg Loss','Loss']]],axis=1)
gldf3.head(20)
First Average Loss = 0.09959285714285773
Out[60]:
Avg Loss Avg Loss Loss
Date
2009-12-14 0.000000 NaN NaN
2009-12-15 0.000000 NaN 0.2487
2009-12-16 0.000000 NaN 0.0000
2009-12-17 0.000000 NaN 0.5373
2009-12-18 0.000000 NaN 0.0000
2009-12-21 0.000000 NaN 0.0000
2009-12-22 0.000000 NaN 0.0000
2009-12-23 0.000000 NaN 0.0000
2009-12-24 0.000000 NaN 0.0000
2009-12-28 0.000000 NaN 0.0000
2009-12-29 0.000000 NaN 0.1895
2009-12-30 0.000000 NaN 0.0000
2009-12-31 0.000000 NaN 0.4188
2010-01-04 0.000000 NaN 0.0000
2010-01-05 0.099593 0.099593 0.0000
2010-01-06 0.112422 0.112422 0.2792
2010-01-07 0.104392 0.104392 0.0000
2010-01-08 0.096935 0.096935 0.0000
2010-01-11 0.103540 0.103540 0.1894
2010-01-12 0.137451 0.137451 0.5783
In [61]:
# Now to calculate relative strength
RS = avg_gain/avg_loss
RS.name = "RS"
rsdf = pd.concat([RS,df1['RS']],axis=1)
rsdf.head(20)
Out[61]:
RS RS
Date
2009-12-14 NaN NaN
2009-12-15 NaN NaN
2009-12-16 NaN NaN
2009-12-17 NaN NaN
2009-12-18 NaN NaN
2009-12-21 NaN NaN
2009-12-22 NaN NaN
2009-12-23 NaN NaN
2009-12-24 NaN NaN
2009-12-28 NaN NaN
2009-12-29 NaN NaN
2009-12-30 NaN NaN
2009-12-31 NaN NaN
2010-01-04 NaN RS
2010-01-05 2.393603 2.3936
2010-01-06 1.968994 1.96899
2010-01-07 1.989521 1.98952
2010-01-08 2.268647 2.26865
2010-01-11 1.972225 1.97222
2010-01-12 1.379528 1.37953
In [67]:
# Now to calculate RSI
RSI = 100-(100/(1+RS))
RSI.name = "RSI"
rsidf = pd.concat([RSI,df1['RSI']],axis=1)
rsidf.tail(15)
Out[67]:
RSI RSI
Date
2010-01-11 66.355169 66.3552
2010-01-12 57.974856 57.9749
2010-01-13 62.929607 62.9296
2010-01-14 63.257148 63.2571
2010-01-15 56.059299 56.0593
2010-01-19 62.377071 62.3771
2010-01-20 54.707573 54.7076
2010-01-21 50.422774 50.4228
2010-01-22 39.989823 39.9898
2010-01-25 41.460482 41.4605
2010-01-26 41.868916 41.8689
2010-01-27 45.463212 45.4632
2010-01-28 37.304042 37.304
2010-01-29 33.079523 33.0795
2010-02-01 37.772952 37.773
In [63]:
RSI.dtype
Out[63]:
dtype('float64')
In [64]:
rsi1 = df1['RSI']
rsi2 = rsi1.iloc[14:-1]
rsi2.astype('float64')
Out[64]:
Date
2010-01-05    70.532789
2010-01-06    66.318562
2010-01-07    66.549830
2010-01-08    69.406305
2010-01-11    66.355169
2010-01-12    57.974856
2010-01-13    62.929607
2010-01-14    63.257148
2010-01-15    56.059299
2010-01-19    62.377071
2010-01-20    54.707573
2010-01-21    50.422774
2010-01-22    39.989823
2010-01-25    41.460482
2010-01-26    41.868916
2010-01-27    45.463212
2010-01-28    37.304042
2010-01-29    33.079523
Name: RSI, dtype: float64
In [71]:
gldf_1 = std_calcs.gain_loss_calc(df1['Close'])
gldf_compare = pd.concat([gldf_1,df1['Gain'],df1['Loss']],axis=1)
gldf_compare.head(5)
Out[71]:
Gain Loss Gain Loss
Date
2009-12-14 0.0000 0.0000 NaN NaN
2009-12-15 0.0000 0.2487 0.0000 0.2487
2009-12-16 0.0595 0.0000 0.0595 0.0000
2009-12-17 0.0000 0.5373 0.0000 0.5373
2009-12-18 0.7154 0.0000 0.7154 0.0000
2009-12-21 0.4986 0.0000 0.4986 0.0000
2009-12-22 0.2691 0.0000 0.2691 0.0000
2009-12-23 0.3290 0.0000 0.3290 0.0000
2009-12-24 0.4188 0.0000 0.4188 0.0000
2009-12-28 0.2393 0.0000 0.2393 0.0000
In [72]:
rsi_1 = std_calcs.rsi_calc(gldf_1['Gain'],gldf_1['Loss'],14)
rsi_compare = pd.concat([rsi_1,df1['RSI']],axis=1)
rsi_compare.head(20)
Out[72]:
RSI RSI
Date
2009-12-14 NaN NaN
2009-12-15 NaN NaN
2009-12-16 NaN NaN
2009-12-17 NaN NaN
2009-12-18 NaN NaN
2009-12-21 NaN NaN
2009-12-22 NaN NaN
2009-12-23 NaN NaN
2009-12-24 NaN NaN
2009-12-28 NaN NaN
2009-12-29 NaN NaN
2009-12-30 NaN NaN
2009-12-31 NaN NaN
2010-01-04 NaN RSI
2010-01-05 70.532789 70.5328
2010-01-06 66.318562 66.3186
2010-01-07 66.549830 66.5498
2010-01-08 69.406305 69.4063
2010-01-11 66.355169 66.3552
2010-01-12 57.974856 57.9749