src/lib/pricing/types.ts

50 lines
import type { TRFSchedule } from "./time";

export interface Dividend {
  /** Ex-date in years from valuation (ACT/360). */
  t: number;
  /** Gross dividend in index points. */
  gross: number;
}

/**
 * Every input of the forward. Any numeric field listed in `SolvableKey`
 * can be backed out of a quote with `implied()`.
 */
export interface ForwardArgs {
  spot: number;
  /** Time to expiry in years (ACT/360). */
  t: number;
  /** Risk-free rate, continuously compounded, ACT/360. */
  rate: number;
  /** Funding spread over the rate, continuously compounded, decimal (50bp = 0.005). */
  fundingSpread: number;
  dividends: Dividend[];
  /** All-in payout factor applied to gross dividends (the "WHT" column, 0.87 = 87%). */
  allIn: number;
  /** Multiplier on the gross schedule; the implied-gross-dividend solve moves this. */
  divScale: number;
  /**
   * `divScale` applies only to dividends going ex after this time (years); earlier ones are
   * taken as given (already scaled by the earlier tenors' curve). Default: scale them all.
   */
  divScaleFrom?: number;
  /** EQL spread over the rate for discounting option premia, continuously compounded, decimal. */
  eqlSpread: number;
  /**
   * Settlement-adjusted TRF day counts (see `trfSchedule`). Without it the TRF uses
   * calendar days and a continuous funding integral — no settlement lag.
   */
  trf?: TRFSchedule;
  /**
   * Settlement dates, years from valuation: `spot` = t + 2 weekdays, `expiry` = T + 2 weekdays.
   * Dividends are discounted to `spot`; the index is carried from `spot` to `expiry`.
   * Without it there is no settlement lag (spot = 0, expiry = t).
   */
  settle?: { spot: number; expiry: number };
}

export type SolvableKey = "spot" | "rate" | "fundingSpread" | "allIn" | "divScale" | "eqlSpread";

export type Pricer = (a: ForwardArgs) => number;