Fixing few parameters in DEoptim as Integer - r

In DEoptim how to fix parameters as integers in lower and upper bounds
opt <- DEoptim(function,lower = c(0.03,17,5,0.002), upper = c(0.12,30,15,-0.5))
In the below example the 2nd, 3rd parameters should be integers but the optimizer takes it as float with upto 6 decimals.
How to fix them as integers?

Here we need to create a Mapping function to map each parameter type. In the above example we have to create the following function,
Mapfun <- function(x){
x[1] <- round(x[1],2) #you can decide to what decimal the optimization to be done by explicit defining the digits here, i need 2 digits
x[2:3] <- round(x[2:3]) #implies that they are integer
x[4] <- round(x[4],3) #here i need 3 digits
}
Now for using in DeOptim:
opt <- Deoptim(function,lower = c(0.03,17,5,0.002), upper = c(0.12,30,15,-0.5),fnMap = Mapfun)

Related

Finding optimal parameter for each input combination in the objective function in an optimization

I am calibrating a model and for that I have to estimate a parameter for each input combination I give to the objective function. I have a bit more than 10k input combinations and I want to minimize the parameter for each combination. All other variables in the model are known. I achieved to estimate 1 minimal value for the whole set but that doesn't help me, and when I tried my approach for each combination I get the error: Error in mP[, logik] <- mPv[, logik, drop = FALSE] : NAs are not allowed in subscripted assignments.
My objective function looks like this
x_vol <- vector(mode = "double", length = 10776)
objective_function_vol <- function(x_vol){
S <- calibration_set$index_level
K <- calibration_set$strike
tau <- calibration_set$tau
r <- calibration_set$riskfree_rate
q <- calibration_set$q
model_prices_vol <- vector(mode = "double", length = 10776)
for (i in 1:10776){
model_prices_vol[i] <- hestonCallcf(S = S[i], K = K[i], t = tau[i],
r = r[i], q = 0,
v0 = x_vol[i],
vbar = 0.1064688, rho = -0.9914710,
a = 1.6240300, vvol = 0.98839192)
print(i)
}
diff_sq <- (market_price - model_prices_vol)^2
wdiff <- diff_sq/market_price
error <- sum(wdiff)/10776
return(error)
}
I am using NMOF::DEopt for the optimization. Is it maybe possible to write a second loop which stores the optimal values of x_vol because I think using the subscript i for the known inputted values as well as the unknown is somehow wrong.
The error means that some objective-function calls resulted in NA.
If you only wish to minimize a single parameter (i.e. a scalar), Differential Evolution is probably not the method you want. A grid search along one dimension, possibly with refinements, would likely work better.

How to calculate Kullback-leiber divergence of Kernel estimation in R

I used Kernel estimation to get a non parametric probability density function. Then, I want to compare the tails 'distance' between two Kernel distribution of continuous variables, using Kullback-leiber divergence. I have tried the following code:
kl_l <- function(x,y) {
integrand <- function(x,y) {
f.x <- fitted(density(x, bw="nrd0"))
f.y <- fitted(density(y, bw="nrd0"))
return((log(f.x)-log(f.y))*f.x)
}
return(integrate(integrand, lower=-Inf,upper=quantile(density(x, bw="nrd0"),0.25))$value)
#the Kullback-leiber equation
}
When I run kl_l(a,b) for a, b = 19 continuous variables, it returns a warning
Error in density(y, bw = "nrd0") : argument "y" is missing, with no default
Is there any way to calculate this?
(If anyone wants to see the actual equation: https://www.bankofengland.co.uk/-/media/boe/files/working-paper/2019/attention-to-the-tails-global-financial-conditions-and-exchange-rate-risks.pdf page 13.)
In short, I think you just need to move the f.x and f.y outside the integrand (and possibly replace fitted with approxfun):
kl_l <- function(x, y) {
f.x <- approxfun(density(x, bw = "nrd0"))
f.y <- approxfun(density(y, bw = "nrd0"))
integrand <- function(z) {
return((log(f.x(z)) - log(f.y(z))) * f.x(z))
}
return(integrate(integrand, lower = -Inf, upper = quantile(density(x, bw="nrd0"), 0.25))$value)
#the Kullback-leiber equation
}
Expanding a little:
Looking at the paper you referenced, it appears as though you need to first create the two fitted distributions f and g. So if your variable a contains observations under the 1-standard-deviation increase in global financial conditions, and b contains the observations under average global financial conditions, you can create two functions as in your example:
f <- approxfun(density(a))
g <- approxfun(density(b))
Then define the integrand:
integrand <- function(x) log(f(x) / g(x)) * f(x)
The upper bound:
upper <- quantile(density(b, bw = "nrd0"), 0.25)
And finally do the integration on x within the specified bounds. Note that each value of x in the numerical computation has to go into both f and g; in your function kl_l, the x and y were separately going into the integrand, which I think is incorrect; and in any case, integrate will only have operated on the first variable.
integrate(integrand, lower = -Inf, upper = upper)$value
One thing to check for is that approxfun returns NA for values outside the range specified in the density, which can mess up your operation, so you'll need to adjust for those (if you expect the density to go to zero, for example).

non-numeric argument to binary operator in integration in R

f1 = function(t){exp(-t^2)}
phi1 = function(theta){
0.5-1/sqrt(pi)*integrate(f1, lower = 0, upper = (10-theta)/(2*sqrt(2)))}
mu1 = (450*barx)/(454)
sigs1 = 36/454
pi_thetapost = function(theta){
(1/sqrt(2*pi*sigs1))*exp(-((theta-mu1)^2)/(2*sigs1))}
E_phipost = integrate(phi1*pi_thetapost, lower = -Inf, upper =Inf)
I was trying to do a integration, and I got the error says:
non-numeric argument to binary operator
I think that * is a binary operator, but I am not sure how to figure this out.
Thanks~
A few problems here. First barx isn't defined. But the main problem is that you can't just multiple functions in R. You can multiple the values returns by function, but not the functions themselves. You need to pass in a proper function to integrate.
But then after that problem, you need to make sure all the functions you pass in to integrate() are vectorized and your phi function is not. you need to be able to pass in a vector and get a vector out. The easiest way to fix this is with Vectorize(). And finally, integrate() returns an object, not just a number. So if you want to return the calculated value, you need to extract it from the object before you can multiply it by another object. Try
f1 <- function(t){
exp(-t^2)
}
phi1 <- function(theta) {
0.5-1/sqrt(pi)*integrate(f1, lower = 0, upper = (10-theta)/(2*sqrt(2)))$value
}
barx <- 2 # or whatever
mu1 <- (450*barx)/(454)
sigs1 <- 36/454
pi_thetapost <- function(theta){
(1/sqrt(2*pi*sigs1))*exp(-((theta-mu1)^2)/(2*sigs1))
}
myfun <- function(x) {
Vectorize(phi1)(x)*pi_thetapost(x)
}
E_phipost <- integrate(myfun, lower = -Inf, upper =Inf)
E_phipost
# 3.690467e-05 with absolute error < 5.6e-05
E_phipost$value
# [1] 3.690467e-05

Inverse of matrix and numerical integration in R

in R I try to
1) get a general form of an inverse of a matrix (I mean a matrix with parameters instead of specific numbers),
2) then use this to compute an integral.
I mean, I've got a P matrix with a parameter theta, I need to add and subtract something, then take an inverse of this and multiply it by a vector so that I am given a vector pil. From the vector pil I take term by term and multiply it by a function with again the parameter theta and the result must be integrated from 0 to infinity.
I tried this, but it didn't work because I know the result should be pst=
(0.3021034 0.0645126 0.6333840)
c<-0.1
g<-0.15
integrand1 <- function(theta) {
pil1 <- function(theta) {
P<-matrix(c(
1-exp(-theta), 1-exp(-theta),1-exp(-theta),exp(-theta),0,0,0,exp(-theta),exp(-theta)
),3,3);
pil<-(rep(1,3))%*%solve(diag(1,3)-P+matrix(1,3,3));
return(pil[[1]])
}
q<-pil1(theta)*(c^g/gamma(g)*theta^(g-1)*exp(-c*theta))
return(q)}
(pst1<-integrate(integrand1, lower = 0, upper = Inf)$value)
#0.4144018
This was just for the first term of the vector pst, because when I didn't know how to a for cycle for this.
Please, do you have any idea why it won't work and how to make it work?
Functions used in integrate should be vectorized as stated in the help.
At the end of your code add this
integrand2 <- Vectorize(integrand1)
integrate(integrand2, lower = 0, upper = Inf)$value
#[1] 0.3021034
The result is the first element of your expected result.
You will have to present more information about the input to get your expected vector.

Integrate a function in R through time

I would like to integrate the following function with respect to t, for lower bound = 0 and upper bound = t. I can do that with the following code, but my ultimate goal is to have a value of the integral for each t. Even if I make t a sequence instead of a value, or if I try and use sapply, I still cannot get a value for the integral at each step of t.
#initialize constants
kap=-0.1527778
alph0<-6
b<-0
po<-0.01
t<-100
gp_st<-integrate(function(t) (1-alph0/(alph0+b*t)*(1-po^kap))^(1/kap),lower=0,upper=t)$value
#try alternate where t is now a sequence
t<-seq(1:100)
gp_st2<-function(h) sapply(h,gp_st) #still gives length of 1
Thanks!
Try making gp_st a function of your upper bound, like so:
gp_st <- function(h) {
integrate(function(t) (1-alph0/(alph0+b*t)*(1-po^kap))^(1/kap),lower=0,upper=h)$value
}
Then you can use sapply much as you intended:
t<-seq(1:100)
gp_st2 <- sapply(t, gp_st)
and now gp_st2 is a numeric vector of length 100.
The problem is that you are evaluating the integral in gp_st, and you don't want to do that. You want the following:
ff = function(t) {
(1-alph0/(alph0+b*t)*(1-po^kap))^(1/kap)
}
sapply(1:100, function(ul) {
integrate(ff, lower = 0, upper = ul)$value
})
There are naturally more efficient ways to do this.

Resources