Add a professional touch to your finances

Should you include RIL in your portfolio?

<strong>Sayantan Ghosh</strong>
Sayantan Ghosh

MBA (Finance), FMVA®

Reliance Industries (NSE: RIL) has been in limelight for quite some time following a streak of investments in its Jio and Retail arms. In spite of there being more than 5,000 listed stocks on Indian bourses, RIL itself accounts for almost 7% of the total Assets Under Management (AUM) of all Equity Mutual Funds (MFs). Have you ever thought why investors are so overweight on RIL? Let’s find out.


This entire analysis is a part of my initial R projects. All views expressed are my own and are not to be used as formal investment advice. Personal research is advised before investing.

Volatility & Track Record

RIL is a highly liquid scrip allowing the market to discover the ‘fair price’ on its own once any material information reaches the exchanges.

Fig: RIL monthly returns over last 10 years

RIL has shown good volatility, ranging between 5-10% MoM for the last 10 years, and has been a favorite for both short and long term investors. It exerts a cyclical trend, creating opportunities for investors to exploit a complete trough – crest phase before moving to the next cycle.

Fig: RIL has rallied to 4.8x its 2010 price in the last decade

“Past performers tend to perform better in the future as well” – Investors who believe in trends often look for high growth multi-baggers for the long term. RIL has shown a consistent track record of growth in Revenues and Bottom line (except some minor disruptions in some quarters). Its diversification from an Oil & Gas company to include new business lines like Telecom, Retail, Broadband and Apparel has been appreciated by investors who have lapped up RIL shares in spite of its rising prices.

Analysis of RIL returns (R code)

# Extracting RIL prices
ril <- tq_get("RELIANCE.NS", from ="2010-11-01", to ="2020-11-01", get ="stock.prices") View(ril) ril %>%
ggplot(aes(x = date, y = adjusted)) +
geom_line() +
ggtitle("RIL prices 2010-2020") +
labs(x = "Date", "Price") +
scale_x_date(date_breaks = "years", date_labels = "%Y") +
labs(x = "Date", y = "Adjusted Price")

# Calculating monthly returns
ril_monthly_returns <- ril %>%
tq_transmute(select = adjusted,
mutate_fun = periodReturn,
period = "monthly",
col_rename = "RIL_returns")

# Plot RIL monthly returns
ril_monthly_returns %>%
ggplot(aes(x = date, y = RIL_returns)) +
geom_bar(stat = "identity") +
theme_classic() +
labs(x = "Date", y = "Monthly returns") +
ggtitle("Monthly Returns for Reliance") +
geom_hline(yintercept = 0) +
scale_y_continuous(breaks = seq(-0.6,0.8,0.1),
labels = scales::percent) +
scale_x_date(date_breaks = "years", date_labels = "%Y")

# PV of Rs. 100 investment
ril_monthly_returns %>%
mutate(cr = 100*cumprod(1 + RIL_returns)) %>%
mutate(cumulative_returns = (cr - 1)) %>%
ggplot(aes(x = date, y = cumulative_returns)) +
geom_line() +
theme_classic() +
labs(x = "Date", y = "RIL Cumulative Returns") +
ggtitle("PV of Rs.100 invested in RIL for 2010-2020") +
scale_y_continuous(limits = c(0,500))

Portfolio Optimization

To understand whether RIL plays a significant role in maximizing our desired returns, we perform a Portfolio Optimization exercise using 5 large-cap stocks from different GICS sectors:

  1. Reliance Industries (RIL)
  2. HDFC Bank (HDFCBK)
  3. Tata Consultancy Services (TCS)
  4. Cipla Pharmaceuticals (CIPLA)
  5. Hindustan Unilever (HUL)

Our aim is to maximize risk-adjusted-returns for the above portfolio, thus obtaining weights for each of the 5 stocks to maximize Sharpe Ratio (excess return over the risk free rate per additional unit of risk). We’ll also look at a defensive outlook (Minimum variance portfolio) and interpret how RIL plays a role in both of the portfolio expectations.

Correlation Matrix

Before creating a portfolio, we look at the correlation of the above 5 stocks with Nifty 50 to track their respective relative movements w.r.t. the index.

Fig: Correlation plot of 5 stocks & Nifty 50 (created using R)

As expected, RIL and HDFC Bank, being the two largest Nifty 50 constituents, exhibit a strong correlation with the index. However, CIPLA and HUL show defensive behavior by exhibiting low correlation, which indicates that these 2 stocks can be used to create a defensive hedge against unexpected downside of the first 2 stocks.

Optimal Portfolio Allocation

We use an iterative process to allot weights to each of the stocks and obtain portfolio returns & risk for that iteration. Finally, the program calculates the Sharpe Ratio and assigns it to the respective vector.

Sharpe Ratio = (Portfolio returns – Risk free return)/Portfolio risk

Here, we have taken 10 year G-sec yield of 5.9% p.a. as the Risk free rate of return. The assignment of Sharpe ratio values to the vector nodes continues till the entire port is filled and then we perform a maxima search (for Tangency portfolio) or risk minima search (for Minimum variance portfolio). Finally, the optimum weights are tabulated and the Tangency portfolio weights are plotted.

Fig: Optimal portfolio allocation for highest Sharpe ratio
Dynamic Portfolio Allocation Tool code (R)
monthly_returns <- function(ticker, base_year)
# Obtain stock price data from Yahoo! Finance
stock <- getSymbols(ticker, src = "yahoo", auto.assign = FALSE)
# Remove missing values
stock <- na.omit(stock)
# Keep only adjusted closing stock prices
stock <- stock[, 6]

# Confine our observations to begin at the base year and end at the last available trading day
horizon <- paste0(as.character(base_year), "/", as.character(Sys.Date()))
stock <- stock[horizon]

# Calculate monthly arithmetic returns
data <- periodReturn(stock, period = "monthly", type = "arithmetic")

# Assign to the global environment to be accessible
assign(ticker, data, envir = .GlobalEnv)
# Call our function for each stock
a <- monthly_returns("RELIANCE.NS", 2017)
b <- monthly_returns("HDFCBANK.NS", 2017)
c <- monthly_returns("TCS.NS", 2017)
d <- monthly_returns("CIPLA.NS", 2017)
e <- monthly_returns("HINDUNILVR.NS", 2017)

# Get Nifty 50 Data
f <- monthly_returns("^NSEI", 2017)

# Merge all the data and create Corrplot
returns <- merge.xts(a,b,c,d,e,f)
colnames(returns) <- c("RIL", "HDFCBK", "TCS", "CIPLA", "HUL", "NIFTY50")

# Starting Portfolio optimization
print(round(returns, 3))
meanret <- colMeans(returns)

# Random asset weights
wts <- runif(n = length(colnames(returns))-1)
wts <- wts/sum(wts)
wts[6] = 0

#Risk-return framework
port_returns <- (sum(wts * meanret) + 1)^12 - 1
port_risk <- sqrt((t(wts) %*% (cor(returns) %*% wts))/21)

#Sharpe Ratio (RFR = 5.9% p.a.)
sharpe_ratio <- ((port_returns-0.059)/port_risk)

# Optimization Vector spaces
num_port <- 1000
all_wts <- matrix(nrow = num_port,
ncol = length(colnames(returns)))
port_returns <- vector('numeric', length = num_port)
port_risk <- vector('numeric', length = num_port)
sharpe_ratio <- vector('numeric', length = num_port)

# Creating iterative loop
for (i in seq_along(port_returns)) {

wts <- runif(length(colnames(returns))-1)
wts <- wts/sum(wts)

# Storing weight in the matrix
all_wts[i,] <- wts

# Portfolio returns

port_ret <- sum(wts * meanret)
port_ret <- ((port_ret + 1)^12) - 1

# Storing Portfolio Returns values
port_returns[i] <- port_ret

# Creating and storing portfolio risk
port_sd <- sqrt((t(wts) %*% (cor(returns) %*% wts))/21)
port_risk[i] <- port_sd

# Creating and storing Portfolio Sharpe Ratios

sr <- (port_ret-0.059)/port_sd
sharpe_ratio[i] <- sr

#Creating data tables
portfolio_values <- tibble(Return = port_returns,
Risk = port_risk,
Sharpe_Ratio = sharpe_ratio)

# Converting matrix to a tibble and changing column names
all_wts <- tk_tbl(all_wts)
colnames(all_wts) <- colnames(returns)

# Combing all the values together
portfolio_values <- tk_tbl(cbind(all_wts, portfolio_values))

#Optimal portfolios
min_var <- portfolio_values[which.min(portfolio_values$Risk),]
max_sr <- portfolio_values[which.max(portfolio_values$Sharpe_Ratio),]

#Optimal allocation plots (Max SR)
com <- c(RIL,HDFCBank,TCS,Cipla,HUL)
opwt <- c(max_sr$RIL,max_sr$HDFCBK,max_sr$TCS,max_sr$CIPLA,max_sr$HUL)
dtf <- data.frame(com,opwt)
ggplot() + geom_point(data=dtf, aes(x=dtf$com,y=dtf$opwt),size=5,color="green")+labs(title = "Dynamic Portfolio Allocation", x = "Stock", y = "Weight")

Interpretation of Results

Portfolio Weights
TypeRILHDFCBKTCSCIPLAHULAnnualized Returns RiskSharpe Ratio
Minimum variance0.0020.2720.0210.3120.3930.2420.1191.55
Table: Final portfolio weights for Optimum (max Sharpe Ratio) and Minimum variance portfolios

a) Optimum (Maximum Sharpe ratio) portfolio:

A maximum Sharpe ratio of 2.16 is obtained with maximum portfolio allocation (54.5%) to RIL. This result supports the investment approach followed by most Fund managers as well, i.e. RIL is one of the prime cuts if you’re looking to beat the market consistently. The high weightage to RIL is partially balanced by the allocation to HUL, which is a defensive FMCG stock and brings down the overall risk of the portfolio.

b) Minimum variance portfolio:

By drawing down on the portfolio allocation to RIL, we obtain a significantly lower (25% reduction) in overall risk. The entire allocation in Tangency portfolio now gets distributed between HDFC Bank, CIPLA and HUL. As observed from the earlier Correlation plot, CIPLA & HUL exhibit slightly negative correlation, thus partially negating each other’s downside risk and bringing down portfolio risk by 25%.


Portfolio managers looking to maximize risk-adjusted-returns (Aggressive Equity) are thus likely to favor RIL as a key driver of the portfolio returns. Looking at the historical performance and key prospects (like 5G onboarding, JioMart, OTT tie-ups, increasing ARPU), this over-weightage on RIL is likely to continue in the coming days as well. However, relatively conservative managers like Pension Funds may opt for an allocation in between the 2 extreme results presented in this analysis. Transferring weight from RIL to CIPLA or HUL is likely to bring down overall portfolio risk and generate a moderate return, keeping undue risk in check.