• Posts tagged "股票"

Blog Archives

R语言构建追涨杀跌量化交易模型

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

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

关于作者:

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

转载请注明出处:
http://blog.fens.me/finance-chase-sell/

chaseSell

前言

久经股市的老股民,通常都会使用一种常见的交易策略,追涨杀跌交易法。追涨杀跌法,是股市操作的一个重要技巧,就是在股市上涨时买入股票,股市下跌时卖出股票。如果操作得当是很好的赢利手段,在中国股市2015年上半年的牛市中,追涨杀跌交易法就是交易神器法门。

目录

  1. 什么是追涨杀跌?
  2. 追涨杀跌的建型和实现
  3. 模型优化

1. 什么是追涨杀跌?

追涨杀跌是金融市场的专业术语,是金融技术派操盘的一种方式,与抄底摸顶的操作方式刚好相反。追涨杀跌的操作方法是,金融市场中在金融产品(股票,期货,外汇等)价格上涨的时候买入,以期待涨得更多,并以更高的价格卖出获利;在价格下跌的时候卖出进行止损,不管之前金融产品买入的价格是多少,都立刻卖出,以避免更大的损失。

下面以平安银行(000001)股票日K线图为例,截取2005年到2015年7月的股票数据,股价为向前复权的价格。

01

上图中有3条曲线,黑色线是平安银行向前复权后的每日股价,红色线为20日均线,蓝色线为60日均线。关于均线的介绍,请参考文章 两条均线打天下。图中还有一条红色的水平线虚线,是这10年的股价平均值等于7.14元。这10年间,平安银行股价起起落落,每次上涨都会持续一段时间,那么在我们可以上涨中段追入买进,在大幅下跌之前卖出,就是追涨杀跌法。

追涨

追涨通常有2种情况,短线追涨和中线追涨。以股票交易为例。

  • 短线追涨:当天股价已经涨了5个点或更多,这时追进去买入,期待当天收盘涨停,等下一个交易日高价卖出,这就是短线追涨。
  • 中线追涨:某只股票的股价已经上涨了一段时间,走势很强,底部上涨已经有30%或更多,这个时追进去买入,期待后势持续上涨,是中线追涨。

不论短线追涨还是中线追涨,我们追涨的理由和判断的标准都是一样的,“涨得好的股票说明走势很强,那么追强势股期待股票持续上涨”。但从另一个角度看,追涨的风险也是很大的,关键在于我们不知道它能涨到什么时候,到什么位置可能会回调,什么时候是庄家出货。所以说追涨技巧性很强,什么情况下能追,什么情况下不能追,都是很有讲究的。

杀跌

杀跌也是一门较深的操作技巧,杀得好的话既可以回避风险。如果不能进行杀跌的准确判断,则很可能会发生硬性止损,导致严重的亏损。

采取杀跌战术,必须掌握以下操作要点:

  • 杀跌的重要前提是知变,就是对消息、对量能、对周边各种因素的影响有一个准确的、快速的知变过程。
  • 杀跌要善于观察盘面、形态、消息、舆论等方面的细微变化,在对大盘作出准确估量的基础上,迅速作出反应就是确定卖出哪支股票,卖出多少等。
  • 杀跌要善于思考大盘与目标股之问的正向、反向的相关性,及目标股的能量能等方向的关系,从中找出变动的规律。
  • 当市场利好消息接踵而至时,应随时准备卖出股票。当利好出尽就会转向利空,往往消息明朗时,股价早已下跌大半,导致措手不及。

杀跌的后续操作就比较简单了,只需保持良好的心态,耐心等待见底信号后再抄底。一般只有在底部成功接回股票或换股才算成功的杀跌,否则杀跌会失去意义。应保持耐心,千万不要在股价反弹时贸然介入,否则屡买屡跌、会加大损失,应待股价反转时再介入。

追涨杀跌的技巧

要观大势,看清整个市场多空对决的优势一方是谁。

追涨杀跌的假设条件:

  • 市场处于强势交易格局。强势格局赋予个股良好的运作基础;相反,如果市场处于平衡状态,就不适合进行追涨杀跌,更适合高抛低吸。
  • 市场形成了鲜明并有持续性上涨能力的热点或板块效应。

追涨操作的对象:

  • 市场形成鲜明的可持续性的热点时,可追涨这个热点。从理论上讲,只要把握热点板块就能获利,追涨时应重点关注龙头企业。比如:沪深300指数的成分股,就是不错的选择。
  • 形成明显的上涨趋势的个股可以考虑追涨。个股突破重要的压力线,如头肩底形态的颈线位、整理箱体的箱顶位、三角形的上边眼、长期下降趋势线等,待回抽确认其突破的有效性后,可考虑追涨。

追涨杀跌的注意事项:

  • 追涨时应设好止盈位和止损位,确定自己的大致盈利目标。
  • 追涨杀跌应该注意频率的减少,过于频繁的操作,一旦失误增多会严重影响情绪。
  • 追涨杀跌中要多一分平和的心态,少一些侥幸;多一分理性,少一分感性。

追涨杀跌的市场操作

在弱市中,短线追涨往往容易被套,因为弱市里大部分股票的行情只有一天,当天追得高了,第二天多半没有获利逃出的机会。相反,弱市中,中线追涨比较可取,能够在弱市中保持强势的股票不多,但这种强势反而可以持续。但很多时候,弱市中这样的股票反倒不敢追了。

有些人专门追涨停板,追新股开板,追次新股开板等,对于2015年上半年IPO的新股来说收获颇丰,如暴风科技,中超电缆等,其他的时候可能用这套追涨停策略就行不通了。

001

我自己操作并不会盲目追涨,安全第一,虽然还没有吃过追涨的亏,但由于本人目前还不具备基本面的分析能力,也没有消息的渠道,仅仅从技术指标入手,投机性太重,很容易被庄家玩死的。道理很简单,因为如果追涨了,下跌的空间自然就大了,尤其中线追涨,庄家获利后随时可能出货。这时候就必须要做好杀跌的策略。庄股出货跌个50%太普遍了,而且跌下去就很难再起来,这种时候不杀跌就等于自杀。所以,追涨之前一定要想清楚,务必先设好止损位,不能只憧憬获利的美妙。

杀跌也有讲究,不是一跌就杀,震荡、洗盘是很常见的,问题在于正确地区别震仓与出货是很难的,所以很多人是硬性止损,即预先设定价位或百分比,到这个位置就坚决出局,不管它是震仓还是庄家出货。这个时候如果没有基本面的判断或第一手消息的来源,就容易被震荡出局。当然,和不确定的风险相比,我其实更愿意早点出来。

2. 追涨杀跌的建型和实现

既然我们要进行追涨杀跌的操作,就要定义什么是追涨,什么又是杀跌,需要把追涨杀跌的概念量化出来,从而进行建模和实现。对于短线追涨策略可以简单粗暴地选择当日涨幅超过5%的股票进行买入,第二日开盘卖出或到止损位卖出,并没有太多的技术细节,再计算一下胜率概率,就能知道我们要不要短线追涨。

下文我们将以中线追涨为例,进行建模和程序实现。

那么对于中线追涨的情况,我们核心的策略思路就可以转化为,当股价(成交量)向上突破最近20日最高价格(量)时买入,当股价向下突破最近10日最低价格卖出,并以沪深300成分股做为股票交易的标的。其中,为什么是20日最高和10日最低都是经验值,可以做为模型参数进行训练和优化。选择沪深300成分股为标的,是考虑到这些股票都是各个板块的强势股或龙头股,要符合追涨杀跌的假设条件。

计算公式:


20日最高价 = max(T日股价,T-1日股价 ... , T-19日股价)
20日最高量 = max(T日成交量,T-1日成交量 ... , T-19日成交量)
10日最低价 = min(T日股价,T-1日股价 ... , T-9日股价)

当股价大于等于20日最高价时作为买入信号点,当股价小于等于10日最低价时作为卖出信号点。这样我们就把追涨杀跌的投资理论,变成了一个数学模型。

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

2.1 数据准备

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

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

本文用到的数据,包括A股日K线(向前复权)数据,从2014年7月到2015年日8月,以CSV格式保存到本地文件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语言加载股票数据,由于数据所有股票都是混合在一起的,而进行计算时又需要按每支票股计算,所以在数据加载时我就进行了转换,按股票代码进行分组,生成R语言的list对象,同时把每支股票的data.frame类型对象转成XTS时间序列类型对象,方便后续的数据处理。


#加载工具包
> 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

# 获得时间范围
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="/"))
}

# 查看股票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

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

2.2 追涨杀跌模型

为了能拉近我们对市场的了解,我们取从2015年1月1日开始的数据,来创建追涨杀跌的模型。以乐视网(300104)的为例,画出乐视网自2015年以来的每日收盘价,20日最高价和10日最低价。乐视网作为创业板标杆的上市公司,在2015年7月首次被纳入沪深300指数。


# 日K线数据
> title<-'300104.SZ'
> stock<-data[[title]]                                # 获得股票数据
> sDate<-as.Date("2015-01-01")                        # 开始日期
> eDate<-as.Date("2015-08-24")                        # 结束日期
> cdata<-stock[dateArea(sDate,eDate,360)]$Close       # 获得收盘价
> vdata<-stock[dateArea(sDate,eDate,360)]$Volume      # 获得交易量

# 收盘价
> names(cdata)<-"Value"   # 重置列名
> tail(cdata)
           Value
2015-08-14 49.81
2015-08-17 48.30
2015-08-18 45.57
2015-08-19 46.98
2015-08-20 45.79
2015-08-21 42.14
 
# 交易量
> tail(vdata)
             Volume
2015-08-14 42108324
2015-08-17 35939096
2015-08-18 52745702
2015-08-19 43447844
2015-08-20 32916746
2015-08-21 34802494

定义画图函数drawLine(),支持画出多条曲线,包括收盘价,最高价,最低价。


# 画图函数
> drawLine<-function(cdata,titie="Stock",sDate=min(index(cdata)),eDate=max(index(cdata)),breaks="1 year"){
+     if(sDate<min(index(cdata))) sDate=min(index(cdata))
+     if(eDate>max(index(cdata))) eDate=max(index(cdata))  
+     cdata<-na.omit(cdata)
+     
+     g<-ggplot(aes(x=Index, y=Value),data=fortify(cdata[,1],melt=TRUE))
+     g<-g+geom_line()
+     
+     if(ncol(cdata)>1){ # 多条线
+         g<-g+geom_line(aes(colour=Series),data=fortify(cdata[,-1],melt=TRUE))  
+     }
+     
+     g<-g+scale_x_date(labels=date_format("%Y-%m"),breaks=date_breaks(breaks),limits = c(sDate,eDate))
+     g<-g+ylim(min(cdata$Value), max(cdata$Value))
+     g<-g+xlab("") + ylab("Price")+ggtitle(title)
+     g
+ }

# 画出收盘价
# drawLine(cdata,title,sDate,eDate,'1 month')    # 画图

# 计算最近20日的最高价和10日的最低价
> minmax<-function(data,max=20,min=10){
+   d1<-na.locf(data,fromLast=TRUE)
+   d2<-merge(d1,min=runMin(d1,min),max=runMax(d1,max))
+   return(d2[,-1])
+ }
 
# 画出股价,最高价和最低价
> ldata<-cbind(cdata,minmax(cdata))
> drawLine(ldata,title,sDate,eDate,'1 month')    # 画图

01

上图中有3条线,黑色线为乐视网的每日收盘价,蓝色线为最近20日最高价,红色线为最近10日最低价。

根据模型的计算公式,我们计算买入信号,当股价向上突破最近20日最高价格时买入。


# 买入信号函数
> buyPoint<-function(ldata){   
+  idx<-which(ldata$Value == ldata$max)
+  return(ldata[idx,])                                  
+ }

# 计算买入的点
> buydata<-buyPoint(ldata)
> buydata
              Value      min      max
2015-01-08 17.43721 13.70164 17.43721
2015-01-09 17.98709 13.74254 17.98709
2015-01-12 19.53222 13.74254 19.53222
2015-01-15 20.21389 14.74232 20.21389
2015-01-16 22.23619 16.08749 22.23619
2015-01-19 23.04056 16.36016 23.04056
2015-01-20 23.89947 16.36016 23.89947
2015-01-26 24.77656 19.22774 24.77656
2015-01-27 25.16284 19.40043 25.16284
2015-02-05 26.91247 21.99533 26.91247
2015-02-10 28.68482 21.99533 28.68482
2015-02-11 31.55239 21.99533 31.55239
2015-02-12 31.87960 21.99533 31.87960
2015-02-13 35.06983 22.72245 35.06983
2015-02-16 38.57817 24.22213 38.57817
2015-02-17 40.99130 24.46753 40.99130
2015-03-16 41.07764 34.32453 41.07764
2015-03-18 41.94564 34.32453 41.94564
2015-03-24 45.34946 37.17393 45.34946
2015-04-23 46.27199 37.06031 46.27199
2015-04-24 50.89829 37.06031 50.89829
2015-04-27 50.90283 37.06031 50.90283
2015-04-28 55.44277 37.06031 55.44277
2015-04-29 60.98705 37.06031 60.98705
2015-05-06 62.25497 45.19495 62.25497
2015-05-07 66.20413 46.27199 66.20413
2015-05-08 67.23573 50.89829 67.23573
2015-05-11 73.96157 50.90283 73.96157
2015-05-12 81.36000 55.44277 81.36000
2015-05-13 82.49000 57.16514 82.49000

画出买入的信号图,让我们可以直观的看到效果。


# 画图函数
> 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
+ }

> drawPoint(ldata,buydata$Value,title,sDate,eDate,'1 month')  # 画图

02

如上图所示,蓝色的点为股价大于等于最近20日最高价的点,作为买入信号。所有买入信号点,都是出现在单边上行的牛势中,对于2015年上半年以来的行情来说,追涨的信号会被大量触发。

接下来,我们继续计算卖出信号点,当股价小于等于最近10日最低价时作为卖出信号点。


> # 计算卖出的信号点
> stopPoint<-function(ldata,buydata){  
+     idx<-which(ldata$Value == ldata$min)
+     idx<-idx[which(c(0,diff(idx))!=1)]   # 第一点用0表示
+     
+     selldata<-ldata[idx,]               # 所有低于最小值的点  
+     idx2<-sapply(index(buydata),function(e){  # 买后的卖点
+         head(which(index(selldata)>e),1)
+     })
+     
+     return(selldata[unique(idx2),])
+ } 

# 卖出信号
> selldata<-stopPoint(ldata,buydata)
> selldata
              Value      min      max
2015-01-30 21.99533 21.99533 25.16284
2015-03-06 34.32453 34.32453 40.99130
2015-04-08 38.01011 38.01011 45.34946
2015-05-28 64.68000 64.68000 82.49000

一共有4笔卖出信号,为了让数据更加直观,我们合并买入信号和卖出信号,进行画图可视化。


# 买卖信号,画图
> bsdata<-merge(buydata$Value,selldata$Value)
> names(bsdata)<-c("buy","sell")
> drawPoint(ldata,bsdata,title,sDate,eDate,'1 month') #画图

03

上图中,紫色点为卖出信号点,红色点为买入信号点。我们可以很明显的看出,如果根据交易信号在红色点买入,紫色点卖出,我们是应该赚钱的。那么具体赚了多少呢,我需要计算出来?


> # 合并交易信号
> signal<-function(buy, sell){
+     selldf<-data.frame(sell,op=as.character(rep("S",nrow(sell))))
+     buydf<-data.frame(buy,op=as.character(rep("B",nrow(buy))))
+     sdata<-rbind(buydf,selldf)                                       # 交易信号数据
+     sdata[order(as.Date(row.names(sdata))),]
+ }

# 合并交易信号
> sdata<-signal(buydata,selldata)                                   
> sdata
              Value      min      max op
2015-01-08 17.43721 13.70164 17.43721  B
2015-01-09 17.98709 13.74254 17.98709  B
2015-01-12 19.53222 13.74254 19.53222  B
2015-01-15 20.21389 14.74232 20.21389  B
2015-01-16 22.23619 16.08749 22.23619  B
2015-01-19 23.04056 16.36016 23.04056  B
2015-01-20 23.89947 16.36016 23.89947  B
2015-01-26 24.77656 19.22774 24.77656  B
2015-01-27 25.16284 19.40043 25.16284  B
2015-01-30 21.99533 21.99533 25.16284  S
2015-02-05 26.91247 21.99533 26.91247  B
2015-02-10 28.68482 21.99533 28.68482  B
2015-02-11 31.55239 21.99533 31.55239  B
2015-02-12 31.87960 21.99533 31.87960  B
2015-02-13 35.06983 22.72245 35.06983  B
2015-02-16 38.57817 24.22213 38.57817  B
2015-02-17 40.99130 24.46753 40.99130  B
2015-03-06 34.32453 34.32453 40.99130  S
2015-03-16 41.07764 34.32453 41.07764  B
2015-03-18 41.94564 34.32453 41.94564  B
2015-03-24 45.34946 37.17393 45.34946  B
2015-04-08 38.01011 38.01011 45.34946  S
2015-04-23 46.27199 37.06031 46.27199  B
2015-04-24 50.89829 37.06031 50.89829  B
2015-04-27 50.90283 37.06031 50.90283  B
2015-04-28 55.44277 37.06031 55.44277  B
2015-04-29 60.98705 37.06031 60.98705  B
2015-05-06 62.25497 45.19495 62.25497  B
2015-05-07 66.20413 46.27199 66.20413  B
2015-05-08 67.23573 50.89829 67.23573  B
2015-05-11 73.96157 50.90283 73.96157  B
2015-05-12 81.36000 55.44277 81.36000  B
2015-05-13 82.49000 57.16514 82.49000  B
2015-05-28 64.68000 64.68000 82.49000  S

接下来,我们利用交易信号数据,进行模拟交易。我们设定交易参数和规则:

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

下面我们进行模拟交易。


> # 模拟交易
> trade<-function(sdata,capital=100000,fixMoney=10000){ # 交易信号,总资金,每次定投资金
+     amount<-0
+     cash<-capital
+     
+     ticks<-data.frame()
+     for(i in 1:nrow(sdata)){
+         row<-sdata[i,]
+         if(row$op=='B'){
+             if(cash<fixMoney){
+                 print(paste(row.names(row),"No enough cash"))
+                 next
+             }
+             amount0<-floor(fixMoney/row$Value) # 本次交易量
+             amount<-amount+amount0
+             cash<-cash-amount0*row$Value
+         }
+         
+         if(row$op=='S'){
+             cash<-cash+amount*row$Value
+             amount<-0
+         }
+         
+         row$cash<-round(cash,2)
+         row$amount<-amount
+         row$asset<-round(cash+amount*row$Value,2)
+         ticks<-rbind(ticks,row)
+     }
+     
+     
+     ticks$diff<-c(0,round(diff(ticks$asset),2))
+     
+     rise<-ticks[intersect(which(ticks$diff>0),which(ticks$op=='S')),]   # 赚钱的交易
+     fall<-ticks[intersect(which(ticks$diff<0),which(ticks$op=='S')),]   # 赔钱的交易
+     
+     return(list(
+         ticks=ticks,
+         rise=rise,
+         fall=fall
+     ))
+ }

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

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


> result$ticks
              Value      min      max op      cash amount    asset      diff
2015-01-08 17.43721 13.70164 17.43721  B  90008.48    573 100000.0      0.00
2015-01-09 17.98709 13.74254 17.98709  B  80025.65   1128 100315.1    315.08
2015-01-12 19.53222 13.74254 19.53222  B  70044.68   1639 102058.0   1742.91
2015-01-15 20.21389 14.74232 20.21389  B  60059.02   2133 103175.2   1117.26
2015-01-16 22.23619 16.08749 22.23619  B  50074.97   2582 107488.8   4313.56
2015-01-19 23.04056 16.36016 23.04056  B  40075.37   3016 109565.7   2076.90
2015-01-20 23.89947 16.36016 23.89947  B  30085.39   3434 112156.2   2590.46
2015-01-26 24.77656 19.22774 24.77656  B  20100.44   3837 115168.1   3011.92
2015-01-27 25.16284 19.40043 25.16284  B  10110.79   4234 116650.2   1482.16
2015-01-30 21.99533 21.99533 25.16284  S 103239.02      0 103239.0 -13411.23
2015-02-05 26.91247 21.99533 26.91247  B  93254.49    371 103239.0      0.00
2015-02-10 28.68482 21.99533 28.68482  B  83272.17    719 103896.6    657.54
2015-02-11 31.55239 21.99533 31.55239  B  73301.62   1035 105958.3   2061.78
2015-02-12 31.87960 21.99533 31.87960  B  63323.30   1348 106297.0    338.66
2015-02-13 35.06983 22.72245 35.06983  B  53328.40   1633 110597.4   4300.43
2015-02-16 38.57817 24.22213 38.57817  B  43336.66   1892 116326.6   5729.13
2015-02-17 40.99130 24.46753 40.99130  B  33375.77   2135 120892.2   4565.63
2015-03-06 34.32453 34.32453 40.99130  S 106658.65      0 106658.6 -14233.54
2015-03-16 41.07764 34.32453 41.07764  B  96676.78    243 106658.6      0.00
2015-03-18 41.94564 34.32453 41.94564  B  86693.72    481 106869.6    210.92
2015-03-24 45.34946 37.17393 45.34946  B  76716.83    701 108506.8   1637.24
2015-04-08 38.01011 38.01011 45.34946  S 103361.92      0 103361.9  -5144.89
2015-04-23 46.27199 37.06031 46.27199  B  93367.17    216 103361.9      0.00
2015-04-24 50.89829 37.06031 50.89829  B  83391.11    412 104361.2    999.28
2015-04-27 50.90283 37.06031 50.90283  B  73414.15    608 104363.1      1.87
2015-04-28 55.44277 37.06031 55.44277  B  63434.45    788 107123.4   2760.29
2015-04-29 60.98705 37.06031 60.98705  B  53493.56    951 111492.2   4368.89
2015-05-06 62.25497 45.19495 62.25497  B  43532.77   1111 112698.0   1205.79
2015-05-07 66.20413 46.27199 66.20413  B  33535.95   1262 117085.6   4387.51
2015-05-08 67.23573 50.89829 67.23573  B  23585.06   1410 118387.4   1301.88
2015-05-11 73.96157 50.90283 73.96157  B  13600.25   1545 127870.9   9483.44
2015-05-12 81.36000 55.44277 81.36000  B   3674.33   1667 139301.5  11430.58
2015-05-28 64.68000 64.68000 82.49000  S 111495.89      0 111495.9 -27805.56

一共发生了34笔交易,其中30笔买入,4笔卖出。最后,资金剩余111495.9元,赚了11495元,收益率11.5%。

3. 模型优化

我们看到在强势格局的大牛市中,通过追涨能让我们获利颇丰。其实我们可以把模型再进一步优化的,在构建卖出信号时,是以最近10日最低价为卖出点来看,应该还有更好的卖出点可以选择。那么我们就要优化一下模型,比如按下面的优化条件。当股价低于前一个买入点价格的时进行卖出,把小于等于最近10日最低价设为止损点。按照这样的优化策略,我们是不是可以有更大的收益呢?

这样的优化思路,会让我们策略对波动更敏感,更容易被震荡出局;当然好外在于,可以更快的触发止盈和止损条件,牛市中收益更大。


# 优化条件,当股价低于前一个买入点价格时进行卖出,小于10日最低价为止损点。
> # 计算卖出的信号点
> sellPoint<-function(ldata,buydata){
+     
+     arr<-c()
+     for(i in 1:nrow(buydata)){
+         
+         if(i>1){ # 跳转第一个点
+             date<-index(buydata[i,])#;print(date)      
+             
+             # 价格 小于 上一次的买入的价格就卖出
+             last<-as.vector(buydata[i-1,]$Value) # 上一次买入的价格
+             lst<-ldata[paste(date,"/",sep="")]$Value      
+             idx<-head(which(lst < last),1)
+             
+             if(length(idx)>0){        
+                 arr<-rbind(arr,index(lst[idx]))
+             }
+         }
+     }
+     selldata<-ldata[as.Date(unique(arr)),]
+     
+     # 过滤多余的卖出点
+     bsdata<-merge(buydata$Value,selldata$Value)
+     names(bsdata)<-c("buy","Value")
+     idx1<-which(!is.na(bsdata$Value))
+     idx2<-idx1[which(c(0,diff(idx1))==1)]
+     bsdata$Value[idx2]<-NA
+     return(bsdata$Value[which(!is.na(bsdata$Value))])
+     
+ }

# 卖出信号
> selldata<-sellPoint(ldata,buydata)
> selldata
              Value
2015-01-21 22.81788
2015-01-28 23.60408
2015-02-25 36.89217
2015-03-17 39.97333
2015-03-19 40.96858
2015-03-26 39.25985
2015-05-14 74.24000

我们重新生成了,卖出的信号点有7个,比上次多出3个点,画出交易信号的图形。

04

合并买卖的交易信号。


> sdata<-signal(buydata$Value,selldata$Value)                                   # 合并交易信号
> sdata
              Value op
2015-01-08 17.43721  B
2015-01-09 17.98709  B
2015-01-12 19.53222  B
2015-01-15 20.21389  B
2015-01-16 22.23619  B
2015-01-19 23.04056  B
2015-01-20 23.89947  B
2015-01-21 22.81788  S
2015-01-26 24.77656  B
2015-01-27 25.16284  B
2015-01-28 23.60408  S
2015-02-05 26.91247  B
2015-02-10 28.68482  B
2015-02-11 31.55239  B
2015-02-12 31.87960  B
2015-02-13 35.06983  B
2015-02-16 38.57817  B
2015-02-17 40.99130  B
2015-02-25 36.89217  S
2015-03-16 41.07764  B
2015-03-17 39.97333  S
2015-03-18 41.94564  B
2015-03-19 40.96858  S
2015-03-24 45.34946  B
2015-03-26 39.25985  S
2015-04-23 46.27199  B
2015-04-24 50.89829  B
2015-04-27 50.90283  B
2015-04-28 55.44277  B
2015-04-29 60.98705  B
2015-05-06 62.25497  B
2015-05-07 66.20413  B
2015-05-08 67.23573  B
2015-05-11 73.96157  B
2015-05-12 81.36000  B
2015-05-13 82.49000  B
2015-05-14 74.24000  S

一共发生了37笔交易,其中30笔买入,7笔卖出。最后,资金剩余137483.8元,赚了37483元,收益率37.5%。

我们把卖号信号和止损信号,合并画到一张图上。


# 止损信号
> stopdata<-stopPoint(ldata,buydata)

# 合并买卖信号,止损信号
> bsdata<-merge(buydata$Value,selldata$Value,stopdata$Value)
> names(bsdata)<-c("buy","sell","stop")
> drawPoint(ldata,bsdata,title,sDate,eDate,'1 month') #画图

05

图中红色点为买点,蓝色点为优化的卖点,紫色点为止损点。从图中可以非常清楚的看到,蓝色卖出点要优于紫色的止损点。这样就达到了,模型优化的目的了。虽然只是一个很小的优化,就可以给我们带来不错的收益。

接下来,通过况客平台,我来够建一个每日更新的交易列表,实现把静态图变成了动态图。

追涨杀跌策略在牛市中会让我们赚取非常大的利润,那么对于2015年下半年行情,牛市已经不复存在,震荡市会一直持续,那么我们可以使用均值回归策略,发现逆市中的投资机会

最后总结,本文从 追涨杀跌 的思路开始,到市场特征检验,再到数学公式,R语言建模,再到历史数据回测。通过R语言,很简单地就实现了一个我们脑子中的投资想法。类似的投资想法其实谁都有,利用IT人的技术优势,可以真正地与实际操作结合起来。

这样就可以更容易地实现,从IT技术到价值的转变。IT人,加油!

转载请注明出处:
http://blog.fens.me/finance-chase-sell/

打赏作者

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

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

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

关于作者:

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

转载请注明出处:
http://blog.fens.me/finance-mean-reversion/

meanReversion

前言

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

目录

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

1. 均值回归原理

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

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

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

01

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

1.1 均值回归的3个特性

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

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

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

02

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

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

03

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

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

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

04

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

1.2 计算原理和公式

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

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

计算公式:


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

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

2. 均值回归模型和实现

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

2.1 数据准备

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

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

本文用到的数据,包括A股日K线(向前复权)数据,从2014年7月到2015年日7月,以CSV格式保存到本地文件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语言加载股票数据,由于数据所有股票都是混合在一起的,而进行计算时又需要按每支票股计算,所以在数据加载时我就进行了转换,按股票代码进行分组,生成R语言的list对象,同时把每支股票的data.frame类型对象转成XTS时间序列类型对象,方便后续的数据处理。


#加载工具包
> 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

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

2.2 均值回归模型
为了能拉近我们对市场的了解,我们取从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

我们设置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日平均线和股价的交叉。那么可以说在相同的时间周期内,短周期的移动平均线,比长周期的移动平均线更具有均值回归的特点。

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


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

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

上一步,我们已经计算出了偏离值,并保存在rate列中。下面我们要找到大于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

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

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


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

07

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


# 计算卖出的信号点
> 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

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


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

08

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


# 合并交易信号
> 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

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

  • 以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%。

在卖出时,赚钱的交易有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)

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


# 资产净值曲线
> 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

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


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

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


> 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)

从数据结果看,我们又赚到了。一共发生了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%以上的情况下,我们还朿9%正收益,那么应该是多么舒心的一件事情啊!!

3. 量化选股

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

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

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

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


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

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


# 合并数据,从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

最后,我们选出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"

我们查看万科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

通过优化的规则设计,一共有2笔交易,赚了495元。如要我们没有进行算法优化,一直交易万科A,那么会发生3笔交易,我们可以赚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

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

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

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

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

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

转载请注明出处:
http://blog.fens.me/finance-mean-reversion/

打赏作者

二条均线打天下

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

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

关于作者:

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

转载请注明出处:
http://blog.fens.me/finance-stock-ma/

stock-ma

前言

移动平均线(MA)是股市中最常用的一种技术分析方法,用来在大行情的波动段找到有效的交易信号。移动平均线不仅简单,而且有效,对股市操作具有神奇的指导作用。

据金融从业人员称,均线模型能有效地打败了大部分的主观策略,是炒股、炒期货的必备基本工具。那么本文将深入研究一下均线模型,如何在股市中发挥作用。

目录

  1. 移动平均线
  2. 均线模型
  3. 用R语言实现均线模型

1. 移动平均线

移动平均线(MA,Moving average)是以道·琼斯的”平均成本概念”为理论基础,采用统计学中”移动平均”的原理,将一段时期内的股票价格平均值连成曲线,用来显示股价的历史波动情况,进而反映股价指数未来发展趋势的技术分析方法。它是道氏理论的形象化表述。

移动平均线的计算方法就是求连续若干天的收盘价的算术平均。天数就是MA的参数。在技术分析领域中,移动平均线是必不可少的指标工具。移动平均线利用统计学上的“移动平均”原理,将每天的市场价格进行移动平均计算,求出一个趋势值,用来作为价格走势的研判工具。

计算公式: MA = (C1+C2+C3+C4+C5+….+Cn)/n ,C为收盘价,n为移动平均周期数例如,5日移动平均价格计算方法为:


MA5 = (前四天收盘价+前三天收盘价+前天收盘价+昨天收盘价+今天收盘价)/5 

移动平均线依时间长短可分为三种,即短期移动平均线,中期移动平均线,长期移动平均线。短期移动平均线一般以5日或10日为计算期间,中期移动平均线大多以30日、60日为计算期间;长期移动平均线大多以100天和200天为计算期间。

移动平均根据对数据的处理方法,又可分为3种:

  • 简单移动平均线(SMA):又称“算术移动平均线”,是指对特定期间的收盘价进行简单平均化的意思。一般所提及之移动平均线即指简单移动平均线(SMA)。
  • 加权移动平均线(WMA):加权移动平均线(Weighted Moving Average 简称WMA),是一种按时间进行加权运算的移动平均线。时间越近越近的价格,权重越大。计算方式是基于加权移动平均线日数,将每一个之前日 数比重提升。每一价格会乘以一个比重,最新的价格会有最大的比重,其之前的每一日的比重将会递减。加权移动平均线是移动平均线(MA)的改良。
  • 指数平滑移动平均线(EMA):指数平滑移动平均线EXPMA(Exponential Moving Average),为解决一旦价格已脱离均线差值扩大,而平均线未能立即反应,EXPMA可以减少类似缺点。

2. 均线模型

在日K线图中除了标准的价格K线以外,另外还有4条线,分别是白线、黄线、紫线、绿线依次分别表示:5日、10日、20日和60日移动平均线,通过这4条线与价格K线的交叉,就可以形成不同的均线模型。

以乐视网(300104)股票日K图为例,截取2012年8月到2014年7月的股价数据。
300104

最低价是13.91,出现在2012年12月;最高价55.50,出现在2014年1月。这段时期,可以看到乐视网的股价一路震荡向上,绿色线为60日均线平滑了股价,趋势性比较明显。

利用均线平滑的特点,可以发现均线与价格K线会有叉,各均线之间也有交叉,我们可以通过这些交叉点判断交易信号。

  • 黄金交叉,当10日均线由下往上穿越30日均线,10日均线在上,30日均线在下,其交叉点就是黄金交叉,黄金交叉是多头的表现,出现黄金交叉后,后市会有一定的涨幅空间,这是进场的最佳时机。
  • 死亡交叉,当30日均线与10日平均线交叉时,30日均线由下住上穿越10日平均线,形成30日平均线在上,10日均线在下时,其交点称之为”死亡交叉”,”死亡交叉”预示空头市场来临,股市将下跌此时是出场的最佳时机。

如果很好地运用移动平均线理论,再掌握行情的真正趋势,就能实现获取可观利润。

但移动平均线理论也有局限性:

  • 移动平均线是股价定型后产生的图形,反映较慢,只适用于日间交易。
  • 移动平均线不能反映股价在当日的变化及成交量的大小,不适用于日内交易。
  • 移动平均线是趋势性模型,如果股价未形成趋势,只是频繁波动,模型不适用。

3. 用R语言实现均线模型

接下来,我们利用R语言对股票数据的进行操作,来实现一个均线模型的实例。

3.1 从互联网下载数据

R语言本身提供了丰富的金融函数工具包,quantmod包就是最常用的一个,另外还要配合时间序列包zoo和xts,指标计算包TTR,可视包ggplot2等一起使用。关于zoo包和xts包的详细使用可以参考文章R语言时间序列基础库zoo可扩展的时间序列xts

我们首先利用quantmod包,从互联网下载股票数据,并以CSV格式保存到本地。


#加载工具包
> library(plyr)
> library(quantmod)
> library(TTR)
> library(ggplot2)
> library(scales)

#下载数据
> download<-function(stock,from="2010-01-01"){
+ df<-getSymbols(stock,from=from,env=environment(),auto.assign=FALSE)  #下载数据
+ names(df)<-c("Open","High","Low","Close","Volume","Adjusted")
+ write.zoo(df,file=paste(stock,".csv",sep=""),sep=",",quote=FALSE) #保存到本地
+}

#本地读数据
> read<-function(stock){  
+  as.xts(read.zoo(file=paste(stock,".csv",sep=""),header = TRUE,sep=",", format="%Y-%m-%d"))
+}

> stock<-"IBM"
> download(stock,from='2010-01-01')
> IBM<-read(stock)

# 查看数据类型
> class(IBM)
[1] "xts" "zoo"

# 查看前6条数据
> head(IBM)
             Open   High    Low  Close  Volume Adjusted
2010-01-04 131.18 132.97 130.85 132.45 6155300   121.91
2010-01-05 131.68 131.85 130.10 130.85 6841400   120.44
2010-01-06 130.68 131.49 129.81 130.00 5605300   119.66
2010-01-07 129.87 130.25 128.91 129.55 5840600   119.24
2010-01-08 129.07 130.92 129.05 130.85 4197200   120.44
2010-01-11 131.06 131.06 128.67 129.48 5730400   119.18

利用quantmod包的getSymbols()函数,默认会通过Yahoo的金融开放API下载数据,我们选择IBM的股票数据,从2010-01-01到今天2014-07-09的4年多的日间交易数据。数据类型为xts格式的时间序列,数据包括7个列,以日期做索引列,其他6列分别为 开盘价(Open), 最高价(High), 最低价(Low), 收盘价(Close), 交易量(Volume), 调整价(Adjusted)。

3.2 实现简单的蜡烛图

直接使用quantmod包的chartSeries()函数,我们可以画出可视化效果还不错的蜡烛图。

简单的蜡烛图


> chartSeries(IBM)

ibm_1

带指标的蜡烛图


> chartSeries(IBM,TA = "addVo(); addSMA(); addEnvelope();addMACD(); addROC()")

ibm_2

非常简单的2个函数,就可以实现股票数据的可视化。当然,这个功能是封装好的通用的函数,如果我们要自定策略模型,就需要自己写代码来实现了,比如 自定义的支持量化机(SVM)分类器模型,不过我们今天不讲太复杂的模型,而是实现均线模型。

3.3 自定义均线图

通过自定义的方式,我们就可以脱离quantmod包了。

我们需要自定义均线指标:

  • 日期时间序列为索引
  • 收盘价做为价格指标
  • 不考虑成交量及其他维度字段
  • 取2010-01-01至2012-01-01,形成趋势的数据
  • 画出价格曲线,5日均线,20日均线,60日是均线

R语言程序实现


#移动平均
> ma<-function(cdata,mas=c(5,20,60)){ 
+     ldata<-cdata
+     for(m in mas){
+         ldata<-merge(ldata,SMA(cdata,m))
+     }
+     ldata<-na.locf(ldata, fromLast=TRUE)
+     names(ldata)<-c('Value',paste('ma',mas,sep=''))
+     return(ldata)
+ }

# 均线图
> drawLine<-function(ldata,titie="Stock_MA",sDate=min(index(ldata)),eDate=max(index(ldata)),out=FALSE){
+     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))
+     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)
+     
+     if(out) ggsave(g,file=paste(titie,".png",sep=""))
+     else g
+ }

# 运行程序
> cdata<-IBM['2010/2012']$Close
> title<-"Stock_IBM" #图片标题
> sDate<-as.Date("2010-1-1") #开始日期
> eDate<-as.Date("2012-1-1") #结束日期

> ldata<-ma(cdata,c(5,20,60))  #选择滑动平均指标
> drawLine(ldata,title,sDate,eDate) #画图

maline

通过自己封装的移动平均函数和可视化函数,就实现了与交易软件中类似的日K线图和多条均线结合的可视化输出。

3.4 一条均线的交易策略

基于上面的定义的均线函数,我们就可以设计自己的交易策略模型了。

模型设计思路:

  • 1. 以股价和20日均线的交叉,进行交易信号的判断。
  • 2. 当股价上穿20日均线则买入(红色),下穿20日均线卖出(蓝色)。

画出股价和20日均线图


> ldata<-ma(cdata,c(20))  #选择滑动平均指标
> drawLine(ldata,title,sDate,eDate) #画图

line1_1

以散点覆盖20日均线,红色点为买入持有,蓝色点为卖出空仓。


# 均线图+散点
> drawPoint<-function(ldata,pdata,titie,sDate,eDate){
+   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))
+   g<-g+geom_point(aes(x=Index,y=Value,colour=Series),data=fortify(pdata,melt=TRUE))
+   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
+ }

# 散点数据
> genPoint<-function(pdata,ldata){} #代码省略
> pdata<-genPoint(pdata,ldata)
> head(pdata)
       Index Series    Value
1 2010-01-04   down 128.7955
2 2010-01-05   down 128.7955
3 2010-01-06   down 128.7955
4 2010-01-07   down 128.7955
5 2010-01-08   down 128.7955
6 2010-01-11   down 128.7955

> drawPoint(ldata,pdata,title,sDate,eDate) #画图

line1_2

用股价和20日均线价格做比较,把股价大于均线的部分用蓝色表示,股价小于均线的部分用红色表示。我们看到图中,蓝色点和红色点在20日均线上交替出现,我们可以在每次红色出现的第一个点买入股票,然后在蓝色的第一个点卖出股票,直观看上去的感觉还是不错的。

我们要找出这些交易信号点,做量化的统计,看看到底能不能赚钱。


#交易信号
> Signal<-function(cdata,pdata){} #代码省略
> tdata<-Signal(cdata,pdata)
> tdata<-tdata[which(as.Date(row.names(tdata)) head(tdata)
            Value op
2010-01-04 132.45  B
2010-01-22 125.50  S
2010-02-17 126.33  B
2010-03-09 125.55  S
2010-03-11 127.60  B
2010-04-08 127.61  S

# 交易记录
> nrow(tdata)
[1] 72

一共有72条交易记录,买卖各占一半。

接下来,我们要利用交易信号数据,进行模拟交易。我们设定交易参数,以$10W为本金,满仓买入或卖出,手续为0,传入交易信号。


#模拟交易
#参数:交易信号,本金,持仓比例,手续费比例
> trade<-function(tdata,capital=100000,position=1,fee=0){} #代码省略
> result1<-trade(tdata,100000)

# 查看每笔交易
> head(result1$ticks)
            Value op     cash amount     asset     diff
2010-01-04 132.45  B     0.25    755 100000.00     0.00
2010-01-22 125.50  S 94752.75      0  94752.75 -5247.25
2010-02-17 126.33  B     5.25    750  94752.75     0.00
2010-03-09 125.55  S 94167.75      0  94167.75  -585.00
2010-03-11 127.60  B   126.55    737  94167.75     0.00
2010-04-08 127.61  S 94175.12      0  94175.12     7.37

# 盈利的交易
> head(result1$rise)
            Value op     cash amount    asset     diff
2010-03-11 127.60  B   126.55    737 94167.75     0.00
2010-04-08 127.61  S 94175.12      0 94175.12     7.37
2010-07-22 127.47  B   108.79    633 80797.30     0.00
2010-08-12 128.30  S 81322.69      0 81322.69   525.39
2010-09-09 126.36  B   120.40    632 79979.92     0.00
2010-11-16 142.24  S 90016.08      0 90016.08 10036.16

# 亏损的交易
> head(result1$fall)
            Value op     cash amount     asset     diff
2010-01-04 132.45  B     0.25    755 100000.00     0.00
2010-01-22 125.50  S 94752.75      0  94752.75 -5247.25
2010-02-17 126.33  B     5.25    750  94752.75     0.00
2010-03-09 125.55  S 94167.75      0  94167.75  -585.00
2010-04-09 128.76  B    51.56    731  94175.12     0.00
2010-04-12 128.36  S 93882.72      0  93882.72  -292.40

通过模拟交易,我们就能精确地算出每笔交易的盈利情况了。你相信么,有56笔交易其实是亏损的,16笔交易是有盈利的。

查看最后的资金情况。


> tail(result1$ticks,1)
            Value op     cash amount    asset     diff
2011-12-21 181.47  S 96363.76      0 96363.76 -3063.87

最后,资金剩余96363.76元,也就是我们亏了3636.24元。

为什么最后会亏损呢?中间的大波段应该赚到了足够多的钱。通过资金曲线我们可以找到亏损的原因。

画出资金曲线


# 股价+现金流量
> drawCash<-function(ldata,adata){
+   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)
+   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
+ }

# 现金流量
> adata<-as.xts(result1$ticks[which(result1$ticks$op=='S'),]['cash'])
> drawCash(ldata,adata)

line1_3

我们把股价和现金流量并排放置,从2010-09开始均线策略开始大幅赚钱,到2011-10到达最高点,并且超过了本金,然后开始下滑,直截到2012-01亏损3859.86元。这是由于我们把赚到利润继续投资,增大了头寸,以至于2011年底的震荡市让模型失效,从而赔了更多的钱。

这样就完成一条20日均线的交易策略模型,并用IBM的股票做了测试。

3.5 二条均线的交易策略

一条均线模型,在大的趋势下是可以稳定赚钱的,但由于一条均线对于波动非常敏感性,如果小波动过于频繁,不仅会增加交易次数,而且会让模型失效。然后,就有二条均线的策略模型,可以减低对波动的敏感性。

二条均线策略模型,与一条均线模型思路类似,以5日均线价格替换股价,是通过5日均线和20日均线交叉来进行信号交易的。

我们首先画出股价,5日均线和20日均线图。


> ldata<-ma(cdata,c(5,20))  #选择滑动平均指标
> drawLine(ldata,title,sDate,eDate) #画图

line2_1

以散点覆盖20日均线,红色点为买入持有,紫色点为卖出空仓。


# 散点数据
> pdata<-genPoint(pdata,ldata)
> head(pdata)
       Index Series    Value
1 2010-01-04   down 128.7955
2 2010-01-05   down 128.7955
3 2010-01-06   down 128.7955
4 2010-01-07   down 128.7955
5 2010-01-08   down 128.7955
6 2010-01-11   down 128.7955
> drawPoint(ldata,pdata,title,sDate,eDate) #画图

line2_2

用5日均线和20日均线价格做比较,把5日大于均线的部分用紫色表示,股价小于均线的部分用红色表示。我们看到图中,紫色点和红色点在20日均线上交替出现,同样地,我们可以在每次红色出现的第一个点买入股票,然后在紫色的第一个点卖出股票,直观看上去的与一条均线模型类似,都是赚钱的。

我们要找出这些交易信号点,做量化的统计,看看到底能不能赚钱。


> tdata<-Signal(cdata,pdata)
> tdata<-tdata[which(as.Date(row.names(tdata)) head(tdata)
            Value op
2010-01-04 132.45  B
2010-01-26 125.75  S
2010-02-18 127.81  B
2010-03-10 125.62  S
2010-03-16 128.67  B
2010-04-12 128.36  S

# 交易记录
> nrow(tdata)
[1] 36

一共有36条交易记录,买卖各占一半,比一条均线模型少了36笔交易。

利用交易信号数据,进行模拟交易。我们设定交易参数,以$10W为本金,满仓买入或卖出,手续为0,传入交易信号。


#模拟交易
> result2<-trade(tdata,100000)

# 查看每笔交易
> head(result2$ticks)
            Value op     cash amount     asset     diff
2010-01-04 132.45  B     0.25    755 100000.00     0.00
2010-01-26 125.75  S 94941.50      0  94941.50 -5058.50
2010-02-18 127.81  B   106.48    742  94941.50     0.00
2010-03-10 125.62  S 93316.52      0  93316.52 -1624.98
2010-03-16 128.67  B    30.77    725  93316.52     0.00
2010-04-12 128.36  S 93091.77      0  93091.77  -224.75

# 盈利的交易
> head(result2$rise)
            Value op      cash amount     asset     diff
2010-09-10 127.99  B     75.34    649  83140.85     0.00
2010-11-18 144.36  S  93764.98      0  93764.98 10624.13
2010-12-07 144.02  B      2.66    638  91887.42     0.00
2011-02-23 160.18  S 102197.50      0 102197.50 10310.08
2011-03-28 161.37  B    124.70    582  94042.04     0.00
2011-05-20 170.16  S  99157.82      0  99157.82  5115.78

# 亏损的交易
> head(result2$fall)
            Value op     cash amount     asset     diff
2010-01-04 132.45  B     0.25    755 100000.00     0.00
2010-01-26 125.75  S 94941.50      0  94941.50 -5058.50
2010-02-18 127.81  B   106.48    742  94941.50     0.00
2010-03-10 125.62  S 93316.52      0  93316.52 -1624.98
2010-03-16 128.67  B    30.77    725  93316.52     0.00
2010-04-12 128.36  S 93091.77      0  93091.77  -224.75

通过模拟交易,我们精确地算出每笔交易的盈利情况了,有26笔交易是亏损的,16笔交易是有盈利的。

查看最后的资金情况。


> tail(result2$ticks,1)
            Value op    cash amount   asset     diff
2011-12-19 182.89  S 96828.9      0 96828.9 -3581.33

最后,资金剩余96828.9元,亏了3171.1元。

查看资金曲线。


> adata<-as.xts(result2$ticks[which(result2$ticks$op=='S'),]['cash'])
> drawCash(ldata,adata)

line2_3

我们可以发现,虽然最后资金也是赔了3171.1,比一条均线策略模型赔的小一点,但二条均线策略模型有3次高于本金的情况,而且最差的情况也比一条均线最差的情况要好。

3.6 对比两个模型的盈利情况

我们再进一步对比两个模型的盈利情况,找出两个模型中所有赚钱的交易。


# 盈利的交易
> rise<-merge(as.xts(result1$rise[1]),as.xts(result2$rise[1]))
> names(rise)<-c("plan1","plan2")

# 查看数据情况
> rise
            plan1  plan2
2010-03-11 127.60     NA
2010-04-08 127.61     NA
2010-07-22 127.47     NA
2010-08-12 128.30     NA
2010-09-09 126.36     NA
2010-09-10     NA 127.99
2010-11-16 142.24     NA
2010-11-18     NA 144.36
2010-12-07     NA 144.02
2010-12-08 144.98     NA
2011-02-22 161.95     NA
2011-02-23     NA 160.18
2011-03-25 162.18     NA
2011-03-28     NA 161.37
2011-05-16 168.86     NA
2011-05-20     NA 170.16
2011-06-21 166.22     NA
2011-06-23     NA 166.12
2011-08-02 178.05     NA
2011-08-04     NA 171.48
2011-09-14 167.24     NA
2011-09-16     NA 172.99
2011-09-22 168.62     NA
2011-09-23 169.34     NA
2011-10-18 178.90     NA
2011-10-21     NA 181.63

plan1是一条均线模型,plan2是二条均线模型。plan1比plan2多了6次交易,显然多的这几次交易是由于对波动敏感性引起的,反而减少了趋势行情收益。

最后,我们画一下盈利部分的交易区间


> # 均线图+交易区间
> drawRange<-function(ldata,plan,titie="Stock_2014",sDate=min(index(ldata)),eDate=max(index(ldata)),out=FALSE){
+   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))
+   g<-g+geom_rect(aes(NULL, NULL,xmin=start,xmax=end,fill=plan),ymin = yrng[1], ymax = yrng[2],data=plan)
+   g<-g+scale_fill_manual(values =alpha(c("blue", "red"), 0.2))
+   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)
+   
+   if(out) ggsave(g,file=paste(titie,".png",sep=""))
+   else g
+ }

#盈利区间
> plan<-comPlan(ldata,result1,result2){} # 代码省略
> drawRange(ldata,plan,title,sDate,eDate) #画图

plan1的盈利区间。
line3_1

plan1和plan2同时存在的盈利区间。
line3_2

从盈利区间我们可以看到,印证一条均线对波动敏感性的问题,二条均线模型是对一条均线模型的优化,这样我们就一个完整均线模型的实例研发。

3.7 模型优化

如果从交易的角度讲,上面的模型还不能算完成,因为还有很多的赔钱交易,要进行更多地优化,减少最大回撤,在更确定的时机做多,反向做空等。模型优化的问题,会在后面的文章中再进行详细的介绍。

看起来均线模型是如此的简单,但实盘交易时真能在趋势行情中跑赢双均线(优化)模型,也真不是一件容易的事情。二条均线打天下,不说东方不败,也是独孤求败。

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

转载请注明出处:
http://blog.fens.me/finance-stock-ma/

打赏作者

股指是什么?

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

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

关于作者:

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

转载请注明出处:
http://blog.fens.me/finance-index/

finance-index

前言

对于刚进股市的新手,一般都是比较盲目的选股。而中国大妈型的股民,一般都是听电视的财经节目,推荐的股票来选股的。不清楚基本面,是最容易被套死股市里的。

如果能简单地了解一下股指,从“沪深300”中选股,也许能够稍微弥补一下对基本面的知识的不足。

注:本人金融入门级,如果文章描述不对或者不准确的地方,还请专家指点。

目录

  1. 股指是什么?
  2. 中国证券市场的股指
  3. 沪深300指数
  4. 沪深300指数统计分析

1. 股指是什么?

股指是股票价格指数简称,股票价格指数即股票指数。是由证券交易所或金融服务机构编制的表明股票行市变动的一种供参考的指示数字。由于股票价格起伏无常,投资者必然面临市场价格风险。对于具体某一种股票的价格变化,投资者容易了解,而对于多种股票的价格变化,要逐一了解,既不容易,也不胜其烦。为了适应这种情况和需要,一些金融服务机构就利用自己的业务知识和熟悉市场的优势,编制出股票价格指数,公开发布,作为市场价格变动的指标。投资者据此就可以检验自己投资的效果,并用以预测股票市场的动向。

计算股票指数,要考虑三个因素:

  • 抽样,即在众多股票中抽取少数具有代表性的成份股
  • 加权,按单价或总值加权平均,或不加权平均
  • 计算程序,计算算术平均数、几何平均数,或兼顾价格与总值

股价平均数的计算

1). 简单算术股价平均数

简单算术股价平均数是将样本股票每日收盘价之和除以样本数得出的,即:
简单算术股价平均数=(P1+P2+P3+…+ Pn)/n

世界上第一个股票价格平均──道·琼斯股价平均数在1928年10月1日前就是使用简单算术平均法计算的。

现假设从某一股市采样的股票为A、B、C、D四种,在某一交易日的收盘价分别为10元、16元、24元和30元,计算该市场股价平均数。将上述数置入公式中,即得:
股价平均数=(P1+P2+P3+P4)/n=(10+16+24+30)/4=20(元)

有两个缺点:

  • 未考虑各种样本股票的权数,从而不能区分重要性不同的样本股票对股价平均数的不同影响
  • 当样本股票发生股票分割派发红股、增资等情况时,股价平均数会产生断层而失去连续性,使时间序列前后的比较发生困难。例如,上述D股票发生以1股分割为3股时,股价势必从30元下调为10元, 这时平均数就不是按上面计算得出的20元,而是(10+16+24+10)/4=15(元)。这就是说,由于D股分割技术上的变化,导致股价平均数从20元下跌为15元(这还未考虑其他影响股价变动的因素),显然不符合平均数作为反映股价变动指标的要求。

2). 修正的股份平均数
修正的股价平均数有两种:

  • 除数修正法,又称道式修正法。这是美国道·琼斯在1928年创造的一种计算股价平均数的方法。该法的核心是求出一个常数除数,以修正因股票分割、增资、发放红股等因素造成股价平均数的变化,以保持股份平均数的连续性和可比性。具体作法是以新股价总额除以旧股价平均数,求出新的除数,再以计算期的股价总额除以新除数,这就得出修正的股价平均数。即:
    新除数=变动后的新股价总额/旧的股价平均数
    修正的股价平均数=报告期股价总额/新除数

    在前面的例子除数是4,经调整后的新的除数应是:
    新的除数=(10+16+24+10)/20=3,将新的除数代入下列式中,则:
    修正的股价平均数=(10+16+24+10)/3=20(元)

    得出的平均数与未分割时计算的一样,股价水平也不会因股票分割而变动。

  • 股价修正法。股价修正法就是将股票分割等,变动后的股价还原为变动前的股价,使股价平均数不会因此变动。美国《纽约时报》编制的500种股价平均数就采用股价修正法来计算股价平均数

3). 加权股价平均数
加权股价平均数是根据各种样本股票的相对重要性进行加权平均计算的股价平均数,其权数(Q) 可以是成交股数、股票总市值、股票发行量等。

股票指数

1). 道·琼斯股票指数

道·琼斯股票指数是世界上历史最为悠久的股票指数,它的全称为股票价格平均数。它是在1884年由道·琼斯公司的创始人查理斯·道开始编制的。其最初的道·琼斯股票价格平均指数是根据11种具有代表性的铁路公司的股票,采用算术平均法进行计算编制而成,发表在查理斯·道自己编辑出版的《每日通讯》上。

其计算公式为:
股票价格平均数=入选股票的价格之和/入选股票的数量。

自1897年起,道·琼斯股票价格平均指数开始分成工业与运输业两大类,其中工业股票价格平均指数包括12种股票,运输业平均指数则包括20种股票,并且开始在道·琼斯公司出版的《华尔街日报》上公布。在1929年,道·琼斯股票价格平均指数又增加了公用事业类股票,使其所包含的股票达到65种,并一直延续至今。

道·琼斯股票价格平均指数是以1928年10月1日为基期,因为这一天收盘时的道·琼斯股票价格平均数恰好约为100美元,所以就将其定为基准日。而以后股票价格同基期相比计算出的百分数,就成为各期的投票价格指数,所以股票指数普遍用点来做单位,而股票指数每一点的涨跌就是相对于基准日的涨跌百分数。

2). 标准·普尔股票价格指数

除了道·琼斯股票价格指数外,标准·普尔股票价格指数在美国也很有影响,它是美国最大的证券研究机构即标准·普尔公司编制的股票价格指数。该公司于1923年开始编制发表股票价格指数。最初采选了230种股票,编制两种股票价格指数。到1957年,这一股票价格指数的范围扩大到500种股票,分成95种组合。其中最重要的四种组合是工业股票组、铁路股票组、公用事业股票组和500种股票混合组。从1976年7月1日开始,改为 400种工业股票,20种运输业股票,40种公用事业股票和40种金融业股票。几十年来,虽然有股票更迭,但始终保持为500种。标准·普尔公司股票价格指数以1941年至1943年抽样股票的平均市价为基期,以上市股票数为权数,按基期进行加权计算,其基点数为10。以股票市场价格乘以股票市场上发行的股票数量为分子,用基期的股票市场价格乘以基期股票数为分母,相除之数再乘以10就是股票价格指数。

3). 纽约证券交易所股票价格指数

纽约证券交易所股票价格指数。这是由纽约证券交易所编制的股票价格指数。它起自1966年6月,先是普通股股票价格指数,后来改为混合指数,包括着在纽约证券交易所上市的1500家公司的1570种股票。具体计算方法是将这些股票按价格高低分开排列,分别计算工业股票、金融业股票、公用事业股票、运输业股票的价格指数,最大和最广泛的是工业股票价格指数,由1093种股票组成;金融业股票价格指数包括投资公司、储蓄贷款协会、分期付款融资公司、商业银行、保险公司和不动产公司的223种股票;运输业股票价格指数包括铁路、航空、轮船、汽车等公司的65种股票;公用事业股票价格指数则有电话电报公司、煤气公司、电力公司和邮电公司的189种股票。

纽约股票价格指数是以1965年12月31日确定的50点为基数,采用的是综合指数形式。纽约证券交易所每半个小时公布一次指数的变动情况。虽然纽约证券交易所编制股票价格指数的时间不长,因它可以全面及时地反映其股票市场活动的综合状况,较为受投资者欢迎。

4). 日经道·琼斯股价指数(日经平均股价)

系由日本经济新闻社编制并公布的反映日本股票市场价格变动的股票价格平均数。该指数从1950年9月开始编制。

日经道·琼斯股价指数指数分为:

  • 日经225股指指数(日经225)。因此种指数延续时间较长,具有很好的可比性,成为考察日本股票市场股价长期演变及最新变动最常用和最可靠的指标,传媒日常引用的日经指数就是指这个指数。
  • 日经300股指指数(日经300)此指数是以发行量加重平均方式来计算
  • 日经综合股指指数(日经综合)此指数是以发行量加重平均方式来计算
  • 日经店头平均股票价格指数。

5). 香港恒生指数

香港恒生指数是香港股票市场上历史最久、影响最大的股票价格指数,由香港恒生银行于1969年11月24日开始发表。

这些股票占香港股票市值的63.8%,因该股票指数涉及到香港的各个行业,具有较强的代表性。

恒生股票价格指数的编制是以1964年7月31日为基期,因为这一天香港股市运行正常,成交值均匀,可反映整个香港股市的基本情况,基点确定为100点。其计算方法是将33种股票按每天的收盘价乘以各自的发行股数为计算日的市值,再与基期的市值相比较,乘以100就得出当天的股票价格指数。

由于恒生股票价格指数所选择的基期适当,因此,不论股票市场狂升或猛跌,还是处于正常交易水平,恒生股票价格指数基本上能反映整个股市的活动情况。

6). 我国内地的股票指数

上证股票指数系由上海证券交易所编制的股票指数,1990年12月19日正式开始发布。该股票指数的样本为所有在上海证券交易所挂牌上市的股票,其中新上市的股票在挂牌的第二天纳入股票指数的计算范围。

该股票指数的权数为上市公司的总股本。由于我国上市公司的股票有流通股和非流通股之分,其流通量与总股本并不一致,所以总股本较大的股票对股票指数的影响就较大,上证指数常常就成为机构大户造市的工具,使股票指数的走势与大部分股票的涨跌相背离。

深圳综合股票指数系由深圳证券交易所编制的股票指数,1991年4月3日为基期。该股票指数的计算方法基本与上证指数相同,其样本为所有在深圳证券交易所挂牌上市的股票,权数为股票的总股本。由于以所有挂牌的上市公司为样本,其代表性非常广泛,且它与深圳股市的行情同步发布,它是股民和证券从业人员研判深圳股市股票价格变化趋势必不可少的参考依据。在前些年,由于深圳证交所的股票交投不如上海证交所那么活跃,深圳证券交易所现已改变了股票指数的编制方法,采用成分股指数,其中只有40只股票入选并于1995年5月开始发布。

文字介绍,摘自:http://baike.baidu.com/view/897308.htm

2. 中国证券市场的股指

  • 上证180指数
  • 上证综指
  • 上证A股
  • 上证B股
  • 上证ADL指标
  • 上证多空指标
  • 上证50指数
  • 上证基金指数
  • 上证红利指数
  • 深证100指数
  • 深证成份
  • 深证综指
  • 深证A股
  • 深证B股
  • 深证ADL指标
  • 深证多空指标
  • 创业板指数
  • 中小企业指数
  • 沪深300指数

上证180指数

index-sh-180

  • 指数代码:000010
  • 指数名称:上证成份指数(简称上证180指数)
  • 指数类别:股票类
  • 创建人 :上海证券交易所
  • 指数基期:2002-06-28
  • 指数基点:3299.0600
  • 计算价格:收盘价
  • 加权方式:派许加权方法
  • 指数简介:上证成份指数(简称上证180指数)是上海证券交易所对原上证30指数进行了调整并更名而成的,其样本股是在所有A股股票中抽取最具市场代表性的180种样本股票,自2002年7月1日起正式发布.作为上证指数系列核心的上证180指数的编制方案,目的在于建立一个反映上海证券市场的概貌和运行状况,具有可操作性和投资性,能够作为投资评价尺度及金融衍生产品基础的基准指数.
  • 成份股的选择:在确定样本空间的基础上,上证180指数根据以下四个步骤进行选样. 据总市值,流通市值,成交金额和换手率对股票进行综合排名.具体方法是:第i行业样本配额=第i行业所有候选股票流通市值之和/上海市场所以候选股票流通市值之和*180
  • 指数计算:报告期指数=报告期成份股的调整市值/基日成份股的调整市值*1000

上证综指

index-sh

上证综指即“上证综合指数”-(上海证券综合指数),英文是:Shanghai(securities)composite index. 通常简称:“Shanghai composite index”(上证综指) 。“上海证券综合指数”它是上海证券交易所编制的,以上海证券交易所挂牌上市的全部股票为计算范围,以发行量为权数综合。上证综指反映了上海证券交易市场的总体走势。指数代码:999999。

上证综合指数是最早发布的指数,是以上证所挂牌上市的全部股票为计算范围,以发行量为权数的加权综合股价指数。这一指数自1991年7月15日起开始实时发布,基日定为1990年12月19日,基日指数定为100点。

新上证综指发布以2005年12月30日为基日,以当日所有样本股票的市价总值为基期,基点为1000点。新上证综指简称“新综指”,指数代码为000017。

文字介绍,摘自:http://baike.baidu.com/view/1283709.htm

上证A股

index-sh-a

  • 指数代码:000002
  • 指数名称:上证A股指数
  • 指数类别:股票类
  • 创建人 :上海证券交易所
  • 指数基期:1990-12-19
  • 指数基点:100
  • 计算价格:收盘价
  • 加权方式:派许加权方法
  • 指数简介:上证A股指数的样本股是全部上市A股,反映了A股的股价整体变动状况,自1992年2月21日起正式发布.
  • 成份股的选择:上证A股指数的样本股是全部上市A股股票
  • 指数计算:报告期指数=报告期成份股的总市值 / 基期 * 基期指数

上证B股

index-sh-b

  • 指数代码:000003
  • 指数名称:上证B股指数
  • 指数类别:股票类
  • 创建人 :上海证券交易所
  • 指数基期:1990-12-19
  • 指数基点:100
  • 计算价格:收盘价
  • 加权方式:派许加权方法
  • 指数简介:上证B股指数的样本股是全部上市B股,反映了B股的股价整体变动状况,自1992年2月21日起正式发布.
  • 成份股的选择:上证B股指数的样本股是全部上市B股
  • 指数计算:报告期指数 =报告期成份股的总市值 / 基 期 * 基期指数

上证ADL指标

2013年12月31日截图
index-sh-adl

上证ADL指标是指上海证券交易所的股票腾落指数。ADL(Advance Decline Line)中文名称为腾落指数,其实就是上升下降曲线的意思。ADL是分析趋势的。以股票市场为例,ADL利用简单的加减法,计算每天股票上涨公司数量和下降公司数量的累计结果,与综合指数相对比,对大势的未来进行预测。

ADL的计算公式为:
今日ADL=昨日ADL+Na-Nd
推出:今日ADL=∑Na-∑Nd。

  • ∑Na—从开始交易的第一天算起,每一个交易日的上涨家数的总和。
  • ∑Nd—从开始交易的第一天算起,每一个交易日的下跌家数的总和。

腾落指数与股价指数比较类似,两者均为反映大势的动向与趋势,不对个股的涨跌提供讯号,但由于股价指数在一定情况下受制于权值大的股只,当这些股只发生暴涨与暴跌时,股价指数有可能反应过度,从而给投资者提供不实的信息,腾落指数则可以弥补这一类一缺点。由于腾落指数与股价指数的关系比较密切,观图时应将两者联系起来。一般情况下,股价指数上和或,腾落指数亦上升,或两者皆跌,则可以对升势或跌势进行确认。如若股价指数大动而腾落指数横行,或两者反方面波动,不可互相印证,说明大势不稳,不可贸然入市。

具体来说有以下六种情况:

  • 股价指数持续上涨,腾落指数亦上升,股价可能仍将继续上升。
  • 股价指数持续下跌,腾落指数亦下降,股价可能仍将继续下跌。
  • 股价指数上涨,而腾落指数下降,股价可能回跌。
  • 股价指数下跌,而腾落指数上升,股价可能回升。
  • 股市处于多头市场时,腾落指数呈上升趋势,其间如果突然出现急速下跌现象,接着又立即扭头向上,创下新高点,则表示引情可能再创新高。
  • 股市处于空头市场时,ADL呈现下降趋势,其间如果突然出现上升现象,接着又回头,下跌突破原先所创低点,则表示另一段新的下跌趋势产生

文字介绍,摘自:http://baike.baidu.com/view/8321995.htm

上证多空指标

2013年12月31日截图
index-sh-bbi

多空指标英文全名为“BullAndBearIndex”,简称BBI,是一种将不同日数移动平均线加权平均之后的综合指标,属于均线型指标。

在使用移动平均线时,投资者往往对参数值选择有不同的偏好,而多空指标恰好解决了中短期移动平均线的期间长短合理性问题

在钱龙分析系统中,多空指标的原始参数值是3、6、12、24,将3日、6日、12日、24日四个平均股价(或指数)相加后除以4得出多空指标的数值,

计算公式:
BBI=(3日MA+6日MA+12日MA+24日MA)/4

文字介绍,摘自:http://baike.baidu.com/view/658748.htm

上证50指数

index-sh-50

  • 指数代码:000016
  • 指数名称:上证50指数
  • 指数类别:股票类
  • 创建人 :上海证券交易所
  • 指数基期:2003-12-31
  • 指数基点:1000
  • 计算价格:收盘价
  • 加权方式:派许加权方法
  • 指数简介:上证50指数是根据科学客观的方法,挑选上海证券市场规模大,流动性好的最具代表性的50只股票组成样本股,以便综合反映上海证券市场最具市场影响力的一批龙头企业的整体状况.
  • 成份股的选择:根据流通市值,成交金额对股票进行综合排名,原则上挑选排名前50位的股票组成样本,但市场表现异常并经专家委员会认定不宜作为样本的股票除外
  • 指数计算:报告期指数 =报告期成份股的调整市值 / 基 期 * 基期指数

上证基金指数

index-sh-fund

  • 指数代码:000011
  • 指数名称:上证基金指数
  • 指数类别:基金类
  • 创建人 :上海证券交易所
  • 指数基期:2000-05-08
  • 指数基点:1000
  • 计算价格:收盘价
  • 加权方式:派许加权方法
  • 指数简介:基金指数的成份股是所有在上海证券交易所上市的证券投资基金,反映了基金的价格整体变动状况.
  • 指数计算:报告期指数 = 报告期基金的总市值 / 基 期 * 基期指数

上证红利指数

index-sh-dvi

  • 指数代码:000015
  • 指数名称:上证红利指数
  • 指数类别:股票类
  • 创建人 :上海证券交易所
  • 指数基期:2004-12-31
  • 指数基点:1000
  • 计算价格:收盘价
  • 加权方式:派许加权方法
  • 指数简介:上证红利指数挑选在上证所上市的现金股息率高,分红比较稳定,具有一定规模及流动性的50只股票作为样本,以反映上海证券市场高红利股票的整体状况和走势.
  • 成份股的选择:对样本空间的股票,按照过去两年的平均现金股息率(税后)进行排名,挑选排名最前的50只股票组成样本股,但市场表现异常并经专家委员会认定不宜作为样本的股票除外
  • 指数计算:报告期指数 =报告期成份股的调整市值 / 基 期 * 基期指数

深证100指数

index-sz-100

  • 指数代码:399004
  • 指数名称:深证100全收益指数
  • 指数类别:股票类
  • 创建人 :深圳证券信息公司
  • 指数基期:2002-12-31
  • 指数基点:1000
  • 计算价格:收盘价
  • 指数简介:深证100指数由深圳市场选取100只A股作为样本编制而成,为深市多层次市场指数体系的核心指数之一,包括全收益指数(深证100R)和价格指数(深证100P).
  • 成份股的选择:计算入围个股在考察期(6 个月)的平均流通市值及平均成交金额所占市场比重,将上述指标按2:1 权重加权计算,再将结果从高到低排序,选取排名前100 名股票构成指数成份股

深证成份指数

index-sz

深证成份股指数,是深圳证券交易所编制的一种成份股指数,是从上市的所有股票中抽取具有市场代表性的40家上市公司的股票作为计算对象,并以流通股为权数计算得出的加权股价指数,综合反映深交所上市A、B股的股价走势。

深圳成份股指数(399001)的内容与发布编码。深圳交易所从于1995年1月23日正式发布,1995年5月5日正式启用。以新证券挂牌方式从行情中实时发布成份股指数,成份股指数(不含分类指数)发布名称、编码见下表:

文字介绍,摘自:http://baike.baidu.com/view/658748.htm

深证综指

index-sz

深证综合指数是深圳证券交易所编制的,以深圳证券交易所挂牌上市的全部股票为计算范围,以发行量为权数的加权综合股价指数。

深证综合指数是深圳证券交易所从1991年4月3日开始编制并公开发表的一种股价指数,该指数规定1991年4月3日为基期,基期指数为100点。综合指数以所有在深圳证交所上市的所有股票为计算范围,以发行量为权数的加权综合股价指数,其基本计算公式为:即日综合指数=(即日指数股总市值/基日指数股总市值×基日指数),每当发行新股上市时,从第二天纳入成份股计算,这时上式中的分母下式调整。

新股上市后,计算公式:
基日指数总市值=原来的基日指数股总市值+新股发行数量×上市第十个交易日收盘价

文字介绍,摘自:http://baike.baidu.com/view/21880.htm

深证A股

index-sz-a

  • 指数代码:399107
  • 指数名称:深证A股指数
  • 指数类别:股票类
  • 创建人 :深圳证券信息公司
  • 指数基期:1991-04-03
  • 指数基点:100
  • 成份股的选择:在深圳证券交易所主板、中小板、创业板上市的全部A股/li>
  • 指数计算:实时指数=上一交易日收市指数×[Σ(样本股实时成交价×样本股总股本)] / [Σ(样本股上一交易日收市价×样本股总股本)]

深证B股

index-sz-b

  • 指数代码:399108
  • 指数名称:深证B股指数
  • 指数类别:股票类
  • 创建人 :深圳证券信息公司
  • 指数基期:1992-02-28
  • 指数基点:100
  • 成份股的选择:在深圳证券交易所上市的全部B股/li>
  • 指数计算:实时指数=上一交易日收市指数×[Σ(样本股实时成交价×样本股总股本)] / [Σ(样本股上一交易日收市价×样本股总股本)]

深证ADL指标

2013年12月31日截图
index-sz-adl

同上证ADL指标。

深证多空指标

2013年12月31日截图
index-sz-bbi

同上证多空指标。

创业板指数

index-gem

  • 指数代码:399006
  • 指数名称:创业板价格指数
  • 指数类别:股票类
  • 创建人 :深圳证券信息公司
  • 指数基期:2010-05-31
  • 指数基点:1000
  • 指数简介:为了更全面地反映创业板市场情况,向市场各类投资者提供更多的跟踪投资目标指数,推进指数基金产品以及丰富证券市场产品品种,为了方便投资者参考,本次同步发布收益指数及价格指数,其中价格指数对样本股公司派息不作除权调整处理,任指数自然回落
  • 成份股的选择:创业板指数的初始成份股为指数发布之日已纳入深证综合指数计算的全部创业板股票。在指数样本未满100只之前,新上市创业板股票在上市后第十一个交易日纳入指数计算;在指数样本数量满100只之后,样本数量锁定为100只,并依照定期调样规则实施样本股定期调样。
  • 指数计算: 创业板指数以2010年5月31日为基日,基点为1000点。创业板指数的计算方法与深证系列其它指数相同,采用自由流通量加权,并按照派氏加权法进行计算。创业板指数调整计算方法与深证100指数等深证系列指数相同

中小企业指数

index-sme

  • 指数代码:399005
  • 指数名称:中小板价格指数
  • 指数类别:股票类
  • 创建人 :深圳证券信息公司
  • 指数基期:2005-06-07
  • 指数基点:1000
  • 指数简介:中小板指数是中国多层次证券市场的重要指数,由100家具有代表性的中小板公司组成.中小板指数包括价格指数(中小板指数P)和全收益指数(中小板指数R),价格指数于200
  • 成份股的选择:计算入围个股在考察期的平均流通市值及平均成交金额所占市场比重,将上述指标按2:1 权重加权计算,再将结果从高到低排序,选取排名前100 名股票构成指数成份股.

沪深300指数

index-ss-300

  • 指数代码:399300
  • 指数名称:沪深300指数
  • 指数类别:股票类
  • 创建人 :深圳证券信息公司
  • 指数基期:2004-12-31
  • 指数基点:1000
  • 指数简介:沪深300指数是由上海和深圳证券市场中选取300只A股作为样本编制而成的成份股指数. 沪深300指数样本覆盖了沪深市场六成左右的市值,具有良好的市场代表性.
  • 成份股的选择:对样本空间股票在最近一年(新股为上市以来)的日均成交金额由高到低排名,剔除排名后50%的股票,然后对剩余股票按照日均总市值由高到低进行排名,选取排名在前300名的股票作为样本股

3. 沪深300指数

沪深300指数是沪深证券交易所于2005年4月8日联合发布的反映A股市场整体走势的指数。沪深300指数编制目标是反映中国证券市场股票价格变动的概貌和运行状况,并能够作为投资业绩的评价标准,为指数化投资和指数衍生产品创新提供基础条件。

  • 沪市000300
  • 深市399300

沪深300指数是由上海和深圳证券市场中选取300只A股作为样本,其中沪市有179只,深市121只。

样本选择标准为规模大、流动性好的股票。
沪深300指数样本覆盖了沪深市场六成左右的市值,具有良好的市场代表性。

主要特点:

  • 严格的样本选择标准,定位于交易性成份指数
  • 采用自由流通量为权数
  • 采用分级靠档法确定成份股权重
  • 样本股稳定性高,调整设置缓冲区
  • 指数行业分布状况基本与市场行业分布比例一致

主要优势:

  • 沪深300成分股的盈利能力突出
  • 沪深300成分股具备较好的成长性
  • 沪深300成分股的分红与股息收益高于市场平均水平
  • 沪深300成分股估值水平低于市场平均水平
  • 沪深300成分股代表了机构投资取向

从基本面来看,沪深300指数成分股在两年的运行中体现了较好的盈利性、成长性和分红收益能力,同时,相对于市场平均水平,其估值优势也较为明显,已经逐渐成为机构投资者乃至整个市场的投资取向标杆。那么,就股指期货而言,沪深300指数有利于得到更多机构的关注,从而更有益于形成以机构投资者为主的投资者结构。

沪深300指数发布,除了要真实反映A股市场状况,为市场提供一个投资标尺外,还有一个重要目的是为了股指期货提供一个标的。有业内人士就表示,推出沪深300指数,并在沪深300指数推出运行一段时间后,如果运行状况良好,就可以推出以该指数为标的的股指期货。

文字介绍,摘自:http://baike.baidu.com/view/539529.htm

4. 沪深300指数统计分析

数据来源于:招商证券智远理财服务平台 客户端
数据采集日期:2014-01-01

个股对指数贡献度:


股票代码,股票名称,贡献点数,涨幅(%),昨日收盘,参与计算股本(W),权重,名次
601398,工商银行,1.39,0.85,3.550,26377716.00,7.18,1
600036,招商银行,1.05,2.74,10.600,2062894.38,1.68,2
601288,农业银行,1.04,0.81,2.460,29405530.00,5.55,3
601166,兴业银行,0.87,2.63,9.880,1905233.63,1.44,4
600028,中国石化,0.80,1.13,4.430,9105184.00,3.09,5
601318,中国平安,0.78,2.25,40.810,478640.94,1.50,6
600000,浦发银行,0.76,2.50,9.200,1865347.13,1.32,7
600519,贵州茅台,0.72,3.15,124.460,103818.00,0.99,8
600030,中信证券,0.71,3.32,12.340,983858.13,0.93,9
002304,洋河股份,0.71,10.00,37.110,108000.00,0.31,10
600016,民生银行,0.60,1.98,7.570,2258819.25,1.31,11
601628,中国人寿,0.55,1.00,14.980,2082353.00,2.39,12
600010,包钢股份,0.55,9.95,3.920,800259.13,0.24,13
000001,平安银行,0.52,4.34,11.740,573815.25,0.52,14
601998,中信银行,0.51,2.38,3.780,3190516.25,0.92,15
000858,五 粮 液,0.50,5.03,14.910,379596.69,0.43,16
601006,大秦铁路,0.37,1.93,7.250,1486679.13,0.83,17
600383,金地集团,0.35,7.22,6.230,447150.84,0.21,18
....

用R语言读入数据


library(ggplot2)
library(scale)

contrib<-read.table(file="contribution.csv",header=FALSE,sep=",",colClasses = "character",fileEncoding="utf-8", encoding = "utf-8")
names(contrib)<-c("股票代码","股票名称","贡献点数","涨幅","昨日收盘","参与计算股本(W)","权重","名次");

1). 选出权重>1的股票


contrib[which(as.numeric(contrib[,7])>1),]

   股票代码 股票名称 贡献点数 涨幅 昨日收盘 参与计算股本(W) 权重 名次
1    601398 工商银行     1.39 0.85    3.550     26377716.00 7.18    1
2    600036 招商银行     1.05 2.74   10.600      2062894.38 1.68    2
3    601288 农业银行     1.04 0.81    2.460     29405530.00 5.55    3
4    601166 兴业银行     0.87 2.63    9.880      1905233.63 1.44    4
5    600028 中国石化     0.80 1.13    4.430      9105184.00 3.09    5
6    601318 中国平安     0.78 2.25   40.810       478640.94 1.50    6
7    600000 浦发银行     0.76 2.50    9.200      1865347.13 1.32    7
11   600016 民生银行     0.60 1.98    7.570      2258819.25 1.31   11
12   601628 中国人寿     0.55 1.00   14.980      2082353.00 2.39   12
19   601988 中国银行     0.34 0.38    2.610     19552620.00 3.91   19
24   600104 上汽集团     0.29 1.07   13.990      1102556.63 1.18   24
26   601857 中国石油     0.29 0.13    7.700     16192208.00 9.56   26
28   601328 交通银行     0.28 1.05    3.800      3925086.25 1.14   28
63   601088 中国神华     0.09 0.19   15.790      1649103.75 2.00   63

2). 画出“涨幅”的分布图


g<-ggplot(contrib, aes(x=as.numeric(contrib$涨幅)))
g<-g+geom_histogram(binwidth=0.2,position="identity")
g<-g+xlab("涨幅(%)")+ylab("股票数量")
g

index1

3). 画出“权重”的分布图


g<-ggplot(contrib, aes(x=as.numeric(contrib$权重)))
g<-g+geom_histogram(binwidth=0.2,position="identity")
g<-g+scale_x_continuous(breaks=-5:10)
g<-g+xlab("权重(%)")+ylab("股票数量")
g

index2

4). 画出“涨幅和权重”的关系


g<-ggplot(contrib, aes(x=as.numeric(contrib$涨幅),y=as.numeric(contrib$权重)))
g<-g+geom_point()
g<-g+scale_x_continuous(breaks=-5:10)
g<-g+xlab("涨幅")+ylab("权重")
g

index3

5). 画出“涨幅和名次”的关系,并做线性回归


g<-ggplot(contrib, aes(x=as.numeric(contrib$涨幅),y=as.numeric(contrib$名次)))
g<-g+geom_point()+geom_smooth(method = lm, size = 1)
g<-g+scale_x_continuous(breaks=-5:10)+ylim(0,300)
g<-g+xlab("涨幅")+ylab("名次")
g

index4

转载请注明出处:
http://blog.fens.me/finance-index/

打赏作者