title: Calculate RSI indicator from pandas DataFrame?
body: <h1>My problem</h1>
  
  <p>I tried many libraries on <strong>Github</strong> but all of them did not produce matching results for <strong>TradingView</strong> so I followed the formula on this <a href="https://school.stockcharts.com/doku.php?id=technical_indicators:relative_strength_index_rsi" rel="noreferrer"><strong>link</strong></a> to calculate <strong>RSI</strong> indicator. I calculated it with <strong>Excel</strong> and collated the results with <strong>TradingView</strong>. I know it's <strong>absolutely correct</strong> but, but I didn't find a way to calculate it with <strong>Pandas</strong>.</p>
  
  <h1>Formula</h1>
  
  <pre><code>              100
  RSI = 100 - --------
               1 + RS
  
  RS = Average Gain / Average Loss
  
  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.
  </code></pre>
  
  <h2>Expected Results</h2>
  
  <pre><code>     close   change     gain     loss     avg_gian    avg_loss        rs  \
  0    4724.89      NaN      NaN      NaN          NaN         NaN       NaN   
  1    4378.51  -346.38     0.00   346.38          NaN         NaN       NaN   
  2    6463.00  2084.49  2084.49     0.00          NaN         NaN       NaN   
  3    9838.96  3375.96  3375.96     0.00          NaN         NaN       NaN   
  4   13716.36  3877.40  3877.40     0.00          NaN         NaN       NaN   
  5   10285.10 -3431.26     0.00  3431.26          NaN         NaN       NaN   
  6   10326.76    41.66    41.66     0.00          NaN         NaN       NaN   
  7    6923.91 -3402.85     0.00  3402.85          NaN         NaN       NaN   
  8    9246.01  2322.10  2322.10     0.00          NaN         NaN       NaN   
  9    7485.01 -1761.00     0.00  1761.00          NaN         NaN       NaN   
  10   6390.07 -1094.94     0.00  1094.94          NaN         NaN       NaN   
  11   7730.93  1340.86  1340.86     0.00          NaN         NaN       NaN   
  12   7011.21  -719.72     0.00   719.72          NaN         NaN       NaN   
  13   6626.57  -384.64     0.00   384.64          NaN         NaN       NaN   
  14   6371.93  -254.64     0.00   254.64   931.605000  813.959286  1.144535   
  15   4041.32 -2330.61     0.00  2330.61   865.061786  922.291480  0.937948   
  16   3702.90  -338.42     0.00   338.42   803.271658  880.586374  0.912201   
  17   3434.10  -268.80     0.00   268.80   745.895111  836.887347  0.891273   
  18   3813.69   379.59   379.59     0.00   719.730460  777.109680  0.926163   
  19   4103.95   290.26   290.26     0.00   689.053999  721.601845  0.954895   
  20   5320.81  1216.86  1216.86     0.00   726.754428  670.058856  1.084613   
  21   8555.00  3234.19  3234.19     0.00   905.856968  622.197509  1.455899   
  22  10854.10  2299.10  2299.10     0.00  1005.374328  577.754830  1.740140   
  
         rsi_14  
  0         NaN  
  1         NaN  
  2         NaN  
  3         NaN  
  4         NaN  
  5         NaN  
  6         NaN  
  7         NaN  
  8         NaN  
  9         NaN  
  10        NaN  
  11        NaN  
  12        NaN  
  13        NaN  
  14  53.369848  
  15  48.399038  
  16  47.704239  
  17  47.125561  
  18  48.083322  
  19  48.846358  
  20  52.029461  
  21  59.281719  
  22  63.505515  
  </code></pre>
  
  <h1>My Code</h1>
  
  <h2>Import</h2>
  
  <pre><code>import pandas as pd
  import numpy as np
  </code></pre>
  
  <h2>Load data</h2>
  
  <pre><code>df = pd.read_csv("rsi_14_test_data.csv")
  close = df['close']
  print(close)
  
  0      4724.89
  1      4378.51
  2      6463.00
  3      9838.96
  4     13716.36
  5     10285.10
  6     10326.76
  7      6923.91
  8      9246.01
  9      7485.01
  10     6390.07
  11     7730.93
  12     7011.21
  13     6626.57
  14     6371.93
  15     4041.32
  16     3702.90
  17     3434.10
  18     3813.69
  19     4103.95
  20     5320.81
  21     8555.00
  22    10854.10
  Name: close, dtype: float64
  </code></pre>
  
  <h2>Change</h2>
  
  <p>Calculate change every row</p>
  
  <pre><code>change = close.diff(1)
  print(change)
  
  0         NaN
  1     -346.38
  2     2084.49
  3     3375.96
  4     3877.40
  5    -3431.26
  6       41.66
  7    -3402.85
  8     2322.10
  9    -1761.00
  10   -1094.94
  11    1340.86
  12    -719.72
  13    -384.64
  14    -254.64
  15   -2330.61
  16    -338.42
  17    -268.80
  18     379.59
  19     290.26
  20    1216.86
  21    3234.19
  22    2299.10
  Name: close, dtype: float64
  </code></pre>
  
  <h2>Gain and loss</h2>
  
  <p>get gain and loss from change</p>
  
  <pre><code>is_gain, is_loss = change &gt; 0, change &lt; 0
  gain, loss = change, -change
  gain[is_loss] = 0
  loss[is_gain] = 0
  ​
  gain.name = 'gain'
  loss.name = 'loss'
  print(loss)
  
  0         NaN
  1      346.38
  2        0.00
  3        0.00
  4        0.00
  5     3431.26
  6        0.00
  7     3402.85
  8        0.00
  9     1761.00
  10    1094.94
  11       0.00
  12     719.72
  13     384.64
  14     254.64
  15    2330.61
  16     338.42
  17     268.80
  18       0.00
  19       0.00
  20       0.00
  21       0.00
  22       0.00
  Name: loss, dtype: float64
  </code></pre>
  
  <h2>Calculate fist avg gain and loss</h2>
  
  <p>Mean of n prior rows</p>
  
  <pre><code>n = 14
  avg_gain = change * np.nan
  avg_loss = change * np.nan
  ​
  avg_gain[n] = gain[:n+1].mean()
  avg_loss[n] = loss[:n+1].mean()
  ​
  avg_gain.name = 'avg_gain'
  avg_loss.name = 'avg_loss'
  ​
  avg_df = pd.concat([gain, loss, avg_gain, avg_loss], axis=1)
  print(avg_df)
  
         gain     loss  avg_gain    avg_loss
  0       NaN      NaN       NaN         NaN
  1      0.00   346.38       NaN         NaN
  2   2084.49     0.00       NaN         NaN
  3   3375.96     0.00       NaN         NaN
  4   3877.40     0.00       NaN         NaN
  5      0.00  3431.26       NaN         NaN
  6     41.66     0.00       NaN         NaN
  7      0.00  3402.85       NaN         NaN
  8   2322.10     0.00       NaN         NaN
  9      0.00  1761.00       NaN         NaN
  10     0.00  1094.94       NaN         NaN
  11  1340.86     0.00       NaN         NaN
  12     0.00   719.72       NaN         NaN
  13     0.00   384.64       NaN         NaN
  14     0.00   254.64   931.605  813.959286
  15     0.00  2330.61       NaN         NaN
  16     0.00   338.42       NaN         NaN
  17     0.00   268.80       NaN         NaN
  18   379.59     0.00       NaN         NaN
  19   290.26     0.00       NaN         NaN
  20  1216.86     0.00       NaN         NaN
  21  3234.19     0.00       NaN         NaN
  22  2299.10     0.00       NaN         NaN
  </code></pre>
  
  <p>The very first calculations for average gain and the average loss is ok but I don't know how to apply pandas.core.window.Rolling.apply for the second, and subsequent because they are in many rows and different columns.
  It may be something like this:</p>
  
  <pre><code>avg_gain[n] = (avg_gain[n-1]*13 + gain[n]) / 14
  </code></pre>
  
  <h2>My Wish - My Question</h2>
  
  <ul>
  <li>The best way to calculate and work with technical indicators?</li>
  <li>Complete the above code in "Pandas Style".</li>
  <li>Does the traditional way of coding with loops reduce performance compared to Pandas?</li>
  </ul>