Skip to main content

Module pnl

Module pnl 

Expand description

P&L attribution between two markets, in parameter space.

Three verbs over the same move Δ = after − before, one lifted input at a time:

  • market_diff — the move itself, under a layout guard: two markets are comparable only if their lifted input sequences are identical, and a mismatch names the first input that differs rather than attributing a hazard move to a rates pillar.
  • predicted_pnl — first order from the risk vector at before, plus the quadratic term from one second-order valuation seeded along the whole move: lift_directional puts Δ on a Jet2 tangent, and the second derivative that comes back is exactly Δᵀ H Δ. No Hessian is assembled, nothing is bumped, and the term is exact rather than a diagonal guess. The same pass along the move restricted to one axis group, and to two, splits it exactly by the groups that moved (GammaTerms): an own gamma per group and one symmetric cross gamma per pair, by the polarisation identity d_aᵀ H d_b = ½[q(d_a + d_b) − q(d_a) − q(d_b)]. That is 1 + m + m(m − 1)/2 passes for m moved groups, a handful on a daily move, and still no matrix: the split is by axis pair, which is what a reconciliation reads, not by input.
  • explain — the sequential revaluation ladder: inputs move from before to after one axis group at a time, each step a full valuation. A step takes the axis’s curves as after holds them — a scenario’s shock transform, which carries no parameter, included — and its parameters at after’s values. The final step is npv(after) bit for bit, checked, and the legs close to the actual P&L within the round-off of summing them.

Both attributions refuse a move they cannot see (PnlError::MoveOutsideParameters): the prediction reads the risk vector at before, whose coordinates a shock transform is not in, and the ladder moves only what an axis holds.

reconcile aligns the two attributions by axis and names what each leg’s difference is made of: the leg’s own gamma, its cross gamma with the axes the ladder moved before it — the step-order effect, as a number — and the residual neither explains. The differences sum to the prediction’s quadratic-plus-residual, the own and cross columns to its second-order terms.

What became known comes first. A print the ending market holds and the starting market does not is not a move of a parameter the starting market has: it is a new parameter. The layout guard relaxes in exactly that one way — a MarketInputId::Fixing present on the after side alone is lifted out as a newly published print, and every other difference is still refused — and both attributions begin by publishing those prints onto the starting market: the ExplainLeg::Resets leg of the ladder, the resets term of the prediction. reset_pnl is the same step read per print, the way a desk reads it: the forecast the print replaced, the print, the move, the sensitivity, the P&L. Both markets must be valued on the same day; the overnight move — yesterday’s close to today’s — re-dates every pillar and is a carry-and-roll step, not this one.

Across days the ladder starts with two legs of its own (explain_across_days): the ExplainLeg::Cash the book was paid between the dates, and the ExplainLeg::Carry — the book on the starting market’s quotes rebuilt at the ending date, less its starting value. From that rolled market to the ending one is a same-day move, which the ladder above explains.

Structs§

ExplainReport
A step-revaluation explain.
GammaTerms
The second-order term split exactly by the axis groups that moved.
LayoutMismatch
Where two markets’ lifted input sequences first diverge.
MarketDiff
The move between two markets, one entry per lifted input, in lift order, and the prints the ending market has that the starting market lacks.
Move
One lifted input’s move.
PredictedPnl
A predicted explain: first order per input, second order along the move.
Published
One print the ending market holds that the starting market does not.
Reconciliation
The two attributions aligned by axis.
ReconciliationRow
One leg of a reconciliation, its terms named.
ResetPnl
The reset step read per print.
ResetPrint 🔒
One print of the reset step: what the coupon applied before it, and the print itself.
ResetRow
One published print’s contribution to the reset step.
ResetStep 🔒
The reset step. A market that lacks a print the book has accrued refuses to value, so the step does not start from before as given: it starts from before with each new print standing at the forecast it replaced — the value the book carried while the print was projected, and before’s own value to round-off where it prices without the print — and ends at before with every print published. diff is the move from there to after, whose layouts now agree. None when after publishes nothing new.

Enums§

ExplainLeg
What a ladder step moved: the prints that became known, one axis, or everything no axis holds.
PnlError
An attribution that could not be produced.

Functions§

default_order
The default ladder order: the axes as declared.
explain
The step-revaluation explain of book from before to after: first the prints after holds that before does not, published onto before as the ExplainLeg::Resets leg (present only when there are any), then one axis group at a time in order: at its step an axis takes after’s rate, repo, security-spread, credit or inflation curves (shock transforms included) and after’s value of every parameter on it. Axes absent from order, and inputs on no axis, move together in the final leg, so the last step is after.
explain_across_days 🔒
The explain of book across days: cash, what the book was paid after before’s date and up to after’s, as the ExplainLeg::Cash leg; the ExplainLeg::Carry leg, from before to rolled — before’s quotes rebuilt at after’s date, each print the book reads in between at the forecast before projected it at; and from rolled to after, a same-day move, the ladder of explain. The legs sum to npv(after) − npv(before) + cash.
forecast_of 🔒
The rate the coupon applied to date while the print was projected: the index’s own window, simple on its day count, off market’s projection curve for that index — not the curve’s continuously compounded forward. A curve reaches no date before its reference, and a print that needs attributing is usually dated before it; for such a date the forecast is the index’s forecast at the reference date, the front of the curve read flat backward, which is the rate the curve projects an unprinted day at.
gamma_terms 🔒
The split of quadratic — ½ dᵀ H d along the whole of diff — by the groups that moved, per GammaTerms. With one moved group the whole move is that group’s move, so its own term is quadratic itself and no pass is repeated.
group_label 🔒
The group a slot labels: the axis, or None for the off-axis group.
group_slot 🔒
The slot of an input’s group: its axis’s position in RiskAxis::ALL, or one past the end for an input on no axis.
leg_groups 🔒
The groups a ladder leg moves: none for the resets, one axis for an axis leg, and for the final leg every axis the ladder did not take plus the inputs on no axis.
lift_out_new_prints 🔒
The prints in ids_after that ids_before lacks, taken out of the sequence with their values, when the markets share a day.
lifted_layout 🔒
The lifted values and input identifiers of a market, passively.
market_diff
The move from before to after, under the layout guard — with one relaxation. A MarketInputId::Fixing that after holds and before does not is a newly published print, not a move: it is lifted out into MarketDiff::published and the remaining inputs are compared position by position as ever. A print before holds and after does not is refused — a print does not un-publish — and so is every other difference. Markets on different valuation days get no relaxation: their prints are compared like any other input.
predicted_pnl
The predicted explain of book between before and after. Prints after holds and before does not are published first — the resets term, an exact step, since the risk vector at before has no row for a print it does not hold — and the first and second order are read from the market with them.
reconcile
Aligns a predicted explain with a ladder explain over the same move, and decomposes each leg’s difference. A leg moves a set of groups — one axis, or for the final leg every axis the ladder did not take plus the inputs on no axis; its own gamma is those groups’ own terms and the cross terms among them, its cross gamma the cross terms between them and every group an earlier leg moved, and its residual the rest. Each second-order term lands on exactly one leg, so the columns sum to the prediction’s terms.
reset_pnl
The reset P&L of book from before to after: one row per print after holds and before does not, or holds at another value, each the exact revaluation from the forecast the print replaced to the print, the earlier prints already published, beside the move and the sensitivity. The walk starts from before with every new print standing at its forecast, since a market lacking a print the book has accrued does not value.
reset_prints 🔒
Every print after holds that before does not, or holds at another value, in date order then by index.
reset_step 🔒
same_day 🔒
Whether the two markets are valued on the same day.
second_along 🔒
vᵀ H v from one second-order pass of book on market along v.
value_at 🔒
The book’s value against market with every input moved at diff’s ending value and the rest at its starting value.
value_of 🔒
The passive value of book against market.
with_axis_from 🔒
market with axis‘s curves taken from after: its rate, repo and security-spread curves, its credit curves or its inflation curves, each as after holds it — a scenario’s shock transform included, which is a move no parameter carries. The other axes’ inputs are parameters alone (FX spots, vol surfaces, correlation, recovery), moved by value_at.
with_prints 🔒
market with each of prints published at at(print) — a print already held is restated.