주가 데이터를 수집하는 방법을 알아본다.
그래서 우선 KRX의 상장회사검색(http://marketdata.krx.co.kr/mdi#document=040601) 메뉴에서 국내 상장 주식회사의 종목코드 정보를 수집하였음. 각각의 코드는 다음의 excel 파일로 저장함.
library(xlsx)
path <- "./meta"
KOSPI <- "KRX_KOSPI_CODE.xls"
KOSDAQ <- "KRX_KOSDAQ_CODE.xls"
KONEX <- "KRX_KONEX_CODE.xls"
fKOSPI <- paste(path, KOSPI, sep="/")
fKOSDAQ <- paste(path, KOSDAQ, sep="/")
fKONEX <- paste(path, KONEX, sep="/")
KOSPI <- read.xlsx(fKOSPI, sheetIndex = 1, encoding = "UTF-8")
KOSDAQ <- read.xlsx(fKOSDAQ, sheetIndex = 1, encoding = "UTF-8")
KONEX <- read.xlsx(fKONEX, sheetIndex = 1, encoding = "UTF-8")
KOSPI <- KOSPI[, -1]
names(KOSPI) <- c("symbols", "company" ,"industry_cd",
"industry_nm", "stock_cnt", "capital",
"face_value", "currency", "phone", "address")
KOSPI$symbols <- as.character(KOSPI$symbols)
KOSPI$stock_cnt <- as.numeric(gsub(",", "", KOSPI$stock_cnt))
KOSPI$capital <- as.numeric(gsub(",", "", KOSPI$capital))
KOSPI$face_value <- as.integer(gsub(",", "", KOSPI$face_value))
KOSDAQ <- KOSDAQ[, -1]
names(KOSDAQ) <- c("symbols", "company" ,"industry_cd",
"industry_nm", "stock_cnt", "capital",
"face_value", "currency", "phone", "address")
KOSDAQ$symbols <- as.character(KOSDAQ$symbols)
KOSDAQ$stock_cnt <- as.numeric(gsub(",", "", KOSDAQ$stock_cnt))
KOSDAQ$capital <- as.numeric(gsub(",", "", KOSDAQ$capital))
KOSDAQ$face_value <- as.integer(gsub(",", "", KOSDAQ$face_value))
KONEX <- KONEX[, -1]
names(KONEX) <- c("symbols", "company" ,"industry_cd",
"industry_nm", "stock_cnt", "capital",
"face_value", "currency", "phone", "address")
KONEX$symbols <- as.character(KONEX$symbols)
KONEX$stock_cnt <- as.numeric(gsub(",", "", KONEX$stock_cnt))
KONEX$capital <- as.numeric(gsub(",", "", KONEX$capital))
KONEX$face_value <- as.integer(gsub(",", "", KONEX$face_value))
KOSPI[KOSPI$symbols == "088350", ]
symbols company industry_cd industry_nm stock_cnt capital
717 088350 한화생명 116501 보험업 868530000 4.34265e+12
face_value currency phone address
717 5000 원(KRW) 02-789-5114 서울특별시 영등포구 63로 50
종목별 거래정보는 시스템을 구축할 경우에는 적재된 종목코드 데이터의 첫번째 코드부터 마지막 코드까지 반복(iteration) 수행을 통해 개별개별 데이터를 가져와서 쌓아야 함
본 종목별 거래정보 가져오기 예제에서는 야후에서 가져옴. 실제로 구글에 비해서 야후의 데이터가 더 많은 기간의 데이터를 수용하고 있음. 다음 예제는 KOSPI의 첫 3종목의 주가 정보를 가져오는 예제임.
library("quantmod")
# getting stock data which 1st KOSPI code from Yahoo
symbols <- paste(KOSPI$symbols[1], "KS", sep = ".")
KOSPI_STOCKS <- getSymbols(symbols, from = '1990-01-01', auto.assign = FALSE)
KOSPI_STOCKS <- data.frame(date = index(KOSPI_STOCKS), symbols = KOSPI$symbols[1],
Open = as.vector(KOSPI_STOCKS[, 1]),
High = as.vector(KOSPI_STOCKS[, 2]),
Low = as.vector(KOSPI_STOCKS[, 3]),
Close = as.vector(KOSPI_STOCKS[, 4]),
Volume = as.vector(KOSPI_STOCKS[, 5]),
Adjusted = as.vector(KOSPI_STOCKS[, 6]))
row.names(KOSPI_STOCKS) <- NULL
n <- length(KOSPI[1:3])
# getting stock data which 2nd, 3rd KOSPI code from Yahoo
for (i in 2:n) {
symbols <- paste(KOSPI$symbols[i], "KS", sep = ".")
x <- getSymbols(symbols, from = '1990-01-01', auto.assign = FALSE)
x <- data.frame(date = index(x), symbols = KOSPI$symbols[i],
Open = as.vector(x[, 1]), High = as.vector(x[, 2]),
Low = as.vector(x[, 3]), Close = as.vector(x[, 4]),
Volume = as.vector(x[, 5]), Adjusted = as.vector(x[, 6]))
row.names(x) <- NULL
KOSPI_STOCKS <- rbind(KOSPI_STOCKS, x)
}
head(KOSPI_STOCKS)
date symbols Open High Low Close Volume Adjusted
1 2015-08-21 095570 6180 7300 5600 7100 9970110 6097.747
2 2015-08-24 095570 6700 6940 6240 6480 1964155 5565.268
3 2015-08-25 095570 6610 6730 6190 6220 1213650 5341.969
4 2015-08-26 095570 6260 7760 6260 7090 3518605 6089.158
5 2015-08-27 095570 7240 8060 6960 7570 2499565 6501.400
6 2015-08-28 095570 7660 7840 7090 7140 956575 6132.101
tail(KOSPI_STOCKS)
date symbols Open High Low Close Volume Adjusted
7735 2021-09-30 006840 26700 27500 26650 26950 11868 26950
7736 2021-10-01 006840 27100 27100 25000 26800 27891 26800
7737 2021-10-05 006840 26900 27300 26300 27250 38909 27250
7738 2021-10-06 006840 26950 27500 25800 26300 29122 26300
7739 2021-10-07 006840 26300 26800 26300 26400 12902 26400
7740 2021-10-08 006840 26350 26850 25950 26300 13620 26300
삼성전자의 종목코드는 0059301
이다. 이 종목의 거래정보를 Yahoo로부터 가져오기 위해서 종목코드를 005930.KS
로 변환 후 조회한다.
symbols <- "005930"
symbols <- paste(symbols, "KS", sep = ".")
symbols
[1] "005930.KS"
samsung.electric <- getSymbols(symbols, from = '1990-01-01', to = '2016-03-31',
auto.assign = FALSE)
tail(samsung.electric)
005930.KS.Open 005930.KS.High 005930.KS.Low
2016-03-24 25580 25800 25320
2016-03-25 25660 25800 25560
2016-03-28 25760 26000 25760
2016-03-29 25880 26000 25700
2016-03-30 26200 26420 26040
2016-03-31 26120 26280 25960
005930.KS.Close 005930.KS.Volume 005930.KS.Adjusted
2016-03-24 25640 10939750 22097.96
2016-03-25 25760 7172300 22201.38
2016-03-28 25880 6060900 22304.80
2016-03-29 25800 8622700 22235.85
2016-03-30 26160 13380250 22546.12
2016-03-31 26240 19130750 22615.06
주가 거래정보를 시각화하기 위해서는 quantmod 패키지의 chartSeries() 함수를 사용한다. 삼성전자의 주가를 주가 그래프로 즐겨보는 candle sticks chart를 그려보면 그림 1과 같다.
chartSeries(samsung.electric, subset = "2016-01-01::2016-03-31",
theme = chartTheme('white', up.col = 'red', dn.col = 'blue'))
Figure 1: 삼성전자 candle sticks chart
한화생명과 삼성생명의 종목코드는 각각 088350
와 032830
이다. 이 종목의 거래정보를 Yahoo로부터 가져오기 위해서 종목코드를 088350.KS
, 032830.KS
로 변환 후 조회한다.
symbols <- "088350"
symbols <- paste(symbols, "KS", sep = ".")
symbols
[1] "088350.KS"
hli <- getSymbols(symbols, from = '1990-01-01', to = '2016-03-31',
auto.assign = FALSE)
tail(hli)
088350.KS.Open 088350.KS.High 088350.KS.Low
2016-03-24 6600 6640 6550
2016-03-25 6580 6680 6540
2016-03-28 6680 6680 6580
2016-03-29 6670 6720 6630
2016-03-30 6700 6830 6650
2016-03-31 6820 6830 6700
088350.KS.Close 088350.KS.Volume 088350.KS.Adjusted
2016-03-24 6570 769252 6061.213
2016-03-25 6650 370720 6135.018
2016-03-28 6640 230891 6125.792
2016-03-29 6700 567218 6181.146
2016-03-30 6800 1192238 6273.402
2016-03-31 6700 1137339 6181.146
symbols <- "032830"
symbols <- paste(symbols, "KS", sep = ".")
symbols
[1] "032830.KS"
sli <- getSymbols(symbols, from = '1990-01-01', to = '2016-03-31',
auto.assign = FALSE)
tail(sli)
032830.KS.Open 032830.KS.High 032830.KS.Low
2016-03-24 114000 115000 113000
2016-03-25 114000 116500 113500
2016-03-28 116000 117500 115000
2016-03-29 116000 116000 113500
2016-03-30 115000 116500 114500
2016-03-31 115500 118500 115000
032830.KS.Close 032830.KS.Volume 032830.KS.Adjusted
2016-03-24 113500 224176 100142.6
2016-03-25 116000 217698 102348.3
2016-03-28 116000 249460 102348.3
2016-03-29 114500 257648 101024.9
2016-03-30 115000 220132 101466.0
2016-03-31 117500 478731 103671.8
주가 거래정보를 시각화하기 위해서 chartSeries() 함수로 그린 한화생명과 삼성생명의 candle sticks chart는 각각 그림 2와 그림 3과 같다.
chartSeries(hli, subset = "2016-01-01::2016-03-31",
theme = chartTheme('white', up.col = 'red', dn.col = 'blue'))
Figure 2: 한화생명 candle sticks chart
chartSeries(sli, subset = "2016-01-01::2016-03-31",
theme = chartTheme('white', up.col = 'red', dn.col = 'blue'))
Figure 3: 삼성생명 candle sticks chart
TTR 패키지를 이용해서 미국의 AMEX, NASDAQ, NYSE 시장의 종목코드를 가져온다.
stock_symbols <- TTR::stockSymbols()
AMEX <- stock_symbols[stock_symbols$Exchange %in% "AMEX", ]
NASDAQ <- stock_symbols[stock_symbols$Exchange %in% "NASDAQ", ]
NYSE <- stock_symbols[stock_symbols$Exchange %in% "NYSE", ]
dim(AMEX)
[1] 305 17
dim(NASDAQ)
[1] 5101 17
dim(NYSE)
[1] 3601 17
head(NYSE)
Symbol
7692 A
7693 AA
7694 AAC
7695 AAC-UN
7696 AAC-WT
7697 AAIC
Name
7692 Agilent Technologies, Inc. Common Stock
7693 Alcoa Corporation Common Stock
7694 Ares Acquisition Corporation Class A Ordinary Shares
7695 Ares Acquisition Corporation Units, each consisting of one Class A ordinary share, and one-fifth of one redeemable warrant
7696 Ares Acquisition Corporation Redeemable Warrants, each whole warrant exercisable for one Class A ordinary share at an exercise price of $11.50
7697 Arlington Asset Investment Corp Class A (new)
LastSale MarketCap IPOyear Sector Industry Exchange Test.Issue
7692 NA NA NA NA NA NYSE FALSE
7693 NA NA NA NA NA NYSE FALSE
7694 NA NA NA NA NA NYSE FALSE
7695 NA NA NA NA NA NYSE FALSE
7696 NA NA NA NA NA NYSE FALSE
7697 NA NA NA NA NA NYSE FALSE
Round.Lot.Size ETF Market.Category Financial.Status
7692 100 FALSE <NA> <NA>
7693 100 FALSE <NA> <NA>
7694 100 FALSE <NA> <NA>
7695 100 FALSE <NA> <NA>
7696 100 FALSE <NA> <NA>
7697 100 FALSE <NA> <NA>
Next.Shares ACT.Symbol CQS.Symbol NASDAQ.Symbol
7692 NA A A A
7693 NA AA AA AA
7694 NA AAC AAC AAC
7695 NA AAC.U AAC.U AAC=
7696 NA AAC.W AAC.WS AAC+
7697 NA AAIC AAIC AAIC
애플의 종목코드는 AAPL
이다. 이 종목의 거래정보를 Yahoo로부터 가져오자.
NASDAQ[grep("Apple", NASDAQ$Name), ]
Symbol Name LastSale MarketCap IPOyear
2599 AAPL Apple Inc. - Common Stock NA NA NA
Sector Industry Exchange Test.Issue Round.Lot.Size ETF
2599 NA NA NASDAQ FALSE 100 FALSE
Market.Category Financial.Status Next.Shares
2599 NASDAQ Global Select MarketSM Normal (Default) NA
ACT.Symbol CQS.Symbol NASDAQ.Symbol
2599 <NA> <NA> AAPL
symbols <- NASDAQ[grep("Apple", NASDAQ$Name), "Symbol"]
apple <- getSymbols(symbols, from = '1990-01-01', to = '2016-03-31',
auto.assign = FALSE)
tail(apple)
AAPL.Open AAPL.High AAPL.Low AAPL.Close AAPL.Volume
2016-03-22 26.3125 26.8225 26.3025 26.6800 129777600
2016-03-23 26.6200 26.7675 26.4750 26.5325 102814000
2016-03-24 26.3675 26.5625 26.2225 26.4175 104532000
2016-03-28 26.5000 26.5475 26.2650 26.2975 77645600
2016-03-29 26.2225 26.9475 26.2200 26.9200 124760400
2016-03-30 27.1625 27.6050 27.1500 27.3900 182404400
AAPL.Adjusted
2016-03-22 24.73616
2016-03-23 24.59941
2016-03-24 24.49279
2016-03-28 24.38153
2016-03-29 24.95867
2016-03-30 25.39443
애플의 candle sticks chart는 그림 4와 같다.
chartSeries(apple, subset = "2016-01-01::2016-03-31",
theme = chartTheme('white', up.col = 'red', dn.col = 'blue'))
Figure 4: apple candle sticks chart
주식 분할 및 배당 정보를 반영한 종가인 Adjusted
변수로 간단한 수익률 분석을 수행한다.
2010-03-17 이후 2016-03-31까지의 한화생명이 최고가를 친 날은 2015-11-03로 8,090.575원이다. 반대로, 최저가를 친 날은 2011-09-23로 4,688.99원이다.
hli1 <- hli[, "088350.KS.Adjusted"]
hli1[which.max(hli1)]
088350.KS.Adjusted
2015-11-03 7705.852
hli1[which.min(hli1)]
088350.KS.Adjusted
2011-09-23 4466.019
매일매일의 단순 수익률과 복리 수익률은 각각 다음과 같이 구한다.
088350.KS.Adjusted
2016-03-24 -1.3533827
2016-03-25 1.2048267
2016-03-28 -0.1492616
2016-03-29 0.8823524
2016-03-30 1.4925524
2016-03-31 NA
088350.KS.Adjusted
2016-03-24 -1.3605645
2016-03-25 1.2103096
2016-03-28 -0.1504970
2016-03-29 0.8995559
2016-03-30 1.4815234
2016-03-31 -1.4815234
단순 수익률을 요약하면 다음과 같다. 가장 큰 일일 손실율은 2013-02-26의 약 -10.8%이고, 가장 큰 일일 수익율은 2011-11-01의 약 10.69%이다. 그런데 평균 일일 수익율은 -0.01975%이다.
summary(coredata(ret.simple))
088350.KS.Adjusted
Min. :-10.81831
1st Qu.: -1.03488
Median : 0.00000
Mean : -0.01976
3rd Qu.: 0.93771
Max. : 10.68815
NA's :2
ret.simple[which.min(ret.simple)]
088350.KS.Adjusted
2013-02-26 -10.81831
ret.simple[which.max(ret.simple)]
088350.KS.Adjusted
2011-11-01 10.68815
일일 단순 손실율의 분포를 히스토그램으로 그리면 그림 5와 같다. 결과를 보면 0% 근접의 마이너스(-) 수익률의 비율이 가장 높음을 알 수 있다.
par(family='NanumGothic')
hist(ret.simple, breaks=100, freq = FALSE,
main = "한화생명 - Histogram of Simple Returns", xlab="%")
Figure 5: 한화생명 일일 단순 손실율의 분포를 히스토그램
일일 99% Value-at-Risk 값을 과거 자료로 분석하면 일일 손실율이 4.426724% 이상의 확률은 1% 가량 발생한다. 즉, working day 기준 일년에 약 2.5번 정도가 최대 손실율인 4.426724%가 발생한다는 것을 의미한다.
quantile(ret.simple, probs = 0.01, na.rm = TRUE)
1%
-4.426712
C.A.G.R. : 복합 연간 성장률 (CAGR, 연평균성장률)을 구하면 다음과 같다.
periodReturn(hli, period = 'yearly')
yearly.returns
2010-12-30 -0.08620690
2011-12-29 -0.06918239
2012-12-28 0.04864865
2013-12-30 -0.02190722
2014-12-30 0.09222661
2015-12-30 -0.10856454
2016-03-31 -0.09336942
주식 분할 및 배당 정보를 반영한 종가인 `Adjusted’ 변수로 간단한 수익률 분석을 수행한다.
2010-05-12 이후 2016-03-31까지의 삼성생명이 최고가를 친 날은 2014-12-04로 115,989.5원이다. 반대로, 최저가를 친 날은 2012-01-16로 70,075.63원이다.
sli1 <- sli[, "032830.KS.Adjusted"]
sli1[which.max(sli1)]
032830.KS.Adjusted
2014-12-04 108537.7
sli1[which.min(sli1)]
032830.KS.Adjusted
2012-01-16 65573.59
매일매일의 단순 수익률과 복리 수익률은 각각 다음과 같이 구한다.
032830.KS.Adjusted
2016-03-24 -0.8620682
2016-03-25 2.1551704
2016-03-28 0.0000000
2016-03-29 -1.3043467
2016-03-30 0.4255240
2016-03-31 NA
032830.KS.Adjusted
2016-03-24 -0.8771978
2016-03-25 2.1787334
2016-03-28 0.0000000
2016-03-29 -1.3015356
2016-03-30 0.4357224
2016-03-31 2.1506263
단순 수익률을 요약하면 다음과 같다. 가장 큰 일일 손실율은 2015-02-13의 -8.415846%이고, 가장 큰 일일 수익율은 2010-05-26의 11.00918%이다. 그런데 평균 일일 수익율은 -0.003446%이다.
summary(coredata(ret.simple))
032830.KS.Adjusted
Min. :-8.415844
1st Qu.:-0.930230
Median : 0.000000
Mean :-0.003452
3rd Qu.: 0.909096
Max. :11.009166
NA's :2
ret.simple[which.min(ret.simple)]
032830.KS.Adjusted
2015-02-13 -8.415844
ret.simple[which.max(ret.simple)]
032830.KS.Adjusted
2010-05-26 11.00917
일일 단순 손실율의 분포를 히스토그램으로 그리면 그림 6과 같다. 결과를 보면 0% 근접의 마이너스(-) 수익률의 비율이 가장 높음을 알 수 있다.
par(family='NanumGothic')
hist(ret.simple, breaks=100, freq = FALSE,
main = "삼성생명 - Histogram of Simple Returns", xlab="%")
Figure 6: 삼성생명 일일 단순 손실율의 분포를 히스토그램
일일 99% Value-at-Risk 값을 과거 자료로 분석하면 일일 손실율이 3.886695% 이상의 확률은 1% 가량 발생한다. 즉, working day 기준 일년에 약 2.5번 정도가 최대 손실율인 3.886695%가 발생한다는 것을 의미한다. 한화생명보다는 리스크가 작다.
quantile(ret.simple, probs = 0.01, na.rm = TRUE)
1%
-3.886696
복합 연간 성장률 (CAGR, 연평균성장률)을 구하면 다음과 같다.
periodReturn(sli, period = 'yearly')
yearly.returns
2010-12-30 -0.14225941
2011-12-29 -0.21073171
2012-12-28 0.16563659
2013-12-30 0.10286320
2014-12-30 0.12019231
2015-12-30 -0.05579399
2016-03-31 0.06818182
For attribution, please cite this work as
유충현 (2016, April 8). Dataholic: 주가 데이터 분석하기. Retrieved from https://choonghyunryu.github.io/posts/2016-04-08-Stock/
BibTeX citation
@misc{유충현2016주가, author = {유충현, }, title = {Dataholic: 주가 데이터 분석하기}, url = {https://choonghyunryu.github.io/posts/2016-04-08-Stock/}, year = {2016} }