首页 理论教育 基于ggplot的政经数据可视化实例

基于ggplot的政经数据可视化实例

时间:2023-11-19 理论教育 版权反馈
【摘要】:以股票数据为例,尽管K线图和成交量图可直接用原始数据画出,但要想对分析指标作图,却要先把这些指标计算出来。无法下载数据的读者,可直接使用课件中名为"AAPL. csv"的文件。另外,道琼斯指数为"^DJI",纳斯达克指数为"^IXIC",标准普尔500指数为"^GSPC"。src为数据来源,我们选择"yahoo"即可。from和to为数据的日期范围。K线图可分为日K线图、周K线图、月K线图以及以分钟为间隔的K线图等。

基于ggplot的政经数据可视化实例

有时,我们不能直接用原始数据作图,而是需要先计算,再用得到的结果作图。以股票数据为例,尽管K线图和成交量图可直接用原始数据画出,但要想对分析指标作图,却要先把这些指标计算出来。

一、获取数据

在下面的例子中,我们要用quantmod包中的get Symbols函数,从网络上下载股票数据,并绘制图表。无法下载数据的读者,可直接使用课件中名为"AAPL. csv"的文件。

# install.packages(c("quantmod", "TTR"))

library(quantmod) # 用于获取数据

library(TTR) # 用于计算移动平均值等指标

library(cowplot)

library(ggplot2)

library(lubridate) # 使用wday

library(reshape2) # 使用melt

options(scipen=10)

# 下载数据

mydata=get Symbols(Symbols="AAPL", src="yahoo", from="2019-05-06", to=’2019-08-31’, auto.assign=FALSE)

在以上代码中,Symbols参数需指向股票代码。例如,苹果公司的代码为"AAPL",微软公司的代码为"MSFT",深市代码需以".sz"结尾,沪市代码需以".ss"结尾。另外,道琼斯指数为"^DJI",纳斯达克指数为"^IXIC",标准普尔500指数为"^GSPC"。src为数据来源,我们选择"yahoo"(雅虎财经)即可。from和to为数据的日期范围(节假日不会出现在数据中)。auto.assign必须设为FALSE,否则无法生成对象。

# 整理数据

mydata=as.data.frame(mydata)[, -6] # 转化成数据框并去掉不需要的列

mydata=cbind(rownames(mydata), mydata) # 将行标题变为数据中的一列

rownames(mydata)=1: nrow(mydata)

colnames(mydata)=c("Date", "Open", "High", "Low", "Close","Volume")

二、K线图和成交量图

尽管quantmod包提供了chart Series等用于作图的函数,但这些函数生成的图表有时并不能满足我们的要求,所以我们改用ggplot作图。

K线图可分为日K线图、周K线图、月K线图以及以分钟为间隔的K线图等。我们在此只示范日K线图的绘制方法,成交量图常常跟日K线图一起出现,为方便操作,我们使用已保存在硬盘上的文件。

dat=read.csv("AAPL.csv", row.names=1) # 课件中的文件

# 为方便后续操作提取出数据框中的变量

n=nrow(dat)

DA=dat$Date

OP=dat$Open

HI=dat$High

LO=dat$Low

CL=dat$Close

VO=dat$Volume

# 我们不使用日期为X轴变量而是使用1至n的整数以便绘制折线图但这样一来我们就需要手动选择X轴标签我们将只标注周一的日期如果周一无数据,就标注周二的日期

lab_pos=which(wday(as.Date(DA)) %in% c(2, 3)) # 先用wday选出所有周一周二的位置注意在wday的结果中1代表周日2和3代表周一和周二

delete_these=c() # 用for循环删掉紧挨着周一的周二

for (i in 2: length(lab_pos)){

if (lab_pos[i]-lab_pos[i-1]==1) delete_these=append(delete_these, i)

}

if (length(delete_these)>0) lab_pos=lab_pos[-delete_these]

lab=DA[lab_pos]

lab=gsub("\\d\\d\\d\\d\\-", "", lab) # 只保留月和日

lab=gsub("\\-", "\n", lab)

# 其他调整

plot_title=paste(" AAPL [", DA[1], " ~ ", DA[n], "]", sep="")

# 图表标题

rect_fill=rep("limegreen", n) # 生成颜色向量收盘价高于开盘价用绿色表示阳线),收盘价低于开盘价用红色表示阴线)。注意国内外使用这两种颜色的习惯相反

rect_fill[OP>=CL]="red"

bar_fill=rect_fill # 成交量图使用的颜色

# 日K线图中的细线是每日最高价与最低价之间的连线用geom_segment绘制柱体用geom_tile绘制阳线的上端是收盘价下端是开盘价阴线的上端是开盘价下端是收盘价

kline=ggplot()+

geom_segment(aes(x=1: n, xend=1: n, y=LO, yend=HI), color="grey50")+

geom_tile(aes(x=1: n, y=(OP+CL)/2, width=0.7, height=abs(OPCL)), fill=rect_fill, color="grey50")

# 修改附属元素

kline=kline+labs(title=plot_title)+

scale_x_continuous(breaks=lab_pos, labels=lab)+

scale_y_continuous(limits=range(HI, LO))+

theme(

panel.background=element_blank(),

panel.grid=element_blank(),

panel.grid.major.y=element_line(linetype=2, color="grey75"),

axis.title=element_blank(),

axis.text=element_text(size=13),

plot.title=element_text(size=15)

)

# 成交量

bar=ggplot()+

geom_bar(aes(x=1: n, y=VO), stat="identity", fill=bar_fill, width=0.7)+

scale_y_continuous(

labels=function(x) format(x, big.mark=", "),

expand=expansion(0)

)+

geom_text(aes(x=1, y=0.95*max(VO), label="Volume"), color="grey30", size=5, fontface=2, hjust="left", vjust="top")+

theme(

panel.background=element_blank(),

panel.grid=element_blank(),

panel.grid.major.y=element_line(linetype=2, color="grey75"),

axis.title=element_blank(),

axis.text.x=element_blank(),

axis.text.y=element_text(size=13),

axis.line.x=element_line()

)

# 合并K线和成交量

plot_grid(kline, bar, align="v", ncol=1, rel_heights=c(2.5, 1)) # 坐标轴在垂直方向上对齐K线图的高度是条形图的2.5倍

#==========

# 练习把K线图和成交量图改造成互动图表

#==========

# 我们之前已经学过了互动图表的绘制方法现在我们来把上边的图表改造成在鼠标悬停时显示标签并可放置在网页中的互动图表事实上只要使用geom_*_interactive图层就可达到这一目的了图8-2-1

图8-2-1 互动K线图和成交量图

library(ggiraph)

# 生成鼠标悬停时显示的标签

tip=apply(dat, 1, FUN=function(x) paste("Date: ", x[1], "<br>","Open: ", x[2], "<br>", "High: ", x[3], "<br>", "Low: ", x[4], "<br>","Close: ", x[5], "<br>", "Volume: ", x[6], sep=""))

# 分别画出K线图和成交量图注意为了使这两个图表对应起来图层中的data_id应该是一样的

kline=ggplot()+

geom_segment_interactive(aes(x=1: n, xend=1: n, y=LO, yend=HI, tooltip=tip, data_id=1: n), color="grey50")+

geom_tile_interactive(aes(x=1: n, y=(OP+CL)/2, width=0.7, height=abs(OP-CL), tooltip=tip, data_id=1: n), fill=rect_fill, color="grey50")

kline=kline+labs(title=plot_title)+

scale_x_continuous(breaks=lab_pos, labels=lab)+

scale_y_continuous(limits=range(HI, LO))+

theme(

panel.background=element_blank(),

panel.grid=element_blank(),

panel.grid.major.y=element_line(linetype=2, color="grey75"), axis.title=element_blank(),

axis.text=element_text(size=13),

plot.title=element_text(size=15)

)

bar=ggplot()+

geom_bar_interactive(aes(x=1: n, y=VO, tooltip=tip, data_id=1: n), stat="identity", fill=bar_fill, width=0.7)+

scale_y_continuous(

labels=function(x) format(x, big.mark=", "),

expand=expansion(0)

)+

geom_text(aes(x=1, y=0.95*max(VO), label="Volume"), color="grey30", size=5, fontface=2, hjust="left", vjust="top")+(www.xing528.com)

theme(

panel.background=element_blank(),

panel.grid=element_blank(),

panel.grid.major.y=element_line(linetype=2, color="grey75"),

axis.title=element_blank(),

axis.text.x=element_blank(),

axis.text.y=element_text(size=13),

axis.line.x=element_line()

)

# 生成互动图表

final=plot_grid(kline, bar, align="v", ncol=1, rel_heights=c(2.5, 1))

girafe(ggobj=final, pointsize=33, width_svg=8, height_svg=7, options=list(opts_tooltip(use_fill=TRUE)))

二、移动平均线

接下来,我们手动计算一些技术指标,并把它们添加到图表上。

移动平均线是各时段股价的均值连线。

ma5=run Mean(CL, n=5) # 5日均线的数据点均值上每个数据点是当天及前4天的股价的均值我们的数据不包含5月6日之前的数据所以计算结果中的前4个数据点均为缺失值

ma10=run Mean(CL, n=10) # 10日均线的数据点

kline+

geom_line(na.rm=TRUE, aes(x=1: n, y=ma5), color="brown", size=1.2)+

geom_line(na.rm=TRUE, aes(x=1: n, y=ma10), color="purple", size=1.2)

三、KDJ指标

KDJ指标包含K、D、J三个值(图8-2-2)。由于该指标计算步骤比较复杂,我们在此仅给出计算函数,有兴趣的读者可通过查阅相关书籍了解计算原理。

在以下函数中,close、high、low为每日收盘价、最高价、最低价。n为计算起始日期的位置,默认值为9,即,从数据中的第9个交易日开始计算,而前8日的计算结果均为缺失值。first_k和first_d为起始日前一日的K值和D值。在本例中,我们设n=9,第9个交易日为5月16日。查询资料可知,前一日(5月15日)的K值和D值分别为23.71和28.36。如果无资料供查阅,也可使用这两个参数的默认值50。method参数用于设置J值的计算方法,当method=1(默认)时, J=3*K-2*D,这也是新浪财经(https://finance.sina.com.cn/)及一些股票软件采用的计算方法‘;当method=2时,J=3*D-2*K。新浪财经页面上的KDJ图表允许用户设置K、D、J三个值,其中的K值相等于本函数中的参数n,而D和J一般设为3,在本函数中无法修改。

图8-2-2 KDJ指标

get_kdj=function(close, high, low, n=9, first_k=50, first_d=50, method= 1){

get_rsv=function(CLOSE, HIGH, LOW, N){

a=CLOSE-TTR::run Min(LOW, n=N)

b=TTR::run Max(HIGH, n=N)-TTR::run Min(LOW, n=N)

100*a/b

}

rsv=get_rsv(close, high, low, N=n)

num=length(close)

k=rep(NA, num)

d=rep(NA, num)

k[n-1]=first_k

d[n-1]=first_d

for (i in n: num){

ilast=i-1

k[i]=(2*k[ilast]/3)+rsv[i]/3

d[i]=(2*d[ilast]/3)+k[i]/3

}

j=if (method==1) 3*k-2*d else 3*d-2*k

data.frame(Date=1: num, K=round(k, 2), D=round(d, 2), J=round(j, 2))

}

value_kdj=get_kdj(CL, HI, LO, n=9, first_k=23.71, first_d=28.36, method=1)

# 用melt调整数据并作图

value_kdj=melt(value_kdj, id.vars="Date", measure.vars=c("K", "D","J"))

colnames(value_kdj)=c("Date", "KDJ", "Value")

p_kdj=ggplot(value_kdj)+

geom_line(data=value_kdj, na.rm=TRUE, aes(Date, Value, color=KDJ), size=1)+

scale_color_manual(values=c("K"="gold", "D"="skyblue", "J"="purple"),

guide=guide_legend(override.aes=list(size=1.5))

)+

theme_void()+

theme(

legend.position="top",

legend.title=element_text(size=13),

legend.text=element_text(size=13),

panel.background=element_rect(fill="#EBEBEB", color=NA),

panel.grid.major.y=element_line(color="white"),

axis.text.y=element_text(size=13)

)

plot_grid(kline, p_kdj, align="v", ncol=1, rel_heights=c(2.5, 1))

四、布林通道指标

布林通道指标,用三条曲线和一个阴影区域表示:中间线为移动平均线(多取20日均线),上曲线为中间线加上2倍移动标准差,下曲线为中间线减去2倍移动标准差(图8-2-3)。以此方式求得的数据等于用TTR::BBands求得的结果。

# 用自编函数计算指标值。函数中的close为收盘价,n为计算移动平均值使用的天数

get_boll=function(close, n=20){

mave=TTR::run Mean(close, n=n)

add_sd=2*TTR::run SD(close, n=n, sample=FALSE)

data.frame(Date=1: length(close), MA=mave, UPPER=mave+add_sd, LOWER=mave-add_sd)

}

value_boll=get_boll(CL)

# 作图时先画出上曲线和下曲线之间的阴影区域再添加三条线

kline+

geom_ribbon(data=value_boll, na.rm=TRUE, aes(Date, ymin=LOWER, ymax=UPPER), alpha=0.2, fill="skyblue")+ #

geom_line(data=value_boll, na.rm=TRUE, aes(Date, MA), size=1, color="skyblue")+

geom_line(data=value_boll, na.rm=TRUE, aes(Date, UPPER), size=1, color="gold")+

geom_line(data=value_boll, na.rm=TRUE, aes(Date, LOWER), size=1, color="purple")

图8-2-3 布林通道指标

五、MACD指标

MACD指标,用两条曲线和一个条形图来表示(图8-2-4)。

图8-2-4 MACD指标

# 用自编函数计算指标值。函数中的close为收盘价,dif、dea、macd相当于新浪财经上允许用户更改的三个同名参数,分别代表快速移动周期、慢速移动周期和信号周期

get_macd=function(close, dif=12, dea=26, macd=9){

di=TTR::EMA(close, n=dif)-TTR::EMA(close, n=dea)

de=TTR::EMA(di, n=macd)

barline=2*(di-de)

data.frame(Date=1: length(close), DIF=di, DEA=de, MACD= barline)

}

value_macd=get_macd(CL)

barline_color=ifelse(value_macd$MACD>0, "orangered", "palegreen1") #条形图颜色

# 用melt调整数据以便绘制曲线

two_line=melt(value_macd, id.vars="Date", measure.vars=c("DIF","DEA"))

colnames(two_line)=c("Date", "MACD", "Value")

p_macd=ggplot()+

geom_segment(data=value_macd, na.rm=TRUE, aes(x=Date, xend= Date, y=0, yend=MACD), color=barline_color, size=1)+

geom_line(data=two_line, na.rm=TRUE, aes(Date, Value, color= MACD), size=1)+

scale_color_manual(values=c("DIF"="skyblue", "DEA"="purple"),

guide=guide_legend(override.aes=list(size=1.5))

)+

theme_void()+

theme(

legend.position="top",

legend.title=element_text(size=13),

legend.text=element_text(size=13),

panel.background=element_rect(fill="#EBEBEB", color=NA),

panel.grid.major.y=element_line(color="white"),

axis.text.y=element_text(size=13)

)

plot_grid(kline, p_macd, align="v", ncol=1, rel_heights=c(2.5, 1))

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈