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

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

- [第１回 TensorFlow (ディープラーニング)で為替(FX)の予測をしてみる](http://qiita.com/hayatoy/items/b9ddf4d6d8e026dc15e5)
- [第２回 ディープじゃない機械学習で為替(FX)の予測をしてみる](http://qiita.com/hayatoy/items/61042af42688464250f9)

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

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

![Unknown-2.png](https://qiita-image-store.s3.amazonaws.com/0/162369/af2c6d37-3e77-3b63-77d9-7d7c694d5f76.png)

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

![Unknown-1.png](https://qiita-image-store.s3.amazonaws.com/0/162369/40ebd749-c3b9-35f5-316c-4ded2575ced3.png)

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

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

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

---

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

![Unknown.png](https://qiita-image-store.s3.amazonaws.com/0/162369/f46fd778-5bb3-0144-112a-f0805e314291.png)

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

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

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

```py: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](https://qiita-image-store.s3.amazonaws.com/0/162369/a8722622-b02c-129f-32d8-287295b85a7b.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](https://qiita-image-store.s3.amazonaws.com/0/162369/bee93603-63dc-f84a-f6d3-4b2706717e8e.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](https://qiita-image-store.s3.amazonaws.com/0/162369/071f4f44-1238-de01-5528-9a8c844beb56.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日に１回しか発生しないことと、最初の１ヶ月間の長いドローダウンでしょうか。

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