
import numpy as np
import Quantlib as ql

from hullwhite import (build_calibrated_hw,simulate_hw_state,swap_npv_from_state)
from instruments import (make_vanilla_swap,make_swaption_helpers)

today = ql.Date(15, 1, 2025)
ql.Settings.instance().evaluationDate = today
calendar = ql.TARGET()
day_count = ql.Actual365Fixed()


def expected_exposure(
    swap,
    hw,
    curve_handle,
    today,
    time_grid,
    x_paths
):
    ee = np.zeros(len(time_grid))

    for j, t in enumerate(time_grid):
        values = []

        for i in range(len(x_paths)):
            v = swap_npv_from_state(
                swap, hw, curve_handle, t, x_paths[i, j], today
            )
            values.append(max(v, 0.0))

        ee[j] = np.mean(values)

    return ee

def main():
    # Time grid
    time_grid = np.linspace(0, 10, 121)

    flat_rate = 0.02
    curve = ql.FlatForward(today, flat_rate, day_count)
    curve_handle = ql.YieldTermStructureHandle(curve)

    #creat and calibrate HW
    a_init = 0.05
    sigma_init = 0.01
    hw = ql.HullWhite(curve_handle, a_init, sigma_init)

    index = ql.Euribor6M(curve_handle)
    helpers=make_swaption_helpers(curve_handle,index,hw)
    optimizer = ql.LevenbergMarquardt()
    end_criteria = ql.EndCriteria(1000, 500, 1e-8, 1e-8, 1e-8)
    hw.calibrate(helpers, optimizer, end_criteria)

    a, sigma = hw.params()
    print(f"Calibrated a     = {a:.4f}")
    print(f"Calibrated sigma = {sigma:.4f}")



    # Simulate model
    x_paths = simulate_hw_state(
        hw, curve_handle, time_grid, n_paths=10000
    )

    # Swap
    swap = make_receiver_swap(
        today, curve_handle, maturity_years=10, fixed_rate=0.025
    )

    # Exposure
    ee = expected_exposure(
        swap, hw, curve_handle, today, time_grid, x_paths
    )



    return 0


if __name__ =='__main__':
    main()