ml-finance-python

python scripts for finance machine learning

git clone https://9o.is/git/ml-finance-python.git

04_cnn_with_time_series.ipynb

(34717B)


      1 {
      2  "cells": [
      3   {
      4    "cell_type": "markdown",
      5    "metadata": {},
      6    "source": [
      7     "# How to use CNN with time series data"
      8    ]
      9   },
     10   {
     11    "cell_type": "markdown",
     12    "metadata": {},
     13    "source": [
     14     "The regular measurements of time series result in a similar grid-like data structure as for the image data we have focused on so far. As a result, we can use CNN architectures for univariate and multivariate time series. In the latter case, we consider different time series as channels, similar to the different color signals.\n",
     15     "\n",
     16     "We will illustrate the time series use case with the univariate asset price forecast example we introduced in the last chapter. Recall that we create rolling monthly stock returns and use the 24 lagged returns alongside one-hot-encoded month information to predict whether the subsequent monthly return is positive or negative."
     17    ]
     18   },
     19   {
     20    "cell_type": "markdown",
     21    "metadata": {},
     22    "source": [
     23     "## Imports & Settings"
     24    ]
     25   },
     26   {
     27    "cell_type": "code",
     28    "execution_count": 1,
     29    "metadata": {},
     30    "outputs": [
     31     {
     32      "name": "stderr",
     33      "output_type": "stream",
     34      "text": [
     35       "Using TensorFlow backend.\n"
     36      ]
     37     }
     38    ],
     39    "source": [
     40     "%matplotlib inline\n",
     41     "import numpy as np\n",
     42     "import pandas as pd\n",
     43     "import matplotlib.pyplot as plt\n",
     44     "from sklearn.metrics import roc_auc_score\n",
     45     "import tensorflow as tf\n",
     46     "import keras\n",
     47     "from keras.utils import np_utils\n",
     48     "from keras.datasets import cifar10\n",
     49     "from keras.models import Sequential\n",
     50     "from keras.preprocessing.image import ImageDataGenerator\n",
     51     "from keras.layers import Dense, Dropout, Activation, Flatten, Conv1D, Conv2D, MaxPooling1D, MaxPooling2D\n",
     52     "from keras.callbacks import ModelCheckpoint, TensorBoard\n",
     53     "from keras.layers.normalization import BatchNormalization\n",
     54     "from keras import backend as K"
     55    ]
     56   },
     57   {
     58    "cell_type": "markdown",
     59    "metadata": {},
     60    "source": [
     61     "## Prepare Data"
     62    ]
     63   },
     64   {
     65    "cell_type": "code",
     66    "execution_count": 2,
     67    "metadata": {},
     68    "outputs": [],
     69    "source": [
     70     "data = pd.read_hdf('data.h5', 'returns')\n",
     71     "data = data.drop([c for c in data.columns if str(c).startswith('year')], axis=1)"
     72    ]
     73   },
     74   {
     75    "cell_type": "code",
     76    "execution_count": 3,
     77    "metadata": {},
     78    "outputs": [],
     79    "source": [
     80     "X_train = data[:'2016'].drop('label', axis=1)\n",
     81     "y_train = data[:'2016'].label\n",
     82     "X_test = data['2017'].drop('label', axis=1)\n",
     83     "y_test = data['2017'].label"
     84    ]
     85   },
     86   {
     87    "cell_type": "code",
     88    "execution_count": 4,
     89    "metadata": {},
     90    "outputs": [],
     91    "source": [
     92     "X_train = X_train.values.reshape(-1, X_train.shape[1], 1)\n",
     93     "X_test = X_test.values.reshape(-1, X_train.shape[1], 1)"
     94    ]
     95   },
     96   {
     97    "cell_type": "markdown",
     98    "metadata": {},
     99    "source": [
    100     "## Define Custom AUC Metric"
    101    ]
    102   },
    103   {
    104    "cell_type": "code",
    105    "execution_count": 5,
    106    "metadata": {},
    107    "outputs": [],
    108    "source": [
    109     "def auc_roc(y_true, y_pred):\n",
    110     "    # any tensorflow metric\n",
    111     "    value, update_op = tf.metrics.auc(y_true, y_pred)\n",
    112     "\n",
    113     "    # find all variables created for this metric\n",
    114     "    metric_vars = [i for i in tf.local_variables() if 'auc_roc' in i.name.split('/')[1]]\n",
    115     "\n",
    116     "    # Add metric variables to GLOBAL_VARIABLES collection.\n",
    117     "    # They will be initialized for new session.\n",
    118     "    for v in metric_vars:\n",
    119     "        tf.add_to_collection(tf.GraphKeys.GLOBAL_VARIABLES, v)\n",
    120     "\n",
    121     "    # force to update metric values\n",
    122     "    with tf.control_dependencies([update_op]):\n",
    123     "        value = tf.identity(value)\n",
    124     "        return value"
    125    ]
    126   },
    127   {
    128    "cell_type": "markdown",
    129    "metadata": {},
    130    "source": [
    131     "## Build ConvNet"
    132    ]
    133   },
    134   {
    135    "cell_type": "markdown",
    136    "metadata": {},
    137    "source": [
    138     "### Model Architecture"
    139    ]
    140   },
    141   {
    142    "cell_type": "markdown",
    143    "metadata": {},
    144    "source": [
    145     "We design a simple one-layer CNN that uses one-dimensional convolutions combined with max pooling to learn time series patterns:"
    146    ]
    147   },
    148   {
    149    "cell_type": "code",
    150    "execution_count": 6,
    151    "metadata": {},
    152    "outputs": [],
    153    "source": [
    154     "model = Sequential([\n",
    155     "    Conv1D(filters=32, kernel_size=3, activation='relu', input_shape=(X_train.shape[1], 1)),\n",
    156     "    MaxPooling1D(pool_size=2),       \n",
    157     "    Flatten(),\n",
    158     "    Dense(1, activation='relu'),\n",
    159     "    Activation('sigmoid')])"
    160    ]
    161   },
    162   {
    163    "cell_type": "markdown",
    164    "metadata": {},
    165    "source": [
    166     "The model has 673 trainable parameters:"
    167    ]
    168   },
    169   {
    170    "cell_type": "code",
    171    "execution_count": 7,
    172    "metadata": {},
    173    "outputs": [
    174     {
    175      "name": "stdout",
    176      "output_type": "stream",
    177      "text": [
    178       "_________________________________________________________________\n",
    179       "Layer (type)                 Output Shape              Param #   \n",
    180       "=================================================================\n",
    181       "conv1d_1 (Conv1D)            (None, 34, 32)            128       \n",
    182       "_________________________________________________________________\n",
    183       "max_pooling1d_1 (MaxPooling1 (None, 17, 32)            0         \n",
    184       "_________________________________________________________________\n",
    185       "flatten_1 (Flatten)          (None, 544)               0         \n",
    186       "_________________________________________________________________\n",
    187       "dense_1 (Dense)              (None, 1)                 545       \n",
    188       "_________________________________________________________________\n",
    189       "activation_1 (Activation)    (None, 1)                 0         \n",
    190       "=================================================================\n",
    191       "Total params: 673\n",
    192       "Trainable params: 673\n",
    193       "Non-trainable params: 0\n",
    194       "_________________________________________________________________\n"
    195      ]
    196     }
    197    ],
    198    "source": [
    199     "model.summary()"
    200    ]
    201   },
    202   {
    203    "cell_type": "markdown",
    204    "metadata": {},
    205    "source": [
    206     "We compile using our custom auc_roc metric developed in the last chapter:"
    207    ]
    208   },
    209   {
    210    "cell_type": "code",
    211    "execution_count": 8,
    212    "metadata": {},
    213    "outputs": [],
    214    "source": [
    215     "model.compile(loss='binary_crossentropy',\n",
    216     "              optimizer='Adam',\n",
    217     "              metrics=['binary_accuracy', auc_roc])"
    218    ]
    219   },
    220   {
    221    "cell_type": "markdown",
    222    "metadata": {},
    223    "source": [
    224     "We train on returns for the years 2010-16 for 20 epochs using the default batch size of 32. Each epoch takes around 13s on a single NVIDIA GTX 1080 GPU."
    225    ]
    226   },
    227   {
    228    "cell_type": "code",
    229    "execution_count": 9,
    230    "metadata": {
    231     "scrolled": false
    232    },
    233    "outputs": [
    234     {
    235      "name": "stdout",
    236      "output_type": "stream",
    237      "text": [
    238       "Train on 206587 samples, validate on 29868 samples\n",
    239       "Epoch 1/20\n",
    240       "206587/206587 [==============================] - 14s 66us/step - loss: 0.6727 - binary_accuracy: 0.5845 - auc_roc: 0.5991 - val_loss: 0.7233 - val_binary_accuracy: 0.5206 - val_auc_roc: 0.6033\n",
    241       "Epoch 2/20\n",
    242       "206587/206587 [==============================] - 14s 68us/step - loss: 0.6687 - binary_accuracy: 0.5935 - auc_roc: 0.6037 - val_loss: 0.7170 - val_binary_accuracy: 0.5205 - val_auc_roc: 0.6056\n",
    243       "Epoch 3/20\n",
    244       "206587/206587 [==============================] - 13s 65us/step - loss: 0.6670 - binary_accuracy: 0.5955 - auc_roc: 0.6067 - val_loss: 0.7242 - val_binary_accuracy: 0.5268 - val_auc_roc: 0.6076\n",
    245       "Epoch 4/20\n",
    246       "206587/206587 [==============================] - 13s 62us/step - loss: 0.6659 - binary_accuracy: 0.5960 - auc_roc: 0.6084 - val_loss: 0.7191 - val_binary_accuracy: 0.5438 - val_auc_roc: 0.6092\n",
    247       "Epoch 5/20\n",
    248       "206587/206587 [==============================] - 13s 63us/step - loss: 0.6652 - binary_accuracy: 0.5969 - auc_roc: 0.6097 - val_loss: 0.7147 - val_binary_accuracy: 0.5453 - val_auc_roc: 0.6106\n",
    249       "Epoch 6/20\n",
    250       "206587/206587 [==============================] - 13s 64us/step - loss: 0.6647 - binary_accuracy: 0.5970 - auc_roc: 0.6110 - val_loss: 0.7155 - val_binary_accuracy: 0.5618 - val_auc_roc: 0.6114\n",
    251       "Epoch 7/20\n",
    252       "206587/206587 [==============================] - 14s 67us/step - loss: 0.6643 - binary_accuracy: 0.5978 - auc_roc: 0.6120 - val_loss: 0.7109 - val_binary_accuracy: 0.5656 - val_auc_roc: 0.6124\n",
    253       "Epoch 8/20\n",
    254       "206587/206587 [==============================] - 14s 68us/step - loss: 0.6637 - binary_accuracy: 0.5988 - auc_roc: 0.6128 - val_loss: 0.7173 - val_binary_accuracy: 0.5605 - val_auc_roc: 0.6133\n",
    255       "Epoch 9/20\n",
    256       "206587/206587 [==============================] - 13s 63us/step - loss: 0.6634 - binary_accuracy: 0.5997 - auc_roc: 0.6136 - val_loss: 0.7121 - val_binary_accuracy: 0.5627 - val_auc_roc: 0.6140\n",
    257       "Epoch 10/20\n",
    258       "206587/206587 [==============================] - 14s 66us/step - loss: 0.6633 - binary_accuracy: 0.5995 - auc_roc: 0.6143 - val_loss: 0.7158 - val_binary_accuracy: 0.5652 - val_auc_roc: 0.6145\n",
    259       "Epoch 11/20\n",
    260       "206587/206587 [==============================] - 14s 70us/step - loss: 0.6631 - binary_accuracy: 0.5999 - auc_roc: 0.6148 - val_loss: 0.7131 - val_binary_accuracy: 0.5627 - val_auc_roc: 0.6151\n",
    261       "Epoch 12/20\n",
    262       "206587/206587 [==============================] - 15s 72us/step - loss: 0.6628 - binary_accuracy: 0.6005 - auc_roc: 0.6153 - val_loss: 0.7068 - val_binary_accuracy: 0.5784 - val_auc_roc: 0.6156\n",
    263       "Epoch 13/20\n",
    264       "206587/206587 [==============================] - 14s 65us/step - loss: 0.6627 - binary_accuracy: 0.6010 - auc_roc: 0.6159 - val_loss: 0.7234 - val_binary_accuracy: 0.5697 - val_auc_roc: 0.6160\n",
    265       "Epoch 14/20\n",
    266       "206587/206587 [==============================] - 14s 69us/step - loss: 0.6625 - binary_accuracy: 0.6003 - auc_roc: 0.6162 - val_loss: 0.7050 - val_binary_accuracy: 0.5830 - val_auc_roc: 0.6164\n",
    267       "Epoch 15/20\n",
    268       "206587/206587 [==============================] - 13s 65us/step - loss: 0.6624 - binary_accuracy: 0.6009 - auc_roc: 0.6166 - val_loss: 0.7068 - val_binary_accuracy: 0.5781 - val_auc_roc: 0.6169\n",
    269       "Epoch 16/20\n",
    270       "206587/206587 [==============================] - 14s 68us/step - loss: 0.6624 - binary_accuracy: 0.6003 - auc_roc: 0.6170 - val_loss: 0.7071 - val_binary_accuracy: 0.5728 - val_auc_roc: 0.6172\n",
    271       "Epoch 17/20\n",
    272       "206587/206587 [==============================] - 14s 66us/step - loss: 0.6622 - binary_accuracy: 0.6012 - auc_roc: 0.6173 - val_loss: 0.7074 - val_binary_accuracy: 0.5598 - val_auc_roc: 0.6174\n",
    273       "Epoch 18/20\n",
    274       "206587/206587 [==============================] - 13s 61us/step - loss: 0.6622 - binary_accuracy: 0.6006 - auc_roc: 0.6175 - val_loss: 0.7220 - val_binary_accuracy: 0.5649 - val_auc_roc: 0.6176\n",
    275       "Epoch 19/20\n",
    276       "206587/206587 [==============================] - 13s 62us/step - loss: 0.6620 - binary_accuracy: 0.6005 - auc_roc: 0.6176 - val_loss: 0.7049 - val_binary_accuracy: 0.5791 - val_auc_roc: 0.6177\n",
    277       "Epoch 20/20\n",
    278       "206587/206587 [==============================] - 13s 62us/step - loss: 0.6619 - binary_accuracy: 0.6014 - auc_roc: 0.6179 - val_loss: 0.7032 - val_binary_accuracy: 0.5828 - val_auc_roc: 0.6180\n"
    279      ]
    280     }
    281    ],
    282    "source": [
    283     "training = model.fit(X_train,\n",
    284     "                     y_train, \n",
    285     "                     epochs=20,\n",
    286     "                     batch_size=32, \n",
    287     "                     validation_data=(X_test, y_test),\n",
    288     "                     shuffle=True,\n",
    289     "                     verbose=1)"
    290    ]
    291   },
    292   {
    293    "cell_type": "code",
    294    "execution_count": 10,
    295    "metadata": {},
    296    "outputs": [
    297     {
    298      "name": "stdout",
    299      "output_type": "stream",
    300      "text": [
    301       "Accuracy: 58.28%\n"
    302      ]
    303     }
    304    ],
    305    "source": [
    306     "accuracy = model.evaluate(X_test, y_test, verbose=0)[1]\n",
    307     "print('Accuracy: {:.2%}'.format(accuracy))"
    308    ]
    309   },
    310   {
    311    "cell_type": "markdown",
    312    "metadata": {},
    313    "source": [
    314     "For 2017 returns, we find a test accuracy of 58.28% and test AUC of 0.5701. The network is still underfitting at this point because both training and validation AUC are still improving after 20 epochs, suggesting that longer training and potentially a higher-capacity network would improve results. You should try!"
    315    ]
    316   },
    317   {
    318    "cell_type": "code",
    319    "execution_count": 11,
    320    "metadata": {},
    321    "outputs": [
    322     {
    323      "data": {
    324       "text/plain": [
    325        "0.5709754730834962"
    326       ]
    327      },
    328      "execution_count": 11,
    329      "metadata": {},
    330      "output_type": "execute_result"
    331     }
    332    ],
    333    "source": [
    334     "y_score = model.predict(X_test)\n",
    335     "roc_auc_score(y_score=y_score, y_true=y_test)"
    336    ]
    337   },
    338   {
    339    "cell_type": "code",
    340    "execution_count": 13,
    341    "metadata": {},
    342    "outputs": [
    343     {
    344      "data": {
    345       "image/png": "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\n",
    346       "text/plain": [
    347        "<Figure size 432x288 with 1 Axes>"
    348       ]
    349      },
    350      "metadata": {
    351       "needs_background": "light"
    352      },
    353      "output_type": "display_data"
    354     }
    355    ],
    356    "source": [
    357     "pd.DataFrame(training.history)[['auc_roc', 'val_auc_roc']].plot();"
    358    ]
    359   },
    360   {
    361    "cell_type": "code",
    362    "execution_count": null,
    363    "metadata": {},
    364    "outputs": [],
    365    "source": []
    366   }
    367  ],
    368  "metadata": {
    369   "kernelspec": {
    370    "display_name": "Python 3",
    371    "language": "python",
    372    "name": "python3"
    373   },
    374   "language_info": {
    375    "codemirror_mode": {
    376     "name": "ipython",
    377     "version": 3
    378    },
    379    "file_extension": ".py",
    380    "mimetype": "text/x-python",
    381    "name": "python",
    382    "nbconvert_exporter": "python",
    383    "pygments_lexer": "ipython3",
    384    "version": "3.6.8"
    385   },
    386   "toc": {
    387    "base_numbering": 1,
    388    "nav_menu": {},
    389    "number_sections": true,
    390    "sideBar": true,
    391    "skip_h1_title": true,
    392    "title_cell": "Table of Contents",
    393    "title_sidebar": "Contents",
    394    "toc_cell": false,
    395    "toc_position": {},
    396    "toc_section_display": true,
    397    "toc_window_display": true
    398   }
    399  },
    400  "nbformat": 4,
    401  "nbformat_minor": 2
    402 }