fzero not working with nested functions and mvncdf
2 vues (au cours des 30 derniers jours)
Afficher commentaires plus anciens
Hello everyone,
I have defined three functions which are (progressively) nested
function E = EBlackCox(V0, sigma, VB, r, d, L, TL)
a = (r - d - sigma.^2./2)./(sigma.^2);
D = @(x, lambda) (log(V0./x) + lambda.*sigma.^2.*TL)./(sigma.*sqrt(TL));
E = V0.*exp(-d.*TL).*(normcdf(D(L, a + 1)) - (VB./V0).^(2.*(a + 1)) .* ...
normcdf(-D(VB.^2./L, -a - 1))) - L.*exp(-r.*TL).*(normcdf(D(L, a)) ...
- (VB./V0).^(2.*a) .* normcdf(-D(VB.^2./L, -a)));
end
function c0 = CBlackCox(V0, sigma, VB, r, d, L, TL, K, T)
a = (r - d - sigma.^2./2)./(sigma.^2);
f = @(x) EBlackCox(x, sigma, VB, r, d, L, TL - T) - K;
Kstar = fzero(f, [K 10.*(K + L./r)]);
D = @(x, lambda, t) (log(V0./x) + lambda.*sigma.^2.*t)./(sigma.*sqrt(t));
rho = sqrt(T./TL);
mu = [0 0];
Rho_p = [1 rho; rho 1];
Rho_m = [1 -rho; -rho 1];
c0 = V0 .* exp(-d.*TL) .*(mvncdf([D(Kstar, a + 1, T) D(L, a + 1, TL)], mu, Rho_p) ...
+ mvncdf([-D(VB.^2./Kstar, a + 1, T) D(L, a + 1, TL)], mu, Rho_m) ...
- (VB./V0).^(2.*(a + 1)) .* (mvncdf([D(Kstar, - a - 1, T) -D(VB.^2./L, - a - 1, TL)], mu, Rho_m) ...
+ mvncdf([-D(VB.^2./Kstar, - a - 1, T) -D(VB.^2./L, - a - 1, TL)], mu, Rho_p)))...
- L .* exp(-r.*TL) .*(mvncdf([D(Kstar, a, T) D(L, a, TL)], mu, Rho_p) ...
+ mvncdf([-D(VB.^2./Kstar, a, T) D(L, a, TL)], mu, Rho_m) ...
- (VB./V0).^(2.*a) .* (mvncdf([D(Kstar, - a, T) -D(VB.^2./L, - a, TL)], mu, Rho_m) ...
+ mvncdf([-D(VB.^2./Kstar, - a, T) -D(VB.^2./L, - a, TL)], mu, Rho_p)))...
- K .* exp(-r.*T) .* (normcdf(D(Kstar, a, T)) - (VB./V0).^(2.*a) .* normcdf(-D(VB.^2./Kstar, -a, T)));
end
function s = sigmaCBlackCox(V0, VB, r, d, L, TL, K, T, price)
option = @(sigma) CBlackCox(V0, sigma, VB, r, d, L, TL, K, T);
difference = @(sigma) (option(sigma) - price);
s = fzero(difference, [.01 .8]);
end
The first two functions work fine when inputting values of the parameter. If you want to try here is a testable set
r = 0.03;
d = 0.06;
sigma = 0.2;
V0 = 100;
L = 40;
VB = 0.6*L;
TL = 10;
T = 1;
a = (r - d - sigma.^2./2)./(sigma.^2);
K = 30;
If applied to the second function
c0 = CBlackCox(V0, sigma, VB, r, d, L, TL, K, T)
it returns c0 = 4.3352.
The problem is when I use the third function which tries to find sigma given c0. An error occurs
FZERO cannot continue because user-supplied function_handle ==> @(s)(option(s)-c0)
failed with the error below.
Function values at the interval endpoints must differ in sign.
Error in fzero (line 245)
fa = localFirstFcnEval(FunFcn,FunFcnIn,a,varargin{:});
However, the function works fine as long as I do something like
option = @(sigma) CBlackCox(V0, sigma, VB, r, d, L, TL, K, T);
difference = @(sigma) (option(sigma) - c0);
difference(0.1)
difference(0.2)
difference(0.3)
...
which are difference(0.1) = -2.7101, difference(0.2) = 0, difference(0.3) = 3.3517 respectively
The purpose of the third function is indeed to return 0.2
Also, I cannot fplot the function difference as I get the following warning
Warning: Error updating FunctionLine.
The following error was reported evaluating the function in FunctionLine update:
Operands to the logical AND (&&) and OR (||) operators must be convertible to logical
scalar values. Use the ANY or ALL functions to reduce operands to logical scalar
values.
and the figure appears blank.
I suspect this errors occurs because of the nesting toghether with using the function mvncdf (multivariate density of a normal vector) because I have a similar code (again three series of nested functions) which does not require the use of mvncdf and the fzero works propertly.
Can someone suggest a way to modify my code so that fzero works?
Thank you
0 commentaires
Réponse acceptée
Torsten
le 6 Déc 2022
Modifié(e) : Torsten
le 6 Déc 2022
r = 0.03;
d = 0.06;
sigma = 0.2;
V0 = 100;
L = 40;
VB = 0.6*L;
TL = 10;
T = 1;
a = (r - d - sigma.^2./2)./(sigma.^2);
K = 30;
price = 4.3352;
[s,fval] = sigmaCBlackCox(V0, VB, r, d, L, TL, K, T, price)
function [s,fval] = sigmaCBlackCox(V0, VB, r, d, L, TL, K, T, price)
option = @(sigma) CBlackCox(V0, sigma, VB, r, d, L, TL, K, T);
difference = @(sigma) arrayfun(@(x)(option(x) - price),sigma);
[s,fval] = fzero(difference, [.1 .8]);
end
function c0 = CBlackCox(V0, sigma, VB, r, d, L, TL, K, T)
a = (r - d - sigma.^2./2)./(sigma.^2);
f = @(x) EBlackCox(x, sigma, VB, r, d, L, TL - T) - K;
Kstar = fzero(f, [K 10.*(K + L./r)]);
D = @(x, lambda, t) (log(V0./x) + lambda.*sigma.^2.*t)./(sigma.*sqrt(t));
rho = sqrt(T./TL);
mu = [0 0] ;
Rho_p = [1 rho; rho 1];
Rho_m = [1 -rho; -rho 1];
c0 = V0 .* exp(-d.*TL) .*(mvncdf([D(Kstar, a + 1, T) D(L, a + 1, TL)], mu, Rho_p) ...
+ mvncdf([-D(VB.^2./Kstar, a + 1, T) D(L, a + 1, TL)], mu, Rho_m) ...
- (VB./V0).^(2.*(a + 1)) .* (mvncdf([D(Kstar, - a - 1, T) -D(VB.^2./L, - a - 1, TL)], mu, Rho_m) ...
+ mvncdf([-D(VB.^2./Kstar, - a - 1, T) -D(VB.^2./L, - a - 1, TL)], mu, Rho_p)))...
- L .* exp(-r.*TL) .*(mvncdf([D(Kstar, a, T) D(L, a, TL)], mu, Rho_p) ...
+ mvncdf([-D(VB.^2./Kstar, a, T) D(L, a, TL)], mu, Rho_m) ...
- (VB./V0).^(2.*a) .* (mvncdf([D(Kstar, - a, T) -D(VB.^2./L, - a, TL)], mu, Rho_m) ...
+ mvncdf([-D(VB.^2./Kstar, - a, T) -D(VB.^2./L, - a, TL)], mu, Rho_p)))...
- K .* exp(-r.*T) .* (normcdf(D(Kstar, a, T)) - (VB./V0).^(2.*a) .* normcdf(-D(VB.^2./Kstar, -a, T)));
end
function E = EBlackCox(V0, sigma, VB, r, d, L, TL)
a = (r - d - sigma.^2./2)./(sigma.^2);
D = @(x, lambda) (log(V0./x) + lambda.*sigma.^2.*TL)./(sigma.*sqrt(TL));
E = V0.*exp(-d.*TL).*(normcdf(D(L, a + 1)) - (VB./V0).^(2.*(a + 1)) .* ...
normcdf(-D(VB.^2./L, -a - 1))) - L.*exp(-r.*TL).*(normcdf(D(L, a)) ...
- (VB./V0).^(2.*a) .* normcdf(-D(VB.^2./L, -a)));
end
3 commentaires
Torsten
le 6 Déc 2022
Modifié(e) : Torsten
le 6 Déc 2022
Your function CBlackCox doesn't accept array inputs (inputs with more than one element at a time) for sigma. With arrayfun, it is called with only one value for sigma at a time.
Further, sigma = 0.01 does not work in CBlackCox ; I had to choose sigma = 0.1 as lower bound in the call to "fzero".
Plus de réponses (1)
Jan
le 6 Déc 2022
I tried to reproduce your problem, but get a different error message:
r = 0.03;
d = 0.06;
sigma = 0.2;
V0 = 100;
L = 40;
VB = 0.6*L;
TL = 10;
T = 1;
a = (r - d - sigma.^2./2) ./ (sigma.^2);
K = 30;
option = @(sigma) CBlackCox(V0, sigma, VB, r, d, L, TL, K, T);
difference = @(sigma) (option(sigma) - price);
s = fzero(difference, [0.01, 0.8]);
function c0 = CBlackCox(V0, sigma, VB, r, d, L, TL, K, T)
a = (r - d - sigma.^2./2) ./ (sigma.^2);
f = @(x) EBlackCox(x, sigma, VB, r, d, L, TL - T) - K;
Kstar = fzero(f, [K, 10.*(K + L./r)]);
D = @(x, lambda, t) (log(V0./x) + lambda.*sigma.^2.*t) ./ (sigma.*sqrt(t));
rho = sqrt(T./TL);
mu = [0 0];
Rho_p = [1 rho; rho 1];
Rho_m = [1 -rho; -rho 1];
c0 = V0 .* exp(-d.*TL) .*(mvncdf([D(Kstar, a + 1, T), D(L, a + 1, TL)], mu, Rho_p) ...
+ mvncdf([-D(VB.^2./Kstar, a + 1, T), D(L, a + 1, TL)], mu, Rho_m) ...
- (VB./V0).^(2.*(a + 1)) .* (mvncdf([D(Kstar, - a - 1, T), -D(VB.^2./L, - a - 1, TL)], mu, Rho_m) ...
+ mvncdf([-D(VB.^2./Kstar, - a - 1, T) -D(VB.^2./L, - a - 1, TL)], mu, Rho_p)))...
- L .* exp(-r.*TL) .*(mvncdf([D(Kstar, a, T), D(L, a, TL)], mu, Rho_p) ...
+ mvncdf([-D(VB.^2./Kstar, a, T), D(L, a, TL)], mu, Rho_m) ...
- (VB./V0).^(2.*a) .* (mvncdf([D(Kstar, - a, T), -D(VB.^2./L, - a, TL)], mu, Rho_m) ...
+ mvncdf([-D(VB.^2./Kstar, - a, T), -D(VB.^2./L, - a, TL)], mu, Rho_p)))...
- K .* exp(-r.*T) .* (normcdf(D(Kstar, a, T)) - (VB./V0).^(2.*a) .* normcdf(-D(VB.^2./Kstar, -a, T)));
end
function E = EBlackCox(V0, sigma, VB, r, d, L, TL)
a = (r - d - sigma.^2./2)./(sigma.^2);
D = @(x, lambda) (log(V0./x) + lambda.*sigma.^2.*TL)./(sigma.*sqrt(TL));
E = V0.*exp(-d.*TL).*(normcdf(D(L, a + 1)) - (VB./V0).^(2.*(a + 1)) .* ...
normcdf(-D(VB.^2./L, -a - 1))) - L.*exp(-r.*TL).*(normcdf(D(L, a)) ...
- (VB./V0).^(2.*a) .* normcdf(-D(VB.^2./L, -a)));
end
3 commentaires
Jan
le 6 Déc 2022
"Did you replace price in difference with c0 = 4.3352?" - I've used copy&paste with code from your question and did not replace anything.
Voir également
Catégories
En savoir plus sur Biomedical Signal Processing dans Help Center et File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!