趨勢行情不會永遠持續下去,事實上市場大部分時間都處于震蕩行情,是以才會有人希望能得到一種交易政策,既可以用在趨勢行情,也可以用在震蕩行情。那麼今天我們就用發明者量化交易平台,建構一個趨勢和震蕩行情通用的經典恒溫器政策。
提到恒溫器可能會有人想到汽車發動機與水箱之間的恒溫器。當發動機溫度低時,恒溫器是關閉狀态,此時發動機和水箱的水是不相通的,直到發動機溫度升高,達到最佳機油潤滑效果;當發動機溫度升高到一定門檻值時,節溫器是開啟狀态,此時發動機和水箱的水形成循環,并流經風扇開啟降溫模式,直到達到發動機最佳工作溫度。
那麼恒溫器政策也類似這個原理,并且延用了這個名字。它通過波動指數作為門檻值,将市場分為趨勢行情和震蕩行情,自動對兩種不同的行情使用對應的交易邏輯,有效彌補了趨勢政策在震蕩行情中的不适應。
如何把市場劃分為趨勢行情和震蕩行情,也就成了這個政策的關鍵,恒溫器政策引入了市場波動指數(Choppy Market Index),簡稱CMI。它是一個用來判斷市場走勢類型的技術名額。通過計算目前收盤價與N周期前收盤價的內插補點與這段時間内價格波動的範圍的比值,來判斷目前的價格走勢是趨勢還是震蕩。
CMI的計算公式為:
CMI=(abs(Close-ref(close,(n-1)))*100/(HHV(high,n)-LLV(low,n))
其中,abs是絕對值,n是周期數
一般來說CMI的值在0~100區間,值越大,趨勢越強。當CMI的值小于20時,政策認為市場處于震蕩模式;當CMI的值大于等于20時,政策認為市場處于趨勢模式。
- 如果CMI < 20,執行震蕩政策;
- 如果CMI ≥ 20,執行趨勢政策;
完整政策代碼
'''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 # 定義一個全局變量,用于控制虛拟持倉
# 政策主函數
def onTick():
exchange.SetContractType("rb000") # 訂閱期貨品種
bar_arr = exchange.GetRecords() # 擷取K線數組
if len(bar_arr) < 100: # 如果K線少于100根
return # 直接傳回
close0 = bar_arr[-1]['Close'] # 擷取最新價格(賣價),用于開平倉
bar_arr.pop() # 删除K線數組最後一個元素,政策采用開平倉條件成立,下根K線交易模式
# 計算CMI名額用以區分震蕩市與趨勢市
close1 = bar_arr[-1]['Close'] # 最新收盤價
close30 = bar_arr[-30]['Close'] # 前30根K線的收盤價
hh30 = TA.Highest(bar_arr, 30, 'High') # 最近30根K線的最高價
ll30 = TA.Lowest(bar_arr, 30, 'Low') # 最近30根K線的最低價
cmi = abs((close1 - close30) / (hh30 - ll30)) * 100 # 計算市場波動指數
# 震蕩市中收盤價大于關鍵價格為宜賣市,否則為宜買市
high1 = bar_arr[-1]['High'] # 最新最高價
low1 = bar_arr[-1]['Low'] # 最新最低價
kod = (close1 + high1 + 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日均線
high2 = bar_arr[-2]['High'] # 上根K線最高價
high3 = bar_arr[-3]['High'] # 前根K線最高價
low2 = bar_arr[-2]['Low'] # 上根K線最低價
low3 = bar_arr[-3]['Low'] # 前根K線最低價
avg3high = (high1 + high2 + high3) / 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 =