{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"### This notebook uses GRU to predict NASDAQ price. It refers to the following code examples:\n\n[AR, ARIMA, LSTM](https://www.kaggle.com/bogdanbaraban/ar-arima-lstm)\n\n[LSTM model of StockData](https://www.kaggle.com/johanvandenheuvel/lstm-model-of-stockdata)\n\n[Kera - Advanced usage of recurrent neural networks](https://github.com/fchollet/deep-learning-with-python-notebooks/blob/master/first_edition/6.3-advanced-usage-of-recurrent-neural-networks.ipynb)\n","metadata":{}},{"cell_type":"code","source":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport matplotlib.pylab as plt\n\nfrom sklearn.preprocessing import MinMaxScaler\nfrom keras.models import Sequential\nfrom keras.layers import Dense\nfrom keras.layers import LSTM, GRU\nfrom keras.layers import Dropout","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-12-20T17:06:46.910350Z","iopub.execute_input":"2021-12-20T17:06:46.910685Z","iopub.status.idle":"2021-12-20T17:06:46.917983Z","shell.execute_reply.started":"2021-12-20T17:06:46.910644Z","shell.execute_reply":"2021-12-20T17:06:46.916857Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Install openpyxl for reading .xlsx file\n!pip install openpyxl","metadata":{"execution":{"iopub.status.busy":"2021-12-20T17:06:46.920024Z","iopub.execute_input":"2021-12-20T17:06:46.920533Z","iopub.status.idle":"2021-12-20T17:06:55.800408Z","shell.execute_reply.started":"2021-12-20T17:06:46.920487Z","shell.execute_reply":"2021-12-20T17:06:55.799404Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_file = '../input/110-1-ntut-ee-ai-hw3/taiex_2014-2021.xlsx'\ndf = pd.read_excel(data_file)\ndf.head()","metadata":{"execution":{"iopub.status.busy":"2021-12-20T17:06:55.802412Z","iopub.execute_input":"2021-12-20T17:06:55.802705Z","iopub.status.idle":"2021-12-20T17:06:56.399054Z","shell.execute_reply.started":"2021-12-20T17:06:55.802672Z","shell.execute_reply":"2021-12-20T17:06:56.398045Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data = pd.read_excel(data_file, converters= {'時間': pd.to_datetime})\nplt.figure(figsize=(16,8))\nplt.grid(True)\nplt.xlabel('Dates')\nplt.ylabel('Closing Prices')\nplt.plot(data['收盤價']);","metadata":{"execution":{"iopub.status.busy":"2021-12-20T17:06:56.400917Z","iopub.execute_input":"2021-12-20T17:06:56.401125Z","iopub.status.idle":"2021-12-20T17:06:57.388354Z","shell.execute_reply.started":"2021-12-20T17:06:56.401100Z","shell.execute_reply":"2021-12-20T17:06:57.387531Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Split train and test data\ntrain_start_idx = 0\ntrain_end_idx = -300\n\nprint('Training data range: ', df.iloc[train_start_idx]['時間'], ' - ', df.iloc[train_end_idx]['時間'])","metadata":{"execution":{"iopub.status.busy":"2021-12-20T17:06:57.389697Z","iopub.execute_input":"2021-12-20T17:06:57.389935Z","iopub.status.idle":"2021-12-20T17:06:57.396825Z","shell.execute_reply.started":"2021-12-20T17:06:57.389905Z","shell.execute_reply":"2021-12-20T17:06:57.395961Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_data = df[train_start_idx:train_end_idx].drop(columns=['時間']).to_numpy()\ntest_data = df[-train_end_idx:].drop(columns=['時間']).to_numpy()\nprint(df.iloc[train_start_idx])\nprint(\"\\n **** Convert stock data into numpy tensor ****\")\nprint(train_data[0])","metadata":{"execution":{"iopub.status.busy":"2021-12-20T17:06:57.398196Z","iopub.execute_input":"2021-12-20T17:06:57.398594Z","iopub.status.idle":"2021-12-20T17:06:57.414182Z","shell.execute_reply.started":"2021-12-20T17:06:57.398560Z","shell.execute_reply":"2021-12-20T17:06:57.413309Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Adapted from Keras Time Series Data Generator. Note that we add two options:\n# normalize: Use the beginning price of a sample price series to normalize data\n# target_index: The index of target value (label) in our tensor. Our target is Adjusted closed price (index: -2) \n\ndef generator(data, lookback, delay, min_index=0, max_index=None, shuffle=False, \n              batch_size=128, step=1, target_index=-2, normalize=True):\n    if max_index is None:\n        max_index = len(data) - delay - 1\n    i = min_index + lookback\n    while 1:\n        if shuffle:\n            rows = np.random.randint(min_index + lookback, max_index, size=batch_size)\n        else:\n            if i + batch_size >= max_index:\n                i = min_index + lookback\n            rows = np.arange(i, min(i + batch_size, max_index))\n            i += len(rows)\n        samples = np.zeros((len(rows), lookback // step, data.shape[-1]))\n        targets = np.zeros((len(rows),))\n        for j, row in enumerate(rows):\n            indices = range(rows[j] - lookback, rows[j], step)\n            if normalize:\n                ## Normalize data using first datium in the series\n                norm = data[rows[j] - lookback]\n                samples[j] = data[indices] / norm\n                targets[j] = data[rows[j] + delay][target_index] / norm[target_index]\n            else:\n                samples[j] = data[indices]\n                targets[j] = data[rows[j] + delay][target_index]\n        yield samples, targets","metadata":{"execution":{"iopub.status.busy":"2021-12-20T17:06:57.415569Z","iopub.execute_input":"2021-12-20T17:06:57.416156Z","iopub.status.idle":"2021-12-20T17:06:57.427999Z","shell.execute_reply.started":"2021-12-20T17:06:57.416115Z","shell.execute_reply":"2021-12-20T17:06:57.427319Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"lookback = 20 # Using last 20 trading days as input data\nstep = 1\ndelay = 2 # Prdict the price in 2 days\nbatch_size = 10 \ntarget_idx = 3 # The 5th column (收盤價) is our target prediction\nnum_val_data = 100 # Use 100 days as validate data \n\ntrain_gen = generator(train_data[0: ],\n                      lookback=lookback,\n                      delay=delay,\n                      max_index= len(train_data) - num_val_data - 1,\n                      step=step, \n                      normalize=True,\n                      target_index = target_idx,\n                      batch_size=batch_size)\n\nval_gen = generator(train_data,\n                      lookback=lookback,\n                      delay=delay,\n                      step=step, \n                      min_index= len(train_data) - num_val_data,\n                      normalize=True,\n                      target_index = target_idx,\n                      batch_size=batch_size)\n\nval_steps = (num_val_data - lookback) // batch_size","metadata":{"execution":{"iopub.status.busy":"2021-12-20T17:06:57.428971Z","iopub.execute_input":"2021-12-20T17:06:57.429520Z","iopub.status.idle":"2021-12-20T17:06:57.444012Z","shell.execute_reply.started":"2021-12-20T17:06:57.429483Z","shell.execute_reply":"2021-12-20T17:06:57.443417Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Take a look for our training samples\n\nfor samples, targets in train_gen:\n    print(samples)\n    print(targets)\n    break","metadata":{"execution":{"iopub.status.busy":"2021-12-20T17:06:57.446770Z","iopub.execute_input":"2021-12-20T17:06:57.447379Z","iopub.status.idle":"2021-12-20T17:06:57.473281Z","shell.execute_reply.started":"2021-12-20T17:06:57.447340Z","shell.execute_reply":"2021-12-20T17:06:57.472443Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from keras.models import Sequential\nfrom keras import layers\n\nmodel = Sequential()\nmodel.add(layers.GRU(16, input_shape=(None, train_data.shape[-1])))\nmodel.add(layers.Dense(1))\nmodel.compile(optimizer='RMSprop', loss='mae')\nhistory = model.fit_generator(train_gen, \n                            steps_per_epoch=500, epochs=20,\n                            validation_data=val_gen,\n                            validation_steps=val_steps)","metadata":{"execution":{"iopub.status.busy":"2021-12-20T17:06:57.474600Z","iopub.execute_input":"2021-12-20T17:06:57.475084Z","iopub.status.idle":"2021-12-20T17:09:21.199840Z","shell.execute_reply.started":"2021-12-20T17:06:57.475048Z","shell.execute_reply":"2021-12-20T17:09:21.198646Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"loss = history.history['loss']\nval_loss = history.history['val_loss']\n\nepochs = range(len(loss))\n\nplt.figure()\n\nplt.plot(epochs, loss, 'bo', label='Training loss')\nplt.plot(epochs, val_loss, 'b', label='Validation loss')\nplt.title('Training and validation loss')\nplt.legend()\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-12-20T17:09:21.204964Z","iopub.execute_input":"2021-12-20T17:09:21.205216Z","iopub.status.idle":"2021-12-20T17:09:21.812246Z","shell.execute_reply.started":"2021-12-20T17:09:21.205185Z","shell.execute_reply":"2021-12-20T17:09:21.811219Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_gen = generator(test_data,\n                      lookback=lookback,\n                      delay=delay,\n                      step=step, \n                      normalize=True,\n                      target_index = target_idx,\n                      batch_size=batch_size)","metadata":{"execution":{"iopub.status.busy":"2021-12-20T17:09:21.813672Z","iopub.execute_input":"2021-12-20T17:09:21.814032Z","iopub.status.idle":"2021-12-20T17:09:21.819985Z","shell.execute_reply.started":"2021-12-20T17:09:21.813998Z","shell.execute_reply":"2021-12-20T17:09:21.819050Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.evaluate_generator(test_gen, len(test_data))","metadata":{"execution":{"iopub.status.busy":"2021-12-20T17:09:21.821211Z","iopub.execute_input":"2021-12-20T17:09:21.821527Z","iopub.status.idle":"2021-12-20T17:09:30.060180Z","shell.execute_reply.started":"2021-12-20T17:09:21.821469Z","shell.execute_reply":"2021-12-20T17:09:30.059575Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Prediction price in 2 days\nprices = df.iloc[-lookback:].drop(columns=['時間']).to_numpy()\nx = prices / prices[0]\nprice_sample = np.expand_dims(x, axis=0)\npred = model.predict(price_sample)\n\npred_price = pred[0][0]*prices[0][target_idx]\n\nprint('The TAIEX price for ', str(delay) ,' trading days after ', df.iloc[-1]['時間'], ' is ' + str(pred_price))","metadata":{"execution":{"iopub.status.busy":"2021-12-20T17:09:30.061276Z","iopub.execute_input":"2021-12-20T17:09:30.061846Z","iopub.status.idle":"2021-12-20T17:09:30.496473Z","shell.execute_reply.started":"2021-12-20T17:09:30.061809Z","shell.execute_reply":"2021-12-20T17:09:30.495605Z"},"trusted":true},"execution_count":null,"outputs":[]}]}