引言:
文中提到此系統摘自「Building Winning Trading Systems with TradeStation」(Pruitt與Hill,2003)。包寧杰強盜(Bollinger Bandit)交易系統計算價格的標準差,基于均數復歸的精神,「當價格突破上N個標準差(N為策略參數)反轉時,作空」,反之,「當價格突破下N個標準差反轉時,作多」。但Pruitt與Hill的實證中發現,反向操作反而更好,亦即採取「當價格突破上N個標準差(N為策略參數)時,作多」,反之,「當價格突破下N個標準差時,作空」,并將策略參數設計成可適應性調整的動態設定。發文者提供了系統編碼與實證績效結果,并自行作了改進。
正文:
今天要報告的是”Building Winning Trading Systems with TradeStation”這本書裡面的第二個交易系統。名字叫做包寧杰強盜Bollinger Bandit交易系統。
要先講一下Bollinger Band這個系統,Bollinger Band這個通道的名詞,最早是由John Bollinger在1960年代所提出的觀念。計算方式就是先取一條簡單移動平均線,然后在這條移動平均線上下個取一個標準差的距離,來分別當作上下通道。Bollinger認為在統計學的觀念來說,在移動平均線上下各取一個標準差的距離,等于總共是有兩個標準差的寬度的通道,應該會包含95%的價格波動。所以當價格位于到上通道的上面的時候,就很有可能會往下回歸均線。這時候就可以在價格往下穿透上通道的時候做空,也就是把上通道當作壓力區間來操作。(下通道則相反)
但是George Pruitt & John Hill做的很多測試發現。Bollinger Band的上通道通常并不是壓力線,而通常會是可以成功做多的突破線。也就是說我們應該在價格突破上通道的時候做多才對。
所以作者就將Bollinger Band的訊號反過來操作。同時也加入了一些其他的設計,其中一個設計就是由King Keltner trading system的系統改進而來的。因為在King Keltner trading system當中,出場的機制是當價位回到移動平均線的時候就出場。但是有時候移動平均線的追蹤速度太慢了,導致我們有時候真正出場的時候會回吐太多的獲利出去。這種情形常常會讓很多人吐血。所以他們設計的出場機制會隨著進場時間的增加,而更緊密的追蹤價位。作法就是隨著進場之后的時間增加,把出場的移動平均線的計算長度,逐漸的減少。所以剛進場的時候的停損金額是會比較寬的,但是進場時間越長,計算出場的移動平均線的時間長度會越短,也就代表這條出場移動平均線會越緊密的追蹤價位。所以當最后價格反轉不利于我們的時候,我們比較不會回吐太多的獲利出去。但是這個時間長度最少只有減到10而已,以防止移動秤均線太貼緊價位而很容易就打到停損出場。
最后作者加了一個簡單的濾網來決定多空的方向。就是如果今天的收盤價比30天前的收盤價高的話就只做多,如果今天收盤價比30天之前的收盤價低的話就只做空。
下面就是書上的程式碼:
{Bollinger Bandit by George Pruitt—program uses Bollinger Bands and Rate of
change to determine entry points. A trailing stop that is proportional with
the amount of time a trade is on is used as the exit technique.}
Inputs: bollingerLengths(50),liqLength(50),rocCalcLength(30);
Vars: upBand(0),dnBand(0),liqDays(50),rocCalc(0);
upBand = BollingerBand(Close,bollingerLengths,1.25);
dnBand = BollingerBand(Close,bollingerLengths,-1.25);
rocCalc = Close - Close[rocCalcLength-1]; {remember to subtract 1}
if(MarketPosition <> 1 and rocCalc > 0) then Buy("BanditBuy")tomorrow upBand stop;
if(MarketPosition <>-1 and rocCalc < 0) then SellShort("BanditSell") tomorrow dnBand stop;
if(MarketPosition = 0) then liqDays = liqLength;
if(MarketPosition <> 0) then begin
liqDays = liqDays - 1;
liqDays = MaxList(liqDays,10);
end;
if(MarketPosition = 1 and Average(Close,liqDays) < upBand) then Sell("Long Liq") tomorrow Average(Close,liqDays) stop;
if(MarketPosition = -1 and Average(Close,liqDays) > dnBand) then BuyToCover("Short Liq") tomorrow Average(Close,liqDays) stop;
而作者測試1982-2002年這20年的歷史資料,所得出的來結果是這樣的。
BB Performance.JPG
BB Performance.JPG (86.56 KiB) 被瀏覽 1223 次
Bollinger Bandit系統像King Keltner系統一樣,同樣的也是把上下通道的寬度固定住了,這裡是固定在標準差的1.25倍。所以我同樣做了個小小的修改,讓我們可以試試看不同的通道寬度,對于績效的影響如何。修改后的程式碼如下:(轉自 http://m.kzuj.com.cn/2016/04/08/35133.shtml )
{Bollinger Bandit by George Pruitt—program uses Bollinger Bands and Rate of
change to determine entry points. A trailing stop that is proportional with
the amount of time a trade is on is used as the exit technique.}
Inputs: bollingerLengths(50),liqLength(50),rocCalcLength(30),StdDevRatio(1);
Vars: upBand(0),dnBand(0),liqDays(50),rocCalc(0);
upBand = BollingerBand(Close,bollingerLengths,StdDevRatio);
dnBand = BollingerBand(Close,bollingerLengths,-StdDevRatio);// m.kzuj.com.cn
rocCalc = Close - Close[rocCalcLength-1]; {remember to subtract 1}
if(MarketPosition <> 1 and rocCalc > 0) then Buy("BanditBuy")tomorrow upBand stop;
if(MarketPosition <>-1 and rocCalc < 0) then SellShort("BanditSell") tomorrow dnBand stop;
if(MarketPosition = 0) then liqDays = liqLength;
if(MarketPosition <> 0) then begin
liqDays = liqDays - 1;
liqDays = MaxList(liqDays,10);
end;
if(MarketPosition = 1 and Average(Close,liqDays) < upBand) then Sell("Long Liq") tomorrow Average(Close,liqDays) stop;
if(MarketPosition = -1 and Average(Close,liqDays) > dnBand) then BuyToCover("Short Liq") tomorrow Average(Close,liqDays) stop;
如果有朋友有研究過上一個介紹的King Keltner系統的話,應該會發現Bollinger Bandit跟King Keltner的績效差不多。這是因為這兩個系統的原理基本上就是很類似的,都是屬于上下通道突破的系統,只是出場跟濾網的設計不一樣而已。所以如果有朋友想要做multi-system的portfolio的話,要注意這兩個交易系統的相關性會是比較高的。而我們設計portfolio的原則,就是應該要採用相關性較低的系統才好。