3  금융 데이터 획득

3.1 주가 데이터 패키지로 받기

3.1.1 tidyquant 패키지

R 패키지를 처음 사용하려면 install.packages("tidyquant") 명령어를 한 번 실행해야 합니다. tidyquant 사용에 문제가 있을 경우 해당 패키지 설명서를 참조하십시오.

library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.4
✔ forcats   1.0.0     ✔ stringr   1.5.0
✔ ggplot2   3.4.3     ✔ tibble    3.2.1
✔ lubridate 1.9.2     ✔ tidyr     1.3.0
✔ purrr     1.0.2     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(tidyquant)
Loading required package: PerformanceAnalytics
Loading required package: xts
Loading required package: zoo

Attaching package: 'zoo'

The following objects are masked from 'package:base':

    as.Date, as.Date.numeric


######################### Warning from 'xts' package ##########################
#                                                                             #
# The dplyr lag() function breaks how base R's lag() function is supposed to  #
# work, which breaks lag(my_xts). Calls to lag(my_xts) that you type or       #
# source() into this session won't work correctly.                            #
#                                                                             #
# Use stats::lag() to make sure you're not using dplyr::lag(), or you can add #
# conflictRules('dplyr', exclude = 'lag') to your .Rprofile to stop           #
# dplyr from breaking base R's lag() function.                                #
#                                                                             #
# Code in packages is not affected. It's protected by R's namespace mechanism #
# Set `options(xts.warn_dplyr_breaks_lag = FALSE)` to suppress this warning.  #
#                                                                             #
###############################################################################

Attaching package: 'xts'

The following objects are masked from 'package:dplyr':

    first, last


Attaching package: 'PerformanceAnalytics'

The following object is masked from 'package:graphics':

    legend

Loading required package: quantmod
Loading required package: TTR
Registered S3 method overwritten by 'quantmod':
  method            from
  as.zoo.data.frame zoo 

먼저, 삼성전자 주식(005930.KS)과 같은 하나의 종목 심볼에 대한 일일 가격 데이터를 데이터 제공자 Yahoo!Finance에서 직접 다운로드하겠습니다. 데이터를 다운로드하기 위해 tq_get 명령어를 사용할 수 있습니다.

만약 tq_get 명령어 사용 방법을 모르는 경우, ?tq_get 명령어를 입력하여 도움말 파일을 확인하십시오. 특히 설명서의 예시 부분을 꼼꼼히 살펴보는 것을 추천합니다.

prices <- tq_get("005930.KS",
  get = "stock.prices",
  from = "2022-01-01",
  to = "2023-12-31"
)

prices
# A tibble: 489 × 8
   symbol    date        open  high   low close   volume adjusted
   <chr>     <date>     <dbl> <dbl> <dbl> <dbl>    <dbl>    <dbl>
 1 005930.KS 2022-01-04 78800 79200 78300 78700 12427416   75235.
 2 005930.KS 2022-01-05 78800 79000 76400 77400 25470640   73992.
 3 005930.KS 2022-01-06 76700 77600 76600 76900 12931954   73514.
 4 005930.KS 2022-01-07 78100 78400 77400 78300 15163757   74853.
 5 005930.KS 2022-01-10 78100 78100 77100 78000  9947422   74566.
 6 005930.KS 2022-01-11 78400 79000 78000 78900 13221123   75426.
 7 005930.KS 2022-01-12 79500 79600 78600 78900 11000502   75426.
 8 005930.KS 2022-01-13 79300 79300 77900 77900 13889401   74470.
 9 005930.KS 2022-01-14 77700 78100 77100 77300 10096725   73897.
10 005930.KS 2022-01-17 77600 77800 76900 77500  8785122   74088.
# ℹ 479 more rows

3.2 주가 데이터 웹스크래핑으로 받기

대한민국의 상장회사 주가 데이터를 받기 위하여 네이버https://www.naver.com/ 검색 사이트를 활용하는 것이 가장 편한 방법이 될 수도 있습니다.

원천 주가 데이터는 한국 거래소의 API를 활용하여 받아야 할 수 있으나 일반적으로 주가 데이터는 Raw data 형태를 그대로 사용하기에는 무리가 있습니다. 일례로 주식분할과 같은 사건이 발생하면 1개의 주식이 여러개로 나누어지면서 주가가 큰 폭으로 줄어들게 됩니다. 시가총액은 동일한데 주식 개당 가치가 어느 날 갑자기 감소하게 되면서 주식분할 일자 이전과 이후의 주식가격은 비교 가능성을 잃게 됩니다. 따라서 이전 주가에 주식분할 효과를 부여하여 수정한 수정 주가를 사용하여야 비교 분석이 가능합니다.

네이버 검색 사이트는 수정 주가 데이터를 제공하므로 이 데이터를 가져다가 가공하는 것이 대한민국 거래소에서 거래되는 주식 가격을 얻는 좋은 방법이 될 수 있습니다.

# 패키지 인스톨

# install.packages("rvest")
# install.packages("R6")
# install.packages("httr")

# 라이브러리 불러오기

library(rvest)

Attaching package: 'rvest'
The following object is masked from 'package:readr':

    guess_encoding
library(R6)
library(httr)
library(tidyverse)

# user_agent 확인URL: http://httpbin.org/user-agent
# user_agent 설정하기
ua <- "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36"

# naver 금융 사이트 설정
ticker <- '066570'

naver_stock <- function(ticker, page){

    stock_df <- tibble(날짜 = ymd("2024-01-01"),
                       종가 = 1,
                       전일비 = 1,
                       시가 = 1,
                       고가 = 1,
                       저가 = 1,
                       거래량 = 1)

    for (i in 1:page){
        url <- paste0('http://finance.naver.com/item/sise_day.nhn?code=',ticker,'&page=',i)

        # 자료가져오기
        price <- GET(url, user_agent(ua)) %>% read_html() %>% html_nodes('.type2') %>% html_table

        # dataframe으로 변환하기
        stock_price <- data.frame(price)
        stock_price <- stock_price %>% 
            as_tibble() %>% 
            na.omit() %>% 
            filter(날짜!="")

        stock_price <- stock_price %>% 
            mutate(across(종가:거래량, ~ gsub(",", "", .x))) %>%
            mutate(across(종가:거래량, ~ as.numeric(.x))) %>%
            mutate(날짜 = ymd(날짜))

        stock_df <- bind_rows(stock_df, stock_price)
    }

    stock_df <- stock_df %>% 
        slice(-1)

    return(stock_df)
}

stock_data_raw <- naver_stock(ticker, 100)
stock_data_raw
# A tibble: 1,000 × 7
   날짜        종가 전일비   시가   고가  저가 거래량
   <date>     <dbl>  <dbl>  <dbl>  <dbl> <dbl>  <dbl>
 1 2024-03-08 95700    800  95600  96000 94800 343993
 2 2024-03-07 94900    200  94700  95300 93900 336931
 3 2024-03-06 94700   1300  93300  95400 93200 440556
 4 2024-03-05 93400    500  93500  94500 92900 400619
 5 2024-03-04 93900   1000  95100  95600 93800 627925
 6 2024-02-29 94900    400  95800  96200 94700 605548
 7 2024-02-28 95300    800  96100  96300 94000 715424
 8 2024-02-27 96100   2100  98600  98700 95500 469486
 9 2024-02-26 98200    300 100400 101400 98200 585114
10 2024-02-23 97900    100  98600  99200 97900 295948
# ℹ 990 more rows
start <- ymd('2022-01-01')
end <- ymd('2023-12-31')

stock_data <- stock_data_raw %>% 
    filter(날짜 > start & 날짜 < end)

stock_data
# A tibble: 491 × 7
   날짜         종가 전일비   시가   고가  저가  거래량
   <date>      <dbl>  <dbl>  <dbl>  <dbl> <dbl>   <dbl>
 1 2023-12-28 101800   1800  99900 101900 99500  751858
 2 2023-12-27 100000      0 100000 100000 98700  306136
 3 2023-12-26 100000    300 100600 100600 99200  313537
 4 2023-12-22  99700    200 100400 100400 99000  319969
 5 2023-12-21  99500    300  98500 100400 98500  543574
 6 2023-12-20  99200    900  99000  99500 98300  570657
 7 2023-12-19  98300   2200  95000  99300 94800 1234344
 8 2023-12-18  96100   1100  97400  97400 96100  537938
 9 2023-12-15  97200    400  96900  97400 96400  925632
10 2023-12-14  96800   1000  97100  97200 96000 1033739
# ℹ 481 more rows

3.3 시가총액 데이터 받기

library(httr)
library(rvest)
library(readr)

gen_otp_url <- 'http://data.krx.co.kr/comm/fileDn/GenerateOTP/generate.cmd'
gen_otp_data <- list(
  mktId = 'STK',
  trdDd = '20231228',
  money = '1',
  csvxls_isNo = 'false',
  name = 'fileDown',
  url = 'dbms/MDC/STAT/standard/MDCSTAT03901'
)
otp <- POST(gen_otp_url, query = gen_otp_data) %>%
  read_html() %>%
  html_text()
down_url = 'http://data.krx.co.kr/comm/fileDn/download_csv/download.cmd'
down_sector_KS = POST(down_url, query = list(code = otp),
                   add_headers(referer = gen_otp_url)) %>%
  read_html(encoding = 'EUC-KR') %>%
  html_text() %>%
  read_csv()
Rows: 953 Columns: 8
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (4): 종목코드, 종목명, 시장구분, 업종명
dbl (4): 종가, 대비, 등락률, 시가총액

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
print(down_sector_KS)
# A tibble: 953 × 8
   종목코드 종목명      시장구분 업종명     종가  대비 등락률      시가총액
   <chr>    <chr>       <chr>    <chr>     <dbl> <dbl>  <dbl>         <dbl>
 1 095570   AJ네트웍스  KOSPI    서비스업   4980    75   1.53  225358739820
 2 006840   AK홀딩스    KOSPI    기타금융  17100   100   0.59  226533293100
 3 027410   BGF         KOSPI    기타금융   3810    15   0.4   364680973710
 4 282330   BGF리테일   KOSPI    유통업   131300  2600   2.02 2269376857800
 5 138930   BNK금융지주 KOSPI    기타금융   7140    60   0.85 2299711447320
 6 001460   BYC         KOSPI    섬유의복 426500  1500   0.35  266398297500
 7 001465   BYC우       KOSPI    섬유의복 142600   900   0.64   30713901000
 8 001040   CJ          KOSPI    기타금융  94400  -800  -0.84 2754308611200
 9 079160   CJ CGV      KOSPI    서비스업   5780    80   1.4   707653890820
10 00104K   CJ4우(전환) KOSPI    기타금융  70300  -900  -1.26  297123793600
# ℹ 943 more rows