您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關python如何實現(xiàn)動態(tài)階梯突破策略的內(nèi)容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
什么是突破策略
我們知道,期貨市場的價格以趨勢和震蕩交替的方式演變,如果我們只使用一種方法抓住趨勢,就能賺到趨勢行情的錢。那么,用什么方式來抓住趨勢呢?比較簡單的一種方法就是用突破策略。通過設置價格的上下軌,或者支撐位、壓力位,當價格超過上軌,我們認為行情即將啟動,開倉做多,反之亦然。
市面上有很多不同種類的突破策略,大致可以分為:形態(tài)突破(包括:雙肩型、頭肩型、頸線、趨勢線等等)、指標突破(均線、KDJ、ATR等等)、通道突破(新高和新低、支撐線和阻力線)、量能突破(成交量、能量潮)。其中在量化交易中,最常用的是:指標突破和通道突破。
突破策略理論
在邏輯學中,有一個“充分不必要條件”的概念,也就是說:如果有A不一定有B,但如果有B就必定有A。那么B就是A的充分而不必要的條件,即充分不必要條件,A是B的必要不充分條件。所以站在結(jié)果的角度講,價格突破關鍵點位后未必形成趨勢,但趨勢上漲或下跌必然會突破其間的關鍵價格位置。
另外,從突破的原因上講,市場漲跌取決于買賣雙方實力對比。當價位沖破上一時段的最高點時,在上一時段任何價位做空頭的人都無一例外被套牢,它當中肯定有一部分要認賠平倉出局,反過來又給升勢推波助瀾。相反,當行情跌破上一時段的最低價時,在上一時段任何一點做多頭的統(tǒng)統(tǒng)都出現(xiàn)浮動虧損,其中一定有部分要止損作平倉賣出,正好對跌勢落井下石。
策略邏輯
階梯策略,這是一個比較土的名字,因為其在圖表上的外形類似臺階而得名,最初的靈感來自于階梯止損。相信有過實盤經(jīng)驗的人應該深有體會:當市場進行橫向整理或者搖擺不定的時候,對交叉類系統(tǒng)的打擊很大,往往會買在高點,賣在低點。如果行情一直持續(xù),則會出現(xiàn)連續(xù)虧損,連續(xù)的虧損信號將對交易者造成嚴重的心理負擔和資金回撤壓力。如下圖:
通過利用,通道技術則可以過濾或者減少價格反復纏繞,減少部分虛假信號,對于降低無效交易有巨大幫助。本策略并非傳統(tǒng)的通道策略。而是根據(jù)前期最高價和最低價,反向建立自適應通道。這里提到的自適應是指回溯日期會根據(jù)我們的邏輯進行調(diào)整,具體來說本策略是由市場波動的變動率來變化。
大部分通道策略的組成是由兩個因子決定,第一個就是中軌,然后再根據(jù)中軌算出通道寬度,即上下軌。比如常見的布林帶通道( BollingerBand ),先是由一條均線當中心線,而通道寬度是由標準差所決定。階梯策略的通道并不是以中軌得來,與之相反的是:先根據(jù)市場波動率計算出通道上下軌,然后再根據(jù)通道寬度算出中軌。
另外,在判定最高點和最低點的 K 線條數(shù)取決于我們愿意給交易多少變化空間,我們用來越多的 K 線條數(shù)來確定上下軌,我們給予程序化交易的變化空間越大,相應的,在觸發(fā)止損前盈利回撤的幅度也會越大。使用越近的高點或低點,止損被觸發(fā)的速度也越快。想讓通道窄一點就設定小一點,想讓通道寬一點就設定大一點。
設置通道
上軌:如果當根K線最低價小于上根K線最低價,上軌就等于前N根K線最高價的最高價
下軌:如果當根K線最高價大于上根K線最高價,下軌就等于前N根K線最低價的最低價
中軌:上軌和下軌的平均值
入場條件
多頭入場:如果當前沒有持倉,并且價格大于上軌,買入開倉。
空頭入場:如果當前沒有持倉,并且價格小于下軌,賣出開倉。
出場條件
多頭出場:如果當前持有多單,并且價格小于中軌,賣出平倉。
空頭出場:如果當前持有空單,兵器價格大于中軌,買入平倉。
為了避免過度擬合,在設計策略的時候,只給定了一個參數(shù)。雖然僅有一個參數(shù),但卻不失策略在市場中的靈活性。不僅如此,階梯策略既能適應國內(nèi)外商品期貨,還可以應用于 A 股 ETF ,包括外盤 ETF 和反向杠桿 ETF,以及外匯市場。當然只是適應部分品種,從全品種統(tǒng)計來看,這是一個普適性比較強的策略。
策略編寫
根據(jù)上面的策略邏輯,我們可以在發(fā)明者量化交易平臺上實現(xiàn)交易策略。依次打開:fmz.com > 登錄 > 控制中心 > 策略庫 > 新建策略 > 點擊右上角下拉菜單選擇Python語言,開始編寫策略,注意看下面代碼中的注釋。
第1步:編寫策略框架
這個在之前的章節(jié)已經(jīng)學習過,一個是onTick函數(shù),另一個是main函數(shù),其中在main函數(shù)中無限循環(huán)執(zhí)行onTick函數(shù),如下:
def onTick(): pass def main(): while True: onTick() Sleep(1000)
第2步:定義全局變量
首先定義策略中的上軌、下軌,因為我們的策略中上軌、下軌時是根據(jù)一定的條件來計算的,也就是說:當前的最高價大于前面K線的最高價時,才重新計算下軌;當前的最低價小于前面K線的最低價時,才重新計算上軌。所以我們必須把上軌和下軌變量定義在onTick主函數(shù)外面。
up_line = 0 # 上軌 under_line = 0 # 下軌 mp = 0 # 用于控制虛擬持倉
另外,我們還需要定義全局變量虛擬持倉mp,策略運行之初默認是空倉mp=0,當開多單后把虛擬持倉重置為mp=1,當開空單后把虛擬持倉重置為,mp=-1,當平多單或空單后把虛擬持倉重置為mp=0。這樣我們在判斷構(gòu)建邏輯獲取倉位時,只需要判斷mp的值就可以了。
第3步:計算上軌、下軌、中軌
因為在計算這些數(shù)據(jù)之前,肯定要先獲取歷史的K線基礎數(shù)據(jù),這些基礎數(shù)據(jù)的獲取方式也很簡單,首先訂閱期貨品種,然后調(diào)用發(fā)明者量化API中的GetRecords方法。接著因為在計算上軌和下軌的時候需要用到talib庫中的Highest和Lowest方法,這兩個方法都要傳入周期參數(shù),但如果K線數(shù)據(jù)不夠的時候,就不能正常計算其值,所以在這里就要判斷K線數(shù)據(jù)的長度,如果K線的長度不足以計算其值時,就直接返回跳過。
接著,我們分別獲取當前K線和上根K線的最高價和最低價,通過對比當前K線最高價與上根K線最高價來定義下軌的值,如果當前的最高價大于前面K線的最高價時,就重新計算下軌;同理如果當前的最低價小于前面K線的最低價時,就重新計算上軌。最后上軌和下軌的平均值就是中軌。
exchange.SetContractType("rb000") # 訂閱期貨品種 bars = exchange.GetRecords() # 獲取K線數(shù)組 if len(bars) < cycle_length + 1: # 如果K線數(shù)組的長度太小,所以直接返回 return close0 = bars[len(bars) - 1].Close; # 獲取當根K線收盤價 high0 = bars[len(bars) - 1].High; # 獲取當根K線最高價 high2 = bars[len(bars) - 2].High; # 獲取上根K線最高價 low0 = bars[len(bars) - 1].Low; # 獲取當根K線最低價 low1 = bars[len(bars) - 2].Low; # 獲取上根K線最低價 highs = TA.Highest(bars, cycle_length, 'High'); # 獲取前cycle_length根K線最高價的最高價 lows = TA.Lowest(bars, cycle_length, 'Low'); # 獲取前cycle_length根K線最低價的最低價 global up_line, under_line, mp # 使用全局變量 if high0 > high2: # 如果當根K線最高價大于上根K線最高價 under_line = lows # 把下軌重新賦值為:前cycle_length根K線最低價的最低價 if low0 < low1: # 如果當根K線最低價小于上根K線最低價 up_line = highs # 把上軌重新賦值為:前cycle_length根K線最高價的最高價 middle_line = (lows + highs) / 2; # 計算中軌的值
這里有一個地方需要注意,可能細心的朋友已經(jīng)發(fā)現(xiàn)了,我們在計算上軌和下軌的時候,用到了talib庫中的Highest和Lowest函數(shù),因為在發(fā)明者量化軟件中已經(jīng)內(nèi)置了這兩個常用的函數(shù),所以我們不需要像前幾節(jié)那樣在策略開頭導入talib庫,并且在使用內(nèi)置函數(shù)的時候,其寫法也略有不同,具體可以查看下方的代碼。
第4步:下單交易
有了上軌、下軌、中軌的值,就可以配合當前的最新價格開平倉交易了,我們可以回過頭再看下之前設計的交易邏輯:如果當前沒有持倉,并且價格大于上軌 * 1.05,買入開倉。如果當前沒有持倉,并且價格小于下軌 * 0.95,賣出開倉。如果當前持有多單,并且價格小于中軌,賣出平倉。如果當前持有空單,兵器價格大于中軌,買入平倉。
if mp == 0 and close0 > up_line: # 如果當前空倉,并且最新價大于上軌 exchange.SetDirection("buy") # 設置交易方向和類型 exchange.Buy(close0, 1) # 開多單 mp = 1 # 設置虛擬持倉的值,即有多單 if mp == 0 and close0 < under_line: # 如果當前空倉,并且最新價小于下軌 exchange.SetDirection("sell") # 設置交易方向和類型 exchange.Sell(close0 - 1, 1) # 開空單 mp = -1 # 設置虛擬持倉的值,即有空單 if mp > 0 and close0 < middle_line: # 如果當前持有多單,并且最新價小于中軌 exchange.SetDirection("closebuy") # 設置交易方向和類型 exchange.Sell(close0 - 1, 1) # 平多單 mp = 0 # 設置虛擬持倉的值,即空倉 if mp < 0 and close0 > middle_line: # 如果當前持有空單,并且最新價大于中軌 exchange.SetDirection("closesell") # 設置交易方向和類型 exchange.Buy(close0, 1) # 平空單 mp = 0 # 設置虛擬持倉的值,即空倉
下單交易使用if語句,如果條件為真,就先設置交易方向和類型,即:開多、開空、平多、平空。然后調(diào)用發(fā)明者量化軟件中的Buy或Sell下單函數(shù),最后下單之后重置虛擬持倉的狀態(tài)。
完整策略代碼
'''backtest start: 2015-02-22 00:00:00 end: 2019-10-29 00:00:00 period: 1h exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}] ''' # 外部參數(shù) cycle_length = 100 # 定義全局變量 up_line = 0 # 上軌 under_line = 0 # 下軌 mp = 0 # 用于控制虛擬持倉 def onTick(): exchange.SetContractType("rb000") # 訂閱期貨品種 bars = exchange.GetRecords() # 獲取K線數(shù)組 if len(bars) < cycle_length + 1: # 如果K線數(shù)組的長度太小,所以直接返回 return close0 = bars[len(bars) - 1].Close; # 獲取當根K線收盤價 high0 = bars[len(bars) - 1].High; # 獲取當根K線最高價 high2 = bars[len(bars) - 2].High; # 獲取上根K線最高價 low0 = bars[len(bars) - 1].Low; # 獲取當根K線最低價 low1 = bars[len(bars) - 2].Low; # 獲取上根K線最低價 highs = TA.Highest(bars, cycle_length, 'High'); # 獲取前cycle_length根K線最高價的最高價 lows = TA.Lowest(bars, cycle_length, 'Low'); # 獲取前cycle_length根K線最低價的最低價 global up_line, under_line, mp # 使用全局變量 if high0 > high2: # 如果當根K線最高價大于上根K線最高價 under_line = lows # 把下軌重新賦值為:前cycle_length根K線最低價的最低價 if low0 < low1: # 如果當根K線最低價小于上根K線最低價 up_line = highs # 把上軌重新賦值為:前cycle_length根K線最高價的最高價 middle_line = (lows + highs) / 2; # 計算中軌的值 if mp == 0 and close0 > up_line: # 如果當前空倉,并且最新價大于上軌 exchange.SetDirection("buy") # 設置交易方向和類型 exchange.Buy(close0, 1) # 開多單 mp = 1 # 設置虛擬持倉的值,即有多單 if mp == 0 and close0 < under_line: # 如果當前空倉,并且最新價小于下軌 exchange.SetDirection("sell") # 設置交易方向和類型 exchange.Sell(close0 - 1, 1) # 開空單 mp = -1 # 設置虛擬持倉的值,即有空單 if mp > 0 and close0 < middle_line: # 如果當前持有多單,并且最新價小于中軌 exchange.SetDirection("closebuy") # 設置交易方向和類型 exchange.Sell(close0 - 1, 1) # 平多單 mp = 0 # 設置虛擬持倉的值,即空倉 if mp < 0 and close0 > middle_line: # 如果當前持有空單,并且最新價大于中軌 exchange.SetDirection("closesell") # 設置交易方向和類型 exchange.Buy(close0, 1) # 平空單 mp = 0 # 設置虛擬持倉的值,即空倉 def main(): while True: onTick() Sleep(1000)
感謝各位的閱讀!關于“python如何實現(xiàn)動態(tài)階梯突破策略”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。