library(quantmod)
getSymbols('AAPL')
[1] "AAPL"
API 제공자는 본인이 가진 데이터베이스를 다른 누군가가 쉽게 사용할 수 있는 형태로 가지고 있으며, 해당 데이터베이스에 접근할 수 있는 열쇠인 API 주소를 가진 사람은 이를 언제든지 사용할 수 있습니다.
API는 API 주소만 가지고 있다면 데이터를 언제, 어디서, 누구나 쉽게 이용할 수 있다는 장점이 있습니다. 또한 대부분의 경우 사용자가 필요한 데이터만을 가지고 있으므로 접속 속도가 빠르며, 데이터를 가공하는 번거로움도 줄어듭니다. 해외에는 금융 데이터를 API의 형태로 제공하는 업체가 많으므로, 이를 잘만 활용한다면 매우 손쉽게 퀀트 투자에 필요한 데이터를 수집할 수 있습니다.
야후 파이낸스에서는 주가 데이터를 무료로 제공하며, quantmod 패키지의 getSymbols()
함수는 해당 API에 접속해 데이터를 다운로드합니다.
getSymbols()
함수의 기본적인 사용법은 매우 간단합니다. 괄호 안에 다운로드하려는 종목의 티커를 입력하면 됩니다.
library(quantmod)
getSymbols('AAPL')
[1] "AAPL"
head(AAPL)
AAPL.Open AAPL.High AAPL.Low AAPL.Close AAPL.Volume AAPL.Adjusted
2007-01-03 3.081786 3.092143 2.925000 2.992857 1238319600 2.551165
2007-01-04 3.001786 3.069643 2.993571 3.059286 847260400 2.607790
2007-01-05 3.063214 3.078571 3.014286 3.037500 834741600 2.589219
2007-01-08 3.070000 3.090357 3.045714 3.052500 797106800 2.602006
2007-01-09 3.087500 3.320714 3.041071 3.306071 3349298400 2.818154
2007-01-10 3.383929 3.492857 3.337500 3.464286 2952880000 2.953019
먼저 getSymbols()
함수 내에 애플의 티커인 AAPL을 입력합니다. 티커와 동일한 변수인 AAPL이 생성되며, 주가 데이터가 다운로드된 후 xts 형태로 입력됩니다.
다운로드 결과로 총 6개의 열이 생성됩니다. Open은 시가, High는 고가, Low는 저가, Close는 종가를 의미합니다. 또한 Volume은 거래량을 의미하며, Adjusted는 배당이 반영된 수정주가를 의미합니다. 이 중 가장 많이 사용되는 데이터는 Adjusted, 즉 배당이 반영된 수정주가입니다.
Ad()
함수를 통해 다운로드한 데이터에서 수정주가만을 선택한 후 chart_Series()
함수를 이용해 시계열 그래프를 그릴 수도 있습니다. 시계열 기간을 입력하지 않으면 2007년 1월부터 현재까지의 데이터가 다운로드되며, 입력 변수를 추가해서 원하는 기간의 데이터를 다운로드할 수도 있습니다.
= getSymbols('AAPL',
data from = '2000-01-01', to = '2018-12-31',
auto.assign = FALSE)
head(data)
AAPL.Open AAPL.High AAPL.Low AAPL.Close AAPL.Volume AAPL.Adjusted
2000-01-03 0.936384 1.004464 0.907924 0.999442 535796800 0.851942
2000-01-04 0.966518 0.987723 0.903460 0.915179 512377600 0.780115
2000-01-05 0.926339 0.987165 0.919643 0.928571 778321600 0.791530
2000-01-06 0.947545 0.955357 0.848214 0.848214 767972800 0.723033
2000-01-07 0.861607 0.901786 0.852679 0.888393 460734400 0.757282
2000-01-10 0.910714 0.912946 0.845982 0.872768 505064000 0.743963
from에는 시작시점을 입력하고 to에는 종료시점을 입력하면 해당 기간의 데이터가 다운로드됩니다.
getSymbols()
함수를 통해 다운로드한 데이터는 자동으로 티커와 동일한 변수명에 저장됩니다. 만일 티커명이 아닌 원하는 변수명에 데이터를 저장하려면 auto.assign 인자를 FALSE로 설정해주면 다운로드한 데이터가 원하는 변수에 저장됩니다.
= c('META', 'NVDA')
ticker getSymbols(ticker)
[1] "META" "NVDA"
head(META)
META.Open META.High META.Low META.Close META.Volume META.Adjusted
2012-05-18 42.05 45.00 38.00 38.23 573576400 38.23
2012-05-21 36.53 36.66 33.00 34.03 168192700 34.03
2012-05-22 32.61 33.59 30.94 31.00 101786600 31.00
2012-05-23 31.37 32.50 31.36 32.00 73600000 32.00
2012-05-24 32.95 33.21 31.77 33.03 50237200 33.03
2012-05-25 32.90 32.95 31.11 31.91 37149800 31.91
head(NVDA)
NVDA.Open NVDA.High NVDA.Low NVDA.Close NVDA.Volume NVDA.Adjusted
2007-01-03 6.178333 6.253333 5.798333 6.013333 115482000 5.518750
2007-01-04 5.991667 6.013333 5.838333 5.985000 79729800 5.492745
2007-01-05 5.843333 5.866667 5.570000 5.610000 124334400 5.148591
2007-01-08 5.630000 5.760000 5.533333 5.651667 65727000 5.186830
2007-01-09 5.660000 5.698333 5.535000 5.541667 76416600 5.085878
2007-01-10 5.483333 5.866667 5.400000 5.815000 110874600 5.336729
한 번에 여러 종목의 주가를 다운로드할 수도 있습니다. 위 예제와 같이 메타와 엔비디아의 티커인 META와 NVDA를 ticker 변수에 입력하고 getSymbols()
함수에 티커를 입력한 변수를 넣으면 두 종목의 주가가 순차적으로 다운로드됩니다.
getSymbols()
함수를 이용하면 미국뿐 아니라 국내 종목의 주가도 다운로드할 수 있습니다. 국내 종목의 티커는 총 6자리로 구성되어 있으며, 해당 함수에 입력되는 티커는 코스피 상장 종목의 경우 티커.KS, 코스닥 상장 종목의 경우 티커.KQ의 형태로 입력해야 합니다.
다음은 코스피 상장 종목인 삼성전자 데이터의 다운로드 예시입니다.
getSymbols('005930.KS')
[1] "005930.KS"
tail(Ad(`005930.KS`))
005930.KS.Adjusted
2023-01-12 60500
2023-01-13 60800
2023-01-16 61100
2023-01-17 61000
2023-01-18 60400
2023-01-19 61100
Cl()
함수는 Close, 즉 종가만을 선택하며, 사용 방법은 Ad()
함수와 동일합니다. 비록 배당을 고려할 수는 없지만, 전반적으로 오류가 없는 데이터를 사용할 수 있습니다.
다음은 코스닥 상장종목인 셀트리온제약의 예시이며, 티커인 068670에 .KQ를 붙여 함수에 입력합니다. 역시나 데이터가 다운로드되어 티커명의 변수에 저장됩니다.
getSymbols("068760.KQ")
[1] "068760.KQ"
tail(Cl(`068760.KQ`))
068760.KQ.Close
2023-01-12 NA
2023-01-13 NA
2023-01-16 NA
2023-01-17 NA
2023-01-18 NA
2023-01-19 66200
API나 크롤링을 통해 수집한 데이털르 SQL에 저장해보도록 하겠다. 먼저 SQL에서 다음과 같이 데이터베이스와 주가가 들어갈 테이블을 만든다.
create database stock_db;
use stock_db;
create table price
(
날짜 date,
시가 double,
고가 double,
저가 double,
종가 double,
거래량 double,varchar(6),
종목코드 key(날짜, 종목코드)
primary );
이제 삼성전자 주가를 SQL에 저장해보도록 하자.
library(magrittr)
= `005930.KS` %>% fortify.zoo() %>%
df select(1:6) %>%
mutate(종목코드 = '005930') %>%
set_colnames(c('날짜', '시가', '고가', '저가', '종가', '거래량', '종목코드'))
데이터를 받은 후 클렌징 처리를 해준다.
library(DBI)
library(RMySQL)
= dbConnect(
con drv = MySQL(),
user = 'root',
password = '1234',
host = '127.0.0.1',
dbname = 'stock_db'
)
dbSendQuery(con,
"SET GLOBAL local_infile = TRUE;"
)
dbWriteTable(con, "price", df,
overwrite = TRUE, row.names = FALSE)
R과 SQL을 연결한다.
local_infile를 TRUE로 설정한다.
dbWriteTable()
함수를 이용해 데이터를 price 테이블에 저장한다.
SQL을 확인해보면 주가 데이터가 저장되어 있습니다.
미국 시장의 데이터만 필요할 경우 유료 데이터 벤더를 이용하는 것도 좋은 방법입니다. 미국에는 금융 데이터를 API로 제공하는 수많은 업체가 있으며, tiingo의 경우는 월 $10만 지불하면 미국과 중국의 4만여개 종목에 대한 데이터를 API 형태로 받을 수 있습니다. 이는 상장폐지된 종목을 커버할 뿐만 아니라, API를 이용하므로 크롤링과는 비교할 수 없는 속도로 데이터를 받을 수 있다는 장점이 있습니다. 이 외에도 Alpha Vantage, Quandl, Polygon 등 수많은 데이터 벤더가 존재합니다.
tiingo는 무료 계정도 하루 1,000회까지 API 요청을 할 수 있으며, R/파이썬에서 사용할 수 있는 패키지도 있어 쉽게 사용이 가능합니다.
먼저 https://api.tiingo.com/ 사이트에 접속하여 우측 상단의 [Sign-up]을 클릭해 회원가입을 합니다. 그 후 로그인을 한 후 우측 상단에서 본인의 ID를 클릭한 후 [Account]를 선택, 좌측 메뉴의 [API] 부분에서 [Token]을 클릭하면 본인의 API token을 확인할 수 있습니다.
다음으로 발급받은 API Key를 .Renviron 파일에 추가하도록 합니다. 해당 파일에는 여러 패스워드를 추가해 안전하게 관리할 수 있습니다.
file.edit("~/.Renviron")
.Renviron 파일이 열리면 다음과 같이 입력을 해줍니다.
= '발급받은 API' RIINGO_TOKEN
파일을 저장한 후 해당 파일을 적용하기 위해 R의 Session을 재시작(ctrl+shift+F10)합니다. 그 후 아래 명령어를 실행하여 API Key를 불러오도록 합니다. (재시작하지 않으면 Key를 불러올 수 없습니다.)
다시 시작한 후 API Key를 불러옵니다.
= Sys.getenv("RIINGO_TOKEN") RIINGO_TOKEN
R에서 tiingo를 사용할 수 있게 해주는 riingo 패키지를 이용해 데이터를 받아보도록 하겠습니다. 먼저 tiingo에서 제공하는 종목은 어떠한 것이 있는지 티커 정보들을 확인해봅니다.
# install.packages("riingo")
library(riingo)
= supported_tickers()
tickers tickers
# A tibble: 106,998 × 6
ticker exchange assetType priceCurr…¹ startDate endDate
<chr> <chr> <chr> <chr> <dttm> <dttm>
1 000001 SHE Stock CNY 2007-01-04 00:00:00 2023-01-18 00:00:00
2 000002 SHE Stock CNY 2007-01-04 00:00:00 2023-01-18 00:00:00
3 000003 SHE Stock CNY NA NA
4 000004 SHE Stock CNY 2007-08-31 00:00:00 2023-01-18 00:00:00
5 000005 SHE Stock CNY 2007-08-31 00:00:00 2023-01-18 00:00:00
6 000006 SHE Stock CNY 2007-01-04 00:00:00 2023-01-18 00:00:00
7 000007 SHE Stock CNY 2007-08-31 00:00:00 2023-01-18 00:00:00
8 000008 SHE Stock CNY 2007-01-04 00:00:00 2023-01-18 00:00:00
9 000009 SHE Stock CNY 2007-01-05 00:00:00 2023-01-18 00:00:00
10 000010 SHE Stock CNY 2007-08-31 00:00:00 2023-01-18 00:00:00
# … with 106,988 more rows, and abbreviated variable name ¹priceCurrency
ticker(티커), exchange(거래소), assetType(주식 종류), priceCurrency(거래 통화), startDate(시작일), endDate(마감일) 정보가 표시됩니다. 거래소와 통화 별 종목이 몇개가 있는지 확인해보도록 하겠습니다.
library(dplyr)
%>% group_by(exchange, priceCurrency) %>% summarize(n = n()) %>%
tickers arrange(priceCurrency, desc(n))
# A tibble: 27 × 3
# Groups: exchange [24]
exchange priceCurrency n
<chr> <chr> <int>
1 ASX AUD 169
2 SHE CNY 2570
3 SHG CNY 1936
4 SHEB HKD 42
5 SHE HKD 12
6 NMFQS USD 46245
7 PINK USD 14416
8 NASDAQ USD 13113
9 NYSE USD 8170
10 OTCGREY USD 4011
# … with 17 more rows
이 중 마이너 거래소나 장외 거래소의 경우 정보를 받아도 우리나라의 증권사를 통해서는 실제로 거래를 할 수 없을수도 있습니다. 따라서 실제 거래가 가능한 거래소 데이터만 필터링한 후 해당 종목들을 받는 것이 효율적입니다.
각 종목의 상세 정보를 확인해보도록 하겠습니다.
riingo_meta("AAPL")
# A tibble: 1 × 6
ticker name description startDate endDate excha…¹
<chr> <chr> <chr> <dttm> <dttm> <chr>
1 AAPL Apple Inc Apple Inc. (… 1980-12-12 00:00:00 2023-01-18 00:00:00 NASDAQ
# … with abbreviated variable name ¹exchangeCode
riingo_meta()
함수 내에 티커를 입력하면 티커, 종목명, 사업내역 등 대략적인 정보를 받아올 수 있습니다.
이제 주가를 받아보도록 합시다.
riingo_prices("AAPL")
# A tibble: 251 × 14
ticker date close high low open volume adjClose adjHigh
<chr> <dttm> <dbl> <dbl> <dbl> <dbl> <int> <dbl> <dbl>
1 AAPL 2022-01-19 00:00:00 166. 171. 166. 170 92914792 165. 170.
2 AAPL 2022-01-20 00:00:00 165. 170. 164. 167. 91420515 163. 168.
3 AAPL 2022-01-21 00:00:00 162. 166. 162. 164. 122848858 161. 165.
4 AAPL 2022-01-24 00:00:00 162. 162. 155. 160. 162706686 160. 161.
5 AAPL 2022-01-25 00:00:00 160. 163. 157. 159. 115798367 159. 162.
6 AAPL 2022-01-26 00:00:00 160. 164. 158. 164. 108275308 159. 163.
7 AAPL 2022-01-27 00:00:00 159. 164. 158. 162. 121954638 158. 163.
8 AAPL 2022-01-28 00:00:00 170. 170. 163. 166. 179935660 169. 169.
9 AAPL 2022-01-31 00:00:00 175. 175 170. 170. 115541590 174. 174.
10 AAPL 2022-02-01 00:00:00 175. 175. 172. 174. 86213911 173. 174.
# … with 241 more rows, and 5 more variables: adjLow <dbl>, adjOpen <dbl>,
# adjVolume <int>, divCash <dbl>, splitFactor <dbl>
riingo_prices()
함수 내에 티커를 입력하면 close(종가), high(고가), low(저가), open(시가), volumne(거래량) 및 수정주가와 divCash(현금 배당), splitFactor(주식분할 조정계수)까지 데이터를 받을 수 있습니다.
이번에는 일별 가치지표를 받아보도록 합니다. (무료 계정의 경우 다우존스 30 지수에 포함되는 종목 정보만 제공합니다.)
riingo_fundamentals_metrics('AAPL')
# A tibble: 254 × 7
ticker date marketCap enterprise…¹ peRatio pbRatio trail…²
<chr> <dttm> <dbl> <dbl> <dbl> <dbl> <dbl>
1 AAPL 2022-01-19 00:00:00 2727235373310 2.81e12 27.1 37.9 1.12
2 AAPL 2022-01-20 00:00:00 2699016370470 2.78e12 26.8 37.5 1.11
3 AAPL 2022-01-21 00:00:00 2664562936770 2.75e12 26.5 37.0 1.10
4 AAPL 2022-01-24 00:00:00 2651601883140 2.74e12 26.4 36.9 1.09
5 AAPL 2022-01-25 00:00:00 2621414112660 2.71e12 26.1 36.4 1.08
6 AAPL 2022-01-26 00:00:00 2619937536930 2.71e12 26.1 36.4 1.08
7 AAPL 2022-01-27 00:00:00 2612226530340 2.70e12 26.0 36.3 1.08
8 AAPL 2022-01-28 00:00:00 2779690385530 2.87e12 27.6 38.6 1.15
9 AAPL 2022-01-31 00:00:00 2852311897980 2.94e12 28.4 39.7 1.18
10 AAPL 2022-02-01 00:00:00 2849537593010 2.94e12 28.3 39.6 1.17
# … with 244 more rows, and abbreviated variable names ¹enterpriseVal,
# ²trailingPEG1Y
riingo_fundamentals_metrics()
함수 내에 티커를 입력하면 일간 시가총액, 기업가치, PER, PBR, PEG 정보가 받아집니다.
마지막으로 재무제표를 받아보도록 합니다.
= riingo_fundamentals_statements('AAPL')
df df
# A tibble: 4 × 8
ticker date year quarter balanceSheet cashF…¹ incom…² overv…³
<chr> <dttm> <int> <int> <list> <list> <list> <list>
1 AAPL 2022-09-24 00:00:00 2022 4 <df [26 × 2]> <df> <df> <df>
2 AAPL 2022-09-24 00:00:00 2022 0 <df [26 × 2]> <df> <df> <df>
3 AAPL 2022-06-25 00:00:00 2022 3 <df [26 × 2]> <df> <df> <df>
4 AAPL 2022-03-26 00:00:00 2022 2 <df [26 × 2]> <df> <df> <df>
# … with abbreviated variable names ¹cashFlow, ²incomeStatement, ³overview
티블 내에 다시 데이터프레임이 들어간 형태입니다. 이 중 필요한 데이터만 선택해 묶음을 풀어주면 됩니다.
library(tidyr)
%>%
df select(ticker, date, year, quarter, balanceSheet) %>%
unnest(cols = c('balanceSheet'))
# A tibble: 104 × 6
ticker date year quarter dataCode value
<chr> <dttm> <int> <int> <chr> <dbl>
1 AAPL 2022-09-24 00:00:00 2022 4 liabilitiesCurrent 153982000000
2 AAPL 2022-09-24 00:00:00 2022 4 equity 50672000000
3 AAPL 2022-09-24 00:00:00 2022 4 taxLiabilities 0
4 AAPL 2022-09-24 00:00:00 2022 4 liabilitiesNonCurrent 148101000000
5 AAPL 2022-09-24 00:00:00 2022 4 retainedEarnings -3068000000
6 AAPL 2022-09-24 00:00:00 2022 4 debtCurrent 21110000000
7 AAPL 2022-09-24 00:00:00 2022 4 taxAssets 0
8 AAPL 2022-09-24 00:00:00 2022 4 assetsNonCurrent 217350000000
9 AAPL 2022-09-24 00:00:00 2022 4 acctPay 64115000000
10 AAPL 2022-09-24 00:00:00 2022 4 debt 120069000000
# … with 94 more rows