# Load packages

# Core
library(tidyverse)
library(tidyquant)
library(gt)

Import Stock prices

symbols <- c("KO","^GSPC")

# Get stocks using tq_get
prices <- tq_get(x = symbols,
                 get = "stock.prices",
                 from = "2014-01-01",
                 to = "2024-10-10")

Calculate Cumulative Percentage Gain

prices <- prices %>%
    group_by(symbol) %>%
    arrange(date) %>%
    mutate(start_price = first(adjusted),
           pct_gain = (adjusted / start_price - 1) * 100) #Calculating Percentage Gain

Plot the percentage gain over time

prices %>%
  ggplot(aes(x = date, y = pct_gain, color = symbol)) +
  geom_line() +
  labs(title = "Percentage Gain Comparison: KO vs S&P 500",
       x = "Date",
       y = "Percentage Gain (%)",
       color = "Symbol") +
scale_x_date(date_breaks = "2 years", date_labels = "%Y") + # x axis date break 2y
scale_y_continuous(breaks = seq(-50,300,by = 25)) +
  theme_minimal()

Speak to Points

How Coca-Cola’s Stock Performance Compares to the Overall Market

The 10-year graph provided above offers valuable insight into how Coca-Cola (KO) has performed relative to the overall market.

Starting in 2014, KO had a rough start[1], initially dipping into negative returns. However, it quickly recovered and matched the market’s rapid incline. KO then held steady, closely tracking the market until 2015. In 2015, KO took a slight dip while the market continued its steady climb. Later in 2015, both the market and KO declined, likely due to disappointing Q3 earnings.

Following this dip, both the market and KO swiftly recovered. KO entered a golden period in 2016[2], outperforming the market[3]. However, by the end of 2016, the market caught up and outperformed KO for the next two years.

In late 2018, KO’s performance climbed while the market dropped 25%. However, both KO and the market experienced rapid declines by year-end, with the market losing about 30% and KO around 13%. Despite these declines, both still posted gains of roughly 30% since the start of 2014.

Entering 2019, KO struggled to keep up with the market’s recovery, briefly dipping before rebounding to match the market by mid-2019, with both posting 50% gains. This parity continued into 2020, where both KO and the market saw gains exceeding 75%. Unfortunately, the COVID-19 pandemic hit in Q1 2020, causing sharp declines. KO returned to levels last seen in 2016 (about 12.5% gains), while the market fell to 2017 levels (around 30% gains).

The market demonstrated strong resilience, quickly bouncing back to a 162.5% total gain by mid-2022, outpacing KO, which lagged at 87%. However, the market cooled off, dropping back to a 100% gain by mid-2022, aligning with KO’s performance. Both then experienced a period of volatility but maintained similar gains until Q3 2022, when both saw a 25% decline.

By 2023 and 2024, both KO and the market recovered strongly, with KO boasting a 137.5% total gain since January 2014, while the market reached 212.5%.

In summary, KO has shown a high correlation to the market but has not matched its overall gains. Based on the graph, KO’s beta is likely around 0.6, indicating lower volatility compared to the market.

Performance Notes

[1] “Starting in 2014, KO had a rough start”. 2014 was an interesting period of time for the Coca-Cola Company. The beginning of 2014 is known for concerns about the Federal Reserve tapering its bond-buying program.

(Explanation: During times of economic distress central banks implement quantitative easing(QE) to simulate the economy. This usually involves buying large quantities of financial assets to inject liquidity into the economy, lowering interest rates and promoting borrowing and spending money. When the market starts to show signs of recovery, the central banks may begin to ‘taper’ its asset purchases. Tapering signals a shift in monetary policy, indicating the central bank believe the economy is strengthening)

This tapering made investors worry about rising interest rates and the potential impact on economic growth, which made a strong impact on various sectors, specifically consumer goods where the Coca-Cola company resides. A decline in stock price like this could also be because of rising industry challenges at the time. During the 2010s, there was growing awareness and concern about health impacts of sugary beverages, which led to a variety of challenges for the Coca-Cola Company. However, the company showed resilience and innovation which leads to the next point.

[2] “Golden Period for Coca-Cola”. In 2016 the Coca-Cola company was able to outshine the market, showing off innovation and making very calculated well timed decisions. The most important being the release of Coke Zero. With the rise of health awareness in America, Coca-cola was able to successfully integrate into the healthy beverage market with the release of Coke Zero. This success was met with further innovation with the Coca-cola company adding specialized new technology, such as ‘Coca-cola Freestyle’ to boost sales under multiple different brands like minute Maid and Vitamin Water.

Coca-Cola was also able to capitalize on their strength as a beverage company and insert themselves into the 2016 Rio Olympics, with limited edition packaging, new sales, and a boost in marketing/advertising. This was a great time for Coca-cola to succeed and grow while the market was facing unique challenges.

[3] ’The market was out performed at the start of 2016

During this period of time, the market was facing a variety of issues. As it doesn’t directly relate to my company I will keep it summarized. The first issue at the time was the concerns about China’s economy. As one of the largest economies in the world, any weakness in China can have widespread implications for global markets.

Falling oil prices were also a unique issue at this time, led primarily by oversupply and weakening global demand. this decline negatively affected energy companies and the related sectors contributing to the dip in the market. Lastly, in 2015 the Federal reserve raised interest rates in December of 2015, which was the first time in nearly a decade, keep in mind the tapering two years prior. Investors were uncertain about future rate hikes and how it would impact possible earnings.

Now there are notable sections that could be mentioned about this 10 year period, such as the market dropping at the end of 2018, and the volatility of 2022. But for the sake of time, patience and space I wont read into them.

Last 12 months

# Define symbols and dates
symbols <- c("KO", "^GSPC")
start_date <- "2023-09-30"
end_date <- "2024-09-30"

# Stock prices using tq_get
prices <- tq_get(symbols, 
                 get = "stock.prices", 
                 from = start_date, 
                 to = end_date) %>%
  filter(date >= as.Date(start_date) & date <= as.Date(end_date)) %>%
  select(date, symbol, adjusted)

# Calculate monthly returns 
monthly_returns <- prices %>%
  group_by(symbol) %>%
  arrange(date) %>%
  mutate(monthly_return = (adjusted / lag(adjusted) - 1)) %>%
  filter(!is.na(monthly_return))


# Calculate average return and St_Dev
stats <- monthly_returns %>%
  group_by(symbol) %>%
  summarise(
    average_monthly_return = mean(monthly_return, na.rm = TRUE),
    monthly_std_dev = sd(monthly_return, na.rm = TRUE)
  )

# Annualize the Returns and st_dev
annualized_stats <- stats %>%
  mutate(
    annualized_return = ((1 + average_monthly_return) ^ 12) - 1,
    annualized_std_dev = monthly_std_dev * sqrt(12)
  )

# Create a Nice Looking table using GT
annualized_stats %>%
  gt() %>%
  tab_header(
    title = "Annualized Return and Risk for KO and S&P 500"
  ) %>%
  fmt_percent(
    columns = vars(annualized_return, annualized_std_dev),
    decimals = 2
  ) %>%
  cols_label(
    average_monthly_return = "Avg. Monthly Return",
    monthly_std_dev = "Monthly Std. Dev.",
    annualized_return = "Annualized Return",
    annualized_std_dev = "Annualized Std. Dev."
  )
Annualized Return and Risk for KO and S&P 500
symbol Avg. Monthly Return Monthly Std. Dev. Annualized Return Annualized Std. Dev.
KO 0.001193828 0.008469804 1.44% 2.93%
^GSPC 0.001201628 0.007929966 1.45% 2.75%
# Define the stock symbols and date range
symbols <- c("KO", "^GSPC")
start_date <- "2023-09-30"
end_date <- "2024-09-30"

# get the data
prices <- tq_get(symbols, 
                 get = "stock.prices", 
                 from = start_date, 
                 to = end_date) %>%
  filter(date >= as.Date(start_date) & date <= as.Date(end_date)) %>%
  select(date, symbol, adjusted)

# Calculate monthly returns ................ monthly_return
monthly_returns <- prices %>%
  group_by(symbol) %>%
  arrange(date) %>%
  mutate(monthly_return = (adjusted / lag(adjusted) - 1)) %>%
  filter(!is.na(monthly_return))

# Calculate average monthly returns.................avg_monthly_return
average_monthly_returns <- monthly_returns %>%
  mutate(month = floor_date(date, "month")) %>%  # Extract the month
  group_by(month, symbol) %>%
  summarise(avg_monthly_return = mean(monthly_return, na.rm = TRUE)) %>%  # Calculate average return
  ungroup()

# Calculate the overall average monthly return
overall_avg_return <- average_monthly_returns %>%
  summarise(overall_avg_monthly_return = mean(avg_monthly_return, na.rm = TRUE)) %>%
  pull(overall_avg_monthly_return)

# Create a bar plot 
ggplot(average_monthly_returns, aes(x = month, y = avg_monthly_return, fill = symbol)) +
  geom_bar(stat = "identity", position = "dodge") +  
  geom_hline(yintercept = overall_avg_return, linetype = "dashed", color = "red") +  
  labs(title = "Average Monthly Returns for KO and S&P 500",
       y = "Average Monthly Return",
       x = "Month") +
  theme_minimal() +
  scale_y_continuous(labels = scales::percent) +  # Format y-axis as percentage
  scale_x_date(date_labels = "%b %Y", date_breaks = "1 month") +  # Format x-axis 
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +  # Rotate x-axis labels
  geom_text(aes(x = max(month), y = overall_avg_return, label = paste0("Overall Avg: ", scales::percent(overall_avg_return))), 
            vjust = -0.5, color = "red")  

Cumalative Returns instead of Average Monthly From Above

# Download stock prices using tq_get
prices <- tq_get(symbols, 
                 get = "stock.prices", 
                 from = start_date, 
                 to = end_date) %>%
  filter(date >= as.Date(start_date) & date <= as.Date(end_date)) %>%
  select(date, symbol, adjusted)

# Calculate daily returns
daily_returns <- prices %>%
  group_by(symbol) %>%
  arrange(date) %>%
  mutate(daily_return = (adjusted / lag(adjusted) - 1)) %>%
  filter(!is.na(daily_return))

# Calculate cumulative returns for each month
monthly_cumulative_returns <- daily_returns %>%
  mutate(month = floor_date(date, "month")) %>%
  group_by(symbol, month) %>%
  summarise(cumulative_monthly_return = prod(1 + daily_return, na.rm = TRUE) - 1) %>%
  ungroup()

# Calculate the average CUMALITIVE monthly return 
cumulative_avg_return <- monthly_cumulative_returns %>%
  group_by(symbol) %>%
  summarise(average_cumulative_monthly_return = mean(cumulative_monthly_return, na.rm = TRUE))

# Calculate standard deviation of daily returns, grouped by month
monthly_std_dev <- daily_returns %>%
  mutate(month = floor_date(date, "month")) %>%
  group_by(symbol, month) %>%
  summarise(monthly_std_dev = sd(daily_return, na.rm = TRUE)) %>%
  ungroup()

# Calculate the average monthly standard deviation
avg_monthly_std_dev <- monthly_std_dev %>%
  group_by(symbol) %>%
  summarise(average_monthly_std_dev = mean(monthly_std_dev, na.rm = TRUE))

# Combine 
monthly_stats <- cumulative_avg_return %>%
  left_join(avg_monthly_std_dev, by = "symbol")

# Calculate for the entire period
annualized_stats <- monthly_stats %>%
  mutate(
    annualized_return = ((1 + average_cumulative_monthly_return) ^ 12) - 1,
    annualized_std_dev = average_monthly_std_dev * sqrt(12)
  )

# Create a nice looking table using GT
annualized_stats %>%
  gt() %>%
  tab_header(
    title = "Annualized and Average Monthly Return and Risk for KO and S&P 500"
  ) %>%
  fmt_percent(
    columns = vars(average_cumulative_monthly_return, average_monthly_std_dev, annualized_return, annualized_std_dev),
    decimals = 2
  ) %>%
  cols_label(
    average_cumulative_monthly_return = "Avg. Monthly Cumulative Return",
    average_monthly_std_dev = "Avg. Monthly Std. Dev.",
    annualized_return = "Annualized Return",
    annualized_std_dev = "Annualized Std. Dev."
  )
Annualized and Average Monthly Return and Risk for KO and S&P 500
symbol Avg. Monthly Cumulative Return Avg. Monthly Std. Dev. Annualized Return Annualized Std. Dev.
KO 2.46% 0.82% 33.80% 2.83%
^GSPC 2.51% 0.76% 34.63% 2.65%

Speak on Stock Performance and an Annual Past Events

In the last year Ko has been making some important decisions in order to show a 30% return. Using data from press releases and other related content from the Coke investors pages, I found that coke did some extensive research into changing consumer tastes and lifestyles which led to the discontinuation of Coke Spiced and Coca-Cola Cherry Vanilla flavors. KO also relayed there operating income grew 4% for the year, they paid out $8 billion dollars in dividends last year ( 2023 ) and has increased their dividend for 61 years in a row. This and the 25% increase in capital expenditures from 2023 has been keeping many investors interested, or attracting new investors.

Finding Beta

# Define stock (5 years )
symbols <- c("KO", "^GSPC")
start_date <- "2019-09-30"
end_date <- "2024-09-30"

# Download stock prices 
prices <- tq_get(symbols, 
                 get = "stock.prices", 
                 from = start_date, 
                 to = end_date) %>%
  filter(date >= as.Date(start_date) & date <= as.Date(end_date)) %>%
  select(date, symbol, adjusted)

# Calculate monthly returns for both company and market
monthly_returns <- prices %>%
  group_by(symbol) %>%
  arrange(date) %>%
  tq_transmute(select = adjusted, 
               mutate_fun = periodReturn, 
               period = "monthly", 
               type = "log") %>%  
  rename(monthly_return = monthly.returns) %>%
  ungroup()

print(monthly_returns)
## # A tibble: 122 × 3
##    symbol date       monthly_return
##    <chr>  <date>              <dbl>
##  1 KO     2019-09-30       0       
##  2 KO     2019-10-31      -0.000184
##  3 KO     2019-11-29      -0.0117  
##  4 KO     2019-12-31       0.0359  
##  5 KO     2020-01-31       0.0536  
##  6 KO     2020-02-28      -0.0878  
##  7 KO     2020-03-31      -0.181   
##  8 KO     2020-04-30       0.0364  
##  9 KO     2020-05-29       0.0171  
## 10 KO     2020-06-30      -0.0347  
## # ℹ 112 more rows
# filter
company_returns <- filter(monthly_returns, symbol == "KO")  
market_returns <- filter(monthly_returns, symbol == "^GSPC")

# Join the returns data into one table to align the dates
combined_returns <- inner_join(company_returns, market_returns, by = "date", suffix = c("_company", "_market"))

# Calculate covariance of company and market returns
covar <- cov(combined_returns$monthly_return_company, combined_returns$monthly_return_market)

# Calculate variance of market returns
market_var <- var(combined_returns$monthly_return_market)

# Estimate beta
beta <- covar / market_var

cat("Estimated Beta (5-year Monthly):", beta)
## Estimated Beta (5-year Monthly): 0.6215767

Interpret your Data

What does this beta estimate mean?

The beta score measures volatility of a stock relative to the market. The market being the s&p500 which has a beta score of 1.0. If a stock beta score > 1, then the stock is more volatile than the market. In my case, the Coca-Cola Company(KO) has a beta score of .6, which is <1. This means the stock is less volatile than the market. So as example, if the market were to raise 10%, then my stock which is only .6 would only rise by 6% or .6 of what the market does.

Estimate G ( Dividend Growth Rate)

#Dividends of last 10 years
dividends <- c(0.33, 0.35, 0.37, 0.39, 0.40, 0.41, 0.42, 0.44, 0.46, 0.49)

#Calculate growth rate
n <- length(dividends) - 1 # number of periods/years
# Estimated Divi Growth Rate
g <- (dividends[n+1] / dividends[1])^(1/n) - 1

print(paste("Growth Rate (g):",g))
## [1] "Growth Rate (g): 0.0449025603706932"
# Step 2: Calculating rs using capm

#S&P500 Prices on April 1 on x year. Price is based on close
sp_2004 <- 1132.17
sp_2024 <- 5243.77

n_years <- 2024 - 2004

#Get rm
rM <- (sp_2024 / sp_2004)^(1/n_years) -1

rRF <- 0.04008  # 10 year treasury
beta <- 0.6215  # Beta

# CAPM calculation
rs <- rRF + beta * (rM - rRF)

#printing Values for viewing
print(paste("Annualized S&P 500 Return (rM):", rM))
## [1] "Annualized S&P 500 Return (rM): 0.0796589756715429"
print(paste("Risk-Free Rate (rRF):", rRF))
## [1] "Risk-Free Rate (rRF): 0.04008"
print(paste("Beta:", beta))
## [1] "Beta: 0.6215"
print(paste("Required Rate of Return (rs):", rs))
## [1] "Required Rate of Return (rs): 0.0646783333798639"
#calculate Intrinsic value using ddm

D0 <- dividends[n+1] # last dividend paid

#calculate the intrinsic value
stock_price <- (D0 * (1 + g)) / (rs - g)

print(paste("Intrinsic Stock Value:", stock_price))
## [1] "Intrinsic Stock Value: 25.8903788157462"

Brief Interpretation

Well, I’ve been fooling around with this for a little bit too long and have settled on two possible outcomes. First is the one I have displayed with an Intrinsic Value (IV) of 25.89. The current stock price for KO is 70.34. So this leads me to believe one of two things. Either I messed up somewhere and cannot figure out where, or maybe the DDM method is not accurate or cannot accurately measure a stock where the brand is the main selling point like Coke. I do not know enough about this to say DDM is wrong, but I just cannot see where I would’ve messed up the calculation.

But that leads me to my next point. While fooling around with the calculations I was able to get an IV of 0.7984. Now this, as is, is definitely wrong. However, if simply multiplied by 10 I think it could be an incredibly reasonable number, again based off my very limited knowledge of what other results DDM could give stocks. I would love to learn more and really try to figure this out but I am just out of time. Truly unfortunate.