このプログラムの目的
前節で作成した予測器を使って,予測値データセットを作成します.
予測できない銘柄は外します.
work_share
├05_lightGBM_predict
├Dockerfile
├docker-compose.yml
└src
├dataset(自動生成)
├result(自動生成)
├experiment01.py
└make_predict_result_dataset.py (これを作成)
使用ライブラリ
import numpy as np
import pandas as pd
import tqdm
import json
import pickle
import os
予測できない銘柄の検出
任意の銘柄が閾値th
以上のrmseの場合は,その銘柄を使用しない銘柄として指定して返します.
def detect_non_fitting_codes(scores, th):
no_use_codes = []
for code, info in scores.items():
train_rmse = info['train rmse']
valid_rmse = info['valid rmse']
test_rmse = info['test rmse']
if (train_rmse > th) or (valid_rmse > th) or (test_rmse > th):
no_use_codes.append(code)
return no_use_codes
t日後が予測できない銘柄を検出
ret = no_use_summary.any()
は全期間(1~t日後)の予測すべてがth
以下の誤差で予測できる銘柄のみを利用するという意味です.
ret = no_use_summary.all()
にすると,全期間(1~t日後)の予測いずれかがth
以下の誤差で予測できれば利用することになります.
利用できる銘柄が少なすぎると感じた場合は`ret = no_use_summary.all()
にしてください.
def calculate_not_use_codes_at_all_time(args):
with open(f'{args["result_dir"]}/code_score_-t1.json', 'r') as f:
scores = json.load(f)
code_list = list(scores.keys())
code_list.sort()
t_list = list(range(1, args['output_time_length']+1))
no_use_summary = pd.DataFrame(columns=code_list, index=t_list)
no_use_summary = no_use_summary.fillna(False).astype('bool')
for t in t_list:
path = f'{args["result_dir"]}/code_score_-t{t}.json'
with open(path, 'r') as f:
scores = json.load(f)
if args['not_use_detect_type'] == 'non_fitting':
not_use_codes = detect_non_fitting_codes(scores, th=args['not_use_th'])
if args['not_use_detect_type'] == 'over_fitting':
not_use_codes = detect_over_fitting_codes(scores, alpha=args['not_use_alpha'])
for code in not_use_codes:
no_use_summary.at[t, code] = True
print(no_use_summary)
ret = no_use_summary.any()
not_use_codes = ret[ret==True].index.to_list()
print(ret[ret==True])
not_use_codes = [int(code) for code in not_use_codes]
return not_use_codes
データセットの作成
データセットを読み込んで,予測器に渡し,新しいデータセットを作成する.
新しいデータセットは銘柄毎に別々の列を持つものとする.
def make_dataset(args):
os.makedirs(args['new_dataset_dir'], exist_ok=True)
not_use_codes = calculate_not_use_codes_at_all_time(args)
t_list = list(range(1, args['output_time_length']+1))
print('load dataset')
X = pd.read_pickle(args['input_dataset_path'])
X_add = pd.read_pickle(args['nearest_input_dataset_path'])
X_add = X_add.drop(['date', 'is_train_data', 'code'], axis=1)
X = pd.concat([X, X_add], axis=1)
date_x = X['date']
code_x = X['code']
is_train_x = X['is_train_data']
X = X.drop(['date', 'code', 'is_train_data'], axis=1)
date_uniques = list(date_x.unique())
date_uniques.sort()
for t in tqdm.tqdm(t_list):
path = f'{args["result_dir"]}/result_-t{t}.pkl'
with open(path, 'rb') as f:
predict_result = pickle.load(f)
model = predict_result['model']
pred = model.predict(X)
temp = pd.DataFrame({'date':date_x, 'pred':pred, 'code':code_x, 'is_train_data':is_train_x})
temp = temp.set_index('date')
pred_codes = pd.DataFrame(index=date_uniques)
for code_name, grouped in temp.groupby('code'):
if code_name not in not_use_codes:
pred_codes[code_name] = grouped['pred']
pred_codes['is_train_data'] = grouped['is_train_data']
pred_codes = pred_codes.reset_index().rename(columns={'index':'date'})
pred_codes.to_pickle(f'{args["new_dataset_dir"]}/pred_codes_-t{t}.dfpkl')
Y = pd.read_pickle(args['output_dataset_path'])
Y = Y.set_index('date')
Y_codes = pd.DataFrame(index=date_uniques)
for code_name, grouped in Y.groupby('code'):
if code_name not in not_use_codes:
Y_codes[code_name] = grouped['original_close_-t0']
Y_codes['is_train_data'] = grouped['is_train_data']
Y_codes = Y_codes.reset_index().rename(columns={'index':'date'})
Y_codes.to_pickle(f'{args["new_dataset_dir"]}/original_value.dfpkl')
パラメータと実行
三種類のデータセットを作成します.
- rmse誤差1.0以下の銘柄の予測値データセット
- rmse誤差0.5以下の銘柄の予測値データセット
- rmse誤差0.3以下の銘柄の予測値データセット
誤差が小さいほど利用できる銘柄が少ないです.
if __name__ == '__main__':
args = {
'input_dataset_path':'../dataset/learning_dataset_inputs.dfpkl',
'nearest_input_dataset_path':'../dataset/learning_dataset_nearest_inputs.dfpkl',
'output_dataset_path':'../dataset/learning_dataset_outputs.dfpkl',
'result_dir':'result/experiment01/lgbm_optuna',
'output_time_length':30,
'not_use_detect_type':'non_fitting',
'not_use_th':1.0,
'new_dataset_dir':'./dataset/non_fitting_1.0'
}
make_dataset(args)
args = {
'input_dataset_path':'../dataset/learning_dataset_inputs.dfpkl',
'nearest_input_dataset_path':'../dataset/learning_dataset_nearest_inputs.dfpkl',
'output_dataset_path':'../dataset/learning_dataset_outputs.dfpkl',
'result_dir':'result/experiment01/lgbm_optuna',
'output_time_length':30,
'not_use_detect_type':'non_fitting',
'not_use_th':0.5,
'new_dataset_dir':'./dataset/non_fitting_0.5'
}
make_dataset(args)
args = {
'input_dataset_path':'../dataset/learning_dataset_inputs.dfpkl',
'nearest_input_dataset_path':'../dataset/learning_dataset_nearest_inputs.dfpkl',
'output_dataset_path':'../dataset/learning_dataset_outputs.dfpkl',
'result_dir':'result/experiment01/lgbm_optuna',
'output_time_length':30,
'not_use_detect_type':'non_fitting',
'not_use_th':0.3,
'new_dataset_dir':'./dataset/non_fitting_0.3'
}
make_dataset(args)