用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/
前言
久经股市的老股民,通常都会使用一种常见的交易策略,追涨杀跌交易法。追涨杀跌法,是股市操作的一个重要技巧,就是在股市上涨时买入股票,股市下跌时卖出股票。如果操作得当是很好的赢利手段,在中国股市2015年上半年的牛市中,追涨杀跌交易法就是交易神器法门。
目录
- 什么是追涨杀跌?
- 追涨杀跌的建型和实现
- 模型优化
1. 什么是追涨杀跌?
追涨杀跌是金融市场的专业术语,是金融技术派操盘的一种方式,与抄底摸顶的操作方式刚好相反。追涨杀跌的操作方法是,金融市场中在金融产品(股票,期货,外汇等)价格上涨的时候买入,以期待涨得更多,并以更高的价格卖出获利;在价格下跌的时候卖出进行止损,不管之前金融产品买入的价格是多少,都立刻卖出,以避免更大的损失。
下面以平安银行(000001)股票日K线图为例,截取2005年到2015年7月的股票数据,股价为向前复权的价格。
上图中有3条曲线,黑色线是平安银行向前复权后的每日股价,红色线为20日均线,蓝色线为60日均线。关于均线的介绍,请参考文章 两条均线打天下。图中还有一条红色的水平线虚线,是这10年的股价平均值等于7.14元。这10年间,平安银行股价起起落落,每次上涨都会持续一段时间,那么在我们可以上涨中段追入买进,在大幅下跌之前卖出,就是追涨杀跌法。
追涨
追涨通常有2种情况,短线追涨和中线追涨。以股票交易为例。
- 短线追涨:当天股价已经涨了5个点或更多,这时追进去买入,期待当天收盘涨停,等下一个交易日高价卖出,这就是短线追涨。
- 中线追涨:某只股票的股价已经上涨了一段时间,走势很强,底部上涨已经有30%或更多,这个时追进去买入,期待后势持续上涨,是中线追涨。
不论短线追涨还是中线追涨,我们追涨的理由和判断的标准都是一样的,“涨得好的股票说明走势很强,那么追强势股期待股票持续上涨”。但从另一个角度看,追涨的风险也是很大的,关键在于我们不知道它能涨到什么时候,到什么位置可能会回调,什么时候是庄家出货。所以说追涨技巧性很强,什么情况下能追,什么情况下不能追,都是很有讲究的。
杀跌
杀跌也是一门较深的操作技巧,杀得好的话既可以回避风险。如果不能进行杀跌的准确判断,则很可能会发生硬性止损,导致严重的亏损。
采取杀跌战术,必须掌握以下操作要点:
- 杀跌的重要前提是知变,就是对消息、对量能、对周边各种因素的影响有一个准确的、快速的知变过程。
- 杀跌要善于观察盘面、形态、消息、舆论等方面的细微变化,在对大盘作出准确估量的基础上,迅速作出反应就是确定卖出哪支股票,卖出多少等。
- 杀跌要善于思考大盘与目标股之问的正向、反向的相关性,及目标股的能量能等方向的关系,从中找出变动的规律。
- 当市场利好消息接踵而至时,应随时准备卖出股票。当利好出尽就会转向利空,往往消息明朗时,股价早已下跌大半,导致措手不及。
杀跌的后续操作就比较简单了,只需保持良好的心态,耐心等待见底信号后再抄底。一般只有在底部成功接回股票或换股才算成功的杀跌,否则杀跌会失去意义。应保持耐心,千万不要在股价反弹时贸然介入,否则屡买屡跌、会加大损失,应待股价反转时再介入。
追涨杀跌的技巧
要观大势,看清整个市场多空对决的优势一方是谁。
追涨杀跌的假设条件:
- 市场处于强势交易格局。强势格局赋予个股良好的运作基础;相反,如果市场处于平衡状态,就不适合进行追涨杀跌,更适合高抛低吸。
- 市场形成了鲜明并有持续性上涨能力的热点或板块效应。
追涨操作的对象:
- 市场形成鲜明的可持续性的热点时,可追涨这个热点。从理论上讲,只要把握热点板块就能获利,追涨时应重点关注龙头企业。比如:沪深300指数的成分股,就是不错的选择。
- 形成明显的上涨趋势的个股可以考虑追涨。个股突破重要的压力线,如头肩底形态的颈线位、整理箱体的箱顶位、三角形的上边眼、长期下降趋势线等,待回抽确认其突破的有效性后,可考虑追涨。
追涨杀跌的注意事项:
- 追涨时应设好止盈位和止损位,确定自己的大致盈利目标。
- 追涨杀跌应该注意频率的减少,过于频繁的操作,一旦失误增多会严重影响情绪。
- 追涨杀跌中要多一分平和的心态,少一些侥幸;多一分理性,少一分感性。
追涨杀跌的市场操作
在弱市中,短线追涨往往容易被套,因为弱市里大部分股票的行情只有一天,当天追得高了,第二天多半没有获利逃出的机会。相反,弱市中,中线追涨比较可取,能够在弱市中保持强势的股票不多,但这种强势反而可以持续。但很多时候,弱市中这样的股票反倒不敢追了。
有些人专门追涨停板,追新股开板,追次新股开板等,对于2015年上半年IPO的新股来说收获颇丰,如暴风科技,中超电缆等,其他的时候可能用这套追涨停策略就行不通了。
我自己操作并不会盲目追涨,安全第一,虽然还没有吃过追涨的亏,但由于本人目前还不具备基本面的分析能力,也没有消息的渠道,仅仅从技术指标入手,投机性太重,很容易被庄家玩死的。道理很简单,因为如果追涨了,下跌的空间自然就大了,尤其中线追涨,庄家获利后随时可能出货。这时候就必须要做好杀跌的策略。庄股出货跌个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') # 画图
上图中有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') # 画图
如上图所示,蓝色的点为股价大于等于最近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') #画图
上图中,紫色点为卖出信号点,红色点为买入信号点。我们可以很明显的看出,如果根据交易信号在红色点买入,紫色点卖出,我们是应该赚钱的。那么具体赚了多少呢,我需要计算出来?
> # 合并交易信号
> 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个点,画出交易信号的图形。
合并买卖的交易信号。
> 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') #画图
图中红色点为买点,蓝色点为优化的卖点,紫色点为止损点。从图中可以非常清楚的看到,蓝色卖出点要优于紫色的止损点。这样就达到了,模型优化的目的了。虽然只是一个很小的优化,就可以给我们带来不错的收益。
接下来,通过况客平台,我来够建一个每日更新的交易列表,实现把静态图变成了动态图。
追涨杀跌策略在牛市中会让我们赚取非常大的利润,那么对于2015年下半年行情,牛市已经不复存在,震荡市会一直持续,那么我们可以使用均值回归策略,发现逆市中的投资机会。
最后总结,本文从 追涨杀跌 的思路开始,到市场特征检验,再到数学公式,R语言建模,再到历史数据回测。通过R语言,很简单地就实现了一个我们脑子中的投资想法。类似的投资想法其实谁都有,利用IT人的技术优势,可以真正地与实际操作结合起来。
这样就可以更容易地实现,从IT技术到价值的转变。IT人,加油!
况客官网的新手指南和使用手册都打不开……请问具体怎么使用况客导出数据呢?
感谢你的关注。
1. 新手指南和使用手册,确实还没有写完,所以打不开。
2. 导出数据的功能,还没有完全开放,请再等待一些时间。
请问 我已经 加载 ruibe的包 没有key 怎么办, 怎么叫做个人专属key
兄弟,你股市里用这套策略赚着钱了吗?
1. 这个不是实盘策略,只是一个例子。
2. 实盘策略,会比文章里写的复杂很多。
3. 实盘交易,是赚钱的。
[…] R语言量化投资数据分析应用,PPT下载,主要内容来自我的一篇博文:R语言构建追涨杀跌量化交易模型 […]
[…] 股市中的R语言量化算法模型,PPT下载,主要内容来自我的一篇博文:R语言构建追涨杀跌量化交易模型 […]
能否提供个stock.csv下载地址,谢谢了。
可以给你一个http://www.iquant.club/wp-content/uploads/2016/02/pinganstock.csv
非常好的例子!
🙂
借用你的思路,我用Python实现了一下,发现目前这段时间不适合这种操作。。。
最近比较适合均值回归,能抄底赚不少。
http://blog.fens.me/finance-mean-reversion/
能共享下你的python代码么,学习一下。
您好,我尝试应用您的模拟交易代码,但是其中一部分代码是缺失的。
文章的代码应该都是完整的。
“ if(row$p==’B’){
+ if(cash0),which(ticks$op==’S’)),] # 赚钱的交易
+ fall<-ticks[intersect(which(ticks$diff<0),which(ticks$op=='S')),] # 赔钱的交易”
我是看的这段代码,不是完整的。
已更新
Hi,Conan,文中说:“况客 会提供各种类型的金融数据API,让开发者可以免费下载”。请问,况客的金融数据API在哪里可以找到,谢谢!
不好意思,回复晚了。2015年12月底之前会正式开放。
目前测试版本可以先看这个项目
https://github.com/qutke/ruibe
https://uibe.qutke.com/i/api.html
Hi,Conan,你的第三本书什么时候出版,有没有具体的时间?谢谢
抱歉回复晚了,还没有具体时间,正在写。。。
如果时间充裕,6月份左右可以出版。
想请问dateArea 是那里的函数,我这里一直提示 没有”dateArea”这个函数
同疑问!!!!没有dateArea这个函数
我检查一下,一会更新上去。
然而并没更新,哈哈。这个dateArea函数您以前的文章中有的,http://blog.fens.me/category/%E7%A8%8B%E5%BA%8F%E7%AE%97%E6%B3%95/
赞!收藏啦~向技术流选手致敬!
🙂
步骤和代码注释都很详细,照着教程本地实现了一遍对R语言构建交易系统有了很大的帮助,非常感谢! 小疑问:定义画图函数 drawLine()中的 sDatemax是在复制时的遗漏还是个新的函数呢?
HTML显示的问题,已经调整。
看到了,谢谢
Hi, 卖出信号这地方一直出错,提示:Error in if (!is.na(zero.index)) i <- i[-zero.index] :
zero.index,是啥? 是不是没数据,空指针的问题
您好 为什么每次都显示 cannot open URL ‘https://datas.qutke.com/api/opendata?data=tradingDay&key=96afe49792a8dff5ca3efeb7f063104e3f5f680866e0800f0542c2584f672fe6’: HTTP status was ‘400 Bad Request’
这个之前是qutke的API,可以显示动态图,不过似乎已经不维护了。我已经把文章中引用部分删除了。