한국 주가정보 가져오기

Crawling Stock

동학개미를 위한 국내 주식 시장의 거래 정보를 수집하고, 이 데이터를 이용해서 수익률과 Value-at-Risk, 연간 성장률을 구하는 방법을 다루어 봅니다.

유충현 https://choonghyunryu.github.io (한국알사용자회)
2022-04-25

들어가기

역시나 왠만하데는 다 있는 정보입니다. 그러나...
데이터를 이용해서 자신이 투자하는, 그리고 투자할 주식의 수익률과 Value-at-Risk, 연간 성장률을 구하는 방법을 다루어 봅니다.
그러기 위해서는 데이터를 수집해서 R 환경으로 가져오는 것이 필요해집니다.

TL;DR

주식의 문외한이라서 오류가 있을 수 있음을 밝혀둡니다.

종목코드 가져오기

KOSPI, KOSDAQ 종목코드 가져오기

한국 거래소(KRX) 정보데이터 시스템즈의 기본통계>주식>세부안내> 업종분류 현황에서 조회하고 다운 받을 수 있습니다.

해당 페이지는 다음 그림과 같으며,

  1. 조회구분에서 거래소 종류를 선택한 후
  2. 조회 버튼으로 업봉분류 현황을 조회합니다.
  3. 다운로드 이미지 버튼을 눌러서 종목코드가 포함된 업종분류현황을 다운로드합니다.

이 페이지에서는 다음과 같은 두 개 거래 시장에 대한 종목 코드를 획득할 수 있습니다.

필자의 경우, KOSPI 파일은 “data_2719_20220425.csv”, KOSDAQ 파일은 “data_2733_20220425.csv”로 다음로드 되었습니다. 두 개의 파일을 읽어 다음처럼 데이터 프레임 객체를 만듭니다.

library(dplyr)

symbol_korea <- c("data_2719_20220425.csv", "data_2733_20220425.csv") %>% 
  purrr::map_df(
    function(x) {
      readr::read_csv(file = glue::glue("data/{x}"), 
                locale = readr::locale(encoding = "cp949"))
    }
  )

종목코드 관련 정보 살펴보기

가져온 2개 거래소의 종목코드 정보는 다음과 같습니다. KOSDAQ에 약 62%가 상장되어 있습니다.

symbol_korea %>% 
  group_by(시장구분) %>% 
  tally() %>% 
  mutate(pct = n /sum(n) * 100) %>% 
  rename(
    "거래소" = 시장구분,
    "종목수" = n,
    "비율(%)" = pct
  ) %>% 
  kableExtra::kable(digits = 2, format.args = list(big.mark = ",", scientific = FALSE)) %>% 
  kableExtra::kable_styling(bootstrap_options = c("striped", "hover"))
거래소 종목수 비율(%)
KOSDAQ 1,555 62.35
KOSPI 939 37.65

2022년 4월 22일 기준으로 시가총액 상위 10위 회사의 목록은 다음과 같습니다. 삼성전자가 약 400조원의 시가총액으로 Top 1에 랭크되어 있습니다.

symbol_korea %>% 
  arrange(desc(시가총액)) %>% 
  filter(row_number() <= 10) %>% 
  mutate(시가총액 = 시가총액 / 1000000000000) %>% 
  rename("시가총액(단위:조원)" = 시가총액) %>% 
  kableExtra::kable(digits = 2, format.args = list(big.mark = ",", scientific = FALSE)) %>% 
  kableExtra::kable_styling(bootstrap_options = c("striped", "hover"))
종목코드 종목명 시장구분 업종명 종가 대비 등락률 시가총액(단위:조원)
005930 삼성전자 KOSPI 전기전자 67,000 -700 -1.03 399.98
373220 LG에너지솔루션 KOSPI 전기전자 436,500 -500 -0.11 102.14
000660 SK하이닉스 KOSPI 전기전자 110,500 -2,500 -2.21 80.44
207940 삼성바이오로직스 KOSPI 의약품 801,000 -5,000 -0.62 53.00
005935 삼성전자우 KOSPI 전기전자 60,400 -200 -0.33 49.70
035420 NAVER KOSPI 서비스업 300,000 -9,500 -3.07 49.21
035720 카카오 KOSPI 서비스업 92,000 -1,600 -1.71 41.06
006400 삼성SDI KOSPI 전기전자 596,000 -14,000 -2.30 40.98
005380 현대차 KOSPI 운수장비 180,000 -3,000 -1.64 38.46
051910 LG화학 KOSPI 화학 486,000 -17,000 -3.38 34.31

주식거래 정보 가져오기

삼성전자

삼성전자의 주식 거래 정보를 가져옵니다. quantmod 패캐지의 getSymbols() 함수로 1975년 6월 11일 이후의 거래 정보를 가져옵니다. (삼성전자는 1975년 6월 11일에 상장되었다고 합니다.) 그러나 수집되는 데이터는 2000년 이후의 거래정보입니다. 코스피의 경우에는 종목코드에 “.KS”를 붙여주어야 합니다.

trade_sec <- symbol_korea %>% 
  filter(종목명 %in% c("삼성전자")) %>% 
  select(종목코드) %>% 
  mutate(종목코드 = paste0(종목코드, ".KS")) %>% 
  pull() %>% 
  quantmod::getSymbols(from = "1975-06-11", auto.assign = FALSE)

head(trade_sec)
           005930.KS.Open 005930.KS.High 005930.KS.Low
2000-01-04           6000           6110          5660
2000-01-05           5800           6060          5520
2000-01-06           5750           5780          5580
2000-01-07           5560           5670          5360
2000-01-10           5600           5770          5580
2000-01-11           5820           6100          5770
           005930.KS.Close 005930.KS.Volume 005930.KS.Adjusted
2000-01-04            6110         74195000           4675.783
2000-01-05            5580         74680000           4270.191
2000-01-06            5620         54390000           4300.802
2000-01-07            5540         40305000           4239.580
2000-01-10            5770         46880000           4415.592
2000-01-11            5770         59745000           4415.592
tail(trade_sec)
           005930.KS.Open 005930.KS.High 005930.KS.Low
2022-04-19          67100          68000         67000
2022-04-20          67000          67400         66500
2022-04-21          67600          68300         67500
2022-04-22          67200          67300         66700
2022-04-25          66500          66700         66300
2022-04-26          66400          66700         66100
           005930.KS.Close 005930.KS.Volume 005930.KS.Adjusted
2022-04-19           67300         12959434              67300
2022-04-20           67400         16693293              67400
2022-04-21           67700         12847448              67700
2022-04-22           67000         11791478              67000
2022-04-25           66300         11016474              66300
2022-04-26           66100         12946923              66100
is(trade_sec)
[1] "xts"      "oldClass" "xtsORzoo"

getSymbols() 함수는 시계열 데이터 구조의 xts 클래스 객체를 반환합니다. 이것을 데이터 프레임 객체로 변환하려면 zoo 패키지의 fortify.zoo() 함수를 사용합니다.

trade_sec_df <- trade_sec %>% 
  zoo::fortify.zoo()

head(trade_sec_df)
       Index 005930.KS.Open 005930.KS.High 005930.KS.Low
1 2000-01-04           6000           6110          5660
2 2000-01-05           5800           6060          5520
3 2000-01-06           5750           5780          5580
4 2000-01-07           5560           5670          5360
5 2000-01-10           5600           5770          5580
6 2000-01-11           5820           6100          5770
  005930.KS.Close 005930.KS.Volume 005930.KS.Adjusted
1            6110         74195000           4675.783
2            5580         74680000           4270.191
3            5620         54390000           4300.802
4            5540         40305000           4239.580
5            5770         46880000           4415.592
6            5770         59745000           4415.592
is(trade_sec_df)
[1] "data.frame" "list"       "oldClass"   "vector"    

삼성전자의 2000년 첫 거래 정보와 최근 거래 정보를 가져옵니다.

compare_trade <- trade_sec_df %>% 
  summarise(
    first = min(Index),
    last = max(Index)
  ) %>% 
  tidyr::pivot_longer(
    everything(),
    names_to = "date_flag", 
    values_to = "base_date"
  ) %>% 
  inner_join(
    trade_sec_df,
    by = c("base_date" = "Index")
  )

compare_trade
# A tibble: 2 × 8
  date_flag base_date  `005930.KS.Open` `005930.KS.High`
  <chr>     <date>                <dbl>            <dbl>
1 first     2000-01-04             6000             6110
2 last      2022-04-26            66400            66700
# … with 4 more variables: `005930.KS.Low` <dbl>,
#   `005930.KS.Close` <dbl>, `005930.KS.Volume` <dbl>,
#   `005930.KS.Adjusted` <dbl>

2000년 첫 거래일의 종가대비 최근 거래일의 종가를 보면 약 709배 주가가 상승했음을 알 수 있습니다. 2018년 5월 4일 기존의 1주를 50주로 쪼개는 액면분할을 실시하였으므로 이를 반영한 결과입니다.

compare_trade$`005930.KS.Adjusted`[2] / compare_trade$`005930.KS.Adjusted`[1] * 50
[1] 706.8335

카카오

테슬라는 2010년 6월 29일에 상장했다고 합니다. getSymbols() 함수에는 시작일자를 “2000-01-01”로 입력해도 알아서 상장일 이후의 데이터를 가져옵니다. 우리가 회사의 상장일을 일일이 다 알 수 없으무로 대충 작은 값을 입력합니다.

trade_kakao<- symbol_korea %>% 
  filter(종목명 %in% c("카카오")) %>% 
  select(종목코드) %>% 
  mutate(종목코드 = paste0(종목코드, ".KS")) %>% 
  pull() %>% 
  quantmod::getSymbols(from = "1975-06-11", auto.assign = FALSE)

head(trade_kakao)
           035720.KS.Open 035720.KS.High 035720.KS.Low
2000-02-11          54600          54600         54600
2000-02-14          52800          59600         48100
2000-02-15          50000          51800         43500
2000-02-16          42000          48700         40000
2000-02-17          49200          53500         47000
2000-02-18          50100          51300         45000
           035720.KS.Close 035720.KS.Volume 035720.KS.Adjusted
2000-02-11           54600           276500           51500.09
2000-02-14           49400          6270500           46595.32
2000-02-15           43500          3243000           41030.29
2000-02-16           48700          4357000           45935.06
2000-02-17           48700          5099000           45935.06
2000-02-18           45600          4561500           43011.05
tail(trade_kakao)
           035720.KS.Open 035720.KS.High 035720.KS.Low
2022-04-19          95000          96500         94900
2022-04-20          96100          96200         94600
2022-04-21          95100          95100         93100
2022-04-22          92200          92400         91400
2022-04-25          90400          91600         89600
2022-04-26          89800          91700         89700
           035720.KS.Close 035720.KS.Volume 035720.KS.Adjusted
2022-04-19           95100           836819              95100
2022-04-20           95100           880905              95100
2022-04-21           93600          1809576              93600
2022-04-22           92000          1553904              92000
2022-04-25           89700          1511408              89700
2022-04-26           90200          1368258              90200
is(trade_kakao)
[1] "xts"      "oldClass" "xtsORzoo"

xts 객체를 핸들링하는 방법으로 카카오의 상장일의 종가와 최근 거래일인 2022-04-25일의 종가를 비교해 봅니다. 51,500원으로 시작한 주가가 약 8.7배 상승하여 89,700원에 거래를 마쳤습니다. 2021년 4월 15일 1주를 5주로 액면분할한 정보를 반영하였습니다.

카카오 상장일은 1999년 11월 11일입니다. 그러나 quantmod 패키지가 수집하는 Yahoo 사이트에서는 한국 주식 거래 정보는 2000년 이후부터 제공하고 있습니다. 상장일과의 한 두달 차이가 있지만, 대략 8.7배 상승했다고 볼 수 있겠습니다.

trade_kakao[c(1, NROW(trade_kakao)), ]
           035720.KS.Open 035720.KS.High 035720.KS.Low
2000-02-11          54600          54600         54600
2022-04-26          89800          91700         89700
           035720.KS.Close 035720.KS.Volume 035720.KS.Adjusted
2000-02-11           54600           276500           51500.09
2022-04-26           90200          1368258           90200.00
trade_kakao[NROW(trade_kakao), "035720.KS.Adjusted"] %>% 
  as.numeric() %>% 
  "/" (trade_kakao[1, "035720.KS.Adjusted"] %>% as.numeric) * 5
[1] 8.757267

주식거래 정보의 시각화

일반적으로 주식거래에 대한 시계열 데이터는 캔들차트(Candlestick Chart)로 시각화합니다. 캔들차트는 quantmod 패키지의 chartSeries() 함수를 사용합니다. 테마를 이용하여, 다음처럼 상승의 패턴은 빨간색, 하락의 패턴은 파란색으로 표시합니다.

삼성전자

trade_sec %>% 
  quantmod::chartSeries(
    theme = quantmod::chartTheme("white", up.col = "red", dn.col = "blue")
  )

워낙 긴 기간의 트랜드이라 캔들차트인지, 단순 시계열 라인차트인지 구분이 되지 않습니다. 그래서 출력 기간을 올해 1월부터 제한을 해 봅니다. 이제 캔들차트처럼 보입니다. 지금이 하락장인가보군요. 주가가 하락하는 트랜드를 보이고 있습니다.

trade_sec %>% 
  quantmod::chartSeries(
    subset="2022-01-01::2022-04-22", 
    theme = quantmod::chartTheme("white", up.col = "red", dn.col = "blue")
  )

카카오

카카오의 주가 흐름은 삼성전자의 패턴과 다른 모양입니다.

trade_kakao %>% 
  quantmod::chartSeries(
    subset="2022-01-01::2022-04-22", 
    theme = quantmod::chartTheme("white", up.col = "red", dn.col = "blue")
  )

수익률분석

삼성전자 주식 거래 데이터로 수익률 분석을 수행합니다. 주식 분할 및 배당 정보를 반영한 종가인 Adjusted 변수로 간단한 수익률 분석을 수행하겠습니다.

최고가/최저가

2000-01-04 이후의 삼성전자의 최고가를 친 날은 2021-01-11로 89,367.73원입니다. 반대로, 최저가를 친 날은 2000-10-18로 2,089.18원입니다.

trade_sec_df %>% 
  summarise(
    price_min = min(`005930.KS.Adjusted`),
    price_max = max(`005930.KS.Adjusted`),
  ) %>% 
  tidyr::pivot_longer(
    everything(),
    names_to = "event",
    values_to = "price"
  ) %>% 
  inner_join(
    trade_sec_df,
    by = c("price" = "005930.KS.Adjusted")
  )
# A tibble: 2 × 8
  event      price Index      `005930.KS.Open` `005930.KS.High`
  <chr>      <dbl> <date>                <dbl>            <dbl>
1 price_min  2089. 2000-10-18             2540             2760
2 price_max 89368. 2021-01-11            90000            96800
# … with 3 more variables: `005930.KS.Low` <dbl>,
#   `005930.KS.Close` <dbl>, `005930.KS.Volume` <dbl>

단순 수익률

매일매일의 단순 수익률은 각각 다음과 같이 구합니다.

ret_simples <- trade_sec_df %>% 
  rename(price = `005930.KS.Adjusted`) %>% 
  arrange(Index) %>% 
  mutate(price_prev = lag(price, n = 1, order_by = Index)) %>%   
  mutate(ret_simple = (price - price_prev) / price_prev * 100) %>% 
  select(Index, price, price_prev, ret_simple)

ret_simples %>% 
  head()
       Index    price price_prev ret_simple
1 2000-01-04 4675.783         NA         NA
2 2000-01-05 4270.191   4675.783 -8.6742976
3 2000-01-06 4300.802   4270.191  0.7168379
4 2000-01-07 4239.580   4300.802 -1.4234946
5 2000-01-10 4415.592   4239.580  4.1516425
6 2000-01-11 4415.592   4415.592  0.0000000

단순 수익률을 요약하면 다음과 같다. 가장 큰 일일 손실율은 2008-10-24의 -14.8%이고, 가장 큰 일일 수익율은 2001-12-05의 15%입니다. 그런데 평균 일일 수익율은 0.07%입니다.

ret_simples %>% 
  select(ret_simple) %>% 
  summary()
   ret_simple       
 Min.   :-14.92062  
 1st Qu.: -1.06381  
 Median :  0.00000  
 Mean   :  0.07173  
 3rd Qu.:  1.17234  
 Max.   : 14.99995  
 NA's   :1          
ret_simples[which.min(ret_simples$ret_simple), ]
          Index    price price_prev ret_simple
2266 2008-10-24 6301.278   7406.351  -14.92062
ret_simples[which.max(ret_simples$ret_simple), ]
         Index    price price_prev ret_simple
502 2001-12-05 4048.263    3520.23   14.99995

분포를 시각화하면 다음과 같습니다. 0%의 비율이 가장 높습니다.

Value-at-Risk

일일 99% Value-at-Risk 값을 과거 자료로 분석하면 일일 손실율이 5.72% 이상의 확률은 1% 가량 발생합니다. 즉, working day(대략 250일로 가정) 기준 일년에 약 2.5번 정도가 최대 손실율인 5.72%가 발생한다는 것을 의미합니다.

quantile(ret_simples$ret_simple, probs = 0.01, na.rm = TRUE)
      1% 
-5.71755 

복합 연간 성장률

복합 연간 성장률(CAGR, 연평균성장률)을 구하면 다음과 같습니다.

close_sec <- trade_sec[, "005930.KS.Adjusted"]
quantmod::periodReturn(close_sec, period = "yearly")
           yearly.returns
2000-12-29   -0.482815168
2001-12-31    0.765823296
2002-12-31    0.125448238
2003-12-31    0.436305587
2004-12-31   -0.001108812
2005-12-29    0.460599396
2006-12-28   -0.059841055
2007-12-28   -0.080227726
2008-12-31   -0.179238809
2009-12-30    0.790165636
2010-12-30    0.201648150
2011-12-29    0.120750509
2012-12-28    0.446560313
2013-12-30   -0.089270728
2014-12-30   -0.018274286
2015-12-30   -0.034493444
2016-12-29    0.453398771
2017-12-28    0.439622802
2018-12-28   -0.216297361
2019-12-30    0.484649506
2020-12-30    0.518439695
2021-12-30   -0.015677717
2022-04-26   -0.155810983

마무리

quantmod, zoo 패키지는 시계열 분석을 좀 더 쉽게 수행할 수 있는 여러 유용한 함수를 제공하고 있으나, tidyverse 패키지를 좀 더 적극적으로 사용했음을 밝혀둡니다.

간단하게 국내 주식의 거래 정보 데이터를 수집하는 방법을 다루어 보았습니다. 그리고 간단한 수익률 분석을 시도해 보았습니다. 아마도 주식에 관심있거나 관련 종사자들은 데이터를 수집한다면, 보다 전문적인 분석을 수행할 수 있을 것입니다. 그것으로 의미를 두고 포스트를 마칩니다.


  1. https://ko.wikipedia.org/wiki/코스피↩︎

  2. https://ko.wikipedia.org/wiki/코스닥↩︎

Citation

For attribution, please cite this work as

유충현 (2022, April 25). Dataholic: 한국 주가정보 가져오기. Retrieved from https://choonghyunryu.github.io/2022-04-25-korea-stock.Rmd

BibTeX citation

@misc{유충현2022한국,
  author = {유충현, },
  title = {Dataholic: 한국 주가정보 가져오기},
  url = {https://choonghyunryu.github.io/2022-04-25-korea-stock.Rmd},
  year = {2022}
}