バックテスト: 戦略の評価方法と陥りがちなミス

概要

・投資戦略の評価方法とその際の落とし穴になるべくハマらないようにする方法
・泣きながら頷きつつ読んだのでメモがてらご紹介
・資料はコチラ(http://www.cboe.com/rmc/2015/olivier-pdf-Backtesting-Full.pdf)
ちょくちょくCitiの宣伝が入りますが、それを割り引いても良い資料だと思います。

バックテストとは?

システムを用いた機械的な手法に基づく投資戦略を構築する場合、その戦略が果たしてワークするのかを評価する方法として、バックテストがあります。
バックテストとは、構築した戦略が仮に過去の時点から存在していたと仮定し、その過去の時点から仮に戦略に基づいて運用した場合にどの程度のパフォーマンスになるのかをシミュレーションする方法となります。

ただしP.6などに紹介されているように、これらのシミュレーションにおいてはトライアンドエラーを何回行なったかは表に出てきません。

Practitioners and academics test many strategies over the same historical dataset; however, their statistical tests of significance and their estimates of expected future Sharpe ratios do not account for this over-testing, thereby returning misleadingly positive results. As a consequence, “most of the empirical research in finance…is likely false.”

その結果として
“I’ve never seen a bad backtest.”
(結果の悪いバックテストなんて見たことがない)

なんて言われるわけですね。

バックテストの現実

バックテストは「過去ワークする戦略は今後もワークするだろう」という観念にもとづいて行なわれていると思います。
ただしその結果として、過去のデータに過剰にフィットするような戦略を構築してしまい(インサンプル)、実際に運用する(アウトサンプル)と結果が惨憺なものとなるというのも良くあるおっとこんな時間に客かな?

P.11にはその典型例が掲載されています。

この資料ではこのようなバックテストにまつわる10個の罠が掲載されています。この罠を認識することで、ミスを最小限に抑えることができるのではないのでしょうか、というのがお話の内容ですね。

落とし穴1. 期待値にのみ着目し、他の指標を無視する

これは要するに、平均だけじゃなくて分散や高次のモーメントもちゃんと見なさいということですね。

  • 分散
  • スキューネス
  • ドローダウン

なども見て評価しましょうとなりますな。年率平均1%コンスタントに稼げるとしても、ドローダウンが年率50%などとなる場合、それに投資しますかという話ですね。

またよく言われる

  • X月効果
  • X曜日効果

としてXの条件を満たした際のリターンが平均よりも高い(低い)という話も要注意と。

資料では9月効果に関してイチャモンをつけています。
P.18には全サンプルをプロットしているわけですが、ここから見て分かるように、9月の平均リターンが低いのは単に分布の妙だった可能性も排除できませんね。
ちゃんと分散(など)で標準化した指標(シャープレシオなど)で見ると、9月効果に対して懐疑的になれます。

対策

  • 分散、スキューネス、ドローダウンなど他の指標を見る

落とし穴4. 期間

少し飛ばして4つめ。適切なシミュレーション期間を選ぶ必要があるというお話。
P.30ではVXX(VIX先物)のショート戦略に関する例を挙げており、2012年以降のパフォーマンスは良いですが、それ以前のパフォーマンスはぱっとしません。当然ながら2012年以降のみの結果だけを鵜呑みにするのは危ないというわけですね。

対策

  • 様々なレジームを含む期間、最低でも20年でシミュレーションを行なう(!)
    例えば金融危機、低ボラティリティ局面など
  • 各レジームにおける戦略の振る舞いの違いを理解する

落とし穴6. オーバーフィッティング、データマイニング

パフォーマンスが上がるまで同じデータセットで何度もシミュレーションを行なうことでこの問題に着面します。その結果、過剰な数のパラメータを設定してしまったり、データマイニング的な投資ルールを設定してしまう可能性があります。

もし何らかのトリガーが「ボラティリティが2.34標準偏差より大きいなら」という条件だった場合、データマイニングが行なわれている可能性がある。

個人的に思うところとしては、こういうトリガーを何らかの値で設定するのは非常に危険だと思いますね。過去はそのパラメータでワークしたかと思いますが、将来そのトリガーの値がワークする保証はありません。

対策

  • パラメータに関してパフォーマンスの結果が頑健かどうかの確認
  • シミュレーション期間を伸ばす
  • クロスバリデーションを行なう

落とし穴7. Mark-to-marketパフォーマンス

Mark-to-marketパフォーマンスとは要するに時価評価した場合の損益でして、特にOTCのデリバティブを用いる場合に必要になりますね。上場物の場合には日々値洗いが行なわれるのでこの落とし穴にハマるということはあまりないと思いますが。

もう少し一般的には、ポジションの最終的な損益だけでなく、保有期間における日々の損益を確認せよということですな。落とし穴その1に通じるところもあるとは思いますが、ドローダウンなどを確認しましょうということですね。

対策

  • mark-to-marketパフォーマンスを確認する
  • ドローダウンを確認する

落とし穴10. 実行可能性を見落とす

オペレーション上の実行可能性や、マーケットインパクト(個人でやる場合にはそこまで問題にならないかもしれませんが)を考えましょうと。

対策

  • 十分な流動性があるかの確認
  • 執行コスト(orスリッページ)を考慮
  • その日の引けの値をシグナルに、その引けの値でのトレードを行なわない
  • その時点では手にはいらない季節調整後の値などを使用しない

個人的な見解ですが、特にネット上に転がっているバックテストを見るとオペレーション上の実行可能性を無視したものをよく見かけるのが事実です。シミュレーション上はたかがラグですが、経験的にはパフォーマンスに大きな影響を与えます(何回もやったことがある(ノ∀`)タハー)

またここには記載されていませんが、マクロ指標の速報値/改定値など、そのシミュレーション時点では得ることができるかどうかなどを確認する必要があるかと思います。

Appendix

Appendixには数学的な内容の補足が書かれています。
外れ値の簡単な補足方法や、実務で使われている予測方法(回帰、SVM、決定木、NN)が紹介されています。

参考

Backtesting: A Practitioner’s Guide to Assessing Strategies and Avoiding Pitfalls
http://www.cboe.com/rmc/2015/olivier-pdf-Backtesting-Full.pdf

ランダムフォレストを使用したコモディティ先物の投資戦略

概要

  • そんなにパフォーマンス良くないよ
  • モメンタム効果(など)を説明変数としたうえでランダムフォレストによりシグナルを発生
  • パフォーマンスの計測とロングオンリーとの比較

モメンタム効果とは

一言で言うと、「上がってる株は今後も上がる、下がってる株は今後も下がる」という傾向を表すものです。また、この効果は何も株に限定されるものではなく、様々な資産クラスにおいて報告されています(例えば参考[1])

モメンタム効果を表す代理変数としては、「過去X日のリターン」といったものが良く使われますね。
もしくは「今日の株価が過去X日の移動平均よりも高いか低いか」などでしょうか。

このモメンタム効果を駆使することによって俺様投資戦略を開発しメシウマヘブンを狙うのがこの記事の趣旨です。

なぜランダムフォレスト?

どうもランダムフォレスト最強と思ってるマンです。
というよりも別にランダムフォレストじゃなくても良いのですが、参考[2]サイト様に触発されたというのが本音です。このサイトではCARTモデルを用いることで買い・売りシグナルを発生させています。

CARTモデル?よろしいならばこっちはランダムフォレストだというわけです。

もう1つの理由としては、モメンタム効果がいつでも効くというわけではありません。上昇している株価が今後も常に上昇するというわけではなく、いつかは反転します。また、過去X日のリターンと言った変数を使う場合にXの値はいくつにするのが良いのかといった問題もあります。今までは過去20日がシグナルとしてよく機能していたけれど、今後は過去40日かもしれない、過去1年かもしれない、もしくはその両方かもしれないといって可能性が微レ存するわけです。

そういった構造をうまく捉えられないかというのもランダムフォレストを使うもう1つの理由になるのではないかと考えられます。

対象資産

今回はコモディティ先物を使います。
株式でも良いのですが、コモディティの方が長い期間のバックテストができますしね。

具体的には

  • C: Corn
  • W: Wheat
  • S: Soybeans
  • GC: Gold
  • SI: Silver
  • HG: Copper
  • CL: WTI Crude oil
  • NG: Natural gas

の8資産を使います。

戦略内容

上記8資産を用いて、週次で買い・売りシグナルを発生させ、それによるパフォーマンスを計測します。
全て引け値を用いて計算しているので、ポジションを取るのはシグナル計算日の翌日引けとなります。

教師データとして、
非説明変数は1週間リターンがプラスかマイナスか、を表すバイナリ
説明変数としては後述する指標を用います。

また、教師データはいわゆるExpanding windowを用います。
すなわち、t時点で得られる全てのデータを教師データとして用いるという方法です。
なので、時間が経つに連れて教師データは増加し、その分だけ計算時間も上昇していきます(重い)

ランダムフォレストにより、説明変数が与えられた元で、今後上昇する確率( \(Pr \left( u \right) \) )を得ることができますので、\(2 Pr \left( u \right) – 1\)の値を取るポジションとします。
こうすることで上昇する確率100%と判定されれば持っている資金の全額ロング、確率0%なら全額ショート、確率50%なら何もしない(ポジションがゼロ)、となります

なお、取引コストは考慮していません。

Sanity check

何はともあれ、まずは各説明変数と非説明変数の関係を見てみます。下図はCornを見たものです。

C

使っている指標は

  • ma: 過去リターン。moving averageとなっていますがただのリターン平均値です。命名ミス。
  • vol: 過去リターンの標準偏差
  • skew: 過去リターンのスキューネス
  • gk: 過去リターンのGarman-Klass volatility. 詳しくは参考[3]
  • curve: 第一限月と第二限月の価格差

となります。1w, 1m, 3m, 6m, 12mはそれぞれ1週間、1ヶ月、3ヶ月、6ヶ月、12ヶ月です。

まあ見て分かりますように、ほとんど傾向らしい傾向は見て取れませんね。
モメンタム効果が報告されるくらいだからmaに傾向が見られるかなとも思ったのですが微妙ですね…
株式ですとボラティリティや高いときリターンが低くなるといった効果も言われてますので入れてみたという感じです。

他の資産に関してもとくに目立った傾向は見られないので割愛。

まずは各資産にランダムフォレストを適用してみる

Return(青色)がロングオンリー、Strategy(緑色)がランダムフォレストです。
比較しやすいように事後的に年率ボラティリティを5%に調整しています。以下同様。
Retは年率リターン、Riskは年率ボラティリティ、Ret/Riskはリスク調整後リターンです。

C: Corn

2000年以降はまあまあですがそれまでは微妙。
C

W: Wheat

微妙。
W

S: Soybeans

惨敗。
S

GC: Gold

珍しくロングオンリーに勝利
GC

SI: Silver

何もしていない
SI

HG: Copper

ロングオンリーに負けてはいるがまあ他の資産に比べればマシか
HG

CL: WTI Crude oil

惨敗。というか直近の原油価格の下落を捉えていないとは何事か。
CL

NG: Natural gas

微妙…
NG

ポートフォリオを組んでみる

既に雲行きが怪しいですが、とりあえずこれらの資産でポートフォリオを組んだ場合にどうなるかも一応見てみます。
なお、各資産の配分比率はリスク(標準偏差)パリティとします。

Portfolio

というわけでドローダウンこそ均されるもののロングオンリーにさえ勝つことができないというシロモノに。
というか各資産をリスクパリティで持つだけでもそこそこパフォーマンスが良いんですね。まあリーマンショック以降はボラティリティも高く微妙ですが。

ちなみにロングオンリーと戦略間の相関は0.25なので、そこまで買いバイアスがかかっているというわけでもないようです。

感想

ランダムフォレストをチューニングするという手もありますが、何よりも説明変数と非説明変数の関係が弱すぎるというのがボトルネックになっている気がします。

またモメンタムという特性上、資産価格にモメンタムが存在しない間は高いパフォーマンスが期待できないのも今後考えるべき問題ですね。

そしてCrude oilのところにもありましたが、直近、原油価格が減少する傾向が続いているにも関わらずそれを戦略が捉えていないというのも問題かと。コーディングミスも含めて見直す必要がありそうですね…といったところで本日は以上m(__)m

参考

Time Series Momentum
http://openarchive.cbs.dk/bitstream/handle/10398/8862/time_series_momentum_lasse_heje.pdf?sequence=1

Using CART for Stock Market Forecasting « The R Trader
http://www.thertrader.com/2014/02/28/using-cart-for-stock-market-forecasting/

MEASURING HISTORICAL VOLATILITY
http://www.todaysgroep.nl/media/236846/measuring_historic_volatility.pdf

強化学習+為替トレード戦略(その2)

概要

・強化学習シリーズその2
・Epsilon-greedyのEpsilonに対する感度分析
→ とりあえずEpsilon=0.1でやろうと思うがQ値が収束していなさそう。。より早く収束させる方法が求められる
・学習させたQ値に対して汎化能力をテストできるようコードを追加
→ 学習期間と同じ期間に対してテストするも微妙な結果に

Epsilonに対する感度分析

相変わらずこのシミュレーション方法で合っているのかすら謎シリーズとも言いますが^^

・Epsilon = 0.5
Q値
赤マスはロングポジションが最適な状態、グレーはフラットポジション、青色はショートポジション。以下同様。
q_ep0.5

各エピソードの累積リターンのエルゴード平均(expanding window)
c_ep0.5

・Epsilon = 0.1
Q値
q_ep0.1

各エピソードの累積リターンのエルゴード平均(expanding window)
c_ep0.1

・Epsilon = 0.05
Q値
q_ep0.05

各エピソードの累積リターンのエルゴード平均(expanding window)
c_ep0.05

・Epsilon = 0.01
Q値
q_ep0.01

各エピソードの累積リターンのエルゴード平均(expanding window)
c_ep0.01

まあどれも累積リターンはなんとなく収束しているようなイメージですが、Q値がシミュレーションを回す度に変わるので、Q値がまだ収束していなさそうな雰囲気。ここは工夫が必要なんですかな。状態数が増えるとなおさらですし。

で、それぞれを比較してみると以下
ep_ret

ep_std

ep_ratio

上から、累積リターンの平均、標準偏差、平均/標準偏差を表しています。
リターンに関しては、探索の頻度(=Epsilon)を上げるほどある程度早く収束しているような気がしなくもない結果に。
ただし収束のレベルはEpsilonによってまちまちという感じ。
平均/標準偏差の比率でみると、0.1がもっとも高くなっておりまして、収束レベルが大きくかつそのばらつきもそれなりに小さい感じなんですかね。Epsilon=0.5とかにすると平均リターンも大きくなりますが、それのばらつきも大きくなってしまうということで比率に直すとそこまで良いというわけでもなく、ここはバランスなんですかな。

ということでEpsilon-Greedy以外のやり方もあるかとは思いますが、とりあえずEpsilon=0.1で今後は進めていこうと思います。

汎化能力のテスト

汎化能力と言いつつ、とりあえず学習期間と同様の期間にテストしてみます。
具体的にはモンテカルロを1000回まわしたあとに得られたQ値を元に、グリーティー方策で同じ期間を運用した場合の結果。

・2011年
testRet: 当該期間に買い持ちだった場合の結果
testMomentum: 当該期間に学習されたQ値を用いたグリーディー方策による結果
test2011

・2012年
test2012

・2013年
test2013

微妙ですな。

コード

loadData関数はFREDから対象ティッカー対象期間のデータを抽出するオレオレ関数です。
今回のシミュレーション対象もドル円(dexjpus)
複利型強化学習(参考文献2)なんてのもあるらしく、複利型でもシミュレーションできるようにしてますがまだうまく考察できてないのでペンディング。
self.isCompoundをTrueにすれば複利型になります。

メモ

やはりシミュレーションの度にQ値が変わるというのがやっかいでして、モンテカルロの回数を上げるというレベルを上げて物理で殴るという方法も考えられますが、もう少し見なおした方が良さそうですね。

また、状態に関してもとりあえず自分自身の長期と短期のシャープレシオを見ていますが、その背景の考えとしては、「今までワークしていた方法が今後もワークする」というまさに順張りのそれがありまして果たしてそれで十分かって話ですね。

今は20営業日と60営業日を見ていますが他のウィンドウで見ても良いですし、他の通貨ペアのパフォーマンスを見ても良いわけですしね。

参考文献

Amazon.co.jp: 強化学習: Richard S.Sutton, Andrew G.Barto, 三上 貞芳, 皆川 雅章: 本
http://www.amazon.co.jp/dp/4627826613

松井 藤五郎:複利型強化学習, 人工知能学会論文誌,
26(2):330–334 (2011)
https://www.jstage.jst.go.jp/article/tjsai/26/2/26_2_330/_pdf

Reinforcement Learning + FX Trading Strategy

This post is based on my previous article written in Japanese.(http://nekopuni.holy.jp/?p=1231)

Summary

– Applying reinforcement learning to trading strategy in fx market
– Estimating Q-value by Monte Carlo(MC) simulation
– Employing first-visit MC for simplicity
– Using short-term and long-term Sharpe-ratio of the strategy itself as a state variable, to test momentum strategy
– Using epsilon-greedy method to decide the action

First-visit MC

1. Calculate the state at day t(state = Sharpe ratio one day before day t)
2. Decide the action according to the state(long position, no position or short position)
3. Update rewards matrix based on the reward obtained at next time step t+1
4. Update Q matrix once t is equal to the last time step T
Loop above procedure until you feel happy

Python code

This time daily USDJPY from FRED is used for simulation.
So-called swap point and any transaction costs are not included in this code so far.

Results

Still this code takes huge computation time for me so the results(Q matrix) below is done by only 1000 iterations.

For long position(action = 0)
140824_mc1000_long_top

For flat position(action = 1)
140824_mc1000_flat_top

For short position(action = 2)
140824_mc1000_short_top

As seen in the figures above, the Q-value is lower if we have relatively extreme medium-term Sharpe ratio(lower than -1 and higher than 1)
For long position the Q-value is highest if short-term Sharpe is somewhere between 0.5 and 1.0 whilst between -0.5 and -1.0 is the highest area for short position.
Presumably this code could be seen as modest momentum strategy although I think this is depending on the sample period

140824_average_cumulative_return

Figure above is the average of cumulative return for each episode with expanding window.
This seems to be converging a certain level.idk..

Further task

– Out of sample
See if this reinforce learning has explanatory power

– other market data such as other currency pairs

– improvement of the computation time
this code is very far from online-learning

強化学習+為替トレード戦略

概要

・強化学習をトレード戦略に適用するとこんな感じになるのかなというテスト。我流なので何やってんのpgrという場合も生暖かい眼で何卒よろしくお願いします(ヘッジ文言^^)
・モンテカルロをぶん回すことでQ-valueを推定します。
・今回は簡単のために初回訪問モンテカルロ(逐一訪問はめんどいのお)
・モメンタム戦略を試すため、状態として過去の自分自身のシャープレシオ(1ヶ月と3ヶ月)を使用しています。
・行動決定にはEpsilon-Greedy法

初回訪問モンテカルロ

いかんせん強化学習の学習自体が何をどう考えて良いか門外漢のため五里霧中+Pythonも同じく門外漢のため五里霧中のため、自身の勉強方法も探索しっぱなしという^^;;
これであってんのですかねえ

詳しくは参考文献[1]のP.134を見てケロというかんじなのですが、
・現在での状態を確認(状態=過去のシャープレシオ)

・その状態における行動価値をもとに行動決定(Epsilon-Greedy法)
・今回はロングポジション・ショートポジション・フラットの3つの行動から選ぶ

・次の期に得られる報酬をもとに、Rewardsマトリックスを更新

・エピソード終端まで来たら各状態行動対のQ値を更新

というフローを何回も繰り返し、Q値を推定していきます。

コード

Pythonは行列計算させたほうが良いとばっちゃも言ってますように、速度が断然違いますな(1つ1つfor文をネストして各要素にアクセスしていたのは内緒)

今回はドル円日次レートを用いています。RLMomentumのインスタンスを作成するときにファイルパスを指定してます。
当然のことながら、所謂スワップポイントや、取引コストは考慮していません。

とりあえずの結果

まだ計算が遅い(私の環境だとモンテカルロ1回しで1秒強くらい)ので、モンテカルロの回数を増やすと大変なことに。。
モンテカルロ1000回で、それぞれの行動に対するQ値を見てみると以下

・ロングポジションに対して
140824_mc1000_long

・フラットポジションに対して
140824_mc1000_flat

・ショートポジションに対して
140824_mc1000_short

3Dグラフを書くとどこかの業界から殴りこみが来そうな気がするので(^^)簡易的にz軸上から見下ろした感じでグラフを書いてみると以下
・ロングポジションに対して
140824_mc1000_long_top

・フラットポジションに対して
140824_mc1000_flat_top

・ショートポジションに対して
140824_mc1000_short_top

結果を概観すると(シミュレーションが正しいとすると(ここ肝心ですよ!!))、3ヶ月のシャープレシオが-1以下、もしくは1以上のときのQ値が相対的に低いですな。
ロングポジションに対してだと、1ヶ月のシャープレシオがやや高い(0.5~1.0)のときに、最もQ値が高くなっています。
一方で、ショートポジションに対しては逆に1ヶ月のシャープレシオがやや低い(-0.5~-1.0)ときにショートすると最もQ値が大きくなると判断しているようですね。

やや控えめなトレンド戦略という感じでしょうか。
期間にも寄ると思いますが。

140824_average_cumulative_return

で、申し訳程度に各エピソードの累積リターンの平均をexpanding windowで取っていくとこんな感じで、まあ収束しているような気がしなくもないのですがどうなんでしょうか。。。

今後の課題

・アウトオブサンプル
上記コード中のコメントアウトを外すと、学習期間と同じ期間に対して当該戦略を適用した場合のパフォーマンスが見られます。
ただ肝心なのはアウトオブサンプルでどうなのよという話

・ドル円以外の為替

・計算速度の向上
計算が遅すぎてオンライン学習にはまだまだほど遠いですなあ

まだ確認すべきことは盛り沢山ですがとりあえず本日は以上(― ―)

参考文献

Amazon.co.jp: 強化学習: Richard S.Sutton, Andrew G.Barto, 三上 貞芳, 皆川 雅章: 本
http://www.amazon.co.jp/dp/4627826613

O’Reilly Japan – バンディットアルゴリズムによる最適化手法
http://www.oreilly.co.jp/books/9784873116273/

mplot3d tutorial — Matplotlib 1.3.1 documentation
http://matplotlib.org/mpl_toolkits/mplot3d/tutorial.html