AtrRsi策略
AtrRsi策略主要依靠兩個技術指標生成交易信號,該指標如下
1 ATR指標
1)ATR指標原理
平均真實波動範圍(Average true range),簡稱ATR指標,是由韋爾德(J.Welles Wilder)發明的,ATR指標主要是用來衡量市場波動的強烈度,即為了顯示市場變化率的指標。注意,這一指標主要用來衡量價格的波動,並不能直接反映價格走向及其趨勢穩定性。
這一指標對於長期持續邊幅移動的時段是非常典型的,這一情況通常發生在市場的頂部,或者是在價格鞏固期間。根據這個指標來進行預測的原則可以表達為:該指標價值越高,趨勢改變的可能性就越高;該指標的價值越低,趨勢的移動性就越弱。
當ATR線上升時,意味著資產的波動性在增加。當ATR線下降時,意味著資產的波動性在減少。ATR 不會顯示資產移動的方向。
下圖展示 ATR 是如何來表示波動性的高低的:
區間1的ATR值較高,表明波動較高
區間2的ATR較低較低,表明波動較低
2)ATR指標計算
首先應計算出TR(即當天的真實波幅),下圖中#1,#2,#2為市場出現跳空高開和跳空低開的情況。TR在當日最高價與最低價,當日最高價與昨日最收盤價,當日最低價與昨日收盤價這3種情況中取最大值。
由於一天的TR缺乏效率以及代表性,韋爾德用ATR來更好的衡量市場的波動性;一般而言,市場常用的數據周期是14以及21,這意味著如果投資者在日圖看ATR,14 = 14天;如果是在周圖看ATR,14 = 14周。ATR的計算公式如下:
ATR = (前13天的TR + 當天的TR)/ 14
3)ATR指標信號判斷
除了通過ATR數值大小來直接判斷市場波動性大小外,也可以通過對比當天平均真實波幅(ATR)和過去N天平均波幅(ATRMa)來判斷市場波動性趨勢。
- 當ATR>ATRMa,說明市場波動性增大,趨勢正在增強
- 當ATR<ATRMa,說明市場波動性減少,趨勢開始減弱
2 RSI指標
1)RSI指標原理
相對強弱指標(Relative Strength Index),簡稱RSI指標,也是由J.Welles Wilder 發明的。RSI指標是根據市場上供求關係平衡的原理,通過比較一段時期內單個標的物價格的漲跌的幅度或整個市場的指數的漲跌的大小來分析判斷市場上多空雙方買賣力量的強弱程度,從而判斷未來市場走勢的一種技術指標。
簡單來說,是一種用來評估「買賣盤雙方力道強弱」情況的技術指標,買家是代表金錢的力量,賣家是代表持貨的力量。當買方力量稍遜,價格就會向下發展;相反,當賣方力量不足,價格就會向上發展。
2)RSI指標計算
3)RSI指標信號判斷
一般而言,RSI 以50為中界線,大於50視為多頭行情,小於50視為空頭行情。
當RSI>70時,屬於超買狀態,後續行情有可能出現回調或轉勢,應該賣出;
當RSI<30時,屬於超賣狀態,短期反彈概率較高,建議買入
4)RSI指標缺點
- RSI 指標在高檔或低檔有時會有鈍化的現象,因此會發生過早賣出或買進。
- RSI 只能作為一個警告訊號,並不意味著市勢必然朝這個方向發展,尤其在市場劇烈震蕩時,超賣還有超賣,超買還有超買,這時須參考其他指標綜合分析,像是利用長天期的RSI均線與RSI線的關係來作買賣訊號判斷,不能單獨依賴RSI的訊號而作出買賣決定。
- 背離走勢的訊號通常者都是事後歷史,而且有背離走勢發生之後,行情並無反轉的現象。有時背離一,二次才真正反轉,因此這方面研判須不斷分析歷史資料以提高經驗。
- 由於 RSI 是一種比率的指標,因此在趨勢分析的能力上會較弱。
- 盤勢進入橫盤整理時,長短天期的RSI也容易形成重複交叉的情形。
3 策略思路
該策略只用到2個技術指標:ATR指標用於過濾,當ATR>ATRMa時,顯示市場波動性增大,趨勢正在增強。只有在市場出現趨勢的時候做單(追漲殺跌),盈利的機會才會增大。RSI指標則是用於產生交易信號,當RSI>規定上限時,開倉做多,反之,當RSI<規定下限時,開倉做空。開倉之後就需要考慮如何盈利離場或者止損離場,這個策略用的是固定百分比點位的移動止損。例如:70這個點位開倉後,行情一路走高至100這個日高點,移動止損設了99%,當行情開始回落時,會在99這個點位自動平倉離場,從而把握住了29點的盈利。
AtrRsi策略三大要素
信號:RSI指標
過濾:ATR指標
出場:固定百分百點位移動止損離場
4策略代碼解析
1)策略參數
ATR指標初始化需要用到11天數據,即11天以後才能產生ATR值;而ATR移動平均(ATRMa)則是統計10天內的平均值
RSI指標規定初始化需要用到5天數據,16是開倉的閾值:當RSI>50+16,即RSI>66時,開倉做多,當RSI<34時,開倉做空。這裡並不用市場公認的RSI高於80做多,RSI低於20做空,因為用的人多了,交易信號已經失效。
fixedSize=1意味著每次開平倉操作只交易1手。
# 策略參數
atrLength = 11 # 計算ATR指標的窗口數
atrMaLength = 10 # 計算ATR均線的窗口數
rsiLength = 5 # 計算RSI的窗口數
rsiEntry = 16 # RSI的開倉信號
trailingPercent = 0.8 # 百分比移動止損
initDays = 10 # 初始化數據所用的天數
fixedSize = 1 # 每次交易的數量
......
#----------------------------------------------------------------------
def onInit(self):
"""初始化策略(必須由用戶繼承實現)"""
self.writeCtaLog(u%s策略初始化 %self.name)
# 初始化RSI入場閾值
self.rsiBuy = 50 + self.rsiEntry
self.rsiSell = 50 - self.rsiEntry
......
2) onBar函數
在開倉交易前,為了防止之前下的掛單在上1分鐘沒有成交,但是下一分鐘可能已經調整了價格,就用cancelAll( )的方法立刻撤銷之前未成交的所有委託,保證策略在當前這1分鐘開始的時候整個狀態是清晰和唯一的。
本地化K線管理模塊(am = http://self.am),以便其運行起來更快。若檢測到K線管理模塊還沒有插入足夠多的數據,即初始化狀態為False,則直接返回不進行下面的操作;反之,計算ATR指標,ATR移動平均和RSI指標。
def onBar(self, bar):
"""收到Bar推送(必須由用戶繼承實現)"""
self.cancelAll()
# 保存K線數據
am = self.am
am.updateBar(bar)
if not am.inited:
return
# 計算指標數值
atrArray = am.atr(self.atrLength, array=True)
self.atrValue = atrArray[-1]
self.atrMa = atrArray[-self.atrMaLength:].mean()
self.rsiValue = am.rsi(self.rsiLength)
- 當前無倉位,先初始化K線日高點和日低點的值,用的是當前K線的最高價和最低價。若ATR指標往上走超過了移動平均,說明趨勢正在增強,市場波動越來越大,則用RSI指標來開倉操作了。RSI的判斷標準是當其指標高於66時,發出買入委託,用超價5個點來保證能夠成交,委託數量為1(fixedSize)。若RSI低於其賣出閾值,用低於市價5個點來保證成交。
- 當前持有多倉,用max()函數來統計當日K線達到的最高點,日低點則是直接更新當前K線最低價。移動止損設置為當K線達到日高點後,回落0.8%時用停止單(Stop Order)進行平倉離場
- 當前持有空倉,用min()函數來統計當日K線達到的最底點,日高點則是直接更新當前K線最高價。移動止損設置為當K線達到日低點後,反彈0.8%時用停止單(Stop Order)進行平倉離場。
# 判斷是否要進行交易
# 當前無倉位
if self.pos == 0:
self.intraTradeHigh = bar.high
self.intraTradeLow = bar.low
# ATR數值上穿其移動平均線,說明行情短期內波動加大
# 即處於趨勢的概率較大,適合CTA開倉
if self.atrValue > self.atrMa:
# 使用RSI指標的趨勢行情時,會在超買超賣區鈍化特徵,作為開倉信號
if self.rsiValue > self.rsiBuy:
# 這裡為了保證成交,選擇超價5個整指數點下單
self.buy(bar.close+5, self.fixedSize)
elif self.rsiValue < self.rsiSell:
self.short(bar.close-5, self.fixedSize)
# 持有多頭倉位
elif self.pos > 0:
# 計算多頭持有期內的最高價,以及重置最低價
self.intraTradeHigh = max(self.intraTradeHigh, bar.high)
self.intraTradeLow = bar.low
# 計算多頭移動止損
longStop = self.intraTradeHigh * (1-self.trailingPercent/100)
# 發出本地止損委託
self.sell(longStop, abs(self.pos), stop=True)
# 持有空頭倉位
elif self.pos < 0:
self.intraTradeLow = min(self.intraTradeLow, bar.low)
self.intraTradeHigh = bar.high
shortStop = self.intraTradeLow * (1+self.trailingPercent/100)
self.cover(shortStop, abs(self.pos), stop=True)
# 同步數據到資料庫
self.saveSyncData()
# 發出狀態更新事件
self.putEvent()
5 策略回測
回測相關數據
# 設置回測使用的數據
engine.setBacktestingMode(engine.BAR_MODE) # 設置引擎的回測模式為K線
engine.setDatabase(MINUTE_DB_NAME, IF0000) # 設置IF股指期貨
engine.setStartDate(20110416) # 設置回測用的數據起始日期
engine.setEndDate(20180101) # 設置回測用的數據結束日期
# 配置回測引擎參數
engine.setSlippage(0.2) # 設置滑點為股指1跳
engine.setRate(0.5/10000) # 設置手續費萬0.5
engine.setSize(300) # 設置股指合約大小
engine.setPriceTick(0.2) # 設置股指最小价格變動
engine.setCapital(1000000) # 設置回測本金
初始本金100萬,期末本金194萬,平均年收益21%,最大回撤達9.6%,夏普比率0.93,但是在2016年後表現不理想,存在持續虧損,如下圖:
6 滾動回測
1)參數優化設置
# 優化配置
setting = OptimizationSetting() # 新建一個優化任務設置對象
setting.setOptimizeTarget(sharpeRatio) # 設置優化排序的目標是夏普比率
setting.addParameter(atrLength, 18,30,2) # 增加第一個優化參數atrLength,起始12,結束20,步進2
setting.addParameter(atrMaLength, 6, 14, 2) # 增加第二個優化參數atrMa,起始20,結束30,步進5
setting.addParameter(rsiLength, 4,8,1) # 增加一個固定數值的參數
# 執行多進程優化
import time
start = time.time()
resultList = engine.runParallelOptimization(AtrRsiStrategy, setting)
#resultList = engine.runOptimization(AtrRsiStrategy, setting)
print u耗時:%s %(time.time()-start)
2)滾動回測設置
以3年為滾動周期,步進是半年,對20100416--20180101區間進行滾動回測以及參數優化,並且收集表現最好的前3組優化參數。
通過對歷史優化參數的統計分析,來預測未來的優化參數。其選擇標準如下:
- 近年參考權重大於遠年
- 若優化參數整體變化不大,取眾數
- 若優化參數整體發生變化,在近年區間取眾數
- 若前一年參數發生劇烈變化,對該區間進行更為細緻的滾動回測和參數優化
上圖顯示歷史優化參數整體發生變化,故在近年區間取眾數,即artLength = 22,atrMaLength = 12,rsiLength = 7。
預測優化參數歷史表現:
年化收益11.72%,最大回撤-18.89%,夏普比率達0.58。
對2018年以後的預測效果:
年化收益提升到37.4%,最大回撤達-6.61%,,夏普比率1.62。
推薦閱讀: