前回の振り返り
前回までで、株式併合に対応できるように、終値に対してかける比率を計算し、調整後終値を計算できるようにした。
how-to-make-stock-trading-system.dogwood008.com
今回の内容
株式併合だけでなく、分割もあわせて扱って、1つの DataFrame にする。
変更内容
主に、下記の点を修正している。
- 株式分割・併合に両対応
- 全体的に構成を変更した
- カラム名を半角文字にした
- 扱いやすいようにするため
adj_close.py
import sys import re import pandas as pd from bs4 import BeautifulSoup from typing import List def get_adj_rate(paths_to_csv: List[str]) -> pd.DataFrame: def _convert_to_ratio(nl: str) -> float: before, after = re.split('[→:]', nl.replace('株', '')) return float(after) / float(before) def _html2df(path_to_csv: str) -> pd.DataFrame: html = open(path_to_csv).read() soup = BeautifulSoup(html, 'html.parser') table = soup.find('table', {'class': 'tbl01'}) rows = table.findAll('tr') csv = [ [cell.get_text() for cell in row.findAll(['td', 'th'])] for row in rows ] df = pd.DataFrame(csv, columns=csv.pop(0)) \ .rename(columns={'銘柄コード': 'code', # 扱いやすいように半角にしておく '銘柄名': 'name', '併合比率': 'rate', '割当比率': 'rate', '権利付最終日': 'from'}) return df def _adj_rates(df_in_desc: pd.DataFrame) -> list: ''' Parameters ---------------------- df_in_desc: pd.DataFrame 日時降順でソートし与えること。 ''' adj_rates_in_each_codes: dict = {} if sys.version_info.major == 3 and sys.version_info.minor >= 8: pass # 動作未検証: # return [adj_rates_in_each_codes[code] := adj_rates_in_each_codes.get(code, 1.0) / rate # for code, rate in df_in_desc[['code', 'rate']].values] else: def calc_adj_rates(code: str, rate: float): adj_rates_in_each_codes[code] = adj_rates_in_each_codes.get(code, 1.0) / rate return adj_rates_in_each_codes[code] return [calc_adj_rates(code, rate) for code, rate in df_in_desc[['code', 'rate']].values] def _reverse(df: pd.DataFrame) -> pd.DataFrame: # https://stackoverflow.com/a/20444256 return df.iloc[::-1] dfs = pd.concat([_html2df(path_to_csv) for path_to_csv in paths_to_csv]) \ .sort_values(['code', 'from'], ascending=False) dfs['rate'] = dfs['rate'].apply(_convert_to_ratio) dfs['adj_rate'] = _adj_rates(dfs) return _reverse(dfs)
実行
df = get_adj_rate(['heigou.html', 'bunkatsu.html']) df[df['from'] == '2020/10/28']
出力
2020年10月28日
の終値から適用されるもの
分割と併合を繰り返した銘柄例 [8928] 穴吹興産(株)
df[df['code'] == '8928']
確認検証
では、この算出した終値調整比が正しいかを Yahoo! ファイナンスの提供する値と比較することで検証する。
ここでは、 [9143] SGホールディングス(株)
を使用する。
まず、先ほど作成した DataFrame から、from: 2020年10月28日
からの終値調整比 adj_rate
は 0.5
とわかる。
次に、 Yahoo! ファイナンスの時系列データにアクセスし、 2020年10月28日
の終値 A
と調整後終値 B
を控える。
B
の値が A
* adj_rate
と等しければ、正しく計算できたと言える。
実際のデータを使用すると、権利上の問題がある可能性があるので、仮に A
が 10000
円だったとして考える。この時、調整後終値 B
は A: 10000
* adj_rate: 0.5
= 5000
円となり、これは Yahoo! ファイナンス上の表示とも一致する。
よって上記より、少なくとも 2020年10月28日から適用される銘柄コード 9143
については、正しく計算できたと言える。
次回
次回は、この終値調整比を使用して、 KABU+ からダウンロードしたCSVに調整後終値を付与する。