最近开始学习用R做数据分析与量化投资,于是写了一篇R语言的入门教程,希望能帮助大家快速上手。我的知乎|简书|CSDN|微信公众号
PurePlay
会不定期分享量化投资与R干货, 欢迎大家关注!
文章目录
- 1.1 安装
- 1.2 获取帮助
- 1.3 工作空间
- 1.4 R文件的输入/输出
- 1.5 变量
- 1.6 运算符
- 1.7 数据容器
- 1.8 plot()绘图
- 1.9 函数
- 1.10 控制结构
- 1.11 实例:下载指定股票价格数据,计算收益率相关性
1. R语言
R是一种开源的解释型脚本语言,多年来在统计学家,数据科学从业人员和学者中非常流行。 它本质上是一种函数式编程语言( functional programming language),同时支持面向对象和命令式编程范例。 R具有数以千计的附加统计和分析库可供下载,在定量金融和学术领域非常受欢迎。
R中的所有内容(包括函数)都是一个对象,可以直接传递给其他函数。
1.1 安装
1.1.1 R安装
进入官网:http://www.r-project.org/。 单击“Getting Started”部分中的下载R链接,或者单击左侧菜单中的“ CRAN”链接。 选择最接近目标计算机所在位置的适当镜像站点。 有关安装R的更多详细说明。
推荐的R代码编辑器:Rstudio,VScode
1.1.2 扩展包安装和载入
R扩展包官方汇总链接:https://mirrors.tuna.tsinghua.edu.cn/CRAN/
(1)安装扩展包
- R与Rstuidio窗口操作均可完成安装,以Rsudio为例:点击Rstudio界面右下角文件区的Packages,点击Install,在弹出对话框中 , 填入需要安装的包
- 命令安装
# 获取R存放已经安装的包的位置,默认位置是R的安装路径下的library文件夹
.libPaths()
# 安装:扩展包名称需要加引号
# destdir:指定下载的二进制zip文件存放的位置,默认是临时会话的downloaded_packages文件夹下
# lib:指定下载的二进制zip软件包被解压后的安装位置,默认值的是.libPaths()获取的路劲
install.packages("ggplot2")
install.packages("ggplot2",
destdir="D:/Download/Package/R",
lib="D:/Program Files/R/R-3.6.1/library")
(2)载入扩展包
-
Rstudio界面:点击Rstudio界面右下角文件区的 Packages,找到你要载入的包 , 在
前面的方框中打上勾 - R界面:点击R界面上方的“程序包”,点击 加载程序包,在弹出的窗口中选择需要,载入的包
- 命令载入
# 扩展包名称可以不加引号
library("ggplot2")
library("ggplot2", lib.loc="C:/Program Files/R/R3.2.2/library")
(3)量化常用扩展包
数据管理:包括数据集抓取、存储、读取、时间序列、数据处理等,涉及的R包有zoo(时间序列对象)、xts(时间序列处理)、timeSeries(Rmetrics系时间序列对象)、timeDate(Rmetrics系时间序列处理)、data.table(数据处理)、quantmod(数据下载和图形可视化)、RQuantLib(QuantLib数据接口)、WindR(Wind数据接口)、RJDBC(数据库访问接口)rhadoop(Hadoop访问接口)、rhive(Hive访问接口)、rredis(Redis访问接口)、rmongodb(MongoDB访问接口)、SparkR(Spark访问接口)、fImport(Rmetrics系数据访问接口)等
指标计算:包括金融市场的技术指标的各种计算方法,涉及的R包有TTR(技术指标)、TSA(时间序列计算)、urca(单位根检验)、fArma(Rmetrics系ARMA计算)、fAsianOptions(Rmetrics系亚洲期权定价)、fBasics(Rmetrics系计算工具)、fCopulae(Rmetrics系财务分析)、fExoticOptions(Rmetrics系期权计算)、fGarch(Rmetrics系Garch模型)、fNonlinear(Rmetrics系非线模型)、fOptions(Rmetrics系期权定价)、fRegression(Rmetrics系回归分析)、fUnitRoots(Rmetrics系单位根检验)等
回测交易:包括金融数据建模,并验证历史数据验证模型的可靠性,涉及的R包有FinancialInstrument(金融产品)、quantstrat(策略模型和回测)、blotter(账户管理)、fTrading(Rmetrics系交易分析)等
投资组合:对多策略或多模型进行管理和优化,涉及的R包有PortfolioAnalytics(组合分析和优化)、stockPortfolio(股票组合管理)、fAssets(Rmetrics系组合管理)等。
风险管理:对持仓进行风险指标的计算和风险提示,涉及的R包有Performance-Analytics(风险分析)、fPortfolio(Rmetrics系组合优化)、fExtremes(Rmetrics系数据处理)
1.2 获取帮助
1.2.1 帮助文档
(1)Rstudio界面
点击Rstudio界面右下角文件区的 Help选项,在最后的搜索框中输入想了解的R包或者函数
(2)R界面
点击R界面的“帮助”,开启一个帮助网页
(3)输入命令
# 获取扩展包信息
help("readr")
? readr
# 获取函数信息
help(read_csv)
? read_csv
#搜索与关键词read_csv相关的帮助文档的信息
help.search('ggplot2')
?? ggplot2
# 获取函数ggplot的使用例子
example("ggplot")
# 给出有关键词ggplot的所有函数
apropos("ggplot",mode="function")
# 打开搜索首页
RSiteSearch("")
# 搜索有关键词ggplot的所有文档和邮件列表存档
RSiteSearch("ggplot")
RSiteSearch("empirical")
# 获取函数源代码
read_csv
# 列出当前已加载包中所含有的所有可用示例数据集
data()
1.2.2 实用网站
R的网页搜索引擎,能查找各种函数、R邮件列表归档中的讨论和博客文章:http://rseek.org
R主要的博客社区:http://www.r-bloggers.com
统计之都:http://cos.name/
Github:http://github.com/
1.3 工作空间
工作空间就是当前R的工作环境
# 获取当前工作空间
getwd()
# 设定工作空间
# 路径用双引号或者单引号,必须完整,斜杠为\\或者/
# 文件夹必须存在,如果不存在,可以用dir.create()函数先创建,但文件夹需要逐个建立。
dir.create('D:/Workfiles/Finance/Quants/R')
setwd('D:/Workfiles/Finance/Quants/R')
list.dirs("D:/Workfiles/Finance/Quants/R") #列出当前工作目录下的文件夹
list.files("D:/Workfiles/Finance/Quants/R") #列出当前工作目录下的文件
ls() #列出当前工作空间中的对象
rm(x) #移除(删除)一个或者多个对象
history(num) #显示最近使用过的num个命令(默认值为25)
savehistory(“aaa”) #保存命令历史到当前路径下文件aaa中(默认值为.Rhistory)
loadhistory(“aaa”) #载入一个命令历史文件aaa(默认值为.Rhistory)
options() ###显示或设置当前选项
q() #退出R或者Rstudio
1.4 R文件的输入/输出
1.4.1 保存文件
利用Rstudio/R界面保存脚本文件;保存其他文件代码如下:
# 将运行结果保存成.R或者.txt文件,相对/绝对路径均可
sink("D:/Workfiles/Finance/Quants/R/try.R")
...program
sink()
# 将工作空间里的对象(结果、变量等)保存成.Rdata
save.image('try.RData')
# 图形文件保存:可输出成pdf/png/jpeg/bmp,方法类似
pdf('xxx.pdf')
...program
dev.off()
1.4.2 打开文件
(1)利用Rstudio/R界面
(2)输入命令
# 打开.R文件/R的脚本文件
file.edit("D:/Workfiles/Finance/Quants/R/1.4如何获得帮助.R",fileEncoding = "UTF-8")
# 运行R脚本文件
source("xxx.R",encoding = "UTF-8")
# 打开.Rdata文件
load('try.RData')
1.5 变量
变量为我们提供了我们的程序可以操作的命名存储。 变量名称由字母(区分大小写),数字和点或下划线字符组成,不允许使用空格或特殊字符。 变量名以字母或不以数字后跟的点开头。
变量名 | 合法性 | 原因 |
---|---|---|
var_name2. | 有效 | 有字母,数字,点和下划线 |
VAR_NAME% | 无效 | 有字符'%'。只有点(.)和下划线允许的。 |
2var_name | 无效 | 以数字开头 |
.var_name, var.name | 有效 | 可以用一个点(.),但启动点(.),不应该后跟一个数字。 |
.2var_name | 无效 | 起始点后面是数字使其无效。 |
_var_name | 无效 | 开头_这是无效的 |
可以使用向左,向右和等于运算符来为变量赋值:
# 等号赋值
var1 = c(0,1,2,3)
# 左赋值
var2 <- c("learn","R")
# 右赋值
c(TRUE,1) -> var3
在R语言中,数据类型有:数值型Numeric
,整型Integer
,复数型Complex
,字符串Character
,逻辑型Logical
,原型Raw
。R中的变量不必声明变量类型,R将动态地找出运行时变量的类型。
展示工作空间中的变量:
# 展示工作空间中的所有变量
ls()
# 展示工作空间中变量名包含“var”的变量
ls(pattern = "var")
# 以点(.)开头的变量默认被隐藏,设置“all.names = TRUE”参数列出
ls(all.name = TRUE)
删除变量:
# 删除指定变量
rm(var1)
# 删除所有变量
rm(list = ls())
1.6 运算符
R语言中拥有如下几种运算符类型:算术运算符,关系运算符,逻辑运算符,赋值运算符等。
1.6.1 算术运算符
下表显示了R语言支持的算术运算符。 操作符对向量的每个元素起作用。
运算符 | 描述 |
---|---|
+ | 两个向量相加 |
- | 两个向量相减 |
* | 两个向量相乘 |
/ | 将第一个向量与第二个向量相除 |
%% | 两个向量求余 |
%/% | 两个向量相除求商 |
^ | 将第二向量作为第一向量的指数 |
1.6.2 关系运算符
下表显示了R语言支持的关系运算符。 将第一向量的每个元素与第二向量的相应元素进行比较。 比较的结果是布尔值。
运算符 | 描述 |
---|---|
> | 检查第一个向量的每个元素是否大于第二向量的相应元素。 |
< | 检查第一个向量的每个元素是否小于第二个向量的相应元素。 |
== | 检查第一个向量的每个元素是否等于第二个向量的相应元素。 |
<= | 检查第一个向量的每个元素是否小于或等于第二向量的相应元素。 |
> = | 检查第一个向量的每个元素是否大于或等于第二向量的相应元素。 |
!= | 检查第一个向量的每个元素是否不等于第二个向量的相应元素。 |
1.6.3 逻辑运算符
下表显示了R语言支持的逻辑运算符。 它只适用于逻辑,数字或复杂类型的向量。 所有大于1的数字被认为是逻辑值TRUE。
将第一向量的每个元素与第二向量的相应元素进行比较。 比较的结果是布尔值。
运算符 | 描述 |
---|---|
& | 它被称为元素逻辑AND运算符。 它将第一向量的每个元素与第二向量的相应元素组合,并且如果两个元素都为TRUE,则给出输出TRUE。 |
| | 它被称为元素逻辑或运算符。 它将第一向量的每个元素与第二向量的相应元素组合,并且如果元素为真,则给出输出TRUE。 |
! | 它被称为逻辑非运算符。 取得向量的每个元素,并给出相反的逻辑值。 |
逻辑运算符&&和|| 只考虑向量的第一个元素,给出单个元素的向量作为输出。
运算符 | 描述 |
---|---|
&& | 逻辑AND运算符。 取两个向量的第一个元素,并且只有两个都为TRUE时才给出TRUE。 |
|| | 逻辑OR运算符。 取两个向量的第一个元素,如果其中一个为TRUE,则给出TRUE。 |
1.6.4 赋值运算符
这些运算符用于向量赋值。
运算符 | 描述 |
---|---|
<− 或= 或<<−
|
左分配 |
-> 或->>
|
右分配 |
1.6.5 其他运算符
这些运算符用于特定目的,而不是一般的数学或逻辑计算。
运算符 | 描述 |
---|---|
: | 冒号运算符。 它为向量按顺序创建一系列数字。 |
%in% | 此运算符用于标识元素是否属于向量。 |
%*% | 此运算符用于将矩阵与其转置相乘。 |
1.7 数据容器
数据容器data container
:向量Vectors
,因子Factors
,列表Lists
,矩阵Matrices
,数据帧Data Frames
,数组Arrays
,
1.7.1 向量Vectors
向量类似一维数组,仅保存类型相同的数据, 如果将数字与字符混合,R会将任何数值的类型转换为字符。运算符c()
用于创建存储数字,字符或布尔值的向量。
first_vector <- c(1,2,3,4,5,6)
second_vector <- c('a', 'b', 'c','d')
third_vector <- c('a', 1, 2, 3)
# 向量合并
new_vector <- c(first_vector,second_vector)
向量索引:
vector <- c(1,2,3,4,5,6,7,8,9)
# 获取向量第四个元素
vector[4]
# 获取第四和第八个元素
# vector[4,8]是错误的
vector[c(4,8)]
# 获取第四到第八个元素
# 第四和第八个元素都会被取出
vector[4:8]
向量化允许我们同时对所有元素执行相同的操作。
vector <- c(1,2,3,4,5,6,7,8,9)
# 向量中所有元素除以3,并保留两位小数
round(vector/3,2)
1.7.2 列表Lists
列表可以同时包含不同类型的元素,如数字、字符串、向量、列表、矩阵、函数等。
myList <- list(a = c(1,2,3,4,5),
b = matrix(1:10, nrow = 2, ncol = 5),
c = data.frame(price = c(89.3, 98.2, 21.2),
stock = c("MOT", "IBM", "CSCO"))
)
通过位置或者元素名索引:
# 返回元素列表
list1 <- myList[1]
list2 <- myList[c(1,3)]
# 返回单个元素
element1 <- myList[[1]]
element2 <- myList[["b"]]
1.7.3 矩阵Matrix
矩阵类似一维数组,只能保存类型相同的数据。
# 按列排列
mat1 <- matrix(c(1,2,3,4,5,6),
nrow=2, ncol=3)
# 按行排列
mat2 <- matrix(c(1,2,3,4,5,6),
nrow=2, ncol=3, byrow=TRUE)
# 定义行名和列名
dimnames(mat2) <- list(c('one','two'),
c('col1','col2','col3'))
# 展示矩阵的特征
attributes(mat2)
索引方法与向量类似,需要增加一个维度
mat2[1,3]
mat2[c(1,2),3]
mat2[1:2,2:3]
mat2[,2:3]
矩阵操作也是向量化的:
# 元素服从标准正太分布的100*10矩阵
mat <- matrix(rnorm(1000),nrow=100)
# 保留三位小数,展示前9行
head(round(mat,3),9)
1.7.4 数据框Dataframe
数据框是一个混合的二维数据容器,可以包含数字,字符,布尔值和因子类型。每当从外部环境将数据读入R时,结果对象最终都可能是 一个数据帧,格式类似于一个Excel表格。
df1 <- data.frame(price = c(89.2, 23.2, 21.2),
symbol = c('MOT','AAPL','IBM'),
action = c('Buy','Sell','Buy'))
数据框索引[,]
, $
df1[1,1]
# dataframe_name $ column_name
df1$symbol
创建数据框时,字符向量将自动转换为因子,它是离散变量的向量。 为了禁止将任何字符向量转换为因子,我们可以使用stringsAsFactors = FALSE
参数。
df2 <- data.frame(price = c(89.2, 23.2, 21.2),
symbol = c('MOT','AAPL','IBM'),
action = c('Buy','Sell','Buy'),
stringsAsFactors = FALSE)
df1$symbol
## [1] MOT AAPL IBM
## Levels: AAPL IBM MOT
df2$symbol
## [1] "MOT" "AAPL" "IBM"
class(df1$symbol)
## [1] "factor"
class(df2$symbol)
## [1] "character"
1.7.5 环境Environment
创建环境空间,定义环境空间中的变量:
env <- new.env()
# [[]]与$均可实现环境空间中的变量定义
env[["first"]] <- 5
env[["second"]] <- 6
env$third <- 7
查看环境空间
env
# 查看环境空间中的变量名
ls(env)
# 获取环境空间中的某一变量
get("first", envir = env)
删除环境空间中的变量
rm("second", envir = env)
ls(env)
环境空间的存储特征:不按值存储对象,而是将对象位置的地址存储在内存中。 由于较大的对象不必在每次传递时都进行复制,因此可以使用更有效的代码。
env1 <- env
env1$third <- 42
get("third", envir = env)
1.8 plot()
绘图
R提供了许多高级的绘图扩展包,如ggplot2
, ggvis
, rCharts
, rgi
等,此处只介绍最基本的plot()
函数绘图。
x <- c(1,2,3.2,4,3,2.1,9,19)
plot(x) # 散点图
plot(x, type = "l") # 折线图
?plot # 查看更多图表类型
绘制一个有标题、横纵轴名称、基本网格的图
plot(rnorm(100), # 正太分布随机数
main = "Some Returns", # 图标题
cex.main = 0.9,
xlab = "Time",# x轴标题
ylab = "Returns", # y轴标题
)
# 添加基本网格
grid()
# 添加水平线与垂直线
abline(v = 40, # x = 40处绘制垂直线
lwd = 2, # 线宽
lty = 1, # 线型
)
abline(h = 1, # y = 1处绘制水平线
lwd = 3,
lty = 3)
# 添加额外的文本
mtext("Some text at the bottom", side = 1)
# 添加图例
legend(50, -1, "A legend")
绘制子图
# 设定2行,2列子图格式
par(mfrow = c(2, 2))
# 第一张图
plot(rnorm(100), main = "Graph 1")
# 第二张图
plot(rnorm(100), main = "Graph 2", type = "l")
# 第三张图
plot(rnorm(100), main = "Graph3", type = "s")
abline(v = 50, lwd = 4)
# 第四张图
plot(rnorm(100), type = "h", main = "Graph4")
# 重置绘图窗口
par(mfrow = c(1,1))
查看绘图所用参数
# 法一
?plot.default
# 法二
formals(plot.default)
1.9 函数
R支持命令式、函数式、面向对象编程。
1.9.1 内置函数
R语言具有大量内置函数,以下展示一些常用内置函数
# 创建标准正态分布随机数
x <- rnorm(100, mean = 0, sd = 1)
# 返回向量长度
length(x)
# 计算均值、方差、中位数
mean(x)
sd(x)
median(x)
# 计算变量值域
range(x)
# 求和/累计求和
sum(x)
cumsum(x)
# 展示前3个元素
head(x, 3)
# 获取描述统计结果
summary(x)
# 将x从大到小排序
sort(x, decreasing = TRUE)
# 计算一阶差分
diff(x)
# 以1为步长创建1至10序列
seq(1, 10, 1)
# 打印:注意两种打印的区别
cat("hello\n")
print("hello\n")
# 展示最近输入的10行命令
history(10)
# 数值计算
sqrt(2)
exp(1)
cos(1)
sin(1)
# 求函数积分
integrand <- function(x) 1/((x+1)*sqrt(x))
integrate(integrand, lower=0, upper=Inf)
1.9.2 自定义函数
自定义函数的基本语法如下
function_name <- function(arg_1, arg_2, ...) {
Function body
return value
}
函数的不同部分
- 函数名称:作为具有此名称的对象存储在R环境中。
- 参数 :当函数被调用时,需要传递具体值到参数。 参数是可选的,一个函数可能不包含参数;参数可以有默认值。
- 函数体 :函数体包含定义函数的功能语句集合。
- 返回值 :返回值即函数的输出。
1.10 控制结构
1.10.1 分支
x = 1
if(x) {
print("true")
} else {
print("false")
}
1.10.2 循环
for(i in 1:5) {
cat(i, "\n")
}
1.11 实例:下载指定股票价格数据,计算收益率相关性
过滤无效的股票代码:
FiltSymbols <- function(symbols) {
# 将小写字母转换为大写
symbols <- toupper(symbols)
# 正则表达式验证证券代码是否有效
valid <- regexpr("^[A-Z]{2,4}$", symbols)
#返回
return(sort(symbols[valid == 1]))
}
symbols <- FiltSymbols(c("xom", "aapl", "cvx","ibm", "GS","600000HS" ))
cat(symbols)
下载股票价格数据:
library("quantmod")
getPrices <- function(symbols) {
# 输入:向量类型的股票代码
# 输出:dataframe,包含多只股票的价格数据
for (i in 1:length(symbols)) {
if (i != 1) {
# 获取第i支股票的价格数据
tempData <- getSymbols(symbols[i], src="yahoo",
from="2007-01-01",to="2017-08-31",
auto.assign = FALSE)
# 将收盘价合并到prices中
prices <- cbind(prices, tempData[,4])
cat(paste("第", i, "支股票下载完成…\r"))
} else {
# 获取第一支股票的价格数据
data <- getSymbols(symbols[i], src="yahoo",
from="2007-01-01",to="2017-08-31",
auto.assign = FALSE)
# 仅保留收盘价
prices <- data[,4]
cat("第1支股票下载完成…\r")
}
}
return(prices)
}
prices <- getPrices(symbols)
print(prices, max = length(symbols)*5)
计算股票收益率相关性:
showCorrelations <- function(prices) {
# 输入:dataframe,股票价格数据
# 输出:相关系数矩阵,两两散点图矩阵
# 将股价转换为对数收益率,参数2表示对列进行计算
returns <- apply(prices, 2, function(x) diff(log(x)))
# 计算相关系数矩阵
print(cor(returns, use = "complete.obs"))
# 绘制两两散点图矩阵
pairs(returns, main = "Pairwise Return Scatter Plot")
}
showCorrelations(prices)
欢迎关注我的知乎|简书|CSDN|微信公众号
PurePlay
, 会不定期分享量化金融与R干货。