1. 程式人生 > >R語言對高頻交易訂單流進行建模分析 4

R語言對高頻交易訂單流進行建模分析 4

一、實驗介紹--訂單流模型擬合

1.1 實驗知識點

  • 指數核 hawkes 過程擬合
  • 正反饋強度分析
  • 訂單量影響分析

1.2 實驗環境

  • R 3.4.1
  • Rstudio

二、訂單流模型擬合

在上節中我們對訂單流資料做了一些統計分析 , 對交易的一些特徵有了一些粗淺的理解 , 在本節中 我們要做的是利用實際資料來擬合 hawkes 過程 ,看一看真實資料的訂單流動力學中有什麼特徵。

首先我們仍是選出交易時間內的資料:

library(tidyverse)
library(lubridate)

dat <- read.csv(url("http://labfile.oss.aliyuncs.com/courses/883/pigu.csv"))

bisect_lower_bound <- function(x) {
  date <- as.POSIXct(x[1],origin="1970-01-01",tz="America/Chicago") + days(1)
  hour(date) <- 8
  minute(date) <- 30
  second(date) <- 0
  k <- as.numeric(date)

  l = -1
  r = length(x)+1
  while(r-l>1) {
    mid = round((l+r)/2)
    if (x[mid] >= k) r=mid
    else l=mid
  }
  r
}

bisect_higher_bound <- function(x) {
  date <- as.POSIXct(x[1],origin="1970-01-01",tz="America/Chicago") + days(1)
  hour(date) <- 15
  minute(date) <- 0
  second(date) <- 0
  k <- as.numeric(date)

  l = -1
  r = length(x)+1
  while(r-l>1) {
    mid = round((l+r)/2)
    if (x[mid] <= k) l=mid
    else r=mid
  }
  l
}

start <- bisect_lower_bound(dat$time)
end <- bisect_higher_bound(dat$time)
trade <- dat[start:end,]

2.1 指數核 hawkes 過程擬合

形象地來看,限價單組建起了買方和賣方的堡壘,而市價單則對對手的堡壘發起衝擊。

那麼作為進攻部隊,市價單對買方賣方力量的博弈是非常關鍵的,在本節中我們就單獨看一看市價單的動力學是怎麼樣的。

我們先把所有的市價單單獨提出來:

market_order <- trade[trade$action_type=="T",] 
head(market_order)
##             X action_item action_type ask_price ask_vol bid_price bid_vol
## 959396 959395         trd           T    145925     643    145900     364
## 959397 959396 trd T 145925 640 145900 364 ## 959413 959412 trd T 145925 642 145900 372 ## 959414 959413 trd T 145925 642 145900 366 ## 959415 959414 trd T 145925 642 145900 365 ## 959416 959415 trd T 145925 642 145900 364
## price time vol ## 959396 145925 1358260200 3 ## 959397 145925 1358260200 3 ## 959413 145900 1358260200 1 ## 959414 145900 1358260200 6 ## 959415 145900 1358260200 1 ## 959416 145900 1358260200 1

然後做一些預處理,把時間相同的訂單進行合併,並把所有時間減去初始值

m <- market_order %>% group_by(time) %>% summarise(sum(vol))
time <- m$time - m$time[1]
vol <- m$`sum(vol)`

首先我們不考慮訂單量的大小,把所有買單賣單視作同質的,用指數核的 hawkes 過程進行擬合,

這裡可以直接使用第二節所用的似然函式,然後用 nlminb 函式做優化:

log_likelihood <- function(params , event) {
  mu = params[1]
  alpha = params[2]
  beta = params[3]

  n = length(event)
  t_n = event[n]

  kernel_sum <- numeric(n)

  for (i in 2:n) {
    kernel_sum[i] = (kernel_sum[i-1]+alpha) * exp(-beta*(event[i] - event[i-1]))
  }

  lambda <- kernel_sum + mu

  L = sum( log(lambda) ) - mu * t_n - alpha*n/beta + alpha/beta*sum(exp(-beta*(t_n-event)))

  #print(L)
  -L
}
nlminb(c(1,1,1) , log_likelihood ,event= time)
## $par
## [1]   1.522979 145.265214 368.465284
## 
## $objective
## [1] -80224.79
## 
## $convergence
## [1] 0
## 
## $iterations
## [1] 39
## 
## $evaluations
## function gradient 
##       44      131 
## 
## $message
## [1] "relative convergence (4)"


擬合得到的 beta 的值非常大,說明前面事件對後面事件的影響衰減得非常快。注意 1/beta 被定義為 Hawkes 過程的記憶時間 , 超過這個時間的後續事件基本不受這個事件的影響 。 這裡我們可以看到影響週期小於一毫秒 , 說明頻率確實非常快。

2.2 正反饋強度分析

索羅斯在他的“金融鍊金術”中提出了一種叫做 reflexity(自反性)的理論 , 這個理論說的是投資者和交易者的認知偏差會改變標的的基本面。例如一支股票持續上漲,會使得投資者對提高對它基本面的認知 ,又反過來推動股價的進一步上升, 從而形成正反饋。

但是如何量化地對正反饋進行分析一直是一個問題。在 Hawkes 過程中,根據 lambda 的表示式我們可以把事件發生的強度分為兩部分 , 一部分是背景的強度 , 一部分則是由前面事件激發而得到的強度,這部分“衍生”的強度的平均值可以被認為是正反饋的強度。

例如在指數核中,我們可以通過積分計算出正反饋機制的比例是 alpha / beta , 下面我們把一天的時間按照30分鐘的間隔分為13段 , 看看每一段的背景強度和 reflexity 分別是多少。

time_cut <- cut(time , breaks = seq(-0.01 , time[length(time)]+0.01 , length.out=14) )
reflexity <- as.data.frame(cbind(time , time_cut))
reflexity_res <- list()
for (i in 1:13) {
    ref_time <- time[reflexity$time_cut==i]
    ref_time <- ref_time - ref_time[1]
    ref_res <- nlminb(c(1,1,1) , log_likelihood ,event= ref_time  )
    reflexity_res[[i]] <- ref_res
}

## Warning messages:
## 1: In log(lambda) : \u4ea7\u751f\u4e86NaNs
## 2: In nlminb(c(1, 1, 1), log_likelihood, event = ref_time) :
##  NA/NaN function evaluation
## 3: In log(lambda) : \u4ea7\u751f\u4e86NaNs
## 4: In nlminb(c(1, 1, 1), log_likelihood, event = ref_time) :
##  NA/NaN function evaluation
## 5: In log(lambda) : \u4ea7\u751f\u4e86NaNs
## 6: In nlminb(c(1, 1, 1), log_likelihood, event = ref_time) :
##  NA/NaN function evaluation

mu_vec <- c()
alpha_vec <- c()
beta_vec <- c()
for (i in 1:13) {
  mu_vec <- c(mu_vec , reflexity_res[[i]]$par[1])
  alpha_vec <- c(alpha_vec , reflexity_res[[i]]$par[2])
  beta_vec <- c(beta_vec , reflexity_res[[i]]$par[3])
}

time_vec <- seq(market_order$time[1]-0.01 , market_order$time[nrow(market_order)]+0.01 , length.out=14)
time_vec <- as.POSIXct(time_vec,origin="1970-01-01",tz="America/Chicago")
par(mfrow=c(2,1))
plot(time_vec[1:(length(time_vec)-1)],mu_vec , col="blue" , type="b" , xlab="time" , ylab="mu" , main="background intensity in different periods")
plot(time_vec[1:(length(time_vec)-1)] , col="red" , type="b",alpha_vec/beta_vec , xlab="time" , ylab="alpha/beta",main = "reflexity in different periods" )

此處輸入圖片的描述

我們把背景強度和 reflexity 分別畫出來,可以看到背景強度形成了一個碗狀,說明開盤和收盤時的事件的背景強度較大。而 reflexity 則在各個 時間段基本一致,基本圍繞 0.4 波動。

2.3 考慮訂單數量

前面我們把訂單視作同質進行分析 ,但是很明顯量大的訂單對市場的衝擊更大,我們應該 把訂單的數量考慮進去。

首先我們看一下整個時間段的訂單強度:

plot(time , vol , type="l" , ylab="volume" , xlab="time" , main="market order intensity")

此處輸入圖片的描述

然後我們可以開始嘗試建模,將量的因素考慮進去:

此處輸入圖片的描述

其中 nj 代表第 j 個事件的數量。

log_likelihood_volume <- function(params , event , vol) {
  mu = params[1]
  alpha = params[2]
  beta = params[3]

  n = length(event)
  t_n = event[n]

  kernel_sum <- numeric(n)

  for (i in 2:n) {
    kernel_sum[i] = (kernel_sum[i-1]+alpha*vol[i-1]) * exp(-beta*(event[i] - event[i-1]))
  }

  lambda <- kernel_sum + mu
  L = sum( log(lambda) ) - mu * t_n - alpha/beta*sum(vol) + alpha/beta*sum(vol*exp(-beta*(t_n-event)))
  #print(L)
  -L
}
nlminb(c(1,1,1) , log_likelihood_volume ,event= time , vol= vol  )
## Warning in log(lambda): NaNs produced

## Warning in nlminb(c(1, 1, 1), log_likelihood_volume, event = time, vol =
## vol): NA/NaN function evaluation

## Warning in log(lambda): NaNs produced

## Warning in nlminb(c(1, 1, 1), log_likelihood_volume, event = time, vol =
## vol): NA/NaN function evaluation

## Warning in log(lambda): NaNs produced

## Warning in nlminb(c(1, 1, 1), log_likelihood_volume, event = time, vol =
## vol): NA/NaN function evaluation

## $par
## [1]   1.557608   7.106736 293.679848
## 
## $objective
## [1] -82261.69
## 
## $convergence
## [1] 0
## 
## $iterations
## [1] 44
## 
## $evaluations
## function gradient 
##       56      150 
## 
## $message
## [1] "relative convergence (4)"


2.4 訂單數量的冪指數

前面我們假設訂單量的影響是線性的,可真實是這樣的嗎,我們嘗試在訂單數量上加入一個冪指數。

那麼強度的表示式變為

此處輸入圖片的描述

log_likelihood_volume_exponent <- function(params , event , vol) {
  mu = params[1]
  alpha = params[2]
  beta = params[3]
  k = params[4]

  n = length(event)
  t_n = event[n]

  kernel_sum <- numeric(n)

  vol <- vol^k

  for (i in 2:n) {
    kernel_sum[i] = (kernel_sum[i-1]+alpha*vol[i-1]) * exp(-beta*(event[i] - event[i-1]))
  }

  lambda <- kernel_sum + mu

  L = sum( log(lambda) ) - mu * t_n - alpha/beta*sum(vol) + alpha/beta*sum(vol*exp(-beta*(t_n-event)))


  -L
}
nlminb(c(1,1,1,1) , log_likelihood_volume_exponent ,event= time , vol= vol)
## $par
## [1]   1.5214343  42.1613593 321.6189710   0.5287265
## 
## $objective
## [1] -86579.32
## 
## $convergence
## [1] 0
## 
## $iterations
## [1] 51
## 
## $evaluations
## function gradient 
##       67      231 
## 
## $message
## [1] "relative convergence (4)"


從引數我們可以看到k的值大約是 0.5 , 說明訂單的影響大約是數量的根號,並不是線性增長的。 這是非常有趣的一個現象 , 說明訂單量的衝擊是邊際遞減的。

三、 總結

在前面我們對市價單的動力學進行建模 , 我們看到了一些有趣的現象, 例如日內交易背景強度的變化;訂單數量影響的冪指數小於1。 這些都可以做進一步地挖掘,可以讓我們更加深入地理解市場的動力學。