Py学习  »  Python

Python金融分析系列-2:数据可视化

连享会 • 1 年前 • 391 次点击  

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

连享会课程 · 2024 Stata 寒假班

相比之前课程的更新内容: 全新的「进阶班」,由中山大学杨海生老师主讲,包括三个全新专题:C1. 政策效应估计;C2. 政策机制分析;C3. 政策效能优化。主要用于回答如下实证研究问题:

  • 一项政策可以通过哪些路径或机制产生效果?最重要的机制是什么?
  • 在 A 地实施的某项政策能否推广到 B 地?适用条件是什么?
  • 现有政策能否优化 (比如调整激励对象、改变激励强度等)?
  • 能否让政策制定兼顾效率和公平性?

显然,主流期刊广泛关注的主题 (如扶贫、限购、税收优惠、数字化、灵活就业等),都可以从上述视角做更深入地挖掘。这为我们选择新的研究切入点提供了广泛的空间:我们不用再疲于奔命寻找新的「政策冲击」,而是深挖「政策作用机制」、「政策优化」、「政策公平性」等更有意思的话题。

进阶班将介绍一组能实现上述研究目标的工具,主要包括:

  • 联邦因果推断和联邦 DID;
  • 高维中介分析、因果路径分析、路径相对重要性分析;
  • 政策学习、基于「多臂 Qini 曲线」的政策公平性评价方法;
  • 适用于连续型政策处理变量的非参数因果推断方法。

作者:陈卓然 (北京大学)
邮箱:chenzhr25@mail2.sysu.edu.cn

编者按:本系列推文在于使用 Python 进行金融分析,部分内容摘译自下文的第三部分 (Part III)。
Source:Hilpisch Y. Python for finance: mastering data-driven finance[M]. O'Reilly Media, 2018. -PDF-

温馨提示: 文中链接在微信中无法生效。请点击底部「阅读原文」。或直接长按/扫描如下二维码,直达原文:


目录

  • 1. 缘起

  • 2. 静态2D图

    • 2.1 一维数据集

    • 2.2. 二维数据集

    • 2.3 其他的绘制方式

  • 3. 静态3D图

  • 4. 交互2D图

    • 4.1 基本绘图

    • 4.2 金融绘图

  • 5. 小结

  • 6. 相关推文



1. 缘起

Use a picture. It’s worth a thousand words. —Arthur Brisbane (1911)

本推文将重点介绍 matplotlibplotly 两个包。其中,matplotlib 只能够绘制一些静态的位图,而对于一些交互式的图,matplotlib 便无能为力了。此时我们应该采用第二种包 plotly 来进行。本推文将从如下几部分展开:

  • 静态 2D 图
  • 静态 3D 图
  • 交互 2D 图

2. 静态2D图

首先导入必要的包:

# import matplotlib
import matplotlib as mpl
# check the version of matplotlib
mpl.__version__
# import the main plotting package with the usual abbreviation plt
import matplotlib.pyplot as plt
# Sets the plotting style to seaborn
plt.style.use("seaborn")
# Sets the font to be serif in all plots.
mpl.rcParams['font.family'] = "serif"

2.1 一维数据集

最基础的,然而也是最强大的绘图函数是 plt.plot(),它需要两个组数据:

  • x 值:横坐标
  • y 值:纵坐标

注意 x 和 y 的值必须能够匹配,例如:

import numpy as np
np.random.seed(1000)
y = np.random.standard_normal(20)
x = np.arange(len(y))
plt.plot(x, y)

注意到如果我们不提供 x 值,plt 将会默认将 index 作为 横坐标:

plt.plot(y)

因为 ndarray 的绝大多数 method 返回的都是 ndarray,因此我们也可以向 plt.plot 中传递一个带有 methodndarray:

plt.plot(y.cumsum())

上述简单的绘图显然无法满足期刊的要求,因此我们需要对其进行一些美化:

plt.plot(y.cumsum())
# turns off the grids
plt.grid(False)
# leads to equal scaling for two axes
plt.axis("equal")

我们也可以对横纵坐标的范围予以限制,为此我们有如下两种方式:

# set the minimum and maximum values of each axis 
plt.plot(y.cumsum())
plt.xlim(-1,20)
plt.ylim(np.min(y.cumsum()) - 1,
         np.max(y.cumsum())+1)

或者:

plt.plot(y.cumsum())
plt.axis([-120, np.min(y.cumsum()) - 1,np.max(y.cumsum())+1])

为了增强可读性,我们也可以为横纵坐标和整个图片加入 label:

# Increases the size of the figure.
plt.figure(figsize=(10,6)
plt.plot(y.cumsum(), "b", lw = 1.5)
# Plots the data as red (thick) dots
plt.plot(y.cumsum(), "ro")
# Places a label on the x-axis.
plt.xlabel("index")
# Places a label on the y-axis.
plt.ylabel("value")
# places a title
plt.title("A simple plot")

2.2. 二维数据集

首先让我们生成一些数据:

y = np.random.standard_normal((20,2)).cumsum(axis=0)

采用相同的方法进行绘制:

# Increases the size of the figure.
plt.figure(figsize=(10,6))
plt.plot(y, lw = 1.5)
# Plots the data as red (thick) dots
plt.plot(y, "ro")
# Places a label on the x-axis.
plt.xlabel("index")
# Places a label on the y-axis.
plt.ylabel("value")
# places a title
plt.title("A simple plot")

当然我们可以加上图例 plt.legend()

plt.figure(figsize=(106))
# Defines labels for the data subsets.
plt.plot(y[:, 0], lw=1.5, label='1st')
plt.plot(y[:, 1], lw=1.5, label='2nd')
plt.plot(y, 'ro')
# Places a legend in the “best” location
plt.legend(loc=0)
plt.xlabel('index')
plt.ylabel('value')
plt.title('A Simple Plot')

假设 y 的第一列为:

y[:,0] = y[:,0]*100
plt.figure(figsize=(106))
# Defines labels for the data subsets.
plt.plot(y[:, 0], lw=1.5, label='1st')
plt.plot(y[:, 1], lw=1.5, label='2nd')
plt.plot(y, 'ro')
# Places a legend in the “best” location
plt.legend(loc=0)
plt.xlabel('index')
plt.ylabel('value')
plt.title('A Simple Plot')

为此我们可以将 y 的两列分别采用不同的轴予以体现,或者将这两列绘制在两个子图上面。一方面,对于第一种方式,我们可以通过如下的方式予以实现:

# define the fig and axis objects
fig, ax1 = plt.subplots()
plt.plot(y[:,0], "b", lw = 1.5, label = "1st")
plt.plot(y[:,0], 'r^')
plt.legend(loc = 8)
plt.xlabel("index")
plt.ylabel(("value 1st"))
plt.title('a simple plot')
# Creates a second axis object that shares the x-axis.
ax2 = ax1.twinx()
plt.plot(y[:,1], 'g', lw = 1.5, label = "2nd")
plt.plot(y[:,1], "ro")
plt.legend(loc = 0)
plt.ylabel("value 2nd")

另一方面对于第二种方式,我们可以采用如下方式:

plt.figure(figsize=(10,6))
# plt.subplot() takes as arguments three integers for
# numrows, numcols, and fignum (either separated by commas or not).
plt.subplot(211)
plt.plot(y[:,0], "b", lw = 2, label = "1st")
plt.plot(y[:,0], 'r>')
plt.legend(loc = 0)
plt.ylabel("value 1st")
plt.title("a simple plot with two y axes")
plt.subplot(2,1,2)
plt.plot(y[:,1], "g", lw = 2, label = "2nd")
plt.plot(y[:,1], 'r)
plt.legend(loc = 0)
plt.ylabel("value 2nd")
plt.xlabel("index")

我们也可以将第二列绘制成柱状图:

plt.figure(figsize=(10,6))
plt.subplot(1,2,1)
plt.plot(y[:,0], 'b', lw = 2, label = "1st")
plt.xlabel("index")
plt.ylabel('value 1st')
plt.title("the first subplot")
plt.legend(loc = 0)
plt.subplot(1,2,2)
plt.bar(np.arange(len(y)), y[:,1], width=0.5,
        color = 'g', label = '2nd')
plt.xlabel('index')
plt.title('the second subplot')
plt.legend(loc = 0)

2.3 其他的绘制方式

2.3.1 散点图

# Creates a larger data set with random numbers.
y = np.random.standard_normal((1000,2))
plt.figure(figsize=(10,6))
plt.plot(y[:,0], y[:,1], 'ro')
plt.xlabel('1st')
plt.ylabel('2nd')
plt.title('Scatter Plot')

我们也可以采用 plt.scatter 的方式,采用这种方式可以引入第三个变量:

c = np.random.randint(0,10,len(y))

plt.figure(figsize=(10,6))
plt.scatter(y[:,0], y[:,1],
            c = c,
            cmap='coolwarm',
            marker='o')
plt.colorbar()
plt.xlabel('1st')
plt.ylabel('2nd')
plt.title('Scatter Plot')

另外一种常用的图是直方图:

plt.figure(figsize=(10,6))
plt.hist(y, label=["1st""2nd"], bins=25)
plt.legend(loc=0)
plt.xlabel('value')
plt.ylabel('frequency')
plt.title('Histogram')
plt.figure(figsize=(106))
plt.hist(y, label=['1st''2nd'], color=['b''g'],
stacked=True, bins=20, alpha=0.5)
plt.legend(loc=0)
plt.xlabel('value')
plt.ylabel('frequency')
plt.title('Histogram')

2.3.2 箱型图

此外在金融中常见的还有箱型图 boxplot

fig,ax = plt.subplots(figsize = (10,6))
plt.boxplot(y)
plt.setp(ax, xticklabels=['1sr''2nd'])
plt.xlabel('data set')
plt.ylabel('value')
plt.title('Boxplot')

2.3.3 数学函数图

绘制一个数学函数图:

def func(x):
    return 0.5 * np.exp(x) + 1
a, b = 0.51.5
x = np.linspace(02)
y = func(x)
Ix = np.linspace(a, b)
Iy = func(Ix)
verts = [(a, 0)] + list(zip(Ix, Iy)) + [(b, 0)]
from matplotlib.patches import Polygon
fig, ax = plt.subplots(figsize=(106))
plt.plot(x, y, 'b', linewidth=2)
plt.ylim(bottom=0)
poly = Polygon(verts, facecolor='0.7', edgecolor='0.5')
ax.add_patch(poly)
plt.text(0.5 * (a + b), 1r'$\int_a^b f(x)\mathrm{d}x$',
horizontalalignment='center', fontsize=20)
plt.figtext(0.90.075'$x$')
plt.figtext(0.0750.9'$f(x)$')
ax.set_xticks((a, b))
ax.set_xticklabels(('$a$''$b$'))
ax.set_yticks([func(a), func(b)])
ax.set_yticklabels(('$f(a)$''$f(b)$'));

3. 静态3D图

在金融中,当考虑波动率曲面的时候,我们可能会考虑波动率对于到期时间和交易期权的行权价格之间的关系。这时便涉及到了三维图的绘制,下面我们将模拟波动率曲面。




    
strike = np.linspace(5015024)
ttm = np.linspace(0.5,2.5,24)
strike, ttm = np.meshgrid(strike, ttm)
iv = (strike - 100)**2/(100*strike)/ttm
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure(figsize=(106))
ax = fig.add_subplot(projection='3d')
surf = ax.plot_surface(strike, ttm, iv, rstride=2, cstride=2,
                       cmap=plt.cm.coolwarm, linewidth=0.5,
                       antialiased=True)
ax.set_xlabel('strike')
ax.set_ylabel('time-to-maturity')
ax.set_zlabel('implied volatility')
fig.colorbar(surf, shrink=0.5, aspect=5);

4. 交互2D图

由于 matplotlib 只能绘制位图,当我们想要绘制交互2D图的时候便需要引入 ployly 包。

4.1 基本绘图

首先导入必要的包。

import pandas as pd
import cufflinks as cf
import plotly.offline as plyo
plyo.init_notebook_mode(connected=True)
a = np.random.standard_normal((2505)).cumsum(axis=0)
index = pd.date_range('2019-1-1',
                      freq = 'B',
                      periods = len(a))
df = pd.DataFrame(100+5*a,
                  index=index,
                  columns=list('abcde'))

cufflinks 可以为 DataFrame 提供一个新的 method:df.iplot()

plyo.iplot(
    df.iplot(asFigure = True),
    image='png',
    filename='ply_01'
)

当然我们也可以加入一些修饰成分。

df[['a''b']].iplot(asFigure=True,
                     theme='polar',
                     title='A Time Series Plot',
                     xTitle='date',
                     yTitle='value',
                     mode={'a''markers' 'b''lines+markers'},
                     symbol={'a''circle''b''diamond'},
                     size=3.5,
                     colors={'a''blue''b''magenta'},
                     )

我们也可以采用相似的方法绘制直方图。

plyo.iplot(
    df.iplot(kind='hist',
    subplots=True,
    bins=15,
    asFigure=True),
    image='png',
    filename='ply_03'
)

4.2 金融绘图

我们下面导入一份真实的数据,这是一份 EUR/USD 汇率的时间序列数据,数据的来源是 FXCM Forex Capital Markets Ltd。

raw = pd.read_csv("data/fxcm_eur_usd_eod_data.csv", index_col=0, parse_dates=True)
raw.info()
quotes = raw[["AskOpen""AskHigh"'AskLow''AskClose']]
quotes = quotes.iloc[-60:]
quotes.tail()

AskOpenAskHighAskLowAskClose
2017-12-25 22:00:001.186671.187911.184671.18587
2017-12-26 22:00:001.185871.191041.185521.18885
2017-12-27 22:00:001.188851.195921.188851.19426
2017-12-28 22:00:001.194261.202561.193691.20092
2017-12-31 22:00:001.200921.201441.199941.20144

在初始化的过程中,QuantFig 对象将会将 DataFrame 对象作为输入项,并允许部分的 customization。然后对于 QuantFig 对象,我们可以应用 qd.iplot() 方法。

qf = cf.QuantFig(
    quotes,
    title = 'EUR/USD Exchange Rate',
    legend = 'top',
    name = 'EUR/USD'
)
qf.iplot(asFigure = True)

我们也可以在此基础上加入 Bollinger Bands

qf.add_bollinger_bands(periods=15, boll_std=2)
qf.iplot(asFigure = True)

5. 小结

本推文着重介绍了 matplotlib 的基本用法,但是 matplotlib 只能用于绘制静态的 2D 或者 3D 图。为了绘制交互的动态图,我们介绍了 plotly,结合 Cufflinks 这一命令能够大大简化我们的绘图,不过后者图片如何导出,仍然是一个较为困难的事情。此外从期刊发表的角度来看,交互的动态图很难放在文章当中,因此 matplotlib 仍然会成为一个重要的绘制工具。

6. 相关推文

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

  • 专题:Python-R-Matlab
    • 周豪波, 2020, Python 调用 API 爬取百度 POI 数据小贴士——坐标转换、数据清洗与 ArcGIS 可视化, 连享会 No.20.
  • 专题:Stata绘图
    • 万莉, 2021, Stata绘图:世行可视化案例-条形图-密度函数图-地图-断点回归图-散点图, 连享会 No.560.
    • 万莉, 2021, Stata绘图:回归系数可视化-论文更出彩, 连享会 No.564.
    • 保瑞, 2021, Stata绘图-组间差异可视化:不良事件火山图、点阵图, 连享会 No.675.
    • 初虹, 2023, 值得收藏!三个Stata可视化绘图网站, 连享会 No.1220.
    • 孙碧洋, 2020, Stata绘图:随机推断中的系数可视化, 连享会 No.471.
    • 左祥太, 2021, Stata可视化:biplot一图看尽方差、相关性和主成分, 连享会 No.814.
    • 张蛟蛟, 2022, Stata绘图-可视化:组间差异比较散点图, 连享会 No.897.
    • 李胜胜, 2023, Stata绘图:balanceplot-系数可视化之平衡性点图, 连享会 No.1252.
    • 林友晖, 2023, Stata绘图:相关系数可视化, 连享会 No.1205.
    • 王胜文, 2022, Stata绘图:COVID-19数据可视化, 连享会 No.1099.
    • 肖蕊, 2022, Stata可视化:能用图形就不用表格, 连享会 No.977.
    • 袁子晴, 2021, forest-森林图:分组回归系数可视化, 连享会 No.651.
    • 谢佳松, 2022, Stata绘图:回归系数可视化-multicoefplot, 连享会 No.956.
    • 陈佳慧, 2023, Stata绘图:mrtab-mrgraph-多元响应变量列表呈现和可视化, 连享会 No.1285.
    • 雷诺, 2023, Stata绘图:confcomptwp-二维系数的置信区间和可比区间可视化, 连享会 No.1257.
  • 专题:交乘项-调节-中介
    • 刘聪聪, 陈点点, 2020, Stata:interflex-交乘项该这么分析!, 连享会 No.121.
    • 邓浩然, 2020, Stata:图示交互效应-调节效应, 连享会 No.383.
  • 专题:公开课
    • 连享会, 2022, 连享会公开课:实证研究中的数据可视化, 连享会 No.880.
  • 专题:其它
    • 高娜娜, 2020, 数据可视化:带孩子们边玩边学吧, 连享会 No.426.
  • 专题:回归分析
    • 连玉君, 2020, Stata:在线可视化模拟-OLS-的性质, 连享会 No.384.
    • 连玉君, 许梦洁, 2020, Stata:系数为何不显著?GIF演示OLS的性质.md, 连享会 No.402.
  • 专题:工具软件
    • 孙法融, 2023, VOSviewer:文献分析软件介绍, 连享会 No.1267.
    • 杨学敏, 2021, 知乎热议:有哪些一用就爱上的可视化工具?, 连享会 No.664.
  • 专题:数据处理
    • 刘亮, 2020, Stata: 约翰霍普金斯大学 COVID-19 疫情数据处理及可视化, 连享会 No.107.
    • 彭甲超, 2021, Stata:边际处理效应及其可视化-mtefe-T309, 连享会 No.128.
  • 专题:结果输出
    • 刘杨, 连玉君, 2020, Stata可视化:让他看懂我的结果!coefplot-arrowplot, 连享会 No.45.
  • 专题:面板数据
    • 韩杰, 2022, Stata绘图:面板数据可视化-panelview, 连享会 No.1035.

课程推荐:Stata2R:针对 Stata 用户的 R 课程
主讲老师:游万海 (福州大学)
课程时间:2023 年 12 月 3/10/17 (三个周日)
🍓 课程主页https://www.lianxh.cn

New! Stata 搜索神器:lianxhsongbl  GIF 动图介绍
搜: 推文、数据分享、期刊论文、重现代码 ……
👉 安装:
. ssc install lianxh
. ssc install songbl
👉  使用:
. lianxh DID 倍分法
. songbl all

🍏 关于我们

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


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