How to calculate it correctly? ( Post in other programming languages are also okay )
Well, let me add one such, from QuantFX
module
One may meet many formulations, some with examples, some with validation data-set(s), so let me pick one such, using a numba.jit
decorated python code, with a few numpy
vectorised tricks:
def RSI_func( priceVEC, RSI_period = 14 ):
"""
__doc__
USE:
RSI_func( priceVEC, RSI_period = 14 )
Developed by J. Welles Wilder and introduced in his 1978 book,
New Concepts in Technical Trading Systems, the Relative Strength Index
(RSI) is an extremely useful and popular momentum oscillator.
The RSI compares the magnitude of a stock's recent gains
to the magnitude of its recent losses and turns that information
into a number that ranges from 0 to 100.
It takes a single parameter, the number of time periods to use
in the calculation. In his book, Wilder recommends using 14 periods.
The RSI's full name is actually rather unfortunate as it is easily
confused with other forms of Relative Strength analysis such as
John Murphy's "Relative Strength" charts and IBD's "Relative Strength"
rankings.
Most other kinds of "Relative Strength" stuff involve using
more than one stock in the calculation. Like most true indicators,
the RSI only needs one stock to be computed.
In order to avoid confusion,
many people avoid using the RSI's full name and just call it "the RSI."
( Written by Nicholas Fisher)
PARAMS:
pricesVEC - a vector of price-DOMAIN-alike data in natural order
RSI_period - a positive integer for an RSI averaging period
RETURNS:
a vector of RSI values
EXAMPLE:
>>> RSI_func( np.asarray( [ 46.1250, 47.1250, 46.4375, 46.9375, 44.9375,
44.2500, 44.6250, 45.7500, 47.8125, 47.5625,
47.0000, 44.5625, 46.3125, 47.6875, 46.6875,
45.6875, 43.0625, 43.5625, 44.8750, 43.6875
]
),
RSI_period = 14
)
array( [ 51.77865613, 51.77865613, 51.77865613, 51.77865613, 51.77865613, 51.77865613, 51.77865613,
51.77865613, 51.77865613, 51.77865613, 51.77865613, 51.77865613, 51.77865613,
51.77865613, 48.47708511, 41.07344947, 42.86342911, 47.38184958, 43.99211059
]
)
OUGHT BE:
51.779, 48.477, 41.073, 42.863, 47.382, 43.992
[PASSED]
Ref.s:
>>> http://cns.bu.edu/~gsc/CN710/fincast/Technical%20_indicators/Relative%20Strength%20Index%20(RSI).htm
"""
deltas = np.diff( priceVEC )
seed = deltas[:RSI_period]
up = seed[seed >= 0].sum() / RSI_period
down = -seed[seed < 0].sum() / RSI_period
rs = up / down
rsi = 50. * np.ones_like( priceVEC ) # NEUTRAL VALUE PRE-FILL
rsi[:RSI_period] = 100. - ( 100. / ( 1. + rs ) )
for i in np.arange( RSI_period, len( priceVEC )-1 ):
delta = deltas[i]
if delta > 0:
upval = delta
downval = 0.
else:
upval = 0.
downval = -delta
up = ( up * ( RSI_period - 1 ) + upval ) / RSI_period
down = ( down * ( RSI_period - 1 ) + downval ) / RSI_period
rs = up / down
rsi[i] = 100. - ( 100. / ( 1. + rs ) )
return rsi[:-1]
Given your wish was to " exactly mirror " someone other's graph, there is a safest mode to cross-check what formulation did they actually used for RSI-calculation. It is common to see differences, so " exact " match requires sort of investigation what they did actually use for generating their data ( also notice a respective administrative UTC-offset difference(s), if working with D1-time-frame ).