株初心者が本気で儲けるブログ

株式投資・仮想通貨に関連するテーマについて取り扱ってます。

【R言語】 Yahoo!ファイナンスから株価データを取得する方法 その1

 

Rでヤフーファンナンスから株価データを直接引っ張ってくるためのパッケージとしては、「quantmodパッケージと「RFinanceYJパッケージ2つがあります。

 

今回はRfinanceYJパッケージで取得する方法を説明していきます。

 

・2016年12月10日時点でのRでヤフーファイナンスから株価データを取得する方法(仕様変更で使えなくなる可能性があります)

 

まずはパッケージのインストール

>install.packages("RFinanceYJ")

 

実行すると、ミラーサイトの場所が聞かれますが、日本に住んでいるならTokyoで問題ないです。パッケージをインストールできたら、

 

>library(RFinanceYJ)

 

でパッケージを読み込みます。

 

そして、株価を取得するには、quoteStockTsData()関数を使用します。

 

例)<9684.T>コナミの株価データを取得する場合


> quoteStockTsData("9684.t",since="2005-01-01")

※()内は ("証券番号",since="期間")を表しています。

 

すると、order(financial.data$date) でエラー: 引数 1 がベクトルではありません

と返されるか、直近2週間分の株価データしか取得できません。

 

このエラーは、YahoofinanceJapanの株価テーブルが記載されているページの仕様が変更になることが原因なようです。向こうもスクリプトで抜かれたくないのかしょっちゅう仕様変更してくるので、今の方法で取得できるうちに、使用する可能性のあるデータはバンバン取っておきましょう。

 

この解決方法は「なんだかなぁ」様のブログページ(「2015-01-20 Rでチャートを書いてみる(9)」)で、quoteStockTsData()関数の修正方法が記載されています。

 

・解決策

 

まずパッケージを呼び出し

 >library(RFinanceYJ)

 

修正コードを読み込ませます。

 #API

quoteStockTsData <- function(x, since=NULL,start.num=0,date.end=NULL,time.interval='daily')
{
time.interval <- substr(time.interval,1,1)
function.stock <- function(quote.table.item){
if( xmlSize(quote.table.item) < 5) return(NULL)
d <- convertToDate(xmlValue(quote.table.item1),time.interval)
o <- as.number(xmlValue(quote.table.item2))
h <- as.number(xmlValue(quote.table.item3))
l <- as.number(xmlValue(quote.table.item4))
c <- as.number(xmlValue(quote.table.item5))
v <- ifelse(xmlSize(quote.table.item) >= 6,as.number(xmlValue(quote.table.item6)),0)
a <- ifelse(xmlSize(quote.table.item) >= 7,as.number(xmlValue(quote.table.item7)),0)
return(data.frame(date=d,open=o,high=h,low=l,close=c,volume=v, adj_close=a))
}
return(quoteTsData(x,function.stock,since,start.num,date.end,time.interval,type="stock"))
}
quoteFundTsData <- function(x, since=NULL,start.num=0,date.end=NULL,time.interval='daily')
{
time.interval <- substr(time.interval,1,1)
function.fund <- function(quote.table.item){
d <- convertToDate(xmlValue(quote.table.item1),time.interval)
if(time.interval=='monthly'){
d <- endOfMonth(d)
}
c <- as.number(xmlValue(quote.table.item2))
v <- as.number(xmlValue(quote.table.item3))
return(data.frame(date=d,constant.value=c,NAV=v))
}
return(quoteTsData(x,function.fund,since,start.num,date.end,time.interval,type="fund"))
}
quoteFXTsData <- function(x, since=NULL,start.num=0,date.end=NULL,time.interval='daily')
{
time.interval <- substr(time.interval,1,1)
function.fx <- function(quote.table.item){
d <- convertToDate(xmlValue(quote.table.item1),time.interval)
o <- as.number(xmlValue(quote.table.item2))
h <- as.number(xmlValue(quote.table.item3))
l <- as.number(xmlValue(quote.table.item4))
c <- as.number(xmlValue(quote.table.item5))
return(data.frame(date=d,open=o,high=h,low=l,close=c))
}
return(quoteTsData(x,function.fx,since,start.num,date.end,time.interval,type="fx"))
}
###### private functions #####
#get time series data from Yahoo! Finance.
quoteTsData <- function(x,function.financialproduct,since,start.num,date.end,time.interval,type="stock"){
r <- NULL
result.num <- 51
financial.data <- data.frame(NULL)
#start <- (gsub("([0-9]{4,4})-([0-9]{2,2})-([0-9]{2,2})","&c=\\1&a=\\2&b=\\3",since))
#end <- (gsub("([0-9]{4,4})-([0-9]{2,2})-([0-9]{2,2})","&f=\\1&d=\\2&e=\\3",date.end))
start <- (gsub("([0-9]{4,4})-([0-9]{2,2})-([0-9]{2,2})","&sy=\\1&sm=\\2&sd=\\3",since))
end <- (gsub("([0-9]{4,4})-([0-9]{2,2})-([0-9]{2,2})","&ey=\\1&em=\\2&ed=\\3",date.end))

if(!any(time.interval==c('d','w','m'))) stop("Invalid time.interval value")

extractQuoteTable <- function(r,type){
if(type %in% c("fund","fx")){
tbl <- r2273392
}
else{
tbl <- r22733102
}
return(tbl)
}

#while( result.num >= 51 ){
while(1){
start.num <- start.num + 1
quote.table <- NULL
quote.url <- paste('http://info.finance.yahoo.co.jp/history/?code=',x,start,end,'&p=',start.num,'&tm=',substr(time.interval,1,1),sep="")
#cat(quote.url)
#try( r <- xmlRoot(htmlTreeParse(quote.url,error=xmlErrorCumulator(immediate=F))), TRUE) # これだと取得時にエラーが出た。。
try(r<-htmlParse(quote.url))
if( is.null(r) ) stop(paste("Can not access :", quote.url))

#try( quote.table <- r211161114111, TRUE )
#try( quote.table <- extractQuoteTable(r,type), TRUE )
try( quote.table <- xpathApply(r,"//table")2, TRUE )

quote.size<-xmlSize(quote.table)
#cat(paste("size:",quote.size))
if(xmlSize(quote.table)<=1){
return (financial.data)
}
if( is.null(quote.table) ){
if( is.null(financial.data) ){
stop(paste("Can not quote :", x))
}else{
financial.data <- financial.data[order(financial.data$date),]
return(financial.data)
}
}

size <- xmlSize(quote.table)
for(i in 2:size){
financial.data <- rbind(financial.data,function.financialproduct(quote.tablei))
}

#result.num <- xmlSize(quote.table)
Sys.sleep(1)
}
financial.data <- financial.data[order(financial.data$date),]
return(financial.data)
}
#convert string formart date to POSIXct object
convertToDate <- function(date.string,time.interval)
{
#data format is different between monthly and dialy or weekly
if(any(time.interval==c('d','w'))){
result <- gsub("^([0-9]{4})([^0-9]+)([0-9]{1,2})([^0-9]+)([0-9]{1,2})([^0-9]+)","\\1-\\3-\\5",date.string)
}else if(time.interval=='m'){
result <- gsub("^([0-9]{4})([^0-9]+)([0-9]{1,2})([^0-9]+)","\\1-\\3-01",date.string)
}
return(as.POSIXct(result))
}
#convert string to number.
as.number <- function(string)
{
return(as.double(as.character(gsub("[^0-9.]", "",string))))
}
#return end of month date.
endOfMonth <- function(date.obj)
{
startOfMonth <- as.Date(format(date.obj,"%Y%m01"),"%Y%m%d")
startOfNextMonth <- as.Date(format(startOfMonth+31,"%Y%m01"),"%Y%m%d")
return(startOfNextMonth-1)
}

 

 

 

・例:2005年からの(9684.t)スクエニの株価データを取得するとき

 

>square<-quoteStockTsData("9684.t",since="2005-01-01")

 

 

すると

f:id:oruka199665:20161210215643p:plain

 外部への出力は

>write.table("square","square.txt")

 

こんな感じで2005年1月1日までの株価データを取得してくれます。

いやーRは便利ですねー!

 

ちなみに時系列データに変換するときは、下の記事で触れたようにrev()で順番をさかさまにしないといけません。

 

まあこんな記事書いておいてなんですがこの方法はすぐ使えなくなる可能性がありますし、quantmodパッケージで取得する方がオススメです。

 

www.dmjtmj-stock.com

www.dmjtmj-stock.com