二條均線打天下


用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/


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com