1 All You Need is Data

2 경제 데이터 다운받기

  • 미국 연방준비은행에서 관리하는 Federal Reserve Economic Data(FRED)
  • quantmod 패키지의 getsymbols() 함수 통해 다운로드 가능
  • 홈페이지 URL 끝에 문자가 티커


- BEI(Breakeven Inflation Rate) 다운로드 (티커: T10YIE)

library(quantmod)
library(ggplot2)
library(highcharter)

getSymbols('T10YIE', src = 'FRED')
## [1] "T10YIE"
highchart(type = 'stock') %>%
  hc_add_series(T10YIE) %>%
  hc_scrollbar(enabled = TRUE)

3 주식 티커 다운받기

  • 주식 데이터 다운로드의 기본, 티커(ticker)
  • 국내는 6자리(예: 삼성은 005930), 해외는 영어 알파벳(예: 애플은 AAPL)
  • 티커 리스트가 있어야 이를 바탕으로 각종 데이터 다운로드 가능
  • 네이버 미국증시에서 모든 리스트 제공(뉴욕 거래소, 나스닥, 아멕스)
https://m.stock.naver.com/worldstock/index.html#/home/USA/marketValue/NYSE
  • 개발자도구 화면 연 상태로 [뉴욕 거래소] 클릭
  • 어디서 데이터 받아오는지 확인


https://api.stock.naver.com/stock/exchange/NYSE/marketValue?page=1&pageSize=20
  • 접속해보면 JSON 형태로 데이터를 제공해줌
  • pageSize= 뒤의 숫자가 한 페이지당 최대 제공가능 종목 수, 60이 맥스
  • 첫번째 페이지 테스트로 긁어오기
library(jsonlite)
library(dplyr)

url = paste0('https://api.stock.naver.com/stock/exchange/NYSE/marketValue?page=1&pageSize=60')
data = fromJSON(url, flatten = TRUE)

names(data)
## [1] "pageSize"   "page"       "totalCount" "stocks"
  • stocks 내에 원하는 데이터 있음
  • 뽑고. 클렌징!
library(readr)

data = as_tibble(data$stocks)
head(data, 3)
## # A tibble: 3 x 40
##   stockEndType reutersCode symbolCode stockName stockNameEng reutersIndustry~
##   <chr>        <chr>       <chr>      <chr>     <chr>        <chr>           
## 1 stock        BABA.K      BABA       알리바바 그룹 ~ Alibaba Gro~ 5720103013      
## 2 stock        TSM         TSM        타이완 반도체 ~ Taiwan Semi~ 5710101010      
## 3 stock        V           V          비자 Class~ Visa Inc Cl~ 5720103015      
## # ... with 34 more variables: openPrice <chr>, closePrice <chr>,
## #   compareToPreviousClosePrice <chr>, fluctuationsRatio <chr>,
## #   executedVolume <lgl>, accumulatedTradingVolume <chr>,
## #   accumulatedTradingValue <chr>, localTradedAt <chr>, marketValue <chr>,
## #   dividend <chr>, dividendPayAt <chr>, stockEndUrl <chr>, delayTime <int>,
## #   marketStatus <chr>, exchangeOperatingTime <lgl>,
## #   compareToPreviousPrice.code <chr>, compareToPreviousPrice.text <chr>,
## #   compareToPreviousPrice.name <chr>, stockExchangeType.code <chr>,
## #   stockExchangeType.zoneId <chr>, stockExchangeType.nationType <chr>,
## #   stockExchangeType.delayTime <int>, stockExchangeType.startTime <chr>,
## #   stockExchangeType.endTime <chr>,
## #   stockExchangeType.closePriceSendTime <chr>,
## #   stockExchangeType.nameKor <chr>, stockExchangeType.nameEng <chr>,
## #   stockExchangeType.name <chr>, industryCodeType.code <chr>,
## #   industryCodeType.industryGroupKor <chr>, industryCodeType.name <chr>,
## #   tradeStopType.code <chr>, tradeStopType.text <chr>,
## #   tradeStopType.name <chr>
data = data %>% 
  select(reutersCode, symbolCode, stockName, stockNameEng, closePrice, accumulatedTradingValue, accumulatedTradingValue,
         marketValue, dividend, `stockExchangeType.name`, `industryCodeType.industryGroupKor`) %>%
  mutate(closePrice = parse_number(closePrice),
         accumulatedTradingValue = parse_number(accumulatedTradingValue),
         marketValue = parse_number(marketValue),
         dividend = parse_number(dividend))

head(data, 3)
## # A tibble: 3 x 10
##   reutersCode symbolCode stockName stockNameEng closePrice accumulatedTrad~
##   <chr>       <chr>      <chr>     <chr>             <dbl>            <dbl>
## 1 BABA.K      BABA       알리바바 그룹 ~ Alibaba Gro~       263.          7749089
## 2 TSM         TSM        타이완 반도체 ~ Taiwan Semi~       128.          1233254
## 3 V           V          비자 Class~ Visa Inc Cl~       201.          2716703
## # ... with 4 more variables: marketValue <dbl>, dividend <dbl>,
## #   stockExchangeType.name <chr>, industryCodeType.industryGroupKor <chr>

3.1 전 종목 티커 다운로드

  • 위 코드를 함수로 묶고, for loop 돌려서 전 거래소에 대해 적용
# 함수로 묶기
down_data = function(ex) {
  
  data_list = list()
  
  tryCatch({
    
    for (i in 1 : 100) {
      
      url = paste0('https://api.stock.naver.com/stock/exchange/',ex,'/marketValue?page=',i,'&pageSize=60')
      data = fromJSON(url, flatten = TRUE)
      
      data = as_tibble(data$stocks)
      
      data = data %>% 
        select(reutersCode, symbolCode, stockName, stockNameEng, closePrice, accumulatedTradingValue, accumulatedTradingValue,
               marketValue, dividend, `stockExchangeType.name`, `industryCodeType.industryGroupKor`) %>%
        mutate(closePrice = parse_number(closePrice),
               accumulatedTradingValue = parse_number(accumulatedTradingValue),
               marketValue = parse_number(marketValue),
               dividend = parse_number(dividend))
      
      
      if (length(data) > 1) {
        data_list[[i]] = data
      } else {
        break
      }
      Sys.sleep(1)
    }
    
  }, error = function(e) {} )
  
  data_bind = bind_rows(data_list)
  
}

ticker_nyse = down_data('NYSE')
ticker_nasdaq = down_data('NASDAQ')
ticker_amex = down_data('AMEX')

ticker = rbind(ticker_nyse, ticker_nasdaq, ticker_amex)

3.2 클렌징 하기

  • 총 6819 개의 종목이 존재
  • 그러나 몇개는 투자할 수 없는 종목 혹은 중복된 종목 존재
  • 클렌징 ㄱㄱ!
  1. 종가 0 인 종목들: 대부분 펀드
ticker %>% filter(closePrice == 0) %>% head(3)
##   reutersCode symbolCode                         stockName
## 1     RIV_r_w  RIV RT WI RiverNorth Opportunities Fund Inc
## 2      ASPI.K       ASPI  Aspire Real Estate Investors Inc
## 3       NXU_u      NXU.U             Novus Capital Corp II
##                        stockNameEng closePrice accumulatedTradingValue
## 1 RiverNorth Opportunities Fund Inc          0                       0
## 2  Aspire Real Estate Investors Inc          0                       0
## 3             Novus Capital Corp II          0                       0
##   marketValue dividend stockExchangeType.name industryCodeType.industryGroupKor
## 1           0        0                   NYSE                 다양한 금융서비스
## 2           0        0                   NYSE                  부동산 운영 관리
## 3           0        0                   NYSE                       기타 금융업
  1. ADR 들어간 종목: 미국 종목이 아님
library(stringr)

ticker %>% filter(str_detect(stockNameEng, 'ADR')) %>% head(3)
##   reutersCode symbolCode                    stockName
## 1      BABA.K       BABA     알리바바 그룹 홀딩스 ADR
## 2         TSM        TSM 타이완 반도체 매뉴팩처링 ADR
## 3         NVS        NVS              노바티스 AG ADR
##                                    stockNameEng closePrice
## 1                 Alibaba Group Holding Ltd ADR     263.43
## 2 Taiwan Semiconductor Manufacturing Co Ltd ADR     127.50
## 3                               Novartis AG ADR      89.34
##   accumulatedTradingValue marketValue dividend stockExchangeType.name
## 1                 7716667   712745850     0.00                   NYSE
## 2                 1229653   661225200     1.74                   NYSE
## 3                  221508   201624482     3.38                   NYSE
##   industryCodeType.industryGroupKor
## 1            소프트웨어 및 IT서비스
## 2             반도체 및 반도체 장비
## 3                              제약
  1. Fund 들어간 종목
ticker %>% filter(str_detect(stockNameEng, 'Fund')) %>% head(3)
##   reutersCode symbolCode                                     stockName
## 1         NEA        NEA Nuveen Amt-Free Quality Municipal Income Fund
## 2         NVG        NVG       누빈 AMT-프리 뮤니시펄 크레딧 인컴 펀드
## 3         NAD        NAD                누빈 퀄리티 뮤니시펄 인컴 펀드
##                                    stockNameEng closePrice
## 1 Nuveen Amt-Free Quality Municipal Income Fund      15.07
## 2  Nuveen AMT-Free Municipal Credit Income Fund      16.99
## 3          Nuveen Quality Municipal Income Fund      15.28
##   accumulatedTradingValue marketValue dividend stockExchangeType.name
## 1                    6349     4198355     0.41                   NYSE
## 2                    5365     3625166     0.81                   NYSE
## 3                    4659     3233997     0.71                   NYSE
##   industryCodeType.industryGroupKor
## 1                 다양한 금융서비스
## 2                 다양한 금융서비스
## 3                 다양한 금융서비스
  1. Acquision 들어간 종목: 인수합병용 회사
ticker %>% filter(str_detect(stockNameEng, 'Acquisition')) %>% head(3)
##   reutersCode symbolCode                           stockName
## 1         BFT        BFT   폴리 트레즈민 애퀴지션 II Class A
## 2       BFT_u      BFT.U Foley Trasimene Acquisition II Corp
## 3         SBE        SBE    스위치백 에너지 어퀴지션 Class A
##                                  stockNameEng closePrice
## 1 Foley Trasimene Acquisition II Corp Class A      18.10
## 2         Foley Trasimene Acquisition II Corp      19.43
## 3  Switchback Energy Acquisition Corp Class A      40.47
##   accumulatedTradingValue marketValue dividend stockExchangeType.name
## 1                  148965     3319163        0                   NYSE
## 2                     199     2850446        0                   NYSE
## 3                  101885     1589043        0                   NYSE
##   industryCodeType.industryGroupKor
## 1                       기타 금융업
## 2                       기타 금융업
## 3                       기타 금융업
  1. PRF 들어간 종목: 우선주
ticker %>% filter(str_detect(stockNameEng, 'PRF')) %>% head(3)
##   reutersCode symbolCode                                stockName
## 1      WFC_pl   WFC PR L               웰스파고 Pref SHS Series L
## 2         ELC        ELC        엔터지 루이지애나 Pref SHS 4.875%
## 3   ALLY_pa.K  ALLY PR A GMAC 캐피탈 트러스트 I Pref SHS Series 2
##                stockNameEng closePrice accumulatedTradingValue marketValue
## 1      Wells Fargo & Co PRF    1457.00                    7013     5781376
## 2 Entergy Louisiana LLC PRF      26.39                     256     5283577
## 3  GMAC Capital Trust I PRF      26.41                    2481     2817419
##   dividend stockExchangeType.name industryCodeType.industryGroupKor
## 1    75.00                   NYSE                              은행
## 2     1.19                   NYSE                     전기 유틸리티
## 3     1.53                   NYSE                 다양한 금융서비스
ticker %>% filter(str_detect(stockName, 'Pref')) %>% head(3)
##   reutersCode symbolCode                                   stockName
## 1        PBRa      PBR.A 페트로브라스 SA ADR Each Rep 2 Pref SHS NPV
## 2      WFC_pl   WFC PR L                  웰스파고 Pref SHS Series L
## 3         ELC        ELC           엔터지 루이지애나 Pref SHS 4.875%
##                           stockNameEng closePrice accumulatedTradingValue
## 1 Petroleo Brasileiro SA Petrobras ADR      10.74                   46467
## 2                 Wells Fargo & Co PRF    1457.00                    7013
## 3            Entergy Louisiana LLC PRF      26.39                     256
##   marketValue dividend stockExchangeType.name industryCodeType.industryGroupKor
## 1    30082578     0.00                   NYSE                      오일 및 가스
## 2     5781376    75.00                   NYSE                              은행
## 3     5283577     1.19                   NYSE                     전기 유틸리티
  1. 다중 클래스
  • 종목명에 아래 캐릭터 들어간 종목은 클래스 여러개 상장된 경우
  • 아래 캐릭터 지운 다음에 중복된 종목 제거하여 클렌징
c('II', 'III', 'IV', 'V', '\\.', 'Class A', 'Class B', 'Class C', 'Class D', 'Class E',
             'Unit', 'Series A', 'Series B', 'Series C', 'Series D', 'Series E')
##  [1] "II"       "III"      "IV"       "V"        "\\."      "Class A" 
##  [7] "Class B"  "Class C"  "Class D"  "Class E"  "Unit"     "Series A"
## [13] "Series B" "Series C" "Series D" "Series E"
  • 위 사항 고려해서 클렌징해주기
spe_char = c('II', 'III', 'IV', 'V', '\\.', 'Class A', 'Class B', 'Class C', 'Class D', 'Class E',
             'Unit', 'Series A', 'Series B', 'Series C', 'Series D', 'Series E') %>%
  str_c(., collapse="|")

ticker_mod = ticker %>% filter(closePrice != 0) %>%
  filter(!str_detect(stockNameEng, 'ADR')) %>%
  filter(!str_detect(stockNameEng, 'Fund')) %>%
  filter(!str_detect(stockNameEng, 'Acquisition'))  %>%
  filter(!str_detect(stockName, 'Pref')) %>%
  filter(!str_detect(stockNameEng, 'PRF')) %>%
  distinct(stockName, .keep_all = TRUE) %>%
  distinct(stockNameEng, .keep_all = TRUE) %>%
  mutate(clean_name = str_remove_all(stockNameEng, spe_char)) %>%
  distinct(clean_name, .keep_all = TRUE)
  • 종목수가 6819에서 4824개로 줄어듬
  • 일단 저장
write.csv(ticker_mod, 'ticker_mod.csv', row.names = FALSE)

4 종목정보

  • 역시나 네이버에서 제공해줌 (ㄳㄳ)
  • 3대 항목인 [대자대조표 / 손익계산서 / 현금흐름표] 클릭해보면 어디서 데이터 오는지 확인 가능
¾ÖÇà À繫 Ç׸ñ

Figure 4.1: ¾ÖÇà À繫 Ç׸ñ

연간: https://api.stock.naver.com/stock/AAPL.O/finance/balance/annual
분기: https://api.stock.naver.com/stock/AAPL.O/finance/balance/quarter
  • 위 url 들어가보면 JSON 형태로 데이터 제공
  • url 분해
    • AAPL.O : 다운받은 티커항목에서 reutersCode 열에 해당
    • balance: 재무제표 항목에 해당, 손익계산서는 income, 현금흐름표는 cash
    • 연간은 annual, 분기는 quarter
  • 대차대조표 크롤링하기
url_bs = 'https://api.stock.naver.com/stock/MSFT.O/finance/balance/annual'
data_bs = fromJSON(url_bs, flatten = TRUE)
str(data_bs)
## List of 5
##  $ isExchangeable: logi TRUE
##  $ isKrw         : logi FALSE
##  $ unit          : chr "USD(백만). %, 배 생략"
##  $ trTitleList   :'data.frame':  3 obs. of  2 variables:
##   ..$ title: chr [1:3] "2018.06.30" "2019.06.30" "2020.06.30"
##   ..$ key  : chr [1:3] "2018.06.30" "2019.06.30" "2020.06.30"
##  $ rowList       :'data.frame':  47 obs. of  10 variables:
##   ..$ title                   : chr [1:47] "현금" "현금 & 현금성 자산" "단기 투자자산" "현금 및 단기투자자산" ...
##   ..$ columns.2019.06.30.value: chr [1:47] NA "11,356.00" "122,463.00" "133,819.00" ...
##   ..$ columns.2019.06.30.krw  : chr [1:47] NA "127,107.71" "1,370,728.36" "1,497,836.07" ...
##   ..$ columns.2019.06.30.cx   : chr [1:47] NA NA NA NA ...
##   ..$ columns.2020.06.30.value: chr [1:47] NA "13,576.00" "122,951.00" "136,527.00" ...
##   ..$ columns.2020.06.30.krw  : chr [1:47] NA "151,956.17" "1,376,190.54" "1,528,146.71" ...
##   ..$ columns.2020.06.30.cx   : chr [1:47] NA NA NA NA ...
##   ..$ columns.2018.06.30.value: chr [1:47] NA "11,946.00" "121,704.00" "133,650.00" ...
##   ..$ columns.2018.06.30.krw  : chr [1:47] NA "133,711.58" "1,362,232.87" "1,495,944.45" ...
##   ..$ columns.2018.06.30.cx   : chr [1:47] NA NA NA NA ...
  • rowList 리스트에 원하는 항목 있음
data_bs = as_tibble(data_bs$rowList)

head(data_bs, 5)
## # A tibble: 5 x 10
##   title columns.2019.06~ columns.2019.06~ columns.2019.06~ columns.2020.06~
##   <chr> <chr>            <chr>            <chr>            <chr>           
## 1 현금  <NA>             <NA>             <NA>             <NA>            
## 2 현금 &~ 11,356.00        127,107.71       <NA>             13,576.00       
## 3 단기 투~ 122,463.00       1,370,728.36     <NA>             122,951.00      
## 4 현금 및~ 133,819.00       1,497,836.07     <NA>             136,527.00      
## 5 미수금-~ 29,524.00        330,462.13       <NA>             32,011.00       
## # ... with 5 more variables: columns.2020.06.30.krw <chr>,
## #   columns.2020.06.30.cx <chr>, columns.2018.06.30.value <chr>,
## #   columns.2018.06.30.krw <chr>, columns.2018.06.30.cx <chr>
  • title과 value(달러 표시)만 선택해서 클렌징
library(tibble)

data_bs = data_bs %>% select('title', contains('value')) %>%
  column_to_rownames('title')

data_bs = data_bs %>%
  sapply(., function(x) {
    str_replace_all(x, ',', '') %>%
      as.numeric()
  }) %>%
  data.frame(., row.names = rownames(data_bs)) %>%
  set_colnames(colnames(data_bs) %>% str_remove_all('\\.') %>% parse_number())

head(data_bs, 3)
##                    20190630 20200630 20180630
## 현금                     NA       NA       NA
## 현금 & 현금성 자산    11356    13576    11946
## 단기 투자자산        122463   122951   121704
  • 클렌징 부분은 간단하게 함수로 짜두기
# 클렌징 부분 함수로
data_clean = function(url) {
  data = fromJSON(url, flatten = TRUE)
  data = as_tibble(data$rowList)
  
  data = data %>% select('title', contains('value')) %>%
    column_to_rownames('title')
  
  data = data %>%
    sapply(., function(x) {
      str_replace_all(x, ',', '') %>%
        as.numeric()
    }) %>%
    data.frame(., row.names = rownames(data)) %>%
    set_colnames(colnames(data) %>% str_remove_all('\\.') %>% parse_number())
}
  • 3대 재무제표 다운로드
data_bs_a = data_clean('https://api.stock.naver.com/stock/AAPL.O/finance/balance/annual')
data_income_a = data_clean('https://api.stock.naver.com/stock/AAPL.O/finance/income/annual')
data_cash_a = data_clean('https://api.stock.naver.com/stock/AAPL.O/finance/cash/annual')
data_bind_a = bind_rows(data_bs_a, data_income_a, data_cash_a) %>% select(sort(names(.)))

head(data_bind_a)
##                      20170930 20180929 20190928 20200926
## 현금                       NA    11575    12204    17773
## 현금 & 현금성 자산         NA    14338    36640    20243
## 단기 투자자산              NA    40388    51713    52927
## 현금 및 단기투자자산       NA    66301   100557    90943
## 미수금-무역,매출           NA    23186    22926    16120
## 총 미수금                  NA    48995    45804    37445
  • 기업 설명도 다운로드
url_overview = 'https://api.stock.naver.com/stock/AAPL.O/overview'
data_overview = fromJSON(url_overview)

data_overview = data.frame(num = data_overview$stockItemListedInfo$countOfListedStock,
                           mv = data_overview$stockItemListedInfo$marketValueFull %>% parse_number(),
                           ex = data_overview$stockItemListedInfo$stockExchange,
                           summary = data_overview$summary)

head(data_overview)
##           num           mv                ex
## 1 16788096000 2.248598e+12 나스닥 증권거래소
##                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      summary
## 1 애플은 모바일 통신 및 미디어 장치, 개인용 컴퓨터 및 휴대용 디지털 음악 플레이어를 설계, 제조 및 판매한다.<br>이 회사는 다양한 관련 소프트웨어, 서비스, 액세서리, 네트워킹 솔루션 및 타사 디지털 콘텐츠 및 애플리케이션을 판매한다.<br><br>이 회사의 시장 부문은 미주, 유럽, 중국, 일본 및 나머지 아시아 태평양 지역이다.<br>미주 부문은 북아메리카와 남아메리카를 모두 포함한다. 유럽 부문에는 유럽 국가, 인도, 중동 및 아프리카가 포함된다. 중국 부문은 중국, 홍콩 및 대만을 포함한다. 아시아태평양 나머지 부문에는 회사의 다른 운영 부문에 포함되지 않은 호주 및 아시아 국가가 포함된다.<br><br>제품 및 서비스에는 iPhone, iPad, Mac, iPod, Apple Watch, Apple TV, 소비자 및 전문 소프트웨어 애플리케이션 포트폴리오, iOS(iPhone OS), OS X 및 watch가 포함된다.<br>OS 운영 체제, iCloud, Apple Pay 및 다양한 액세서리, 서비스 및 지원 서비스를 제공한다.
  • 한번에 함수로 짜기: 3대 재무제표 연간/분기 및 기업정보 다운로드
# 클렌징
data_clean = function(url) {
  data = fromJSON(url, flatten = TRUE)
  data = as_tibble(data$rowList)
  
  data = data %>% select('title', contains('value')) %>%
    column_to_rownames('title')
  
  data = data %>%
    sapply(., function(x) {
      str_replace_all(x, ',', '') %>%
        as.numeric()
    }) %>%
    data.frame(., row.names = rownames(data)) %>%
    set_colnames(colnames(data) %>% str_remove_all('\\.') %>% parse_number()) %>%
    select(sort(names(.)))
}

data_down = function(ticker) {
  
  # 기업정보
  url_overview = paste0('https://api.stock.naver.com/stock/', ticker, '/overview')
  data_overview = fromJSON(url_overview)
  data_overview = data.frame(num = data_overview$stockItemListedInfo$countOfListedStock,
                             mv = data_overview$stockItemListedInfo$marketValueFull %>% parse_number(),
                             ex = data_overview$stockItemListedInfo$stockExchange,
                             summary = data_overview$summary)
  write.csv(data_overview, paste0(ticker, '_overview.csv'))
  
  # 재무재표 (연간)
  data_bs_a = data_clean(paste0('https://api.stock.naver.com/stock/',ticker,'/finance/balance/annual'))
  data_income_a = data_clean(paste0('https://api.stock.naver.com/stock/',ticker,'/finance/income/annual'))
  data_cash_a = data_clean(paste0('https://api.stock.naver.com/stock/',ticker,'/finance/cash/annual'))
  data_bind_a = bind_rows(data_bs_a, data_income_a, data_cash_a) %>% select(sort(names(.)))
  write.csv(data_bind_a, paste0(ticker, '_annual.csv'))
  
  # 재무제표 (분기)
  data_bs_q = data_clean(paste0('https://api.stock.naver.com/stock/',ticker,'/finance/balance/quarter'))
  data_income_q = data_clean(paste0('https://api.stock.naver.com/stock/',ticker,'/finance/income/quarter'))
  data_cash_q = data_clean(paste0('https://api.stock.naver.com/stock/',ticker,'/finance/cash/quarter'))
  data_bind_q = bind_rows(data_bs_q, data_income_q, data_cash_q) %>% select(sort(names(.)))
  write.csv(data_bind_q, paste0(ticker, '_quarter.csv'))
  
  Sys.sleep(1)
  
}
data_down('AAPL.O')
  • 폴더 확인해보면 티커_annual.csv, 티커_quarter.csv, 티커_overview.csv 저장되있음
  • 티커 리스트에서 for loop 돌리면 전 종목 데이터 다운로드 가능

5 주가 다운로드

  • getSymbols() 함수로 매우 손쉽게 다운로드 가능
  • 해당 함수쓰면 야후 파이낸스 API로 데이터 다운로드 알아서 해줌
  • 티커 리스트에서 reutersCode가 아니라 symbolCode 이용해야 함
getSymbols('AAPL', from = '1900-01-01')
## [1] "AAPL"
head(AAPL)
##            AAPL.Open AAPL.High AAPL.Low AAPL.Close AAPL.Volume AAPL.Adjusted
## 1980-12-12  0.128348  0.128906 0.128348   0.128348   469033600      0.101073
## 1980-12-15  0.122210  0.122210 0.121652   0.121652   175884800      0.095800
## 1980-12-16  0.113281  0.113281 0.112723   0.112723   105728000      0.088768
## 1980-12-17  0.115513  0.116071 0.115513   0.115513    86441600      0.090965
## 1980-12-18  0.118862  0.119420 0.118862   0.118862    73449600      0.093603
## 1980-12-19  0.126116  0.126674 0.126116   0.126116    48630400      0.099315
  • Open: 시가
  • High: 고가
  • Low: 저가 _ Close: 종가
  • Volumn: 거래량
  • Adjusted: 수정주가
Ad(AAPL) %>% chart_Series()

6 기타 투자에 도움되는 지표들

6.1 Shiller CAPE (US)

library(rvest)
library(httr)
library(dplyr)
library(lubridate)
library(stringr)
library(magrittr)
library(highcharter)
library(timetk)

Sys.setlocale("LC_ALL", "English")
## [1] "LC_COLLATE=English_United States.1252;LC_CTYPE=English_United States.1252;LC_MONETARY=English_United States.1252;LC_NUMERIC=C;LC_TIME=English_United States.1252"
url = 'https://www.multpl.com/shiller-pe/table/by-month'
data = GET(url)

data_table = data %>% read_html() %>% html_table() %>% .[[1]]

head(data_table)
##          Date Value\n\n\n\nValue
## 1 Feb 3, 2021              34.88
## 2 Jan 1, 2021              34.10
## 3 Dec 1, 2020              33.70
## 4 Nov 1, 2020              32.44
## 5 Oct 1, 2020              31.28
## 6 Sep 1, 2020              30.84
data_table = data_table %>%
  mutate(Date = as.Date(Date, format = "%B %d, %Y")) %>%
  set_colnames(c('Date', 'Value')) %>%
  tk_xts()

highchart(type = 'stock') %>%
  hc_add_series(data_table) %>%
  hc_scrollbar(enabled = TRUE)

6.2 Global CAPE

  • 전세계 CAPE 지수를 starcapital이라는 곳에서 계산해줌
  • 역사적 데이터는 없음. 시차 약간 존재
library(jsonlite)
library(magrittr)
library(dplyr)
library(httr)
library(rvest)
library(tidyr)
library(tibble)
library(DT)

url = 'https://www.starcapital.de/fileadmin/charts/Res_Aktienmarktbewertungen_FundamentalKZ_Tbl.php?lang=en'
data = fromJSON(url)

head(data)
## $cols
##      label   type
## 1  Country string
## 2   Weight number
## 3     CAPE number
## 4       PE number
## 5       PC number
## 6       PB number
## 7       PS number
## 8       DY number
## 9   RS 26W number
## 10  RS 52W number
## 11   Score number
## 
## $rows
##                                                                             c
## 1                            Venezuela, 0, NA, NA, NA, NA, NA, NA, NA, NA, NA
## 2             Korea (South), 1.7, 13.3, 24.5, 6.6, 1, 0.8, 1.9, 1.06, 1.08, 1
## 3                     China, 3.9, 18.4, 13, 6.9, 1.3, 1.2, 2.5, 1.11, 1.15, 2
## 4                       Czech, 0, 7.7, 11.1, 5.5, 1.1, 1.3, 6.3, 0.96, 0.9, 3
## 5                   Russia, 0.7, 5.9, 11.2, 4.2, 0.8, 0.7, 7.7, 0.86, 0.79, 4
## 6               Singapore, 0.6, 10.7, 19.4, 6.5, 0.8, 0.8, 4.3, 0.96, 0.87, 5
## 7                 Austria, 0.1, 10.4, 15.8, 4.5, 0.8, 0.5, 3.2, 0.91, 0.83, 6
## 8                         Spain, 0.8, 10.5, 24, 6, 1.1, 1, 4.2, 0.94, 0.88, 7
## 9                       Turkey, 0.2, 7, 13, 5.9, 1.4, 0.8, 1.1, 0.92, 0.89, 8
## 10            Philippines, 0.3, 14.3, 21.1, 8.8, 1.6, 1.2, 1.9, 1.06, 0.98, 9
## 11                   Poland, 0.1, 7.4, 14.8, 5, 0.8, 0.5, 1.1, 0.82, 0.77, 10
## 12                Portugal, 0.1, 14.9, 25, 4.9, 1.3, 0.6, 4.5, 0.91, 0.88, 11
## 13                Mexico, 0.4, 14.9, 21.6, 8.7, 1.6, 1.1, 2.8, 1.03, 0.93, 12
## 14                 Japan, 8.4, 18.8, 25.3, 9.2, 1.2, 0.8, 2.3, 1.01, 1.01, 13
## 15                    Hungary, 0, 11.1, 14.4, 6, 0.9, 0.5, 0.8, 0.89, 0.8, 14
## 16                Taiwan, 1.5, 22.4, 19.5, 11.2, 2.2, 1.3, 3.3, 1.06, 1.1, 15
## 17            South Africa, 0.5, 15, 17.7, 8.7, 1.8, 1.5, 2.9, 1.01, 0.94, 16
## 18        United Kingdom, 3.4, 11.8, 38.9, 8.5, 1.4, 0.9, 3.6, 0.95, 0.88, 17
## 19                     Italy, 0.8, 15.8, 25.8, 7, 1, 0.5, 2.7, 0.93, 0.89, 18
## 20            Hong Kong, 4.5, 13.2, 21.8, 13.7, 1.7, 2.1, 2.2, 1.04, 1.05, 19
## 21               Germany, 2.9, 15.5, 29.7, 7.8, 1.5, 0.8, 2.6, 0.94, 0.96, 20
## 22               Malaysia, 0.4, 14.3, 24, 10.5, 1.5, 1.9, 2.9, 0.98, 0.97, 21
## 23              Thailand, 0.4, 12.1, 19.3, 8.4, 1.5, 1.1, 3.2, 0.89, 0.82, 22
## 24                  Greece, 0.1, -1.6, NA, 5.1, 0.6, 0.6, 4.6, 0.91, 0.83, 23
## 25                Finland, 0.4, 22.8, 18.5, 12.5, 1.8, 1.4, 3, 1.01, 1.04, 24
## 26                Israel, 0.2, 15.5, 22.1, 12.9, 1.3, 1.1, 1.7, 0.98, 0.9, 25
## 27                Canada, 2.6, 19.5, 27.4, 8.6, 1.7, 1.4, 3.2, 0.99, 0.97, 26
## 28            Indonesia, 0.4, 13.3, 19.6, 12.8, 2.5, 1.9, 2.8, 1.01, 0.93, 27
## 29                Norway, 0.3, 13.5, 35.9, 8.8, 1.7, 1.2, 3.5, 0.94, 0.91, 28
## 30                   Australia, 1.8, 16.9, 29.2, 11.5, 2, 2, 3.6, 1, 0.99, 29
## 31                Belgium, 0.4, 17.1, 26, 11.8, 1.3, 1.4, 2.7, 0.95, 0.89, 30
## 32                   Sweden, 1, 20.7, 17.1, 14.8, 2.3, 2, 1.4, 1.01, 1.06, 31
## 33                  France, 3.4, 17.1, 43.7, 9.1, 1.6, 1, 1.9, 0.96, 0.93, 32
## 34             Ireland, 0.2, 38.1, 219.4, 13.5, 1.5, 1.8, 0.7, 1.06, 1.03, 33
## 35          New Zealand, 0.2, 29.8, 32.8, 16.7, 2.3, 2.4, 2.2, 1.06, 1.08, 34
## 36                India, 2.7, 21.3, 35.6, 17.2, 2.8, 1.8, 1.3, 1.07, 1.03, 35
## 37                Brazil, 0.8, 15.5, 32.3, 8.1, 2.1, 1.5, 3.2, 0.92, 0.79, 36
## 38              Switzerland, 2.5, 23.7, 23.7, 13.6, 2.6, 2, 3, 0.97, 0.97, 37
## 39             Netherlands, 1.4, 23.7, 46.1, 13.7, 2.1, 1.7, 1.5, 1, 1.02, 38
## 40              Denmark, 0.7, 36.2, 31.6, 17.3, 3.7, 3.1, 1.3, 1.04, 1.11, 39
## 41       United States, 47.6, 29.8, 29.1, 16.1, 3.8, 2.4, 1.6, 1.01, 1.03, 40
## 42                   WORLD AC, 100, 22.3, 26.3, 11.6, 2.1, 1.5, 2.2, 1, 1, NA
## 43         DEVELOPED MARKETS, 86.1, 23.4, 28.3, 12.3, 2.2, 1.6, 2.1, 1, 1, NA
## 44     EMERGING MARKETS, 13.9, 15.7, 18.2, 8.5, 1.6, 1.2, 2.8, 1.02, 0.99, NA
## 45       DEVELOPED EUROPE, 18.7, 15.8, 31.1, 9.4, 1.6, 1, 2.6, 0.96, 0.94, NA
## 46        EMERGING EUROPE, 1.1, 7.2, 12.2, 4.7, 0.9, 0.7, 5.3, 0.88, 0.81, NA
## 47        EMERGING AMERICA, 1.6, 16.3, 26, 7.7, 1.6, 1.1, 3.4, 0.95, 0.84, NA
## 48   DEVELOPED ASIA-PACIFIC, 17.1, NA, 24.3, 9.8, 1.3, 1, 2.5, 1.02, 1.02, NA
## 49 EMERGING ASIA-PACIFIC, 9.6, 17.1, 18.3, 9.6, 1.7, 1.4, 2.3, 1.07, 1.07, NA
## 50          EMERGING AFRICA, 0.6, NA, 17.4, 10, 1.8, 1.5, 3.3, 1.03, 0.97, NA
## 51                MIDDLE EAST, 1.1, NA, 20.1, 7.7, 1.3, 1.2, 3.4, 1.04, 1, NA
## 52                       BRIC, 8, 16.3, 17.5, 8.3, 1.6, 1.3, 2.6, 1.04, 1, NA
## 53     OTHER EMERGING MKT., 1.6, NA, 23.1, 6.8, 1.2, 0.9, 4.1, 1.02, 0.97, NA
col_name = data$cols$label

global_cape = data$rows %>% lapply(., data.frame) %>% .$c %>% t() %>% set_colnames(col_name) %>%
  data.frame() %>% set_rownames(NULL) %>%
  mutate_at(vars(-c('Country')), as.numeric) %>%
  arrange(Score)

head(global_cape)
##         Country Weight CAPE   PE  PC  PB  PS  DY RS.26W RS.52W Score
## 1 Korea (South)    1.7 13.3 24.5 6.6 1.0 0.8 1.9   1.06   1.08     1
## 2         China    3.9 18.4 13.0 6.9 1.3 1.2 2.5   1.11   1.15     2
## 3         Czech    0.0  7.7 11.1 5.5 1.1 1.3 6.3   0.96   0.90     3
## 4        Russia    0.7  5.9 11.2 4.2 0.8 0.7 7.7   0.86   0.79     4
## 5     Singapore    0.6 10.7 19.4 6.5 0.8 0.8 4.3   0.96   0.87     5
## 6       Austria    0.1 10.4 15.8 4.5 0.8 0.5 3.2   0.91   0.83     6
  • Weight: 글로벌 비중
  • CAPE: CAPE 지수
  • PE: Price To Earning
  • PC: Price to Cashflow
  • PB: Price to Book Value
  • PS: Price to Sales
  • DY: 배당수익률
  • RS26W: 26주 기준 RSI
  • RS52W: 52주 기준 RSI
  • Score: 종합점수
global_cape %>% datatable()

6.3 Fear & Greed


- 과열 단계(80 이상)에서는 매도, 공포 단계(20 이하)에서는 매수하면 개꿀

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

url = 'https://money.cnn.com/data/fear-and-greed/'
web = GET(url)

fear_data = web %>% read_html() %>% html_nodes('#needleChart') %>%
  html_nodes('ul') %>%
  html_nodes('li') %>%
  html_text() 

head(fear_data)
## [1] "Fear & Greed Now: 57 (Greed)"             
## [2] "Fear & Greed Previous Close: 51 (Neutral)"
## [3] "Fear & Greed 1 Week Ago: 36 (Fear)"       
## [4] "Fear & Greed 1 Month Ago: 52 (Neutral)"   
## [5] "Fear & Greed 1 Year Ago: 55 (Neutral)"
  • 현재 기준만 차트로 나타냄
plot_ly(
  domain = list(x = c(0, 1), y = c(0, 1)),
  value = fear_data[1] %>% parse_number,
  title = list(text = "Fear & Greed"),
  type = "indicator",
  mode = "gauge+number",
  gauge = list(
    axis = list(range = list(NULL, 100), tickwidth = 1, tickcolor = "black"),
    bar = list(color = "black"),
    bgcolor = "white",
    borderwidth = 2,
    bordercolor = "gray",
    steps = list(
      list(range = c(0, 10), color = "#ff1a1a"),
      list(range = c(10, 20), color = "#ff531a"),
      list(range = c(20, 30), color = "#ff8c1a"),
      list(range = c(30, 40), color = "#ffc61a"),
      list(range = c(40, 50), color = "#ffff1a"),
      list(range = c(50, 60), color = "#bfff00"),
      list(range = c(60, 70), color = "#80ff00"),
      list(range = c(70, 80), color = "#40ff00"),
      list(range = c(80, 90), color = "#00ff00"),
      list(range = c(90, 100), color = "#00ff40")
    ),
    threshold = list(
      line = list(color = "red", width = 4),
      thickness = 0.75,
      value = 80)) 
  ) %>%
  layout(margin = list(l=20,r=30),
         paper_bgcolor = "lavender")

6.4 인베스팅닷컴

  • 투자 소스의 끝판왕이지만, 크롤링하기 어렵게 짜둠
  • 셀레니움 사용할 경우 왠만한 데이터 모두 크롤링 가능
  • 일부 페이지는 그냥 허무하게 뚤리기도 함….

6.4.1 세계 주요 주가지수

url = 'https://www.investing.com/indices/major-indices'
data = GET(url)
data_table = data %>% read_html() %>% html_table()
data_table[[1]] %>% select(Index, Last, `Chg. %`) %>%
  datatable()
  • 비슷한 형태로 여러 테이블 크롤링 가능

6.4.2 틱 데이터

  • 차트에서 제공하는 틱/분/시/일/월/년 주가 데이터 크롤링 가능
  • https://www.investing.com/indices/kospi-chart 접속
  • [Chart 클릭] → [개발자도구 화면 열기] → [1] 선택 → [history?symbol=….]

  • url 다음과 같음
https://tvc4.forexpros.com/dbb2c736a344aeeb799279422d975bf0/1612416851/1/1/8/history?symbol=37426&resolution=1&from=1612330498&to=1612416958
  • symbol: 코스피 티커

  • resolution: n분(틱) 데이터

  • from: 시작시점. as.POSIXct 형태(1970년 1월 1일 시작)

  • to: 종료시점. as.POSIXct 형태(1970년 1월 1일 시작)

  • 위에 4가지 바꾸면 다양한 차트로 변경 가능

url = 'https://tvc4.forexpros.com/dbb2c736a344aeeb799279422d975bf0/1612416851/1/1/8/history?symbol=37426&resolution=1&from=1612330498&to=1612416958'

data = fromJSON(url)
data = data %>% data.frame() %>% select(t, c, o, h, l) %>%
  mutate_all(as.numeric) %>%
  mutate(t = as.POSIXct(t, origin="1970-01-01"))

head(data)
##                     t       c       o       h       l
## 1 2021-02-03 14:35:00 3120.77 3122.77 3122.77 3120.77
## 2 2021-02-03 14:36:00 3120.72 3121.21 3121.62 3120.51
## 3 2021-02-03 14:37:00 3123.24 3122.45 3123.24 3121.33
## 4 2021-02-03 14:38:00 3121.37 3121.93 3122.33 3120.96
## 5 2021-02-03 14:39:00 3121.13 3122.18 3122.18 3120.38
## 6 2021-02-03 14:40:00 3120.77 3121.17 3122.68 3119.88
  • t: time. 시간
  • c: close. 종가
  • o: open. 시가
  • h: high. 고가
  • l: low. 저가
i = list(line = list(color = 'red'))
d = list(line = list(color = 'blue'))

data %>% 
  plot_ly(x = ~t, type="candlestick",
          open = ~data$o, close = ~data$c,
          high = ~data$h, low = ~data$l,
          increasing = i, decreasing = d) %>%
  layout(xaxis = list(title = NA),
         yaxis = list(title = '(%)'))