前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >时序分析|01时序数据分析和处理技能入门

时序分析|01时序数据分析和处理技能入门

作者头像
用户4434621
发布2024-09-18 16:41:10
1030
发布2024-09-18 16:41:10
举报
文章被收录于专栏:科学最Top

写在前面

我博士毕业之后去了公司工作,但等安稳下来经常会想,既然接受8年的科学研究培养,如果就此搁下科研未免太对不起自己过去的付出。自那开始,我有空就开始琢磨继续独立做点什么研究。首先,我排除了CV和NLP,其一个是没显卡;其二,这些领域实在是太卷了,神仙的战场凡人还是不要参与了。

经过一段时间的摸索,我决定选定时间序列预测作为业余的研究方向。相比之下,时序的研究算是不冷不热,对显卡需求没那么高。更重要的是,我对量化投资一直非常有兴趣,数字货币、股票、外汇这些都有参与。但我从没赚过钱,事实上读书期间我陆续赔掉了2万多块钱,不过好在我的热情一直没有消减。我想有兴趣做驱动,应该能在时序的路上能走的更远一些。过去我一直是手动交易赔钱,我未来期望至少也要让模型替我亏钱,而我则能在赔钱过程中收获技能的成长和乐趣。

最后,如你所见,在时序领域我也是新人。我期望通过记录自己的学习过程,包括:时序论文阅读分享、时序数据分析技巧,能让所看、所做的工作有所积淀。当然,如果我的笔记能帮助到后来者则是更好的。

So,让我们从Kaggle竞赛的数字货币可视化和基本预处理分析开始吧!

数据集导入

今天记录的是时序数据可视化和基本分析的入门篇,数据来源Kaggle竞赛(G-Research Crypto forecasting competition),包含train,supplemental_train,asset_details这三个核心数据文件。各位可到官网去了解学习,本文的代码大量来自上面。赛题要求参赛者运用机器学习专业知识来预测比特币、以太坊等14种热门加密货币的短期回报。数据集包含数百万行自2018年以来的真实市场数据,不过今天我们不做建模,只进行数据基本分析和可视化。

首先,导入train.csv数据结构,发现数据包含时间戳、货币ID、收盘、开盘价、最低、最高价、预期收益率(Target)等特征。其中预期收益率Target的计算,我们在之后的博客中详细讲。

代码语言:javascript
复制
import pandas as pd
df_train = pd.read_csv('量化数据/train.csv')
df_train.head()

我们继续导入asset_details.csv数据集,查看都有哪些数字货币对。实际总共包含14种货币,这里只显示出了前五种,可以看到asset_details中中间有一列Weight特征,这个特征表示每种货币的在市场中的权重,之后我们计算Target时,还会用到该特征。

代码语言:javascript
复制
asset_details = pd.read_csv('量化数据/asset_details.csv')
asset_details

蜡烛图

蜡烛图表是一种以开盘价、最高价、最低价和收盘价为基础的市场数据聚合形式。我们可以通过常用的蜡烛图表来可视化这些数据,并对盘中数值进行技术分析。我们使用 plotly 库可视化比特币价格数据的一部分,绘图的底部显示一个范围滑块,我们可以使用它来放大绘图。

以比特币(Asset_ID=1)的数据为例,我们选取最近的200条数据

代码语言:javascript
复制
btc = crypto_df[crypto_df["Asset_ID"]==1].set_index("timestamp") # Asset_ID = 1 for Bitcoin
btc_mini = btc.iloc[-200:] # Select recent data rows

使用plotly 库函数,绘制比特币的蜡烛图

代码语言:javascript
复制
import plotly.graph_objects as go
import cufflinks as cf
# 不加下两行,图表可能显示空白
cf.go_offline()
cf.set_config_file(offline=True, world_readable=True)

fig = go.Figure(data=[go.Candlestick(x=btc_mini.index, open=btc_mini['Open'], high=btc_mini['High'], low=btc_mini['Low'], close=btc_mini['Close'])])
fig.show()

结果如下所示,注意该图表是可交互的,通过拖动下方滑块可以放大缩小。

数据预处理

像这类时序数据,有缺失值是常见的,接下来我们以以太坊ETH为例,查看缺失值并进行填补处理。可以看到以太坊货币对的Target特征行数少于其他特征,表明有缺失值。

代码语言:javascript
复制
eth = crypto_df[crypto_df["Asset_ID"]==6].set_index("timestamp") # Asset_ID = 6 for Ethereum
eth.info(show_counts =True)

使用.isna()和.sum()函数可以具体统计缺失值的数量,可以看到在这个时间范围内,以太坊Target缺少340条数据。

代码语言:javascript
复制
eth.isna().sum()

继续进行分析,我们把时间戳转换为正常时间格式,并查看数据的时间横跨范围。

代码语言:javascript
复制
beg_btc = btc.index[0].astype('datetime64[s]')
end_btc = btc.index[-1].astype('datetime64[s]')
beg_eth = eth.index[0].astype('datetime64[s]')
end_eth = eth.index[-1].astype('datetime64[s]')

print('BTC data goes from ', beg_btc, 'to ', end_btc)
print('Ethereum data goes from ', beg_eth, 'to ', end_eth)

由于缺失的资产数据是直接成行的缺失,因此我们可以检查连续行之间的时间戳差异,看看是否有丢失的数据。正常情况下,数据是连续的,两行数据相减应为60,如果两行相见大于60,则说明缺行。

代码语言:javascript
复制
(eth.index[1:]-eth.index[:-1]).value_counts().head()

上面的结果显示数据中存在许多空白。为了使用时间序列连续,我们应该将数据预处理为没有时间间隙的格式。我们固定时间戳的开始和结尾,使用 .reindex() 方法进行前向填充,填充代码如下,填充完毕再次进行检查,现在我们发现数据变成连续的固定时间间隔了。

代码语言:javascript
复制
eth = eth.reindex(range(eth.index[0],eth.index[-1]+60,60),method='pad')
(eth.index[1:]-eth.index[:-1]).value_counts().head(

数据可视化分析

上面使用了蜡烛图进行可视化分析,由于收盘价非常关键,我们这里首先可视化两种资产的收盘价。

代码语言:javascript
复制
import matplotlib.pyplot as plt

# plot vwap time series for both chosen assets
f = plt.figure(figsize=(15,4))

# fill missing values for BTC
btc = btc.reindex(range(btc.index[0],btc.index[-1]+60,60),method='pad')

ax = f.add_subplot(121)
plt.plot(btc['Close'], label='BTC')
plt.legend()
plt.xlabel('Time')
plt.ylabel('Bitcoin')

ax2 = f.add_subplot(122)
ax2.plot(eth['Close'], color='red', label='ETH')
plt.legend()
plt.xlabel('Time')
plt.ylabel('Ethereum')

plt.tight_layout()
plt.show()

从折线图可以看出来,两种资产价格差异很大,并且历史数据的变化幅度也有差异,我们进一步检查最近两种资产的变化幅度。选取2021年6月-2021年7月的数据,并绘制图表。

代码语言:javascript
复制
import time

# auxiliary function, from datetime to timestamp
totimestamp = lambda s: np.int32(time.mktime(datetime.strptime(s, "%d/%m/%Y").timetuple()))

# create intervals
btc_mini_2021 = btc.loc[totimestamp('01/06/2021'):totimestamp('01/07/2021')]
eth_mini_2021 = eth.loc[totimestamp('01/06/2021'):totimestamp('01/07/2021')]

在选定的短时间间隔内,我们可以直观地看到两种资产之间的似乎有一些潜在相关性(同涨同跌)。接下来,我们要做的是定量刻画这种相关性的强弱。然而,不同的资产的价格规模不同,因此价格实际不具有可比性。我们可以通过对数函数log对收盘价进行处理,然后计算相邻时间价格差,即每个时刻的return。

这里使用了.diff()函数,该函数是在给定周期periods后,求该周期的差值,如periods=1,就是相邻数值求差。

Log return

代码语言:javascript
复制
# define function to compute log returns
def log_return(series, periods=1):
    return np.log(series).diff(periods=periods)

接下来可视化两种资产的对数回报(相当于在这一分钟买入,下一分钟卖出),由于取了对数,数值变化幅度在基本在较小区间内,重合度很高。

代码语言:javascript
复制
import scipy.stats as stats

lret_btc = log_return(btc_mini_2021.Close)[1:]
lret_eth = log_return(eth_mini_2021.Close)[1:]
lret_btc.rename('lret_btc', inplace=True)
lret_eth.rename('lret_eth', inplace=True)

plt.figure(figsize=(8,4))
plt.plot(lret_btc);
plt.plot(lret_eth);
plt.show()

两种资产的相关性

那么,两种资产变化的相关性到底如何呢,现在让我们更详细地检查一下。先使用之前定义的log_return获取每个时间点的return,然后使用concat拼接,注意axis=1是左右拼,默认为0是上下拼。

代码语言:javascript
复制
# join two asset in single DataFrame

lret_btc_long = log_return(btc.Close)[1:]
lret_eth_long = log_return(eth.Close)[1:]
lret_btc_long.rename('lret_btc', inplace=True)
lret_eth_long.rename('lret_eth', inplace=True)
two_assets = pd.concat([lret_btc_long, lret_eth_long], axis=1)

# group consecutive rows and use .corr() for correlation between columns
corr_time = two_assets.groupby(two_assets.index//(10000*60)).corr().loc[:,"lret_btc"].loc[:,"lret_eth"]

corr_time.plot();
plt.xticks([])
plt.ylabel("Correlation")
plt.title("Correlation between BTC and ETH over time");

如果你不理解上面关于corr_time的计算,我特意在下方写了一个分步骤的小例子,看完应该差不多能懂。

这样,我们就算出了比特币和以太坊return的相关性,可以看到越到后期,两者的相关性越强,一般来说相关性系数超过0.8,已经是非常相关了。接下来通过可视化相关矩阵来检查所有资产之间的相关性。我们可以看到某些资产的成对相关性比其他资产高得多,这也许是潜在的投资机会。

代码语言:javascript
复制
# create dataframe with returns for all assets
all_assets_2021 = pd.DataFrame([])
for asset_id, asset_name in zip(asset_details.Asset_ID, asset_details.Asset_Name):
  asset = crypto_df[crypto_df["Asset_ID"]==asset_id].set_index("timestamp")
  asset = asset.loc[totimestamp('01/01/2021'):totimestamp('01/05/2021')]
  asset = asset.reindex(range(asset.index[0],asset.index[-1]+60,60),method='pad')
  lret = log_return(asset.Close.fillna(0))[1:]
  all_assets_2021 = all_assets_2021.join(lret, rsuffix=asset_name, how="outer")

算出结果,就可以可视化的显示出来了

代码语言:javascript
复制
plt.imshow(all_assets_2021.corr());
plt.yticks(range(14), asset_details.Asset_Name.values);
plt.xticks(range(14), asset_details.Asset_Name.values, rotation='vertical');
plt.colorbar();

至此,我们基本走通了数据读取、缺失值处理、可视化和相关性的基本分析。限于篇幅,在下一篇我们将开始尝试建立基础模型,来进行Target的预测任务。

以上数据集和代码可在公众号,回复“代码01” 获取。除了本文的数字币数据集外,时间序列常用的electricity、exchange_rate、illness、traffic、weather数据集一并打包在里面。

参考链接: [1]https://www.kaggle.com/competitions/g-research-crypto-forecasting/overview

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-11-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 科学最Top 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 写在前面
  • 数据集导入
  • 蜡烛图
  • 数据预处理
  • 数据可视化分析
    • Log return
      • 两种资产的相关性
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档