Dự Đoán Chứng Khoán Sử Dụng Tensorflow

Lời mở đầu

Ở bài viết này, mình sẽ xây dựng mô hình hơn giản để áp dụng vào tập dữ liệu giá chứng khoán. Mục tiêu của bài này là chúng ta sẽ dự đoán chỉ số S&P 500 dựa trên chỉ số của 500 mã chứng khoán. Các bạn có nhu cầu tìm hiểu thêm về chỉ số sp 500 có thể đọc thêm ở https://vi.wikipedia.org/wiki/S%26P_500. Đây là một ứng dụng nhỏ, không có ý nghĩa nhiều ở thực tế do khi phân tích chứng khoán, ta còn xét thêm rất nhiều yếu tố phụ nữa. Mô hình này thực chất chỉ là một trong những mô hình chơi chơi.

Dẫn nhập

Phân tích dữ liệu

Các bạn có thể download dữ liệu ở https://drive.google.com/open?id=1UTlj5Ced-yj6RBRVc6bBM6IWMjfQR3GR.

Đầu tiên, chúng ta sẽ dùng pandas để load mô hình lên:

1import pandas as pd
2
3# Import data
4data = pd.read_csv('data_stocks.csv')

Xem kích thước của dữ liệu:

1print(data.shape)
1(41266, 502)

Kết quả là ta có hơn 40 ngàn dòng và 502 cột. Thử show 10 row đầu tiên của dữ liệu lên xem như thế nào.

1print(data.head())
 1         DATE      SP500  NASDAQ.AAL  NASDAQ.AAPL  NASDAQ.ADBE  NASDAQ.ADI  \
 20  1491226200  2363.6101     42.3300     143.6800     129.6300      82.040
 31  1491226260  2364.1001     42.3600     143.7000     130.3200      82.080
 42  1491226320  2362.6799     42.3100     143.6901     130.2250      82.030
 53  1491226380  2364.3101     42.3700     143.6400     130.0729      82.000
 64  1491226440  2364.8501     42.5378     143.6600     129.8800      82.035
 7
 8   NASDAQ.ADP  NASDAQ.ADSK  NASDAQ.AKAM  NASDAQ.ALXN    ...     NYSE.WYN  \
 90    102.2300      85.2200       59.760       121.52    ...       84.370
101    102.1400      85.6500       59.840       121.48    ...       84.370
112    102.2125      85.5100       59.795       121.93    ...       84.585
123    102.1400      85.4872       59.620       121.44    ...       84.460
134    102.0600      85.7001       59.620       121.60    ...       84.470
14
15   NYSE.XEC  NYSE.XEL  NYSE.XL  NYSE.XOM  NYSE.XRX  NYSE.XYL  NYSE.YUM  \
160   119.035     44.40    39.88     82.03      7.36     50.22     63.86
171   119.035     44.11    39.88     82.03      7.38     50.22     63.74
182   119.260     44.09    39.98     82.02      7.36     50.12     63.75
193   119.260     44.25    39.99     82.02      7.35     50.16     63.88
204   119.610     44.11    39.96     82.03      7.36     50.20     63.91
21
22   NYSE.ZBH  NYSE.ZTS
230   122.000    53.350
241   121.770    53.350
252   121.700    53.365
263   121.700    53.380
274   121.695    53.240

Cột đầu tiên là ngày, sau đó là mã chứng khoán. Chúng ta có tổng cộng 500 mã chứng khoán và 1 chỉ số. Để ý cột Date, ta thấy giá trị đầu tiên là 1491226200, giá trị thứ 2 là 1491226260, giá trị thứ 3 là 1491226320, mỗi giá trị cách nhau 60. Chuyển đổi số 1491226200 sang dạng datetime thì ra giá trị Monday, April 3, 2017 1:30:00 PM giờ GMT, tương tự số 1491226260 ra Monday, April 3, 2017 1:31:00 PM giờ GMT. Ta có thể suy luận ra là giá trị giao dịch lưu theo từng phút một (khoảng interval là 60 giây), và dữ liệu chúng ta có bắt đầu vào 3 tháng 4 năm 2017.

Plot đồ thị của mã SP500 lên:

1import matplotlib.pyplot as plt
2
3plt.plot(data['SP500'])
4plt.show()

Hình ảnh đừng đồ thị của chỉ số sp 500

1Notes: Ở đây có một lưu ý nhỏ nhưng rất quan trọng. Đó là tại thời điểm phút thứ t lưu trữ giá trị sp500 của thời điểm phút thứ t+1. Ví dụ với chỉ số sp500, dòng đầu tiên ta thấy là 1491226200  2363.6101, nghĩa là giá thực tế của thời điểm 1491226260 là 2363.6101. Do bài toán của chúng ta là dữ đoán giá tương lại, nên tại thời điểm hiện tại ta sẽ dự đoán giá 1 phút sau sẽ bằng bao nhiêu. Và tập dữ liệu đã tự động dịch chuyển giá trị lên 1 phút cho chúng ta đỡ mất công làm. Còn giá của 500 cỗ phiếu còn lại vẫn là giá tại thời điểm t

Phân chia tập train và test.

Chúng ta sẽ chia dữ liệu thành 2 phần với 80% là train và 20% còn lại là test. Do tích chất của dữ liệu là time serial nên chúng ta không thể làm thay đổi thứ tự dữ liệu.

Chúng ta sẽ bỏ đi cột DATE đầu tiên, và sau đó chuyển dữ liệu về dạng numpy array để dễ dàng thực hiện các phép chuyển đổi.

 1data_ = data_raw.drop(['DATE'], 1)
 2
 3data = data_.values
 4# Training and test data
 5train_start = 0
 6train_end = int(np.floor(0.8*n))
 7test_start = train_end
 8test_end = n
 9data_train = data[ :train_end]
10data_test = data[train_end:]

Scale dữ liệu

Khi sử dụng ANN, chúng ta thông thường sẽ scale dữ liệu input về đoạn [-1,1]. Trong python, thư viện sklearn đã hỗ trợ cho chúng ta sẵn các hàm scale dữ liệu cần thiết.

 1# Scale data
 2from sklearn.preprocessing import MinMaxScaler
 3scaler = MinMaxScaler()
 4data_train = scaler.fit_transform(data_train)
 5data_test = scaler.transform(data_test)
 6# Build X and y
 7X_train = data_train[:, 1:]
 8y_train = data_train[:, 0]
 9X_test = data_test[:, 1:]
10y_test = data_test[:, 0]

Mình cần dự đoán giá trị của chỉ số sp 500, nên giá trị của sp500 sẽ là cái mình cần dự đoán, chính là cột đầu tiên, còn 500 cái còn lại là input của mình.

Xây dựng mô hình sử dụng keras

Ở đây mình sử dụng keras xây dựng mô hình ANN. Mô hình của mình xây dựng gồm

 1from keras.models import Sequential
 2from keras.layers.core import Dense, Dropout, Activation
 3from keras.callbacks import ModelCheckpoint
 4from keras.optimizers import SGD
 5
 6import os
 7os.environ["CUDA_DEVICE_ORDER"]="PCI_BUS_ID"
 8# The GPU id to use, usually either "0" or "1"
 9os.environ["CUDA_VISIBLE_DEVICES"]="0"
10# create model
11model = Sequential()
12model.add(Dense(2048, input_dim=input_dim,kernel_initializer='normal', activation='relu'))
13model.add(Dense(1024,kernel_initializer='normal', activation='relu'))
14model.add(Dense(512,kernel_initializer='normal', activation='relu'))
15model.add(Dense(256,kernel_initializer='normal', activation='relu'))
16model.add(Dense(128,kernel_initializer='normal', activation='relu'))
17model.add(Dense(1,kernel_initializer='normal'))
18
19
20
21model.compile(loss='mse', optimizer='rmsprop')
22checkpoint = ModelCheckpoint(filepath='my_model3.h5', verbose=1, save_best_only=True)
23model.fit(X_train, y_train, epochs=100, batch_size=256, verbose=1, callbacks=[checkpoint], validation_split=0.2)

Sau một thời gian chạy, mình cũng thu được model. Các bạn quan tâm có thể download model của mình huấn luyện được tại https://drive.google.com/open?id=1BLQZbcADfnLqzIHlkgpsqZBlhljBp1Eb . Tiến hành plot dữ liệu tập test lên xem kết quả như thế nào.

 1
 2yhat = model.predict(X_test)
 3
 4
 5x = np.arange(len(yhat))
 6
 7plt.plot(x, y_test)
 8plt.plot(x, yhat)
 9plt.legend(['real', 'test'], loc='upper right')
10plt.show()
11
12
13from sklearn.metrics import mean_squared_error
14
15print("mse: "+ str(mean_squared_error(y_test, yhat)))

hình chứng khoán

1mse: 0.0014582120695331884

Kết quả của mô hình tạm chấp nhận được, về hình dạng thì khá tương đồng với kết quả. Chúng ta có thể cải tiến model bằng cách nâng số lượng layter/ hidden node, hoặc thêm dropout. Hoặc có thể thay thế mô hình bằng RNN. Chúng ta sẽ đề cập đến mô hình RNN trong bài viết sau.

Cảm ơn các bạn đã theo dõi. Hẹn gặp bạn ở các bài viết tiếp theo.

Comments