形が似ているグラフ(時系列データ)を見つけたいときってありますよね.
今回は,スケールが違うけど形は似ている時系列データを見つけるために,スケールを正規化してMAE(平均絶対誤差)で比較する方法を書きます.
#動機
普段はこちらの記事で株式投資について書いていますが,形が似ている銘柄をスクリーニングしたいと考えました(例えば,コロナショックで大きく変動した銘柄を抽出する).
形が似ている銘柄をスクリーニングするメリットとして,
・形が同じような銘柄は避け,分散投資に役立てる
・形が同じような銘柄を買い,ひとつの個別銘柄の不調を補う
・形が同じような銘柄の共通点を分析することで投資に役立てる
などがあります.
しかし,株価というものは形が似ていてもスケールがバラバラです.
例えば,以下のUAL(ユナイテッド・エアライン・ホールディングス)とDAL(デルタ航空)はコロナショックで大きく下落したので形は似ていますが,スケールが違うのでスクリーニングするときに何を基準に比較するか困ってしまいます.
そこでこの記事では,スクリーニングの準備のために同じスケールに正規化して比較するコードを用意します.
#株価データの準備
すでに比較したいデータがある場合は,この章は飛ばしてください.
今回は,Pythonのpandas-datareaderでUAL,DAL,AAPLの株価を取得します.
※今回の内容には関係ないですが,取得したらCSVなどに保存することをおすすめします.APIのサーバーの負担になるからです.
import datetime
import pandas_datareader.data as web
start = datetime.date(2018,1,1)
end = datetime.date.today()
ual = web.DataReader('UAL', 'yahoo', start, end)['Adj Close']
dal = web.DataReader('DAL', 'yahoo', start, end)['Adj Close']
aapl = web.DataReader('AAPL', 'yahoo', start, end)['Adj Close']
※調整後終値(Adj Close)のみを取得しています.
これらの株価データはpandasのDataFrameで与えられます.
この時点では,以下のデータようなデータになっています.
#正規化する
データの形だけを比較するために,スケールを0~1に正規化します.
正規化には,Min-Max Normalizationを使います.
mmn(x) = \frac{x_i-\min(x)}{\max(x)-\min(x)}
pandasのDataFrameは,以下で正規化できます.
def mmn(ticker):
mmn = (ticker - ticker.min()) / (ticker.max() - ticker.min())
return mmn
ual = mmn(ual)
dal = mmn(dal)
aapl = mmn(aapl)
これで,以下のようにデータが0~1に正規化されていると思います.
UALとDALの株価の形が似ていることが分かりやすくなりました.
#MAEで比較する
最後に,類似度を定量的に計算します.
類似度には平均絶対誤差(MAE)を使うことにします.
MAE = \frac{1}{N}\sum_{i=1}^{N}|x_{1i} - x_{2i}|
今回の場合,MAEは小さいほど似ている形のデータ系列といくことになります.MAEが0だと完全に一致していることになります.
MAEは以下で計算できます.
from sklearn.metrics import mean_absolute_error
MSE_dal_ual = mean_absolute_error(dal, ual)
MSE_ual_aapl = mean_absolute_error(ual, aapl)
MSE_aapl_dal = mean_absolute_error(aapl, dal)
MSE_dal_ual = 0.08767186335370042
MSE_ual_aapl = 0.5756471586956278
MSE_aapl_dal = 0.5380791440469056
UALとDALが似ていることが確認できました.
#むすび
今回はそのま比較しましたが,移動平均を取ってからMAEで比べたほうが傾向で比較できるかもしれません.その場合は,TA-Libを使うと簡単に移動平均が作れるのでおすすめです.
では後日,本記事の内容を使って「似た形の株価チャートをスクリーニング」したいと思います.