變點理論CUSUM在擇時交易中的應用

張國平發表於2019-08-19

之前看到一篇文章,變點理論CUSUM在量化交易中;列了一堆資料和公式,說結果不錯。連結如下:

https://max.book118.com/html/2017/0726/124391946.shtm

或者這個,就是整理版,有很詳細的公式推導,不過程式碼寫的不清不楚的,應該沒寫完。

https://wizardforcel.gitbooks.io/python-quant-uqer/134.html


花了些時間研究下:

原理描述:CUSUM控制圖的設計思想是對資訊加以累積,將過程的小偏移累加起來,達到放大的結果,從而提高檢驗小偏移的靈敏度。CUSUM作為一個統計量,其由來具有嚴格的數學推理,總的來說,是一個變點假設檢驗通過極大似然法推導得到的統計量。

具體推導不研究了,直接看具體引用



其實就是我之前說到那個那個對數收益率,形成一個對數收益率的近似正太分佈。如上圖,這裡有一個上下允偏量k,這裡設為k = 0.02, 先說上閾值, 那麼時序佇列裡面,下一個時段的對數收益率大於0.02,yi則差值為正;如果差值累計yi的和Ci大於h,比如h為0.5。則觸發向上趨勢。

其實就是如果多次上閾值收益率發生,或者一次非常大的收益率情況發生,是的c值大於h 就會觸發向上趨勢判斷。如果只是偶爾一次大於閾值,那麼下一次小於k (0.02)時候,差值為負值,和值Ci就變小了,這裡Max的作用就是保證C為正,不會因為多次低於k值為負值。下閾值也是同理。


程式碼如下,這裡呼叫ta-lib庫來計算均值和標準差,速度比起用numpy還快一些。用標準差做為 允偏量k;5倍標準差為h 閾值。

# encoding: UTF-8
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import talib
def detect_via_cusum_lg(ts, istart=30, threshold_times=5):
    """
    detect a time series using  cusum algorithm
    :param ts: the time series to be detected
    :param istart: the data from index 0 to index istart will be used as cold startup data to train
    :param threshold_times: the times for setting threshold
    :return:
    """
    S_h = 0
    S_l = 0
    S_list = np.zeros(istart)
    meanArray = talib.SMA(ts,timeperiod = istart)
    stdArray = talib.STDDEV(np.log(ts/meanArray),timeperiod = istart)
    for i in range(istart+1, len(ts)-1):
        tslog = np.log(ts[i] / meanArray[i - 1])
        S_h_ = max(0, S_h + tslog - stdArray[i-1])
        S_l_ = min(0, S_l + tslog + stdArray[i-1])
        if S_h_> threshold_times * stdArray[i-1]:
            S_list = np.append(S_list,1)
            S_h_ = 0
        elif abs(S_l_)> threshold_times *  stdArray[i-1]:
            S_list = np.append(S_list, -1)
            S_l_ = 0
        else:
            S_list = np.append(S_list, 0)
        S_h = S_h_
        S_l = S_l_
    return S_list
#資料匯入
df5min =  pd.read_csv("bar5rb8888.csv")
dt0 = np.array(df5min["close"])
listup,listdown = [],[]
s_list = detect_via_cusum_lg(dt0,istart=30, threshold_times=5)
for i in range(0,len(s_list)):
    if s_list[i] == 1:
        listup.append(i)
    elif s_list[i] == -1 :
        listdown.append(i)
plt.subplot(2,1,1)
plt.plot(dt0, color='y', lw=2.)
plt.plot(dt0, '^', markersize=5, color='r', label='UP signal', markevery=listup)
plt.plot(dt0, 'v', markersize=5, color='g', label='DOWN signal', markevery=listdown)
plt.legend()
plt.subplot(2,1,2)
plt.title('s_list')
plt.plot(s_list,'r-')
plt.show()


用5分鐘螺紋鋼資料跑出來,部分如下,好像有搞頭。程式碼在我Github裡面可以找到

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/22259926/viewspace-2654170/,如需轉載,請註明出處,否則將追究法律責任。

相關文章