Quandlを利用して先物ロングオンリー系列を作成する

概要

・Quandlから各限月の先物価格を取得し、月末ローリングでのリターン系列を作成する
・Quandlのデフォルト期近系列そのものは実現可能なリターンではない

Quandlの先物ロール方法について

Quandlには期近の価格系列がすでにあるのですが、それを用いて分析する場合少し問題があります。

Continuous Contracts – Data from Quandl
https://www.quandl.com/c/futures/continuous

Quandl’s continuous contracts are created using the simplest possible roll algorithm: “end-to-end concatenation”. That is to say, CL1 is always the crude oil contract with the shortest time to expiry; CL2 is the second shortest contract, and so on. On expiry date, CL1 starts to point to the next future in line, and so on all the way down the strip. There’s no price adjustment, and the roll dates are simply the last trading dates.

上記サイトには期近(ここではCL1)のローリング方法について記載されています。満期日ローリングなのはまあ良いとして、満期日のCL1はnext futureを参照するとなっております。
つまり、満期日の価格と、満期日の1日前の価格は別の限月を参照しており、単純にCL1の系列のみからリターンを計算すると、実際には実現不可能なリターンを計算することになってしまいます。

今回作成したロール方法

今回は月末ローリングとします。つまり、月末になった時点で期近を売却し、期先を購入します。
ちなみに月末にした特に深い意味はなく、単純にコードが書きやすいと思ったからです。
月末(t)とした場合、t日のリターンは期近(t)と期近(t-1)から、t+1日のリターンは期先(t+1)と期先(t)から計算します。
こうすることで理屈上は全ての日のリターンは実現可能な値となります。

Pythonコード

結構な数のクエリを実行しますのでトークン取得が必要になるかと思います。
self.retに最終的なリターン系列が格納されるようになっています。

結果

適当に指数化してプロットしてみたのが以下

日経平均

150329_NK

SP500

150329_SP

EuroStoxx

150329_EuroStoxx

FTSE

150329_FTSE

全体(y軸は対数表示)

150329_all_log

こうしてみると1987年のブラックマンデーってかなりシャープに落ちていることが分かりますね笑
また日経平均はスタート地点が1990年とバブル崩壊直後だったこともあり未だに100を割っています。エクイティリスクプレミアムとは何だったのか。

ということで今後は株式先物を使っても分析ができそうですね。
また同じコードを流用することでコモディティなども分析できそうです。実際に個人が取引できるのかは知りませんが。。。

Google financeでティックデータを取得するときのメモ

概要

・しばらくティックデータで遊んでいたのだが、その際にハマった点についてのメモ

取得方法

URL

そもそも取得する方法ですが、
http://www.google.com/finance/getprices?p=1d&f=d,h,o,l,c,v&i=300&x=INDEXNIKKEI&q=NI225
このような形で取得することができます。上記URLは日経平均を取得します。
ちなみに、ティックデータのAPIに関するドキュメントはどうやら公式には無いらしく、詳しいことは分からないようです(知っている人が居たら教えて下さい!)

URLパラメータの説明

URLに付随するパラメータに関しては

q – ティッカー (日経平均ならNI225、ドル円ならUSDJPY)
x – ティッカーが取引されている取引所 (為替や特定の株価に関しては指定する必要なし)
i – 何秒刻みのデータか (86400で1日ごと。300で5分ごと)
p – 取得期間 (日ならdを、年ならYをつける)
f – 取得する系列(d: 時間、o: オープン、c: クローズ、l: ロー、h: ハイ、v: ボリューム。順不同)
df – ??
auto – ??
ei – ??
ts – タイムスタンプ(Unix)。指定しない場合、今日になる
(参考サイト2より抄訳)

取引所情報

株価を取得する場合、取引所コードをURLのパラメータxに指定する必要がありますが、それは

免責条項 – Google Finance
http://www.google.com/googlefinance/disclaimer/

から取得することができます。またはGoogle financeに直接行き、

Screen Shot 2015-03-28 at 2.47.06 PM

(INDEXNIKKEI:NI225)となっているコロンの前の文字列が取引所コードとなります。

その他ハマった点についてのメモ

ヘッダーについて

上記例で出したアドレスに行くと、上部数行(ティッカーにより異なる)がヘッダーとなっている。この中にはマーケットの取引時間やGMTからの時差などが記載されている。

  • MARKET_OPEN_MINUTE: 取引開始時間(分) 例えば2015年3月27日(金)のデータを取得した場合、起点は0時0分0秒なのでそこから540分ズラした時間が取引開始時間となり、午前9時となる。
  • MARKET_CLOSE_MINUTE: 取引終了時間(分) OPENと同様。日経平均の場合は15時となる。
  • INTERVAL: 観測期間(秒)。この場合は300秒(=5分)間隔のティックデータとなる
  • COLUMNS: 何の情報がどの順番で返されるか。この順番はURLパラメータの順番で指定できない模様。
  • DATA_SESSIONS: 前場後場が存在する場合、それぞれの寄り引けの時間が格納される。S&Pなど昼休みが存在しない場合は空白となる。
  • DATA: ??
  • TIMEZONE_OFFSET: 時差(分)。基本的にGoogle financeはGMT基準で時間を表示しているのでローカル時間に変更する場合はこの値を足す。

ティックデータの時間情報の計算方法

URLの中身を見るとわかると思いますが、時間の情報が見当たらない。なので、各ティックデータの観測時間を取得する場合は少し計算が必要となります。
例えば日経平均を取得すると、ヘッダーの下の行は

というような感じになっていると思います。一番左の行が時間を表しているのですが、これはUNIX時間となります。
最初の”a”を除外した時間を変換すると所望の時間が得られます。例えばPythonの場合

とすることで変換できます。3月27日0時5分(GMT)ですね。ここからローカル時間(東京時間)に変換するためにはTIMEZONE_OFFSETの値を足します。

これで東京時間となります。

また、S&Pの場合では
http://www.google.com/finance/getprices?p=1d&f=d,h,o,l,c,v&i=300&x=INDEXSP&q=INX
で取得できますが、ヘッダーとその下の1行目は

というような感じになっています。
なのでGMT基準での取引開始時間は

となります。またローカル時間(NY時間)は

となります。NY午前9時35分ですね。この時間をMARKET_OPEN_MINUTEで取得する場合は

というような感じになります。MARKET_OPEN_MINUTEは常にGMT0時からの時差を表しているわけですね。

観測時間は常に各時間間隔のCloseの時間となる

ちょっと何を言っているか分かりませんが、例えば5分間隔でデータを取得した場合、最初の行には東京時間での9時〜9時5分までのOHLCとなります。したがって、9時5分がその行の時間として、記載されているわけですね。
なので、上述した日経平均の例ように、UNIX時間が記載されている時間も9時5分となります。

各ティックデータ時間間隔はパラメータpに依存する

URLパラメータpでティック間隔(秒)を指定しましたが、これを使うことで各観測時間を計算します。

こういう感じですね。これはUNIX時間が記載されている行の、下の行のClose時間となります。

為替は土日もある。株価は営業日のみ

為替の情報は土日のデータも含まれます。(価格はほとんど動きませんが)
一方で株価は営業日のみのデータとなり、土日の情報は省かれるようです。
なのでURLを叩く日が土曜日だった場合、同じパラメータp=1dだとしても株式は金曜日のデータを返す一方、為替は土曜日のデータを返してきます。

前場引けの価格は正しいが、時間がずれている。後場引けの価格は取れない

*これは数日分のデータを見てみただけなので確証がありません。

例えば日経平均の場合ですが、前場引けは11時30分となります。一方で、Google financeにて取得したティックデータには11時30分のデータと11時35分のデータがなぜかあります。Dateが30の行と31の行(5分間隔データの場合)
詳しいことは良く分かりませんが、他の情報ベンダーの価格などと比較するとどうやら11時35分のデータが正しい前場引けの情報の模様。
ということで前場引けを正しく取得するためには1個次の行の情報を参照する必要がありそうです。

また、後場引けに関してですが、後場引けは15時となります。Google finaneから取得するデータにも15時の行(Dateが71の行)は存在しているのですが、これまた他のベンダーと比較するとどうやら違う模様。
ということで後場引け(というかその日の引け値)を取得する場合は他の方法を使用する必要があります。
一番手っ取り早い方法はURLを叩くときのパラメータiを86400として取得する方法。こうすると正しい終値が酒盗切るようです。

i=300の場合の3月27日の一番下の行

i=86400の場合の3月27日の一番下の行

実際に見てみると、i=300の場合、Closeが19300.25となりますが、i=86400の場合はCloseが19285.63となります。
この日の引け値は19285.63です。なのでi=86400が正しい値を取得しているようです。

他にも何かあったら追記していこうと思います。

参考サイト

Downloading Google Finance historical data with Python | Trading Systems and More
http://trading.cheno.net/downloading-google-finance-historical-data-with-python/

Downloading Google Intraday historical data with Python | Trading Systems and More
http://trading.cheno.net/downloading-google-intraday-historical-data-with-python/

Google’s Undocumented Finance API
http://www.networkerror.org/component/content/article/1-technical-wootness/44-googles-undocumented-finance-api.html

定常過程かどうかのチェック(ADF検定)

概要

・ADF検定の計算の確認。結局は単回帰係数が有意かどうかを検定している。ただし収束する分布が異なる。
・tserisパッケージのadf.test()関数の他に、CADFtestパッケージのCADFtest()関数の確認
・CADFtestの方がモデル(定数、トレンドを含むかどうか)を指定できたり、AIC基準でラグを設定できたりと柔軟。

tseriesパッケージのadf.test()

普通に使う分には全く問題ないと思うのですが、以下の2つが設定できない点で玉に瑕
1. モデルの指定(H0, H1の設定)
2. ラグの指定

以下がマニュアルの抜粋なのですが、adf.test関数は定数項とトレンド項を含んだ場合を想定しています。

The general regression equation which incorporates a constant and a linear trend is used and the t-statistic for a first order autoregressive coefficient equals one is computed. The number of lags used in the regression is k.

通常は両者とも含めた上で検定すれば良い場合が多いかと思いますが、何らかの想定や大人の事情により両者とも含めない場合で検定したい場合などには少し使いづらい。

また、検定に使うラグに関しても k = trunc((length(x)-1)^(1/3)) というような形で与えられています。
普通ならAIC基準などでラグを設定したいので、adf.testを使う場合にはAICを自分で計算しなければなりません。

CADFtestパッケージのCADFtest()

そういうかゆいところに手が届く関数がこちら。定数項とトレンド項を含むかどうかの設定、ラグを決める情報量基準もAICの他にBIC, HQC, MAICに対応しています(AIC, BIC以外は良く知りませんが)

簡単なテスト

ということでコードを丸投げ。
CADFtest関数においてモデルの指定はtypeにて設定できます。type=c(“trend”, “drift”, “none”)の3タイプから指定でき、デフォルトはtrend(つまりtseriesと同じ)
また、今回のコードでは触れていませんが、検定に含めるラグに関してはcriterion=c(“none”, “BIC”, “AIC”, “HQC”,”MAIC”)で決定させることが出来ます。

1つめの部分がシンプルなDF検定。
adf.test関数、CADFtest関数共に、ADF 値を出してきます。これが単純な自己回帰係数のt値と一致していることを確認。ただし収束する分布が異なるので有意かどうかを判定するラインが異なります。

ということで3つの方法でそれぞれ同じ値を計算していることが分かります。
後の結果に関しては省略。