Related Posts Display

  DỰ ÁN 06: KIỂM ĐỊNH  COINTEGRATION CRYPTO CÙNG BINANCE API VÀ  KALMAN FILTER I.      Ý tưởng chính             Trong bài viết này...

Dự án 06: Kiểm định cointegration Crypto cùng Binance API và Kalman Filter

 DỰ ÁN 06: KIỂM ĐỊNH COINTEGRATION CRYPTO CÙNG BINANCE API VÀ KALMAN FILTER

I.    Ý tưởng chính

         Trong bài viết này tôi sẽ kiểm định cointegration, tính hedging ratio tĩnh và động bằng bộ lọc Kalman.

II.   Kiểm định cointegration

Dữ liệu được sử dụng trong bài viết là chuỗi dữ liệu của 2 symbol là ATOMUSDT và NEARUSDT từ 1/1/2021 đến 1/9/2021, khung thời gian là H1.

Import các thư viện như sau:

Hàm để lấy dữ liệu từ binance api như sau:


Dùng block lệnh sau để lấy data của hai symbol và lưu vào Dataframe c:

Dataframe c sẽ có dạng:
Tôi sẽ kiểm định đồng kết hợp theo 2 cách thông thường là Engle-Granger two-step (hay còn gọi là Cointegrated Augmented Dickey-Fuller (CADF)) và Johansen Test:
1. Engle-Granger two-step:
Sử dụng đoạn code sau:
Như ta thấy kết quả p-value = 0.04 < 0.05, như vậy giá thiết 2 chuỗi giá này không là đồng kết hợp bị bác bỏ với độ tin cậy lớn hơn 95%
2. Johansen Test:
Điểm mạnh của Johansen Test là có thể kiểm định và tính toán luôn hệ số góc (hedging ratio) của tổ hợp nhiều chuỗi giá cùng lúc (<12 chuỗi). Sử dụng đoạn code sau:
Như ta đã thấy 2 phần tử của thuộc tính trace_stat đều lớn hơn phần tử trong thuộc tính  trace_stat_crit_vals tương ứng với độ tin cậy 95% (18.6 > 15.5, 4.07 > 3.84). Như vậy 2 chuỗi giá này là đồng kết hợp với độ tin cậy lớn hơn 95%
=> Trong cả 2 cách kết quả là tương đương nhau

III.   Tính toán Hedging ratio (HR)

HR hiểu đơn giản là hệ số góc đường hồi quy của 2 chuỗi giá

Công thức: At = I + H * Bt + et (H là hedging ratio của 2 chuỗi giá A và B, I là hệ số chặn, et là sai số)

1. Tính toán HR tĩnh:

1.1 Tính HR theo CADF

Ta sẽ tính toán trong 2 trường hợp, tại đó mỗi symbol sẽ được làm biến độc lập hoặc phụ thuộc một lần:

Như ta thấy kết qủa test-statistic của test 2 là -3.78 < -3.63 của lần test 1, như vậy ra sẽ chọn ATOMUSDT là biến phụ thuộc và NEARUSDT là biến độc lập.
Hệ số góc tại đây cho kết quả là 3.17, hệ số chặn là 3.99
Đồ thị biểu diễn et (spread):
Trông khá là mean reversion đấy chứ, phải vậy thôi vì data mining mà 😆

1.2 Tính HR theo Johansen Test:
Thực ra ngay ở trên phần test chúng ta đã có kết quả rồi, tôi xin được viết lại tại đây:
Như chúng ta thấy cột đầu tiên của ma trận evector có 2 hệ số là 0.37 và -1.25 => HR =  -(1.25/0.37) = 3.39, gần bằng kết quả 3.17 ở trên (nhưng hơi xa so với dự tính của tôi, có sai ở đâu không ta ? 😐).
Đồ thị biểu diễn I + et:
Kết quả giống như cách trên
1.3 Tính Half Life
Nói đơn giản thì Half life không phải là game bắn súng mà chúng ta hay chơi mà là số điểm dữ liệu trung bình trong mỗi chu kỳ reversion của chuỗi giá.
Hàm tính Half line:

Kết quả Half Life:
- Của chuỗi et tạo ra từ phương pháp CADF: 123 (giờ)
- Của chuỗi et tạo ra từ phương pháp Johansen Test: 120 (giờ)
2. Tính toán HR động bằng Kalman Filter:
Giải thích Kalman Filter là cả một câu chuyện dài nên tôi xin phép chỉ upcode 😝
Cách 1 - Dùng thư viện pykalman:
Kết quả:

Cách 2 - Không cần dùng thư viện:
Code:
class MyKalmanFilter:
    
    def __init__(self, delta=1e-4, R=1e-3):
        # measurement noise variance
        self.R = R

        # co-variance of process noise(2 dimensions)
        self.Q = delta / (1-delta) * np.eye(2) #Tao ma tran 2*2 voi 1 o duong cheo, sau do nhan ma tran nay voi delta/(1-delta) 

        # state (slope, intercept) will be (2 x n), we will initialize with just one column at first
        self.x = np.zeros((2, 1)) #Tao ma tran rong 2*1 (se thay doi theo thoi gian) 

        # state covariance
        self.P = np.zeros((2,2)) #Tao ma tran rong 2*2 (se thay doi theo thoi gian)    

    def step_forward(self, y1, y2): #y1, y2 lan luot la gia tri tung hang cua cot EWC va EWA
        # Before entering the equations, let's define H as (1, 2) matrix
        H = np.array([y2, 1])[None] #Tao mot array kieu [[y2, 1]]
        # and define z
        z = y1

        ## TIME UPDATE ##
        # first thing is to predict new state as the previous one (2x1)
        x_hat = self.x[:, -1][..., None]

        # then, the uncertainty or covariance prediction 
        P_hat = self.P + self.Q

        ## MEASUREMENT UPDATE ##
        # calc the Kalman gain
        K = P_hat.dot(H.T)/(H.dot(P_hat.dot(H.T))+self.R)

        # state update part 1 (measurement estimation)
        z_hat = H.dot(x_hat)
        # state update part 2
        x = x_hat + K.dot(z-z_hat)

        # uncertainty update
        self.P = (np.eye(2)-K.dot(H)).dot(P_hat)

        # append the new state to the vector
        self.x = np.concatenate([self.x, x], axis=1)

        return x, self.P, K, z_hat

mkf = MyKalmanFilter(delta=1e-4, R=1e-3)
series = []
for idx, row in c.iterrows():
    x, P, K, z_hat = mkf.step_forward(row[symbol_list[1]], row[symbol_list[0]])
    series.append(row[symbol_list[1]] - z_hat.squeeze())

# Plot the combined portfolio
plt.figure(figsize=(20,10))
plt.plot(series[10:])

# Plot the hedge ratio over time
plt.figure(figsize=(20,5))
plt.plot(mkf.x[0, 1:])

# Plot the intercept over time
plt.figure(figsize=(20,5))
plt.plot(mkf.x[1, 1:])


Kết quả:
et:

HR:

Hệ số chặn:



Túm lại là kết quả giống nhau.
Các bạn có thể tải full notebook tại đây, sorry vì cái notebook nhìn như tờ nháp 😝
Cùng đón xem bài viết tiếp theo về thực thi chiến lược pair trading Crypto bằng Kalman Filter nha.

0 nhận xét: