作者 :陈卓然 (北京大学) 邮箱 :chenzhr25@mail2.sysu.edu.cn
温馨提示: 文中链接在微信中无法生效。请点击底部 「阅读原文」 。或直接长按/扫描如下二维码,直达原文:
1. 引言 金融时间序列是金融分析中不可或缺的一部分,而在 Python 中,处理金融时间序列的一个强大工具就是 pandas
库。值得一提的是, pandas
的重要作者之一 Wes Mckinney 在创造这个库时,刚好是知名资产管理公司 AQR 的分析师。因此,可以说 pandas
库与生俱来就具备处理金融时间序列的优越性。
本推文将从如下的几个方面展开:
2. 金融数据集 首先让我们加载一些常用的包:
# import packages import numpy as np import pandas as pd from pylab import mpl, plt plt.style.use( "seaborn" ) mpl.rcParams[ 'font.family' ] = 'serif' %matplotlib inline
2.1 数据导入 我们首先使用 pd.read_csv()
导入一份不同金融工具的日末数据 (End-of-Day)。
# open the data filename = 'data/tr_eikon_eod_data.csv' with open(filename, 'r' ) as f: list = f.readlines()[: 5 ] data = pd.read_csv(filename, # Specifies that the first column shall be handled as an index. index_col= 0 , #Specifies that the index values are of type datetime. parse_dates= True )
我们可以很方便地将这份数据进行可视化。
data.plot(figsize = ( 10 , 6 ), subplots = True )
这份数据是来自 Thomson Reuters (TR) Eikon Data API。在 TR 的数据库中,不同的金融产品有着自己对应的代码(Reuters Instrument Codes, RICs)。在我们上面的几种金融产品中,其对于的实际股票名称为:
instruments = [ 'Apple Stock' , 'Microsoft Stock' , 'Intel Stock' , 'Amazon Stock' , 'Goldman Sachs Stock' , 'SPDR S&P 500 ETF Trust' , 'S&P 500 Index' , 'VIX Volatility Index' , 'EUR/USD Exchange Rate' , 'Gold Price' ,
'VanEck Vectors Gold Miners ETF' , 'SPDR Gold Trust' ] for ric, name in zip(data.columns, instruments): print( f" {ric} | {name} " )
VanEck Vectors Gold Miners ETF
2.2 描述性统计 对于 DataFrame
,我们首先可以使用 info()
来对其中的元信息进行窥探,然后使用 describe()
来得到一些有用的描述性统计分析结果。
data.describe().round( 2 )
我们也可以定制化我们需要的统计量,比如说使用 aggregate()
方法来传入多个描述性统计函数。
data.aggregate([min, np.mean, np.std, np.median, np.max]).round()
2.3 时间维度上的变化 统计分析方法往往需要计算一个时间序列在时间层面上面的变化,比如进行差分,百分比变化,或者对数变化。首先是绝对差分,我们可以采用 pandas
中的 diff()
方法:
data.diff().head()
为了消除单位差异,我们往往需要百分比的变化,为此我们可以采用 pandas
中的 pct_change()
:
data.pct_change().round( 3 ).head()
data.pct_change().mean().plot(kind= 'bar' , figsize=( 10 , 6 ))
在金融中我们常常会用到对数转换的方法,在 Python 中我们可以采用如下的方式计算对数收益率:
rets = np.log(data/data.shift( 1 )) rets.head().round( 3 )
计算好对数回报率之后我们便可以计算累计收益率。需要注意的是,我们前面的代码中计算得到的收益率是总的收益率(Total return):
rets.cumsum().apply(np.exp).plot(figsize = ( 10 , 6 ))
2.4 低频向高频转换(重抽样) 重抽样在金融时间序列分析中是一项至关重要的操作,通常采用的是向下抽样方法。具体而言,当我们拥有日度数据时,通常会通过重抽样将其转换为月度或周度数据。在 pandas
库中,我们使用 resample
方法来实现这一目的。需要注意的是,这里的重抽样并非指随机重复抽样,而是将高频数据转换为低频数据的一种技术手段。此过程中,为避免前视偏误,我们要采用如下的参数设定:
data.resample( '1w' , label= 'right' ).last().head()
rets.cumsum().apply(np.exp).resample( '1m' , label = 'right' ).last().plot(figsize = ( 10 , 6 ))
3. 滚动统计量 在这一小节中我们考虑一个时间序列:apple 的股票
sym = 'AAPL.O' data = pd.DataFrame(data[sym]).dropna()
3.1 概览 首先我们先使用 pandas
推导一些简单的滚动统计量。
window = 20 data[ 'min' ] = data[sym].rolling(window=window).min() data[ 'mean' ] = data[sym].rolling(window=window).mean() data[ 'max' ] = data[sym].rolling(window=window).max() data[ 'std' ] = data[sym].rolling(window=window).std() data[ 'median' ] = data[sym].rolling(window=window).median()
ax = data[[ 'min' , 'mean' , 'max' ]].iloc[ -200 :].plot( figsize=( 10 , 6 ), style=[ 'g--' , 'r--' , 'g-.' ], lw= 0.8 ) data[sym].iloc[ -200 :].plot(ax=ax, lw= 2.0 )
3.2 移动平均 这是一个题外话,在金融中的技术分析中,一个古老的方法是观察移动平均线。当短期的移动平均线高于长期的移动平均线,往往传递出的买入的信号,而当长期的移动平均线高于短期的移动平均下,往往传递出的是卖出的信号。
data[ 'SMA1' ] = data[sym].rolling( 42 ).mean() data[ 'SMA2' ] = data[sym].rolling( 252 ).mean() data[[sym, 'SMA1' , 'SMA2' ]].plot(figsize=( 10 , 6 ))
data[ 'positions' ] = np.where(data[ 'SMA1' ]>data[ 'SMA2' ], 1 , -1 )
data[[sym, 'SMA1' , 'SMA2' , 'positions' ]].plot(figsize=( 10 , 6 ), secondary_y= "positions" )
3.3 相关性分析 通常而言,当 S&P500 上涨的时候,VIX 指数会下降,反之亦然。
raw = pd.read_csv( "data/tr_eikon_eod_data.csv" , index_col= 0 , parse_dates= True ) data = raw[[ '.SPX' , '.VIX' ]].dropna()
data.loc[: '2012-12-31' ].plot(figsize=( 10 , 6 ), secondary_y= '.VIX' )
从上图不难看出,VIX 指数和 S&P500 之间存在明显的负相关关系。我们现在将两种指数均做对数化变化。
rets = np.log(data/data.shift( 1 ))
rets = np.log(data/data.shift( 1 )) rets.dropna(inplace= True ) rets.plot(subplots = True , figsize = ( 10 , 6 ))
pd.plotting.scatter_matrix(rets, alpha= 0.2 , diagonal= 'hist' , hist_kwds={ 'bins' : 35 }, figsize=( 10 , 6 ))
3.4 OLS 回归 # implement a linear OLS regression reg = np.polyfit(rets[ '.SPX' ], rets[ '.VIX' ], deg= 1 ) ax = rets.plot(kind= 'scatter' , x= '.SPX' , y= '.VIX' , figsize=( 10 , 6 )) ax.plot(rets[ '.SPX' ], np.polyval(reg, rets[ '.SPX' ]), 'r' , lw= 2 );
我们当然也可以使用标准的OLS回归来进行。
import statsmodels.formula.api as smf rets2 = rets.rename(columns={ ".SPX" : "SPX" , '.VIX' : 'VIX' }) results = smf.ols( "VIX ~ SPX" , data = rets2).fit() print(results.summary())
ax = rets[ '.SPX' ].rolling(window= 252 ).corr( rets[ '.VIX' ]).plot(figsize=( 10 , 6 )) ax.axhline(rets.corr().iloc[ 0 , 1 ], c= 'r' );
4. 小结 本推文介绍了金融时间序列,不难看出 pandas
在分析金融时间序列方面有着重要的用处。
5. 相关推文 Note:产生如下推文列表的 Stata 命令为: lianxh 时间序列
安装最新版 lianxh
命令: ssc install lianxh, replace
朱菲菲, 2023, Stata:导入年度、季度、月度等频数面板数据-xtimportu , 连享会 No.1276.
李亭, 2022, Stata:中断时间序列分析-itsa , 连享会 No.1016. 史柯, 2022, Stata:时间序列数据转换-tstransform , 连享会 No.941. 连享会, 2020, 如何处理时间序列中的日期间隔-(with-gaps)-问题? , 连享会 No.99. 吕媛, 2021, Stata:时变 Granger 因果检验 , 连享会 No.582. 张悦, 2020, Stata:时间序列数据的回归和预测 , 连享会 No.393. 许梦洁, 2020, Stata: 单位根检验就这么轻松 , 连享会 No.96. 许梦洁, 2020, Stata:VAR-中的脉冲响应分析-(IRF) , 连享会 No.92. 张瑞钰, 2021, 知乎热议:纠结-计量经济、时间序列和机器学习 , 连享会 No.585. 🍓 课程推荐: 连享会:结构模型·2025 现场班 嘉宾:谭用,南京财经大学 时间:2025 年 6 月 7-8 日 咨询:王老师 18903405450(微信)
连享会微信小店上线啦! Note:扫一扫进入“连享会微信小店”,你想学的课程在这里······
尊敬的老师 / 亲爱的同学们:
连享会致力于不断优化和丰富课程内容,以确保每位学员都能获得最有价值的学习体验。为了更精准地满足您的学习需求,我们诚挚地邀请您参与到我们的课程规划中来。 请您在下面的问卷中,分享您 感兴趣的学习主题或您希望深入了解的知识领域 。您的每一条建议都是我们宝贵的资源,将直接影响到我们课程的改进和创新。 我们期待您的反馈,因为您的参与和支持是我们不断前进的动力。感谢您抽出宝贵时间,与我们共同塑造更加精彩的学习旅程!https://www.wjx.cn/vm/YgPfdsJ.aspx# 再次感谢大家宝贵的意见!
New! Stata 搜索神器: lianxh
和 songbl
GIF 动图介绍 搜: 推文、数据分享、期刊论文、重现代码 …… 👉 安装: . ssc install lianxh
. ssc install songbl
👉 使用: . lianxh DID 倍分法
. songbl all
🍏 关于我们 直通车: 👉【 百度一下: 连享会 】即可直达连享会主页。亦可进一步添加 「知乎」,「b 站」,「面板数据」,「公开课」 等关键词细化搜索。