Skip to content

Commit

Permalink
update coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
rcalxrc08 committed Jan 2, 2024
1 parent e76785f commit 996a029
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 61 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
*.jl.mem
docs/build/
Manifest.toml
page/__site
page/__site
.vscode/
4 changes: 2 additions & 2 deletions src/financial_implied_volatility.jl
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ julia> blsimpv(10.0,10.0,0.01,2.0,2.0)
0.3433730534290586
```
"""
function blsimpv(S0, K, r, T, Price, d = 0, FlagIsCall::Bool = true, xtol::Real = 100 * eps(Float64), n_iter_max::Integer = 80)
function blsimpv(S0, K, r, T, Price, d = 0, FlagIsCall::Bool = true, xtol::Real = 100 * eps(Float64), n_iter_max::Integer = 4)
cv = exp(r * T)
cv2 = exp(-d * T)
adj_S0 = S0 * cv * cv2
Expand Down Expand Up @@ -90,7 +90,7 @@ julia> blkimpv(10.0,10.0,0.01,2.0,2.0)
0.36568658096623635
```
"""
function blkimpv(F0, K, r, T, Price, FlagIsCall::Bool = true, xtol::Real = 1e-14, n_iter_max::Integer = 80)
function blkimpv(F0, K, r, T, Price, FlagIsCall::Bool = true, xtol::Real = 1e-14, n_iter_max::Integer = 4)
adj_price = Price * exp(r * T)
σ = blimpv(F0, K, T, adj_price, FlagIsCall, xtol, n_iter_max)
return σ
Expand Down
74 changes: 16 additions & 58 deletions src/financial_lets_be_rational.jl
Original file line number Diff line number Diff line change
Expand Up @@ -138,12 +138,7 @@ end

# Set this to 0 if you want positive results for (positive) denormalised inputs, else to dbl_min.
# Note that you cannot achieve full machine accuracy from denormalised inputs!
const DENORMALISATION_CUTOFF = 0;

is_below_horizon(x) = abs(x) < DENORMALISATION_CUTOFF;
const implied_volatility_maximum_iterations = 2

implied_volatility_output(count, volatility) = volatility;
householder_factor(newton, halley, hh3) = @muladd (1 + halley * newton / 2) / (1 + newton * (halley + hh3 * newton / 6));

function normalised_intrinsic(x, q)
Expand Down Expand Up @@ -389,7 +384,7 @@ function normalised_black_call(x::T, s::V) where {T <: Real, V <: Real}
if (x > 0)
return normalised_intrinsic_call(x) + normalised_black_call(-x, s) # In the money.
end
if (s <= abs(x) * DENORMALISATION_CUTOFF)
if (s <= 0)
return normalised_intrinsic_call(x) # sigma=0 -> intrinsic value.
end
zero_typed = zero(promote_type(T, V))
Expand Down Expand Up @@ -459,20 +454,10 @@ function compute_f_lower_map_and_first_two_derivatives(x::T, s::V) where {T <: R
exp_y_adj = exp(y + s2 / 8)

@muladd fpp = pi * y / (6 * s2 * s) * Phi * (8 * s * sqrt3 * ax + (3 * s2 * (s2 - 8) - 8 * square(x)) * Phi / phi) * square(exp_y_adj)
if (is_below_horizon(s))
fp = typed_zero + 1
f = typed_zero
return f, fp, fpp
else
Phi2 = square(Phi)
fp = 2 * y * pi * Phi2 * exp_y_adj
if (is_below_horizon(x))
f = typed_zero
else
f = twoπ * ax * Phi2 / 3 * Phi / sqrt3
end
return f, fp, fpp
end
Phi2 = square(Phi)
fp = 2 * y * pi * Phi2 * exp_y_adj
f = twoπ * ax * Phi2 / 3 * Phi / sqrt3
return f, fp, fpp
end

using SpecialFunctions
Expand All @@ -485,28 +470,16 @@ end
# end

function inverse_f_lower_map(x::T, f::V) where {T <: Real, V <: Real}
typed_zero = zero(promote_type(T, V))
if is_below_horizon(f)
return typed_zero
end
y = abs(x) / 3 * twoπ
return abs(x / (sqrt3 * inverse_normcdf(cbrt(sqrt3 * f / y))))
end

function compute_f_upper_map_and_first_two_derivatives(x::T, s::S) where {T <: Real, S <: Real}
f = normcdf(-s / 2)
typed_zero = zero(promote_type(S, T))
typed_one = one(typed_zero)
if (is_below_horizon(x))
fp = -typed_one / 2
fpp = typed_zero
return f, fp, fpp
else
w = square(x / s)
fp = -exp(w / 2) / 2
fpp = sqrt2π * exp(w + square(s) / 8) / 2 * w / s
return f, fp, fpp
end
w = square(x / s)
fp = -exp(w / 2) / 2
fpp = sqrt2π * exp(w + square(s) / 8) / 2 * w / s
return f, fp, fpp
end

function inverse_f_upper_map(f)
Expand All @@ -527,10 +500,7 @@ function unchecked_normalised_implied_volatility_from_a_transformed_rational_gue
q = -q
end
if (beta <= 0) # For negative or zero prices we return 0.0.
return implied_volatility_output(0, typed_zero)
end
if (beta < DENORMALISATION_CUTOFF) # For positive but denormalised (a.k.a. 'subnormal') prices, we return 0.0 since it would be impossible to converge to full machine accuracy anyway.
return implied_volatility_output(0, typed_zero)
return typed_zero
end
b_max = exp(x / 2)
if (beta >= b_max)
Expand Down Expand Up @@ -621,7 +591,7 @@ function unchecked_normalised_implied_volatility_from_a_transformed_rational_gue
ds = max(-s / 2, ds)
s += ds
end
return implied_volatility_output(iterations, s)
return s
else
v_l_inv = normalised_vega_inverse(x, s_l)
r_lm = convex_rational_cubic_control_parameter_to_fit_second_derivative_at_right_side(b_l, b_c, s_l, s_c, v_l_inv, v_c_inv, typed_zero, false)
Expand Down Expand Up @@ -707,7 +677,7 @@ function unchecked_normalised_implied_volatility_from_a_transformed_rational_gue
ds = max(-s / 2, ds)
s += ds
end
return implied_volatility_output(iterations, s)
return s
end
end
end
Expand Down Expand Up @@ -748,7 +718,7 @@ function unchecked_normalised_implied_volatility_from_a_transformed_rational_gue
ds = max(-s / 2, newton * householder_factor(newton, halley, hh3))
s += ds
end
return implied_volatility_output(iterations, s)
return s
end

function implied_volatility_from_a_transformed_rational_guess_with_limited_iterations(price::num1, F::num2, K::num3, T::num4, q, N) where {num1 <: Number, num2 <: Number, num3 <: Number, num4 <: Number}
Expand All @@ -762,19 +732,7 @@ function implied_volatility_from_a_transformed_rational_guess_with_limited_itera
return unchecked_normalised_implied_volatility_from_a_transformed_rational_guess_with_limited_iterations(price / sqrt(F * K), x, q, N) / sqrt(T)
end

function implied_volatility_from_a_transformed_rational_guess(price, F, K, T, iscall::Bool)
q = ifelse(iscall, 1, -1)
return implied_volatility_from_a_transformed_rational_guess_with_limited_iterations(price, F, K, T, q, implied_volatility_maximum_iterations)
function new_blimpv(F::num1, K::num2, T::num4, price::num5, FlagIsCall::Bool, ::Real, niter::Integer) where {num1, num2, num4, num5}
q = ifelse(FlagIsCall, 1, -1)
return implied_volatility_from_a_transformed_rational_guess_with_limited_iterations(price, F, K, T, q, niter)
end

function new_blimpv(F::num1, K::num2, T::num4, price::num5, FlagIsCall::Bool, ::Real, ::Integer) where {num1, num2, num4, num5}
return implied_volatility_from_a_transformed_rational_guess(price, F, K, T, FlagIsCall)
end

# function new_blsprice(S0, K, r, T, sigma, d, FlagIsCall::Bool = true)
# cv = exp(r * T)
# cv2 = exp(-d * T)
# F = S0 * cv * cv2
# q = ifelse(FlagIsCall, 1, -1)
# return black(F, K, sigma, T, q) / cv
# end

0 comments on commit 996a029

Please sign in to comment.