TensorFlowではじめる 株式投資のためのディープラーニング ですね。(p.92)
本の通りにやったらできましたよ。以下のコードが欠損してますが大丈夫ですか?
python3
1 aligned = values.assign(
2 announcement_date = lambda x: pd.cut(
3 x['日時'],
4 (
5 list(announcement_dates)
6 ) + [np.datetime64(values['日時'].max() + pd.offsets.Day())],
7 labels = announcement_dates,
8 right=False
9 ).astype(
10 np.datetime64
11 )
12 )
13 temporary_list.append(aligned)
Notebook を再起動したときは各ブロックのimport したライブラリを、[run] ボタンでリロードしてますか。一応、写経したコードを貼っておきます。
追記)
エラーが出た箇所の、tqdm, datetime のインポート表記を変更・追加をしました。
Python3
1from IPython.core.display import display
2
3from os import path
4import re
5import pandas as pd
6import numpy as np
7from tqdm.notebook import tqdm
8import datetime
9
10# データの保存場所を指定
11# この場合は、C:/Users/hoge/Anaconda3/linear_regression/ を読み書きする
12
13WORK_DIR = 'C:/Users/hoge/Anaconda3/linear_regression/'
14DATA_DIR = 'C:/Users/hoge/Anaconda3/linear_regression/data/'
15DATA_CHAPTER1 = 'C:/Users/hoge/Anaconda3/data/download_data/'
16
17daily_data = pd.read_pickle(f"{DATA_CHAPTER1}daily_data.pickle")
18
19# 銘柄ごとに計算するため、証券コード(SC)で集計する
20groups = daily_data.groupby('SC')
21
22data_set = []
23for security, values in tqdm(groups):
24 # 全体の10%以上の取引日で取引のない銘柄は無視する
25 if values['株価'].isnull().sum() > values.shape[0]*0.1:
26 continue
27
28 # 一時的に market_value 列を作って計算する
29 # 証券コード(SC)1、2 は株価指数を表しているので、単純に指数値を入れる
30 if security in {1, 2}:
31 values = values.assign(market_value = lambda x: x['株価'])
32 else:
33 values = values.assign(market_value = lambda x: x['時価総額(百万円)'])
34
35 # calculation return
36 values = values.sort_values('日時') # 時系列でソート
37 values['収益率'] = values['market_value'].pct_change() # 変化率の計算
38 values.drop(columns = ['market_value']) # 一時的な列を削除
39 data_set.append(values)
40
41daily_data_adj = pd.concat(data_set) # 銘柄ごとに計算したものを結合
42
43# 極端な値を外れ値として削除。ここでは上下 0.1% を外れ値とする
44threshold = 0.001
45
46lower = daily_data_adj['収益率'].quantile(threshold)
47upper = daily_data_adj['収益率'].quantile(1-threshold)
48
49daily_data_adj = daily_data_adj[
50 (lower < daily_data_adj['収益率']) & (daily_data_adj['収益率'] < upper)
51].copy()
52
53#############################################################
54
55jgb_path = f'{DATA_DIR}risk_free_rate/jgbcm_all.csv'
56risk_free_rate = pd.read_csv(
57 jgb_path,
58 skiprows=1,
59 usecols=['基準日', '10年'],
60 parse_dates=['基準日'],
61 encoding='sjis',
62 index_col=['基準日'],
63 na_values='-'
64)
65
66risk_free_rate = risk_free_rate['10年'].apply(
67 # 半年複利(%表記)を日時対数収益率に変換
68 lambda x: np.log(1 + 0.01 * 0.5 * x) / 125
69).apply(
70 # 単利へ変換
71 lambda x: np.exp(x) -1
72)
73risk_free_rate.rename('安全資産利子率', inplace=True)
74risk_free_rate.index.rename('日時', inplace=True)
75
76risk_free_rate = pd.DataFrame(risk_free_rate)
77
78# 出力して結果を確認
79display(risk_free_rate.dropna().head())
80
81############################################################
82
83stock_return_and_risk_free_return = pd.merge(
84 daily_data_adj[daily_data_adj['SC'] > 2],
85 risk_free_rate, on='日時'
86)
87
88# SC と日時を index にする
89stock_return_and_risk_free_return.set_index(
90 ['SC', '日時'],
91 verify_integrity=True,
92 inplace=True
93)
94# 出力して結果を確認
95display(stock_return_and_risk_free_return.head())
96
97############################################################
98
99# 日時で集計
100group_by_date = stock_return_and_risk_free_return.groupby('日時')
101
102data_with_market_returns = []
103for date, values in tqdm(group_by_date):
104 sum_of_market_capital = values['時価総額(百万円)'].sum()
105 values = values.assign(
106 # retuen がすべて null なら null にする
107 市場収益率 = lambda x: (
108 x['収益率'] * (x['時価総額(百万円)'] / sum_of_market_capital)
109 ).sum(
110 min_count=1
111 )
112 )
113 data_with_market_returns.append(values)
114
115data_with_market_returns = pd.concat(data_with_market_returns)
116
117display(data_with_market_returns.head())
118
119############################################################
120data_with_excess_returns = data_with_market_returns.assign(
121 超過収益率 = lambda x: x['収益率'] -x['安全資産利子率'],
122 市場超過収益率 = lambda x: x['市場収益率'] -x['安全資産利子率']
123)
124
125###########################################################
126# 扱いやすくするために index を通常の列に戻す
127temporary_data_excess_returns = data_with_excess_returns.reset_index()
128
129# read financial data
130financial_data = pd.read_pickle(
131 f'{DATA_CHAPTER1}financial_data_all.pickle'
132)
133
134# 利用しない列を削除
135financial_data.drop(
136 columns=['発行済株式数', '日時'],
137 inplace=True
138)
139
140# 決算発表日の株価データとマージできるように、株価データに決算発表日を張る
141group_by_security = temporary_data_excess_returns.groupby('SC')
142
143temporary_list = []
144for security, values in tqdm(group_by_security):
145
146 # 財務データから決算発表日を取得
147 # 例: array(
148 # ['2016-05-11T00:00:00.000000000', '2017-05-T00:00:00.000000000'],
149 # dtype='datetime64[ns]'
150 # )
151 announcement_dates = financial_data[
152 '決算発表日(本決算)'
153 ][
154 financial_data.SC == security
155 ].dropna().unique()
156
157 # 古いソートにして np.array に戻す
158 announcement_dates = pd.Series(announcement_dates).sort_values().values
159
160 # 収益率データの「日時」が含まれる決算期を意味するカテゴリカル変数を作る
161 # 例:「日時」が 2016-05-11 より前 → 欠損値、
162 # 「日時」が 2016-05-11 ~ 2017-05-11 → 2016-05-11、など
163
164 aligned = values.assign(
165 announcement_date = lambda x: pd.cut(
166 x['日時'],
167 (
168 list(announcement_dates)
169 ) + [np.datetime64(values['日時'].max() + pd.offsets.Day())],
170 labels = announcement_dates,
171 right=False
172 ).astype(
173 np.datetime64
174 )
175 )
176 temporary_list.append(aligned)
177
178temporary_data_excess_returns = pd.concat(temporary_list)
179temporary_data_excess_returns.rename(
180 columns = {'announcement_date':'決算発表日(日時)'},
181 inplace=True
182)
183del temporary_list
184
185# 財務データを決算発表日について一意にする
186financial_data = financial_data.groupby(
187 ['SC', '決算発表日(本決算)']
188).first().reset_index()
189
190excess_returns_with_financial_data = pd.merge(
191 temporary_data_excess_returns,
192 financial_data,
193 left_on=['SC', '名称', '決算発表日(日時)'],
194 right_on=['SC', '名称', '決算発表日(本決算)'],
195 how='left'
196)
197
198excess_returns_with_financial_data.set_index(
199 ['SC', '日時'],
200 inplace=True,
201 verify_integrity=True
202)
203
204del temporary_data_excess_returns
205
206# データを pickle で保存
207excess_returns_with_financial_data.to_pickle(
208 f'{DATA_DIR}excess_returns_with_financial_data.pickle'
209)