Skip to main content

HullWhiteLattice

Struct HullWhiteLattice 

pub struct HullWhiteLattice<R: Scalar> {
    params: HullWhiteParameters<R>,
    grid: TimeGrid,
    dx: Vec<R>,
    hw: Vec<usize>,
    alpha: Vec<R>,
    branch: Vec<[(R, i64); 3]>,
    branch_off: Vec<usize>,
    qpow: Vec<R>,
}
Expand description

The Hull-White trinomial lattice at one mode. Geometry, displacements and rollback values are all R; only node indices are integers.

Fields§

§params: HullWhiteParameters<R>§grid: TimeGrid§dx: Vec<R>

Per-slice node spacing Δx_i (x_{i,j} = j·Δx_i); Δx_0 unused (root).

§hw: Vec<usize>

Per-slice half-width (max |j|).

§alpha: Vec<R>

Per-slice displacement α_i (r_{i,j} = α_i + j·Δx_i). Indices 0..n_steps−1 are fitted to reprice the curve; the terminal one is the analytic HW displacement, used only to value exercise at the last slice.

§branch: Vec<[(R, i64); 3]>

The precomputed branch table — one [(prob, child_j); 3] per node, step-major. Geometry only (a, σ, Δt, Δx): curve-, spread- and asset-independent, built once and shared by the fit and every rollback.

§branch_off: Vec<usize>

Per-step offsets into branch; branch_off[n] is the table length.

§qpow: Vec<R>

The per-node discount ladder q_i^j = e^{−jΔx_iΔt_i}, node-major on the same offsets as branch. Geometry only, like the branch table: computed once with the same power the fit and every rollback used to recompute per node per pass — so the values are the same and the power is gone from the passes.

Implementations§

§

impl<R: Scalar> HullWhiteLattice<R>

pub fn build<C: YieldCurve<R>>( params: HullWhiteParameters<R>, grid: TimeGrid, curve: &C, ) -> Result<HullWhiteLattice<R>, CurveError>

Builds and curve-fits a lattice over grid against curve, with the mean reversion and the volatility term in the pricing mode — market inputs, so their sensitivities flow with everything else’s.

§Errors

CurveError from the curve queries the fit makes.

pub fn geometry( params: HullWhiteParameters<R>, grid: TimeGrid, ) -> HullWhiteLattice<R>

The lattice’s geometry alone — grid, node spacing, half-widths, branch table and the per-node discount ladder — which depends on the mean reversion, the volatility term and the grid, and on no curve.

Separable from the fit on purpose: a scenario ladder over curves, or an OAS solve re-rolling one asset, builds this once and calls fit per curve. Until it is fitted the lattice has no displacements and cannot roll anything back.

fn half_width(&self, i: usize) -> usize

The half-width (max |j|) of the node range at step i.

fn width(&self, i: usize) -> usize

The number of nodes at step i.

fn j_at(&self, i: usize, jo: usize) -> i64

The level j at offset jo of step i (offset 0 ⇒ j = −half_width).

pub fn node_rate(&self, i: usize, j: i64) -> R

The short rate at node (i, j): α_i + j·Δx_i, in the pricing mode.

pub(crate) fn implied_forward(&self, i: usize) -> R

The instantaneous forward f(0, t_i) the lattice’s fitted displacement at step i implies: α_i − C(t_i) — α_i − (σ²/2a²)(1 − e^{−a·t_i})² for a flat volatility, α_i − ½σ²t_i² as a → 0 — the inverse of the analytic relation the terminal slice is built from. An affine bond price read at a node of this lattice must use this forward, not the curve’s: the node rates are this lattice’s, fitted over its own steps, and a bond formula keyed to a different forward misprices every node by B·Δf.

fn branches(&self, i: usize, j: i64) -> [(R, i64); 3]

The three (probability, child_j) branches from node (i, j).

pub fn fit<C: YieldCurve<R>>(&mut self, curve: &C) -> Result<(), CurveError>

Fits α to the discount curve via forward induction of the Arrow-Debreu state prices Q: α_i is chosen so the tree reprices P(0, t_{i+1}).

Callable again on the same geometry against another curve — that is what makes a scenario ladder a sequence of fits over one build.

§Errors

CurveError from the curve queries the fit makes.

fn inst_fwd<C: YieldCurve<R>>( curve: &C, date: NaiveDate, ) -> Result<R, CurveError>

Instantaneous forward f^M(0, date) from the curve — a forward difference of −ln P(0,·) over the one day from date, in the pricing mode: the rate of the segment the terminal slice enters, exactly, on a curve read log-linearly between day-dated pillars. The stencil instantaneous_forward uses, so the exercise values and this displacement agree.

pub fn rollback<A: DiscretizedAsset<R> + ?Sized>(&self, asset: &A, oas: R) -> R

Rolls asset backward from its last step to the root, returning the root present value. At each step the node value is the spread-discounted probability-weighted branch sum, then asset.adjust_values is applied.

oas is a continuously compounded zero spread added to every node’s short rate — the option-adjusted-spread slot. Zero is the identity.

pub fn rollback_risky<A: DiscretizedAsset<R> + ?Sized>( &self, asset: &A, oas: R, credit: Option<&StepCredit<R>>, ) -> R

rollback on an issuer’s credit: each step’s continuation is weighted by the survival over the step, and the recovery a default in it pays is added at the step’s end, before DiscretizedAsset::adjust_values — so exercise compares against the risky continuation. None is the riskless rollback, the same arithmetic bit for bit.

pub fn grid(&self) -> &TimeGrid

The lattice’s time grid.

pub fn levels(&self, i: usize) -> impl Iterator<Item = i64> + use<R>

The node range [−half_width, half_width] at step i, as j values.

Auto Trait Implementations§

§

impl<R> Freeze for HullWhiteLattice<R>
where R: Freeze,

§

impl<R> RefUnwindSafe for HullWhiteLattice<R>
where R: RefUnwindSafe,

§

impl<R> Send for HullWhiteLattice<R>

§

impl<R> Sync for HullWhiteLattice<R>

§

impl<R> Unpin for HullWhiteLattice<R>
where R: Unpin,

§

impl<R> UnsafeUnpin for HullWhiteLattice<R>
where R: UnsafeUnpin,

§

impl<R> UnwindSafe for HullWhiteLattice<R>
where R: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.