30
42

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

日本株の株価を取得してpandasデータフレームに格納する

Last updated at Posted at 2017-12-17

これはなに?

  • pandas_datareaderというライブラリから海外株は取得できますが、日本株は取得できません。
  • jsmというライブラリによってBeautifulSoupを利用してxmlパースで日本株のデータを取得できますが、pandas DataFrame形式にしてはくれません。

そこで両者をいいとこどりして、データのダウンロードと同時にpandas DataFrameに直してくれるコードを書きました。

使用例

株価の取得

ファーストリテイリング(証券コード9983)の日足を現在から30日遡って取得
from read_nikkei import get_jstock
df = get_jstock(6502)
df.tail()
Open High Low Close Adj Close Volume
Date
2017-12-11 44800 45000 44410 44630 44630 562800
2017-12-12 44630 44770 44320 44340 44340 511200
2017-12-13 44480 44720 44080 44340 44340 531100
2017-12-14 44100 44400 43980 44050 44050 393500
2017-12-15 43920 45080 43840 44600 44600 646900
任天堂(証券コード7974)の2016年の週足を取得
df = get_jstock(7974, 'W', start=pd.Timestamp('2016'), end=pd.Timestamp('2017'))
df.tail()
Open High Low Close Adj Close Volume
Date
2016-11-28 27810 28245 26860 27045 27045 8573500
2016-12-05 26850 29420 26650 29255 29255 10525400
2016-12-12 29900 30180 26030 26405 26405 16958500
2016-12-19 25000 25430 23505 23595 23595 15262800
2016-12-26 23860 24820 23800 24540 24540 8286600
ソフトバンク(証券コード9984)の2017/2/1から遡って100日前からの日足を取得
df = get_jstock(9984, end=pd.Timestamp('20170201'), periods=100)
df.head(5).append(df.tail(5))
Open High Low Close Adj Close Volume
Date
2016-10-24 6584 6610 6515 6524 6524 3428700
2016-10-25 6517 6571 6515 6531 6531 4082600
2016-10-26 6532 6597 6504 6585 6585 3835600
2016-10-27 6568 6622 6526 6622 6622 3859800
2016-10-28 6620 6685 6607 6654 6654 12014500
2017-01-26 8772 8960 8765 8956 8956 12706000
2017-01-27 8983 9066 8920 8977 8977 10963300
2017-01-30 8900 8967 8833 8853 8853 6160500
2017-01-31 8703 8822 8688 8701 8701 7696500
2017-02-01 8650 8814 8636 8805 8805 6654700
東芝(証券コード6502)の取得できる最も古い日から現在までの月足を取得
df = get_jstock(6502, 'M', start='first', end='last')
df.head(5).append(df.tail(5))
Open High Low Close Adj Close Volume
Date
2000-01-01 820.0 855.0 761.0 839.0 839.0 169788000
2000-02-01 835.0 971.0 806.0 897.0 897.0 245281000
2000-03-01 937.0 1070.0 853.0 1046.0 1046.0 254632000
2000-04-01 1046.0 1080.0 891.0 1048.0 1048.0 149523000
2000-05-01 1079.0 1171.0 967.0 1040.0 1040.0 186095000
2017-08-01 249.0 326.0 244.0 306.0 306.0 776378000
2017-09-01 302.0 338.0 295.0 315.0 315.0 570638000
2017-10-01 307.0 347.0 298.0 329.0 329.0 476897000
2017-11-01 330.0 332.0 273.0 276.0 276.0 1044946000
2017-12-01 279.0 329.0 273.0 323.0 323.0 1038915000

株価の保存

データの保存は「pandas DataFrame 保存」でググって下さい。
df.to_csv('ファイル名.csv')とかdf.to_pickle('ファイル名.pkl')とか。

read_nikkeiソースコード

read_nikkei.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pandas as pd
import numpy as np
from pandas.core import common as com
import jsm

def set_span(start=None, end=None, periods=None, freq='D'):
    """ 引数のstart, end, periodsに対して
    startとendの時間を返す。

    * start, end, periods合わせて2つの引数が指定されていなければエラー
    * start, endが指定されていたらそのまま返す
    * start, periodsが指定されていたら、endを計算する
    * end, periodsが指定されていたら、startを計算する
    """
    if com._count_not_none(start, end, periods) != 2:  # Like a pd.date_range Error
        raise ValueError('Must specify two of start, end, or periods')
    start = start if start else (pd.Period(end, freq) - periods).start_time
    end = end if end else (pd.Period(start, freq) + periods).start_time
    return start, end


def get_jstock(code, freq='D', start=None, end=None, periods=None):
    """get Japanese stock data using jsm
    Usage:
        `get_jstock(6502)`
        To get TOSHIBA daily from today back to 30days except holiday.

        `get_jstock(6502, 'W', start=pd.Timestamp('2016'), end=pd.Timestamp('2017'))`
        To get TOSHIBA weekly from 2016-01-01 to 2017-01-01.

        `get_jstock(6502, end=pd.Timestamp('20170201'), periods=50)`
        To get TOSHIBA daily from 2017-02-01 back to 50days except holiday.

        `get_jstock(6502, 'M', start='first', end='last')`
        To get TOSHIBA monthly from 2000-01-01 (the date of start recording) to today.
    """
    # Default args
    if com._count_not_none(start, end, periods) == 0:  # All of args is None
        end, periods = 'last', 30

    # Switch frequency Dayly, Weekly or Monthly
    freq_dict = {'D': jsm.DAILY, 'W': jsm.WEEKLY, 'M': jsm.MONTHLY}

    # 'first' means the start of recording date
    if start == 'first':
        data = jsm.Quotes().get_historical_prices(
            code, range_type=freq_dict[freq], all=True)
        start = [i.date for i in data][-1]
    else:
        data = None  # Temporaly defined

    # 'last' means last weekday (or today)
    if end == 'last':
        end = pd.datetime.today()

    # Return "start" and "end"
    start, end = (x.date() if hasattr(x, 'date')
                  else x for x in set_span(start, end, periods, freq))
    print('Get data from {} to {}'.format(start, end))

    data = jsm.Quotes().get_historical_prices(
        code, range_type=freq_dict[freq], start_date=start, end_date=end) if not data else data
    df = _convert_dataframe(data)
    return df[start:end]


def _convert_dataframe(target):
    """Convert <jsm.pricebase.PriceData> to <pandas.DataFrame>"""
    date = [_.date for _ in target]
    open = [_.open for _ in target]
    high = [_.high for _ in target]
    low = [_.low for _ in target]
    close = [_.close for _ in target]
    adj_close = [_._adj_close for _ in target]
    volume = [_.volume for _ in target]
    data = {'Open': open,
            'High': high,
            'Low': low,
            'Close': close,
            'Adj Close': adj_close,
            'Volume': volume}
    columns = *data.keys(),
    df = pd.DataFrame(data, index=date, columns=columns).sort_index()
    df.index.name = 'Date'
    return df

pandas_datareaderと比較

pandas_datareaderと異なる機能

  • 銘柄はsymbol(Amazonなら'AMZN'とする)ではなく株価コード(数字4桁)で取得
  • 週足、月足での取得も可能(freq='W', freq='M'オプション)
    • デフォルトは日足(freq='D')
  • 期間の指定(periods=<数字>)で「endまたはstartから数えて<数字>本足の取得」
    • periodsを指定するとendまたはstartオプションが必ず必要です。
  • デフォルトでは、今日から数えて30日前からの日足データの取得(freq='D', end=pd.datetime.today(), periods=30と同様)
    • pandas_datereaderではデフォルトで2010年1月1日から今日までの株価取得(start=20100101, end=pd.datetime.today())

pandas_datareaderの使用例

pandas-datareader公式
インストールは$ conda install pandas-datareader$ pip install pandas-datareader

pandas_datareaderによるamazonの株価取得
from pandas_datareader import data
end = pd.datetime.today()  # 今日の日付
start = (pd.Period(end, 'D')-300).start_time  # 300日前日付
df = data.get_data_yahoo('AMZN', end=end, start=start)  # 300日前からのAmazon株価取得
df.tail()
Open High Low Close Adj Close Volume
Date
2017-12-11 1164.599976 1169.900024 1157.000000 1168.920044 1168.920044 2363500
2017-12-12 1166.510010 1173.599976 1161.609985 1165.079956 1165.079956 2235900
2017-12-13 1170.000000 1170.869995 1160.270020 1164.130005 1164.130005 2616800
2017-12-14 1163.709961 1177.930054 1162.449951 1174.260010 1174.260010 3156600
2017-12-14 1163.709961 1177.930054 1162.449951 1176.089966 1176.089966 1873348
30
42
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
30
42

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?