使方差伽玛适合数据

时间:2020-06-28 20:27:04

标签: r

我正在使用R studio估算方差Gamma下数据的参数。我想将此数据拟合到数据中并找到参数的估计值。我的代码是

x<-c(1291,849,238,140,118,108,87,70,63,58,50,47,21,21,19)
library(VarianceGamma)
init<-c(0,0.5,0,0.5)
vgFit(x, freq = NULL, breaks = NULL, paramStart = init, startMethod = "Nelder-Mead", startValues = "SL", method = "Nelder-Mead", hessian = FALSE, plots = TRUE)

我得到的错误是:

optim中的错误(paramStart,llsklp,NULL,方法= startMethodSL,粗麻布= FALSE 、: 无法在初始参数处评估功能 我不确定是什么问题?

1 个答案:

答案 0 :(得分:3)

该错误可能表明存在差异。根据您之前的问题,我很怀疑x是股票价值的原始数字。因此,在对每个时间单位的变化进行建模(例如每日收益)之前,可能需要log-transformation

x <- c(1291,849,238,140,118,108,87,70,63,58,50,47,21,21,19)
dx <- log(x)[2:length(dx)] - log(x)[1:(length(dx)-1)]

vgFit(dx)
#Parameter estimates:
#     vgC     sigma     theta        nu  
# 0.16887   0.03128  -0.47164   0.27558

我们可能要与模拟数据进行比较。我实现了两种方法,它们对于大观察数nt似乎是等效的。

方法2如下: method 2

#Simulating VG as a time-fixed Brownian Motion
set.seed(1) 

nt = 15 #number of observations
T = nt - 1 #total time
dt = rep(T/(nt-1), nt-1) #fixed time increments
r = 1 + 0.16887 #interest rate
vgC = (r-1)
sigma = 0.03128 
theta = -0.47164 
nu = 0.27558

V_ = rep(NA,nt) #Simulations for log stock value
V_[1] = 7.163172 #log(x[1])
V2_ = V_ #alternative simulation method
for(i in 2:nt) 
    {#method 1: by VarianceGamma package
    V_[i] <- V_[i-1] + rvg(1,vgC=vgC*dt[i-1], sigma=sigma, theta=theta, nu=nu)
    
    #method 2: by R built-in packages
    gamma_i<-rgamma(1, shape=dt[i-1]/nu, scale = nu)
    normal<-rnorm(1, mean=0, sd=sigma*sqrt(gamma_i))
    V2_[i] <- V2_[i-1] + vgC*dt[i-1] + theta*gamma_i + normal
    }

# Visual comparison
x11(width=4,height=4)
plot(x, xlab='Time',ylab='Stock value',type='l')
lines(exp(V_), col='red')
lines(exp(V2_), col='blue')
legend('topright',legend=c('Observed','Method1','Method2'),fill=c('black','red','blue'))

由于样本量小nt,结果参数表明估算值不稳定:

#The real parameter:
c(vgC*dt[1], sigma, theta, nu).
#     vgC     sigma     theta        nu 
# 0.16887   0.03128  -0.47164   0.27558

#Parameter estimates for 1st data set:
dV = V_[2:nt] - V_[1:(nt-1)]
vgFit(dV)
#    vgC    sigma    theta       nu  
#-0.9851   0.3480   1.2382   2.0000

#Parameter estimates for 2nd data set:
dV2 = V2_[2:nt] - V2_[1:(nt-1)]
vgFit(dV2)
#     vgC     sigma     theta        nu  
#-0.78033   0.07641   0.52414   0.11840

此外,rvg函数采用固定的时间增量。我们可以使用log-likelihood方法来放松@Louis Marascio的answer的假设。

#Simulating VG as a time-changed Brownian Motion
set.seed(1) 

nt = 100 #Increase the number of observations!
T = nt-1
dt = runif(nt-1) #random time increments 
dt = dt/sum(dt)*T
r = 1 + 0.16887
vgC = (r-1)
sigma = 0.03128 
theta = -0.47164 
nu = 0.27558

V_ = rep(NA,nt) #simulations for log stock value
V_[1] = 7.163172
for(i in 2:nt) 
    {V_[i] <- V_[i-1] + rvg(1,vgC=vgC*dt[i-1], sigma=sigma, theta=theta, nu=nu)
    }
dV = V_[2:nt] - V_[1:(nt-1)]

# -log-likelihood function with different time increments
ll = function(par){
if(par[2]>0 & par[4]>0)
    {tem = 0
    for (i in 1:(length(dV)))
        {tem = tem - log(dvg(dV[i], vgC = par[1]*dt[i], sigma=par[2], theta=par[3], nu = par[4]))
        }
    return (tem)
    }
else return(Inf)}

实际上,通过放宽固定时间假设,结果显示出更好的估计:

#The real parameters:
c(vgC, sigma, theta, nu)
#       vgC      sigma      theta         nu
#   0.16887    0.03128   -0.47164    0.27558

#Assuming fixed time increments
vgFit(dV)$param*c(1/mean(dt),1,1,1)
#       vgC      sigma      theta         nu 
#-0.2445969  0.3299023 -0.0696895  1.5623556

#Assuming different time increments
optim(vgFit(dV)$param*c(1/mean(dt),1,1,1),ll,
    method = c("Nelder-Mead", "BFGS", "CG", "L-BFGS-B", "SANN", "Brent")[5])
#        vgC       sigma       theta          nu 
# 0.16503125  0.03241617 -0.50193694  0.28221985

最后,可以通过多次模拟获得估计参数的置信区间:

set.seed(1)
out = NULL
for (j in 1:100) #100 simulations
    {V_ = rep(NA,nt)
    V_[1] = 7.163172
    for(i in 2:nt) 
        {V_[i] <- V_[i-1] + rvg(1,vgC=vgC*dt[i-1], sigma=sigma, theta=theta, nu=nu)
        }
    dV = V_[2:nt] - V_[1:(nt-1)]
    
    #to skip divergence
    tem <- try(vgFit(dV)$param)
    if (inherits(tem, "try-error")) next

    out = rbind(out,tem)
    }

apply(out,2,mean)
#       vgC      sigma      theta         nu 
#-0.8735168  0.1652970  0.4737270  0.9821458
apply(out,2,sd)
#      vgC     sigma     theta        nu 
#2.8935938 0.3092993 2.6833866 1.3161695
相关问题