#Computes the value of the test statistic  for the innovation distribution in a stochastic duration model; see Section 4 of Meintanis, Milosevic and Obradovic.    
#Compute the characteristic function  
char.fun=function(r1,r2,a=0.003,b=0.9,alpha=2,beta=0,v=1,sigma=0.1)
{
  return(exp(a*1i*(r1+r2)/(1-b)-sigma^alpha/2/(1-abs(b)^alpha)*(abs(r1+b*r2)^alpha+(1-abs(b)^alpha)*abs(r2)^alpha)+1i*sigma^alpha*beta*tan(pi*alpha/2)/(1-abs(b)^alpha*sign(b))*(abs(r1+b*r2)^alpha*sign(r1+b*r2)+abs(r2)^alpha*sign(r2)*(1-abs(b)^alpha*sign(b))))*gammaz(v+r1*1i)*gammaz(v+r2*1i)/gammaz(v)^2)
}


#Compute the empirical characteristic function
#Empirical characteristic function - real part
empreal<-function(r1,r2,data)
{
  mat=expand.grid(r1,r2)
  n=length(data)
  q=sapply(1:nrow(mat),function(x)
    sum(cos(mat[x,1]*data[1:(n-1)]+mat[x,2]*data[2:n])))
  
  return(1/(n-1)*q)
}

#Empirical characteristic function - imaginary part
empim<-function(r1,r2,data)
{
  mat=expand.grid(r1,r2)
  n=length(data)
  q=sapply(1:nrow(mat),function(x)
    sum(sin(mat[x,1]*data[1:(n-1)]+mat[x,2]*data[2:n])))
  
  return(1/(n-1)*q)
}
#Compute the objective function; see the integral in Section 4. 
#Integrand Re^2-Im^2

integrand<-function(rr1,rr2,a1,b1,alpha,beta,v1,sigma,data)
{
  
  r1=-log(rr1/(1-rr1))
  r2=-log(rr2/(1-rr2))
  n=length(data)
  
  re.diff=(Re(char.fun(r1,r2,a=a1,b=b1,alpha,beta,v1,sigma))-empreal(r1[1,],r2[,1],data))^2
  im.diff=(Im(char.fun(r1,r2,a=a1,b=b1,alpha,beta,v1,sigma))-empim(r1[1,],r2[,1],data))^2
  #print((re.diff+im.diff)*exp(-r1^2-r2^2)*(1+exp(r1))^2/exp(r1)*(1+exp(r2))^2/exp(r2))
  return((re.diff+im.diff)*exp(-r1^2-r2^2)*(1+exp(r1))^2/exp(r1)*(1+exp(r2))^2/exp(r2))
}

#Function (integral) to be minimized

funOpt<-function(parameters,y1,alpha,beta,sigma)
{
  return(pracma::integral2(integrand,xmin=0,xmax=1,ymin=0,ymax=1,a1=parameters[1],b1=1/(1+exp(-parameters[2])),alpha=alpha,beta=beta,v1=1,sigma=sigma,data=y1)$Q)
}







#Calculation of test statistic
scd.test<-function(durations,start_a,start_b,alpha=2,beta=0,sigma=1,nu=1,Nburn=50)
{
  modelOut<-try(optim(par=c(start_a,log(start_b/(1-start_b))), funOpt, gr =
                        NULL, siim,alpha,beta,sigma),silent=FALSE)
  if ('try-error' %in% class(modelOut)) next
  
  #Extracting value of statistic and parameter estimates
  stat=modelOut$value
  param=c(modelOut$par[1],1/(1+exp(-modelOut$par[2])))
  
  #Output
  return(list(stat=stat,param=param))
}
