Analytics Functions
In this section we document methods for instrument pricing, exposure and collateral simulation.
DiffFusion.ScenarioCube
— Typestruct 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 typeModelValue
whereN_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 legnumeraire_context_key
- the context_key of theNumeraireEntry
; this label should indicate the cash flow currency.discount_curve_key
- a flag specifying whether prices inX
are discounted prices (for XVA) or undiscounted prices (for CCR).
DiffFusion.scenarios
— Functionscenarios(
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_scenarios
— Functionjoin_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_scenarios
— Functioninterpolate_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.concatenate_scenarios
— Functionconcatenate_scenarios(cubes::AbstractVector{ScenarioCube})
Concatenate a list of scenarios along time axis.
DiffFusion.aggregate
— Functionaggregate(
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_exposure
— Functionexpected_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_exposure
— Functionpotential_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_adjustment
— Functionvaluation_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_times
— Functioncollateral_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_csa
— Functionmarket_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_csa
— Functioncollateral_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_values
— Functioneffective_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_portfolio
— Functioncollateralised_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_price
— Functionmodel_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_deltas
— Functionmodel_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_vegas
— Functionmodel_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_vector
— Functionmodel_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_vector
— Functionmodel_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.