社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

Python金融分析系列:金融时间序列

连享会 • 2 周前 • 26 次点击  


👇 连享会 · 推文导航 | www.lianxh.cn

图片
图片

🍓 连享会:2025五一论文班·线上
嘉宾 :连玉君;申广军;董展育;林文炼;杨海生 (中山大学)
时间:2025 年 5 月 2-4 日
咨询:王老师 18903405450(微信)

图片



作者:陈卓然 (北京大学)
邮箱: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}")

RICs
StockName
0
AAPL.O
Apple Stock
1
MSFT.O
Microsoft Stock
2
INTC.O
Intel Stock
3
AMZN.O
Amazon Stock
4
GS.N
Goldman Sachs Stock
5
SPY
SPDR S&P 500 ETF Trust
6
.SPX
S&P 500 Index
7
.VIX
VIX Volatility Index
8
EUR=
EUR/USD Exchange Rate
9
XAU=
Gold Price
10
GDX
VanEck Vectors Gold Miners ETF
11
GLD
SPDR Gold Trust

2.2 描述性统计

对于 DataFrame,我们首先可以使用 info() 来对其中的元信息进行窥探,然后使用 describe() 来得到一些有用的描述性统计分析结果。

data.describe().round(2)

AAPL.O
MSFT.O
INTC.O
AMZN.O
GS.N
SPY
.SPX
.VIX
EUR=
XAU=
GDX
GLD
count
2138
2138
2138
2138
2138
2138
2138
2138
2216
2211
2138
2138
mean
93.46
44.56
29.36
480.46
170.22
180.32
1802.71
17.03
1.25
1349.01
33.57
130.09
std
40.55
19.53
8.17
372.31
42.48
48.19
483.34
5.88
0.11
188.75
15.17
18.78
min
27.44
23.01
17.66
108.61
87.7
102.2
1022.58
9.14
1.04
1051.36
12.47
100.5
25%
60.29
28.57
22.51
213.6
146.61
133.99
1338.57
13.07
1.13
1221.53
22.14
117.4
50%
90.55
39.66
27.33
322.06
164.43
186.32
1863.08
15.58
1.27
1292.61
25.62
124
75%
117.24
54.37
34.71
698.85
192.13
210.99
2108.94
19.07
1.35
1428.24
48.34
139
max
193.98
102.49
57.08
1750.08
273.38
286.58
2872.87
48
1.48
1898.99
66.63
184.59

我们也可以定制化我们需要的统计量,比如说使用 aggregate() 方法来传入多个描述性统计函数。

data.aggregate([min,
                np.mean,
                np.std,
                np.median,
                np.max]).round()

AAPL.O
MSFT.O
INTC.O
AMZN.O
GS.N
SPY
.SPX
.VIX
EUR=
XAU=
GDX
GLD
min
27
23
18
109
88
102
1023
9
1
1051
12
100
mean
93
45
29
480
170
180
1803
17
1
1349
34
130
std
41
20
8
372
42
48
483
6
0
189
15
19
median
91
40
27
322
164
186
1863
16
1
1293
26
124
max
194
102
57
1750
273
287
2873
48
1
1899
67
185

2.3 时间维度上的变化

统计分析方法往往需要计算一个时间序列在时间层面上面的变化,比如进行差分,百分比变化,或者对数变化。首先是绝对差分,我们可以采用 pandas 中的 diff() 方法:

data.diff().head()
Date
AAPL.O
MSFT.O
INTC.O
AMZN.O
GS.N
SPY
.SPX
.VIX
EUR=
XAU=
GDX
GLD
2010-01-01 00:00:00
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
2010-01-04 00:00:00
nan
nan
nan
nan
nan
nan
nan
nan
0.0088
23.65
nan
nan
2010-01-05 00:00:00
0.0528571
0.01
-0.01
0.79
3.06
0.3
3.53
-0.69
-0.0043
-1.35
0.46
-0.1
2010-01-06 00:00:00
-0.487142
-0.19
-0.07
-2.44
-1.88
0.08
0.62
-0.19
0.0044
19.85
1.17
1.81
2010-01-07 00:00:00
-0.0557142
-0.318
-0.2
-2.25
3.41
0.48
4.55
-0.1
-0.0094
-6.6
-0.24
-0.69

为了消除单位差异,我们往往需要百分比的变化,为此我们可以采用 pandas 中的 pct_change()



    
data.pct_change().round(3).head()
Date
AAPL.O
MSFT.O
INTC.O
AMZN.O
GS.N
SPY
.SPX
.VIX
EUR=
XAU=
GDX
GLD
2010-01-01 00:00:00
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
2010-01-04 00:00:00
nan
nan
nan
nan
nan
nan
nan
nan
0.006
0.022
nan
nan
2010-01-05 00:00:00
0.002
0
-0
0.006
0.018
0.003
0.003
-0.034
-0.003
-0.001
0.01
-0.001
2010-01-06 00:00:00
-0.016
-0.006
-0.003
-0.018
-0.011
0.001
0.001
-0.01
0.003
0.018
0.024
0.016
2010-01-07 00:00:00
-0.002
-0.01
-0.01
-0.017
0.02
0.004
0.004
-0.005
-0.007
-0.006
-0.005
-0.006
data.pct_change().mean().plot(kind='bar', figsize=(10,6))

在金融中我们常常会用到对数转换的方法,在 Python 中我们可以采用如下的方式计算对数收益率:

rets = np.log(data/data.shift(1))
rets.head().round(3)
Date
AAPL.O
MSFT.O
INTC.O
AMZN.O
GS.N
SPY
.SPX
.VIX
EUR=
XAU=
GDX
GLD
2010-01-01 00:00:00
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
2010-01-04 00:00:00
nan
nan
nan
nan
nan
nan
nan
nan
0.006
0.021
nan
nan
2010-01-05 00:00:00
0.002
0
-0
0.006
0.018
0.003
0.003
-0.035
-0.003
-0.001
0.01
-0.001
2010-01-06 00:00:00
-0.016
-0.006
-0.003
-0.018
-0.011
0.001
0.001
-0.01
0.003
0.018
0.024
0.016
2010-01-07 00:00:00
-0.002
-0.01
-0.01
-0.017
0.019
0.004
0.004
-0.005
-0.007
-0.006
-0.005
-0.006

计算好对数回报率之后我们便可以计算累计收益率。需要注意的是,我们前面的代码中计算得到的收益率是总的收益率(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=(106), 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=(106))

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=(106))
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())

0
1
2
3
4
5
6
0

coef
std err
t
P>t
[0.025
0.975]
1
Intercept
0.0026
0.001
2.633
0.009
0.001
0.005
2
SPX
-6.6516
0.106
-62.559
0.000
-6.860
-6.443
ax = rets['.SPX'].rolling(window=252).corr(
    rets['.VIX']).plot(figsize=(106))
ax.axhline(rets.corr().iloc[01], c='r');

4. 小结

本推文介绍了金融时间序列,不难看出 pandas 在分析金融时间序列方面有着重要的用处。

5. 相关推文

Note:产生如下推文列表的 Stata 命令为:
  lianxh 时间序列
安装最新版 lianxh 命令:
  ssc install lianxh, replace

  • 专题:Stata命令
    • 朱菲菲, 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

图片

🍏 关于我们

  • 连享会 ( www.lianxh.cn ,推文列表) 由中山大学连玉君老师团队创办,定期分享实证分析经验。
  • 直通车: 👉【百度一下: 连享会】即可直达连享会主页。亦可进一步添加 「知乎」,「b 站」,「面板数据」,「公开课」 等关键词细化搜索。
图片

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/181137
 
26 次点击