2021年9月10日金曜日

似たような値動きを探す python

毎日Rといいながら、またpythonです。似たような値動きを探します。

参考にしたのは

https://saturday-in-the-park.netlify.app/TradingTools/09_RecognizeChartShape/

です。感謝です。



















 図は、2019-04-25 から 2021-09-09 の 6125岡本工の終値データ から作成したものです。青い太い線は直近30日間のデータです。青太線の最後が 2021-09-09 です。この日付は、凡例の最初の行に示されています。この青太線と同じような値動きをこのデータ内から探すというのがやろうとしていることです。
 凡例の2行目2021-01-20とあります。橙色の細線がその値動きで、2021-01-20に至る30日間の値動きが青太線に近いということです。
 値動きの近さは、相関係数で計ります。2行目r=0.908が相関係数です。この相関係数で近さを計るというのが素晴らしい着想だと思うのです。
 ふつうはそのあとの値動きが気になるので、探し当てた過去データについてはその後の10日間の値動きを表示しています。
 値動きが近いもの、すなわち相関係数が1に近い方から5日分を描いています。
結構いいところついているように思いますがどうでしょう。
 ソースは次の通りです。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

def cor(x,y):
  return np.corrcoef(x,y)[0,1]

def similar(df,term=30,after=10,n=5,figsize=(10,10)):
  x=df.reset_index(drop=True)
  v=[(cor(x.iloc[i:i+term].C, x.iloc[-term:].C), i)\
     for i in range(len(x)-term+1-after)]
  v.sort(reverse=True)
  fig,ax=plt.subplots(figsize=figsize)
  ax.plot(x.iloc[-term:].reset_index().C/x.iloc[-1].C,linewidth=3\
          ,label=x.iloc[-1].d)
  for c,i in v[:n]:
    ax.plot(x.iloc[i:i+term+after].reset_index().C/x.iloc[i+term-1].C\
            ,linewidth=1\
            ,label=f"{x.loc[i+term+1].d} r={c:.3f}")
  plt.grid()
  ax.legend()
  return fig,ax

similar(x)


 なお、xはデータフレームで日付を持つd(文字列)と、終値を持つC(数値)が必要です。今回使用したものは次のようなもので、約4年半のデータです。私は株探の時系列データを利用しています。

               d       C
2019-04-25  3035.0
2019-04-26  2965.0
2019-05-07  2890.0
2019-05-08  2987.0
2019-05-09  2868.0
2019-05-10  3175.0
・・・・
2021-09-06  6430.0
2021-09-07  6480.0
2021-09-08  6840.0
2021-09-09  6820.0

 一応プログラムの説明をしてみます。
 相関係数はnumpyのものを使いましたが、そのままでは使いにくいので関数にしました。関数corです。
 similarが主眼の関数です。
 reset_indexが何回か出てきますが、グラフを縦にそろえるため、indexが0からになるように振りなおしています。
 vは1日ずつずらして相関係数をとった結果ですが、相関係数といつからか(i)が必要なので、タプルにして保存しました。この後相関係数でソートするので相関係数を先にしてあります。内包表記です。
 plotのところでは、基準日の値が同じになるように、各データを基準日の値で割っています。これによって、基準日にはすべてのデータが同じ点を通ります。
 以上です。