libitofin 0.2.0

A ground-up Rust port of QuantLib: quantitative-finance primitives for pricing, risk, and numerical methods.
Documentation
//! Market quotes.
//!
//! Port of `ql/quote.hpp`: the [`Quote`] trait is the purely virtual base
//! class for market observables. QuantLib's `Quote` inherits `Observable`;
//! here the trait exposes the embedded observable through its
//! [`AsObservable`] supertrait, which is also what lets a
//! [`Handle`](crate::handle::Handle) forward pointee changes to its
//! observers.
//!
//! `handleFromVariant` (a `std::variant<Real, Handle<Quote>>` convenience for
//! C++ term-structure constructors) has no caller in the core yet and is not
//! ported.
//!
//! The remaining `ql/quotes/` classes depend on layers not yet ported and
//! follow with them: `ForwardValueQuote` and `LastFixingQuote` (Index),
//! `ForwardSwapQuote` (SwapIndex/VanillaSwap), `FuturesConvAdjustmentQuote`
//! (IborIndex), `ImpliedStdDevQuote` and
//! `EurodollarFuturesImpliedStdDevQuote` (`blackFormulaImpliedStdDev`).

mod compositequote;
mod deltavolquote;
mod derivedquote;
mod multicompositequote;
mod simplequote;

pub use compositequote::CompositeQuote;
pub use deltavolquote::{AtmType, DeltaType, DeltaVolQuote};
pub use derivedquote::DerivedQuote;
pub use multicompositequote::MultiCompositeQuote;
pub use simplequote::{SimpleQuote, make_quote_handle};

use std::cell::Cell;

use crate::errors::QlResult;
use crate::patterns::observable::{AsObservable, Observable, Observer};
use crate::shared::{Shared, SharedMut, shared, shared_mut};
use crate::types::Real;

/// Purely virtual base class for market observables.
///
/// Mirrors QuantLib's `Quote`. Implementors embed an
/// [`Observable`](crate::patterns::observable::Observable) and notify it when
/// their value changes; observers of a quote register through
/// [`observable`](AsObservable::observable).
pub trait Quote: AsObservable {
    /// Returns the current value, or an error if the quote holds none.
    fn value(&self) -> QlResult<Real>;

    /// Whether the quote holds a valid value.
    fn is_valid(&self) -> bool;
}

/// Observer half of a derived quote (the C++ `update()` of `DerivedQuote` and
/// friends): drops the cached value and passes the notification on to the
/// quote's own observers.
///
/// Derived quotes register one of these with their source handle(s) and hold
/// the strong reference; the observer registry keeps only a weak one.
struct Invalidator {
    cache: Shared<Cell<Option<Real>>>,
    observable: Shared<Observable>,
}

impl Invalidator {
    /// Builds the empty cache, the quote's observable and the invalidating
    /// listener wired to both - the shared construction step of every derived
    /// quote.
    fn new() -> (
        Shared<Cell<Option<Real>>>,
        Shared<Observable>,
        SharedMut<Invalidator>,
    ) {
        let cache = shared(Cell::new(None));
        let observable = shared(Observable::new());
        let listener = shared_mut(Invalidator {
            cache: Shared::clone(&cache),
            observable: Shared::clone(&observable),
        });
        (cache, observable, listener)
    }
}

impl Observer for Invalidator {
    fn update(&mut self) {
        self.cache.set(None);
        self.observable.notify_observers();
    }
}