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

  • 53
    いいね
  • 7
    コメント

前回まで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ヶ月間の長いドローダウンでしょうか。

次回以降

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