Why dividend stocks are so attractive: Analyzing the top 10 dividend stocks on the Korean stock market with R code

Hello, everyone! Today we're here to talk about something really exciting: dividend investing. Have you ever fallen for the lure of a steady stream of dividends every month? Or maybe you're still not sure what dividend investing is? Don't worry. By the time you're done reading today's post, you'll be hooked on the world of dividend investing! As a bonus, you'll be able to visualize it like this

배당주 투자 - 삼성전자
( Investing in Dividend Stocks - Samsung Electronics )

In this post, we'll use R programming to analyze the top 10 dividend stocks on the Korean stock market in depth. From stock price movements to dividend yields to stock volatility, we've packed a lot of information into this post. Let's dive into the world of dividend investing together.

Why Invest in Dividend Stocks?

Investing in dividend stocks is one of the favorite investment strategies of many investors. Why? Apart from the ups and downs of the stock price, companies distribute a portion of their profits to shareholders in the form of dividends. Stocks that offer a steady stream of dividends are called dividend stocks.

But can you just pick any stock and invest in it? No. There are many factors to consider when picking a good dividend stock. Today, we'll use R code to create an South Korean stock market's top 10 dividend stocks to see what to look for.

SK텔레콤
( Investing in Dividend Stocks - SK Telecom )

Analyzing Dividend Stocks with R Code

Now it's time to dive into the R code, and if it looks a bit long, don't worry. We'll break it down piece by piece.

# Load Prerequisite Libraries
library(quantmod)
library(ggplot2)
library(reshape2)
library(dplyr)
library(gridExtra)
library(scales)
library(furrr) # Parallel Processing Library

Set up stock information for # to analyze
stocks_info <- data.frame(
  symbol = c("005930.KS", "017670.KS", "033780.KS", "000270.KS", "051910.KS",
             "032640.KS", "030200.KS", "000810.KS", "035250.KS", "316140.KS"),
  name = c("Samsung Electronics", "SK Telecom", "KT", "Kia", "LG Chem",
           "LG Uplus", "KT&G", "Samsung Fire", "POSCO Holdings", "Woori Financial")
)

Code commentary

  1. First, load the necessary R packages, which are used for stock data collection, data processing, visualization, and more.
  2. stocks_info Create a dataframe to store the symbols and names of the 10 stocks you want to analyze. These companies are known dividend-paying stocks in the Korean stock market.

Now we'll define functions to collect and analyze stock data.

# stock data collection function definition
get_stock_data <- function(symbol) {
  tryCatch({
    Collect # stock data for the last 10 years
    data <- getSymbols(
      symbol, src = "yahoo",
      from = Sys.Date() - years(10),
      to = Sys.Date(),
      auto.assign = FALSE
    )

    Check # data
    if (is.null(data)) stop("No data retrieved.")

    # Remove data after the current date
    data <- data[index(data) <= Sys.Date()]

    # Convert to annual data
    annual_close <- to.yearly(Cl(data))
    annual_open <- to.yearly(Op(data))
    annual_high <- to.yearly(Hi(data))
    annual_low <- to.yearly(Lo(data))
    annual_volume <- to.yearly(Vo(data))

    Handle # dividends (fill with 0 if none)
    annual_dividends <- if ("Dividends" %in% colnames(data)) {
      to.yearly(data$Dividends)
    } else {
      xts(rep(0, nrow(annual_close)), order.by = index(annual_close))
    }

    } cbind(annual_open, annual_high, annual_low, annual_close,
          annual_volume, annual_dividends)
  }, error = function(e) {
    warning(paste("Data fetch failed for", symbol, ":", e$message))
    return(NULL)
  })
}

Code commentary

  1. get_stock_data function fetches the last 10 years of data from Yahoo Finance for a given stock symbol.
  2. Converts data to an annualized basis and includes open, high, low, close, volume, and dividend information.
  3. Error handling ensures that your program doesn't break if data collection fails.

Let's also create a function to visualize the data we've collected.

# data visualization functions
plot_stock_data <- function(data, stock_info) {
  if (is.null(data)) {
    warning(paste("No data available for", stock_info$name))
    return(NULL)
  }

  Create the # dataframe and calculate the metric
  df %
    mutate(
      DividendYield = (Dividends / Close) * 100, # Dividend Yield
      AnnualReturn = (Close / lag(Close) - 1) * 100, # Annualized Return
      VolatilityRange = High - Low # Volatility Range
    )

  Remove # NA values
  df <- na.omit(df)

  Apply # trending color
  close_color <- "#1f77b4"
  dividend_color <- "#2ca02c"
  return_color <- "#d62728"
  volatility_color <- "#9467bd"
  volume_color <- "#8c564b"

  Create a # stock price and volume chart
  p1 <- ggplot(df, aes(x = Year)) +
    geom_line(aes(y = Close), color = close_color, size = 1) +
    geom_point(aes(y = Close), color = close_color) +
    geom_text(aes(y = Close, label = round(Close, 0)),
              vjust = -0.6, size = 3) +
    geom_col(aes(y = Volume/max(Volume, na.rm = TRUE) * max(Close, na.rm = TRUE)),
             fill = volume_color, alpha = 0.3) +
    scale_y_continuous(
      name = "Price (KRW)",
      labels = scales::comma,
      sec.axis = sec_axis(~./max(df$Close, na.rm = TRUE) * max(df$Volume, na.rm = TRUE),
                          name = "Volume"),
      expand = expansion(mult = c(0.05, 0.1))
    )
    labs(title = paste(stock_info$name, "(", stock_info$symbol, ")"),
         subtitle = "Annual Price and Volume") +
    theme_minimal()
    theme(
      plot.title = element_text(size = 14, face = "bold"),
      axis.title = element_text(size = 10),
      legend.position = "bottom"
    )

  Create a # return chart
  p2 <- ggplot(df, aes(x = Year)) +
    geom_line(aes(y = DividendYield, color = "Dividend Yield"), size = 1) +
    geom_point(aes(y = DividendYield), color = dividend_color) +
    geom_text(aes(y = DividendYield, label = round(DividendYield, 1)),
              color = dividend_color, vjust = -0.6, size = 3) +
    geom_line(aes(y = AnnualReturn, color = "Annual Return"), size = 1) +
    geom_point(aes(y = AnnualReturn), color = return_color) +
    geom_text(aes(y = AnnualReturn, label = round(AnnualReturn, 1)),
              color = return_color, vjust = 1.5, size = 3) +
    scale_color_manual(values = c("Dividend Yield" = dividend_color,
                                  "Annual Return" = return_color)) +
    labs(y = "Rate (%)", color = "Metrics") +
    scale_y_continuous(expand = expansion(mult = c(0.05, 0.1))) +
    theme_minimal() +
    theme(legend.position = "bottom")

  Create a # volatility chart
  p3 <- ggplot(df, aes(x = Year, y = VolatilityRange)) +
    geom_line(color = volatility_color, size = 1) +
    geom_point(color = volatility_color) +
    geom_text(aes(label = round(VolatilityRange, 0)),
              vjust = -0.6, size = 3, color = volatility_color) +
    labs(y = "Volatility Range (High-Low)") +
    scale_y_continuous(labels = scales::comma,
                       expand = expansion(mult = c(0.05, 0.1))) +
    theme_minimal()

  Laying out the # chart
  gridExtra::grid.arrange(p1, p2, p3, ncol = 1,
                          heights = c(1.2, 1, 1))
}

Code commentary

1. plot_stock_data The function takes stock data and generates three charts:

  • Stock price and volume charts
  • Dividend Yield and Annualized Return Charts
  • Volatility Range Chart

2. use ggplot2 to generate each chart, and gridExtra to combine the three charts into one graph.

3. Each chart is color-coded and labeled to make it easier to read.

Now we'll create a function to analyze stock data.

# stock data analysis functions
analyze_stocks <- function(stock_data, stocks_info) {
  results <- lapply(1:nrow(stocks_info), function(i) {
    if (is.null(stock_data[[i]])) return(NULL)

    symbol <- stocks_info$symbol[i]
    data <- stock_data[[i]]

    df <- data.frame(
      Close = as.numeric(data[,4]),
      Dividends = as.numeric(data[,6])
    )

    list(
      StockName = stocks_info$name[i],
      Symbol = symbol,
      MeanPrice = mean(df$Close, na.rm = TRUE),
      PriceStdDev = sd(df$Close, na.rm = TRUE),
      MeanDividend = mean(df$Dividends, na.rm = TRUE),
      TotalReturn = (tail(df$Close, 1) / df$Close[1] - 1) * 100
    )
  })

  results <- results[!sapply(results, is.null)] # remove NULLs
  do.call(rbind, lapply(results, as.data.frame))
}

Code commentary

Yes, let's continue with the code commentary.

  1. analyze_stocks For each stock, the function calculates the average price, standard deviation of the price, average dividend, total return, and more.
  2. Create a list of analytics results for each stock, convert them to a dataframe, and return them.

Now it's time to actually use these functions to collect and analyze data!

# Main Execution
plan(multisession) # Parallel Session Setup

Collect and visualize # data
stock_data <- future_map(1:nrow(stocks_info), function(i) {
  symbol <- stocks_info$symbol[i]
  data <- get_stock_data(symbol)
  if (!is.null(data)) {
    plot_stock_data(data, stocks_info[i,])
  }
  data
})

Output the results of the # analysis
analysis_results <- analyze_stocks(stock_data, stocks_info)
print(analysis_results)

Code commentary

  1. plan(multisession)to set up parallel processing. This saves me time by allowing me to collect data for multiple stocks at the same time.
  2. future_map function to collect and visualize data for each stock.
  3. And finally, the analyze_stocks function to get and print the analysis results for all stocks.

Investing in dividend stocks, here's how to approach it!

Now that we've analyzed the top 10 dividend stocks on the Korean stock market with the R code we wrote, here are some tips on how to approach dividend investing.

  1. Check your dividend yield: The DividendYieldThe higher this value is, the more dividends you'll receive for your investment.
  2. Consider stock price volatility: VolatilityRangeto see how much the stock price has fluctuated. Stocks with low volatility are generally considered stable dividend stocks.
  3. Explore total return: TotalReturnis the return that takes into account both stock price appreciation and dividends. Stocks with a high value may be worthy of long-term investment.
  4. Check your company's financial health: While not included in our code, it's important to check a company's financial statements when investing in dividend stocks. A company with stable earnings can consistently pay dividends.
  5. Identify industry trendsThe future prospects of each company's industry are also important: companies in industries with high growth potential are more likely to increase their dividends.

Closing thoughts: The appeal of dividend stocks

Investing in dividend stocks is an attractive strategy for investors looking for steady income, but as with all investments, there are risks. The information we get from our R code helps us make investment decisions, but it's not enough.

Before making an actual investment, consider a combination of in-depth analysis, personal risk appetite, and professional advice. The real beauty of dividend stocks is often in the long term.

Why not use R code to create your own dividend stock portfolio? The world of investing is wide and deep. Let's learn and grow together!

You can also check out our post on coding dividend stocks with Python I've written one, and you can compare it to the post you're looking at now to get a better idea of which stocks to buy.

# Full Code

# Load Prerequisite Libraries
library(quantmod)
library(ggplot2)
library(reshape2)
library(dplyr)
library(gridExtra)
library(scales)
library(furrr) # Parallel Processing Library

Set up stock information for # to analyze
stocks_info <- data.frame(
  symbol = c("005930.KS", "017670.KS", "033780.KS", "000270.KS", "051910.KS",
             "032640.KS", "030200.KS", "000810.KS", "035250.KS", "316140.KS"),
  name = c("Samsung Electronics", "SK Telecom", "KT", "Kia", "LG Chem",
           "LG Uplus", "KT&G", "Samsung Fire", "POSCO Holdings", "Woori Financial")
)

Define the # stock data collection function
get_stock_data <- function(symbol) {
  tryCatch({
    Collect the last 10 years of # data
    data <- getSymbols(
      symbol, src = "yahoo",
      from = Sys.Date() - years(10),
      to = Sys.Date(),
      auto.assign = FALSE
    )
    
    Check # data
    if (is.null(data)) stop("No data retrieved.")
    
    # Remove data after the current date
    data <- data[index(data) <= Sys.Date()]
    
    # Convert to annual data
    annual_close <- to.yearly(Cl(data))
    annual_open <- to.yearly(Op(data))
    annual_high <- to.yearly(Hi(data))
    annual_low <- to.yearly(Lo(data))
    annual_volume <- to.yearly(Vo(data))
    
    Handle # dividends (fill with 0 if none)
    annual_dividends <- if ("Dividends" %in% colnames(data)) {
      to.yearly(data$Dividends)
    } else {
      xts(rep(0, nrow(annual_close)), order.by = index(annual_close))
    }
    
    } cbind(annual_open, annual_high, annual_low, annual_close,
          annual_volume, annual_dividends)
  }, error = function(e) {
    warning(paste("Data fetch failed for", symbol, ":", e$message))
    return(NULL)
  })
}

# data visualization functions
plot_stock_data <- function(data, stock_info) {
  if (is.null(data)) {
    warning(paste("No data available for", stock_info$name))
    return(NULL)
  }
  
  Create the # dataframe and calculate the metric
  df %
    mutate(
      DividendYield = (Dividends / Close) * 100, # Dividend Yield
      AnnualReturn = (Close / lag(Close) - 1) * 100, # Annualized Return
      VolatilityRange = High - Low # Volatility Range
    )
  
  Remove # NA values
  df <- na.omit(df)
  
  Apply # trending color
  close_color <- "#1f77b4"
  dividend_color <- "#2ca02c"
  return_color <- "#d62728"
  volatility_color <- "#9467bd"
  volume_color <- "#8c564b"
  
  Create a # stock price and volume chart
  p1 <- ggplot(df, aes(x = Year)) +
    geom_line(aes(y = Close), color = close_color, size = 1) +
    geom_point(aes(y = Close), color = close_color) +
    geom_text(aes(y = Close, label = round(Close, 0)),
              vjust = -0.6, size = 3) + # Adjust vjust value
    geom_col(aes(y = Volume/max(Volume, na.rm = TRUE) * max(Close, na.rm = TRUE)),
             fill = volume_color, alpha = 0.3) +
    scale_y_continuous(
      name = "Price (KRW)",
      labels = scales::comma,
      sec.axis = sec_axis(~./max(df$Close, na.rm = TRUE) * max(df$Volume, na.rm = TRUE),
                          name = "Volume"),
      expand = expansion(mult = c(0.05, 0.1)) # add top margin
    )
    labs(title = paste(stock_info$name, "(", stock_info$symbol, ")"),
         subtitle = "Annual Price and Volume") +
    theme_minimal()
    theme(
      plot.title = element_text(size = 14, face = "bold"),
      axis.title = element_text(size = 10),
      legend.position = "bottom"
    )
  
  Create a # return chart
  p2 <- ggplot(df, aes(x = Year)) +
    geom_line(aes(y = DividendYield, color = "Dividend Yield"), size = 1) +
    geom_point(aes(y = DividendYield), color = dividend_color) +
    geom_text(aes(y = DividendYield, label = round(DividendYield, 1)),
              color = dividend_color, vjust = -0.6, size = 3) + # Adjust vjust value
    geom_line(aes(y = AnnualReturn, color = "Annual Return"), size = 1) +
    geom_point(aes(y = AnnualReturn), color = return_color) +
    geom_text(aes(y = AnnualReturn, label = round(AnnualReturn, 1)),
              color = return_color, vjust = 1.5, size = 3) +
    scale_color_manual(values = c("Dividend Yield" = dividend_color,
                                  "Annual Return" = return_color)) +
    labs(y = "Rate (%)", color = "Metrics") +
    scale_y_continuous(expand = expansion(mult = c(0.05, 0.1))) + # add top margin
    theme_minimal() + #
    theme(legend.position = "bottom")
  
  Create a # volatility chart
  p3 <- ggplot(df, aes(x = Year, y = VolatilityRange)) +
    geom_line(color = volatility_color, size = 1) +
    geom_point(color = volatility_color) +
    geom_text(aes(label = round(VolatilityRange, 0)),
              vjust = -0.6, size = 3, color = volatility_color) + # Adjust the vjust value
    labs(y = "Volatility Range (High-Low)") +
    scale_y_continuous(labels = scales::comma,
                       expand = expansion(mult = c(0.05, 0.1))) + # add top margin
    theme_minimal()
  
  Position the # chart
  gridExtra::grid.arrange(p1, p2, p3, ncol = 1,
                          heights = c(1.2, 1, 1))
}

# stock data analysis functions
analyze_stocks <- function(stock_data, stocks_info) {
  results <- lapply(1:nrow(stocks_info), function(i) {
    if (is.null(stock_data[[i]])) return(NULL)
    
    symbol <- stocks_info$symbol[i]
    data <- stock_data[[i]]
    
    df <- data.frame(
      Close = as.numeric(data[,4]),
      Dividends = as.numeric(data[,6])
    )
    
    list(
      StockName = stocks_info$name[i],
      Symbol = symbol,
      MeanPrice = mean(df$Close, na.rm = TRUE),
      PriceStdDev = sd(df$Close, na.rm = TRUE),
      MeanDividend = mean(df$Dividends, na.rm = TRUE),
      TotalReturn = (tail(df$Close, 1) / df$Close[1] - 1) * 100
    )
  })
  
  results <- results[!sapply(results, is.null)] # remove NULLs
  do.call(rbind, lapply(results, as.data.frame))
}

# Main execution
plan(multisession) # Set up parallel sessions

Collect and visualize # data
stock_data <- future_map(1:nrow(stocks_info), function(i) {
  symbol <- stocks_info$symbol[i]
  data <- get_stock_data(symbol)
  if (!is.null(data)) {
    plot_stock_data(data, stocks_info[i,])
  }
  data
})

Output the results of the # analysis
analysis_results <- analyze_stocks(stock_data, stocks_info)
print(analysis_results)

Similar Posts