发布时间:2022-11-11 16:30
来源:yv.l1.pnn - kesci.com
原文链接:时间序列分析入门,看这一篇就够了
点击以上链接 不用配置环境,直接在线运行
数据集下载:DJIA 30股票时间序列
本文包含时间序列的数据结构、可视化、统计学理论及模型介绍,主要侧重金融相关数据实践。翻译自:kaggle - everything you can do with a time series
# 导入必要的包
import os
import warnings
warnings.filterwarnings('ignore')
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
plt.style.use('fivethirtyeight')
# Above is a special style template for matplotlib, highly useful for visualizing time series data
%matplotlib inline
from pylab import rcParams
from plotly import tools
import plotly.plotly as py
from plotly.offline import init_notebook_mode, iplot
init_notebook_mode(connected=True)
import plotly.graph_objs as go
import plotly.figure_factory as ff
import statsmodels.api as sm
from numpy.random import normal, seed
from scipy.stats import norm
from statsmodels.tsa.arima_model import ARMA
from statsmodels.tsa.stattools import adfuller
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
from statsmodels.tsa.arima_process import ArmaProcess
from statsmodels.tsa.arima_model import ARIMA
import math
from sklearn.metrics import mean_squared_error
print(os.listdir("../input"))
Matplotlib is building the font cache using fc-list. This may take a moment.
['DJIA3716', 'djia307822']
这里使用parse_dates
参数将所需的时间序列列导入为datetime
列,并使用index_col
参数将其选择为数据框的索引。
google = pd.read_csv('/home/kesci/input/DJIA3716/GOOGL_2006-01-01_to_2018-01-01.csv',
index_col='Date', parse_dates=['Date'])
google.head()
Google 数据没有缺失值,所以我们这里不用处理缺失值。如果有缺失值的话,我们可以使用 fillna() 方法并设置参数 ffill 来填充缺失值。
该参数 ffill 意味着用空白处前面的的最后一个的有效观察值来填补缺失值。
google.isnull().any()
Open False
High False
Low False
Close False
Volume False
Name False
dtype: bool
google.isnull().sum()
Open 0
High 0
Low 0
Close 0
Volume 0
Name 0
dtype: int64
以上代码表示这几列都没有缺失值。
plt.figure()
google['2008':'2010'].plot(subplots=True, figsize=(10,12))
plt.title('2008年至2010年Google股票各个属性的表现')
plt.show()
Timestamps 用于表示时间点. Periods 代表时间间隔.
Periods 可用于检查给定期间内是否有特定事件.
它们也可以转换为彼此的形式。
# 创建一个Timestamp
timestamp = pd.Timestamp(2017, 1, 1, 12)
timestamp
Timestamp('2017-01-01 12:00:00')
# 创建一个period
period = pd.Period('2017-01-01')
period
Period('2017-01-01', 'D')
# 检查给定timestamp是否在给定period内
period.start_time < timestamp < period.end_time
True
# timestamp 转换为 period
new_period = timestamp.to_period(freq='H')
new_period
Period('2017-01-01 12:00', 'H')
# period 转换为 timestamp
new_timestamp = period.to_timestamp(freq='H', how='start')
new_timestamp
Timestamp('2017-01-01 00:00:00')
date_range 是一种返回固定频率datetimeindex
的方法。
当创建自己的时间序列属性——以用于预先存在的数据,或围绕您创建的时间序列属性排列整个数据时,此函数非常有用。
# 创建一个 datetimeindex ,使用日频率(freq 默认是 daily)
dr1 = pd.date_range(start='1/1/18', end='1/9/18')
dr1
DatetimeIndex(['2018-01-01', '2018-01-02', '2018-01-03', '2018-01-04',
'2018-01-05', '2018-01-06', '2018-01-07', '2018-01-08',
'2018-01-09'],
dtype='datetime64[ns]', freq='D')
# 创建一个 datetimeindex ,使用月(month)频率
dr2 = pd.date_range(start='1/1/18', end='1/1/19', freq='M')
dr2
DatetimeIndex(['2018-01-31', '2018-02-28', '2018-03-31', '2018-04-30',
'2018-05-31', '2018-06-30', '2018-07-31', '2018-08-31',
'2018-09-30', '2018-10-31', '2018-11-30', '2018-12-31'],
dtype='datetime64[ns]', freq='M')
# 创建一个 datetimeindex ,并且不指定起始日期,只使用 periods
dr3 = pd.date_range(end='1/4/2014', periods=8)
dr3
DatetimeIndex(['2013-12-28', '2013-12-29', '2013-12-30', '2013-12-31',
'2014-01-01', '2014-01-02', '2014-01-03', '2014-01-04'],
dtype='datetime64[ns]', freq='D')
# 创建一个 datetimeindex ,并且指定起始日期,终止日期与 periods
dr4 = pd.date_range(start='2013-04-24', end='2014-11-27', periods=3)
dr4
DatetimeIndex(['2013-04-24', '2014-02-09', '2014-11-27'], dtype='datetime64[ns]', freq=None)
pandas.to_datetime() 用于将参数转换为日期时间。
在这里,DataFrame
转换为日期时间Series。
df = pd.DataFrame({'year': [2015, 2016], 'month': [2, 3], 'day': [4, 5]})
df
# 转化为时间Series
df = pd.to_datetime(df)
df
0 2015-02-04
1 2016-03-05
dtype: datetime64[ns]
# 转化为Timestamp
df = pd.to_datetime(df)
df
Timestamp('2017-01-01 00:00:00')
我们可以使用可选的时间频率将索引按所需的周期数移动。
可让我们将时间序列与其自身的过去进行比较时,这很有用
google.loc['2008':'2009'].High.plot(legend=True)
google.loc['2008':'2009'].High.shift(10).plot(legend=True,label='移动后High')
plt.show()
Upsampling - 向上采样,时间序列从低频到高频(每月到每天)重新采样。 它涉及填充或内插丢失的数据
Downsampling - 向下采样,时间序列从高频重新采样到低频(每周一次到每月一次)。 它涉及现有数据的汇总。
这里要用一个极其不完整的数据集来展示
pressure = pd.read_csv('/home/kesci/input/djia307822/pressure.csv',
index_col='datetime', parse_dates=['datetime'])
pressure.tail()
可以看到有非常多的缺失值需要我们去填充
pressure = pressure.iloc[1:]
pressure = pressure.fillna(method='ffill')
pressure.tail()
pressure.head(3)
# 向上填充
pressure = pressure.fillna(method='bfill')
pressure.head(3)
解释一下
首先,我们使用 ffill 参数向下填充缺失值。
然后,我们使用 bfill 向上填充缺失值。
# downsampling前查看数据形状
pressure.shape
(45252, 36)
# 使用3日频率进行downsample,这里使用了mean (减少数据量——高频到低频)
pressure = pressure.resample('3D').mean()
pressure.head()
# downsampling后数据形状
pressure.shape
(629, 36)
可以看见,downsample后剩下的行要少得多。
现在,我们将从3天的频率 upsample 到每日频率,即低频到高频
pressure = pressure.resample('D').pad()
pressure.head()
pressure.shape
(1885, 36)
行数再次增加。
如果使用正确,Resample的操作是很酷炫的。
# div为除法,shift()表示向后移动一期,这里是一天,因为是日数据
google['Change'] = google.High.div(google.High.shift())
google['Change'].plot(figsize=(20,8))
plt.figure()
google['Return'] = google.Change.sub(1).mul(100)
google['Return'].plot(figsize=(20,8))
plt.axhline(y=0, color='r', linestyle='-')
plt.show()
# 另一个计算收益的方法
plt.figure()
google.High.pct_change().mul(100).plot(figsize=(20,6),color='b')
google['Return'].plot(figsize=(20,8))
plt.axhline(y=0, color='r', linestyle='-')
plt.show()
# 用差分
google.High.diff().plot(figsize=(20,6))
plt.axhline(y=0, color='r', linestyle='-')
plt.show()
我们将通过归一化两个时间序列再进行比较。
这是通过将所有时间序列的每个时间序列元素除以第一个元素来实现的。
这样,两个系列都从同一点开始,可以轻松进行比较。
# 我们将比较微软和Google的股价
microsoft = pd.read_csv('/home/kesci/input/djia307822/MSFT_2006-01-01_to_2018-01-01.csv', index_col='Date', parse_dates=['Date'])
# 可视化
plt.figure()
google.High.plot()
microsoft.High.plot()
plt.legend(['Google','Microsoft'])
plt.show()
# 标准化并进行比较
# 全部都除以第一行的数据
# 两支股票都从100开始
normalized_google = google.High.div(google.High.iloc[0]).mul(100)
normalized_microsoft = microsoft.High.div(microsoft.High.iloc[0]).mul(100)
# 可视化
plt.figure()
normalized_google.plot()
normalized_microsoft.plot()
plt.legend(['Google','Microsoft'])
plt.show()
您可以清楚地看到Google在一段时间内的表现胜过微软。
Window 函数用于标识子periods,计算子periods的子度量metrics。
Rolling - 大小相同,且滑动步数相同
Expanding - 包含所有先前值
# Rolling window 函数
# Rolling 90天
rolling_google = google.High.rolling('90D').mean()
# 与Rolling前数据进行比较
google.High.plot()
rolling_google.plot()
plt.legend(['High','Rolling Mean'])
plt.show()
可看出,Rolling均值图是原始图的平滑版本。
# Expanding window 函数
microsoft_mean = microsoft.High.expanding().mean()
microsoft_std = microsoft.High.expanding().std()
microsoft.High.plot()
microsoft_mean.plot()
microsoft_std.plot()
plt.legend(['High','Expanding Mean','Expanding Standard Deviation'])
plt.show()
O:代表开盘价
Open H:代表最高价
High L: 代表最低价
Low C: 代表收盘价
OHLC图是显示特定时间段的开盘价,最高价,最低价和收盘价的任何类型的价格图。开盘-高-低-收盘图表(或OHLC图)用作交易工具来可视化和分析证券,货币,股票,债券,商品等随时间的价格变化。
OHLC图可解释当日价格-当今市场的情绪,并通过产生的模式预测未来的价格变化。
OHLC图上的y轴用于价格标度,而x轴是时间标度。在每个单个时间段上,OHLC图都会绘制一个代表两个范围的符号:最高和最低交易价格,以及该单个时间段(例如一天)中的开盘价和收盘价。
在范围符号上,高和低价格范围由主垂直线的长度表示。开盘价和收盘价由刻度线的垂直位置表示,这些刻度线出现在高低垂直线的左侧(代表开盘价)和右侧(代表收盘价)。
可以为每个OHLC图符号分配颜色,以区分市场是“看涨”(收盘价高于开盘价)还是“看涨”(收盘价低于开盘价)。
# 2008六月的OHLC图
trace = go.Ohlc(x=google['06-2008'].index,
open=google['06-2008'].Open,
high=google['06-2008'].High,
low=google['06-2008'].Low,
close=google['06-2008'].Close)
data = [trace]
iplot(data, filename='simple_ohlc')
# 2008年OHLC图
trace = go.Ohlc(x=google['2008'].index,
open=google['2008'].Open,
high=google['2008'].High,
low=google['2008'].Low,
close=google['2008'].Close)
data = [trace]
iplot(data, filename='simple_ohlc')
# 2006-2018年OLHC图
trace = go.Ohlc(x=google.index,
open=google.Open,
high=google.High,
low=google.Low,
close=google.Close)
data = [trace]
iplot(data, filename='simple_ohlc')
这种图表用作交易工具,以可视化和分析证券,衍生工具,货币,股票,债券,商品等随时间的价格变动。尽管烛台图中使用的符号类似于箱形图,但它们的功能不同,不要彼此混淆。
蜡烛图通过使用类似烛台的符号来显示价格信息的多个维度,例如开盘价,收盘价,最高价和最低价。每个符号代表单个时间段(分钟,小时,天,月等)的交易活动。每个烛台符号均沿时间轴绘制在x轴上,以显示一段时间内的交易活动。
蜡烛符号中的主要矩形称为real body,用于显示该时间段的开盘价和收盘价之间的范围。从实体的底部和顶部延伸的线被称为上下阴影(或灯芯)。每个阴影代表所表示的时间段内交易的最高或最低价格。当市场看涨(收盘价高于开盘价)时,机构的颜色通常为白色或绿色。但是,当市场看跌(收盘价低于开盘价)时,机构通常会被涂成黑色或红色。
蜡烛图非常适合检测和预测一段时间内的市场趋势,并且通过每个蜡烛符号的颜色和形状来解释市场的日常情绪很有用。例如,身体越长,销售或购买压力就越大。虽然这是一个非常短的主体,但这表明该时间段内价格变动很小。
蜡烛图通过各种指标(例如形状和颜色)以及烛台图表中可以找到的许多可识别模式,帮助揭示市场心理(买卖双方所经历的恐惧和贪婪)。总共有42种公认的模式,分为简单模式和复杂模式。烛台图表中的这些模式对于显示价格关系很有用,并可用于预测市场的未来走势。您可以在此处找到每个模式的列表和说明。
请记住,蜡烛图不表示开盘价和收盘价之间发生的事件,仅表示两种价格之间的关系。 因此,您无法确定在那个时间段内交易的波动性。
Source: Datavizcatalogue
# 2008三月蜡烛图
trace = go.Candlestick(x=google['03-2008'].index,
open=google['03-2008'].Open,
high=google['03-2008'].High,
low=google['03-2008'].Low,
close=google['03-2008'].Close)
data = [trace]
iplot(data, filename='simple_candlestick')
# 2008蜡烛图
trace = go.Candlestick(x=google['2008'].index,
open=google['2008'].Open,
high=google['2008'].High,
low=google['2008'].Low,
close=google['2008'].Close)
data = [trace]
iplot(data, filename='simple_candlestick')
# 2006-2018蜡烛图
trace = go.Candlestick(x=google.index,
open=google.Open,
high=google.High,
low=google.Low,
close=google.Close)
data = [trace]
iplot(data, filename='simple_candlestick')