Skip to content

Commit

Permalink
add Symbolics, coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
rcalxrc08 committed Aug 27, 2024
1 parent 16d0f9d commit 258026a
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 31 deletions.
37 changes: 11 additions & 26 deletions src/financial_symbolics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,47 +6,30 @@ end

@register_symbolic blimpv(S0, K, T, Price, FlagIsCall::Bool, xtol::Float64, n_iter_max::Int64)

function blvega_impl_registered(S0, K, T, σ)
return blvega_impl(S0, K, T, σ)
end

function Symbolics.derivative(::typeof(blvega_impl_registered), ::NTuple{4, Any}, ::Any)
return 0
end
function finalize_derivative_fwd(S0, K, T, σ, der_fwd)
vega = blvega_impl_registered(S0, K, T, σ)
vega = blvega_impl(S0, K, T, σ)
return der_fwd / vega
end
# function finalize_derivative_fwd(vega, price_diff, target_var, original_var)
# der_fwd = Symbolics.derivative(price_diff, target_var)
# der_fwd = substitute(der_fwd, Dict(target_var => original_var))
# return der_fwd / vega
# end
function bldelta(S0, K, T, σ, FlagIsCall)
sigma_sqrtT = σ * sqrt(T)
S0_K = S0 / K
d1 = log(S0_K) / sigma_sqrtT + sigma_sqrtT / FinancialToolbox.two_internal
iscall = ifelse(FlagIsCall, FinancialToolbox.one_internal, FinancialToolbox.minus_one_internal)
Δ = normcdf(iscall * d1) * iscall
return Δ
end

#TODO: implement derivatives
function Symbolics.derivative(::typeof(blimpv), args::NTuple{7, Any}, ::Val{1})
S0, K, T, price_d, FlagIsCall, xtol, n_iter_max = args
σ = blimpv(S0, K, T, price_d, FlagIsCall, xtol, n_iter_max)
@variables new_S0
D_S0 = Differential(new_S0)
price_diff = -blprice_impl(new_S0, K, T, σ, FlagIsCall)
der_fwd = Symbolics.derivative(price_diff, new_S0)
der_fwd = expand_derivatives(D_S0(price_diff))
der_fwd = substitute(der_fwd, Dict(new_S0 => S0))
#der_fwd = bldelta(S0, K, r, T, σ, d, FlagIsCall)
# der_fwd = -bldelta(S0, K, T, σ, FlagIsCall)
return finalize_derivative_fwd(S0, K, T, σ, der_fwd)
end
function Symbolics.derivative(::typeof(blimpv), args::NTuple{7, Any}, ::Val{2})
S0, K, T, price_d, FlagIsCall, xtol, n_iter_max = args
σ = blimpv(S0, K, T, price_d, FlagIsCall, xtol, n_iter_max)
@variables new_K
D_K = Differential(new_K)
price_diff = -blprice_impl(S0, new_K, T, σ, FlagIsCall)
der_fwd = Symbolics.derivative(price_diff, new_K)
der_fwd = expand_derivatives(D_K(price_diff))
der_fwd = substitute(der_fwd, Dict(new_K => K))
#der_fwd = bldelta(S0, K, r, T, σ, d, FlagIsCall)
return finalize_derivative_fwd(S0, K, T, σ, der_fwd)
Expand All @@ -55,18 +38,20 @@ function Symbolics.derivative(::typeof(blimpv), args::NTuple{7, Any}, ::Val{3})
S0, K, T, price_d, FlagIsCall, xtol, n_iter_max = args
σ = blimpv(S0, K, T, price_d, FlagIsCall, xtol, n_iter_max)
@variables new_T
D_T = Differential(new_T)
price_diff = -blprice_impl(S0, K, new_T, σ, FlagIsCall)
der_fwd = Symbolics.derivative(price_diff, new_T)
der_fwd = expand_derivatives(D_T(price_diff))
der_fwd = substitute(der_fwd, Dict(new_T => T))
#der_fwd = bldelta(S0, K, r, T, σ, d, FlagIsCall)
return finalize_derivative_fwd(S0, K, T, σ, der_fwd)
end
function Symbolics.derivative(::typeof(blimpv), args::NTuple{7, Any}, ::Val{4})
S0, K, T, price_d, FlagIsCall, xtol, n_iter_max = args
σ = blimpv(S0, K, T, price_d, FlagIsCall, xtol, n_iter_max)
vega = blvega_impl_registered(S0, K, T, σ)
vega = blvega_impl(S0, K, T, σ)
return inv(vega)
end

function Symbolics.derivative(::typeof(blimpv), ::NTuple{7, Any}, ::Any)
return 0
end
24 changes: 19 additions & 5 deletions test/testSymbolics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,10 @@ using HyperDualNumbers
#S0
der_vol_S0 = Symbolics.derivative(vol_s, S0_s, simplify = true);
der_vol_S02 = Symbolics.derivative(der_vol_S0, S0_s, simplify = true);
vol_h_S0 = blsimpv(hyper(S0, 1.0, 1.0, 0.0), K, r, T, price, d)
@show vol_h_S0 = blsimpv(hyper(S0, 1.0, 1.0, 0.0), K, r, T, price, d)
delta = substitute(der_vol_S0, dict_vals)
gamma = substitute(der_vol_S02, dict_vals)
@show gamma = substitute(der_vol_S02, dict_vals)
@test abs(delta - vol_h_S0.epsilon1) < toll
@test abs(gamma - vol_h_S0.epsilon12) < toll

#K
der_vol_K = Symbolics.derivative(vol_s, K_s, simplify = true);
Expand All @@ -37,20 +36,35 @@ vol_h_K = blsimpv(S0, hyper(K, 1.0, 1.0, 0.0), r, T, price, d)
delta_k = substitute(der_vol_K, dict_vals)
gamma_k = substitute(der_vol_K2, dict_vals)
@test abs(delta_k - vol_h_K.epsilon1) < toll
@test abs(gamma_k - vol_h_K.epsilon12) < toll
#r
der_vol_r = Symbolics.derivative(vol_s, r_s, simplify = true);
der_vol_r2 = Symbolics.derivative(der_vol_r, r_s, simplify = true);
vol_h_r = blsimpv(S0, K, hyper(r, 1.0, 1.0, 0.0), T, price, d)
delta_r = substitute(der_vol_r, dict_vals)
gamma_r = substitute(der_vol_r2, dict_vals)
@test abs(delta_r - vol_h_r.epsilon1) < toll
@test abs(gamma_r - vol_h_r.epsilon12) < toll
#T
der_vol_T = Symbolics.derivative(vol_s, T_s, simplify = true);
der_vol_T2 = Symbolics.derivative(der_vol_T, T_s, simplify = true);
vol_h_T = blsimpv(S0, K, r, hyper(T, 1.0, 1.0, 0.0), price, d)
delta_T = substitute(der_vol_T, dict_vals)
gamma_T = substitute(der_vol_T2, dict_vals)
@test abs(delta_T - vol_h_T.epsilon1) < toll

#Mixed derivative r,T
der_vol_T = Symbolics.derivative(vol_s, T_s, simplify = true);
der_vol_T_r_s = Symbolics.derivative(der_vol_T, r_s, simplify = true);
vol_h_T = blsimpv(S0, K, hyper(r, 0.0, 1.0, 0.0), hyper(T, 1.0, 0.0, 0.0), price, d)
delta_T = substitute(der_vol_T, dict_vals)
gamma_T = substitute(der_vol_T_r_s, dict_vals)
@test abs(delta_T - vol_h_T.epsilon1) < toll

println("Test First Order Passed")

@test abs(gamma - vol_h_S0.epsilon12) < toll
@test abs(gamma_k - vol_h_K.epsilon12) < toll
@test abs(gamma_r - vol_h_r.epsilon12) < toll
@test abs(gamma_T - vol_h_T.epsilon12) < toll
@test abs(gamma_T - vol_h_T.epsilon12) < toll

println("Test Second Order Passed")

0 comments on commit 258026a

Please sign in to comment.