Python学習編55回目です。
scikit-learnライブラリで実際にデータをいじってみる。題材は金利と株価。データは財務省の国債金利とTOPIX終値。前回は日数0~30日をずらし、回帰直線の係数が最大、または最小となるnをとってみた…らnを求めるコードと求めたnを使って散布図描かせるコードで結果が大きく違っていた。
原因は全くわからんが、原因不明ということだけはわかるのでコードと出力結果をChatGPTに投げたところ、ラグ特徴量に原因があるらしい。コードを見てみると、.shift(-n)の「-」が抜けていた。そりゃ合わないわけだ。
原因もわかったところで散布図を描かせてみた。
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score
import numpy as np
import matplotlib.pyplot as plt
# データの読み込み
df = pd.read_csv('10年債とTOPIX.csv')
# ラグ特徴量の作成
df['target'] = df['TOPIX変化率'].shift(-12) #12日後
# 欠損値の削除(ラグ特徴量作成により発生する可能性がある)
df.dropna(inplace=True)
# 特徴量とターゲット変数の定義
X = df[['10年債利回り変化値']] # ここで複数の特徴量を使用する場合は、適宜調整してください。
y = df['target']
# 訓練データとテストデータに分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=False)
model=LinearRegression() # 線形回帰モデル
model.fit(X_train,y_train) # モデルを訓練データに適合
y_predicted=model.predict(X_test) # テストデータで予測
print(mean_squared_error(y_test,y_predicted)*10000) # 予測精度(平均二乗誤差)の評価。%の2乗の単位
coefficient = model.coef_[0] # 係数を取得
intercept = model.intercept_ # 切片を取得
print(f"回帰式: y = {intercept} + {coefficient}x") #回帰式を表示
x_plot=np.linspace(-0.1,0.1) # xの値の範囲を設定
X_plot=x_plot[:,np.newaxis] #モデルのpredictメソッドに適合する形式にするため、xの値を2次元配列に変換
y_plot=model.predict(X_plot) # 生成したxの値に対する予測値yを計算
plt.scatter(X,y, s = 2) # 元のデータ点を散布図としてプロット
plt.plot(x_plot,y_plot); # 線形回帰モデルに基づく予測値を直線としてプロット
12日後
平均二乗誤差:1.0088958330121207
回帰式: y = 0.0004326857981090838 + -0.04523734918364472x
1日後
平均二乗誤差:1.0260290118607345
回帰式: y = 0.0004771118250189825 + 0.06982140957420953x
10年債金利0.1%の上昇に対し1日後はTOPIX0.7%の増加、12日後は(始値と終値で)0.5%の減少。雑に言うなら
・10年債金利が上昇している場中が買い時
・10年債金利が上昇した11営業日後が売り時
・10年債金利が下落している場中が売り時
・10年債金利が下落した11営業日後が売り時
みたいな話なんだが、そもそも10年債金利は通常0.1%も動かず、±0.02%程度、つまりTOPIXへの寄与は0.1%程度。一方で平均二乗誤差は1%程度と約10倍なので、大量に試行回数重ねてやっと有意に表れてくる、みたいな感じになりそう。そうか、ちょっとしたことでも試行回数が大きくなってくると影響も大きくなってくるから機関投資家や専業トレーダーは手法の開発にしのぎを削ってるのか。なるほどなぁ。
次回に続く