Skip to main content

Schedule

Struct Schedule 

pub struct Schedule {
    pub dates: Vec<NaiveDate>,
}
Expand description

An ordered set of adjusted calculation-period boundary dates.

Fields§

§dates: Vec<NaiveDate>

Boundary dates, ascending. n boundaries delimit n - 1 periods.

Implementations§

§

impl Schedule

The schedule’s payment-date projection.

Schedule is a statics-layer type and this is an inherent method on it, but the impl block lives here rather than beside Schedule::generate: LagAdjustment belongs to this layer, and writing the method in statics::schedules would make the reference-data layer import the cashflow layer above it. Split this way, callers still write schedule.paying(&lag) and the dependency edge points down, which is the direction the layering allows.

pub fn paying(&self, lag: &LagAdjustment) -> Vec<NaiveDate>

The payment date of every period, under a lag supplied at the call.

One date per period, so this is one shorter than Schedule::dates.

The schedule carries no payment lag of its own and stores nothing here. When a period pays is the coupon’s business: two legs sharing one schedule may pay under different lags against different calendars, which a stored lag could not express. The lag is therefore handed in, and this is a projection over it rather than a property of the schedule.

It routes through LagAdjustment::apply — the same operation a coupon’s payment date is computed by — rather than a second walk, so a lag cannot mean one thing in a schedule and another in a leg. That is the discipline RollConvention::apply already holds between the schedule generator and a caller.

A zero lag is the identity on a date that is already a good business day, and LagAdjustment::from_payment_lag returns None for one; a caller with no lag reads the accrual ends off Schedule::periods, which is what “no lag” means.

§

impl Schedule

pub fn generate( effective: NaiveDate, termination: NaiveDate, frequency: Period, calendar: &dyn Calendar, convention: BusinessDayConvention, roll: RollConvention, stub: StubPeriodType, end_of_month: bool, terminal_convention: Option<BusinessDayConvention>, date_generation: Option<DateGenerationRule>, ) -> Result<Self, ScheduleError>

Generates a schedule between effective and termination.

Initial stubs generate backward from termination; final stubs generate forward from effective. Interior boundaries are snapped by roll, then every boundary is adjusted by convention against calendar.

§Both dates are unadjusted anchors

effective and termination are unadjusted generation anchors, not the adjusted boundaries this returns. One of the two is the seed regular boundaries are measured from; the other is only a boundary:

stubseedboundary only
ShortFinal / LongFinaleffectivetermination
ShortInitial / LongInitialterminationeffective

Passing an already-adjusted date in place of the seed moves every interior boundary, because they are measured as seed + k·frequency. Passing one in place of the other date is harmless — it is adjusted again, which is idempotent. So the same substitution is corrupting in one direction and invisible in the other, and neither raises.

A caller holding only adjusted dates — read off a confirm, say — recovers the unadjusted schedule by supplying the roll that generated them. roll snaps interior boundaries after generation, so it supersedes the seed’s day of month: an adjusted effective of 2000-01-03 under RollConvention::DayOfMonth(1) produces the same dates as the unadjusted 2000-01-01 under RollConvention::None, date for date. Only RollConvention::None carries no snap and so cannot recover anything; see an_adjusted_seed_under_its_roll_is_the_unadjusted_schedule.

To state boundary dates outright rather than generate them, use Schedule::from_dates, which applies no calendar, roll or adjustment at all.

Every regular boundary is a whole multiple of frequency measured from a single fixed anchor — effective when generating forward, termination when generating backward — never from the previously generated boundary. Month arithmetic clamps into short months (31 Jan + 1M = 28 Feb), and anchoring keeps each clamp local to the boundary that incurs it instead of ratcheting the day-of-month down for every later one — seed + n·tenor rather than a cumulative step; see scale.

A frequency that does not carry the cursor toward the far anchor — a zero multiplier, a Term period, or a negative multiplier — yields the lone [effective, termination] period rather than looping (see advances).

When end_of_month is set and the seed anchors a month end (it is on or after its month’s last business day), every interior boundary is rolled to the calendar last day of its month — the end-of-month roll (FpML EOM, RollConvention::Eom) — and convention then adjusts it like any other boundary. So Following on a Saturday 31 January gives Monday 2 February, ModifiedFollowing gives Friday 30 January, and None keeps the Saturday. roll is not applied in that mode (the flag is the roll). The endpoints are never end-of-month rolled, but they are still adjusted to business days: the effective date by convention, the termination by terminal_convention.

Whichever roll applies, it is applied to each candidate boundary before the stop test against the far anchor, so a boundary the raw arithmetic placed inside the schedule cannot be rolled onto or past its end: the result is strictly ascending, and a long stub merges the two rolled periods it names.

This is a different rule from the money-market end/end rule that Calendar::advance applies under the same flag, which always lands on the last business day: a deposit or index window from a month end matures on the last business day whatever the convention, while a schedule boundary is the calendar month end, adjusted. The two differ under Following and None on a weekend month end.

terminal_convention adjusts the final boundary (the termination date) independently of convention; None adjusts it by convention (the historical behaviour), while Some(BusinessDayConvention::None) keeps the termination date exactly as passed — the separate end-date business-day adjustment that market conventions specify independently of the interior.

When date_generation is Some(DateGenerationRule::Cds), the schedule anchors its start at the prior CDS-IMM date of effective, steps forward quarterly snapping interior boundaries to the 20th (the ImmTwentieth roll, superseding roll and end_of_month), and—paired with a terminal_convention of None business-day adjustment—reproduces the standard CDS2015 boundary list. None and the non-CDS rules generate as before (direction inferred from stub).

§Errors

ScheduleError::RepeatedDate when termination equals effective, and ScheduleError::OutOfOrder when it precedes it: a term that does not run forwards delimits no period, and silently accepting one once produced a two-date schedule with a single negative-length period.

pub fn generate_with_stubs( effective: NaiveDate, first_regular_start: Option<NaiveDate>, last_regular_end: Option<NaiveDate>, termination: NaiveDate, frequency: Period, calendar: &dyn Calendar, convention: BusinessDayConvention, roll: RollConvention, stub: StubPeriodType, end_of_month: bool, terminal_convention: Option<BusinessDayConvention>, ) -> Result<Self, ScheduleError>

generate with stated stub dates: FpML’s firstRegularPeriodStartDate and lastRegularPeriodEndDate.

The regular periods run between the regular anchors — first_regular_start, else effective, and last_regular_end, else termination — measured from one fixed anchor in the direction stub names, exactly as generate measures them; any irregular period the anchors leave sits where stub says. A stated first regular start adds the front stub from effective to it, a stated last regular end the back stub from it to termination: both give a double stub. Every boundary is then adjusted as generate adjusts them, the last by terminal_convention.

§Errors

ScheduleError::StubDateOutsideTerm for a stated date not strictly inside (effective, termination), and ScheduleError::StubDatesOutOfOrder for a first regular start not before the last regular end.

pub fn from_dates(dates: Vec<NaiveDate>) -> Result<Self, ScheduleError>

A schedule from boundary dates stated verbatim.

No calendar, no roll convention and no business-day adjustment is applied: a stated boundary has already had all three applied by whoever stated it, and applying them again is exactly the double adjustment Schedule::generate’s anchor contract exists to prevent. This is the entry point for a schedule read off a confirm, or printed by another library, rather than generated from conventions.

The result is the same value generate produces, so a leg built on stated dates differs from one built on generated dates in nothing but its dates.

A stated schedule is not refused for being unconventional — a boundary on a weekend, or periods of unequal length, are what stating dates is for. Only an ill-formed list is refused.

§Errors

ScheduleError::TooFewDates below two dates, ScheduleError::OutOfOrder on a descending pair, and ScheduleError::RepeatedDate on a repeat.

A repeat is refused rather than dropped, where generate drops one. The two cases differ in kind: in generation the collision is produced by the adjustment, so dropping one answers a question the caller never asked, whereas a caller who wrote a date twice made an error, and returning a schedule with fewer periods than were enumerated is the silent wrong answer this entry point exists to avoid.

pub fn periods(&self) -> Vec<(NaiveDate, NaiveDate)>

The periods as (start, end) pairs. n boundaries yield n - 1.

To ask when each of those periods pays, see Schedule::paying, whose impl block lives in cashflows::adjustments — it takes a LagAdjustment, which belongs to the layer above this one, so the method is written there to keep this layer from importing it.

Trait Implementations§

§

impl Clone for Schedule

§

fn clone(&self) -> Schedule

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
§

impl Debug for Schedule

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
§

impl Eq for Schedule

§

impl PartialEq for Schedule

§

fn eq(&self, other: &Schedule) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
§

impl StructuralPartialEq for Schedule

Auto Trait Implementations§

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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.