ゆるふわめも

東京か京都にいます。

時系列データ解析のメモ+pythonで株価の取得

GWが始まる前に簡単に覚えておきたい.

※かきかけです

時系列データとは

  • 時系列: 決められた間隔にしたがって観測されるデータ列
  • 点過程: 適当なタイミングで生起するデータを観測したもの(観測した値と、観測した時間に意味があるデータ)
    • 例:カウント点過程:時間内にて生起した点の数の統計的性質を観測したもの

よく出る確率分布・密度関数

待ち行列を学習するときによく見たものが多い.

  • 正規分布
  • ポアソン分布
  • 二項分布

など.

ポアソン分布

単位時間あたりにあるお店に

{ \displaystyle
 \lambda = \frac{K}{T}
}

の数だけお客さんがくるとして,それぞれの客は互いに独立に店にくる時間を選ぶとすれば, t = (y, y+x] の時間内にくるお客さんがk人である確率は

f:id:misos:20170504013709p:plain

とできる. ここで T→∞, K→∞としていくケースを考えるとポアソン分布

f:id:misos:20170504013721p:plain

となる(平均 λx を持つポアソン分布).

goodness of fit test

データに上記のような確率分布を当てはめて, その当てはまり具合を検証する.

pythonにて株価を取得

pandas_datareaderのインストール

pip install pandas_datareader 
conda install pandas-datareader # anaconda 環境の場合はこっち

としてインストールされる.

この状態でpandas (0.19.2), pandas-datareader (0.3.0.post0)がインストールされていれば、以下のコードは動きます.

データの取得

必要最小限のもののみ. 株価以外の細かいデータの取得はドキュメントを参照してください.

ドキュメント: Remote Data Access — pandas-datareader 0.1 documentation

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from datetime import datetime
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from pandas_datareader import data

_from, _to = datetime(2012,1,1), datetime(2017,1,1)
stock = data.DataReader("F", 'yahoo', _from, _to)

print(stock)

とすれば

Open High    Low Close   Volume  Adj Close
Date                        
2012-01-03  11.00   11.25   10.99   11.13   45709900    8.993629
2012-01-04  11.15   11.53   11.07   11.30   79725200    9.130998
2012-01-05  11.33   11.63   11.24   11.59   67877500    9.365333
2012-01-06  11.74   11.80   11.52   11.71   59840700    9.462299
2012-01-09  11.83   11.95   11.70   11.80   53981500    9.535024
2012-01-10  12.00   12.05   11.63   11.80   121750600   9.535024
2012-01-11  11.74   12.18   11.65   12.07   63806000    9.753198
2012-01-12  12.16   12.18   11.89   12.14   48687700    9.809762
2012-01-13  12.01   12.08   11.84   12.04   46366700    9.728957
2012-01-17  12.20   12.26   11.96   12.02   44398400    9.712796

と取得できるはず. このデータを用いてデータ解析の練習をする.

データのプロット

_open, _close = stock['Open'], stock['Close']
plt.plot(_open, label="open")
plt.plot(_close, label="close")
plt.legend()

f:id:misos:20170504005246p:plain

対数収益率の計算

対数差分をとることで、実データの分散を小さくしてデータを捉えることができるようになります.

logdiff = np.log(_open[1:].values) - np.log(_open[:-1].values)
plt.plot(logdiff, label="log diff")
plt.legend()

f:id:misos:20170504010352p:plain

統計量の計算・分析

平均・分散・相関

平均、分散は省略. 他の会社(yahoo, google)との相関をプロットしてみてみます. データ取得のたびに何回も上のようなコードを書くのは面倒なので、関数を定義しています.

def _get_timeseries_data(company_name, column_name, target='F', 
                        start=datetime(2016,1,1), end=datetime(2017,1,1)):
    target_data = data.DataReader(target, company_name, start, end)
    return target_data[column_name]

yahoo = _get_timeseries_data('yahoo', 'Open')
google = _get_timeseries_data('google', 'Open')
plt.scatter(yahoo, google, marker='x')

f:id:misos:20170504011613p:plain

ヒストリカルボラティリティー

何かと思ったら標準偏差でした.

np.std(yahoo), np.std(google)

(0.662619218725916, 0.66224033569369867)

検定

shapiro-wilk検定

scipy.stats.shapiroに便利な関数が定義されていました. 正規分布への適合具合をテストします.

The Shapiro-Wilk test tests the null hypothesis that the data was drawn from a normal distribution.

from scipy import stats
stats.shapiro(yahoo)

Ljung-Box検定

PyPR Documentにて関数が定義されていたのでインストールして利用します. データに自己相関が含まれているかどうかを検証します.

pip install pypr

でインストールしたものはLjung-Boxがないためエラーになる…?

単位根検定・定常性検定

時系列データがランダムウォークにしたがっているかを検証する検定. 単位根検定での検定統計量は正規分布に従わないことに注意.

  • KPSS 検定
  • McCabe 検定
  • Dickey-Fuller 検定
  • Phillips-Perron 検定

モデル

AR(Auto Regressive)

MA(Moving Average)

直前の状態が次の状態に大きく影響する時系列データに対して有効なモデル.

ARMA(AutoRegressive Moving Average)

ARIMA(AutoRegressive Integrated Moving Average)

SARIMA(Seasonal AutoRegressive Integrated Moving Average)

Skew-GARCH(multivariate Skew-GARCH)

参考文献

経済・ファイナンスデータの計量時系列分析 (統計ライブラリー)

経済・ファイナンスデータの計量時系列分析 (統計ライブラリー)

matplotlibでの凡例(ラベル)の表示場所・形式を変更する

たまによく使うので. matplotlibでのグラフ・プロットの作成のさいのラベルの表示例.

データを生成

ダミーのデータを2000こ生成します.

#!/usr/bin/env python
# -*- coding: utf-8 -*-00
import matplotlib.pyplot as plt
import matplotlib.lines as mlines
import numpy as np
from sklearn.datasets import make_moons

data, label = make_moons(noise=0.2, n_samples=2000)
x0, y0 = data[label==0,0], data[label==0,1]
x1, y1 = data[label==1,0], data[label==1,1]
x2, y2 = -1*data[label==1,0], 2*data[label==1,1]

legend(凡例)の表示方法の指定

通常

自動で適切な場所に表示されます.

plt.title("moon")
plt.scatter(x0, y0, label="label-A")
plt.scatter(x1, y1, label="label-B")

plt.xlabel("X-LABEL")
plt.xlabel("Y-LABEL")
plt.legend()

f:id:misos:20170502150559p:plain

場所を指定(グラフ枠内)

lower right(右下)に指定. lowerupper, leftcenterright で場所を指定.

plt.title("moon")
plt.scatter(x0, y0, label="label-A")
plt.scatter(x1, y1, label="label-B")

plt.xlabel("X-LABEL")
plt.xlabel("Y-LABEL")
plt.legend(loc='lower right')

f:id:misos:20170502150812p:plain

凡例表示を複数列に分割する, 枠に影をつける, 横幅いっぱいにする

ncol=2 で凡例表示の中にいくつの列を作るかを決定します(この場合は2). shadow=True,で影をつけます.

plt.title("moon")
plt.scatter(x0, y0, label="label-A")
plt.scatter(x1, y1, label="label-B")
plt.scatter(x2, y2, label="label-C")

plt.xlabel("X-LABEL")
plt.xlabel("Y-LABEL")
plt.legend(loc='uppper right',
           bbox_to_anchor=(0., 1.02, 1., .102),
           borderaxespad=0.,
           ncol=2,
           shadow=True,
           mode="expand")

f:id:misos:20170502151224p:plain

グラフの枠外に表示する

bbox_to_anchorを調整して決定します.

plt.title("moon")
plt.scatter(x0, y0, label="label-A")
plt.scatter(x1, y1, label="label-B")
plt.scatter(x2, y2, label="label-C")

plt.xlabel("X-LABEL")
plt.xlabel("Y-LABEL")
plt.legend(loc='uppper right',
           bbox_to_anchor=(1.05, 0.5, 0.5, .100), 
           borderaxespad=0.,)

f:id:misos:20170502151555p:plain

凡例にタイトルをつける

titleで指定します.

plt.title("moon")
plt.scatter(x0, y0, label="label-A")
plt.scatter(x1, y1, label="label-B")
plt.scatter(x2, y2, label="label-C")

plt.xlabel("X-LABEL")
plt.xlabel("Y-LABEL")
plt.legend(loc='uppper right',
           bbox_to_anchor=(1.05, 0.5, 0.5, .100), 
           borderaxespad=0.,
           ncol=1,
           mode="expand",
           title="LABEL NAME")

f:id:misos:20170502151546p:plain

凡例を分割して別々に表示する

多少面倒ですが, ax = plt.gca().add_artist(legend_p1)の箇所で新しく凡例を表示するように用意をしています. handles=[p3]p3に対応するラベルを表示するように指定する箇所で、リスト形式で複数指定ができます.

plt.title("moon")
p1 = plt.scatter(x0, y0, label="label-A")
p2 = plt.scatter(x1, y1, label="label-B")
p3 = plt.scatter(x2, y2, label="label-C")

plt.xlabel("X-LABEL")
plt.xlabel("Y-LABEL")
legend_p1 = plt.legend(handles=[p1],
           loc=1,
           title="LABEL NAME")

ax = plt.gca().add_artist(legend_p1)
legend_p2 = plt.legend(handles=[p2],
           loc=2,
           title="LABEL NAME")

ax = plt.gca().add_artist(legend_p2)
legend_p3 = plt.legend(handles=[p3],
           loc=3,
           title="LABEL NAME")

f:id:misos:20170502151507p:plain

ラベル名を任意の文字列に付け替える

ラベルをつけるデータ([p1, p2, p3])と, それに対応するラベル名(["wa~i!", "sugo~i!", "nande?"])を渡すことで表示を変えます.

plt.title("moon")
p1 = plt.scatter(x0, y0, label="label-A")
p2 = plt.scatter(x1, y1, label="label-B")
p3 = plt.scatter(x2, y2, label="label-C")

plt.xlabel("X-LABEL")
plt.xlabel("Y-LABEL")
plt.legend([p1, p2, p3],
           ["wa~i!", "sugo~i!", "nande?"],
           loc=1, 
           title="LABEL NAME")

f:id:misos:20170502151812p:plain

凡例の大きさ, フォントサイズ, 行間のスペースを変える

prop={'size':12,}にて大きさを指定、数が大きいほど大きくなります. fontsize=20にてフォントサイズを指定します. labelspacing=1.25にて行間のスペースを変更します.

plt.figure(figsize=(15, 5))

plt.subplot(131)
plt.title("moon")
p1 = plt.scatter(x0, y0, label="label-A")
p2 = plt.scatter(x1, y1, label="label-B")
p3 = plt.scatter(x2, y2, label="label-C")

plt.xlabel("X-LABEL")
plt.xlabel("Y-LABEL")
plt.legend([p1, p2, p3],
           ["wa~i!", "sugo~i!", "nande?"],
           fontsize=20,
           loc=1, 
           title="LABEL NAME", 
           prop={'size':6})


plt.subplot(132)
plt.title("moon")
p1 = plt.scatter(x0, y0, label="label-A")
p2 = plt.scatter(x1, y1, label="label-B")
p3 = plt.scatter(x2, y2, label="label-C")

plt.xlabel("X-LABEL")
plt.xlabel("Y-LABEL")
plt.legend([p1, p2, p3],
           ["wa~i!", "sugo~i!", "nande?"],
           fontsize=20,
           loc=1, 
           title="LABEL NAME", 
           prop={'size':8,})

plt.subplot(133)
plt.title("moon")
p1 = plt.scatter(x0, y0, label="label-A")
p2 = plt.scatter(x1, y1, label="label-B")
p3 = plt.scatter(x2, y2, label="label-C")

plt.xlabel("X-LABEL")
plt.xlabel("Y-LABEL")
plt.legend([p1, p2, p3],
           ["wa~i!", "sugo~i!", "nande?"],
           fontsize=20,
           loc=1, 
           title="LABEL NAME", 
           labelspacing=1.25,
           prop={'size':12,})

f:id:misos:20170502152029p:plain

その他

ドキュメント

legend and legend_handler — Matplotlib 2.0.2 documentation

フォントの変更・日本語をラベル名に用いる

プロット例

Anacondaで作成した環境の名前を変更する

コマンド

conda create --n NEW_NAME --clone PREVIOUS_NAME
conda remove --n PREVIOUS_NAME --all

説明

ドキュメントになさそうだったので、

  1. 一旦クローンして全く同じ環境を新しい名前でコピーしてから

  2. 前の名前の環境を削除

という手順にて行う.

paper.hatenadiary.jp

Python djangoでGroup byを用いて要素ごとのレコード数をカウントしてテンプレートに渡す

使いそうになったので.

ModelNameがモデルの名前, attribute_nameがgroup byを行いたいカラムの名前です.

from django.db.models import Count
target_data = ModelName.objects.all()
groupby_data = target_data.values('attribute_name').annotate(total=Count('attribute_name')).order_by('total')

カウントを行ったあとの total 属性にレコード数が含まれています.

詳しくは以下のドキュメントにて.

QuerySet API reference | Django documentation | Django

エラー解決:Anaconda環境でauto-sklearnをインストール

エラー内容

python2.7, 3.5にて、OSはMac OS X.

auto-sklearnのドキュメントにしたがって Anaconda以下で指定の手順でauto-sklearnをインストールすると、 以下のエラーで止まってしまった。

ted_api.h:15:2: warning: "Using deprecated NumPy API, disable it by "          "#defining NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION" [-W#warnings]
    #warning "Using deprecated NumPy API, disable it by " \
     ^
    pyrfr/regression.cpp:496:10: fatal error: 'random' file not found
    #include <random>
             ^
    1 warning and 1 error generated.
    error: command 'gcc' failed with exit status 1
    
    ----------------------------------------
Command "/Users/ユーザー名/anaconda/envs/python27/bin/python -u -c "import setuptools, tokenize;__file__='/private/var/folders/yp/khbks_h91tlbdvqxnxyqtv5m0000gp/T/pip-build-g8wAgb/pyrfr/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /var/folders/yp/khbks_h91tlbdvqxnxyqtv5m0000gp/T/pip-jCTD7x-record/install-record.txt --single-version-externally-managed --compile" failed with error code 1 in /private/var/folders/yp/khbks_h91tlbdvqxnxyqtv5m0000gp/T/pip-build-g8wAgb/pyrfr/

インストール手順

python2.7にて以下の手順でインストール成功。

環境に入る

$ source activate python27env 

gccをインストール

conda install gcc

(必要なら)以下のライブラリをアンインストール

pip uninstall pyrfr
pip uninstall auto-sklearn

auto-sklearnのインストール

$ curl https://raw.githubusercontent.com/automl/auto-sklearn/master/requirements.txt | xargs -n 1 -L 1 pip install
$ pip install auto-sklearn

追記

参考文献

What is auto-sklearn? — AutoSklearn 0.2.0 documentation