基于时间序列分析或回归分析的股票预测

一. 课程设计选题内容及需求分析

(1)选择题目:基于时间序列分析或回归分析的股票预测

股票市场是衡量经济健康的重要指标,对投资者和决策者而言,理解市场动态并预测未来趋势至关重要。本课程设计旨在通过分析历史股票数据,探索股票间的相关性及其价格影响因素,进而构建模型预测股票的未来走势。

2基本要求与分析

数据探索:

初步分析提供的股票市场数据,包括基本统计描述、异常值检测等。

分析不同股票之间的相关性,识别价格走势一致或相反的股票。

数据预处理:

清洗和预处理数据,处理缺失值、异常值、数据规范化等。

分析影响股票价格的因素,如市场指数、汇率、黄金价格等。

回归分析/时间序列分析:

选择至少两种适当的回归分析方法进行回归分析。

选择合适的自变量,建立合适的回归模型,必要时进行模型参数调整和优化。

或使用时间序列分析算法ARIMA进行时间序列分析,预测各股票价格走势。

结果评价:

评价预测效果,使用均方误差(MSE)、均方根误差(RMSE)、决定系数(R²)等常见评价指标。

可视化:

使用适当的可视化工具和方法展示回归分析结果。

结合实际背景和需求,对模型结果进行合理解释和应用。

二.课程设计

2.1 数据探索

1通过查询我们将数据分成股票和影响因素两大类,下面是对数据描述的说明:

Date:日期列,表示数据记录的日期。

AAPL.O:苹果公司(Apple Inc.)的股票代码,后缀".O"可能表示该股票在海外市场上市,通常是奥斯陆证券交易所(Oslo Bors)的代码。

MSFT.O:微软公司(Microsoft Corporation)的股票代码,同样".O"可能表示该股票在海外市场上市。

INTC.O:英特尔公司(Intel Corporation)的股票代码,".O"同样可能表示该股票在海外市场上市。

AMZN.O:亚马逊公司(Amazon.com Inc.)的股票代码,".O"表示可能在海外市场上市。

GS.N:高盛集团(The Goldman Sachs Group, Inc.)的股票代码,".N"可能表示该股票在纽约证券交易所(New York Stock Exchange)上市。

SPY:代表标普500指数基金(SPDR S&P 500 ETF Trust)的股票代码,这是一个跟踪标普500指数的交易所交易基金(ETF)。

GDX:VanEck Vectors Gold Miners ETF的股票代码,这是一个投资于黄金开采公司的ETF。

GLD:SPDR Gold Shares的股票代码,这是一个投资于实物黄金的ETF

.SPX:标普500指数(S&P 500 Index)的代码,这是一个衡量美国大型股票市场表现的指数。

.VIX:芝加哥期权交易所波动率指数(CBOE Volatility Index),通常被称为恐慌指数,它衡量市场预期的波动性。

EUR=:欧元对美元的汇率,表示一单位欧元可以兑换多少美元。

XAU=:黄金价格,通常以每盎司多少美元表示。

在excel中筛选分析可知存在缺失值,且缺失值的特点是当一支股票存在缺失值时其余几支股票都存在缺失值,所以这样的空缺值删除即可不影响股票的分析。使用excel筛选查看数据初步得到以上需要操作的部分,关于数据异常值的处理需要使用箱线图观察。

读取data.csv 的文件,并将数据存储在 data 变量中。将数据统计结果计数、均值、标准差、最小值、四分位数和最大值等存为文件。通过两个循环分别绘制数据各列的直方图。如图1所示:

import pandas as pd
import matplotlib.pyplot as plt
# 读取 CSV 文件
data = pd.read_csv('data.csv')
# 将时间列转换为时间戳
data['Date'] = pd.to_datetime(data['Date']).astype('int64') // 10**9
# 将描述性统计结果保存为 CSV 文件
describe_result = data.describe()
describe_result.to_csv('describe_result.csv')  # 保存结果
# 绘制各列数据的直方图
plt.figure(figsize=(15, 8))
for column_index, column in enumerate(data.columns):
    plt.subplot(2, 7, column_index + 1)
    data[column].hist()
    plt.title(f'Histogram of {column}')
plt.tight_layout()
plt.show()

图1数据探索代码

数据探索运行,初步了解数据的基本属性。结果如图2所示:

图2数据统计结果

数据探索运行结果如图3所示:

图3数据探索结果

使用统计分析方法初步展示数据。发现数据数值之间差异较大。数值的大小差距存在一位和三位数值,所以需要进行数据的标准化消除量纲之间的差异。

2.2 数据预处理

(1)删除空白数值

原始数据中出现空白数值,删除空白数值不影响分析。在excel中通过对数据的初步观察发现数据有缺失值,筛选出缺失值的部分发现,存在缺失值的部分每只股票都同时存在缺失值。汇率和黄金价格一直存在所以只需要('AAPL.O', 'MSFT.O', 'INTC.O', 'AMZN.O','GS.N', 'SPY', '.SPX', '.VIX', 'GDX', 'GLD')几个指标同时为空,则删除即可。删除空白值代码如图4所示:

# 处理空白数值
import pandas as pd
# 读取CSV文件
data = pd.read_csv('data.csv')
# 定义要检查的列名列表
columns_to_check = ['AAPL.O', 'MSFT.O', 'INTC.O', 'AMZN.O',
                    'GS.N', 'SPY', '.SPX', '.VIX', 'GDX', 'GLD']
# 删除指定列中同时为空白数值的数据
data = data.dropna(subset=columns_to_check, how='all')
# 将结果输出到新的CSV文件
data.to_csv('删除空白值的数据.csv', index=False)

图4删除空白值代码

  1. 检测处理异常值,通过观察可以发现异常值差异较小对数据分析影响大所以不可以直接删除。所以使用四分位范围(IQR)来检测处理异常值。

导入所需的库,包括用于数据处理的 pandas,用于绘图的 matplotlib.pyplot 和增强绘图效果的 seaborn。读取一个 CSV 文件的数据并存入 data 变量。指定了一系列要处理的列名。创建一个较大的图形窗口,并通过循环为每个指定的列绘制一个箱线图作为子图,每个子图的位置由 plt.subplot 确定,标题为对应的列名。最后调整子图布局使显示更美观,并展示绘制好的所有子图。其目的是通过箱线图来直观地查看和识别这些列数据中的异常值情况。如图5所示:

# 检测处理异常值
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
# 读取CSV文件
data = pd.read_csv('删除空白值的数据.csv')
# 选择需要处理的列
columns = ['AAPL.O', 'MSFT.O', 'INTC.O', 'AMZN.O', 'GS.N',
           'SPY', '.SPX', '.VIX', 'EUR=', 'XAU=', 'GDX', 'GLD']
# 使用箱线图识别异常值  绘制原始数据的箱线图
plt.figure(figsize=(15, 10))
for i, column in enumerate(columns):
    plt.subplot(3, 4, i + 1)
    sns.boxplot(data[column])
    plt.title(column)
plt.tight_layout()
plt.show()

图5检测异常值代码

    定义了一个函数,用于根据给定的列数据去除异常值。通过计算四分位数 Q1 和 Q3 得出四分位距 IQR ,进而确定上下限,最终返回处于上下限范围内的数据。复制原始数据为 processed_data ,通过循环对指定的每一列调用 remove_outliers 函数来处理异常值。再次绘制处理后数据的箱线图,与之前类似,不过这次用的是处理后的数据,并且颜色为红色。将处理后的数据集保存为新的 CSV 文件,且不包含索引列。如图6所示:

# 使用IQR方法处理异常值
def remove_outliers(df, column):
    Q1 = df[column].quantile(0.25)
    Q3 = df[column].quantile(0.75)
    IQR = Q3 - Q1
    lower_bound = Q1 - 1.5 * IQR
    upper_bound = Q3 + 1.5 * IQR
    return df[(df[column] >= lower_bound) & (df[column] <= upper_bound)]
# 处理异常值
processed_data = data.copy()
for column in columns:
    processed_data = remove_outliers(processed_data, column)
# 绘制处理后数据的箱线图
plt.figure(figsize=(15, 10))
for i, column in enumerate(columns):
    plt.subplot(3, 4, i + 1)
    sns.boxplot(processed_data[column], color='red')
    plt.title(column)
plt.tight_layout()
plt.show()
# 将处理后的数据保存为csv文件
processed_data.to_csv('处理异常值后的数据.csv', index=False)

图6处理异常值代码

处理前箱线图运行结果如图7所示:

图7处理前箱线图结果

处理后箱线图运行结果如图8所示:

图8处理后箱线图结果

(3)通过观察箱线图发现还存在GS.N,‘ .VIX‘,’XAU=‘ ,’GLD‘几列数据存在异常值,读取处理异常值后的文件数据,选择这四列数据生成箱线图并计算上下界的数值,如图9所示:

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
# 读取csv文件
data = pd.read_csv('处理异常值后的数据.csv')
# 选择需要的列
selected_columns = ['GS.N', '.VIX', 'XAU=', 'GLD']
filtered_data = data[selected_columns]
# 绘制箱线图
for column in selected_columns:
    plt.figure(figsize=(10, 6))
    sns.boxplot(data=filtered_data[column])
    plt.title(f'Boxplot of {column}')
    plt.show()
# 计算异常值点的分界点
Q1 = filtered_data.quantile(0.25)
Q3 = filtered_data.quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
print("异常值点的分界点:")
print("下界:", lower_bound)
print("上界:", upper_bound)

图9计算异常值分界点代码

   在excel表中进行观察,发现这几列数据在上下界外的异常值均属于一个群体,没有出现不符合群体的异常值,所以可以直接使用,然后进行下一步预处理操作。异常值点的分界点如图10所示:

图10异常值点的分界点

    输出有异常值的箱线图,初步观察箱线图异常值排布,发现数据呈现有规律分布结果如图11所示:

图11输出有异常值的箱线图

(4)数据与数据之间差距较大,所以需要使用数据转换对数据进行规范化处理,消除量纲之间的差异。定义了一个名为 standardize_and_save_data 的函数,它接受一个文件路径作为参数。在函数内部,先读取指定的 CSV 文件数据。指定了需要进行标准化处理的列和提取时间列。使用 StandardScaler 对指定列的数据进行标准化处理,并将标准化后的数据转换为 DataFrame 格式。再把之前提取的时间列添加回标准化后的数据中。将包含时间列的标准化数据保存为新的 CSV 文件,且不包含索引列。在代码的最后,指定了要处理的文件路径,并调用这个函数来执行数据的标准化和保存操作。代码如图12所示:

# 数据标准化
import pandas as pd
from sklearn.preprocessing import StandardScaler
def standardize_and_save_data(file_path):
    # 读取文件
    data = pd.read_csv('cleaned_data.csv')
    # 提取需要标准化的数据列
    columns_to_standardize = ['AAPL.O', 'MSFT.O', 'INTC.O', 'AMZN.O', 'GS.N',
                              'SPY', '.SPX', '.VIX', 'EUR=', 'XAU=', 'GDX', 'GLD']
    # 提取时间列
    time_column = data['Date']
    # 提取需要标准化的数据列
    data_to_standardize = data[columns_to_standardize]
    # 标准化数据
    scaler = StandardScaler()
    standardized_data = scaler.fit_transform(data_to_standardize)
    # 将标准化后的数据保存到新文件
    standardized_data = pd.DataFrame(standardized_data, columns=columns_to_standardize)
    # 将时间列添加回去
    standardized_data['Date'] = time_column
    standardized_data.to_csv('数据标准化后的数据.csv', index=False)
# 替换为你的文件路径
file_path = '数据标准化后的数据.csv'
standardize_and_save_data(file_path)

图12数据标准化代码

数据标准化后数据都处于一个区间内,消除了量纲之间的差异。标准化结果如图13所示:

图13数据标准化结果

2.3 数据分析

1.股票与股票之间相关性

通过搜索分析可知,哪几类为股票数据将其分为一组进行研究。'AAPL.O', 'MSFT.O', 'INTC.O', 'AMZN.O', 'GS.N', 'SPY', 'GDX', 'GLD'六支为股票数据,通过热力图分析他们之间的关系。如图14所示:

# 将价格趋势一样的可以当成一类使用热力图分析
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.cluster import AgglomerativeClustering
from scipy.cluster.hierarchy import dendrogram, linkage
# 读取CSV文件
data = pd.read_csv('处理异常值后的数据.csv')
# 假设CSV文件中有多个股票的价格数据,列名为'AAPL.O', 'MSFT.O', 'INTC.O', 'AMZN.O', 'GS.N', 'SPY', 'GDX', 'GLD'
stocks = ['AAPL.O', 'MSFT.O', 'INTC.O', 'AMZN.O', 'GS.N', 'SPY', 'GDX', 'GLD']
# # 计算每对股票之间的相关系数
correlation_matrix = data[stocks].corr()
# 选择聚类算法,这里使用Ward方法
clustering = AgglomerativeClustering(linkage='ward')
# 对相关系数矩阵进行层次聚类
clustering.fit(correlation_matrix)
# 获取聚类结果
clusters = clustering.labels_
# 将聚类结果添加到股票列表中
stocks_with_clusters = [(stock, clusters[i]) for i, stock in enumerate(stocks)]
# 绘制树状图
plt.figure(figsize=(10, 8))
dendrogram(linkage(correlation_matrix, method='ward'), labels=stocks, leaf_font_size=10)
plt.title('Dendrogram of Stock Correlations')
plt.xlabel('Stocks')
plt.ylabel('Distance')
plt.show()
# 使用热力图显示聚类结果
plt.figure(figsize=(10, 8))
sns.heatmap(correlation_matrix, cmap='coolwarm', annot=True, square=True, fmt=".2f", xticklabels=stocks, yticklabels=stocks)
for i in range(correlation_matrix.shape[0]):
    for j in range(correlation_matrix.shape[1]):
        if i == j:
            plt.text(j, i, stocks_with_clusters[i][1], ha='center', va='center', color='black', fontsize=10)
plt.title('Correlation Matrix with Cluster Labels')
plt.show()

图14股票与股票相关性代码

股票与股票之间分类情况,结果如图15所示:

图15股票与股票树状图

股票与股票之间相关性和分类情况,结果如图15所示:

图16股票与股票热力图

通过树状图和热力分析图利用相关性数值可以看出股票数据最终被分为两类。且MSFT.O与AMZN.O相关性最强。根据价格趋势将股票分成两类,前六个股票代码可以归为一类,因为它们直接代表公司股票或跟踪特定指数的ETF;而后两个股票代码可以归为另一类,因为它们是专门投资于黄金相关资产的ETF。然后根据每类股票受不同因素的共同影响下预测未来趋势。

2.股票与因素之间的相关性分析

使用股票与因素之间的相关性分析哪些因素(如市场指数、汇率、黄金价格等)对股票价格有显著影响。读取文件,并将数据存储在 data 变量中。指定了一个包含股票名称的列表 stocks 。从 data 中提取出指定股票列的数据,并计算这些列之间的相关系数,将结果存储在 correlation_matrix 中。创建一个图形窗口,并使用 seaborn 的 heatmap 函数绘制相关系数的热力图。设置图形的标题并显示图形,以便直观地观察这些股票之间的相关性。如图17所示:

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
# 读取CSV文件
data = pd.read_csv('处理异常值后的数据.csv')
stocks = ['AAPL.O', 'MSFT.O', 'INTC.O', 'AMZN.O', 'GS.N',
          'SPY', '.SPX', '.VIX', 'EUR=', 'XAU=', 'GDX', 'GLD']
# 计算每对股票之间的相关系数
correlation_matrix = data[stocks].corr()
# 使用热力图显示股票之间的相关性
plt.figure(figsize=(10, 8))
sns.heatmap(correlation_matrix, cmap='coolwarm', annot=True, square=True,
            fmt=".2f", xticklabels=stocks, yticklabels=stocks)
plt.title('Correlation Matrix of Stocks')
plt.show()


图17股票与因素之间的相关性代码

股票与因素之间相关性,通过相关性结果分析可知SPX影响最显著。可以探索受到该因素影响的环境原因。’GDX’和‘GLD’是和黄金相关的股票受黄金价格影响最大,其余几支股票是与非黄金相关的股票受SPX标普系数影响最大。结果如图18所示:

图18股票与因素热力图

2.4 结果评价及可视化

1.回归分析预测

  1. 多元线性回归

定义一个计算评价指标的函数用于后期获取评价效果,读入特定的 CSV 数据,并选取指定的列。之后,将数据划分为两类(class_1 和 class_2)以及对应的预测因素(factors)。如图19所示:

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score
import numpy as np
import matplotlib.pyplot as plt
def calculate_metrics(y_true, y_pred):
    mse = mean_squared_error(y_true, y_pred)
    rmse = np.sqrt(mse)
    r2 = r2_score(y_true, y_pred)
    return mse, rmse, r2

data = pd.read_csv('数据标准化后的数据.csv')
selected_columns = ['AAPL.O', 'MSFT.O', 'INTC.O', 'AMZN.O', 'GS.N',
                     'SPY', '.SPX', 'EUR=', 'XAU=', 'GDX', 'GLD', '.VIX']
data = data[selected_columns]
class_1 = data[['AAPL.O', 'MSFT.O', 'INTC.O', 'AMZN.O', 'GS.N', 'SPY']]
class_2 = data[['GDX', 'GLD']]
factors = data[['.SPX', 'EUR=', 'XAU=', '.VIX']]

图19多元回归代码

使用 train_test_split 函数,将 factors 分别与 class_1 和 class_2 划分成训练集和测试集。然后,创建两个线性回归模型 lr_1 和 lr_2 ,分别用训练集 (X_train, y_train_1) 和 (X_train, y_train_2) 进行训练。接着,用训练好的模型对各自的测试集 X_test 进行预测,得到预测结果 y_pred_lr_1 和 y_pred_lr_2 。最后,调用定义的函数 calculate_metrics ,分别计算两类数据的预测结果和真实测试结果之间的均方误差、均方根误差和决定系数。如图20所示:

X_train, X_test, y_train_1, y_test_1 = train_test_split(factors, class_1, test_size=0.2, random_state=42)
X_train, X_test, y_train_2, y_test_2 = train_test_split(factors, class_2, test_size=0.2, random_state=42)

lr_1 = LinearRegression()
lr_1.fit(X_train, y_train_1)
y_pred_lr_1 = lr_1.predict(X_test)

lr_2 = LinearRegression()
lr_2.fit(X_train, y_train_2)
y_pred_lr_2 = lr_2.predict(X_test)

mse_lr_1, rmse_lr_1, r2_lr_1 = calculate_metrics(y_test_1, y_pred_lr_1)
mse_lr_2, rmse_lr_2, r2_lr_2 = calculate_metrics(y_test_2, y_pred_lr_2)

图20多元回归代码

使用创建一个包含两个子图的绘图区域,fig 表示整个图形对象,ax1 和 ax2 分别表示两个子图。通过两个循环分别在两个子图中绘制数据点。对于第一个子图 ax1 ,循环遍历 selected_columns 前 6 列对应的 y_test_1 和 y_pred_lr_1 的数据,绘制散点图,并绘制一条从最小值到最大值的对角线参考线。同时设置 x 轴和 y 轴的标签以及子图的标题。对于第二个子图 ax2 ,循环遍历 selected_columns 后 2 列对应的 y_test_2 和 y_pred_lr_2 的数据,进行类似的绘制操作。使用 plt.show 显示绘制好的图形。如图21所示:

# 绘制回归图
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 6))
for i in range(len(selected_columns[:6])):
    ax1.scatter(y_test_1.iloc[:, i], y_pred_lr_1[:, i])
    ax1.plot([y_test_1.iloc[:, i].min(), y_test_1.iloc[:, i].max()],
             [y_test_1.iloc[:, i].min(), y_test_1.iloc[:, i].max()], 'k--', lw=2)
    ax1.set_xlabel('True values')
    ax1.set_ylabel('Predicted values')
    ax1.set_title('Linear Regression for Class 1 Stocks')
for i in range(len(selected_columns[-2:])):
    ax2.scatter(y_test_2.iloc[:, i], y_pred_lr_2[:, i])
    ax2.plot([y_test_2.iloc[:, i].min(), y_test_2.iloc[:, i].max()],
             [y_test_2.iloc[:, i].min(), y_test_2.iloc[:, i].max()], 'k--', lw=2)
    ax2.set_xlabel('True values')
    ax2.set_ylabel('Predicted values')
    ax2.set_title('Linear Regression for Class 2 Stocks')
plt.show()

图21多元回归代码

    先获取然后输出回归模型的参数,如图22所示:

# 获取回归模型参数
weights_1 = lr_1.coef_
intercept_1 = lr_1.intercept_
weights_2 = lr_2.coef_
intercept_2 = lr_2.intercept_
print("第一类股票的回归模型参数:")
print("权重系数:", weights_1)
print("截距:", intercept_1)
print("第二类股票的回归模型参数:")
print("权重系数:", weights_2)
print("截距:", intercept_2)
# 模型评价
print("线性回归 - 第一类股票的 MSE:", mse_lr_1)
print("线性回归 - 第一类股票的 RMSE:", rmse_lr_1)
print("线性回归 - 第一类股票的 R²:", r2_lr_1)
print("线性回归 - 第二类股票的 MSE:", mse_lr_2)
print("线性回归 - 第二类股票的 RMSE:", rmse_lr_2)
print("线性回归 - 第二类股票的 R²:", r2_lr_2)

图22多元回归代码

多元线性回归图运行结果23如图:

图23多元回归结果

多元线性回归模型参数和评价参数如图24所示:

图24多元回归模型和评价

结论:

权重系数(coefficients):正权重系数表示自变量与因变量呈正相关关系,即自变量增加时,因变量也增加;负权重系数表示自变量与因变量呈负相关关系,即自变量增加时,因变量减少。权重系数的绝对值大小表示影响程度的强弱。第一类权重系数中最大的是9.64则表示INTC.O受恐怖指数影响大。第二类权重系数中最大权重系数为0.96,则表示GLD受欧元汇率影响较大。

第一类股票的线性回归模型具有较低的均方误差(MSE)、均方根误差(RMSE)和较高的决定系数(R²),说明模型拟合效果较好,能够较好地预测第一类股票的价格。

第二类股票的线性回归模型也具有较低的均方误差(MSE)、均方根误差(RMSE)和较高的决定系数(R²),说明模型拟合效果较好,能够较好地预测第二类股票的价格。

这两个线性回归模型在预测股票价格方面表现良好,具有较高的准确性和可靠性。

  1. 岭回归

导入所需的库和模块定义了一个计算评估指标的函数 。读取数据文件,并选取指定的列。将数据划分为两类(class_1 和 class_2)以及相关的预测因素(factors)。对每类数据分别进行训练集和测试集的划分。创建并训练两个岭回归模型(ridge_1 和 ridge_2),分别对应两类数据。对测试集进行预测,得到预测结果 y_pred_ridge_1 和 y_pred_ridge_2 。计算两类数据的预测结果和真实测试结果之间的评估指标。绘制两类数据的真实值和预测值的散点图,同时绘制完美拟合的对角线参考线,并添加标题、坐标轴标签和图例。打印两类数据的回归模型参数。输出两类数据的模型评估结果。代码不同之处为岭回归模型的创建和训练,如图25所示:

# 创建并训练岭回归模型
ridge_1 = Ridge(alpha=1.0)
ridge_1.fit(X_train, y_train_1)
y_pred_ridge_1 = ridge_1.predict(X_test)

ridge_2 = Ridge(alpha=1.0)
ridge_2.fit(X_train, y_train_2)
y_pred_ridge_2 = ridge_2.predict(X_test)

# 计算评价指标
mse_ridge_1, rmse_ridge_1, r2_ridge_1 = calculate_metrics(y_test_1, y_pred_ridge_1)
mse_ridge_2, rmse_ridge_2, r2_ridge_2 = calculate_metrics(y_test_2, y_pred_ridge_2)

# 绘制图形
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 5))

ax1.scatter(y_test_1, y_pred_ridge_1, color='blue', label='Actual vs Predicted')
ax1.plot([y_test_1.min(), y_test_1.max()], [y_test_1.min(), y_test_1.max()], 'k--', lw=2, label='Perfect Fit')
ax1.set_title('Ridge Regression - Class 1 Stocks')
ax1.set_xlabel('True Values')
ax1.set_ylabel('Predicted Values')
ax1.legend()

ax2.scatter(y_test_2, y_pred_ridge_2, color='red', label='Actual vs Predicted')
ax2.plot([y_test_2.min(), y_test_2.max()], [y_test_2.min(), y_test_2.max()], 'k--', lw=2, label='Perfect Fit')
ax2.set_title('Ridge Regression - Class 2 Stocks')
ax2.set_xlabel('True Values')
ax2.set_ylabel('Predicted Values')
ax2.legend()

plt.show()

图25岭回归代码

  岭回归图运行结果26如图:

图26岭回归结果

岭回归模型参数和评价结果如图27所示:

图27岭回归模型和评价

结论:

权重系数(coefficients):正权重系数表示自变量与因变量呈正相关关系;负权重系数表示自变量与因变量呈负相关关系。权重系数的绝对值大小表示影响程度的强弱。第一类权重系数中0.997最大,表示SPY受SPX标普500指数影响最大,第二类权重系数中0.962最大,表示GLD受欧元汇率影响较大。

第一类股票岭回归模型的MSE为0.1422,RMSE为0.3771,R²为0.8584。这意味着模型解释了85.84%的方差,且预测误差的平均平方值为0.1422。

第二类股票岭回归模型的MSE为0.1191,RMSE为0.3451,R²为0.8816。这意味着模型解释了88.16%的方差,且预测误差的平均平方值为0.1191。

岭回归模型在两类股票的预测中表现良好,能够解释较高的方差并具有较低的平均平方误差。

  1. 时间序列分析预测
  1. 预测评价

导入所需的库。读取标准化后的数据文件,并将日期列转换为 datetime 类型,接着将日期列设置为数据的索引。从数据中提取出两部分数据,分别命名为 class_1 和 class_2 ,以及相关的预测因素 factors 。 class_1 包含了一些特定的列,class_2 包含另外的列,factors 则是用于后续分析的预测变量。如图28所示:

import pandas as pd
import statsmodels.api as sm
from matplotlib import pyplot as plt
from sklearn.metrics import mean_squared_error, mean_absolute_error
import numpy as np
# 读取标准化后的数据文件
data = pd.read_csv('数据标准化后的数据.csv')
# 将日期列转换为 datetime 类型
data['Date'] = pd.to_datetime(data['Date'])
# 设置日期列为索引
data.set_index('Date', inplace=True)
class_1 = data[['AAPL.O', 'MSFT.O', 'INTC.O', 'AMZN.O', 'GS.N', 'SPY']]
class_2 = data[['GDX', 'GLD']]
factors = data[['.SPX', 'EUR=', 'XAU=', '.VIX']]

图28时间序列代码

    创建一个包含两个子图的图形,用于分别展示两类股票的分析结果。通过一个循环对两类股票(class_1 和 class_2)分别进行处理:对于每类股票:计算该类股票所有列的均值,得到一个新的时间序列数据。以这个时间序列数据作为因变量,以 factors 数据作为外生变量,拟合一个多元的 ARIMA 模型。打印模型的摘要信息。在当前子图中绘制时间序列的实际值,并设置标题和图例。进行预测,并在子图中绘制预测值的折线,添加图例。如图29所示:

# 对每类股票进行时间序列分析,同时考虑其他因素
for i, stock_class in enumerate([class_1, class_2]):
    # 计算每类股票的均值作为新的时间序列数据
    time_series = stock_class.mean(axis=1)
    factors_data = factors
    # 拟合多元 ARIMA 模型(这里假设为 AR(1)模型)
    model = sm.tsa.arima.ARIMA(time_series, exog=factors_data, order=(1, 0, 0))
    results = model.fit()
    # 打印模型摘要信息
    print(f"Model summary for Class {i + 1} with factors:")
    print(results.summary())
    # 绘制时间序列图
    ax = axs[i]
    ax.plot(time_series, label=f"Class {i + 1} (Actual)")
    ax.set_title(f"Class {i + 1} Time Series with factors")
    ax.legend()
    # 预测未来数据并绘制预测线
    forecast = results.get_prediction(start=0, end=-1, exog=factors_data)
    ax.plot(forecast.predicted_mean, label=f"Class {i + 1} (Forecast)", linestyle='--')
    ax.legend()

图29时间序列代码

在前面对时间序列进行分析和预测的基础上,继续为每类股票计算评价指标。均方误差(MSE):通过 mean_squared_error 函数计算实际值 time_series 和预测值 forecast.predicted_mean 之间的均方误差。平均绝对误差(MAE):通过 mean_absolute_error 函数计算。均方根误差(RMSE):通过对 MSE 取平方根得到。

决定系数(R²):手动计算,通过计算残差平方和 ss_res 和总平方和 ss_tot ,然后根据公式计算得到。接着,打印出每类股票的上述评价指标值。最后,使用 plt.show 显示绘制的图形。如图30所示:

 # 计算评价指标
    mse = mean_squared_error(time_series, forecast.predicted_mean)
    mae = mean_absolute_error(time_series, forecast.predicted_mean)
    rmse = np.sqrt(mse)
    # 手动计算决定系数 R²
    y_true = time_series
    y_pred = forecast.predicted_mean
    ss_res = np.sum((y_true - y_pred) ** 2)
    ss_tot = np.sum((y_true - np.mean(y_true)) ** 2)
    r2 = 1 - (ss_res / ss_tot)
    print(f"Mean Squared Error for Class {i + 1}: {mse}")
    print(f"Mean Absolute Error for Class {i + 1}: {mae}")
    print(f"Root Mean Squared Error for Class {i + 1}: {rmse}")
    print(f"R-squared for Class {i + 1}: {r2}")
# 显示图形
plt.show()

图30时间序列代码

时间序列预测结果如图31所示:

图31时间序列预测结果

时间序列评价结果如图32所示:

图32时间序列评价结果

时间序列评价结果如图33所示:

图33时间序列评价结果

    (2)结论:

第一类股票多元ARIMA模型拟合效果较好。模型的决定系数R²接近1,表示模型解释了大部分的方差。均方误差(MSE)和平均绝对误差(MAE)都较小,说明预测值与实际值之间的差异较小。

第二类股票多元ARIMA模型拟合效果也较好。模型的决定系数R²接近1,表示模型解释了大部分的方差。均方误差(MSE)和平均绝对误差(MAE)都较小,说明预测值与实际值之间的差异较小。

3.说明以上分析结果对于该领域的应用

通过比较三种方法的R²发现时间序列的评价模型结果更接近与1,所以时间序列的预测结果更为准确。

对股票价格的走势进行准确预测能够揭示股票价格与其影响因素之间的复杂关系,帮助投资者和决策者理解市场动态,评估潜在风险与回报,从而制定更有效的投资策略和风险管理措施。通过分析标普500指数(.SPX)与其他因素对股票价格的影响,可以识别出具有较大市值、稳定业绩和良好市场流动性的股票,为投资决策提供科学依据。

三.遇到的问题与解决方法

1.问题:生成回归分析预测时,如果生成每种因素的预测,这个预测结果会出现过拟合,预测是不准确的

解决方法:进行预测时应该使用多个因素对同一类股票的预测,这样的预测结果是准确的

2.问题:时间序列分析中需要时间列但是在标准化后,由于时间列没有进行标准化处理所以没有时间列

解决方法:修改标准化代码,再其他列进行标准化处理后,将读取的时间列保留并存储

3.问题:处理完异常值后还会存在一部分数据有异常

解决方法:将还存在异常的数据摘出来计算出现异常的上下界,然后观察数据是否存在异常值,通过观察数据呈现一个趋势属于一个整体

四.总结 

通过热力图分析发现'GDX'和'GLD'与黄金价格有较强的正相关性,说明这两支股票的价格走势与黄金价格的变动紧密相关。而其他股票如'AAPL.O', 'MSFT.O', 'INTC.O', 'AMZN.O', 'GS.N', 'SPY'等则与标普500指数显示出更强的相关性,表明这些股票更多地受到整体市场状况的影响。

'GDX'和'GLD'作为投资于黄金开采公司和实物黄金的ETF,其价值直接与黄金市场价格相关联。而其他股票则属于不同领域的大型上市公司,它们的股价更多反映了投资者对整个经济环境和市场趋势的预期,因此与标普500指数的关系更为密切。

标普500指数作为一个广泛衡量美国股市表现的指标,对大多数非黄金相关股票有着显著的影响力。标普500指数对各个股票的影响程度大,反映了市场领导力、依赖性、投资者信心和波动性敏感性等多个方面。投资者和基金经理通常会利用这些信息来评估潜在风险和回报,制定投资策略,并进行风险管理。股票与标普500指数的相关性还是市场趋势、市场预期和市场集中度的重要指标,它可以帮助投资者判断市场的健康状况并做出相应的投资决策。因此,了解这种相关性对于理解市场动态和制定有效的投资策略至关重要。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值