CTA策略之均價振幅ATR策略

語言: CN / TW / HK

一、摘要

在物理學中,振幅是在波動或振動中距離平衡位置或靜止位置的最大位移,它是表示振動的範圍和強度的物理量。而商品期貨中的振幅就是:開盤後的當日最高價和最低價之間的差的絕對值與昨日收盤價的百分比,它在一定程度上表現該品種的活躍程度。另外還有一種當日振幅的簡單的計算方式,即收盤價減去開盤價。本篇就以發明者量化平臺的MY語言開發一個均價振幅ATR策略。

二、什麼是振幅

對於CTA趨勢跟蹤策略來說,趨勢行情是其獲利來源,振幅直接反映了一個品種是否活躍,間接則反映了一個品種是否有趨勢行情。振幅有很多計算方式:當日振幅、週期振幅等等...以週期振幅為例:

假如鐵礦石10日前的收盤價是1000,當前K線最高價是1050,上漲5%,最低價是950,下跌5%,那麼振幅就是10%。也就是說價格的振幅是當前K線最高價減去當前K線最低價,再除以前10日K線的收盤價就是其振富比。

除了週期振幅的計算方式外,還有一種更為簡單的計算方式,即當日振幅:最高價減去最低價,或者收盤價減去開盤價。而本策略則是以N日的平均收盤價減去N日的平均開盤價為振幅的依據。

三、什麼是真實波動幅度

在這個策略中,真實波動幅度主要用於判斷開盤倉的買賣時機。真實波動幅度(ATR)是計算一段時期內價格波動幅度的移動平均值。最初是由Welles Wilder在《技術交易系統中的新概念》中最先提出的。

真實波動幅度(ATR)經常引用趨勢跟蹤策略中,如果ATR的值越高,表示價格的趨勢性越強,反之ATR的值越低,表示價格的趨勢性越弱。所以使用ATR作為策略開平倉條件的一部分,可以有效過濾部分震盪行情。

四、策略實現

第1步:計算均價振幅

AMP     :   EMA(CLOSE, N) - EMA(OPEN, N);
AMPUP   :=  CROSSUP(AMP, 0);
AMPDOWN :=  CROSSDOWN(AMP, 0);

定義均價振幅(AMP),即收盤價均線 - 開盤價均線

第2步:計算真實波動幅度

TR      :=  MAX(MAX((HIGH - LOW), ABS(REF(CLOSE, 1) - HIGH)), ABS(REF(CLOSE, 1) - LOW));
ATR     :=  MA(TR, N);
NATR    :=  ATR * X * 0.1;

首先計算出TR(即當天的真實波幅),計算公式為:TR = 當天的高點—當天的低點;但有時候價格會出現跳空高開以及跳空低開的情況,在這種情況下,當天的TR值為:

  • 跳空高開:TR = 當天的高點—昨天的收盤價
  • 跳空低開:TR = 昨天的收盤價—當天的低點

由於一天TR有隨機性,並不能代表最近市場整體波動率,所以用ATR更能衡量市場的波動性,常用的是14週期的ATR,即:ATR = (前13天的TR + 當天的TR)/ 14。最後為了針對部分品種,使用一個係數重新定義平均真實波幅(NATR)。

第3步:計算開平倉價格

  • 多開價格:如果均價振幅上穿0,那麼其價格是最高價+NATR
  • 空開價格:如果均價振幅上穿0,那麼其價格是最低價-NATR
  • 多平價格:如果均價振幅下穿0,那麼其價格是最低價-NATR
  • 空平價格:如果均價振幅下穿0,那麼其價格是最高價+NATR
BKP     :   VALUEWHEN(AMPUP, HIGH + NATR);
SPP     :   VALUEWHEN(AMPUP, LOW - NATR);
SKP     :   VALUEWHEN(AMPDOWN, LOW - NATR);
BPP     :   VALUEWHEN(AMPDOWN, HIGH + NATR);

第4步:下單交易

  • 多頭開倉:如果當前K線數量大於N,並且收盤價大於等於BKP
  • 空頭開倉:如果當前K線數量大於N,並且收盤價小於等於SKP
  • 多頭平倉:如果均價振幅是否下穿0,或者收盤價小於等於SPP
  • 空頭平倉:如果均價振幅是否上穿0,或者收盤價大於等於BPP
BARPOS > N AND CLOSE >= BKP, BK(1);
BARPOS > N AND CLOSE <= SKP, SK(1);
AMPDOWN OR CLOSE <= SPP, SP(1);
AMPUP OR CLOSE >= BPP, BP(1);

五、策略回測

  • 回測開始日期:2016-01-01
  • 回測結束日期:2021-04-01
  • 資料品種:鐵礦石指數
  • 資料週期:日線
  • 滑點:開平倉各2跳

回測配置

回測績效

收益概覽

六、完整策略程式碼

// 回測配置
(*backtest
start: 2016-01-01 00:00:00
end: 2021-04-01 00:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Futures_CTP","currency":"FUTURES","balance":20000}]
args: [["ContractType","i000",126961]]
*)

AMP     :   EMA(CLOSE, N) - EMA(OPEN, N);       // 定義均價振幅(AMP),即收盤價均線 - 開盤價均線
AMPUP   :=  CROSSUP(AMP, 0);                    // 判斷均價振幅是否上穿0,並賦值為AMPUP
AMPDOWN :=  CROSSDOWN(AMP, 0);                  // 判斷均價振幅是否下穿0,並賦值為AMPDOWN
TR      :=  MAX(MAX((HIGH - LOW), ABS(REF(CLOSE, 1) - HIGH)), ABS(REF(CLOSE, 1) - LOW));  // 計算真實波幅(TR)
ATR     :=  MA(TR, N);                          // 計算平均真實波幅(ATR)
NATR    :=  ATR * X * 0.1;                      // 根據係數定義新的平均真實波幅(NATR)
BKP     :   VALUEWHEN(AMPUP, HIGH + NATR);      // 計算多開價格,如果均價振幅上穿0,那麼其價格是最高價+NATR
SPP     :   VALUEWHEN(AMPUP, LOW - NATR);       // 計算多平價格,如果均價振幅上穿0,那麼其價格是最低價-NATR
SKP     :   VALUEWHEN(AMPDOWN, LOW - NATR);     // 計算空開價格,如果均價振幅下穿0,那麼其價格是最低價-NATR
BPP     :   VALUEWHEN(AMPDOWN, HIGH + NATR);    // 計算空平價格,如果均價振幅下穿0,那麼其價格是最高價+NATR

// 開倉
BARPOS > N AND CLOSE >= BKP, BK(1);             // 如果當前K線數量大於N,並且收盤價大於等於BKP,多開
BARPOS > N AND CLOSE <= SKP, SK(1);             // 如果當前K線數量大於N,並且收盤價小於等於SKP,空開

// 止損
AMPDOWN OR CLOSE <= SPP, SP(1);                 // 如果均價振幅是否下穿0,或者收盤價小於等於SPP,多平
AMPUP OR CLOSE >= BPP, BP(1);                   // 如果均價振幅是否上穿0,或者收盤價大於等於BPP, 空平