Briefly about the RSI and Stochastic oscillators
The operating principle of oscillators is based on comparing the current price of an asset with its price levels for a certain period. For example, if the current price is close to the upper range of the last period, the oscillator will show high values, indicating overbought. Conversely, if the price is close to the lower range, it indicates oversold conditions.
Oscillators can be used in a variety of market conditions, including trending and sideways markets. In trending markets, oscillators help to find entry points in the direction of the main trend, and in side markets, they help identify reversal points.
Relative Strength Index (RSI)
RSI was developed by G. Wells Wilder and presented in his book “New Concepts in Technical Trading Systems” in 1978. RSI is an oscillator that measures the speed and change in an asset's price movements by assessing whether it is overbought or oversold. It ranges between values from 0 to 100 and helps traders determine when to buy or sell assets.
Calculating RSI involves two steps:
Relative Strength (RS) Calculation:
Calculation of RSI itself:
The standard period for calculating RSI is 14 days. For example, if an asset closed higher on 7 of the last 14 days with an average gain of 1%, and the remaining 7 days closed lower with an average loss of 0.8%, then the initial RS value would be 1.25 (1% / 0.8%). Next, the formula is applied to obtain RSI.
RSI values are interpreted as follows:
Above 70 – the asset is overbought, there may be a downward correction.
Below 30 — the asset is oversold, perhaps the price is expected to rise.
RSI helps traders identify overbought and oversold market conditions, which can signal possible trend reversals. For example, if the RSI is above 70, it indicates that the asset is overbought, which could lead to a correction. Conversely, if the RSI falls below 30, it signals oversold conditions, which could cause the price to rise.
RSI Divergences occur when the price trend of an asset and the trend of the RSI itself diverge, which may indicate a weakening of the current trend and a possible reversal.
Bullish divergence occurs when price makes a new low and the RSI makes a higher low. This indicates a weakening of the downtrend and a possible upward reversal.
Bearish divergence occurs when price makes a new high and the RSI makes a lower high. This signals weakness in the uptrend and a possible downward reversal.
Code examples for calculating RSI
Python
import pandas as pd
def calculate_rsi(data, period=14):
delta = data['Close'].diff()
gain = (delta.where(delta > 0, 0)).fillna(0)
loss = (-delta.where(delta < 0, 0)).fillna(0)
avg_gain = gain.rolling(window=period).mean()
avg_loss = loss.rolling(window=period).mean()
rs = avg_gain / avg_loss
rsi = 100 - (100 / (1 + rs))
return rsi
# Example usage
data = pd.DataFrame({
'Close': [45.15, 46.23, 45.56, 46.33, 45.86, 46.71, 47.24, 46.69, 47.28, 47.88, 48.07, 47.86, 47.33, 47.59]
})
data['RSI'] = calculate_rsi(data)
print(data)
JavaScript
function calculateRSI(closes, period = 14) {
let gains = [];
let losses = [];
for (let i = 1; i < closes.length; i++) {
let change = closes[i] - closes[i - 1];
gains.push(change > 0 ? change : 0);
losses.push(change < 0 ? -change : 0);
}
let avgGain = gains.slice(0, period).reduce((a, b) => a + b, 0) / period;
let avgLoss = losses.slice(0, period).reduce((a, b) => a + b, 0) / period;
let rs = avgGain / avgLoss;
let rsi = [100 - (100 / (1 + rs))];
for (let i = period; i < gains.length; i++) {
avgGain = (avgGain * (period - 1) + gains[i]) / period;
avgLoss = (avgLoss * (period - 1) + losses[i]) / period;
rs = avgGain / avgLoss;
rsi.push(100 - (100 / (1 + rs)));
}
return rsi;
}
// example
let closes = [45.15, 46.23, 45.56, 46.33, 45.86, 46.71, 47.24, 46.69, 47.28, 47.88, 48.07, 47.86, 47.33, 47.59];
console.log(calculateRSI(closes));
R
calculate_rsi <- function(prices, n = 14) {
deltas <- diff(prices)
seed <- deltas[1:n]
up <- seed[seed >= 0]
down <- -seed[seed < 0]
up[is.na(up)] <- 0
down[is.na(down)] <- 0
avg_gain <- sum(up) / n
avg_loss <- sum(down) / n
rs <- avg_gain / avg_loss
rsi <- 100 - (100 / (1 + rs))
rsi_values <- c(rep(NA, n), rsi)
for (i in (n+1):length(deltas)) {
delta <- deltas[i]
gain <- ifelse(delta > 0, delta, 0)
loss <- ifelse(delta < 0, -delta, 0)
avg_gain <- (avg_gain * (n - 1) + gain) / n
avg_loss <- (avg_loss * (n - 1) + loss) / n
rs <- avg_gain / avg_loss
rsi <- 100 - (100 / (1 + rs))
rsi_values <- c(rsi_values, rsi)
}
return(rsi_values)
}
# example
prices <- c(45.15, 46.23, 45.56, 46.33, 45.86, 46.71, 47.24, 46.69, 47.28, 47.88, 48.07, 47.86, 47.33, 47.59)
rsi <- calculate_rsi(prices)
print(rsi)
Stochastic Oscillator
The stochastic oscillator was developed by George Lane in the late 1950s. This is a technical indicator that measures the ratio of the current closing price to the price range over a certain period of time. The basic idea behind a stochastic oscillator is that in an uptrend, closing prices tend to be closer to the top end of the range, and in a downtrend, closing prices tend to be closer to the bottom end.
The stochastic oscillator consists of two main components: the %K line and the %D line.
%K line calculated by the formula
Where:— current closing price,
— the lowest price for the last N periods,
— the highest price over the last N periods.
%D line represents a moving average of the %K line over three periods:
The default period is 14 days for %K and 3 days for %D, but these parameters can be changed depending on preference.
Stochastic oscillator values range from 0 to 100. Levels above 80 indicate the asset is overbought, and levels below 20 indicate it is oversold.
Overbought: When the oscillator exceeds 80, it may indicate a possible downward reversal. Traders use this as a sell signal.
Oversold: When the oscillator falls below 20, it could indicate a possible reversal to the upside. This is a signal to buy.
The stochastic oscillator is good in sideways markets, where it helps identify short-term fluctuations. In trending markets, the oscillator may remain in the overbought or oversold zone for a long time, which requires additional. indicators to confirm signals.
Stochastic oscillator divergences occur when the direction of the oscillator does not coincide with the direction of the asset price.
Examples of calculations in code
Python
import pandas as pd
def calculate_stochastic_oscillator(data, k_period=14, d_period=3):
low_min = data['Low'].rolling(window=k_period).min()
high_max = data['High'].rolling(window=k_period).max()
data['%K'] = 100 * ((data['Close'] - low_min) / (high_max - low_min))
data['%D'] = data['%K'].rolling(window=d_period).mean()
return data
# example
data = pd.DataFrame({
'High': [127.01, 128.48, 128.43, 128.72, 128.22, 128.43, 128.72, 128.21, 128.35, 128.75, 128.37, 128.57, 128.88, 128.78],
'Low': [125.36, 126.41, 126.74, 126.82, 126.32, 126.74, 126.82, 126.41, 126.35, 126.82, 126.41, 126.72, 126.92, 126.72],
'Close': [126.45, 127.98, 127.98, 128.43, 127.38, 127.68, 128.43, 127.88, 127.88, 128.28, 127.78, 128.15, 128.43, 128.23]
})
data = calculate_stochastic_oscillator(data)
print(data[['%K', '%D']])
JavaScript
function calculateStochasticOscillator(highs, lows, closes, kPeriod = 14, dPeriod = 3) {
let stochastics = [];
let percentK = [];
let percentD = [];
for (let i = 0; i < closes.length; i++) {
if (i >= kPeriod - 1) {
let highMax = Math.max(...highs.slice(i - kPeriod + 1, i + 1));
let lowMin = Math.min(...lows.slice(i - kPeriod + 1, i + 1));
let k = ((closes[i] - lowMin) / (highMax - lowMin)) * 100;
percentK.push(k);
if (percentK.length >= dPeriod) {
let d = percentK.slice(-dPeriod).reduce((a, b) => a + b) / dPeriod;
percentD.push(d);
} else {
percentD.push(null);
}
} else {
percentK.push(null);
percentD.push(null);
}
stochastics.push({
K: percentK[percentK.length - 1],
D: percentD[percentD.length - 1]
});
}
return stochastics;
}
// example
let highs = [127.01, 128.48, 128.43, 128.72, 128.22, 128.43, 128.72, 128.21, 128.35, 128.75, 128.37, 128.57, 128.88, 128.78];
let lows = [125.36, 126.41, 126.74, 126.82, 126.32, 126.74, 126.82, 126.41, 126.35, 126.82, 126.41, 126.72, 126.92, 126.72];
let closes = [126.45, 127.98, 127.98, 128.43, 127.38, 127.68, 128.43, 127.88, 127.88, 128.28, 127.78, 128.15, 128.43, 128.23];
console.log(calculateStochasticOscillator(highs, lows, closes));
R
calculate_stochastic <- function(highs, lows, closes, k_period = 14, d_period = 3) {
K <- rep(NA, length(closes))
D <- rep(NA, length(closes))
for (i in seq(k_period, length(closes))) {
high_max <- max(highs[(i - k_period + 1):i])
low_min <- min(lows[(i - k_period + 1):i])
K[i] <- ((closes[i] - low_min) / (high_max - low_min)) * 100
}
for (i in seq((k_period + d_period - 1), length(closes))) {
D[i] <- mean(K[(i - d_period + 1):i], na.rm = TRUE)
}
return(data.frame(K = K, D = D))
}
# example
highs <- c(127.01, 128.48, 128.43, 128.72, 128.22, 128.43, 128.72, 128.21, 128.35, 128.75, 128.37, 128.57, 128.88, 128.78)
lows <- c(125.36, 126.41, 126.74, 126.82, 126.32, 126.74, 126.82, 126.41, 126.35, 126.82, 126.41, 126.72, 126.92, 126.72)
closes <- c(126.45, 127.98, 127.98, 128.43, 127.38, 127.68, 128.43, 127.88, 127.88, 128.28, 127.78, 128.15, 128.43, 128.23)
stochastic <- calculate_stochastic(highs, lows, closes)
print(stochastic)
Both indicators can be used in combination with other technical analysis tools to improve the accuracy of signals. For example, using the RSI and stochastic oscillator along with trend lines, moving averages, or support and resistance levels often improves trading strategies.
Experts from OTUS discuss more tools for data analysis in practical online courses. More details in the catalog.