# Analytics Functions

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

`DiffFusion.ScenarioCube`

— Type```
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.scenarios`

— Function```
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_scenarios`

— Function`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_scenarios`

— Function```
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.concatenate_scenarios`

— Function`concatenate_scenarios(cubes::AbstractVector{ScenarioCube})`

Concatenate a list of scenarios along time axis.

`DiffFusion.aggregate`

— Function```
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_exposure`

— Function```
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_exposure`

— Function```
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_adjustment`

— Function```
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_times`

— Function```
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_csa`

— Function```
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_csa`

— Function```
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_values`

— Function```
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_portfolio`

— Function```
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_price`

— Function```
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_deltas`

— Function```
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_vegas`

— Function```
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_vector`

— Function```
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_vector`

— Function```
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.