いつの間にかQiitaに引用されていました。(^^!
http://qiita.com/HirofumiYashima/items/4b3a3a3e49be59d81e4f
うまく動かないとのことなので修正をしてみました。
RFinanceYJはYahooのHTML変更に振り回されているようで、うまく動かない場合が多いです。
> library(RFinanceYJ)
> quoteStockTsData("6758.t")
以下にエラー order(financial.data$date) : 引数 1 がベクトルではありません
どうもStockTsDataの↓の部分でテーブルの形を決まりきった物として扱っているので、Yahoo側のちょっとした変更(たとえば上の方になんか広告などを追加するとか)に負けてしまっています。
extractQuoteTable <- function(r,type){
if(type %in% c("fund","fx")){
tbl <- r[[2]][[2]][[7]][[3]][[3]][[9]][[2]]
}
else{
tbl <- r[[2]][[2]][[7]][[3]][[3]][[10]][[2]]
}
return(tbl)
}
while( result.num >= 51 ){
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="")
..
#try( quote.table <- r[[2]][[1]][[1]][[16]][[1]][[1]][[1]][[4]][[1]][[1]][[1]], TRUE )
try( quote.table <- extractQuoteTable(r,type), TRUE )
Xpathで解析するようにし、若干の変更には耐えられるように修正してみました。この株価ページにはテーブルが3個あり、その2番目が株価のテーブルですので、最新版の0.3.1にまたまたパッチを当ててみました。こう書き換えます。
#try( quote.table <- extractQuoteTable(r,type), TRUE )
try( quote.table <- xpathApply(r,"//table")[[2]], TRUE )
この関数だけを読み込んでもだめなので全体を記述しそれをlibrary(RFinanceYJ)に続けて読んでやります
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.item[[1]]),time.interval)
o <- as.number(xmlValue(quote.table.item[[2]]))
h <- as.number(xmlValue(quote.table.item[[3]]))
l <- as.number(xmlValue(quote.table.item[[4]]))
c <- as.number(xmlValue(quote.table.item[[5]]))
v <- ifelse(xmlSize(quote.table.item) >= 6,as.number(xmlValue(quote.table.item[[6]])),0)
a <- ifelse(xmlSize(quote.table.item) >= 7,as.number(xmlValue(quote.table.item[[7]])),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.item[[1]]),time.interval)
if(time.interval=='monthly'){
d <- endOfMonth(d)
}
c <- as.number(xmlValue(quote.table.item[[2]]))
v <- as.number(xmlValue(quote.table.item[[3]]))
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.item[[1]]),time.interval)
o <- as.number(xmlValue(quote.table.item[[2]]))
h <- as.number(xmlValue(quote.table.item[[3]]))
l <- as.number(xmlValue(quote.table.item[[4]]))
c <- as.number(xmlValue(quote.table.item[[5]]))
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 <- r[[2]][[2]][[7]][[3]][[3]][[9]][[2]]
}
else{
tbl <- r[[2]][[2]][[7]][[3]][[3]][[10]][[2]]
}
return(tbl)
}
while( result.num >= 51 ){
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="")
#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 <- r[[2]][[1]][[1]][[16]][[1]][[1]][[1]][[4]][[1]][[1]][[1]], TRUE )
#try( quote.table <- extractQuoteTable(r,type), TRUE )
try( quote.table <- xpathApply(r,"//table")[[2]], TRUE )
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.table[[i]]))
}
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)
}
実行結果
> quoteStockTsData("6758.t",since="2010-01-01")
date open high low close volume adj_close
1136 2010-01-04 2700.0 2744.0 2694.0 2731.0 4004500 2731.0
1135 2010-01-05 2781.0 2782.0 2704.0 2719.0 4894300 2719.0
1134 2010-01-06 2719.0 2757.0 2699.0 2744.0 4270900 2744.0
1133 2010-01-07 2750.0 2764.0 2723.0 2743.0 2899600 2743.0
1132 2010-01-08 2785.0 2809.0 2769.0 2809.0 6981100 2809.0
..
長いヒストリカルデータも何のその!!
2014.8.19
HirofumiYashima様の指摘により修正してみました
なお、実行環境はMacOS10.9のR version 3.0.3 です
2015.1.20
こちらの記事はYahooの仕様変更によりとれなくなってしまいました
http://d.hatena.ne.jp/anagotan/20150120
こちらを参照ください