Analytics Functions

In this section we document methods for instrument pricing, exposure and collateral simulation.

DiffFusion.ScenarioCubeType
struct ScenarioCube
    X::AbstractArray
    times::AbstractVector
    leg_aliases::AbstractVector
    numeraire_context_key::String
    discount_curve_key::Union{String,Nothing}
end

A ScenarioCube represents the result of MC pricing results of a list of product legs and is calculated for a list of observation times.

Elements are

  • X - tensor of size (N_1, N_2, N_3) and type ModelValue where
    • N_1 is number of Monte Carlo paths,
    • N_2 is number of time steps,
    • N_3 is number of legs.
  • times - a vector representing observation times.
  • leg_aliases - a list of aliases (identifiers) corresponding to each leg
  • numeraire_context_key - the context_key of the NumeraireEntry; this label should indicate the cash flow currency.
  • discount_curve_key - a flag specifying whether prices in X are discounted prices (for XVA) or undiscounted prices (for CCR).
DiffFusion.scenariosFunction
scenarios(
    legs::AbstractVector,
    times::AbstractVector,
    path::Path,
    discount_curve_key::Union{String,Nothing};
    with_progress_bar::Bool = true,
    )

Calculate ScenarioCube for a vector of CashFlowLeg objects and a vector of scenario observation times.

DiffFusion.join_scenariosFunction
join_scenarios(cube1::ScenarioCube, cube2::ScenarioCube)

Join two scenario cubes along leg-axis.

join_scenarios(cubes::AbstractVector{ScenarioCube})

Join a list of scenario cubes along leg-axis.

DiffFusion.interpolate_scenariosFunction
interpolate_scenarios(
    t::ModelTime,
    cube::ScenarioCube,
    )

Interpolation scenarios along time axis.

We implement linear interpolation with flat extrapolation.

Other interpolations, e.g., piece-wise flat or Brownian Bridge should be incorporated here.

DiffFusion.aggregateFunction
aggregate(
    scens::ScenarioCube,
    average_paths::Bool=true,
    aggregate_legs::Bool=true,
    )

Average paths and aggregate legs in ScenarioCube.

scens is the input ScenarioCube.

If average_paths is true then reduce scenario cube along path axis. Otherwise, keep individual paths.

If aggregate_legs is true then reduce scenario cube along the axis of legs. Otherwise, keep individual legs.

DiffFusion.expected_exposureFunction
expected_exposure(
    scens::ScenarioCube,
    gross_leg::Bool = false,
    average_paths::Bool = true,
    aggregate_legs::Bool = true,
    )

Calculate expected positive exposure (EPE or EE).

scens is the input ScenarioCube.

If gross_leg is true then calculate positive floor on trade level. Otherwise, use netted portfolio to determine positive floor.

If average_paths is true then reduce scenario cube along path axis. Otherwise, keep individual paths.

If aggregate_legs is true then reduce scenario cube along the axis of legs. Otherwise, keep individual legs.

DiffFusion.potential_future_exposureFunction
potential_future_exposure(
    scens::ScenarioCube,
    quantile_::ModelValue,
    gross_leg::Bool = false,
    )

Calculate the potential future exposure (PFE).

scens is the input ScenarioCube.

quantile_ is the desired quantile for PFE calculation.

If gross_leg is true then calculate positive floor on trade level. Otherwise, use netted portfolio to determine positive floor.

DiffFusion.valuation_adjustmentFunction
valuation_adjustment(
    credit_ts::CreditDefaultTermstructure,
    recovery_rate::ModelValue,
    cva_dva::ModelValue,
    scens::ScenarioCube,
    gross_leg::Bool = false,
    average_paths::Bool = true,
    aggregate_legs::Bool = true,
    rho::ModelValue = 0.5,
    )

Calculate unilateral CVA and DVA for a given ScenarioCube. Result is a ScenarioCube with non-negative XVA contributions along the time axis.

credit_ts is the credit spread curve to calculate survival probabilities. recovery_rate is the corresponding constant recovery rate value (typicall 0.40).

cva_dva is a binary flag to model CVA (+1.0) and DVA (-1.0).

scens is the input ScenarioCube. Values are assumed to be discounted prices in the corresponding portfolio currency.

Parameters gross_leg, average_paths and aggregate_legs are used as in function expected_exposure.

rho specifies how to integrate discounted prices. rho=0.5 uses trapezoidal rule. This choice is used in BCBS paper Basel III: A global regulatory framework for more resilient banks and banking systems (2011). rho=0.0 uses prices at the start of period and is proposed in Green, XVA (2016).

Collateral Modelling

This section contains methods for collateralised exposure calculation.

We follow the approaches in A. Green, XVA, 2016.

DiffFusion.collateral_call_timesFunction
collateral_call_times(
    Δt::ModelTime,
    first_call_time::ModelTime,
    last_call_time::ModelTime,
    )

Calculate margin call times.

Margin frequency is represented as time difference between margin call times, Δt.

first_call_time is the first margin time greater/equal time-0 and last_call_time is the last modelled margin call time.

DiffFusion.market_values_for_csaFunction
market_values_for_csa(
    portfolio::ScenarioCube,
    obs_times::AbstractVector,
    fx_rates::Union{ScenarioCube, Nothing} = nothing
    )

Calculate future market values of a given portfolio in CSA currency. Result is represented as ScenarioCube.

Market values of the portfolio are assumed in numeraire currency from a simulation.

fx_rates are simulated FOR-DOM exchange rates where FOR currency represents the CSA currency and DOM currency represents the numeraire currency of the simulation.

obs_times represent the margin call times for which market values are required. We implement linear interpolation of available market values.

DiffFusion.collateral_values_for_csaFunction
collateral_values_for_csa(
   portfolio::ScenarioCube,
   initial_collateral_balance::ModelValue,
   minimum_transfer_amount::ModelValue,
   threshold_amount::ModelValue,
   independent_amount::ModelValue,
   )

Calculate the collateral balance based on CSA parameters.

portfolio is assumed to be aggregated over legs and represents un-discounted market values in CSA currency.

CSA parameters are all denominated in CSA currency (or base currency).

initial_collateral_balance is the (net-)balance of posted/received collateral at time-0.

minimum_transfer_amount (MTA) is the minimum amount of collateral that is exchanged at a collateral call time. Here, MTA is assumed equal for bank and counterparty.

threshold_amount (TA) represents the maximum exposure of the portfolio below which no collateral is posted. Here, TA is assumed equal for bank and counterparty.

independent_amount represents a (net-)amount of collateral that is posted/received independent of the portfolio market value.

DiffFusion.effective_collateral_valuesFunction
effective_collateral_values(
    obs_times::AbstractVector,
    collateral_balance::ScenarioCube,
    margin_period_of_risk::ModelTime,
    )

Calculate the effective collateral balance per observation times.

The effective effective collateral balance is modelled as an additional ScenarioCube which can be joined with the original portfolio ScenarioCube. The resulting combined ScenarioCube represents the collateralised portfolio.

Portfolio observation times obs_times represent termination times following a potential default.

collateral_balance represent un-discounted market values of the collateral account from bank's perspective in CSA currency. Collateral observation times are margin call times.

margin_period_of_risk (MPR) represents the modelled time between default time τ and observation time t.

We make the following assumptions:

  • No margin flows are paid during MPR.
  • All trade flows are paid during MPR.

The modelled approach refers to the "Classical+" approach in Andersen/Pykhtin/Sokol, 2016.

DiffFusion.collateralised_portfolioFunction
collateralised_portfolio(
    portfolio::ScenarioCube,
    fx_rates::Union{ScenarioCube, Nothing},
    margin_call_times::AbstractVector,
    initial_collateral_balance::ModelValue,
    minimum_transfer_amount::ModelValue,
    threshold_amount::ModelValue,
    independent_amount::ModelValue,
    margin_period_of_risk::ModelTime,
    )

Calculate a collateralised portfolio by joining the effective collateral balance.

Pricing Analytics

DiffFusion.model_priceFunction
model_price(
    payoffs::AbstractVector,
    path_obj::Path,
    pay_time::Union{ModelTime, Nothing} = nothing,
    discount_curve_key::Union{String,Nothing} = nothing
    )

Calculate model price for a vector of Payoff objects.

DiffFusion.model_price_and_deltasFunction
model_price_and_deltas(
    payoffs::AbstractVector,
    path_obj::Path,
    pay_time::Union{ModelTime, Nothing} = nothing,
    discount_curve_key::Union{String,Nothing} = nothing
    )

Calculate model price and curve sensitivities.

Here, payoffs is a vector of Payoff objects and path_obj is a simulated Path.

pay_time and discount_curve_key control payoff discounting via numeraire calculation.

DiffFusion.model_price_and_vegasFunction
model_price_and_vegas(
    payoffs::AbstractVector,
    model::CompositeModel,
    simulation::Function,
    ts_list::AbstractVector,
    context::Context,
    pay_time::Union{ModelTime, Nothing} = nothing,
    discount_curve_key::Union{String,Nothing} = nothing
    )

Calculate model price and model sensitivities.

Here, payoffs is a vector of Payoff objects, model is a full hybrid model.

simulation is a short cut for a Simulation constructor with the signature simulation(model::Model, ch::CorrelationHolder).

ts_list is a list of TermStructure objects for pricing and context is a Context for valuation.

pay_time and discount_curve_key control payoff discounting via numeraire calculation.

DiffFusion.model_price_and_deltas_vectorFunction
model_price_and_deltas_vector(
    payoffs::AbstractVector,
    path_obj::Path,
    pay_time::Union{ModelTime, Nothing} = nothing,
    discount_curve_key::Union{String,Nothing} = nothing,
    ad_module::Module = ForwardDiff,
    )

Calculate model price and curve sensitivities. Sensitivities are calculated as vector together with a vector of labels.

Here, payoffs is a vector of Payoff objects and path_obj is a simulated Path.

pay_time and discount_curve_key control payoff discounting via numeraire calculation.

ad_module can be Zygote or ForwardDiff.

For AMC payoffs we need to update the regression path and trigger a recalibration. For sensitivity calculation, we impose the constraint that regression calibration uses the same paths as valuation.

DiffFusion.model_price_and_vegas_vectorFunction
model_price_and_vegas_vector(
    payoffs::AbstractVector,
    model::CompositeModel,
    simulation::Function,
    ts_list::AbstractVector,
    context::Context,
    pay_time::Union{ModelTime, Nothing} = nothing,
    discount_curve_key::Union{String,Nothing} = nothing,
    ad_module::Module = ForwardDiff,
    )

Calculate model price and model sensitivities. Sensitivities are calculated as vector together with a vector of labels.

Here, payoffs is a vector of Payoff objects, model is a full hybrid model.

simulation is a short cut for a Simulation constructor with the signature simulation(model::Model, ch::CorrelationHolder).

ts_list is a list of TermStructure objects for pricing and context is a Context for valuation.

pay_time and discount_curve_key control payoff discounting via numeraire calculation.

ad_module can be Zygote or ForwardDiff.

For AMC payoffs we need to update the regression path and trigger a recalibration. For sensitivity calculation, we impose the constraint that regression calibration uses the same paths as valuation.