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