相場商売

トレーディングビジネスあれこれ

PythonでYahooファイナンスの時系列データを取得してみた

第7章のデータダウンロードについて。

まずはlibフォルダのstock_data_getter.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import codecs, os
import datetime
import urllib.request, urllib.error
import re

# Yahoo!ファイナンスから株価データをダウンロードするクラス
class StockDataGetter:
    def __init__(self, frm, to, market):
        self.from_date = datetime.datetime.strptime(frm, '%Y/%m/%d')
        self.to_date   = datetime.datetime.strptime(to, '%Y/%m/%d')
        self.market    = market
        self.data_dir  = 'data'
        
    # 株価データの新規取得
    def get_price_data(self, code):
        self.code = code
        self.save_to_file(self.prices_text())
        
    def update_price_data(self, code):
        self.code = code
        if os.path.exists(self.data_file_name()):
            self.get_from_date()
            self.append_to_file(self.prices_text())
        else:
            self.save_to_file(self.prices_text())
            
    # ファイルに記録される文字列
    def prices_text(self):
        prices = self.get_price_data_from_historical_data_pages()
        if len(prices) == 0:
            return []
        else:
            return self.prices_to_text(prices)   
 
    # 時系列データのページを読み込む
    def get_price_data_from_historical_data_pages(self):
        page_num = 1
        prices = []
        reg_data = re.compile(self.reg_prices())
        reg_next = re.compile(r'次へ</a></ul>')
        while True:
            url = self.url_for_historical_data(page_num)
            try:
                request = urllib.request.Request(url)
                text = urllib.request.urlopen(request).read().decode('utf-8')
            except urllib.error.HTTPError:
                return []
            except urllib.error.URLError:
                return []
            prices.extend(reg_data.findall(text))
            page_num += 1
            if reg_next.search(text) == None:
                break
        return prices
    
    # 時系列データのURL
    def url_for_historical_data(self, page_num):
        return 'http://info.finance.yahoo.co.jp/history/?code={0}.{1}&sy={2}&sm={3}&sd={4}&ey={5}&em={6}&ed={7}&tm=d&p={8}'.format(self.code, self.market, self.from_date.year, self.from_date.month, self.from_date.day, self.to_date.year, self.to_date.month, self.to_date.day, page_num)
    
    # 株価データ表から株価データを取り出すための
    # 正規表現パターン
    def reg_prices(self):
        return r'<td>(\d{4}年\d{1,2}月\d{1,2}日)</td><td>((?:\d|,)+)</td><td>((?:\d|,)+)</td><td>((?:\d|,)+)</td><td>((?:\d|,)+)</td><td>((?:\d|,)+)</td><td>((?:\d|,)+)</td>'
    
    # 株価データの配列を文字列に変換
    def prices_to_text(self, prices):
        new_prices = []
        reg_month = re.compile('/(\d)/')
        reg_day   = re.compile('/(\d)$')
        for price in reversed(prices):
            p = []
            # price[0]は日付
            # 年月日の文字を取り除き"/"で区切る
            p.append(re.sub('[年月]', '/', price[0]))
            p[0] = re.sub('日', '', p[0])
            # 1桁の月や日を0で始まる二桁の数字に            
            if reg_month.search(p[0]):
                p[0] = reg_month.sub('/0' + reg_month.search(p[0]).group(1) +'/', p[0])
            if reg_day.search(p[0]) != None:
                p[0] = reg_day.sub('/0' + reg_day.search(p[0]).group(1), p[0])
            # price[1..6]は値段と出来高
            # 数字の間にあるカンマを取り除く
            for i in range(1, 7):
                p.append(re.sub(',', '', price[i]))
            new_prices.append(','.join(p))
        return '\n'.join(new_prices)
      
    def data_file_name(self):
        return '{0}/{1}.txt'.format(self.data_dir, self.code)
    
    # ファイル中の最終日の翌日を新しい開始日とする
    def get_from_date(self):
        last_date = codecs.open(self.data_file_name(), 'r', 'utf-8').readlines()[-1][:10]
        self.from_date = datetime.datetime.strptime(last_date, '%Y/%m/%d') + datetime.timedelta(days=+1)

    # データをテキストに保存
    def save_to_file(self, prices_text):
        self.save(prices_text, "w")

    # 既存のファイルにデータを追加
    def append_to_file(self, prices_text):
        self.save(prices_text, "a")

    def save(self, prices_text, open_mode):
        if len(prices_text) != 0:
            f = codecs.open(self.data_file_name(), open_mode)
            f.write(prices_text)
            f.close()
            print(self.code)

fromが予約語だったのでfrmに変えた。

それからcheckフォルダのget_price_data.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from lib.stock_data_getter import StockDataGetter

# 東証銘柄をダウンロードする
# 名証銘柄をダウンロードしたければ、market =:n とする
# 福証なら market = f、札証なら market = s

frm = "2011/01/4"
to  = "2011/07/30"
market = 't'

sdg = StockDataGetter(frm, to, market)

for code in range(1301, 10000, 1):
    sdg.get_price_data(code)

input()

Googleで'Python ヤフーファイナンス 時系列'などと検索して、
他の方の書いたコードを見ていたらほとんどbeautifulsoupを使っていた。
それほど便利ということだろうから、
10章以降のシミュレーション編に移る前にbeautifulsoupの使い方も覚えることにした。

それなりにPythonが分かってきた。
やっぱり興味ある分野でコード書かないと脳が覚えようとしない。

とりあえず8章に続く。