Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hull White Model - calibration not aligning to input prices #91

Closed
mchandlernz opened this issue Feb 28, 2023 · 3 comments
Closed

Hull White Model - calibration not aligning to input prices #91

mchandlernz opened this issue Feb 28, 2023 · 3 comments

Comments

@mchandlernz
Copy link

I'm observing an issue when trying to calibrate the hull white model using calibration_from_swaptions function. Specifically, when I try to recalculate the prices using the calibrated parameters, I do not return to my source prices. I've included a demo of the issue below:

import numpy as np
import tensorflow as tf
import tf_quant_finance as tff

notional = 100.
prices = np.array([28.54, 27.63, 26.82, 25.76, 24.26])
expiries = np.array([10, 10, 10, 10, 15])
zero_rate_fn = lambda x: 0.01 * tf.ones_like(x, dtype=tf.float64)
start_times = np.array([
    [10. , 10.5, 11. , 11. , 11. , 11. , 11. , 11. , 11. , 11. ],
    [10. , 10.5, 11. , 11.5, 12. , 12. , 12. , 12. , 12. , 12. ],
    [10. , 10.5, 11. , 11.5, 12. , 12.5, 13. , 13. , 13. , 13. ],
    [10. , 10.5, 11. , 11.5, 12. , 12.5, 13. , 13.5, 14. , 14.5],
    [15. , 15.5, 16. , 16. , 16. , 16. , 16. , 16. , 16. , 16. ]])

end_times = np.array([
    [10.5, 11. , 11. , 11. , 11. , 11. , 11. , 11. , 11. , 11. ],
    [10.5, 11. , 11.5, 12. , 12. , 12. , 12. , 12. , 12. , 12. ],
    [10.5, 11. , 11.5, 12. , 12.5, 13. , 13. , 13. , 13. , 13. ],
    [10.5, 11. , 11.5, 12. , 12.5, 13. , 13.5, 14. , 14.5, 15. ],
    [15.5, 16. , 16. , 16. , 16. , 16. , 16. , 16. , 16. , 16. ]])

coupons = np.array([
    [0.03057629, 0.03057629, 0.        , 0.        , 0.        ,
    0.        , 0.        , 0.        , 0.        , 0.        ],
    [0.030797  , 0.030797  , 0.030797  , 0.030797  , 0.        ,
     0.        , 0.        , 0.        , 0.        , 0.        ],
    [0.03072953, 0.03072953, 0.03072953, 0.03072953, 0.03072953,
    0.03072953, 0.        , 0.        , 0.        , 0.        ],
    [0.03086061, 0.03086061, 0.03086061, 0.03086061, 0.03086061,
    0.03086061, 0.03086061, 0.03086061, 0.03086061, 0.03086061],
    [0.02808885, 0.02808885, 0.        , 0.        , 0.        ,
    0.        , 0.        , 0.        , 0.        , 0.        ]])
 
init_mr_guess = [0.05]
init_vol_guess = [0.05]

calibrated_params, converged, _ = tff.models.hull_white.calibration_from_swaptions(
    prices=prices,
    expiries=expiries,
    floating_leg_start_times=start_times,
    floating_leg_end_times=end_times,
    fixed_leg_payment_times=end_times,
    floating_leg_daycount_fractions=end_times - start_times,
    fixed_leg_daycount_fractions=end_times - start_times,
    fixed_leg_coupon=coupons,
    reference_rate_fn=zero_rate_fn,
    mean_reversion=init_mr_guess,
    volatility=init_vol_guess,
    maximum_iterations=50,
    notional=notional,
    use_analytic_pricing=True,
    dtype=tf.float64,
)

print("Calibrated params")
print("Vol:", calibrated_params.volatility.values())
print("Mean reversion:", calibrated_params.mean_reversion.values())
print("Is converged:", converged)
print("")`

recalced_prices = tff.models.hull_white.swaption_price(
    expiries=expiries,
    floating_leg_start_times=start_times,
    floating_leg_end_times=end_times,
    fixed_leg_payment_times=end_times,
    floating_leg_daycount_fractions=end_times-start_times,
    fixed_leg_daycount_fractions=end_times-start_times,
    fixed_leg_coupon=coupons,
    reference_rate_fn=zero_rate_fn,
    notional=notional,
    mean_reversion=calibrated_params.mean_reversion,
    volatility=calibrated_params.volatility,
    dtype=tf.float64,
)

print("Source prices: ", prices)
print("Recalculated prices: ", recalced_prices.numpy())

Output I'm seeing:
Source prices: [28.54, 27.63, 26.82, 25.76, 24.26]
Recalculated prices: [10.43644126, 20.46670051, 29.87954086, 46.01337643, 12.38118779]

Thanks in advance!

@mchandlernz mchandlernz changed the title Hull White Model - calibration not aligning to recalculated prices Hull White Model - calibration not aligning to input prices Feb 28, 2023
@cyrilchim
Copy link
Contributor

I'll take a look into that!

@cyrilchim
Copy link
Contributor

It seems that volatility_upper_bound and mean_reversion_upper_bound are hit by the algo. I tried adjusting the bounds a bit as well as the starting point

init_mr_guess = np.array([2.3])
init_vol_guess = np.array([4.0])
volatility_upper_bound = np.array(10.0)
mean_reversion_upper_bound = np.array(10.0)

calibrated_params, converged, num_iterations = tff.models.hull_white.calibration_from_swaptions( 
    prices=prices,
    expiries=expiries,
    floating_leg_start_times=start_times,
    floating_leg_end_times=end_times,
    fixed_leg_payment_times=end_times,
    floating_leg_daycount_fractions=end_times - start_times,
    fixed_leg_daycount_fractions=end_times - start_times,
    fixed_leg_coupon=coupons,
    reference_rate_fn=zero_rate_fn,
    mean_reversion=init_mr_guess,
    volatility=init_vol_guess,
    maximum_iterations=50,
    volatility_upper_bound=volatility_upper_bound,
    mean_reversion_upper_bound=mean_reversion_upper_bound,
    notional=notional,
    use_analytic_pricing=True,
    dtype=tf.float64,
)

I got estimated values as

Vol: tf.Tensor([6.89840182], shape=(1,), dtype=float64)
Mean reversion: tf.Tensor([3.26636998], shape=(1,), dtype=float64)

The recalculated prices are now

Source prices:  [28.54 27.63 26.82 25.76 24.26]
Recalculated prices:  [27.25619778 27.63154018 27.09365106 25.98051968 26.00355828]

which is a much better result.

@mchandlernz
Copy link
Author

Ah, that makes sense! Thank you for your help :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants