Edited at

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

More than 1 year has 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ヶ月間の長いドローダウンでしょうか。


次回以降

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