• Archive by category "程序算法"

Blog Archives

R语言实现聚类kmeans

R的极客理想系列文章,涵盖了R的思想,使用,cpcp彩票工具 ,创新等的一系列要点,以cpcp彩票我 个人的学习和体验去诠释R的强大。

R语言作为统计学一门语言,一直在小众领域闪耀着光芒。直到大数据的爆发,R语言变成了一门炙手可热的数据分析的利器。随着越来越多的工程背景的人的加入,R语言的社区在迅速扩大成长。现在已不仅仅是统计领域,教育,银行,电商,cpcp彩票互联网 ….都在使用R语言。

要成为有理想的极客,cpcp彩票cpcp彩票我 们 不能停留在语法上,要掌握牢固的数学,概率,统计知识,同时还要有创新精神,把R语言发挥到各个领域。让cpcp彩票cpcp彩票我 们 一起动起来吧,开始R的极客理想。

cpcp彩票关于 作者:

  • 张丹(Conan), 程序员/Quant: Java,R,Nodejs
  • blog: http://whgmhg.com
  • email: bsspirit@gmail.com

转载请注明出处:
http://whgmhg.com/r-cluster-kmeans

前言

聚类属于无监督学习中的一种cpcp彩票方法 ,k-means作为数据挖掘的十大算法之一,是一种最广泛使用的聚类算法。cpcp彩票cpcp彩票我 们 使用聚类算法将数据集的点,分到特定的组中,同一组的数据点具有相似的特征,而不同类中的数据点特征差异很大。PAM是对k-means的一种改进算法,能降低异常值对于聚类效果的影响。

聚类可以cpcp彩票帮助 cpcp彩票cpcp彩票我 们 认识未知的数据,发现新的规律。

目录

  1. k-means实现
  2. PAM实现
  3. 可视化和段剖面图

1. k-means实现

k-means算法,是一种最广泛使用的聚类算法。k-means以k作为参数,把数据分为k个组,通过迭代计算过程,将各个分组内的所有数据样本的均值作为该类的中心点,使得组内数据具有较高的相似度,而组间的相似度最低。

k-means工作原理:

  1. 初始化数据,选择k个对象作为中心点。
  2. 遍历整个数据集,计算每个点与每个中心点的距离,将它分配给距离中心最近的组。
  3. 重新计算每个组的平均值,作为新的聚类中心。
  4. 上面2-3步,过程不断重复,直到函数收敛,不再新的分组情况出现。

k-means聚类,适用于连续型数据集。在计算数据样本之间的距离时,通常使用欧式距离作为相似性度量。k-means支持多种距离计算,还包括maximum, manhattan, pearson, correlation, spearman, kendall等。各种的距离算法的介绍,请参考文章R语言实现46种距离算法

1.1 kmeans()函数实现

在R语言中,cpcp彩票cpcp彩票我 们 可以直接调用系统中自带的kmeans()函数,就可以实现k-means的聚类。同时,有很多第三方算法包也提供了k-means的计算函数。当cpcp彩票cpcp彩票我 们 需要使用kmeans算法,可以使用第三方扩展的包,比如flexclust, amap等包。

本文的系统环境为:

  • cpcp彩票Win 10 64bit
  • R: 3.4.4 x86_64-w64-mingw32

接下来,让cpcp彩票cpcp彩票我 们 做一个k-means聚类的例子。首先,创建数据集。

# 创建数据集
> set.seed(0)
> df <- rbind(matrix(rnorm(100, 0.5, 4.5), ncol = 2),
+             matrix(rnorm(100, 0.5, 0.1), ncol = 2))
> colnames(df) <- c("x", "y")
> head(df)
              x          y
[1,]  6.1832943  1.6976181
[2,] -0.9680501 -1.1951622
[3,]  6.4840967 11.4861408
[4,]  6.2259319 -3.0790260
[5,]  2.3658865  0.2530514
[6,] -6.4297752  1.6256360

使用stats::kmeans()函数,进行聚类。


> cl <- kmeans(df,2); cl
K-means clustering with 2 clusters of sizes 14, 86

Cluster means:                   # 中心点坐标
          x         y
1  5.821526 2.7343127
2 -0.315946 0.1992429

Clustering vector:               # 分组的索引
  [1] 1 2 1 1 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 1 2 2 2 2 2 2 2 2 1 1 2 1 2 1 2 2 2 2 2 2 1 1 2
 [51] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2

Within cluster sum of squares by cluster:   
[1] 316.0216 716.4009                       # withinss,分组内平方和  
 (between_SS / total_SS =  34.0 %)          # 组间的平方和/总平方和,用于衡量点聚集程度

Available components:            # 对象属性
[1] "cluster"      "centers"      "totss"        "withinss"     "tot.withinss" "betweenss"   
[7] "size"         "iter"         "ifault"      

# 查看数据分组情况,第1组86个,第2组14个
> cl$size
[1] 86 14

对象属性解读:

  • cluster,每个点的分组
  • centers,聚类的中心点坐标
  • totss,总平方和
  • withinss,每个分组内的平方和
  • tot.withinss,分组总和,sum(withinss)
  • betweenss,组间的平方和,totss – tot.withinss
  • size,每个组中的数据点数量
  • iter,迭代次数。
  • ifault,可能有问题的指标

1.2 kcca()函数实现
cpcp彩票cpcp彩票我 们 再使用flexclust::kcca()函数,进行聚类。


# 安装flexclust包
> # install.packages("flexclust")
> library(flexclust)

# 进行聚类
> clk<-kcca(df,k=2);clk
kcca object of family ‘kmeans’ 

call:
kcca(x = df, k = 2)

cluster sizes:  # 聚类的分组大小
 1  2 
84 16 

# 聚类的中心
> clk@centers
              x         y
[1,] -0.3976465 0.2015319
[2,]  5.4832702 2.4054118

# 查看聚类的概览信息
> summary(clk)
kcca object of family ‘kmeans’ 

call:
kcca(x = df, k = 2)

cluster info:         # 每个组的基本信息,包括分组数量,平均距离、最大距离、分割值
  size  av_dist max_dist separation
1   84 2.102458 9.748136   3.368939
2   16 3.972920 9.576635   3.189891

convergence after 5 iterations                   # 5次迭代
sum of within cluster distances: 240.1732        # 聚类距离之和

cpcp彩票cpcp彩票我 们 比较2个不同包的k-means算法,所得到的分组数据都是一样的,中心点位置略有一点偏差。接下来,cpcp彩票cpcp彩票我 们 可以把聚类画图。

> plot(df, col = cl$cluster, main="Kmeans Cluster")
> points(cl$centers, col = 1:3, pch = 10, cex = 4) # 画出kmeans()函数效果

从上图中看到k-means的总分2组,每个组的中心点分别用红色十字圆圈和黑色十字圆圈表示,为组内的所有数据样本的均值。再叠加上kcca()函数聚类后的中心点画图。

> points(clk@centers, col = 3:4, pch = 10, cex = 4)  # 画出kcca()函数效果


新的中心点,分别用别用绿色十字圆圈和蓝色十字圆圈表示。虽然cpcp彩票cpcp彩票我 们 使用了相同的算法,分组个数也相同,但中心点还有一些不同的。

这里其实就要对聚类的稳定性进行判断了,有可能是聚类迭代次数过少,就会出现不同的聚类结果,就需要增加迭代次数,达到每次计算结果是一致的。也有可能是因为不同的包,实现的代码有所区别导致的。

k-means算法,也有一些缺点就是对于孤立点是敏感的,会被一些极端值影响聚类的效果。一种改进的算法是PAM,用于解决这个问题。PAM不使用分组平均值作为计算的参照点,而是直接使用每个组内最中心的对象作为中心点。

2. PAM实现

PAM(Partitioning Around Medoids),又叫k-medoids,它可以将数据分组为k个组,k为数量是要事前定义的。PAM与k-means一样,找到距离中心点最小点组成同一类。PAM对噪声和异常值更具鲁棒性,该算法的目标是最小化对象与其最接近的所选对象的平均差异。PAM可以支持混合的数据类型,不仅限于连续变量。

PAM算法分为两个阶段:

  1. 第1阶段BUILD,为初始集合S选择k个对象的集合。
  2. 第2阶段SWAP,尝试用未选择的对象,交换选定的中心点,来提高聚类的质量。

PAM的工作原理:

  1. 初始化数据集,选择k个对象作为中心。
  2. 遍历数据点,把每个数据点关联到最近中心点m。
  3. 随机选择一个非中心对象,与中心对象交换,计算交换后的距离成本
  4. 如果总成本增加,则撤销交换的动作。
  5. 上面2-4步,过程不断重复,直到函数收敛,中心不再改变为止。

优点与缺点:

  • 消除了k-means算法对于孤立点的敏感性。
  • 比k-means的计算的复杂度要高。
  • 与k-means一样,必须设置k的值。
  • 对小的数据集非常有效,对大数据集效率不高。

在R语言中,cpcp彩票cpcp彩票我 们 可以通过cluster包来使用pam算法函数。cluster包的安装很简单,一条命令就安装完了。


> install.packages("cluster")
> library(cluster)

pam()函数定义:


pam(x, k, diss = inherits(x, "dist"), metric = "euclidean",
    medoids = NULL, stand = FALSE, cluster.only = FALSE,
    do.swap = TRUE,
    keep.diss = !diss && !cluster.only && n < 100,
    keep.data = !diss && !cluster.only,
    pamonce = FALSE, trace.lev = 0)

参数列表:

  • x,数据框或矩阵,允许有空值(NA)
  • k,设置分组数量
  • diss,为TRUE时,x为距离矩阵;为FALSE时,x是变量矩阵。默认为FALSE
  • metric,设置距离算法,默认为euclidean,距离矩阵忽略此项
  • medoids,指定初始的中心,默认为不指定。
  • stand,为TRUE时进行标准化,距离矩阵忽略此项。
  • cluster.only,为TRUE时,仅计算聚类结果,默认为FALSE
  • do.swap,是否进行中心点交换,默认为TRUE;对于超大的数据集,可以不进行交换。
  • keep.diss,是否保存距离矩阵数据
  • keep.data,是否保存原始数据
  • pamonce,一种加速算法,接受值为TRUE,FALSE,0,1,2
  • trace.lev,日志打印,默认为0,不打印

cpcp彩票cpcp彩票我 们 使用上面已创建好的数据集df,进行pam聚类,设置k=2。

> kclus <- pam(df,2)

# 查看kclus对象
> kclus
Medoids:                                     # 中心点
     ID         x         y
[1,] 27 5.3859621 1.1469717
[2,] 89 0.4130217 0.4798659

Clustering vector:                           # 分组
  [1] 1 2 1 1 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 1 2 2 2 2 2 2 2 1 1 1 2 1 2 1 2 2 2 2 2 2 1 1 2
 [51] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2

Objective function:                          # 目标函数的局部最小值
   build     swap                           
2.126918 2.124185 

Available components:                        # 聚类对象的属性
 [1] "medoids"    "id.med"     "clustering" "objective"  "isolation"  "clusinfo"   "silinfo"   
 [8] "diss"       "call"       "data"      

> kclus$clusinfo        # 聚类的分组数量,每个组的平均距离、最大距离、分割值
     size  max_diss  av_diss diameter separation
[1,]   15 10.397323 4.033095 17.35984   1.556862
[2,]   85  9.987604 1.787318 15.83646   1.556862

属性解读:

  • medoids,中心点的数据值
  • id.med,中心点的索引
  • clustering,每个点的分组
  • objective,目标函数的局部最小值
  • isolation,孤立的聚类(用L或L*表示)
  • clusinfo,每个组的基本信息
  • silinfo,存储各观测所属的类、其邻居类以及轮宽(silhouette)值
  • diss,不相似度
  • call,执行函数和参数
  • data,原始数据集

把聚类画图输出。

# 画图
> plot(df, col = kclus$clustering, main="Kmedoids Cluster")
> points(kclus$medoids, col = 1:3, pch = 10, cex = 4)

图中,PAM聚类后分为2组,红色一组,黑色一组,用十字圆圈表示2个中心点,可以清晰地看到中心点就是数据点。

cpcp彩票cpcp彩票我 们 可以在开始计算时,设置聚类的中心点,为索引1,2坐标点,打印聚类的日志,查看计算过程。


# 设置聚类的中心为1,2
> kclus2<-pam(df,2,medoids=c(1,2),trace.lev=20)
C pam(): computing 4951 dissimilarities from  100 x 2  matrix: [Ok]
pam()'s bswap(*, s=21.837, pamonce=0): medoids given
  after build: medoids are   1   2
  and min.dist dysma[1:n] are
      0      0   9.79   4.78   3.63   6.15   5.23  0.929   8.44   8.59
   2.29   2.69   4.48   1.19   1.98   2.81   5.39    4.2   3.72   4.56
   1.84   3.99    2.4    2.7   4.84   5.08  0.969   2.01   4.94   5.06
   1.94    7.4   5.19   1.62   3.94   3.12   3.51   0.65   4.46   4.61
   5.16   4.57   1.82   3.21   5.79   4.01   5.59   5.38   1.95    6.2
   2.41   2.09    2.2   2.43   2.24   2.26   2.09   2.39   2.21   2.33
   2.24   2.14   2.45   2.37    2.2   2.37   2.13   2.33   2.25   2.18
   2.38   2.19   2.15   2.14    2.1   2.39   2.24   2.24   2.12   2.14
   2.34   2.18   2.25   2.26   2.33   2.17   2.18   2.12   2.17   2.27
   2.29   2.26   2.38   2.12   2.25   2.33   2.09   2.21   2.24   2.13
   swp new  89 <->   2 old; decreasing diss. 306.742 by -93.214
   swp new  27 <->   1 old; decreasing diss. 213.528 by -1.10916
end{bswap()}, end{cstat()}

# 查看中心
> kclus2$id.med
[1] 27 89

通过日志查看,cpcp彩票cpcp彩票我 们 可以清楚地看到,2个中心的选择过程,分别用89替换1,距离成本减少93.214,用27替换2,距离成本减少1.1。

PAM作为k-means的一种改进算法,到底结果是否更合理,还要看最终哪种结果能够准确地表达业务的含义,被业务人员所认可,就需要不断地和业务人员来沟通。

3. 可视化和段剖面图

cpcp彩票cpcp彩票我 们 实现了聚类计算后,通常需要把复杂的数据逻辑,用简单的语言和图形来解释给业务人员,聚类的可视化就很重要的。如果数据量不太大,参与聚类的指标维度不太多的时候,cpcp彩票cpcp彩票我 们 可以用2维散点图,把指标两两画出来。

cpcp彩票cpcp彩票我 们 对iris数据集,进行k-means聚类分成3组,画出聚类后的2维散点图结果。

> res <- kmeans(iris[,1:4], centers=3)
> pairs(iris, col = res$cluster + 1)


每2个维度就会生成一张图, cpcp彩票cpcp彩票我 们 可以全面直观的看到聚类的效果。

高级画图cpcp彩票工具 ,使用GGally包中的ggpairs()函数。

> library(GGally)
> ggpairs(iris,columns = 1:5,mapping=aes(colour=as.character(res$cluster)))


图更漂亮了而且包含cpcp彩票更多 的信息,除了2维散点图,还包括了相关性检查,分布图,分箱图,频率图等。用这样的可视化效果图与业务人员沟通,一定会非常愉快的。

但是如果数据维度,不止3个而是30个,数据量也不是几百个点,而是几百万个点,再用2维散点图画出来就会很难看了,而且也表达不清,还会失去重点,计算的复杂度也是非常的高。

当数据量和数据维度多起来,cpcp彩票cpcp彩票我 们 就需要用段剖面图来做展示了,放弃个体特征,反应的群体特征和规律。

使用flexclust包中的barchart()函数,画出段剖面图,cpcp彩票cpcp彩票我 们 还是用iris数据集进行举例。


> library(flexclust)
> clk2 <- cclust(iris[,-5], k=3);clk2
kcca object of family ‘kmeans’ 

call:
cclust(x = iris[, -5], k = 3)

cluster sizes:
 1  2  3 
39 61 50 

# 画出段剖面图
> barchart(clk2,legend=TRUE)

如上图所示,每一区块是一个类别,每行是不同的指标。红点表示均值,柱状是这个类别每个指标的情况,透明色表示不重要指标。

查看段剖面图,可以清楚的看到,每个分组中特征是非常明显的。

  • Cluster1中,有39个数据点占26%,Sepal.Width指标在均值附近,其他指标都大于均值。
  • Cluster2中,有61个数据点占41%,Sepal.Width指标略小于均值,其他指标在均值附近。
  • Cluster3中,有50个数据点占33%,Sepal.Width略大于均值,其他指标都小于均值。

从段剖面图,cpcp彩票cpcp彩票我 们 可以一眼就能直观地发现数据聚类后的每个分组的总体特征,而不是每个分组中数据的个体特征,对于数据的解读是非常有cpcp彩票帮助 的。

对于段剖面图,原来cpcp彩票我 并不知道是什么效果。在和业务人员沟通中,发现他们使用SAScpcp彩票软件 做出了很漂亮的段剖面图,而且他们都能理解,后来cpcp彩票我 发现R语言也有这个cpcp彩票工具 函数,图确实能极大地cpcp彩票帮助 进行数据解读,所以写了这篇文章记录一下。

本文介绍了k-means的聚类计算cpcp彩票方法 和具体的使用cpcp彩票方法 ,也是对最近做了一个聚类模型的总结。作为数据分析师,cpcp彩票cpcp彩票我 们 不仅自己能发现数据的规律,还要让业务人员看明白cpcp彩票你 的思路,看懂数据的价值,这也是算法本身的价值。

转载请注明出处:
http://whgmhg.com/r-cluster-kmeans

打赏作者

R语言轻巧的时间包hms

R的极客理想系列文章,涵盖了R的思想,使用,cpcp彩票工具 ,创新等的一系列要点,以cpcp彩票我 个人的学习和体验去诠释R的强大。

R语言作为统计学一门语言,一直在小众领域闪耀着光芒。直到大数据的爆发,R语言变成了一门炙手可热的数据分析的利器。随着越来越多的工程背景的人的加入,R语言的社区在迅速扩大成长。现在已不仅仅是统计领域,教育,银行,电商,cpcp彩票互联网 ….都在使用R语言。

要成为有理想的极客,cpcp彩票cpcp彩票我 们 不能停留在语法上,要掌握牢固的数学,概率,统计知识,同时还要有创新精神,把R语言发挥到各个领域。让cpcp彩票cpcp彩票我 们 一起动起来吧,开始R的极客理想。

cpcp彩票关于 作者:

  • 张丹(Conan), 程序员/Quant: Java,R,Nodejs
  • blog: http://whgmhg.com
  • email: bsspirit@gmail.com

转载请注明出处:
http://whgmhg.com/r-hms/

前言
时间是数据的基本维度,是在做数据处理的时候,必须要掌握的cpcp彩票技术 。根据时间周期的不同,通常把时间分为,年、月、日、时、分、秒、毫秒等。对于年月日的数据是最常见的,也有很多的处理cpcp彩票工具 ,时分秒的数据通常也会用处理日期的cpcp彩票工具 ,这样有时候就不太方便。

hms包,很小很轻,专注于时、分、秒的时间数据处理。

目录

  1. hms包介绍
  2. hms包的使用

1. hms包介绍

hms包,用于存储和格式化时间,基于difftime类型,使用S3的面向对象数据结构。

本文的系统环境为:

  • cpcp彩票Win 10 64bit
  • R: 3.4.2 x86_64-w64-mingw32

安装hms包,非常简单,一条命令就可以了。


~ R
> install.packages("hms")
> library(hms)

函数列表:

  • hms: 创建一个hms类型对象
  • is.hms: 判断是否是hms类型
  • parse_hm: 解析hm值
  • parse_hms: 解析hms值
  • round_hms:四舍五入对齐
  • trunc_hms:裁剪对齐
  • as.hms: hms泛型函数,S3类型,用于隐式调用它的继承函数
  • as.hms.character: character转型hms,用于as.hms的继承调用
  • as.hms.default: hms转型hms,用于as.hms的继承调用
  • as.hms.difftime:difftime转型hms,用于as.hms的继承调用
  • as.hms.numeric: numeric转型hms,用于as.hms的继承调用
  • as.hms.POSIXlt: POSIXlt转型hms,用于as.hms的继承调用
  • as.hms.POSIXt: POSIXt转型hms,用于as.hms的继承调用
  • as.character.hms: hms转型character,用于as.character的继承调用
  • as.data.frame.hms: hms转型data.frame,用于as.data.frame的继承调用
  • as.POSIXct.hms: hms转型POSIXct,用于as.POSIXct的继承调用
  • as.POSIXlt.hms: hms转型POSIXlt,用于as.POSIXlt的继承调用
  • format.hms: 格式化hms,用于format的继承调用
  • print.hms: 打印hms对像,用于print的继承调用

从函数列表可以看到,hms包的功能很单一,就在做数据类型和数据变型,是底层的数据结构包,设计思路与zoo包的设计思路一致。zoo包的详细介绍,请参考文章R语言时间序列基础库zoo

hms包中,有大量的as.xxx()函数、format.hms()函数和print.hms()函数,是被用于S3类型函数继承调用的,是不需要cpcp彩票cpcp彩票我 们 在写程序的时候显示调用的。S3数据结构详细介绍,请参考文章R语言基于S3的面向对象编程

2. hms包的使用

接下来,cpcp彩票cpcp彩票我 们 找几个重点函数进行介绍。

2.1 hms()函数
hms()函数,用于创建一个hms类型的对象。
函数定义:

hms(seconds = NULL, minutes = NULL, hours = NULL, days = NULL)

hms()函数,接收4个参数,分别对应秒,分,时,日。

创建hms对象


# 创建12:34:56的时间对象
> a1<-hms(56, 34, 12);a1
12:34:56

# 创建 10日12:34:56的时间对象
> a2<-hms(56, 34, 12,10);a2
252:34:56

打印结果的第一位252=10*24+12。

2.2 is.hms: 判断是否是hms类型


# 判断是否是hms类型
> is.hms(a1)
[1] TRUE

# 查看hms类型,父类是difftime类型
> class(a1)
[1] "hms"      "difftime"

# 查看hms的属性
> attributes(a1)
$units
[1] "secs"

$class
[1] "hms"      "difftime"

# 查看hms对象的静态数据结构
> str(a1)
Classes 'hms', 'difftime'  atomic [1:1] 45296
  ..- attr(*, "units")= chr "secs"

# 查看面向对象类型
> library(pryr)
> otype(a1)
[1] "S3"

2.3 as.xxx.hms:把hms转型到其他类型


# 默认转型
> as.hms(a1)
12:34:56

# hms转型character,实际会隐式调用as.character.hms()函数
> as.character(a1)
[1] "12:34:56"

# hms转型POSIXct
> as.POSIXct(a1)
[1] "1970-01-01 12:34:56 UTC"

# hms转型POSIXlt
> as.POSIXlt(a1)
[1] "1970-01-01 12:34:56 UTC"

由于cpcp彩票cpcp彩票我 们 没有定义as.Date.hms()函数,所以as.Date()函数,不能认识hms类型的转换。


# hms转型Date
> as.Date(a1)
Error in as.Date.default(a1) : 不知如何将'a1'转换成“Date”类别
Error during wrapup: cannot open the connection

自己定义一个as.Date.hms()函数,仅用于转型实验,没有实际业务意义。


# 函数定义
> as.Date.hms<-function(hms){
+   s<-paste(Sys.Date(),' ',hms,sep="")
+   as.Date(s)
+ }

# 显示调用函数
> as.Date.hms(a1)
[1] "2018-12-14"

# 隐式调用函数
> as.Date(a1)
[1] "2018-12-14"

2.4 as.hms.xxx:把其他类型转型到hms


# 把字符串转hms
> as.hms('19:13:14')
19:13:14
# 非法时间字符串转型
> as.hms('19:78:14')
NA

# 数字转型
> as.hms(111312)
30:55:12

# 时间转型
> as.hms(Sys.time())
14:22:59.462795

# 日期转型,同样发生了错误
> as.hms(Sys.Date())
Error: Can't convert object of class Date to hms.
Error during wrapup: cannot open the connection

2.5 parse_hms()/parse_hm()字符串解析

parse_hms对字符串进行转型,对比parse_hms()与as.hms()结果一样的。


# 执行parse_hms
> parse_hms("12:34:56.789")
12:34:56.789
> as.hms("12:34:56.789")
12:34:56.789

# 执行parse_hm
> parse_hm("12:34")
12:34:00
> as.hms("12:34")
NA

打印parse_hms 函数名,查看源代码实现。


> parse_hms 
function (x) {
as.hms(as.difftime(as.character(x), format = "%H:%M:%OS",
units = "secs"))
}
>environment: namespace:hms<

parse_hms()函数,实际就是调用了as.hms()函数。

2.6 round_hms/trunc_hms
round_hms()函数,是把时间进行四舍五入对齐。


# 按秒,以5的倍数进行对齐,四舍五入
> round_hms(as.hms("12:34:51"), 5)
12:34:50
> round_hms(as.hms("12:34:54"), 5)
12:34:55
> round_hms(as.hms("12:34:56"), 5)
12:34:55
> round_hms(as.hms("12:34:59"), 5)
12:35:00

# 按秒,以60的倍数对齐
> round_hms(as.hms("12:34:56"), 60)
12:35:00

trunc_hms()函数,是把时间进行裁剪对齐。


# 按秒去掉末位,以5的倍数进行对齐
> trunc_hms(as.hms("12:34:01"), 5)
12:34:00
> trunc_hms(as.hms("12:34:44"), 5)
12:34:40
> trunc_hms(as.hms("12:34:56"), 60)
12:34:00

2.7 在data.frame中插入hms列


# 创建data.frame
> df<-data.frame(hours = 1:3, hms = hms(hours = 1:3))
> df
  hours      hms
1     1 01:00:00
2     2 02:00:00
3     3 03:00:00

# 查看df的静态结构
> str(df)
'data.frame':	3 obs. of  2 variables:
 $ hours: int  1 2 3
 $ hms  :Classes 'hms', 'difftime'  atomic [1:3] 3600 7200 10800
  .. ..- attr(*, "units")= chr "secs"

hms包很轻巧很简单,但却可以快速提高cpcp彩票帮助 cpcp彩票cpcp彩票我 们 处理时分秒数据,这些基础函数库是需要cpcp彩票cpcp彩票我 们 完全掌握和熟练运用的。

转载请注明出处:
http://whgmhg.com/r-hms/

打赏作者

算法,如何改变命运

架构师的信仰系列文章,主要介绍cpcp彩票我 对系统架构的理解,从cpcp彩票我 的视角描述各种cpcp彩票软件 应用系统的架构设计思想和实现思路。

从程序员开始,到架构师一路走来,经历过太多的系统和应用。做过手机cpcp彩票游戏 ,写过编程cpcp彩票工具 ;做过大型Web应用系统,写过cpcp彩票公司 内部CRM;做过SOA的系统集成,写过基于Hadoop的大数据cpcp彩票工具 ;做过外包,做过电商,做过团购,做过支付,做过SNS,也做过移动SNS。以前只用Java,然后学了PHP,现在用R和Javascript。最后跳出IT圈,进入金融圈,研发量化交易cpcp彩票软件 。

架构设计就是定义一套完整的程序规范,坚持架构师的信仰,做自己想做的东西。

cpcp彩票关于 作者:

  • 张丹(Conan), 程序员R,Nodejs,Java
  • weibo:@Conan_Z
  • blog: http://whgmhg.com
  • email: bsspirit@gmail.com

转载请注明出处:
http://whgmhg.com/architect-algorithm/

前言

近年来,随着大数据的飞跃式的发展,已经越来越深地开始影响到cpcp彩票cpcp彩票我 们 的cpcp彩票生活,社交有腾讯大数据,购物有阿里大数据,cpcp彩票搜索 有百度大数据,出行有滴滴大数据等等。当数据越来越多地被积累,就需要算法来挖掘出数据的价值。特别是进入到大数据时代,算法显得越来越重要。

让死的数据变得有价值,就是算法的力量。进入到全民大数据的时代后,数据已经不再是门槛儿,最重要的是算法,算法才是真正能够创造生产力的地方。算法工程师的价值也会越来越大,但是cpcp彩票你 们真的发掘出来cpcp彩票你 们的价值了吗?

目录

  1. 算法在各个cpcp彩票行业 的应用
  2. 投身于哪个cpcp彩票行业 好?
  3. 金融最靠谱

1. 算法在各个cpcp彩票行业 的应用

大数据的兴起冲击着各行各业,带来机遇也带来挑战,没有数据cpcp彩票你 就没有核心价值。当有了数据作为基础,cpcp彩票你 要继续需要思考如何让数据变的有价值。过去的2016年的投资市场很惨淡,唯有人工智能大火了一把。从深度挖掘(Deep Learning)cpcp彩票技术 在图像识别领域的精确识别,迭代决策树(GBDT)在数据挖掘算法比赛中频繁获奖,到AlphaGo在围棋领域打败在人类选手,百度小度机器人在最强大脑的舞台上挑战人类脑王等等,这些事件都是算法领域的突破。

算法,真的已经应用到了各行各业,在慢慢地改变着人们的cpcp彩票生活和习惯,比如说图像识别,自动驾驶,用户行为,金融征信,量化投资等领域,都在发生着变化。

图像识别领域,深度学习算法异军突起,不仅可以进行准确的人脸识别、指纹识别,还可以进行复杂的图像对比。cpcp彩票我 深刻记得,2016年参加的光谷人工智能大会上,听西安电子科技cpcp彩票大学 公茂果教授分享的“深度神经网络稀疏特征学习与空时影像变化检测”主题,利用图像识别cpcp彩票技术 ,对比汶川地震前后的卫星照片和光感照片,准确地找到了受到地震影响最严重的区域,即震前和震后地貌发生变化最大的区域,快速地为救援队定位到最需要cpcp彩票帮助 的地点,解救伤者,投放救援物资。

自动驾驶领域,可以通过识别路面的状况来实现自动驾驶、自动停车。Uber无人驾驶汽车已经在匹兹堡上路测试,自动驾驶汽车配备了各式传感器,包括雷达、激光扫描仪以及高分辨率摄像头,以便绘制周边环境的细节。自动驾驶汽车有望改善人类的cpcp彩票生活质量,也可挽救数百万人的性命,为人们提供cpcp彩票更多 的出行方便。5年前,cpcp彩票我 在听Andrew Ng的斯坦福cpcp彩票大学 机器学习公开课的时候,就被当时的自动驾驶cpcp彩票视频 介绍所震撼,科幻电影中的世界就快变成现实了。

用户行为分析,人类有各种各样的行为和需求。衣食住行,吃喝玩乐,都是人的最基本的行为。大多数人的行为是共性的,商家可以收集这些行为数据,通过数据挖掘算法来找到人们行为共性的规律。根据用户的购物行为,商家可以为用户cpcp彩票推荐 喜欢的商品,这样就有了cpcp彩票推荐 系统; 根据用户对信息的查询行为,可以发现用户对信息的需求,这样就有了cpcp彩票搜索 引擎;根据用户位置的变化,可以发现用户的出行需求,这样就有了地图应用;针对用户个性化的行为,可以给用户打上标签,用来标注用户的特征或身份,这样就有了用户画像。用户行为分析,让商家了解用户习惯,同时也让用户了解自己,有巨大的商业价值。

在金融领域也有很多,算法应用的场景。

金融征信领域,传统信贷业务都是银行核心业务,但由于中国人数众多且小客户居多,银行无法负担为小客户cpcp彩票服务 的高成本,导致民间信贷的兴起。2014年底cpcp彩票互联网 金融P2P的开始爆发,贷款需求被满足的同时,却暴露出了违约风险。征信体系缺失,导致很多P2Pcpcp彩票公司 坏账率很高,到2016年底P2P跑路的多达数千家。征信需求,变得非常迫切。比如,某个人想买车但现金不够,这时就需要进行贷款。商家给用户进行贷款时,通过信用风险的评级就能判断出这个用户的还款能力,从而来决定给他贷多少钱,以什么周期还款,减少违约风险。支付宝的芝麻信用分,是目前被市场一致认可的信用评分模型。

量化投资领域,cpcp彩票我 认为这个领域最复杂的,最有挑战性的,同时也是最有意思的。可以通过量化算法模型实现cpcp彩票赚钱 ,是最容易变现的一种cpcp彩票方法 。在金融投资领域中,有各式各样的数据,反应的各种金融市场的规则,有宏观数据,经济数据,股票数据,债券数据,期货数据,还有新闻数据,情绪数据等等,金融宽客(Quant)通过分析各种各样的数据,判断出国家的经济形势和个股的走势,进行投资组合算法,实现投资的盈利。

看到这里,cpcp彩票我 想问问大家,cpcp彩票你 们脑子里那些聪明的想法,有没有被金融cpcp彩票行业 的魅力撩出些许的荷尔蒙?

2. 投身于哪个cpcp彩票行业 好?

从上面各个cpcp彩票行业 的算法应用来说,都有很广阔的应用前景。作为一个算法的研究者,那cpcp彩票cpcp彩票我 们 究竟投身到哪个cpcp彩票行业 更好呢?

这个其实要从多个方面进行考虑,cpcp彩票cpcp彩票我 们 的目标是个人价值最大化。那么,cpcp彩票你 要选择一个自己能够接触到的、完全竞争的、短流程的渠道,利用cpcp彩票你 的算法cpcp彩票技术 和对业务的理解实现变现的过程。

其实,满足个人可变现的渠道其实非常有限,cpcp彩票你 很难通过一个图像识别的算法,直接面向市场进行收钱,cpcp彩票你 需要有一个承载的cpcp彩票产品 ,而cpcp彩票产品 研发的过程是非常漫长的。同样地,自动驾驶算法需要汽车生产场商的实验。用户行为分析算法,需要电子商务平台的以用户购买行为进行验证。

量化投资,可以用个人账号在中国二级投资交易市场,完成交易过程。这种方式没有很多的中间环节,cpcp彩票你 获得交易所的数据,自己编写算法模型,然后用自己的钱去交易,完全自己把握。只要算法有稳定的收益率,cpcp彩票你 就可以赚到钱。这种变现cpcp彩票方法 ,其实就是量化投资,从金融的角度才是最靠谱的一种变现cpcp彩票方法 。

3. 金融最靠谱

作为IT人,cpcp彩票cpcp彩票我 们 懂编程,懂算法,只要再了解金融市场的规则,就能去金融市场抢钱了。中国的金融二级投资交易市场,是一个不成熟的市场,同时又是情绪化的市场。市场中,每天都存在着大量的交易机会,每天都会有“乌龙指”。量化投资的cpcp彩票技术 ,可以cpcp彩票帮助 cpcp彩票cpcp彩票我 们 发现这些由于信息不对称出现的机会,赚取超额的收益。

那么到底怎么做量化投资呢?。

下面举个例子,一个私募基金,募集了1亿资金准备杀入金融市场。基金经理决定按照投资组合的建模思路,对各类金融资产进行组合配置。下图就反应了各类资产,以均值-方差的标准来创建投资组合,符合资本资产定价模型(CAPM)的原理。cpcp彩票关于 资本资产定价模型详细介绍,请参考文章R语言解读资本资产定价模型CAPM

图中,x轴为收益率的标准差,y轴为收益率的均值,图中的点构建了可投资区域,每个点代表一个可投资cpcp彩票产品 ,每条虚线连接的点的集合,就是一个有效的投资组合。

对于,图中近百个点来说,假设每次要配置5种资产做投资组合,那么就是75287520种组合cpcp彩票方法 ;如果配置10种资产,可选方案就是一个非常大的数字了。

cpcp彩票我 可以用R语言来计算一下,投资组合的数量。


# 100个选5个,做组合
> choose(100,5) 
[1] 75287520

# 100个选10个,做组合
> choose(100,10) 
[1] 1.731031e+13

对于金融市场来说,有非常多的金融资产可供cpcp彩票cpcp彩票我 们 来选择。中国A股股票有3000多只,基金2000多支, 债券3000多支,期货100多支,还有大综商品,货币市场cpcp彩票产品 ,汇率cpcp彩票产品 ,海外投资市场等。如果把这个多种的资产进行组合,将有无限多的投资组合可以进行选择,是一个无限大的计算量。cpcp彩票cpcp彩票我 们 需要利用算法进行组合cpcp彩票优化 ,从而找到市场上最优的投资组合。算法本身,才是最能体现价值的部分。

那么传统的基金是如何进行投资组合的?大多都是靠投资经理的主观投资经验来完成的。在金融市场里,每支基金都配置了不同的资产做组合,cpcp彩票cpcp彩票我 们 随便找支基金看看,它的投资组合是如何配置的。比如,华夏成长(000001.OF)基金,它是股债混合型的。数据来源于万得, 2017年2月8日的数据。

从业绩表现来看,这支基金最辉煌的时代在2006-2007年,连续6个月回报101.49%,那么最低1年表现就比较差,为仅落后于沪深300指数,整体排名也都在后面。今年以来收益率0.58%,同类排名144/507;1年收益率-1.45%,同类排名400/487;3年收益11.67%,同类排名378/426;5年收益39.96%,同类排名290/352。

cpcp彩票cpcp彩票我 们 再来看一下,这支基金的组合成分,主要是股票和债券。

债券占比 :

证券名称 占净值比 近3月涨跌
12石化01 2.34%↑ -0.49%
116国泰君安CP008 2.12%↑ -0.03%
116农发01 1.91%↑ -0.08%
110营口港 1.70%↑ -1.59%
109常高新 1.62%↑ -0.65%

股票占比:

证券名称 占净值比 近3月涨跌
中工国际 4.09%↑ -0.95%
中国医药 3.85%↑ 0.34%
神雾环保 3.81%↑ 2.56%
东方网络 2.89%↑ -13.00%
立讯精密 1.52%↑ -1.82%
高能环境 1.42%↑ -14.96%
上汽cpcp彩票集团 1.38%↑ 7.88%
田中精机 1.31%↑ -12.28%
cpcp彩票上海 医药 1.25%↑ 5.39%
中牧股份 1.21%↑ -4.25%

从市场上几千支的股票和债券中进行选择,并配置不同的权重,之前都是基金经理干的活,那么cpcp彩票cpcp彩票我 们 用算法一样也可以干,说不定用算法模型构建的组合业绩会更好。如果cpcp彩票cpcp彩票我 们 用算法模型,取代了年薪几百万的基金经理,那么cpcp彩票你 就能够获得这个收益。最终实现个人价值,从而用算法改变命运。所以,通过金融变现才是最靠谱的。

转载请注明出处:
http://whgmhg.com/architect-algorithm/

打赏作者

R语言解读资本资产定价模型CAPM

用ITcpcp彩票技术 玩金融系列文章,将介绍如何使用ITcpcp彩票技术 ,处理金融大数据。在cpcp彩票互联网 混迹多年,已经熟练掌握一些ITcpcp彩票技术 。单纯地在cpcp彩票互联网 做开发,总觉得使劲的方式不对。要想靠cpcp彩票技术 养活自己,就要把cpcp彩票技术 变现。通过“跨界”可以寻找新的机会,创造cpcp彩票技术 的壁垒。

金融是离钱最近的市场,也是变现的好渠道!今天就开始踏上“用ITcpcp彩票技术 玩金融”之旅!

cpcp彩票关于 作者:

  • 张丹(Conan), 程序员R,Nodejs,Java
  • weibo:@Conan_Z
  • blog: http://whgmhg.com
  • email: bsspirit@gmail.com

转载请注明出处:
http://whgmhg.com/finance-capm

前言

伴随2016年中国金融交易市场的跌宕起伏,风险越来越不确定,利率持续走低,理财等无风险资产收益持续下降的情况,唯有投资组合才能让cpcp彩票cpcp彩票我 们 的资产保值、增值。根据资本资产定价模型(CAPM),通过对金融数据的分析,构建投资组合,cpcp彩票帮助 cpcp彩票cpcp彩票我 们 在有效的市场中控制风险、稳定收益。

本文将深入浅出地介绍资本资产定价模型,从理论到建模,再到程序现实。资本资产定价模型反应的是资产的风险与期望收益之间的关系,风险越高,收益越高。当风险一样时,投资者会选择预期收益最高的资产;而预期收益一样时,投资者会选择风险最低的资产。

由于本文为非金融教材类文章,所以当出现与教课书不符的描述,请以教课书为准。本文力求用简化的语言,来介绍自资本资产定价模型的知识,同时配合R语言的实现。

目录

  1. 故事背景
  2. 资本市场线
  3. 资本资产定价模型
  4. 用R构建投资组合模型
  5. Beta VS Alpha

1. 故事背景

1952年,马科维茨(Markowitz)提出了投资组合选择理论,他认为最佳投资组合应当是,风险厌恶特征的投资者的无差异曲线和资产的有效边界线的交点。投资者在选择资产时会在收益和风险之间做出平衡:当风险一样时,会选择预期收益最高的资产;而预期收益一样时,会选择风险最低的资产。

01

图1 投资组合选择示意图

到1964年,威廉-夏普(William Sharp),约翰-林特纳(John Lintner)与简-莫森(Jan Mossin)则在马科维茨基础上提出的单指数模型,将市场组合引入均值-方差模型,极大地简化了计算,他们认为获得了市场任意资组合的收益与某个共同因素之间是有线性关系,最终将其发展为资本资产定价模型(Capital Asset Pricing Model, CAPM)。从马科维茨的投资组合选择理论,发展到资本资产定价模型经历了一个漫长的过程。

简单一句话概括,资本资产定价模型的核心思想,资产价格取决于其获得的风险价格补偿。

假设条件

资本资产定价模型,是基于一系列假设条件而成立的。但这些条件,可能并不符合现实的标准,资本资产定价模型也一度遭到质疑。

  • 资产可以无限分割。
  • 不存在交易成本和个人所得税。
  • 可以无限卖空。
  • 存在一种无风险利率,投资者在此利率水平下,可以无限制地贷出和借入任意数额的资金。
  • 投资者是价格接受者,市场是完全竞争的。
  • 投资者是理智的,通过比较资产的期望收益和方差来作出投资决策,在相同预期收益下会选择风险最小的资产。
  • 投资者在相同的投资期限出作出决策,而市场信息是公开免费的,并可以及时获得。
  • 投资者对市场中的经济变量有相同的预期,他们对任意资产的预期收益率、市场风险的看法是一致的。

资本资产定价模型的核心假设是认为市场满足完全、无摩擦和信息完会对称的条件,市场中的投资人都是Markowitz理论中的理性经济人。

2. 资本市场线

由于涉及到金融专业领域,有几个概念是cpcp彩票cpcp彩票我 们 应该提前知道的。

  • 风险资产:风险资产是指具有未来收益能力的资产,但收益率不确定且可能招致损失,比如股票、债券等。
  • 无风险资产:没有任何风险或者风险非常小的资产,有确定的收益率,并且不存在违约的风险。
  • 收益率:指从投资开始到投资结束时,所获得的投资回报率。
  • 无风险收益率:无风险资产,所产生的投资回报率。
  • 投资组合:由投资人或金融机构所持有的股票、债券、基金、衍生金融cpcp彩票产品 等组成的集合,目的在于分散风险。
  • 杠杆交易:就是利用小资金来进行数倍于原始金额的投资,以期望获取相对投资标的物波动的数倍收益率的盈利或亏损。

2.1 风险资产

对于风险资产来说,cpcp彩票cpcp彩票我 们 可以用预期收益和风险,通过二维的坐标来进行描述。

对上图的解释:

  • X轴,为风险
  • y轴,为收益率
  • 灰色区域,为金融资产可投资区域
  • 黑色线,为有效投资边界
  • A和B点,为2个风险资产

A和B有相同的x值,表示具有相同的风险。B点在A点上面,表示B的收益率高于A。对于理性的投资者来说,如果只在A点和B点之间做投资选择,那么大家都会投资到B点,而不投资于A点。

2.2 无风险资产

在下图中,cpcp彩票cpcp彩票我 们 加入无风险资产,来比较无风险资产和风险资产的关系。

对上图的解释:

  • B点,为1个风险资产,在有效投资边界上
  • C点,为无风险资产,在y轴上
  • X轴,为风险
  • y轴,为收益率
  • 灰色区域,金融资产为可投资区域
  • 黑色线,为有效投资边界

C点为无风险资产,他的位置在图示的y轴上,这时x为0,即风险为0。cpcp彩票cpcp彩票我 们 可以把投资,分配到C点或B点上。如果都投到C点,那么cpcp彩票cpcp彩票我 们 将获得的是R0部分的无风险收益;如果都投到B点,那么cpcp彩票cpcp彩票我 们 需要承担σB的风险,同时获得RB的风险收益。如果cpcp彩票cpcp彩票我 们 把资金,一部分投资到B点对应的风险资产上,另一部分投资到C点对应的无风险资产上,那么将构成一个由B和C资产组成的投资组合,而且风险和收益部分,将体现在B和C的连线上。

2.3 最优组合

那么,有没有最优的投资组合呢?收益最大、风险最小。下面就让cpcp彩票cpcp彩票我 们 来,发现这个最优的组合M。

对上图的解释:

  • M点,为最优组合的风险资产
  • B点,为1个风险资产,在有效投资边界上
  • C点,为无风险资产,在y轴上
  • X轴,为风险
  • y轴,为收益率
  • 灰色区域,金融资产为可投资区域
  • 黑色线,为有效投资边界

假设有最优的组合,在上图中M点处,当cpcp彩票cpcp彩票我 们 把C和M进行连线,使得CM的连线与灰色区域相切。从图上看,CM的连线会比任意的C与可投资区域点的连线斜率都要大,比如C和B的连线。cpcp彩票cpcp彩票我 们 取CB的连线的延长线,在CB的延长线上找到,与M具有相同x的点B’,这时M与B’风险相同,M点在B’点的上面,所以M点的收益率大。也就是说,当风险相同的时候,cpcp彩票cpcp彩票我 们 都会选择收益率最大的资产。

不论从可投资区域中怎么选取,M点都是斜率最大的点,那么cpcp彩票cpcp彩票我 们 可以认为,M点为市场上各资产的最优的投资组合.

对于最优的投资组合,其实不管投资者的收益风险的偏好是什么样子的,只要找到了最优的风险资产组合,再加上无风险的资产,就可以为投资者获得最佳的投资方案了。那么对于理性的投资者,如果发现了最优的组合,他们只会投资于这个组合,这时与收益和风险偏好无关。

M点构建的投资组合,一般是由所有可投资证券cpcp彩票产品 组成的,每种证券资产构成的比例,为证券的相对市值。无风险资产C,并没有包括在M中,人们都会选择CM的连接线进行投资,来构建最优的投资组合。

在实际的市场交易中,金融资产的价格会发生偏离,因为价格受市场的供需关系所影响,当价格发生偏离后,市场会自动修复会回均衡价格水平。

2.4 资本市场线

对于CM的连线,就是马科维茨提出了投资组合选择理论,风险厌恶特征的投资者的无差异曲线和资产的有效边界线的交点。这条线就叫,资本市场线(Capital Market Line)。

资本市场线是指表明有效组合的期望收益率和标准差之间的一种简单的线性关系。

资本市场线决定了证券的价格。因为资本市场线是证券有效组合条件下的风险与收益的均衡,如果脱离了这一均衡,则就会在资本市场线之外,形成另一种风险与收益的对应关系。

2.5 投资组合构建

资本市场线,就是cpcp彩票cpcp彩票我 们 最优的投资组合,当cpcp彩票cpcp彩票我 们 发现这个投资组合,所有资金都会投到这个组合上。通过对无风险资产C和风险资产M分配不同的投资权重,cpcp彩票cpcp彩票我 们 可以自己配置出自己想要的风险和收益来,同时可以利用金融cpcp彩票工具 来加杠杆放大风险和收益的范围。

如果cpcp彩票cpcp彩票我 们 把投资者分成,风险厌恶型和风险激进型。

对于风险厌恶型,他们对于资金安全有非常高的要求,不追求高收益但求本金安全,这些资金通常都是用来cpcp彩票生活的。那么在为这些资金做资产配置方案的时候,可以把一部分资金配置无风险资产上,同时少量资金配置到M点的最优组合上,保证低风险并获得少量收益。

如图中CM1点,如果配置50%的风险资产M和50%的无风险资产C,来实现投资组合。公式如下:

CM1 = 0.5C + 0.5M

对于风险激进型,他们对于资金有非常高的收益要求,本金可以部分或全部损失,这些资金通常都是“闲钱”,就是用来进行投资活动的。那么在为这些资金做资配置方案时,可以全部都投到M上,再激进点,可以通过借钱、融资的方式,增加杠杆,把资金放大进行投资。这种操作风险会随着杠杆的放大剧增,当然同时cpcp彩票你 也会有更大的收益。

如图中CM2点,落在了CM的延长线上。cpcp彩票cpcp彩票我 们 可以配置150%的风险资产M,同时用50%的钱去抵押以无风险资产C的收益率去借钱。公式如下:

CM2 = -0.5C + 1.5M

2.6 风险和收益的关系

上面cpcp彩票cpcp彩票我 们 描述风险和收益的关系,主要是从思路上定性介绍,没有进行定量描述,那么究竟风险和收益从数学上怎么进行定义呢。

对上图的解释:

  • M点,为最优组合的风险资产
  • C点,为无风险资产,在y轴上
  • r0,为无风险资产的收益率
  • rM,为M点的收益率
  • x轴,σp为风险资产的收益率的方差
  • y轴,rp为收益率

根据威廉-夏普所引入的均值-方差模型,极大地简化了计算,就是解决了公式计算的问题。用方差来刻画风险,建立收益和风险的一元线性关系。可以用下面公式来表示:

公式

E(rm) – r0 = A * σM^2

公式解释:

  • E(rm):市场投资组合的预期收益率
  • r0:无风险收益率
  • E(rm)–r0, 市场投资组合的风险溢价
  • σM^2: 市场投资组合方差Var(rM)
  • A:风险厌恶水平

有了公式,cpcp彩票cpcp彩票我 们 就明确的知道了,风险和收益的定量关系,并且可以利用数据来进行计算。

3. 资本资产定价模型

对于市场的投资组合,风险溢价和市场投资组合的方差成线性关系。但对于单个资产来说,收益和风险是市场投资组合组成的一分部,受市场共同变化的影响。

3.1 单个资产风险溢价

对于单个资产的风险来说,在资本资产定价模型中,用β来进行表示。β是衡量单个金融资产与市场收益的共同变化程度,通过协方差来计算。单个资产的风险为,当前资产与投资组合收益率的协议差,除以投资组合收益率的方差。

单个资产的风险的计算公式:


βi = Cov(ri, rm) / Var(rm) 
   = Cov(ri, rm) /  σm^2

单个资产的风险溢价的计算公式:


E(ri) – rf = (Cov(ri, rm) / σm^2)*[E(rm) – rf] 
           =  βi  *  [E(rm) – rf]

对公式的解释:

  • E(ri),为风险资产i的预期收益
  • E(rm),为市场投资组合的预期收益
  • rf,为无风险资产收益
  • Cov(ri, rm),为风险资产收益率和市场投资组合收益率的协议差
  • Var(rm),为市场投资组合的收益率的方差

从公式可以看出,单个资产的风险溢价与市场投资组合M的风险溢价成正比,受β影响。

3.2 资本资产定价模型

资本资产定价模型,是现化金融学中的基石理论。在上述假设条件下,可以推到出资本资产定价模型的具体公式。整个和推到过程,就是上面文章介绍的过程,从后人学习的角度看,这个理论比较简单的,仅用到了简单地统计学知识,但是前人却花了很长的时间研究和探索。

判断单个资产的风险时,当β=1时,则说明当前资产与整个市场的趋势是完全保持一致的;当β为2时,代表高风险,其回报的变化将大于市场大盘的变化幅度;当β为0.5时,代表是低风险的资产配置。

3.3 2种风险

在资本资产定价模型,定义了2种风险,即系统性风险和非系统性风险。

系统性风险,就是由外部因素引起的风险,比如:通货膨胀,GDP,重大政治事件等等。这一类事件对于资产收益率的影响不能通过组合本身来消除的,所以这一类风险对于投资者来说是无法回避的。

非系统性风险,就是组合内部结构引起的风险,比如:A股与B股高度相关,A股的收益率出现大幅波动的时候,B股也会出现相似幅度的波动,波峰叠加或波谷叠加,就会增加整个组合的风险;反之,如果A与B为负相关,则A与B的波动就会相互抵消。这样,风险是由组合里的资产类型决定的,所以通过多样化分散的投资策略,无论在理论还是实际上,这种风险都是可以最小化甚至消除的。而这个消除的过程中,整个投资组合的收益率是不会下降的。

3.4 2种收益

与风险相对应是收益,cpcp彩票cpcp彩票我 们 承受了2种风险的同时,也获得了风险所带来的收益。一部分是与市场完全相关收益部分,即beta(β)收益;另一部分与市场不相关的收益部分,即alpha(α)收益。

  • beta收益,相对容易获得,例如,cpcp彩票你 看好一个市场,可以持有成本低廉的对应市场的指数基金,等待市场上涨。
  • alpha收益,比较难获得,alpha是体现投资水平的策略收益。

alpha是,投资组合的实际期望收益与预期收益之间的差。计算alpha的公式为:


E(ri) – rf = αi + βi  *  [E(rm) – rf]
αi         = [E(ri) – rf] -  βi * [E(rm) – rf]

alpha是衡量投资人投资水平的,cpcp彩票cpcp彩票我 们 举个例来说明。比如:市场收益率为14%,A证券的β=1.2,短期国债利率6%,投资者对这只股票的进行了交易,获得的实际收益为17%,那么cpcp彩票cpcp彩票我 们 怎么判断投资人的水平呢?

首先,先求出A证券的预期收益率 = 6% + 1.2*(14-6)% = 15.6%,再用投资者实际收益减去A证券预期收益 17% – 15.6% = 1.4%。最后获得的1.4%就是alpha,表示投资者能力,可以额外获得1.4%的收益。

3.5 资本资产定价模型的应用场景

进行组合投资分散风险:投资者可以按市场组合的构成比例分散持有多种风险资产,使持有的风险资产组合最大限度地接近市场组合,以达到消除非系统风险的目的。

调整收益风险比例:将无风险资产与风险资产市场组合进行再组合,以获得所希望的个性化的风险收益组合。

指数化投资:将资产配置在与某一指数相同的权重的投资cpcp彩票方法 ,通过微调权重或成分,获得比指数更好的alpha。

资产定价:资本资产定价模型可以用来判断有价证券或其他金融资产的市场价格是否处于均衡水平,是否被高估或低估,以便通过套利活动获取超额收益。

基金购买:举一个贴近市场的例子,当cpcp彩票cpcp彩票我 们 要购买基金时,也可以用到资本资产定价模型帮cpcp彩票cpcp彩票我 们 分析。比如,基金A的期望收益率12%,风险β=1,基金B期望收益率13%,β=1.5。市场期望收益率11%,无风险资产收益率r0 = 5%。 那么哪只基金更值得买?

当cpcp彩票你 每天打开支付宝,看到里面的各种基金cpcp彩票推荐 。cpcp彩票你 就会发现这是一个实际的问题。如果cpcp彩票你 懂学了本文,按照资本资产定价模型的思路,其实就是求alpha,哪个基金的alpha高,就买哪个。

求alpha,cpcp彩票cpcp彩票我 们 就直接套用公式。


αA = 12 – 5 – 1 * [11 - 5] = 1%
αB = 13 – 5 – 1.5* [11 -5 ] = -1%

基金A的alpha为1%,而基金B的alpha为-1%。结论就很明显,基金A的管理人能力很好,超额收益1%;而基金B的管理人,就差一些,盈利低于市场1%。所以,cpcp彩票cpcp彩票我 们 会投资基金A,而不会投资基金B。

4. 用R构建投资组合模型

花了大量的篇幅介绍了资本资产定价模型的原理,对于程序实现其实是相当简单地。因为R语言中,已经把资本资产定价模型相关的计算函数都封包好了,cpcp彩票cpcp彩票我 们 仅仅是调用就能完成整个的计算过程。

R语言程序实现,cpcp彩票cpcp彩票我 们 主要会用到2个包,quantmod和PerformanceAnalytics。对于为什么要用R语言,可以参考文章R语言为量化而生

  • quantmod,用于cpcp彩票下载 数据。
  • PerformanceAnalytics,用于进行各种评价指标计算。

cpcp彩票cpcp彩票我 们 设计一个应用场景,假如cpcp彩票我 有10万美金想投资于美国的股市,cpcp彩票我 想获得比标普好(SP500)的投资收益,那么cpcp彩票我 应该如何购买股票。

首先,cpcp彩票cpcp彩票我 们 先想清楚,cpcp彩票我 的最终的目标是“比标普好的投资收益”。其次,cpcp彩票cpcp彩票我 们 基于资本资产定价模型理论基础,从投资组合角度思考投资策略,而不是cpcp彩票技术 指标的角度。比标普好,那么cpcp彩票cpcp彩票我 们 就需要以标普指数做为理想投资组合。然后,cpcp彩票cpcp彩票我 们 去市场上选择几个股票,分别计算出收益率,beta,alpha等指标,判断是否符合的预期,反复测试,直到找到合适的股票或股票组合。

本文只是案例介绍,用于说明投资思路和cpcp彩票方法 ,不购成任何的股票cpcp彩票推荐 。

本文的系统环境

  • cpcp彩票Win 10 64bit
  • R version 3.2.3 (2015-12-10)

从yahoocpcp彩票下载 IBM,GE(通用电器),YHOO(Yahoo)的3只股票,从2010年01月01日的日行情数据,同时cpcp彩票下载 标普指数(SP500)的日行情数据。

下面代码并不完整,但思路已经给出,请大家不要太随意地张嘴要数据和代码,毕竟写一篇文章非常辛苦。如果cpcp彩票你 想直接用cpcp彩票我 的代码,请扫文章下面二维码,请作者喝杯咖啡吧。 :_D

执行R语言程序。


# 加载程序包
> library(quantmod) 
> library(PerformanceAnalytics)

# 从yahoocpcp彩票下载
3只股票的数据,和SP500的数据
> getSymbols(c('IBM','GE','YHOO','^GSPC'), from = '2010-01-01')

# 打印前6行和后6行数据
> head(GSPC)
              open    high     low   close     volume adjusted
2010-01-04 1116.56 1133.87 1116.56 1132.99 3991400000  1132.99
2010-01-05 1132.66 1136.63 1129.66 1136.52 2491020000  1136.52
2010-01-06 1135.71 1139.19 1133.95 1137.14 4972660000  1137.14
2010-01-07 1136.27 1142.46 1131.32 1141.69 5270680000  1141.69
2010-01-08 1140.52 1145.39 1136.22 1144.98 4389590000  1144.98
2010-01-11 1145.96 1149.74 1142.02 1146.98 4255780000  1146.98

> tail(GSPC)
              open    high     low   close     volume adjusted
2016-12-20 2266.50 2272.56 2266.14 2270.76 3298780000  2270.76
2016-12-21 2270.54 2271.23 2265.15 2265.18 2852230000  2265.18
2016-12-22 2262.93 2263.18 2256.08 2260.96 2876320000  2260.96
2016-12-23 2260.25 2263.79 2258.84 2263.79 2020550000  2263.79
2016-12-27 2266.23 2273.82 2266.15 2268.88 1987080000  2268.88
2016-12-28 2270.23 2271.31 2249.11 2249.92 2392360000  2249.92

# 画出SP500的K线图
> barChart(GSPC)

把4个品种的调整后的价格进行合并。


> # 改列名
> names(IBM)<-c("open","high","low","close","volume","adjusted")
> names(GE)<-c("open","high","low","close","volume","adjusted")
> names(YHOO)<-c("open","high","low","close","volume","adjusted")
> names(GSPC)<-c("open","high","low","close","volume","adjusted")

# 数据合并
> dat=merge(IBM$adjusted,GE$adjusted,YHOO$adjusted,GSPC$adjusted)
> names(dat)<-c('IBM','GE','YHOO','SP500')

# 打印前6行
> head(dat)
                IBM       GE  YHOO   SP500
2010-01-04 112.2859 12.27367 17.10 1132.99
2010-01-05 110.9295 12.33722 17.23 1136.52
2010-01-06 110.2089 12.27367 17.17 1137.14
2010-01-07 109.8274 12.90920 16.70 1141.69
2010-01-08 110.9295 13.18724 16.70 1144.98
2010-01-11 109.7680 13.31435 16.74 1146.98

计算每日收益率,合并收益率到dat_ret


> dat_ret=merge(IBM_ret,GE_ret,YHOO_ret,SP500_ret)
> names(dat_ret)<-c('IBM','GE','YHOO','SP500')
> head(dat_ret)
                    IBM           GE         YHOO        SP500
2010-01-04  0.009681385  0.015111695  0.009445041 0.0147147759
2010-01-05 -0.012079963  0.005177994  0.007602339 0.0031156762
2010-01-06 -0.006496033 -0.005151320 -0.003482298 0.0005455205
2010-01-07 -0.003461515  0.051779935 -0.027373267 0.0040012012
2010-01-08  0.010034759  0.021538462  0.000000000 0.0028817272
2010-01-11 -0.010470080  0.009638554  0.002395150 0.0017467554

定义无风险收益率为4%,计算4个资产的平均年化收益率。


# 无风险收益率
> Rf<-.04/12

# 计算平均年化收益率,平均年化标准差,平均年化Sharpe 
> results<-table.AnnualizedReturns(dat_ret,Rf=Rf)
> results
                               IBM      GE    YHOO   SP500
Annualized Return           0.0345  0.1108  0.1257  0.1055
Annualized Std Dev          0.1918  0.2180  0.3043  0.1555
Annualized Sharpe (Rf=84%) -2.8892 -2.3899 -1.6911 -3.3659

统计指标分析,每个资产有1760个样本点,没有NA值。日最小收益率,YHOO最小为-0.0871。日最大收益率,在GE为0.1080。算数平均,几何平均,方差,标准差都是YHOO最大。


# 计算统计指标
> stats
                      IBM        GE      YHOO     SP500
Observations    1760.0000 1760.0000 1760.0000 1760.0000
NAs                0.0000    0.0000    0.0000    0.0000
Minimum           -0.0828   -0.0654   -0.0871   -0.0666
Quartile 1        -0.0060   -0.0065   -0.0098   -0.0039
Median             0.0002    0.0004    0.0005    0.0005
Arithmetic Mean    0.0002    0.0005    0.0007    0.0004
Geometric Mean     0.0001    0.0004    0.0005    0.0004
Quartile 3         0.0067    0.0077    0.0112    0.0053
Maximum            0.0567    0.1080    0.1034    0.0474
SE Mean            0.0003    0.0003    0.0005    0.0002
LCL Mean (0.95)   -0.0004   -0.0001   -0.0002    0.0000
UCL Mean (0.95)    0.0008    0.0012    0.0015    0.0009
Variance           0.0001    0.0002    0.0004    0.0001
Stdev              0.0121    0.0137    0.0192    0.0098
Skewness          -0.5876    0.3084    0.0959   -0.3514
Kurtosis           4.6634    4.7294    2.9990    4.0151

画出IBM股票,日收益和月收益的图,4个资的累积收益率图,并对4个资产做相关性分析。

IBM股票,每日收益图

IBM股票,每月收益图

4个品种的累积收益率图

从上图中可以看出,红线(GE)和蓝线(SP500)的走势基本稳合,说明GE在从2010开始在跟着美国经济持续发展。绿线(YHOO)从2013初到2015年初大幅拉升,领先于SP500很多,说明这段时期YHOO所处的cpcp彩票互联网 cpcp彩票行业 ,带来了非常大的市场红利;从2015年到2016年,又下跌很大,大起大落,受市场影响非常敏感。黑线(IBM)大部分时间都处于SP500的下方,说明美国经济这几年的高速发展,并没有给IBM带来很大的发展空间。如果从cpcp彩票cpcp彩票我 们 的目标来说,”比标普好的投资收益”那么cpcp彩票cpcp彩票我 们 只能选择GE或YHOO。

相关性分析

对4个品种进行相关性分析,发现GE和SP500相关系数为0.78,是3只股票中最相关的。而YHOO是与其他3个品种走势最不一样的。

最后,以SP500为市场组合,分别计算出3只股票的alpha和beta。


# 计算alpha
> CAPM.alpha(dat_ret[,1:3],dat_ret[,4],Rf=Rf)
                      IBM           GE         YHOO
Alpha: SP500 -0.000752943 0.0003502332 0.0003944279

# 计算beta
> CAPM.beta(dat_ret[,1:3],dat_ret[,4],Rf=Rf)
                  IBM       GE     YHOO
Beta: SP500 0.8218135 1.098877 1.064844

3只股票中,IBM的alpha是最小的,而且是负的,说明IBM落后于市场,买IBM不如直接SP500更好。GE的Beta是最大的,在上升时期beta越大,获得的市场收益也会越大。YHOO从Alpha和Beta上看,虽然与GE接近,但由于标准差,最大回撤等指标过大,会导致波动太大。

综上分析,cpcp彩票cpcp彩票我 们 如果配置部分GE和部分YHOO,就可以获得比标普好的收益,但由于GE和YHOO的beta都高于SP500,所以风险也会高于SP500,需要增加新的股票来分散风险,具体的定量分析,将在以后的文章中再进行介绍了。

5. Beta VS Alpha

最后,补充一些Alpha和Beta的说明。Alpha和Beta的认知最早是一个股市起源的概念,是一个cpcp彩票关于 投资组合的收益率分解的问题

  • Alpha:一般被认为是投资组合的超额收益,也既管理人的能力;
  • Beta:市场风险,最初主要指股票市场的系统性风险

Alpha是平均实际回报和平均预期回报的差额。

  • α>0,表示一基金或股票的价格可能被低估,建议买入。
  • α<0,表示一基金或股票的价格可能被高估,建议卖空。
  • α=0,表示一基金或股票的价格准确反映其内在价值,未被高估也未被低估。

Beta反映了单个证券与整体市场组合的联动性。

  • β>1,攻击性,市场上升时涨幅大。
  • β<1,防御性,市场下跌时跌幅小。
  • β=1,中立性,与市场波动一致。

从资本资产定价模型开始发展到现今,已经有很长的时间了。金融理论在一直发展,继资本资产定价模型之后又一重要的理论突破是套利定价理论,cpcp彩票我 将在下一篇文章中进行介绍。

本文中,cpcp彩票我 详细地介绍了资本资产定价模型的金融理论、推到过程、以及R语言实现,用cpcp彩票我 自己的理解进行阐述。希望能给走在量化道路上的朋友带来入门的指引和cpcp彩票帮助 ,也希望找到像cpcp彩票我 一样,通过IT转金融的人,让cpcp彩票我 一起用ITcpcp彩票技术 +金融的思维在金融市场抢钱吧。

转载请注明出处:
http://whgmhg.com/finance-capm

打赏作者

均值回归,逆市中的投资机会

用ITcpcp彩票技术 玩金融系列文章,将介绍如何使用ITcpcp彩票技术 ,处理金融大数据。在cpcp彩票互联网 混迹多年,已经熟练掌握一些ITcpcp彩票技术 。单纯地在cpcp彩票互联网 做开发,总觉得使劲的方式不对。要想靠cpcp彩票技术 养活自己,就要把cpcp彩票技术 变现。通过“跨界”可以寻找新的机会,创造cpcp彩票技术 的壁垒。

金融是离钱最近的市场,也是变现的好渠道!今天就开始踏上“用ITcpcp彩票技术 玩金融”之旅!

cpcp彩票关于 作者:

  • 张丹(Conan), 程序员Java,R,PHP,Javascript
  • weibo:@Conan_Z
  • blog: http://whgmhg.com
  • email: bsspirit@gmail.com

转载请注明出处:
http://whgmhg.com/finance-mean-reversion/

meanReversion

前言

在股票市场中有两种典型的投资策略:趋势追踪(Trend Follocpcp彩票Win g) 和 均值回归(Mean Reversion)。 趋势追踪策略的特点在大行情的波动段找到有效的交易信号,不仅简单而且有效,cpcp彩票我 之前写的一篇文章 两条均线打天下 就属于趋势追踪策略。而均值回归策略则是一种反趋势策略,一波大幅上涨后容易出现下跌,而一波大幅下跌后容易出现上涨。其特点在振荡的在震荡的市场中非常有效,捕捉小的机会,本文就将介绍这种策略。

目录

  1. 均值回归原理
  2. 均值回归模型和实现
  3. 量化选股

1. 均值回归原理

在金融学中,均值回归是价格偏离均衡价格水平一定程度后向均衡价格靠拢的规律。本质上,均值回归就是哲学思想中所说的物极必反,可以简单地概括为“涨多必跌,跌多必涨”的规律。

均值回归是指股票价格无论高于或低于均值(均衡价格水平)都会以很高的概率向均值回归。根据这个理论,股票价格总是围绕其均值上下波动。一种上涨或者下跌的趋势不管其延续的时间多长都不能永远持续下去,最终均值回归的规律一定会出现:涨得太多了,就会向均值移动下跌;跌得太多了,就会向均值移动上升。如果cpcp彩票cpcp彩票我 们 认为事物总要回归常态,并且基于这样的预期来做任何决策的时候,cpcp彩票cpcp彩票我 们 就是在应用均值回归的理论。

下面以平安银行(000001)股票日K线图为例,可以非常直观的了解均值回归这种现象, 截取2005年到2015年7月的股票数据,股价为向前复权的价格。

01

上图中有3条曲线,黑色线是平安银行向前复权后的每日股价,红色线为20日均线,蓝色线为60日均线。cpcp彩票关于 均线的介绍,请参考文章 两条均线打天下。图中还有一条红色的水平线虚线,是这10年的股价平均值等于7.14元。这10年间,平安银行的股价经历了几波上涨和下跌,多次穿越7.14平均值。那么这个现象就是cpcp彩票cpcp彩票我 们 要讨论的均值回归。

1.1 均值回归的3个特性

均值回归是价值投资理论成立的一个核心理论,具有3个特性:必然性、不对称性、cpcp彩票政府 调控。

必然性,股票价格不能总是上涨或下跌,一种趋势不管其持续的时间多长都不能永远持续下去。在一个趋势内,股票价格呈持续上升或下降,cpcp彩票cpcp彩票我 们 称之为均值回避(Mean Aversion)。当出现相反趋势时就呈均值回归(Mean Reversion),但回归的周期有随机性是cpcp彩票cpcp彩票我 们 不能预测。不同的股票市场,回归的周期会不一样的,就算是相同的市场,回归的周期也是不一样的。

cpcp彩票cpcp彩票我 们 换支股票,以苏宁云商(002024)股票日K线图为例, 同样截取2005年到2015年7月的向前复权的股价数据,如下图所示。cpcp彩票cpcp彩票我 们 看到苏宁云商在2006年到2007年有一波大涨随后下跌;从2009到2010年时,第二波大涨;2013年下半年迎来第三波大涨;2014年下半年到2015年第四波大涨。从图形上可以直观看到,2015年这波涨的最急,波动率也是最大的;从现象中,cpcp彩票cpcp彩票我 们 可以判断一种趋势不管其持续的时间多长都不能永远持续下去。

02

不对称性,股价波动的幅度与速度是不一样的,回归时的幅度与速度具有随机性。对称的均值回归才是不正常的、偶然的,这一点也也可以从股票中所验证。

cpcp彩票cpcp彩票我 们 合并平安银行(000001)和苏宁云商(002024)股票日K线图为例,所下图所示。两支股票在2007年中,都赶上了大的上涨行情,曲线基本吻合。到2008年2支股票都遇到了大跌,但波动率和速度都是不一样的,随后在2010年到2012年出现了完成不一样的走势,无规律可寻,体现了均值回归时的随机性和不对称性。

03

cpcp彩票政府 行为,股票收益率不会偏离价值均值时间太久,市场的内在力量会促使其向内在价值回归。市场在没有cpcp彩票政府 政策的作用下,股票价格会在市场机制下自然地向均值回归。但这并不否定cpcp彩票政府 行为对促进市场有效性的作用,因为市场偏离内在价值后并不等于立即就会向内在价值回归,很可能会出现持续地均值回避。cpcp彩票政府 行为会起到抑制市场调节市场的作用,是必不可少的因素之一,市场失灵也是cpcp彩票政府 参与调控的直接的结果。

对于cpcp彩票政府 政策行为,比如升准、降准、升息、降息,在股市中都会有比如明显的体现。房地产股、银行股,都会受到国家宏观调控的直接的影响。下如所示,在图中增加万科A(0000002)的股票,图中3条线分别是平安银行,万科A,苏宁云商3支股票。cpcp彩票cpcp彩票我 们 发现地产和银行的股价走势是比较相近的,而电商的走势是不太一样的。

另外,增加2种颜色的辅助线,红色为升息的时间点和利率变动值,黄色为降息的时间点和利率变动值。当2007年股市超涨的时候,国家宏观调控通过升息鼓励存款,抑制高股价;当股票超跌的时候,通过降息推动投资和消费。2015年金融改革,cpcp彩票政府 一直都在降息拉动股市。从图中,cpcp彩票cpcp彩票我 们 看到万科A和平安银行对于升息和降息的调控是比较明显的,对于苏宁云商就不是特别的明显了。

04

通过对市场的回顾,cpcp彩票cpcp彩票我 们 基本验证了均值回归的理论是和市场的行为是一致的。那么,接下来cpcp彩票cpcp彩票我 们 应该如何应用这个理论来找到投资的切入点呢?

1.2 计算原理和公式

从价值投资的角度,cpcp彩票cpcp彩票我 们 发现股价会在平均值上下波动,但如果考虑到资金的时间成本,把钱都压在股市中,等待几年的大行情,也是很不划算的。那么cpcp彩票cpcp彩票我 们 就需要对价值均值进行重新定义,以20日均值来代替长期均值,找到短周期的一种投资cpcp彩票方法 。

计算原理:取日K线,以N日均线做为均值回归的短期均衡价格水平(均值),计算股价到均值的差值,求出差值的N日的平均标准差,从而判断差值的对于均值的偏离,当偏离超过2倍标准差时,cpcp彩票cpcp彩票我 们 就认为股价超涨或超跌,股价会遵循均值回归的理论,向均值不停地进行修复。

计算公式:


N日平均值     =  [T日股价 + (T-1)日股价 + ... + (T-(N-1))日股价]/N
差值          =  N日平均值 - N日股价
N日差值均值   =  [T日差值 + (T-1)日差值 + ... + (T-(N-1))日差值]/N
N日差值标准差 =  sqrt([(T日差值 - T日差值均值)^2 + ... + ((T-(N-1))日差值 - (T-(N-1))日差值均值)^2 ]/N)

如果N为20日,则


20日平均值     =  [T日股价 + (T-1)日股价 + ... + (T-19)日股价]/20

计算偏离点


T日差值 > T日差值标准差 * 2

cpcp彩票cpcp彩票我 们 以偏离点作为买入信号点,以均线和股价的下一个交点做为卖出信号点。这样cpcp彩票cpcp彩票我 们 就把均值回归的投资理论,变成了一个数学模型。

2. 均值回归模型和实现

接下来,cpcp彩票cpcp彩票我 们 利用R语言对股票数据的进行操作,来实现一个均值回归模型的实例,从而验证cpcp彩票我 的们投资理论,是否能发现cpcp彩票赚钱 的机会。

2.1 数据准备

R语言本身提供了丰富的金融函数cpcp彩票工具 包,时间序列包zoo和xts,指标计算包TTR,数据处理包plyr,可视包ggplot2等,cpcp彩票cpcp彩票我 们 会一起使用这些cpcp彩票工具 包来完成建模、计算和可视化的工作。cpcp彩票关于 zoo包和xts包的详细使用可以参考文章,R语言时间序列基础库zoo可扩展的时间序列xts

cpcp彩票我 本次用到的数据是从 况客 直接导出的,况客 会提供各种类型的金融数据API,让开发者可以免费cpcp彩票下载 。当然,cpcp彩票你 也可以用quantmod包从Yahoo财经cpcp彩票下载 。

本文用到的数据,包括A股日K线(向前复权)数据,从2014年7月到2015年日7月,以CSV格式保存到cpcp彩票本地 文件stock.csv。

数据格式如下:


000001.SZ,2014-07-02,8.14,8.18,8.10,8.17,28604171
000002.SZ,2014-07-02,8.09,8.13,8.05,8.12,40633122
000004.SZ,2014-07-02,13.9,13.99,13.82,13.95,1081139
000005.SZ,2014-07-02,2.27,2.29,2.26,2.28,4157537
000006.SZ,2014-07-02,4.57,4.57,4.50,4.55,5137384
000010.SZ,2014-07-02,6.6,6.82,6.5,6.73,9909143

一共7列:

  • 第1列,股票代码,code,000001.SZ
  • 第2列,交易日期,date,2014-07-02
  • 第3列,开盘价,Open,8.14
  • 第4列,最高价,High,8.18
  • 第5列,最低价,Low,8.10
  • 第6列,收盘价,Close,8.17
  • 第7列,交易量,Volume,28604171

通过R语言加载股票数据,由于数据所有股票都是混合在一起的,而进行计算时又需要按每支票股计算,所以在数据加载时cpcp彩票我 就进行了转换,按股票代码进行分组,生成R语言的list对象,同时把每支股票的data.frame类型对象转成XTS时间序列类型对象,方便后续的数据处理。


#加载cpcp彩票工具
包
> library(plyr)
> library(xts)
> library(TTR)
> library(ggplot2)
> library(scales)

# 读取CSV数据文件
> read<-function(file){ 
+   df<-read.table(file=file,header=FALSE,sep = ",", na.strings = "NULL") # 读文件
+   names(df)<-c("code","date","Open","High","Low","Close","Volume")      # 设置列名
+   dl<-split(df[-1],df$code)                                             # 按ccode分组
+   
+   lapply(dl,function(row){                                              # 换成xts类型数据
+     xts(row[-1],order.by = as.Date(row$date))
+   })
+ }

# 加载数据
> data<-read("stock.csv")

# 查看数据类型
> class(data)
[1] "list"

# 查看数据的索引值
> head(names(data))
[1] "000001.SZ" "000002.SZ" "000004.SZ" "000005.SZ" "000006.SZ" "000007.SZ"

# 查看包括的股票数量
> length(data)
[1] 2782

# 查看股票000001.SZ
> head(data[['000001.SZ']])
               Open     High      Low    Close   Volume
2014-07-02 8.146949 8.180000 8.105636 8.171737 28604171
2014-07-03 8.171737 8.254364 8.122162 8.229576 44690486
2014-07-04 8.237838 8.270889 8.146949 8.188263 34231126
2014-07-07 8.188263 8.204788 8.097374 8.146949 34306164
2014-07-08 8.130424 8.204788 8.072586 8.204788 34608702
2014-07-09 8.196525 8.196525 7.915596 7.973434 58789114

把数据准备好了,cpcp彩票cpcp彩票我 们 就可以来建立模型了。

2.2 均值回归模型
为了能拉近cpcp彩票cpcp彩票我 们 对市场的了解,cpcp彩票cpcp彩票我 们 取从2015年1月1日开始的数据,来创建均值回归模型。以平安银行(000001)的为例,画出平安银行的2015年以来的日K线和均线。


# 获得时间范围
> dateArea<-function(sDate=Sys.Date()-365,eDate= Sys.Date(),before=0){  #开始日期,结束日期,提单开始时
+     if(class(sDate)=='character') sDate=as.Date(sDate)
+     if(class(eDate)=='character') eDate=as.Date(eDate)  
+     return(paste(sDate-before,eDate,sep="/"))
+ }
 
# 计算移动平均线
> ma<-function(cdata,mas=c(5,20,60)){
+     if(nrow(cdata)<=max(mas)) return(NULL)
+     ldata<-cdata
+     for(m in mas){
+         ldata<-merge(ldata,SMA(cdata,m))
+     }
+     names(ldata)<-c('Value',paste('ma',mas,sep=''))
+     return(ldata)
+ }

# 日K线和均线
> title<-'000001.SZ'
> SZ000011<-data[[title]]                             # 获得股票数据
> sDate<-as.Date("2015-01-01")                        # 开始日期
> eDate<-as.Date("2015-07-10")                        # 结束日期
> cdata<-SZ000011[dateArea(sDate,eDate,360)]$Close    # 获得收盘价
> ldata<-ma(cdata,c(5,20,60))                         # 选择移动平均指标

# 打印移动平均指标
> tail(ldata)
           Value    ma5    ma20     ma60
2015-07-03 13.07 13.768 15.2545 15.84355
2015-07-06 13.88 13.832 15.1335 15.82700
2015-07-07 14.65 13.854 15.0015 15.79850
2015-07-08 13.19 13.708 14.8120 15.74267
2015-07-09 14.26 13.810 14.6910 15.70867
2015-07-10 14.86 14.168 14.6100 15.67883

cpcp彩票cpcp彩票我 们 设置3条移动平均线,分别是5日平均线,20日平均线,60日平均线,当然也可以按照自己的个性要求设置符合自己的周期。画出日K线和均线图。


> drawLine<-function(ldata,titie="Stock_MA",sDate=min(index(ldata)),eDate=max(index(ldata)),breaks="1 year",avg=FALSE,out=FALSE){
+     if(sDate<min(index(ldata))) sDate=min(index(ldata))
+     if(eDate>max(index(ldata))) eDate=max(index(ldata))  
+     ldata<-na.omit(ldata)
+     
+     g<-ggplot(aes(x=Index, y=Value),data=fortify(ldata[,1],melt=TRUE))
+     g<-g+geom_line()
+     g<-g+geom_line(aes(colour=Series),data=fortify(ldata[,-1],melt=TRUE))
+ 
+     if(avg){
+         meanVal<<-round(mean(ldata[dateArea(sDate,eDate)]$Value),2) # 均值
+         g<-g+geom_hline(aes(yintercept=meanVal),color="red",alpha=0.8,size=1,linetype="dashed")
+         g<-g+geom_text(aes(x=sDate, y=meanVal,label=meanVal),color="red",vjust=-0.4)
+     }
+     g<-g+scale_x_date(labels=date_format("%Y-%m"),breaks=date_breaks(breaks),limits = c(sDate,eDate))
+     g<-g+ylim(min(ldata$Value), max(ldata$Value))
+     g<-g+xlab("") + ylab("Price")+ggtitle(title)
+     g
+ }

> drawLine(ldata,title,sDate,eDate,'1 month',TRUE)    # 画图

05

如图所示,60日的移动平均线是最平滑的,5日的移动平均线是波动最大的。5日平均线和股价的交叉,明显多于60日平均线和股价的交叉。那么可以说在相同的时间周期内,短周期的移动平均线,比长周期的移动平均线更具有均值回归的特点。

cpcp彩票cpcp彩票我 们 分别计算不同周期的,股价与移动平均线的差值的平均标准差。


> getMaSd<-function(ldata,mas=20,sDate,eDate){}) # ...代码省略

# 5日平均线的差值、平均标准差
> ldata5<-getMaSd(ldata,5,sDate,eDate)
> head(ldata5)
              Value      ma5        dif        sd  rate
2015-01-05 13.23673 12.78724 -0.4494869 0.1613198 -2.79
2015-01-06 13.03842 12.89961 -0.1388121 0.1909328 -0.73
2015-01-07 12.79055 12.99215  0.2016081 0.3169068  0.64
2015-01-08 12.36089 12.90292  0.5420283 0.4472248  1.21
2015-01-09 12.46004 12.77733  0.3172848 0.3910700  0.81
2015-01-12 12.20390 12.57076  0.3668606 0.2533165  1.45


# 20日平均线的差值、平均标准差
> ldata20<-getMaSd(ldata,20,sDate,eDate)
> head(ldata20)
              Value     ma20         dif        sd  rate
2015-01-05 13.23673 12.18613 -1.05059293 0.6556366 -1.60
2015-01-06 13.03842 12.23778 -0.80064848 0.6021093 -1.33
2015-01-07 12.79055 12.24810 -0.54244141 0.4754686 -1.14
2015-01-08 12.36089 12.29975 -0.06114343 0.5130410 -0.12
2015-01-09 12.46004 12.33651 -0.12352626 0.5150453 -0.24
2015-01-12 12.20390 12.37163  0.16773131 0.5531618  0.30


# 60日平均线的差值、平均标准差
> ldata60<-getMaSd(ldata,60,sDate,eDate)
> head(ldata60)
              Value     ma60       dif       sd  rate
2015-01-05 13.23673 10.06939 -3.167340 1.264792 -2.50
2015-01-06 13.03842 10.14678 -2.891644 1.271689 -2.27
2015-01-07 12.79055 10.22087 -2.569677 1.269302 -2.02
2015-01-08 12.36089 10.28752 -2.073368 1.258813 -1.65
2015-01-09 12.46004 10.35527 -2.104766 1.247967 -1.69
2015-01-12 12.20390 10.41821 -1.785691 1.233989 -1.45

5日的平均线的差值和平均标准差是最小的,而60日的平均线的差值和平均标准差是最大的。如果cpcp彩票cpcp彩票我 们 以5日移动平均线做为均值时,会频繁进行交易,但每次收益都很小,可能都不够手续费的成本;另一方面,如果cpcp彩票cpcp彩票我 们 以60日移动平均线做为均值时,交易次数会较少,但可能会出现股票成形趋势性上涨或下跌,长时间不能回归的情况,可能会造成现金头寸的紧张。综合上面的2种情况,cpcp彩票cpcp彩票我 们 可以选择20日均线作为均值的标的。

根据模型的计算公式,当差值超过2倍的平均标准差时,cpcp彩票cpcp彩票我 们 认为股价出现了偏离,以偏离点做为模型的买入信号,当均线和股价再次相交时做为卖出信号。

上一步,cpcp彩票cpcp彩票我 们 已经计算出了偏离值,并保存在rate列中。下面cpcp彩票cpcp彩票我 们 要找到大于2倍标准化差的点,并画图。


# 差值和平均标准差,大于2倍平均标准差的点
> buyPoint<-function(ldata,x=2,dir=2){})     # ...代码省略

# 画交易信号点
> drawPoint<-function(ldata,pdata,titie,sDate,eDate,breaks="1 year"){
+     ldata<-na.omit(ldata)
+     g<-ggplot(aes(x=Index, y=Value),data=fortify(ldata[,1],melt=TRUE))
+     g<-g+geom_line()
+     g<-g+geom_line(aes(colour=Series),data=fortify(ldata[,-1],melt=TRUE))
+     
+     if(is.data.frame(pdata)){
+         g<-g+geom_point(aes(x=Index,y=Value,colour=op),data=pdata,size=4)
+     }else{
+         g<-g+geom_point(aes(x=Index,y=Value,colour=Series),data=na.omit(fortify(pdata,melt=TRUE)),size=4)  
+     }
+     g<-g+scale_x_date(labels=date_format("%Y-%m"),breaks=date_breaks(breaks),limits = c(sDate,eDate))
+     g<-g+xlab("") + ylab("Price")+ggtitle(title)
+     g
+ }
 
> buydata<-buyPoint(ldata20,2,2)                                       # 多空信号点
> drawPoint(ldata20[,c(1,2)],buydata$Value,title,sDate,eDate,'1 month')  # 画图

06

图中蓝色的点就是买入的信号点,由于股票cpcp彩票cpcp彩票我 们 只能进行单向交易,即低买高卖,并不能直接做空,所以cpcp彩票cpcp彩票我 们 要过滤股价高于移动平均线的点,只留下股价低于移动平均线的点,就是cpcp彩票cpcp彩票我 们 的买入信号点。

画出买入信号点,只保留股价低于移动平均线的点。


> buydata<-buyPoint(ldata20,2,1)        # 做多信号点
> drawPoint(ldata20[,c(1,2)],buydata$Value,title,sDate,eDate,'1 month') # 画图

07

计算卖出的信号点,当买入后,下一个股价与移动平均线的交点就是卖出的信号点,cpcp彩票cpcp彩票我 们 看一下是否可以赚到钱?!


# 计算卖出的信号点
> sellPoint<-function(ldata,buydata){})     # ...代码省略
> selldata<-sellPoint(ldata20,buydata)

# 买出信号
> selldata
           Value  ma20   dif        sd  rate
2015-07-10 14.86 14.61 -0.25 0.7384824 -0.34

cpcp彩票cpcp彩票我 们 把买入信号和卖出信号,合并到一张图上显示,如图所示。


> bsdata<-merge(buydata$Value,selldata$Value)
> names(bsdata)<-c("buy","sell")
> drawPoint(ldata20[,c(1,2)],bsdata,title,sDate,eDate,'1 month') #画图

08

从图上看,cpcp彩票cpcp彩票我 们 在绿色点位置进行买入,而在蓝色点位置进行卖出,确实是cpcp彩票赚钱 的。那么究竟赚了多少钱呢?cpcp彩票cpcp彩票我 们 还需要精确的计算出来。


# 合并交易信号
> signal<-function(buy, sell){})    # ...代码省略

# 交易信号数据
> sdata<-signal(buydata,selldata)                                   
> sdata
           Value    ma20     dif        sd  rate op
2015-06-19 14.63 16.0965  1.4665 0.6620157  2.22  B
2015-06-26 13.77 15.7720  2.0020 0.8271793  2.42  B
2015-06-29 13.56 15.6840  2.1240 0.9271735  2.29  B
2015-07-03 13.07 15.2545  2.1845 1.0434926  2.09  B
2015-07-10 14.86 14.6100 -0.2500 0.7384824 -0.34  S

利用交易信号数据,进行模拟交易。cpcp彩票cpcp彩票我 们 设定交易参数和规则:

  • 以10万元人民币为本金
  • 买入信号出现时,以收盘价买入,每次买入价值1万元的股票。如果连续出现买入信号,则一直买入。若现金不足1万元时,则跳过买入信号。
  • 卖出信号出现时,以收盘价卖出,一次性平仓信号对应的股票。
  • 手续费为0元

# 模拟交易
> trade<-function(sdata,capital=100000,fixMoney=10000){})    # ...代码省略

# 交易结果
> result<-trade(sdata,100000,10000)  

来看一下,每笔交易的明细。


> result$ticks
           Value    ma20     dif        sd  rate op      cash amount     asset     diff
2015-06-19 14.63 16.0965  1.4665 0.6620157  2.22  B  90007.71    683 100000.00     0.00
2015-06-26 13.77 15.7720  2.0020 0.8271793  2.42  B  80010.69   1409  99412.62  -587.38
2015-06-29 13.56 15.6840  2.1240 0.9271735  2.29  B  70016.97   2146  99116.73  -295.89
2015-07-03 13.07 15.2545  2.1845 1.0434926  2.09  B  60018.42   2911  98065.19 -1051.54
2015-07-10 14.86 14.6100 -0.2500 0.7384824 -0.34  S 103275.88      0 103275.88  5210.69

一共发生了5笔交易,其中4笔买入,1笔卖出。最后,资金剩余103275.88元,赚了3275.88元,收益率3.275%。

在卖出时,cpcp彩票赚钱 的交易有1笔。


> result$rise
           Value  ma20   dif        sd  rate op     cash amount    asset    diff
2015-07-10 14.86 14.61 -0.25 0.7384824 -0.34  S 103275.9      0 103275.9 5210.69

在卖出时,赔钱的交易,没有发生。


> result$fall
 [1] Value  ma20   dif    sd     rate   op     cash   amount asset  diff  
<0 行> (或0-长度的row.names)

接下来,cpcp彩票cpcp彩票我 们 再对比一下,资产净值和股价。


# 资产净值曲线
> drawAsset<-function(ldata,adata,sDate=FALSE,capital=100000){
+     if(!sDate) sDate<-index(ldata)[1]
+     adata<-rbind(adata,as.xts(capital,as.Date(sDate)))
+     
+     g<-ggplot(aes(x=Index, y=Value),data=fortify(ldata[,1],melt=TRUE))
+     g<-g+geom_line()
+     g<-g+geom_line(aes(x=as.Date(Index), y=Value,colour=Series),data=fortify(adata,melt=TRUE))
+     g<-g+facet_grid(Series ~ .,scales = "free_y")
+     g<-g+scale_y_continuous(labels=dollar_format(prefix = "¥"))
+     g<-g+scale_x_date(labels=date_format("%Y-%m"),breaks=date_breaks("2 months"),limits = c(sDate,eDate))
+     g<-g+xlab("") + ylab("Price")+ggtitle(title)
+     g
+ }

> drawAsset(ldata20,as.xts(result$ticks['asset']))  # 资产净值曲线

09

刚才cpcp彩票cpcp彩票我 们 是对一支股票进行了测试,发现是有机会的,那么cpcp彩票我 再换另外一支股票,看一下是否用同样的效果呢?cpcp彩票cpcp彩票我 们 把刚才数据操作的过程,封装到统一的quick函数,就可以快速验证均值回归在其他股票的表现情况了。


> quick<-function(title,sDate,eDate){}  # ...代码省略

cpcp彩票cpcp彩票我 们 用乐视网(300104)试一下,看看有没有cpcp彩票赚钱 的机会!!


> title<-"300104.SZ"
> sDate<-as.Date("2015-01-01") #开始日期
> eDate<-as.Date("2015-07-10") #结束日期

> quick(title,sDate,eDate)
$ticks
           Value    ma20     dif       sd  rate op      cash amount     asset     diff
2015-06-19 55.04 69.9095 14.8695 5.347756  2.78  B  90037.76    181 100000.00     0.00
2015-06-23 54.30 68.8075 14.5075 5.477894  2.65  B  80046.56    365  99866.06  -133.94
2015-06-24 56.21 67.8735 11.6635 5.404922  2.16  B  70097.39    542 100563.21   697.15
2015-06-25 51.80 66.8775 15.0775 5.770806  2.61  B  60099.99    735  98172.99 -2390.22
2015-06-26 46.79 65.9830 19.1930 6.580622  2.92  B  50133.72    948  94490.64 -3682.35
2015-06-29 47.05 64.9445 17.8945 7.096230  2.52  B  40159.12   1160  94737.12   246.48
2015-07-07 47.86 58.8150 10.9550 5.401247  2.03  B  30204.24   1368  95676.72   939.60
2015-07-10 57.92 57.3520 -0.5680 5.625309 -0.10  S 109438.80      0 109438.80 13762.08

$rise
           Value   ma20    dif       sd rate op     cash amount    asset     diff
2015-07-10 57.92 57.352 -0.568 5.625309 -0.1  S 109438.8      0 109438.8 13762.08

$fall
 [1] Value  ma20   dif    sd     rate   op     cash   amount asset  diff  
<0 行> (或0-长度的row.names)

从数据结果看,cpcp彩票cpcp彩票我 们 又赚到了。一共发生了8笔交易,其中7笔买入,1笔卖出。最后,资金剩余109438.80元,赚了9438.80元,收益率9.43%。

画出交易信号图


> title<-"300104.SZ"
> sDate<-as.Date("2015-01-01") #开始日期
> eDate<-as.Date("2015-07-10") #结束日期

> stock<-data[[title]]
> cdata<-stock[dateArea(sDate,eDate,360)]$Close
> ldata<-ma(cdata,c(20))
> ldata<-getMaSd(ldata,20,sDate,eDate)
> buydata<-buyPoint(ldata,2,1)  
> selldata<-sellPoint(ldata,buydata)
> bsdata<-merge(buydata$Value,selldata$Value)
> drawPoint(ldata[,c(1,2)],bsdata,title,sDate,eDate,'1 month') #画图

10

在恐慌的6月份,当别人都被套牢30%以上的情况下,cpcp彩票cpcp彩票我 们 还朿9%正收益,那么应该是多么舒心的一件事情啊!!

3. 量化选股

上文中,cpcp彩票cpcp彩票我 们 用2支股票进行了测试,发现均值回归模型是适合于股票交易的。如果cpcp彩票cpcp彩票我 们 利用模型对全市场的股票进行扫描,应用会产生cpcp彩票更多 的交易信号,找到cpcp彩票更多 的投资机会,这样cpcp彩票cpcp彩票我 们 就能如何能获得更大的收益。

那么,接下来cpcp彩票cpcp彩票我 们 就根据均值回归的理论进行量化选股。

根据cpcp彩票cpcp彩票我 们 之前的经验,当股价与平均标准差的偏离越大,有可能带来的收益就越大。那么通过量化的手段,在整个的市场2700多支股票中,把每天偏离最大股票的找出来进行交易,就可以有效地分配cpcp彩票cpcp彩票我 们 的资金,进行更有效的投资。cpcp彩票cpcp彩票我 们 要试一下,市场是否是和cpcp彩票cpcp彩票我 们 的思路是一致的。

对全市场股票进行扫描,首先计算差值、平均值和平均标准差。


> sDate<-as.Date("2015-01-01")                # 开始日期
> eDate<-as.Date("2015-07-10")                # 结束日期

# 计算差值、平均值和平均标准差
> data0<-lapply(data,function(stock){})       # 代码省略

# 去掉空数据
> data0<-data0[!sapply(data0, is.null)]      

# 全市场股票
> length(data)
[1] 2782

# 有效的股票
> length(data0)
[1] 2697

# 查看第1支股票
> head(data0[[1]])
              Value     ma20         dif        sd  rate
2015-01-05 13.23673 12.18613 -1.05059293 0.6556366 -1.60
2015-01-06 13.03842 12.23778 -0.80064848 0.6021093 -1.33
2015-01-07 12.79055 12.24810 -0.54244141 0.4754686 -1.14
2015-01-08 12.36089 12.29975 -0.06114343 0.5130410 -0.12
2015-01-09 12.46004 12.33651 -0.12352626 0.5150453 -0.24
2015-01-12 12.20390 12.37163  0.16773131 0.5531618  0.30

第一次扫描后,有2697支股票是符合条件的,有85支股票由于数据样本不足被排除。

接下来,继续对2697支股票进行筛选,找到符合要求的买入信号点。


# 计算买入信号
> buys<-lapply(data0,function(stock){})  # ...代码省略 

# 去掉空数据
> buys<-buys[!sapply(buys, is.null)] 

# 查看有买入信号的股票
> length(buys)
[1] 1819

# 查看买入信号
> head(buys)
$`000001.SZ`
           Value    ma20    dif        sd rate
2015-06-19 14.63 16.0965 1.4665 0.6620157 2.22
2015-06-26 13.77 15.7720 2.0020 0.8271793 2.42
2015-06-29 13.56 15.6840 2.1240 0.9271735 2.29
2015-07-03 13.07 15.2545 2.1845 1.0434926 2.09

$`000002.SZ`
           Value   ma20   dif        sd rate
2015-03-05 11.90 12.568 0.668 0.2644101 2.53
2015-03-06 11.94 12.509 0.569 0.2674732 2.13

$`000004.SZ`
           Value    ma20     dif        sd rate
2015-01-05 15.69 17.7210  2.0310 0.7395717 2.75
2015-07-06 26.03 39.1540 13.1240 6.3898795 2.05
2015-07-07 23.43 38.2025 14.7725 6.9421723 2.13
2015-07-08 22.22 37.2635 15.0435 7.4287088 2.03

$`000005.SZ`
           Value    ma20    dif       sd rate
2015-07-06  6.02 10.9600 4.9400 2.381665 2.07
2015-07-07  5.42 10.5655 5.1455 2.333008 2.21

$`000006.SZ`
              Value     ma20       dif      sd rate
2015-01-19 5.829283 6.519462 0.6901792 0.26929 2.56

$`000007.SZ`
           Value    ma20    dif        sd rate
2015-02-06 12.47 14.4200 1.9500 0.6182860 3.15
2015-02-09 12.52 14.3270 1.8070 0.7440473 2.43
2015-02-10 12.10 14.1845 2.0845 0.8484250 2.46

通过计算发现,有1819支股票,在这半年中产生过买入信号。每支股票产生的买入信号的时间和频率都是不同,这样cpcp彩票cpcp彩票我 们 就可以把钱分散投资到不同的股票上,同时分散风险。如果交易信号同一天出现在多支的股票上,而cpcp彩票cpcp彩票我 们 资金有限,又想让收益最大化,那么cpcp彩票cpcp彩票我 们 可以选择偏离值最大的股票进行交易。

接下来,cpcp彩票cpcp彩票我 们 用程序找到每日偏离最大的股票。


# 合并数据,从list转型到data.frame
buydf<-ldply(buys,function(e){})    # ...代码省略

# 选出同一日rate最大的股票,做为买入信号
buydatas<-ddply(buydf, .(date), function(row){}) # ...代码省略

# 查看买入信号
> nrow(buydatas)
[1] 81

# 查看买入信号细节
> head(buydatas)
         .id       date      Value       ma20        dif         sd rate
1  002551.SZ 2015-01-05  16.573846  19.565446  2.9916000 0.74591596 4.01
2  002450.SZ 2015-01-06  18.548809  19.766636  1.2178275 0.34008453 3.58
3  300143.SZ 2015-01-07  11.480000  12.603000  1.1230000 0.32028018 3.51
4  300335.SZ 2015-01-08  12.113677  13.139601  1.0259238 0.21760484 4.71
5  300335.SZ 2015-01-09  12.243288  13.043888  0.8005994 0.22940845 3.49
6  300335.SZ 2015-01-12  11.994036  12.941694  0.9476584 0.23168313 4.09

最后,cpcp彩票cpcp彩票我 们 选出81个买入信号点,基本上每个交易日都是买入信号。有了买入信号,继续找到卖出信号。


# 卖出信号
> selldatas<-data.frame()     # ...代码省略

# 卖出信号去重
> selldatas<-unique(selldatas)  
> nrow(selldatas)
[1] 33

# 查看买出信号
> head(selldatas)
                Value      ma20         dif        sd  rate       .id       date op
2015-01-12  19.232308 18.848908 -0.38340000 0.9051374 -0.42 002551.SZ 2015-01-12  S
2015-01-08  19.814257 19.729006 -0.08525126 0.3782955 -0.23 002450.SZ 2015-01-08  S
2015-01-28  11.210000 11.019500 -0.19050000 0.7781848 -0.24 300143.SZ 2015-01-28  S
2015-01-21  13.190448 12.899321 -0.29112706 0.3871871 -0.75 300335.SZ 2015-01-21  S
2015-01-213  7.140000  6.989500 -0.15050000 0.2007652 -0.75 002505.SZ 2015-01-21  S
2015-01-22   5.561561  5.490668 -0.07089242 0.2127939 -0.33 600077.SH 2015-01-22  S

通过计算,一共有33个买出信号点。最后,合并买入信号和卖出信号,并计算收益。


> buydatas$op<-'B'                              # 买入标志
> selldatas$op<-'S'                             # 卖出标志
> sdatas<-rbind(buydatas,selldatas)             # 合并数据
> row.names(sdatas)<-1:nrow(sdatas)             # 重设行号
> sdatas<-sdatas[order(sdatas$.id),]            # 按股票代码排序

# 查看合并的信号
> head(sdatas)
          .id       date Value     ma20       dif         sd  rate op
36  000002.SZ 2015-03-05 11.90 12.56800  0.668000 0.26441011  2.53  B
100 000002.SZ 2015-03-16 12.49 12.38050 -0.109500 0.23702768 -0.46  S
58  000553.SZ 2015-05-06 14.35 15.50882  1.158824 0.38429912  3.02  B
110 000553.SZ 2015-05-21 16.57 15.18903 -1.380972 0.55647152 -2.48  S
26  000725.SZ 2015-02-09  2.80  3.11400  0.314000 0.07934585  3.96  B
94  000725.SZ 2015-02-16  3.09  3.06500 -0.025000 0.08182388 -0.31  S

最后,按照股票进行分组,分别计算个股的收益。


# 计算个股的收益
> slist<-split(sdatas[-1],sdatas$.id)      # 按股票代码分组
> results<-lapply(slist,trade)

# 查看信号的股票
> names(results)
 [1] "000002.SZ" "000553.SZ" "000725.SZ" "000786.SZ" "000826.SZ" "002240.SZ" "002450.SZ"
 [8] "002496.SZ" "002505.SZ" "002544.SZ" "002551.SZ" "002646.SZ" "002652.SZ" "300143.SZ"
[15] "300335.SZ" "300359.SZ" "300380.SZ" "300397.SZ" "300439.SZ" "300440.SZ" "300444.SZ"
[22] "600030.SH" "600038.SH" "600077.SH" "600168.SH" "600199.SH" "600213.SH" "600375.SH"
[29] "600490.SH" "600536.SH" "600656.SH" "600733.SH" "600890.SH" "601179.SH" "601186.SH"
[36] "601628.SH" "601633.SH" "601939.SH" "603019.SH"

cpcp彩票cpcp彩票我 们 查看万科A(000002)的股票。


> results[['000002.SZ']]$ticks
          date Value    ma20     dif        sd  rate op     cash amount    asset  diff
36  2015-03-05 11.90 12.5680  0.6680 0.2644101  2.53  B  90004.0    840 100000.0   0.0
100 2015-03-16 12.49 12.3805 -0.1095 0.2370277 -0.46  S 100495.6      0 100495.6 495.6

通过cpcp彩票优化 的规则设计,一共有2笔交易,赚了495元。如要cpcp彩票cpcp彩票我 们 没有进行算法cpcp彩票优化 ,一直交易万科A,那么会发生3笔交易,cpcp彩票cpcp彩票我 们 可以赚955.95元。


> quick('000002.SZ',sDate,eDate)$ticks
           Value    ma20     dif        sd  rate op      cash amount    asset   diff
2015-03-05 11.90 12.5680  0.6680 0.2644101  2.53  B  90004.00    840 100000.0   0.00
2015-03-06 11.94 12.5090  0.5690 0.2674732  2.13  B  80010.22   1677 100033.6  33.60
2015-03-16 12.49 12.3805 -0.1095 0.2370277 -0.46  S 100955.95      0 100955.9 922.35

本文到此就要结束了!但其实还有很多的事情要做,比如对模型参数的cpcp彩票优化 ,用10日均线代替20日均线,用3倍标准差偏移代替2倍标准差偏移,对样本进行正态分布的检验,结合其他趋势类模型共同产生信号等,这些就不是一篇文章可以解决的事情了。大家可以况客金融平台的网站上,发现cpcp彩票更多 不一样的策略。

本文从均值回归的理论的介绍开始,到市场特征检验,再到数学公式,R语言建模,历史数据回测,最后找到投资机会,是一套完整的从理论到实践的学习cpcp彩票方法 。虽然困难重重,但做为有理想的极客,cpcp彩票cpcp彩票我 们 是有能力来克服这些困难的。

本文同时用到了计算机、金融、数学、统计等多学科知识的结合,cpcp彩票我 认为这是cpcp彩票技术 复合人才未来的发展方向。如果说过去10年是房地产的黄金10年,那么未来的10年将是金融的黄金10年。当cpcp彩票cpcp彩票我 们 IT人掌握了足够的金融知识,一定会有能力去金融市场抢钱的。

抓住机会!!程序员,加油!

######################################################
看文字不过瘾,作者cpcp彩票视频 讲解,请访问网站:http://onbook.me/video
######################################################

转载请注明出处:
http://whgmhg.com/finance-mean-reversion/

打赏作者