Rでチャートを書いてみる(9)

どうやらまたYahooの時系列データの仕様が変わったようです。

http://d.hatena.ne.jp/anagotan/20140816/1408276789

こちらで書いたものが使えなくなっていました。具体的には先頭(直近)のページのみのデータしか拾えていません。

そこでちょっとまたまた、いじってみました。

RFinanceYJを作った方の真意わかりませんがquoteTsData関数の

while( result.num >= 51 ){
..
result.num <- xmlSize(quote.table)

この部分で次ページがあるかどうか判定していたのがうまく作用しなくなっています。

そこで下記のように修正してみました。

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 ){
	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 <- 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 )
 
		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.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="2014-01-01")

以前と同じようにRのコンソールにコピーアンドペーストで実行

> quoteStockTsData("6758.t",since="2014-01-01")
					date	 open	 high		low	close	 volume adj_close
1	 2015-01-20 2430.0 2466.5 2397.5 2462.5	8926300		2462.5
2	 2015-01-19 2425.0 2448.5 2402.0 2443.5	7436000		2443.5
3	 2015-01-16 2426.0 2437.5 2351.5 2384.0 15055500		2384.0
4	 2015-01-15 2453.5 2511.0 2452.5 2500.0	7843800		2500.0
..
252 2014-01-09 1898.0 1920.0 1870.0 1894.0 37843200		1894.0
253 2014-01-08 1799.0 1827.0 1788.0 1825.0 10182500		1825.0
254 2014-01-07 1820.0 1820.0 1792.0 1800.0	7516600		1800.0
255 2014-01-06 1815.0 1830.0 1787.0 1802.0 10114200		1802.0
> 

無事取れるようになりました

Rでチャートを書いてみる(9)” への1件のフィードバック

  1. たかし

    ありがとうございます.使えるようになりました

コメントは停止中です。