Forecasting Multiple Time-Series Using Neural Network | by Sarit Maitra | Towards Data Science

https://sarit-maitra.medium.com/membership
Stock prediction is a difficult task because the data generated is enormous and is highly non-linear. Modeling such dynamical data require effective modeling technique which can analyze the hidden patterns and underlying dynamics. Neural network which is deep learning algorithms are capable of identifying and exploiting the interactions and patterns existing in a data through a self learning process.
We shall focus on a simple prediction model using long-short term memory architecture involving multiple time-series. We shall keep the whole exercise a simple process for illustration purpose and better understanding.
Let us consider four different series S&P 500 (^GSPC), Dow Jones Industrial Average (^DJI), NASDAQ Composite (^IXIC) and Russell 2000 (^RUT) which is Chicago options. Our data set if from 1990 to till date. The data retrieved from yahoo finance and formatted into a Pandas DataFrame object.
stock = ['^RUT', '^GSPC', '^DJI', '^IXIC' ]start = pd.to_datetime('1990-01-03')df = web.DataReader(stock, data_source = 'yahoo', start = start )print(df.head())
Let us fit all the closing prices of the series in a neural network architecture and shall predict one series from there.
X = data.copy()X = X.drop(columns = [‘Date’])print(X.shape)print(X.tail())
If we see the correlation analysis, we will know as why these 4 series are chosen.
The time series was split into a training set (80%) and a test set (20%) as shown below.
split_ratio = 0.2X = X.values # Convert to NumPy arraysplit = int(len(X) * (1-split_ratio))train_set = X[: split]test_set = X[split:]print(train_set.shape, test_set.shape)
Let us format the in such a way that, supervised learning can be applied for ML model. Here, both the training set and test set will undergo the same transformation. We will achieve the objective with the below function.
def supvervisedSeries(data, n, h):  x, y = list (), list ()  for i in range (len(data)-n-h+1):    x.append(data[i:(i+n)])    y.append(data[i+h+n-1])  return np.array(x), np.array(y)h = 1n = 4trainX, trainY = supvervisedSeries(training_set, n, h)testX, testY = supvervisedSeries(test_set, n, h)print("trainX: ", trainX.shape)print("trainY: ", trainY.shape)print("testX: ", testX.shape)print("testY: ", testY.shape)
h = time horizon & n = number of features; these parameters are chosen prior to transformation.
Now, trainY and testY must be modified as per required feature prediction because by default it contains all 4 features.
testY = np.reshape(testY[:, 0], (testY [:, 0].shape[0], 1))trainY = np.reshape(trainY[:, 0], (trainY[:, 0].shape[0], 1))print(“trainY: “, trainY.shape)print(“testY: “, testY.shape)
Here, we have selected index[0] which is ^RUT daily Adj Close price.
ML model require the data to lie within the range (0, 1). We have used MinMaxScaler which rescales the data set such that all feature values are in the range [0, 1]. It normally preserve the shape of the data set.
scalers = {}for i in range (trainX.shape[2]):  scalers[i] = MinMaxScaler()  trainX[:, :, i] = scalers[i].fit_transform(trainX[:, :, i])for i in range(testX.shape[2]):  testX[:, :, i] = scalers[i].transform(testX[:, :, i])# The target values are 2D arrays, which is easy to scalescalerY = MinMaxScaler()trainY = scalerY.fit_transform(trainY)testY = scalerY.transform(testY)
In below, only 100 neurons in each layer was used to deal with our small data set. Also, dropout as a regularization technique was used to reduce overfitting. The class Dense represents a fully connected layer.
# Flatten input (to support multivariate input)n_input = trainX.shape[1] * trainX.shape[2]trainX = trainX.reshape((trainX.shape[0], n_input))n_input = testX.shape[1] * testX.shape[2]testX = testX.reshape((testX.shape[0], n_input))# Create multilayered FFNN modelmodel = Sequential()model.add(Dense(100, activation='relu', input_dim=trainX.shape[1]))model.add(Dropout(0.2))model.add(Dense(100, activation='relu'))model.add(Dropout(0.2))model.add(Dense(100, activation='relu'))model.add(Dense(trainY.shape[1]))model.compile(loss='mean_squared_error', optimizer='adam')model.summary()# Fit modelhistory = model.fit(trainX, trainY, epochs =60, verbose =1)# Predict the test setpredictions = model.predict(testX)
We have to descale the data to bring back to original values using the same scaler that was originally used to scale the data.
# Descalepredictions = scalerY.inverse_transform(predictions)testY = scalerY.inverse_transform(testY)# Mean absolute errormae = mean_absolute_error(testY, predictions)print("Test MAE: %.6f" % mae)
plt.figure(figsize=(15,6))plt.plot(predictions, label="Test set predictions" )plt.plot(testY, label="Real data")plt.legend()plt.ylabel('Price Index')plt.xlabel('time step' )plt.title ("Russell 2000 Adj close Price prediction- with MAE {:10.4f}".format(mae))plt.show()
Here, it can be seen that out network architecture is able to pick-up the hidden trend in the data; similarly, other series can also be predicted selecting the right scale for chosen the series.
We can see that, deep neural network architecture is capable of capturing hidden dynamics and are able to make predictions. To keep it simple, we have just fitted a simple LSTM network and not optimized any parameter of our network. in order to built a robust network we have to work on the right parameters such as number of epochs, batch size, number of neurons, number of hidden layers etc.
Connect me here.