在本文中,我们将使用纳斯达克100指数数据和Python来分析历史熊市。在这个过程中,我们还将学习如何衡量时间序列数据的相似性。
纳斯达克100指数经历过哪些熊市?
哪些历史熊市与当前熊市相似?
如何衡量时间序列数据的相似性?
import os
import datetime as dt
import itertools
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import pandas_datareader.data as web
from sklearn import preprocessing
from sklearn.metrics.pairwise import cosine_similarity
from fastdtw import fastdtwdata_dir = "./data/nasdaq_bear_analysis"
os.makedirs(data_dir, exist_ok=True)1 下载数据集
纳斯达克100指数
我们将从雅虎财经获得纳斯达克100指数的历史数据。欲了解更多信息,请点击这里。所有资料可在此下载。
# get historical data of Nasdaq 100 index(^NDX)
nasdaq_100 = web.DataReader('^NDX', 'yahoo', start='1980-01-01', end='2022-05-28')
print(nasdaq_100.shape)
# save the data
nasdaq100_file_path = f"{data_dir}/nasdaq100.csv"
nasdaq_100.to_csv(nasdaq100_file_path)
nasdaq_100 = pd.read_csv(nasdaq100_file_path, index_col="Date", parse_dates=True)
nasdaq_100.head(3)画一个时间序列图来看看价格是如何变化
fig, ax = plt.subplots(figsize=(15, 8))
ax.plot(nasdaq_100.index, nasdaq_100["Close"])
ax.grid(axis="y")
ax.set_title("Nasdaq 100 historical price")
ax.set_xlabel("Date")
ax.set_ylabel("Price")
plt.show()2 预处理
在这篇文章中,我们将提取和分析股票价格从高位下跌20%或以上的六个时期(熊市)。
黑色星期一(1987-10-05 ~ 1987-10-26)
90年代早期衰退(1990-07-16 ~ 1990-10-11)
互联网泡沫(2000-03-27 ~ 2002-10-07)
金融危机(2008-06-05 ~ 2009-03-09)
COVID-19大流行(2020-02-19 ~ 2020-03-20)
当前熊市(2010-11-19 ~ 2202-05-24)
提取的数据是时间序列数据,在熊市中从最高值开始,到最低值结束。请注意,目前还不清楚当前的熊市是仍在途中还是已经触底。
画出每个熊市的股价下跌曲线。在每一个熊市中,最高价格的价值被调整为1。此外,我们在(x)上标记了这段时期和下降的平均值。平均跌幅52.46%,平均持续时间211.8个交易日。
fig, ax = plt.subplots(figsize=(15, 8))
ax.plot(range(len(ts_black_monday)), ts_black_monday, alpha=1, label="Black Monday")
ax.plot(range(len(ts_1990_recession)), ts_1990_recession, alpha=0.5, label="early 1990s recession")
ax.plot(range(len(ts_dotcom)), ts_dotcom, alpha=0.5, label="Dotcom Bubble")
ax.plot(range(len(ts_financial_crisis)), ts_financial_crisis, alpha=0.5, label="Financial Crisis")
ax.plot(range(len(ts_covid19_pandemic)), ts_covid19_pandemic, alpha=1, label="COVID-19 recession")
ax.plot(range(len(ts_current_bear)), ts_current_bear, alpha=0.7, label="current bear market")
ax.scatter([211.8], [1 - 0.5246], marker="x", color="red")
ax.grid(axis="y")
ax.set_ylim(0, 1)
ax.set_title("Nasdaq 100 historical bear market")
ax.set_xlabel("Duration(in trading days)")
ax.set_ylabel("Price")
ax.legend()
plt.show()3.计算相似性
除了这次,纳斯达克100指数已经经历了5次熊市。哪一个离现在的落点最近?为了找到答案,我们需要计算每个时间序列数据的相似性。现在,我们如何衡量不同长度的时间序列数据的相似性?当我们以前聚集股票价格数据时,我们处理的是相同长度的时间序列数据。如果你有兴趣,你可以阅读这篇文章来更好地理解。
4 间接计算
让我们首先考虑间接计算方法。如果我们可以将数据转换成固定长度的可比形式,我们就可以间接地计算相似性。这里有四种转换数据的方法。下降率 我们将计算从最高到最低的下降率。
event_name_list = ["Black Monday", "Early 1990 Recession", "Dotcom Bubble",
"Financial Crirsis", "COVID19 Pandmic", "Current Bear"]def calculate_downside(data):
return 1 - data.min()decrease_rate = [calculate_downside(ts_black_monday),
calculate_downside(ts_1990_recession),
calculate_downside(ts_dotcom),
calculate_downside(ts_financial_crisis),
calculate_downside(ts_covid19_pandemic),
calculate_downside(ts_current_bear)]df_feature1 = pd.DataFrame({"Name": event_name_list, "Decrease Rate": decrease_rate})
df_feature1目前的熊市显然更接近COVID - 19大流行的时间。
下降速度 计算从最高下降到最低的速度。
def calculate_slope(data):
return (1 - data.min()) / len(data)decrease_speed = [calculate_slope(ts_black_monday),
calculate_slope(ts_1990_recession),
calculate_slope(ts_dotcom),
calculate_slope(ts_financial_crisis),
calculate_slope(ts_covid19_pandemic),
calculate_slope(ts_current_bear)]df_feature2 = pd.DataFrame({"Name": event_name_list, "Decrease Speed": decrease_speed})
df_feature2当前熊市的下跌速度与金融危机时相似。
持续时间 计算熊市的持续时间。
duration = [len(ts_black_monday),
len(ts_1990_recession),
len(ts_dotcom),
len(ts_financial_crisis),
len(ts_covid19_pandemic),
len(ts_current_bear)]df_feature3 = pd.DataFrame({"Name": event_name_list, "Duration": duration})
df_feature3就熊市的持续时间而言,当前熊市的价值大约介于金融危机和20世纪90年代初衰退的价值之间。这在某种程度上更接近金融危机的价值。另一种方法是使用神经网络进行特征提取,或者同时使用另一个变量的值。最后,我们展示了如何结合上述特征来计算相似度。这里我们将使用两个变量的组合,因为这样更容易形象化。
4. 降低率和持续时间
df_feature4 = pd.DataFrame({"Name": event_name_list, "Decrease Rate": decrease_rate, "Duration": duration})
df_feature4因为我们处理的是不同尺度的多个变量,所以我们应用标准化来对齐这些尺度。
decrease_rate_scaled = preprocessing.scale(decrease_rate)
duration_scaled = preprocessing.scale(duration)fig, ax = plt.subplots(figsize=(8, 8))
for i, event in enumerate(event_name_list):
ax.scatter(decrease_rate_scaled[i], duration_scaled[i], marker="D", label=event)
ax.grid(linestyle="--")
ax.set_xlim(-2.5, 2.5)
ax.set_ylim(-2.5, 2.5)
ax.set_xlabel("Decrease Rate")
ax.set_ylabel("Duration(trading days)")
ax.legend()
plt.show()从上图中可以看出,上世纪90年代初的衰退似乎与当前的熊市类似。到目前为止,我们无意中使用了欧氏距离来计算距离,但这里我们将使用不同的距离度量来计算相似度(余弦相似度)。
df_feature4_1 = pd.DataFrame(
{"Name": event_name_list, "Decrease Rate": decrease_rate_scaled, "Duration": duration_scaled})similarity_list = []
for i in df_feature4_1.index:
cos_sim = cosine_similarity(df_feature4_1.loc[[i], ["Decrease Rate", "Duration"]], df_feature4_1.loc[[5], [
"Decrease Rate", "Duration"]])
similarity_list.append(cos_sim[0][0])df_feature4_1["Similarity"] = similarity_list
df_feature4_1fig, ax = plt.subplots(figsize=(8, 8))
for i, event in enumerate(event_name_list):
ax.scatter(decrease_rate_scaled[i], duration_scaled[i], marker="D", label=event)
ax.plot([0, decrease_rate_scaled[5]], [0, duration_scaled[5]], color="black", alpha=0.6)
ax.plot([0, decrease_rate_scaled[4]], [0, duration_scaled[4]], color="black", linestyle="dotted", alpha=0.6)
ax.grid(linestyle="--")
ax.set_xlim(-2.5, 2.5)
ax.set_ylim(-2.5, 2.5)
ax.set_xlabel("Decrease Rate")
ax.set_ylabel("Duration(trading days)")
ax.legend()
plt.show()直接计算 实际上还有其他方法可以直接计算不同长度的时间序列数据的相似度。其中一种方法是DTW(动态时间规整)。到当前熊市的距离是用DTW计算出来的,并在热图中显示出来。
def calc_dtw(l_sr):
dict_dtw = {}
for item1, item2 in itertools.product(l_sr, repeat=2):
distance, path = fastdtw(item1[1], item2[1])
dict_dtw[(item1[0], item2[0])] = distancereturn dict_dtwdict_dtw = calc_dtw(list(zip(event_name_list,
[ts_1990_recession,
ts_black_monday,
ts_dotcom,
ts_financial_crisis,
ts_covid19_pandemic,
ts_current_bear])))dist_matrix = np.array(list(dict_dtw.values())).reshape(6, 6)
df_dist_matrix = pd.DataFrame(data=dist_matrix, index=event_name_list, columns=event_name_list)plt.figure(figsize=(8, 6))
sns.heatmap(df_dist_matrix, square=True, annot=True, cmap='Blues')
plt.show()互联网泡沫似乎与其他5个熊市都相去甚远。因此,我们将再次绘制排除互联网泡沫的热图。
event_name_list_2 = event_name_list[:2] + event_name_list[3:]
dict_dtw_2 = calc_dtw(list(zip(event_name_list_2,
[ts_1990_recession,
ts_black_monday,
ts_financial_crisis,
ts_covid19_pandemic,
ts_current_bear])))dist_matrix_2 = np.array(list(dict_dtw_2.values())).reshape(5, 5)df_dist_matrix_2 = pd.DataFrame(data=dist_matrix_2, index=event_name_list_2, columns=event_name_list_2)plt.figure(figsize=(8, 6))
sns.heatmap(df_dist_matrix_2, square=True, annot=True, cmap='Blues')
plt.show()我们能够测量距离(相似性的反比),而无需对齐数据的长度。covid - 19大流行的时间似乎最接近当前的熊市;20世纪90年代初的经济衰退和黑色星期一也与现在的市场类似。
结论
在本文中,我们重点讨论了各种模式中时间序列数据的相似性。根据我们所关注的变量以及我们用来评估它们的标准,结果可能会有很大的不同。这与我们看待世界的方式相似。这就是为什么变量和标准的选择如此重要,无论是在数据科学中还是在日常生活中。
| 留言与评论(共有 0 条评论) “” |