您好,登錄后才能下訂單哦!
小編給大家分享一下如何使用python實現(xiàn)恒溫器策略,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
策略簡介
提到恒溫器可能會有人想到汽車發(fā)動機與水箱之間的恒溫器。當發(fā)動機溫度低時,恒溫器是關閉狀態(tài),此時發(fā)動機和水箱的水是不相通的,直到發(fā)動機溫度升高,達到最佳機油潤滑效果;當發(fā)動機溫度升高到一定閾值時,節(jié)溫器是開啟狀態(tài),此時發(fā)動機和水箱的水形成循環(huán),并流經(jīng)風扇開啟降溫模式,直到達到發(fā)動機最佳工作溫度。
那么恒溫器策略也類似這個原理,并且延用了這個名字。它通過波動指數(shù)作為閾值,將市場分為趨勢行情和震蕩行情,自動對兩種不同的行情使用對應的交易邏輯,有效彌補了趨勢策略在震蕩行情中的不適應。
市場波動指數(shù)
如何把市場劃分為趨勢行情和震蕩行情,也就成了這個策略的關鍵,恒溫器策略引入了市場波動指數(shù)(Choppy Market Index),簡稱CMI。它是一個用來判斷市場走勢類型的技術指標。通過計算當前收盤價與N周期前收盤價的差值與這段時間內價格波動的范圍的比值,來判斷目前的價格走勢是趨勢還是震蕩。
CMI的計算公式為:
CMI=(abs(Close-ref(close,(n-1)))*100/(HHV(high,n)-LLV(low,n))
其中,abs是絕對值,n是周期數(shù)。
策略邏輯
一般來說CMI的值在0~100區(qū)間,值越大,趨勢越強。當CMI的值小于20時,策略認為市場處于震蕩模式;當CMI的值大于等于20時,策略認為市場處于趨勢模式。
整個策略邏輯,可以簡化的寫成下面這樣:
如果CMI < 20,執(zhí)行震蕩策略;
如果CMI ≥ 20,執(zhí)行趨勢策略;
策略架構就是這么簡單,剩下的就是把震蕩策略的內容和趨勢策略的內容,填充到這個框架里面。
策略編寫
依次打開:fmz.com網(wǎng)站 > 登錄 > 控制中心 > 策略庫 > 新建策略 > 點擊右上角下拉菜單選擇Python語言,開始編寫策略,注意看下面代碼中的注釋。
第1步:編寫策略框架
這個在之前的章節(jié)已經(jīng)學習過,一個是onTick函數(shù),另一個是main函數(shù),其中在main函數(shù)中無限循環(huán)執(zhí)行onTick函數(shù),如下:
# 策略主函數(shù) def onTick(): pass # 程序入口 def main(): while True: # 進入無限循環(huán)模式 onTick() # 執(zhí)行策略主函數(shù) Sleep(1000) # 休眠1秒
第2步:定義虛擬持倉變量
mp = 0 # 定義一個全局變量,用于控制虛擬持倉
虛擬持倉的作用主要是用來控制策略倉位,當策略運行之初默認是空倉mp=0,當開多單后把虛擬持倉重置為mp=1,當開空單后把虛擬持倉重置為,mp=-1,當平多單或空單后把虛擬持倉重置為mp=0。這樣我們在判斷構建邏輯獲取倉位時,只需要判斷mp的值就可以了。虛擬持倉的特點時編寫簡單,快速迭代策略更新,一般用于回測環(huán)境中,假設每一筆訂單都完全成交,但在實際交易中常用的還是真實持倉。
第3步:獲取基礎數(shù)據(jù)
exchange.SetContractType("rb000") # 訂閱期貨品種 bar_arr = exchange.GetRecords() # 獲取K線數(shù)組 if len(bar_arr) < 100: # 如果K線少于100根 return # 直接返回 close0 = bar_arr[-1]['Close'] # 獲取最新價格(賣價),用于開平倉 bar_arr.pop() # 刪除K線數(shù)組最后一個元素,策略采用開平倉條件成立,下根K線交易模式
首先使用發(fā)明者量化API中的SetContractType方法訂閱期貨品種。接著使用GetRecords方法獲取K線數(shù)組,因為有時候K線數(shù)量太少,導致無法計算一些數(shù)據(jù),所以我們判斷如果K線少于100根,就直接返回等待下一次新數(shù)據(jù)。
然后我們從K線數(shù)組中獲取最新的賣一價,這個主要用于使用開平倉函數(shù)時傳入價格參數(shù)。最后因為我們的策略采用當前K線開平倉條件成立,在下根K線交易的模式,所以需要刪除K線數(shù)組最后一個元素。這樣做有2個好處:第1個可以使回測績效更接近于實盤;第2個是避免未來函數(shù)和偷價這些常見的策略邏輯錯誤。
計算市場波動指數(shù)CMI
close1 = bar_arr[-1]['Close'] # 最新收盤價 close30 = bar_arr[-30]['Close'] # 前30根K線的收盤價 hh40 = TA.Highest(bar_arr, 30, 'High') # 最近30根K線的最高價 ll30 = TA.Lowest(bar_arr, 30, 'Low') # 最近30根K線的最低價 cmi = abs((close1 - close30) / (hh40 - ll30)) * 100 # 計算市場波動指數(shù)
根據(jù)CMI的計算公式,我們需要4個數(shù)據(jù),分別是:最新收盤價、前30根K線的收盤價、最近30根K線的最高價、最近30根K線的最低價。前兩個很簡單,可以直接從K線數(shù)組中獲取。最后兩個則需要調用發(fā)明者量化內置的talib指標庫TA.Highest和TA.Lowest,這兩個指標函數(shù)需要傳入三個參數(shù),分別是:K線數(shù)據(jù)、周期、屬性。最后當前收盤價與前30根K線的收盤價的差值與這段時間內價格波動的范圍的比值就是市場波動指數(shù)CMI。
定義宜賣市和宜買市
high2 = bar_arr[-1]['High'] # 最新最高價 low1 = bar_arr[-1]['Low'] # 最新最低價 kod = (close1 + high2 + low1) / 3 # 計算關鍵價格 if close1 > kod: be = 1 se = 0 else: be = 0 se = 1
在震蕩市場中,通常存在一種現(xiàn)象:如果今天價格上漲的話,那么明天的價格下跌的概率更大。而今天價格如果下跌的話,那么明天的價格上漲的概率更大,而這也正是震蕩市場的特性。所以這里首先定義一個關鍵價格(最高價+最低價+收盤價的平均值)。這些數(shù)據(jù)都可以在K線數(shù)據(jù)中直接獲取。如果當前價格大于關鍵價格,那么明天應該震蕩看空。相反的,如果當前價格小于關鍵價格,那么明天應該震蕩看多。
計算震蕩行情的進出場價格
# 計算10根K線ATR指標 atr10 = TA.ATR(bar_arr, 10)[-1] # 定義最高價與最低價3日均線 high3 = bar_arr[-2]['High'] # 上根K線最高價 high4 = bar_arr[-3]['High'] # 前根K線最高價 low2 = bar_arr[-2]['Low'] # 上根K線最低價 low3 = bar_arr[-3]['Low'] # 前根K線最低價 avg3high = (high2 + high3 + high4) / 3 # 最近3根K線最高價的均值 avg3low = (low1 + low2 + low3) / 3 # 最近3根K線最低價的均值 # 計算震蕩行情的進出場價格 open1 = bar_arr[-1]['Open'] # 最新開盤價 if close1 > kod: # 如果收盤價大于關鍵價格 lep = open1 + atr10 * 3 sep = open1 - atr10 * 2 else: lep = open1 + atr10 * 2 sep = open1 - atr10 * 3 lep1 = max(lep, avg3high) # 計算震蕩市多頭進場價格 sep1 = min(sep, avg3low) # 計算震蕩市空頭進場價格
首先計算10根K線ATR指標,同樣也是直接調用發(fā)明者量化的內置talib庫中的TA.ATR即可。為了防止假突破,導致策略來回止損,因此加入了一個最高價與最低價3日均線濾網(wǎng)來避免這種情形,分別從K線數(shù)組中獲取最近3根K線的值求其平均就可以了。
有了以上計算步驟,最后就可以計算震蕩行情中的進出場價格了,其原理是以開盤價為中心,上下加減最近10根K線的真實波動幅度,形成一個開多和開空的價格通道。為了使策略更加符合市場走勢,在做多和做空時分別設置了不同的空間。
在震蕩行情中看多,只代表價格上漲的概率更大一些,并不是指價格一定就會上漲。所以把做多的閾值設置的比較低一點,把做空的閾值設置的比較高一點。同理在震蕩行情中看空,只代表價格下跌的概率更大一些,并不是指價格一定就會下跌。所以把做空的閾值設置的比較低一點,把做多的閾值設置的比較高一點。
計算趨勢行情的進場價格
boll = TA.BOLL(bar_arr, 50, 2) up_line = boll[0][-1] mid_line = boll[1][-1] down_line = boll[2][-1]
在處理趨勢行情的進出場價格上,沿用了布林帶策略,當價格向上突破布林帶上軌時多頭開倉,當價格向下突破布林帶下軌時空頭開倉,平倉方式則是以當前價格與布林中軌的位置關系來判斷。
完整策略代碼
'''backtest start: 2015-02-22 00:00:00 end: 2019-12-20 00:00:00 period: 1h exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}] ''' mp = 0 # 定義一個全局變量,用于控制虛擬持倉 # 策略主函數(shù) def onTick(): exchange.SetContractType("rb000") # 訂閱期貨品種 bar_arr = exchange.GetRecords() # 獲取K線數(shù)組 if len(bar_arr) < 100: # 如果K線少于100根 return # 直接返回 close0 = bar_arr[-1]['Close'] # 獲取最新價格(賣價),用于開平倉 bar_arr.pop() # 刪除K線數(shù)組最后一個元素,策略采用開平倉條件成立,下根K線交易模式 # 計算CMI指標用以區(qū)分震蕩市與趨勢市 close1 = bar_arr[-1]['Close'] # 最新收盤價 close30 = bar_arr[-30]['Close'] # 前30根K線的收盤價 hh40 = TA.Highest(bar_arr, 30, 'High') # 最近30根K線的最高價 ll30 = TA.Lowest(bar_arr, 30, 'Low') # 最近30根K線的最低價 cmi = abs((close1 - close30) / (hh40 - ll30)) * 100 # 計算市場波動指數(shù) # 震蕩市中收盤價大于關鍵價格為宜賣市,否則為宜買市 high2 = bar_arr[-1]['High'] # 最新最高價 low1 = bar_arr[-1]['Low'] # 最新最低價 kod = (close1 + high2 + low1) / 3 # 計算關鍵價格 if close1 > kod: be = 1 se = 0 else: be = 0 se = 1 # 計算10根K線ATR指標 atr10 = TA.ATR(bar_arr, 10)[-1] # 定義最高價與最低價3日均線 high3 = bar_arr[-2]['High'] # 上根K線最高價 high4 = bar_arr[-3]['High'] # 前根K線最高價 low2 = bar_arr[-2]['Low'] # 上根K線最低價 low3 = bar_arr[-3]['Low'] # 前根K線最低價 avg3high = (high2 + high3 + high4) / 3 # 最近3根K線最高價的均值 avg3low = (low1 + low2 + low3) / 3 # 最近3根K線最低價的均值 # 計算震蕩行情的進場價格 open1 = bar_arr[-1]['Open'] # 最新開盤價 if close1 > kod: # 如果收盤價大于關鍵價格 lep = open1 + atr10 * 3 sep = open1 - atr10 * 2 else: lep = open1 + atr10 * 2 sep = open1 - atr10 * 3 lep1 = max(lep, avg3high) # 計算震蕩市多頭進場價格 sep1 = min(sep, avg3low) # 計算震蕩市空頭進場價格 # 計算趨勢行情的進場價格 boll = TA.BOLL(bar_arr, 50, 2) up_line = boll[0][-1] mid_line = boll[1][-1] down_line = boll[2][-1] global mp # 引入全局變量 if cmi < 20: # 如果是震蕩行情 if mp == 0 and close1 >= lep1 and se: exchange.SetDirection("buy") # 設置交易方向和類型 exchange.Buy(close0, 1) # 開多單 mp = 1 # 設置虛擬持倉的值,即有多單 if mp == 0 and close1 <= sep1 and be: exchange.SetDirection("sell") # 設置交易方向和類型 exchange.Sell(close0 - 1, 1) # 開空單 mp = -1 # 設置虛擬持倉的值,即有空單 if mp == 1 and (close1 >= avg3high or be): exchange.SetDirection("closebuy") # 設置交易方向和類型 exchange.Sell(close0 - 1, 1) # 平多單 mp = 0 # 設置虛擬持倉的值,即空倉 if mp == -1 and (close1 <= avg3low or se): exchange.SetDirection("closesell") # 設置交易方向和類型 exchange.Buy(close0, 1) # 平空單 mp = 0 # 設置虛擬持倉的值,即空倉 else: # 如果是趨勢行情 if mp == 0 and close1 >= up_line: exchange.SetDirection("buy") # 設置交易方向和類型 exchange.Buy(close0, 1) # 開多單 mp = 1 # 設置虛擬持倉的值,即有多單 if mp == 0 and close1 <= down_line: exchange.SetDirection("sell") # 設置交易方向和類型 exchange.Sell(close0 - 1, 1) # 開空單 mp = -1 # 設置虛擬持倉的值,即有空單 if mp == 1 and close1 <= mid_line: exchange.SetDirection("closebuy") # 設置交易方向和類型 exchange.Sell(close0 - 1, 1) # 平多單 mp = 0 # 設置虛擬持倉的值,即空倉 if mp == -1 and close1 >= mid_line: exchange.SetDirection("closesell") # 設置交易方向和類型 exchange.Buy(close0, 1) # 平空單 mp = 0 # 設置虛擬持倉的值,即空倉 # 程序入口 def main(): while True: # 進入無限循環(huán)模式 onTick() # 執(zhí)行策略主函數(shù) Sleep(1000) # 休眠1秒
點擊復制完整策略源碼 https://www.fmz.com/strategy/179014 無需配置直接回測
策略回測
為了將回測結果盡量接近實盤交易,這里把手續(xù)費設置為交易所的2倍,開倉和平倉各加2跳的滑點,回測的數(shù)據(jù)品種為螺紋鋼指數(shù),交易品種為螺紋鋼主力連續(xù)。固定1手開倉。以下是在1小時級別的初步回測績效報告。
以上是“如何使用python實現(xiàn)恒溫器策略”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業(yè)資訊頻道!
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內容。