股票市场的预测是金融领域中的一个重要研究方向,尤其是如何通过历史数据预测未来股价。这篇博客将带你走进如何通过多种方法,如CEEMDAN(Complete Ensemble Empirical Mode Decomposition with Adaptive Noise)分解技术与机器学习模型(如SVM、XGBoost、LSTM等)结合,来实现股票价格预测。我们将使用苹果公司(AAPL)股票的历史数据进行详细分析,并逐步展示如何通过不同的技术和模型对股票市场进行预测。
1. 数据预处理与模态分解
股票市场数据通常呈现出非常复杂的非线性和非平稳性特征。为了更好地进行预测,我们首先需要对数据进行适当的处理,去除噪声并提取更有用的信息。
部分数据如下所示:
1.1 数据读取与清洗
我们从苹果公司(AAPL)股票的历史数据入手,加载CSV文件,并去除缺失值。然后,我们将数据中的“Date”列删除,保留价格信息。
df_apple = pd.read_csv("AAPL.csv")
df_apple = df_apple.dropna()
del df_apple["Date"]
df_apple.head()
1.2 数据统计分析
对数据进行初步的统计分析,计算最大值、最小值、平均值、标准差等基本统计量,并进行偏度、峰度、JB检验等高级统计检验,以了解数据的分布特征。
def num_jy(df111):print("最大值", max(df111))print("最小值", min(df111))print("平均值", np.mean(df111))print("标准差:", np.std(df111))print("偏度:", pd.Series(df111).skew())print("峰度:", pd.Series(df111).kurt())# 计算JB检验量skew = pd.Series(df111).skew()krut = stats.kurtosis(df111) + 3JB = len(df111) * (skew ** 2 / 6 + (krut - 3) ** 2 / 24)print("JB检验:", JB)p_value = 1 - stats.chi2.cdf(JB, df=2)print('p_value:', p_value)
num_jy(df_apple["Close"])
1.3 CEEMDAN分解
为了从原始股价数据中提取潜在的模式,我们使用CEEMDAN(Complete Ensemble Empirical Mode Decomposition with Adaptive Noise)技术对数据进行模态分解。这一技术可以将复杂的时间序列分解为多个本征模态函数(IMFs),有助于去除数据中的噪声并提取出有效的信号。
ceemdan = CEEMDAN()
ceemdan.ceemdan(df_apple["Close"].to_numpy())
imfs, res = ceemdan.get_imfs_and_residue()
1.4 分解结果可视化
通过可视化分解后的IMFs(本征模态函数)和残差,可以直观地了解股价的不同时间尺度上的变化趋势。
plt.figure(figsize=(10,8))
plt.subplot(imfs.shape[0] + 2, 1, 1)
plt.plot(df_apple["Close"], 'r')
plt.ylabel("Original", rotation=60, fontsize=10)
for i in range(imfs.shape[0]):plt.subplot(imfs.shape[0] + 2, 1, i + 2)plt.plot(imfs[i], 'g')plt.ylabel(f"imf{i+1}", rotation=60, fontsize=10)
plt.subplot(imfs.shape[0] + 2, 1, imfs.shape[0] + 2)
plt.plot(res, 'g')
plt.ylabel("res", rotation=60, fontsize=10)
plt.show()
2. 特征选择与数据集划分
在对数据进行模态分解后,我们选择有意义的特征(如IMFs和残差),并将其作为输入特征来训练我们的模型。同时,划分数据集为训练集和测试集,通常选择80%的数据用于训练,剩余20%的数据用于测试。
def data_make(df):arr1 = ['imf'+str(i+1) for i in range(imfs.shape[0])] + ['res']arr2 = 'target'data_set_train1 = df[:int(df.shape[0] * 0.8)]data_set_test1 = df[int(df.shape[0] * 0.8):]train_X = data_set_train1[arr1]train_y = data_set_train1[arr2].to_numpy()test_X = data_set_test1[arr1]test_y = data_set_test1[arr2].to_numpy()return train_X, train_y, test_X, test_y
3. 模型构建与训练
3.1 支持向量机(SVM)
支持向量机(SVM)是一种常用的回归与分类算法,适用于非线性问题。我们首先使用标准的SVM模型进行训练,并用交叉验证评估其性能。
model = svm.LinearSVR()
model.fit(train1_X_apple, train1_y_apple)
y_pred_apple_ceemdan_svm = model.predict(test1_X_apple)
3.2 贝叶斯优化(Bayesian Optimization)
为了进一步提高模型的性能,我们使用贝叶斯优化技术来调整SVM的超参数。贝叶斯优化是一种全局优化算法,特别适合于调参问题。
def SVM_mse_cv(params):random_state = 10cv = 5params = {'epsilon': params['epsilon'],'C': int(params['C']),'intercept_scaling': params['intercept_scaling']}model = svm.LinearSVR(random_state=random_state, **params)score = -cross_val_score(model, train1_X_apple, train1_y_apple, cv=cv, scoring='neg_mean_squared_error',n_jobs=1).mean()return {'loss': score, 'status': 'ok'}def BO_SVM_pri(train_X, train_y, test_X):random_state = 10space = {'epsilon': hp.loguniform('epsilon', -2, 1),'C': hp.quniform('C', 1, 300, 1),'intercept_scaling': hp.loguniform('intercept_scaling', -2, 0)}trials = Trials()print("==========================贝叶斯参数优化==============================")best = fmin(fn=SVM_mse_cv,space=space,algo=tpe.suggest,max_evals=200,trials=trials)if best is None:raise ValueError("贝叶斯优化未能找到有效解")model = svm.LinearSVR(random_state=random_state, epsilon=best['epsilon'], C=int(best['C']), intercept_scaling=best['intercept_scaling'])model.fit(train_X, train_y)y_pred = model.predict(test_X)return y_pred
3.3 XGBoost与LightGBM
XGBoost和LightGBM是目前应用广泛的树模型,常用于回归与分类任务。它们通过提升树的性能,在许多竞赛中表现出色。我们使用Optuna进行超参数优化,并使用训练好的模型进行预测。
def objective(trial):params = {'objective': 'reg:squarederror','learning_rate': trial.suggest_loguniform('learning_rate', 1e-3, 1),'max_depth': trial.suggest_int('max_depth', 3, 15),'n_estimators': trial.suggest_int('n_estimators', 50, 300),'subsample': trial.suggest_float('subsample', 0.5, 1.0),'colsample_bytree': trial.suggest_float('colsample_bytree', 0.5, 1.0),'reg_alpha': trial.suggest_float('reg_alpha', 0, 10),'reg_lambda': trial.suggest_float('reg_lambda', 0, 10),}model = XGBRegressor(**params)model.fit(train2_X_apple, train2_y_apple)y_pred = model.predict(test2_X_apple)mse = mean_squared_error(test2_y_apple, y_pred)return mse
3.4 LSTM与GRU
长短时记忆(LSTM)和门控循环单元(GRU)是两种常用的循环神经网络(RNN)结构,适用于时间序列数据。通过这些网络结构,可以捕捉股价的长期依赖关系,提高预测准确性。
def LSTM_model(x_train, y_train, x_test, epochs, batch_size):model = Sequential()model.add(LSTM(units=32, return_sequences=True, input_shape=(x_train.shape[1], 1)))model.add(Dropout(0.2))model.add(LSTM(units=16))model.add(Dropout(0.2))model.add(Dense(units=1))model.compile(loss='mean_squared_error', optimizer='adam')model.fit(np.array(x_train), np.array(y_train), epochs=epochs, batch_size=batch_size)prediction = model.predict(x_test)return prediction
4. 模型评估与性能比较
通过计算RMSE(均方根误差)、MAE(平均绝对误差)、MAPE(平均绝对百分比误差)等指标,我们可以评
估每个模型的表现并比较其优劣。下面是一个基于RMSE和MAPE评估模型的代码示例:
def evaluate_predictions(y_true, y_pred):rmse = np.sqrt(mean_squared_error(y_true, y_pred))mape = np.mean(np.abs((y_true - y_pred) / y_true)) * 100print(f"RMSE: {rmse:.4f}, MAPE: {mape:.4f}%")
5. 结果可视化与总结
最后,我们通过可视化预测结果与实际值的对比,直观地展示每个模型的效果。通过图形,可以清楚地看到哪些模型在股票价格预测中表现得更好。
plt.plot(test_y_apple, color='blue', label='Real AAPL Price')
plt.plot(y_pred_apple_svm, color='red', label='Predicted AAPL Price')
plt.title('AAPL Price Prediction using SVM')
plt.xlabel('Time')
plt.ylabel('Price')
plt.legend()
plt.show()
总结
通过结合CEEMDAN和多种机器学习模型(如SVM、XGBoost、LSTM等),我们能够更准确地预测股票价格。每种模型在不同数据集上的表现有所不同,通过评估指标的比较,我们可以选择最佳的模型进行未来的预测。通过这种方法,不仅能提升股票预测的准确性,还能为金融分析师和投资者提供更有力的数据支持。