您的位置:首页 > 其它

R语言对高频交易订单流进行建模分析 4

2017-08-25 20:05 615 查看

一、实验介绍--订单流模型拟合

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

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

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

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。 这些都可以做进一步地挖掘,可以让我们更加深入地理解市场的动力学。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: