FC2ブログ
最初
http://blog-imgs-36.fc2.com/a/m/a/amamiyaprog/YahooFinance1.txt

修正1
http://blog-imgs-36.fc2.com/a/m/a/amamiyaprog/YahooFinance2.txt

修正2
http://blog-imgs-36.fc2.com/a/m/a/amamiyaprog/YahooFinance3.txt

修正3

# Yahoo Finance JP から株価時系列データを取得
# 引数 開始日 終了日 日 銘柄コード ($StartDate, $EndDate, $Date, $Code)
# 戻り値 [0] 日付 [1] 始値 [2] 高値 [3] 安値 [4] 終値 [5] 出来高 [6] 調整後終値 (@YahooFinance)
sub YAHOOFINANCE{
my ($StartDate, $EndDate, $Date, $Code) = @_;
my $Limit = 10;
my @Temp = ();
my @YahooFinance = ();

# 期間の確認
if($StartDate == $EndDate){
return 0;
}

# $Date d = 日 w = 週 m = 月
# 日付のフォーマット yyyymm 例(2010年3月=20103, 2009年12月=200912)
my $StartYear = substr($StartDate, 0, 4);
my $EndYear = substr($EndDate, 0, 4);
my $StartMonth = substr($StartDate, 4);
my $EndMonth = substr($EndDate, 4);
my $StartDay = 1;
my $EndDay = 1;
if($StartYear > $EndYear){
($StartYear, $EndYear) = ($EndYear, $StartYear);
($StartMonth, $EndMonth) = ($EndMonth, $StartMonth);
}
if(($StartYear == $EndYear) && ($StartMonth > $EndMonth)){
($StartMonth, $EndMonth) = ($EndMonth, $StartMonth);
}

# 取得の上限を500($Limit=10)にしておく
for(my $i = 0; $i < $Limit; $i++){
my $Page = (50 * $i);
my $Path = $StartYear."&a=".$StartMonth."&b=".$StartDay."&f=".$EndYear."&d=".$EndMonth."&e=".$EndDay."&g=".$Date."&y=".$Page."&s=".$Code;

# 株価時系列データを取得
my @Html = &GETHTML($Path, $Page);
last if(@Html == 0);
# 株価時系列データを加工
my @TimeSeries = &TIMESERIES(\@Html);
# 株価時系列データのコピー
@Temp = (@Temp, @TimeSeries);

# 取得件数が50未満なら終わり
last if(@TimeSeries < 50);
}

# 株式分割
@YahooFinance = &STOCKSPLIT(\@Temp);

return @YahooFinance;
}

# Yahoo Finance JP からHTMLを取得
# 引数 Path Page ($Path, $Page)
# 戻り値 Html (@GetHtml)
sub GETHTML{
my ($Path, $Page) = @_;
my $Host = "table.yahoo.co.jp";
my $Port = 80;
$Path = "/t?c=".$Path;
my $Ua = "GetHtml/1.0";
my @GetHtml = ();

# ソケット生成
my $IpAddr = inet_aton($Host) or die;
my $SockAddr = pack_sockaddr_in($Port, $IpAddr);
socket(SOCKET, PF_INET, SOCK_STREAM, getprotobyname('tcp')) or die;

# ソケットの接続
connect(SOCKET, $SockAddr) or die;
autoflush SOCKET (1);

# HTTPリクエスト
print SOCKET "GET ".$Path." HTTP/1.0\r\n";
print SOCKET "Connection: close\r\n";
print SOCKET "Host: ".$Host.":".$Port."\r\n";
print SOCKET "User-Agent: ".$Ua."\r\n";
print SOCKET "Referer: ".$Host.$Path."\r\n";
print SOCKET "Accept: text/html\r\n";
print SOCKET "\r\n";

# Htmlの取得
my $i = 0;
my $Flag = 0;
while(<SOCKET>){
# 時系列データのtableタグ
$Flag = 1 if($_ =~ /<table border=0 cellpadding=5 cellspacing=1 width=100%>/);
$Flag = 0 if($_ =~ m(</table>));

# <td><small> 株価
if(($Flag == 1) && ($_ =~ /<td><small>/)){
$GetHtml[$i] = $_;
# 「,」htmlタグ 改行の削除
$GetHtml[$i] =~ s/,|<.*?>|\n//g;
$i++;
}
}

# 終了
close(SOCKET);

return @GetHtml;
}

# 時系列データを加工する
# 引数 株価時系列データ ($Html)
# 戻り値 時系列データ (@TimeSeries)
sub TIMESERIES{
my ($Html) = @_;
my $Num = 0;
my $Count = 0;
my @TimeSeries = ();

# [0] 日付 [1] 始値 [2] 高値 [3] 安値 [4] 終値 [5] 出来高 [6] 調整後終値
for(my $i = 0; $i < @$Html; $i++){
# 数字以外が含まれている場合 (日付)
if($$Html[$i] =~ /^\d+(\.\d+)?$/){
$TimeSeries[$Count - 1][$Num] = $$Html[$i];
$Num++;
}else {
# 日付
$TimeSeries[$Count][0] = $$Html[$i];
$Count++;
$Num = 1;
}
}

return @TimeSeries;
}

# 株式分割
# 引数 株価時系列データ ($TimeSeries)
# 戻り値 StockSplit (@StockSplit)
sub STOCKSPLIT{
my ($TimeSeries) = @_;
my @StockSplit = @$TimeSeries;
my $Count = @$TimeSeries - 1;
my $Split = (defined($$TimeSeries[$Count][6]) == 1 ? $$TimeSeries[$Count][4] / $$TimeSeries[$Count][6] : 1);
my $PrevSplit = 0;

# 調整後終値なし 株式分割なし
if($Split == 1){
return @StockSplit;
}

for(my $i = $Count; $i >= 0; $i--){
$PrevSplit = $Split;
$Split = (defined($$TimeSeries[$i][6]) == 1 ? $$TimeSeries[$i][4] / $$TimeSeries[$i][6] : 1);

# [3] 安値
if($StockSplit[$i][3] > $$TimeSeries[$i][6]){
$StockSplit[$i][3] = int($$TimeSeries[$i][3] / $Split);
}
# [4] 終値 [6] 調整後終値
$StockSplit[$i][4] = $$TimeSeries[$i][6];
# [1] 始値 [2] 高値
if(($$TimeSeries[$i][2] / $PrevSplit) >= $StockSplit[$i][3]){
for(my $j = 1; $j <= 2; $j++){
$StockSplit[$i][$j] = int($$TimeSeries[$i][$j] / $PrevSplit);
}
}else {
for(my $j = 1; $j <= 2; $j++){
$StockSplit[$i][$j] = int($$TimeSeries[$i][$j] / $Split);
}
}

# 分割数 1 なら終わり
last if($Split <= 1);
}

return @StockSplit;
}




use warnings;
use strict;
use Socket;
use FileHandle;

# 例 2008年12月 から 2010年3月 まで デイリー
my @Yahoo = &YAHOOFINANCE(200812, 20103, "d", "8411.t");
# 例 2008年12月 から 2010年3月 まで 週間
#my @Yahoo = &YAHOOFINANCE(200812, 20103, "w", "8411.t");
# 例 2008年12月 から 2010年3月 まで 月間
#my @Yahoo = &YAHOOFINANCE(200812, 20103, "m", "8411.t");
for(my $i = 0; $i <= $#Yahoo; $i++){
for(my $j = 0; $j <= $#{$Yahoo[$i]}; $j++){
print "$Yahoo[$i][$j]\t";
}
print "\n";
}


前回
Web::Scraperを使ってyahoo financeから時系列を取得

一言
一日以降の時系列データを取得したい場合は、翌月にする (20103 -> 20104)
分割後の株価が整数でないことがある
修正不可 分割後の高値 < 終値の場合
(例: 4689.t 週間 20061 - 20071 まで取得する 2006年3月27日の時系列データ)

修正1
分割情報に小数点がある時
小数点以下を切り捨てた

修正2
分割情報を調整後終値からだす (終値 / 調整後終値)

修正3
毎回、分割情報を調整後終値からだす

メモ
正規表現がさっぱりわからん
出来高に分割情報を適用するべきなのか?
小数点以下を切り捨てたら、指数や為替の値に影響が出た
オンライン コンパイラ/インタプリタ
テクニカル分析
プロフィール

Author:雨宮
Firefoxを使用しているので気づかなかったけど、IE6でソースコードを上手くコピーできない

5/3
携帯用ならIE6でもソースコードをコピーできる
携帯用

検索フォーム


あわせて読みたいブログパーツ
一寸先は闇 RSS