これはなに?
- 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_datereaderではデフォルトで2010年1月1日から今日までの株価取得(
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 |