今日も窓辺でプログラム

外資系企業勤めのエンジニアが勉強した内容をまとめておくブログ

金融データのPythonでの扱い方

はじめに

Udacityというネット上のビデオを視聴する形で受講できる講義を提供しているサイトがあります。
Learn the Latest Tech Skills; Advance Your Career | Udacity

サイトや講義は英語なのですが、その中で Machine Learning for Tradingという講義を見つけました。
この講義は主に3つのパートに分かれています

  1. 金融データをPythonで操作する
  2. コンピュータを使った投資
  3. 取引に使う機械学習アルゴリズム

1つ目のパートを視聴したので、Pythonの基本的な知識の部分で知らなかった点を、実際のデータを操作する中で紹介しようと思います。
2つ目と3つ目はまた後日にでも。。

今回使用するデータとJupyter Notebook

Yahoo! Financeからダウンロードできる2016年の日経平均とS&P500のデータを使用しました。
下記URLのDownload dataというリンクからダウンロードできます。これにn225.csvとspy.csvというファイル名を付けて保存しました。
http://finance.yahoo.com/quote/%5EN225/history?period1=1451574000&period2=1483110000&interval=1d&filter=history&frequency=1d

また、今回はデータの操作・可視化を行うにあたってJupyter Notebookを使用していて、使用したNotebookはGitHubにあげてあります。
github.com

Jupyter Notebookの紹介記事も過去に書いているので、馴染みのない方はぜひご参照ください。
www.madopro.net

データの読み込み

Yahoo!からダウンロードできるCSVファイルは、最新の日付が上に、古い日付が下に来るような形式になっています。
この順番は通常時系列データを扱う場合とは逆順なので、このような方法が紹介されていました。

  1. 正しい向きのインデックスを持った空のDataFrameを用意する
  2. ダウンロードしたCSVからデータを読んで、空のDataFrameに結合(join)する

コードは以下のようになります。

# 2016年1年分のDataFrameを用意
start_date = "2016-01-01"
end_date = "2016-12-31"
df = pd.DataFrame(index=pd.date_range(start_date, end_date))

# 日経平均のデータを読み込んでjoinする
df = df.join(pd.read_csv("n225.csv", index_col="Date", parse_dates=True, usecols=["Date", "Adj Close"]))

# 終値がない日(市場が休みの日)を取り除く
df = df.dropna()
print(df.head())

#                Adj Close
# 2016-01-04  18450.980469
# 2016-01-05  18374.000000
# 2016-01-06  18191.320312
# 2016-01-07  17767.339844
# 2016-01-08  17697.960938

pd.read_csvの中で、index_colで日付の列をインデックスに指定し、かつparse_dates=Trueを渡すことで、日付を自動的にdatetime型に変換してくれます。
また、pd.read_csvではusecolsで日付と終値の2つの値のみを読み込むように指定しました。CSVには始値や高値安値などほかのデータも含まれていますが、今回は使いません。

移動平均の計算

pandasのrollingを使う

株のチャートではよく見られる移動平均などのrolling statisticsを計算する方法が紹介されていました。
pandasのrollingという関数を使うと、任意の長さのウインドウの移動統計量が簡単に計算できます。
例えば、25日移動平均は次のように計算・プロットできます。

# 25日移動平均の計算
rm = df.rolling(window=25).mean()

# プロット
ax = df.plot()
rm.columns = ["Rolling mean"]
rm.plot(ax=ax)

プロットされた画像はこんな感じです。
f:id:kanohk:20170103232030p:plain

もちろん平均だけではなく、最大値や最小値など様々な統計量が移動ウインドウに対して簡単に計算できます。

(手元の環境だと、rm.plot(ax=ax, label="Rolling mean")としてもラベルが変更されないので、仕方なく直前でデータフレームの列の名前を変更しています。なぜlabelを渡してもラベルが変わらないんでしょうか。。)

ボリンジャーバンドの計算

この機能を使うと、ボリンジャーバンドの計算も簡単にできてしまいます。
過去20日移動平均線と、移動平均線に標準偏差の2倍の値の幅をプロットしたら完成です。

# ボリンジャーバンドの計算
rm = df.rolling(window=20).mean()
rstd = df.rolling(window=20).std()
upper_band = rm + rstd * 2
lower_band = rm - rstd * 2

# プロット
ax = df.plot(color="blue")
rm.columns = ["Rolling mean"]
rm.plot(ax=ax, color="green")
upper_band.columns = ["Upper band"]
upper_band.plot(ax=ax, color="red")
lower_band.columns = ["Lower band"]
lower_band.plot(ax=ax, color="red")

f:id:kanohk:20170103234514p:plain

散布図と相関

散布図を描いたり、2つのデータの相関を見たいことがあります。
一例として、日経平均とS&P500の日次リターンの散布図を描いて、直線を当てはめてみます。

まずは日経平均とS&P5001年分のデータを読み込み、日次リターンを計算します。

start_date = "2016-01-01"
end_date = "2016-12-31"
df = pd.DataFrame(index=pd.date_range(start_date, end_date))
symbols = ["n225", "spy"]
for symbol in symbols:
    df = df.join(pd.read_csv("%s.csv" % symbol, index_col="Date", parse_dates=True, usecols=["Date", "Adj Close"]))
    df = df.rename(columns={"Adj Close": symbol})
df = df / df.shift() - 1
df = df.dropna()
print(df.head())
#                 n225       spy
# 2016-01-05 -0.004172  0.002012
# 2016-01-06 -0.009942 -0.013115
# 2016-01-07 -0.023307 -0.023700
# 2016-01-08 -0.003905 -0.010838
# 2016-01-13  0.028844 -0.024965

これで、2つのデータが入った1年分のデータフレームが用意できました。
これを散布図としてプロットするにはこのようにします。

df.plot(kind="scatter", x="n225", y="spy")

さらに、直線を当てはめるにはnumpyのpolyfitという関数をこのように使います。

beta, alpha = np.polyfit(df["n225"], df["spy"], 1)
plt.plot(df["n225"], beta * df["n225"] + alpha, '-', color='r')

すると、こんな形のグラフが得られます。この例の場合は2つのデータの相関がほぼないのであまり直線の当てはめは意味がないかもしれませんが。。

f:id:kanohk:20170104232330p:plain

ちなみに、この2つのデータの相関係数はこのように計算します。

print(df.corr())
#           n225       spy
# n225  1.000000  0.185885
# spy   0.185885  1.000000

講義はまだまだ続く…

講義の内容をかいつまんで紹介しましたが、1つ目の「金融をPythonで操作する」というパートですらまだ続きがあります。
ポートフォリオをPythonでどう扱うか、ポートフォリオの最適化などの内容が紹介されていますが、記事も長くなってきたので今回はここまでにします。



関連記事

読み込んだ株価データでローソク足チャートを描画する方法を記事にしました。
www.madopro.net

過去に日経平均の動きを予測しようとした記事です。
www.madopro.net

この記事が、このブログで初めてホットエントリーに掲載されたので、その様子を記事にしました!
www.madopro.net