Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

TensorFlow (ディープラーニング)で為替(FX)の予測をしてみる CNN編

More than 3 years have passed since last update.

前回までRNN(LSTM)や他の識別器で為替の予測を行ってきましたが、今回はCNNで予測をしてみたいと思います。

データの準備

前回まで終値の差分を学習データとしていましたが、今回は終値そのものを学習データにしてみます。
また、今回はUSDJPYの1時間足、2008年1月1日〜2017年3月10日を利用し、前半95%を学習、後半5%をテスト(バリデーション)としました。

CNNは画像認識で高い精度を発揮していますが、画像以外でも応用することは可能です。例えば終値が以下のようなデータがあったとします。

Unknown-2.png

これを画像に変換します。

Unknown-1.png

このように1次元の画像と見なすことができます。
色が複数チャネルあるように見えますが実際はグレースケールです。カラーマップを以下のようにして見えやすくしています。

plt.imshow(data.reshape(1, -1), vmin=0.0, vmax=1.0,
                       cmap='summer', interpolation='nearest')

ラベルは前回同様に次の期間で終値が上がるか下がるかの2クラスとします。


まずは学習データのストライドを1にしてやってみます。初めの10データを表示してみます。

Unknown.png

一つずつスライドしているのがわかりますね。これらを学習データとして使います。
ただし、このような学習データにはやや疑問があります。RNNのときは良いのですが、たった1画素スライドしただけでほぼ同じ特徴を持っているにも関わらず、クラスが上にも下にもなるからです。
(学習の過程で画像の左端ー未来に近い側ーの終値が強調される特徴抽出がされるかもしれませんが)

まずは取りあえずやってみましょう。

CNN

基本的な2層のCNNを使ってみます。今回はKerasがv2.0になったという事なのでKerasで書いてみます。
え?タイトルと違うって?backendはTensorFlowにしたのでセーフです!

CNN
input_shape = (24, 1)

model = Sequential()
model.add(Conv1D(32, 
                 3,
                 activation='relu',
                 padding='valid',
                 input_shape=input_shape))
model.add(MaxPooling1D(pool_size=2))
model.add(Conv1D(64,
                 3,
                 activation='relu',
                 padding='valid'))
model.add(MaxPooling1D(pool_size=2))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(250, activation='relu'))
model.add(Dropout(0.25))
model.add(Dense(num_classes, activation='softmax'))
model.compile(loss=keras.losses.categorical_crossentropy,
              optimizer='adam',
              metrics=['accuracy'])

結果

40エポックほど回した結果です。

Epoch 40/40
54545/54545 [==============================] - 4s - 
loss: 0.6905 - acc: 0.5275 - val_loss: 0.6921 - val_acc: 0.5200

正解率52%・・汎化性能は良いですが。
バックテストで利益の推移を見てみます。

Unknown-3.png

Net Profit            : ¥29710.00
Max Drawdown          : ¥-114250.00
Number Winning Trades : 1488
Number Losing Trades  : 1372
Percent Profitable    : 52.03%
Avg Win Trade         : ¥1071.855
Avg Los Trade         : ¥-1140.824
Largest Win Trade     : ¥9470.000
Largest Los Trade     : ¥-14790.000
Profit Factor         : 1.02

ドローダウンが酷いですが、12月からは上昇に転じています。ロットの調整でマシになりそうですがそれはまた別の話。機械学習の範囲で改善をしてみましょう。

学習データの見直し

やはり1ずつのストライドは気になるので、オーバーラップが丁度無くなる24に設定します。

Unknown-4.png

オーバーラップがなくなりました。これでほぼ同じ画像(値動き)なのにラベルが異なるケースがなくなったはずです。(もちろん過去に同様の値動きがあり、その時は上下逆に動いたという場合はあります)

見直し後の結果

先ほどと同様に40エポック回しました。

Epoch 40/40
2273/2273 [==============================] - 0s -
loss: 0.6528 - acc: 0.6067 - val_loss: 0.6869 - val_acc: 0.5583

正解率55.8%
正解率が上がりました。ただし学習データが1/24になってしまったのでまだ喜べません。オーバーフィッティングの兆候も見えてきました。

バックテストの結果を見てみます。

Unknown-5.png

Net Profit            : ¥38620.00
Max Drawdown          : ¥-11820.00
Number Winning Trades : 67
Number Losing Trades  : 53
Percent Profitable    : 55.83%
Avg Win Trade         : ¥1677.313
Avg Los Trade         : ¥-1391.698
Largest Win Trade     : ¥7410.000
Largest Los Trade     : ¥-9490.000
Profit Factor         : 1.52

PF 1.52
いいですね。ドローダウンも少なく全体的に先ほどより安定しています。
難点を言えば取引が1日に1回しか発生しないことと、最初の1ヶ月間の長いドローダウンでしょうか。

次回以降

次は転移学習か強化学習をやってみようかと思っています。思いつきで色々脱線するかもしれませんけどね。

hayatoy
Pythonista, Google Cloud Platform enthusiast, Cloud Solutions Architect
https://twitter.com/hayatoy82
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away