2017年8月20日

【MultiCharts】Dynamic Breakout System(DBS)(附程式碼)

動態突破系統(Dynamic Breakout System,DBS)最早是George Pruitt在1996期貨雜誌(Futures Mazagine)所發表,後來作者在自己的著作「Building winning Trading Systems with TradeStation」(2003)中再發表一篇改良版的DBS。”Dynamic”一詞其實意同”Adaptive”(可參考本篇AMA指標),目的都是希望系統參數可以依市況自行動態調整。DBS是筆者非常欣賞的策略,它透過簡單幾行語法就可以實現「動態調整」的效果,非常值得觀摩學習。

第一代DBS

我們先直接看第一代DBS的程式碼:

==============================
Inputs: Ceil(30),Flr(10),S(30);
Vars: X(0),ZDelta(0),N(0);

X = Stddev(Close, S);
if X<>0 then ZDelta = (X – X[1]) / X;

If CurrentBar=1 then N = (Ceil+Flr)/2;
If CurrentBar>1 then N = N [1]* (1 +ZDelta);
N = MaxList(N, Flr);
N = MinList(N, Ceil);

{Entry}
if marketposition<>1 then Buy next bar at Highest(High, N) Stop;
if marketposition<>-1 then sellshort next bar at Lowest(Low, N) Stop;
==============================

是不是精簡的令人吃驚!接下來我們就一一解析語法。首先DBS基本原型是一個高低價格通道系統(Price Channel Breakout),這種典型通道系統就是取一個例如N=20天的最高、最低價來算出上下通道,向上突破上通道就做多,向下跌破下通道就做空,而DBS的”Dynamic”就體現在把上例的N由固定值20設計成變動的--可以依盤勢結構不同來對應變化。

接下來就是變動的邏輯或者說基礎是甚麼,這裡採用的是波動率,以函式Stddev(C,30)計算30天期歷史波動率,基本的邏輯假設就是,當波動變大時,行情呈現劇烈震盪,N應該大一點,例如N變成30,通道就會放大,等於是把進場的條件設嚴格,避免被假突破給騙進場;反之,當波動率趨小時,N就隨之變小,所謂盤久必變,如此行情一發動就可進場。Zdelta負責算出與前根歷史波動率的差異(取%),正值代表波動率大於前根,反之負值代表小於前根,所以當波動率變大,N= N [1]*(1+ZDelta),N將同步增加,反之亦然,這樣就達到了我們要的N與波動率同向變動的效果,此外,實務上還要限制N在一定範圍內,否則N爆漲暴跌成為極端值將失真。所以初始值設定N=(Ceil+Flr)/2,也就是上下限的中間值,再透過N=MaxList(N, Flr)、N=MinList(N, Ceil) 將N限制在界線10~30之內(很實用的語法技巧,可以學起來)。完成後,進場訊號是典型的價格通道系統,但此時N已經具有”Dynamic”的能力了!

亦可以把DBS繪成指標,下面兩張圖是以固定N=20及DBS(動態N=10~30)來比較,可以明顯看後者通道隨波動擴張或壓縮。如果把上述參數及策略套到台指期會發現績效還不如N固定等於20,這是因為我們的下限界線值Flr設10太小了。所以採用DBS策略有一個要點,就是下限值Flr不宜設太小。

第二代DBS

二代DBS其實精神不變,只是原本是價格通道換成布林通道,一樣是依波動率來決定布林通道要計算的K棒數,以下是「Building winning Trading Systems with TradeStation」附的程式碼(網路上可GOOGLE到),原版是TS的語法,這邊有稍作修改成MC語法,另外它在比較前後期波動率變化的語法也跟一代語法稍有差異,不過基本上是大同小異,都可以通。

==============================
Inputs: ceilingAmt(60),floorAmt(20),bolBandTrig(2.00);
Vars: lookBackDays(20),todayVolatility(0),yesterDayVolatility(0),deltaVolatility(0);
Vars: buyPoint(0),sellPoint(0),longLiqPoint(0),shortLiqPoint(0),upBand(0),dnBand(0);
todayVolatility = StdDev(Close,30);
yesterDayVolatility = StdDev(Close[1],30); {See how I offset the function call to
get yesterday's value}
deltaVolatility = (todayVolatility – yesterDayVolatility)/todayVolatility;
lookBackDays = lookBackDays * (1 + deltaVolatility);
lookBackDays = Round(lookBackDays,0);
lookBackDays = MinList(lookBackDays,ceilingAmt); {Keep adaptive engine within bounds}
lookBackDays = MaxList(lookBackDays,floorAmt);

upBand = BollingerBand(Close,lookBackDays,+BolBandTrig);
dnBand = BollingerBand(Close,lookBackDays,–BolBandTrig);
buyPoint = Highest(High,lookBackDays);
sellPoint = Lowest(Low,lookBackDays);
longLiqPoint = Average(Close,lookBackDays); {Exit long at 1/2 look back period}
shortLiqPoint = Average(Close,lookBackDays); {Exit short at 1/2 look back period}
if(Close > upBand) then Buy("DBS-2 Buy") next bar at buyPoint stop;
if(Close < dnBand) then SellShort("DBS-2 Sell") next bar at sellPoint stop;
if(MarketPosition = 1) then Sell("LongLiq") next bar at longLiqPoint stop;
if(MarketPosition = –1) then BuytoCover("ShortLiq") next bar at shortLiqPoint stop;
==============================

結論

連同前面一篇介紹Adaptive Moving Average(AMA),我們探討了如何透過簡單的機制來達到自適應(Adaptive)或是動態(Dynamic)的效果,當然距離所謂的人工智慧(AI)還有很大一段距離,但這是一個賦予程式策略彈性與應變能力的開始,讀者可以嘗試擴大運用,除了波動率以外,籌碼方面的資訊是否也有機會開發出”動態”調整的新策略,都是可以思考的方向。

警語:程式碼為教學目的,僅供參考,版權亦屬原作者。


歡迎加入LINE@
加入好友
(點擊上方圖示)

1 則留言:

  1. 這個lookBackDays是否同時 = lookBackDays * (1 + deltaVolatility) Round(lookBackDays,0) MinList(lookBackDays,ceilingAmt) 三樣?

    回覆刪除

歡迎留言討論!