Kalotay
Analytics
A Division of Andrew Kalotay Associates, Inc.
BondOAS™ Library API Documentation

Description

BondOAS™ is a rigorously developed, continuously enhanced, thoroughly tested valuation engine for the universe of fixed coupon bonds. The BondOAS™ library is a thread-safe library written in C/C++. The library is released as both static and dynamic libraries for multiple architectures including 32 and 64 bit Linux, Windows, and SunOS. BondOAS™ has APIs for C++, C, Java, and C#. See BondOAS™ Overview for additional information.

C++ API — akaapi.hpp

* Copyright (c) 2014, Andrew Kalotay Associates, Inc.. All rights reserved. *

Note: all objects are defined within the namespace 'AndrewKalotayAssociates'

Overview

This file contains the class definitions for using the C++ API to BondOAS™. This file also serves as documentation for the API. It is arranged in the following sections:

  1. General Notes
  2. Error Handling
  3. Initialization
  4. Interest Rate Model Definition
  5. Bond Definition
  6. Valuation
  7. Supporting Classes

Section 1. General Notes

BondOAS™ is a multi-thread safe C++ API. The interface is through a small set of classes. These classes are described below.

There are four primary classes:

  1. Initialization -- initializes library functions
  2. InterestRateModel -- defines an interest rate environment
  3. Bond -- defines a bond
  4. Value -- values a bond given an interest rate environment

All error handling is managed through the Status class which is inherited by each other class.

A simple program has the following steps.
// The Initialization object must be successfully created and authorized Initialization init; if (init.Authorize(key, name) > 0) exit(init.Error()); // Create both an interest rate model and a bond object Bond bond("bullet", Date(2000, 1, 1), Date(2030, 1, 1), 2.0); // 30yr, 2% InterestRateModel model; model.SetRate(1, 2.0); // set a flat 2% rate model.Solve(); if (model.Error() > 0) exit(model.Error()); // Now value the bond Value value(bond, model, Date(2013, 7, 1)); if (value.Error() > 0) exit(value.Error()); double price = value.Price(0); // price at OAS 0

Section 2. Error Handling

All major classes inherit from the Status class. It supports retrieving status/errors/warnings about the state of an object. See akaerrno.h for a C enum of the AKA library error codes.

class Status { protected: class StatusData *statusdata; public: Status(); ~Status(); public: // all are const methods int Error() const; // returns AKA Error Number of error (or zero, none) int WarningCount() const; int Warning(int idx) const; // returns AKA Error Number of warning // converts a numeric status code to a string static const char *ErrorString(int); // get errors/warnings in string form const char *ErrorString() const { return ErrorString(Error()); }; const char *WarningString(int idx) const { return ErrorString(Warning(idx)); }; /* Clear any error and warnings. In most use cases there should be no need to call this method as each class inheriting from this object clears messages before each of its operations/methods. */ void Clear(); }; // forward declarations, see below class Date; class ConstantString;

Section 3. Initialization.

The Initialization object must be successfully authorized with a valid key in order to use the library. All operations will fail if the library is not initialized or is shutdown. By default, the library is shutdown (de-initialized) when the Initialization object goes out of scope or is deleted. This behavior can be inhibited by ShutdownAutomatically(false), see below. If automatic shutdown is disabled the library can be shutdown via the static Shutdown() method. The Shutdown() method should otherwise never be called. The behavior of multiple concurrent initializations is undefined and should be avoided. Use of valid library objects subsequent to shutdown is also undefined and should be avoided.

class Initialization : public Status { private: // disallow copy, assignment Initialization(const Initialization &) { }; Initialization & operator=(const Initialization &) { return *this; }; public: /* Initialize the library but do not check authorization. All library operations will fail until authorization is done. */ Initialization(); /* Initialize and authorize, call the appropriate authorization method, below, and set Error(). */ Initialization(long key, const char *uname); Initialization(const char *keyfilename); ~Initialization(); // by default library is shutdown void ShutdownAutomatically(bool); // set auto-shutdown behavior static void Shutdown(); // shutdown library when not done automatically // Returns error code or 0 on success. int Authorize(long key, const char *uname); /* Authorize getting key and user-name from a key file with key and user-name in that order. White space between the key and the user-name is ignored, as is trailing white space after the user-name. Any read or parsing errors cause initialization to fail with AKA_ERROR_AUTHORIZATION. Returns error code or 0 on success. */ int Authorize(const char *keyfilename = "./akalib.key"); /* Initialization inherits from Status. Error() must be checked after instantiation. No library operations will work if the this object has an error. Nor will they work if this object is not instantiated. */ Date Expiration() const; // when the provided key expires as a Date static double Version(); // library version as a number static const char *VersionString(); // library version as a string };

Section 4. Interest Rate Model Definition

InterestRateModel is the solved representation of future interest rates states based on an interest rate curve and volatility.

class MuniCurve; // forward declare class InterestRateModel : public Status { private: friend class Value; friend class ValueAfterTax; friend class InterestRateScenario; friend class Compatibility; class InterestRateModelData *data; public: enum INPUTTYPE { FACTORCURVE, PARCURVE }; // note, for Zero curves use FACTORCURVE and SetZeroRate() explicit InterestRateModel(INPUTTYPE = PARCURVE); ~InterestRateModel(); /* Copy Constructor Using a forward period greater than zero creates a new interest rate model with rates projected forward that number of years. The resulting new curve will be of type PARCURVE. It will not be already solved. A simple copy (no forward rate passed) of a solved model creates a new copied model that is also already solved. There is no cost to solving the new model. */ InterestRateModel(const InterestRateModel &, double forward_period = 0); InterestRateModel & operator=(const InterestRateModel &); // produce an XML representation, for serialization and printing const ConstantString ToXML() const; explicit InterestRateModel(const char *XML); // construct from XML // create a par InterestRateModel from a MuniCurve (see def. below) InterestRateModel(const MuniCurve &); // Curve Configuration /* all Set{X}() methods return true/false. If the value is false the set operation has been ignored. A false value is only due to bad/invalid inputs given to the method. */ /* Set a rate on the par curve, 4.25% is 4.25. Will fail if year is <= 0, rate is too low, or curve is a FACTORCURVE */ bool SetRate(double year, double rate); /* Set a factor on the discount curve. Will fail if year is <= 0, factor is too low, or curve is a PARCURVE */ bool SetFactor(double year, double factor); /* Set a rate using the zero rate. Will fail if year is <= 0, rate is too low, or curve is not a FACTORCURVE */ bool SetZeroRate(double year, double zerorate); // remove the curve point, either par or factor -- always succeeds void RemovePoint(double year); void RemoveAllPoints(); // returns the par rate at the year, interpolated if not explicitly set, // a year <= 0 causes Value::BadValue to be returned. double GetRate(double year) const; // like GetRate() but returns the discount factor double GetFactor(double year) const; /* If the model input type (Factor or Par) does not match the type of rate requested (GetRate() vs. GetFactor()) the model must first be successfully solved using Solve(). Otherwise, Value::BadValue will be returned. */ /* Par rates and discount factors are interpolated differently. Par rates are straight line interpolated while discount factors are fitted exponentially. This produces smooth curves in each case. However, when converting between one curve type and another you must specify points at semi-annual intervals or the different interpolation approaches will result in slightly different curves. That is, if you specify new points using the rates/factors gotten from a curve of a different type, get and use points for each six-month interval. */ // convert between zero and factor rates static double ZeroToFactor(double rate, double year); static double FactorToZero(double discount, double year); // short-rate volatility, 18% represented as 18.0, initialized to zero bool SetVolatility(double); double GetVolatility() const; /* Interest rate model long volatility (30 year) is either determined by a mean reversion factor or by being set explicitly. In the former case the short-term volatility and the mean reversion together determine the long-term volatility. In the latter case the mean reversion is set explicitly. These are mutually exclusive. The default behavior is to use a mean reversion of zero. */ // mean reversion speed, 2% represented as 2.0, initialized to zero bool SetAlpha(double); // forces use of mean reversion double GetAlpha() const; /* explicitly set long volatility, 18% is represented as 18.0. It is NOT RECOMMENDED to set long volatility. Simple volatility and alpha are the recommend approach. Alpha of zero is the default and recommended. */ bool SetLongVolatility(double); // forces use of explicit long volatility /* The long volatility is either explicitly set or solved for based on the mean reversion. See note above. If set explicitly this method returns the user set value. If it must be solved for (alpha/mean reversion mode) then the interest rate model must be solved (see Solve() below) before the long volatility can be returned. */ double GetLongVolatility() const; // get the input curve type -- set in constructor INPUTTYPE GetInputType() const; bool IsParCurve() const { return GetInputType() == PARCURVE; }; /* Solve for the interest rate model from the current configuration. Solve() must be invoked successfully before the InterestRateModel may be used in a Value constructor. Solve() returns the value of Error(). This will be AKA_ERROR_NONE except if a) initialization failed, b) permission is denied, c) curve is incomplete (no points), d) the curve points describe an unsolvable interest environment. */ int Solve(); /* Discount from the time in the future expressed as fractional years, returns Value::BadValue unless Solve() ran successfully */ double Discount(double value, double fromtime, double oas = 0) const; /* Returns the volatility at a time. Returns Value::BadValue unless Solve() ran successfully */ double GetVolatility(double fromtime) const; // Deprecated interface void EnableCompatibility(); // does nothing }; /* Input to convert a 5% callable (NC-10) muni yield curve into optionless par yield curve. See InterestRateModel() constructor above. */ class MuniCurve { public: MuniCurve(); ~MuniCurve(); /* Set a yield on the muni curve, 7% as 7.0. Will fail if year is <= 0, or rate is out of band */ bool SetYield(double year, double rate); // Set the non-call-period for the underlying bonds, default is 10yrs bool SetNonCallPeriod(double); /* Set a non-default coupon for the underlying bond (default 5%); will fail if year does not already have a specified yield or coupon is out of band */ bool SetCoupon(double year, double coupon); // clear the yield and coupon for year void RemovePoint(double year); // see matching functions in InterestRateModel bool SetVolatility(double); bool SetAlpha(double); // forces use of mean reversion bool SetLongVolatility(double); // forces use of explicit long volatility private: friend class InterestRateModel; class MuniCurveData *data; };

Section 5. Bond Definition

The Bond object contains all the properties of a fixed income security. It provides for a minimal initial definition and has Set methods in order to specialize the instrument.

Error checking note: only the constructor can raise an error. The only error conditions are failed initialization or bad dates or coupon as arguments to the constructor. All the Set{} methods will return true/false as described below. In either case they will not set/reset the Error() status.

// forward declare template <class T> class AKAArray; typedef AKAArray<Date> DateArray; class Bond : public Status { private: friend class Value; friend class ValueAfterTax; friend class Compatibility; class BondData *data; public: Bond(const char *name, const Date &idate, const Date &mdate, double coupon); // Note, coupon is a percent, 10.0 is 10% // Also note, see discussion of zero coupon bonds in SetFrequency(), below ~Bond(); Bond(const Bond &); Bond & operator=(const Bond &); // produce an XML representation, for serialization and printing const ConstantString ToXML() const; explicit Bond(const char *XML); // construct from XML // methods to set bond features /* all Set{X}() methods return true/false. If the value is false the set operation has been ignored. A false value is only due to bad/invalid values given to the method. All dates must be valid dates and between the initial date and the maturity date. In addition, all operations will fail if the constructor failed. The Error() status will not be updated by the Set{X}() methods. */ /* The following are the supported day counts. Please see http://kalotay.com/SupportingDocumentation/daycounts.html for fuller documentation. */ enum DAYCOUNT { // needed for yield and accrued interest calculation DC_30_360, /* each month has 30 days and a year has 360 days, applies to most corporate, municipal, and agency bonds */ DC_30E_360, // 30/360 with European treatment of Feb. DC_ACT_360, /* days in month are actual but year has 360 days, applies to U.S. Treasury bills */ DC_ACT_365, /* days in month are actual but year has 365 days, applies to some CDs */ DC_ACT_ACT, /* days in month are actual and coupon period days are actual, applies to U.S. Treasury notes and bonds, and some European sovereign debt issues */ DC_CD_365, /* CD daycounts cause interest cash flows to be proportional to the number of ACT days in the period, i.e., the interest cash flow is the coupon * days-in-period / 365. Note: bonds with CD daycounts always use the CD yield method regardless of the yield method specified. */ DC_30_360_ISDA, // also called, ISDA Bond Basis DC_30E_360_ISDA, DC_NO_LEAP_365, /*The number of days is calculated as the actual number of days between dates without including any occurrences of the leap day, February 29th. This number is divided by 365. */ /* This day count depends on a holiday schedule (see SetHoliday() below) and on weekends being non-business-days (see, SetBusinessDayWeekends() below). */ DC_BUS_252 // business days / 252 }; bool SetDaycount(DAYCOUNT); // constructor defaults to 30/360 enum FREQUENCY { FREQ_INT_AT_MATURITY, /* interest pays at maturity but yield is calculated on an annual basis. */ FREQ_ANNUAL, FREQ_SEMIANNUAL, FREQ_QUARTERLY, FREQ_MONTHLY, FREQ_SEMIANNUAL_COMPOUNDED, FREQ_QUARTERLY_COMPOUNDED }; bool SetFrequency(FREQUENCY); // constructor defaults to semi-annual /* Note, the coupon frequency also applies to zero coupon bonds. Frequency is used to determine yields. Do not use Interest at Maturity for zero coupon bonds. */ bool SetRedemptionPrice(double); // defaults to par /* Note on pre-refunded bonds. These must be characterized as optionless bonds maturing on the "pre-refunded to" date. They should not include calls and puts that may have been part of the original bond. The pre-funded call price should be used as the redemption price. */ bool SetIssuePrice(double); // defaults to par /* Note, for after-tax valuation (see MuniOAS package) it is necessary to set the issue price of Original Issue Discount (OID) bonds in order for valuation to be accurate. */ bool SetFaceAmount(unsigned long); bool SetFaceAmount(double); // for very large numbers under 32 bit /* Since output values are reported in percent of par, face amount is usually unimportant, but it is used for sinking fund bonds. Ideally the sinking fund schedule adds up to the face amount. Otherwise the library does its best to find a reasonable resolution. a) the face amount is zero -- this is the default case -> the sum of the schedule taken as the face -> no warning is issued b) the face amount is less than the sum of the schedule -> the sum of the schedule is taken as the face -> if the difference is > 1%, WARN_SINKSUM_HIGH is issued c) the face amount is greater than the sum of the schedule -> the difference is added to the last flow so that the sum and face are now equal -> if the difference is > 1% WARN_SINKSUM_LOW is issued Note: the only reason to set the face to other than zero is to use the library to catch data errors as the face can be more accurate than the schedule. The constructor defaults the face amount to zero. For mortgages, however, SetFaceAmount() must be used to set the mortgage amount. A nominal value of 100 will otherwise be used. */ /* The next two methods allow specification of odd first and last coupons. They are necessary only if these coupons are odd. The last coupon is the final coupon before maturity. It is not necessary to specify the last coupon if a first coupon is specified and the last coupon is not longer than one regular coupon period. */ bool SetFirstCoupon(const Date &); // set first coupon bool SetLastCoupon(const Date &); // set penultimate coupon /* Configure the End-Of-Month (EOM) rule. By default, EOM is disabled. If EOM is enabled the cyclical coupon payment date will always fall on the end of the month. For example, assume a semiannual bond that matures on 6/30 (or has a last coupon date of 6/30, if specified). It will pay on 6/30 and 12/30 with EOM disabled (the default). It will pay on 6/30 and 12/31 (note, not 12/30) with EOM enabled. The EOM setting is ignored if the payment schedule would never fall on the end of the month. A semiannual bond paying on 6/15 will always pay on 12/15 regardless of the EOM setting. */ bool SetPayDayEndOfMonth(bool); bool SetPayDay(int); // supports interface like C API (see documentation) enum YIELD_METHOD { // the following three yields compound at the bond frequency YLD_BEY = 1, /* Discount cash flows using bond equivalent yield. Example for semiannual 30/360, the yield (y) explaining the input price is given by applying discount factors to each cashflow as 1/(1+y/2)^(days to cashflow/180) */ YLD_SIMPLE_LAST_PERIOD, /* Default method. If the pvdate is in the last coupon period then the yield is calculated on a simple-interest basis, otherwise BEY. */ YLD_SIMPLE_LAST_YEAR, /* If the pvdate is within the last year of a bond's life, then simple interest is used for the cash flows occurring after the pvdate, otherwise BEY. (Used for some Canada bonds) */ // YLD_MUNI, /* Like simple_last_period but has some special treatment if bond has odd first or last coupons. */ // following yields ignore bond frequency when computing yield YLD_ANNUALIZED, YLD_ANNUALIZED_SIMPLE_LAST_PERIOD, YLD_ANNUALIZED_SIMPLE_LAST_YEAR }; /* Note: see discussion of CD yields in DAYCOUNT above, this method will return false if the bond daycount is CD_x */ bool SetYieldMethod(YIELD_METHOD); // set the default yield method // add call/put/sink options bool SetCall(const Date &, double price); bool SetPut(const Date &, double price); // note: SetSink() will fail and return false if PIK is configured bool SetSink(const Date &, double amount, double price = 100); // Set a coupon schedule, for step-up/down coupons bool SetCoupon(const Date &, double); bool SetXCouponDays(int); /* Number of days bond trades ex-coupon (optional; defaults to zero), see notification settings, below. */ /* Note: the following PIK methods will fail and return false if the bond has been configured to be a sinking fund. */ /* Configure the bond to be PIK. The pikrate is expressed as a percent like a coupon. The percent_cash is also a percent and represents what percent of the pikrate must be given in cash. For example, 50% == 1/2, so SetPIK(14, 50) means 7% cash and 7% equity. */ bool SetPIK(double pikrate, double percent_cash = 0); /* Like SetPIK() above but supports multiple PIK rates. A rate goes into effect on the date and remains so until the next PIK schedule date or maturity. */ bool SetPIK(const Date &, double pikrate, double percent_cash = 0); /* Enable PIK payments to be toggled by issuer (see Value::PikToggle()). Non-toggled PIK payments (default) are in addition to the coupon. Toggled PIK payments are in place of the coupon. */ bool PIKToggleAllow(bool); // remove the call/put/sink/coupon/PIK for the date void RemoveCall(const Date &); void RemovePut(const Date &); void RemoveSink(const Date &); void RemoveCoupon(const Date &); void RemovePIK(const Date &); // configure the call/put options /* Notice period must be >= 0 and < coupon frequency, constructor defaults to 30 days, the notice is the same for puts and calls. See notification settings, below. */ bool SetNoticePeriod(int); bool SetOptionDelay(int d) { return SetNoticePeriod(d); }; bool SetCallAmerican(bool is_american); // constructor defaults to true bool SetPutAmerican(bool is_american); // constructor defaults to false /* there are no known examples of American puts but the library accommodates such a case */ /* ALLOCATION configures the designation option in sinking funds. It specifies how bonds purchased by issuer at a discount to satisfy sink are allocated */ enum ALLOCATION { ALLOC_PRORATA, // on a pro-rata basis across sink schedule ALLOC_FRONT, /* to the sink amounts after the pvdate, satisfying as much of the amount as available */ ALLOC_BACK // like front, but working back from maturity }; /* Configure the sinking fund options. Allow delivery allows purchase of discount bonds by issuer to meet sink, defaults to false. Acceleration allows the issuer to sink more than the sink amount on a sink date. Acceleration is a percent where 100 is 100%. 100% allows issuer to sink twice the amount on the schedule on a given date, 200% three times the amount, The default is 0%. Allocation is explained above. Note: SetSinkOption() will fail and return false if PIK is configured. */ bool SetSinkOption(bool allow_delivery, // .. false double acceleration, // .. 0% ALLOCATION allocation); // ... pro-rata // coupon schedule dates can mark when coupon // begins or ends (reset at, or until) bool SetCouponSchedulePeriod(bool at_begin); // default is true /* Configure notification period behavior. This is used for both option notification and ex-coupon days. */ enum NotifyBehavior { /* Extend the end of the notification/ex-coupon period so that it falls on a a business day. This is the default behavior. Example, for a currently callable American call with 30 days required notice, if the 30th day is a weekend (or holiday, if holiday list supplied) then push the next possible call opportunity to the next business day. */ BusinessDaysExtend, /* Only count business days when determining the notification * date. */ BusinessDaysOnly }; // configure the behavior, returns prior setting NotifyBehavior SetNotifyBehavior(NotifyBehavior); /* Set weekends to be business days, returns prior setting. By default weekends are not business days, i.e., SetBusinessDayWeekends(false); Note, if weekends are business days and no holidays are set (see below), notification is simply exact calendar days. */ bool SetBusinessDayWeekends(bool); // set a day to be a non-business day, true if date is valid bool SetHoliday(const Date &); // set an array of dates to be holidays, int must contain the count bool SetHolidays(const Date *, int); bool ClearHolidays(); // remove all set holidays, true unless bond invalid DateArray GetHolidays() const; // get all the holidays set // Predefined holiday lists, see http://kalotay.com/SupportingDocumentation/holidays.html enum HOLIDAYS { HOLIDAYS_US, HOLIDAYS_BRAZIL }; bool SetHolidays(HOLIDAYS); // add predefined holidays static DateArray GetHolidays(HOLIDAYS); // get list of predefined /* Configure a bond to behave like a mortgage. This configures the option and sink schedules so that the bond behaves like a mortgage. Existing sink and option schedules are removed. Step Up/Down coupon schedules are also removed. Subsequent calls to any Set methods for options or sinks will return false and fail. The exception is SetNoticeDays(), see next. SetMortgage() will set the frequency to Monthly unless it has already been set by SetFrequency(). SetFrequency() may also be used after the call to SetMortgage() to reset it. Use SetFaceAmount() to set the mortgage amount. SetMortgage() will always succeed */ bool SetMortgage(); /* Set mortgage amortization years. This will return true if SetMortgage() has been invoked and the years are greater than or equal to the maturity of the bond (mortgage). Otherwise, it will return false. */ bool SetAmortization(double years); /* Set mortgage refinancing fees as a percent of par for "calling" the mortgage. Fees are expressed as points, 1.5% is 1.5. This will return true if SetMortgage() has been invoked. Otherwise it will return false. */ bool SetMortgageRefinanceCost(double); /* Clears mortgage settings and restores functionality of Set methods for Options and Sinks. */ void ClearMortgage(); // return basic setup const char *GetName() const; Date GetInitialDate() const; Date GetMaturityDate() const; double GetCoupon() const; DAYCOUNT GetDaycount() const; FREQUENCY GetFrequency() const; double GetFaceAmount() const; int GetNoticePeriod() const; // presets can be used as a shorthand for certain bond types enum PRESET { // note: all US presets have the US holiday calendar US_CORPORATE, // 30/360, semiannual, bey simple last period yield US_MUNI, // 30/360, semiannual, muni yield US_TREASURYBOND, // ACT/ACT, seminannual, bey simple last period yield BRAZIL_BOND, /* BUS/252, semiannual compounded, annualized yield, Brazilian holiday calendar */ US_CD // CD/365, quarterly, CD yield }; /* Apply the above characteristics to the bond. Subsequent Set methods (e.g., SetFrequency()) will overwrite the preset settings. */ bool ApplyPreset(PRESET); };

Section 6. Valuation

All library valuation results are provided by the Value object.

A Value object can be created with or without an interest rate model. Some valuation methods require that an interest model be present.

The following classes define complex values returned by some methods of the Value class (defined below). These classes could/should be nested in Value however swig which is used to generate cross language interfaces does not support nested classes.

class Duration { // used to return complex value of duration and convexity public: Duration(double d, double c) : duration(d), convexity(c) {}; Duration() : duration(0), convexity(0) {}; double duration; double convexity; // so can use as a double and get just duration operator double() { return duration; }; }; class ScenarioAnalysis { // the result of a scenario analysis public: enum REDEEMED { NOTREDEEMED, CALL, PUT, SINK, MATURITY } redeemed; int flowwhen; // index of flow when redeemed, or index of // first flow after horizon date double efficiency; // efficiency of redemption (call or put) double reinvestment; // value at horizon of intermediary coupon and // principal flows static const char *redeemstring(REDEEMED); const char *redeemstring() const { return redeemstring(redeemed); }; }; class ScenarioHorizon { // values at scenario horizon date public: double interestincome; // sum of intermediary coupon flows double principalincome; // sum of principal flows double price; // bond price at scenario horizon, zero if redeemed double accrued; // bond accrued at horizon, zero if redeemed double outstanding; // outstanding percent at horizon, zero if redeemed };

The following classes define complex inputs to Value methods

// forward declare -- see below class SinkingFundStatus; class InterestRateScenario; class Quote { // used to specify input price or other pricing value public: double quote; enum QuoteType { OAS, PRICE, YTM, YTC, YTP } quotetype; Quote(double q, QuoteType qt) : quote(q), quotetype(qt) {}; }; typedef AKAArray<Duration> DurationArray; typedef AKAArray<double> DoubleArray;

Value provides all library valuation functionality (except for after-tax)

Note on caching and efficiency: this class caches values. Thus, calling Value::<method>() is free the second time. The values cached are based on the last valid OAS. The OAS is reset upon each call to Value::OAS() or Value::Price() and the cache is flushed. Caching is also done separately for yield calculations. These are cached for the last price and yield method used.

class Value : public Status { protected: // disallow copy, assignment Value(const Value &) { }; Value & operator=(const Value &) { return *this; }; protected: class ValueData *data; public: // construct a Value without an InterestRateModel, not all valuation // methods are supported Value(const Bond &, const Date &pvdate); Value(const Bond &, const Date &pvdate, const Date &tradedate); // construct a Value with an InterestRateModel Value(const Bond &, const InterestRateModel &, const Date &pvdate); Value(const Bond &, const InterestRateModel &, const Date &pvdate, const Date &tradedate); // construct a Value with an InterestRateModel and additional sinking // fund information Value(const Bond &, const InterestRateModel &, const SinkingFundStatus &, const Date &pvdate); Value(const Bond &, const InterestRateModel &, const SinkingFundStatus &, const Date &pvdate, const Date &tradedate); /* Tradedate and Settlement Days Each constructor comes in two flavors: with and without a tradedate. Specifying a tradedate affects the option notice period and ex-coupon days in effect at the pvdate. The days are counted from the tradedate rather than the pvdate. The tradedate must be less than the pvdate and no more than 31 days before the pvdate. Invalid tradedates cause a warning and are then ignored. A tradedate equal to the pvdate is the same as no tradedate and is silently accepted. Note, pvdate is synonymous with settlement date. */ ~Value(); // destructor /* Use the Error() method inherited from the Status object to check the state after the last operation. This must be checked after construction and reset(). Warnings() should also be checked. Most subsequent operations will succeed if the construction succeeded. Operations after initialization may also produce warnings. */ // Like the constructors, returns Error() for convenience. int Reset(const Bond &, const Date &pvdate); int Reset(const Bond &, const Date &pvdate, const Date &tradedate); int Reset(const Bond &, const InterestRateModel &, const Date &pvdate); int Reset(const Bond &, const InterestRateModel &, const Date &pvdate, const Date &tradedate); int Reset(const Bond &, const InterestRateModel &, const class SinkingFundStatus &, const Date &pvdate); int Reset(const Bond &, const InterestRateModel &, const class SinkingFundStatus &, const Date &pvdate, const Date &tradedate); // constants static const double BadValue; /* number returned by all valuation routines if the valuation failed. Error() should be checked for an explanation */ /* This method must be used instead of comparing directly to BadValue when the library is used as a Windows dll due to dll issues with exporting variables. */ static bool IsBadValue(double v); Date PVDate() const; // returns pv date in use // Bond fundamentals, do not require an interest rate model /* returns number of coupon/option/principal flows, 0 indicates a bond configuration error, last flow is always maturity */ int FlowCount() const; enum FLOWTYPE { // a flow will be one or more the following INTEREST = 1, // coupon payment PRINCIPAL = 2, // maturity or sinking fund date CALLOPTION = 4, // call option date (and subsequent flows if American) PUTOPTION = 8, // put ... PSEUDO_REGULAR = 16 /* for irregular coupons this indicates the date of where the regular coupon would fall, it is not an actual interest payment */ }; int FlowType(int) const; /* returns bitwise-or'd flags of one or more of the above types */ bool FlowType(int idx, FLOWTYPE t) const { return (FlowType(idx) & t) != 0; }; int FirstFlow() const; // index of first flow after pvdate Date FlowDate(int) const; // date of flow double YearsTo(int) const; // year fractions to flow from pvdate // NOTE: following are quoted like prices, i.e, in percent of par // interest payment on flow, relative to par, 5% coupon == 5.0 double Interest(int) const; double Principal(int) const; /* principal payment on flow, this is the PrincipalPrice() * PrincipalAmount() */ double Accrued(int) const; // accrued on flow, 0 on interest flows, 5% == 5 // NOTE: percents are true percents, 100% = 1.0 double InitialOutstandingPercent() const; // outstanding percent at pvdate double OutstandingPercent(int) const; /* outstanding percent at a flow _prior_ to any principal flows */ double PrincipalPercent(int) const; /* percent of principal flowed at this flow, returns value between 0 and 1, inclusive. */ double PrincipalPrice(int) const; /* price at which principal flow occurs, 0 if not a principal flow, normally 100, but can be sink price or redemption value other than 100. */ double CallPrice(int) const; // call price at flow or BadValue double PutPrice(int) const; // put price at flow or BadValue const char *BondName() const; // name of bond // PV Date based values, do not require an interest rate model double Accrued() const; // accrued at pvdate int AccruedDays() const; // accrued days on pvdate double AccruedOn(const Date &); // Yields, do not require an interest rate model bool SetYieldMethod(Bond::YIELD_METHOD); // set the yield method, cached // yield values will be flushed Bond::YIELD_METHOD GetYieldMethod() const; /* get current yield method, default is how Bond was set */ double YieldToCall(double price); double YieldToPut(double price); double YieldToMaturity(double price); /* Given a price, return the worst yield at that price, the second form sets the index of the worst flow, if also_to_sink is true, sinking fund principal flows are included as candidates. Results are cached so that consecutive calls with the same yield are free, i.e., YieldToWorst(10) followed by YieldToWorstFlow(10) costs the same as YieldToWorstFlow(10, flowindex) */ double YieldToWorst(double price, bool also_to_sink = false); double YieldToWorst(double price, int &flowindex, bool also_to_sink = false); int YieldToWorstFlow(double price, bool also_to_sinks = false); double WeightedAverageMaturity(double price); Duration ModifiedDuration(double price); // Calculate yields to a particular flow -- will return BadValue // unless the flow has an option or principal payment. // Note, this result is not cached. double YieldToFlow(int, double price, bool as_cashflow_yield = false); // given a price and a yield, compute modified duration to a flow, // like YieldToFlow(), flow must have an option or principal payment Duration ModifiedDurationToFlow(int flowindex, double price, double yield); // convert yields to a price, can also use Price(Quote) method double ytm2price(double); double ytc2price(double); double ytp2price(double); // Complex Valuations, require an interest rate model double Price(double oas); double Price(Quote); double PVInterest(Quote); // present value of interest cash flows double PVPrincipal(Quote); // present value of principal cash flows // note: PVInterest(qt) + PVPrincipal(qt) - Accrued() = Price(qt) double OAS(double price); double OAS(Quote); /* Expected life of bond in years. Will be time to maturity for optionless bonds, otherwise may be shorter depending on redemption due to calls, puts, or sink acceleration. */ double ExpectedLife(Quote); double OptionValue(double oas); double OptionValue(Quote); /* Calculate price to a particular flow given a yield to that flow -- will return BadValue unless the flow has an option or principal payment. Note, this result is not cached. */ double PriceToFlow(int flowindex, double yield, bool as_cashflow_yield = false); /* Given a yield, compute the worst price at that yield, and the flow at which that worst price occurs. If also_to_sink is true, sinking fund principal flows are included as candidates. The three forms below return the price, the flowindex, or both the price and the flowindex, with the flowindex in a non-const reference variable. Results are cached so that consequtive calls with the same yield are free, i.e., PriceToWorst(10) followed by PriceToWorstFlow(10) costs the same as PriceToWorst(10, flowindex) */ double PriceToWorst(double yield, bool also_to_sinks = false); double PriceToWorst(double yield, int &flowindex, bool also_to_sinks = false); int PriceToWorstFlow(double yield, bool also_to_sinks = false); // effective duration and convexity Duration EffectiveDuration(double oas, double durationbp = 30); Duration EffectiveDuration(Quote, double durationbp = 30); // one-sided durations double UpDuration(double oas, double durationbp = 30); double DownDuration(double oas, double durationbp = 30); double UpDuration(Quote, double durationbp = 30); double DownDuration(Quote, double durationbp = 30); /* Key rate duration measures the sensitivity of the bond's value to a shift in a specified year's yield. The key rate is not shifted in isolation; rather, the rates around it are "tented" with the key year at the center. The tenting process keeps rates unchanged at anchor points (years) on either side of the key rate and interpolates the rates between the anchor points and the key rate. The different flavors of KeyRateDuration(), below, control the anchor points. */ /* Terms is an array of terms (in years) -- these are the key rates used. An array of durations of the same size is returned. The tented rates are anchored (see above) at the previous and next terms in the terms array. The first term is left-anchored at zero, and the last is right-anchored at past the maturity of the instrument. If scale is true (the default) the resulting durations are slightly smoothed (scaled) so that the sum of the durations equals the effective duration. */ DurationArray KeyRatesDurations(Quote, double durationbp, const DoubleArray &terms, bool scale = true); /* The following KeyRateDuration() methods work on a single term and differ on how the tenting is done. The above method is the recommended approach. */ // anchor at years +/- sqrt(year), anchors rounded to semi-annual Duration KeyRateDuration(double oas, double durationbp, double year); Duration KeyRateDuration(Quote, double durationbp, double year); // anchor at years +/- width, anchors rounded to semi-annual Duration KeyRateDuration(double oas, double durationbp, double year, double width); Duration KeyRateDuration(Quote, double durationbp, double year, double width); // anchor at specified years, anchors rounded to semi-annual Duration KeyRateDuration(double oas, double durationbp, double year, double leftanchoryear, double rightanchoryear); Duration KeyRateDuration(Quote, double durationbp, double year, double leftanchoryear, double rightanchoryear); // see InterestRateModel::Discount(), GetRate(), GetFactor() double Discount(double value, double fromtime, double oas = 0) const; double GetRate(double year) const; double GetFactor(double year) const; // scenario Analysis, if false, Error() has been set bool AnalyzeScenario(const InterestRateScenario &, double oas, ScenarioAnalysis &); bool AnalyzeScenario(const InterestRateScenario &, Quote, ScenarioAnalysis &); bool AnalyzeScenario(const InterestRateScenario &, Quote, ScenarioAnalysis &, ScenarioHorizon &); /* Solve for a single fixed spread such that if the same spread is added to each coupon in the coupon schedule of the bond, then the clean price of the bond, computed using the tree with zero OAS, is equal to clean_price provided as input. */ double AssetSwapSpread(double price); /* Compute the I-Spread. This is the difference between the YTM of a bond at the provided price, and the yield on the weighted-average-maturity-matched point on the provided yield curve. The yield will be straight-line interpolated between points on the provided curve. Industry refers to this spread as I-Spread if swap curve provided and G-Spread if government curve (treasuries) provided. */ double ISpread(double price); /* Enable or disable all PIK flows. Returns false if bond is not a toggled PIK bond. Note, Toggled PIK bonds with all PIK flows disabled are equivalent to non-PIK bonds. */ bool PIKToggle(bool); /* Enable/disable PIK for flow on date. Returns false if bond is not a toggled PIK bond. Also returns false if date is prior to pvdate or date is not an interest flow date. Date can be within two days of a flow to allow for loose periodicity. */ bool PIKToggle(const Date &, bool); // Same as above, but accepts a flowindex rather than a date. bool PIKToggle(int flowindex, bool); };

support classes for Value

Sinking fund bonds have additional market information that determines pricing. This information is only required/meaningful for sinking fund bonds and is optional even then. Note: doubles are used to accommodate very large numbers

class SinkingFundStatus { public: double outstanding; /* The outstanding amount must be reconciled with the sinking fund schedule. The sum of the schedule after the pvdate is the remaining sink amount. The following cases apply: a) outstanding amount is zero -> outstanding is set to remaining sink amounts -> no warning is issued b) the outstanding amount equals the remaining amount (+/- 0.1 %) -> outstanding is set to remaining -> no warning is issued c) remaining < outstanding (+ 0.1 %) -> outstanding is set to remaining -> issue AKA_WARN_OUTSTANDING_HIGH d) remaining > outstanding amount -> using allowable acceleration try to reduce remaining flows to match outstanding -> designate reduction to flows per designation method (prorata/front/back) - prorata is default -> if reduced remaining is still > outstanding then issue AKA_WARN_SINK_UNDESIGNATED -> set outstanding to recomputed remaining Note: Case d might happen if there has been optional additional redemption (acceleration), extraordinary redemptions (triggered by certain events in the bond's indenture), or by buybacks by the issuer, and the data vendor has not updated the sink schedule accordingly. */ double accumulation; /* Amount in dollars held by accumulators, if not provided, will be zero. */ public: SinkingFundStatus(unsigned long os, unsigned long ac) : outstanding(os), accumulation(ac) {}; SinkingFundStatus(double os, double ac) : outstanding(os), accumulation(ac) {}; // construct so uses default behavior SinkingFundStatus() : outstanding(0), accumulation(0) {}; };

Define an interest rate scenario for analysis. An interest rate scenario requires at minimum one interest rate model. The base Value class interest rate model is transformed over time into the models in the scenario. The bond is valued at each of its flows in order to determine whether it is redeemed.

class InterestRateScenario { protected: // disallow copy, assignment InterestRateScenario(const InterestRateScenario &) { }; InterestRateScenario & operator=(const InterestRateScenario &) { return *this; }; protected: friend class Value; class InterestRateScenarioData *data; public: enum SCENTYPE { // When scenario shifts occur NOW, // Suddenly at time 0 GRADUAL, // Linearly in time, this can be slow THEN // Suddenly at horizon }; // create with at least one interest rate environment at // years in the future, years does not have to be a whole number InterestRateScenario(double years, const InterestRateModel &horizonmodel, SCENTYPE = NOW); ~InterestRateScenario(); /* add an interest rate environment between the start and the horizon to fine tune how interest rates transition over time. Will return false if InterestRateModel is unsolved */ bool AddTransition(double years, const InterestRateModel &); // efficiency threshold for option exercise, default is 100% // must be > 0 and <= 100 bool SetEfficiencyThreshold(double); /* Scenario analysis is normally based on input yield curves and the input OAS. If OAS is negative, zero OAS is assumed */ void SetReinvestStandard(); // default behavior /* The initial OAS may not be appropriate for subsequent curves in the scenario. The user can suppress using the OAS after the start date. */ void SetReinvestAtZeroOAS(); /* Finally, the reinvestment can be done at a fixed rate. In this case option decisions are still made using the OAS */ void SetReinvestAtFixed(double); };

Section 8. Supporting Classes

The following classes are used to support other fundamental objects in the API

This object handles validation and construction of a date representation from a variety of forms. It also provides simple date math. The constructor will always succeed, however invalid input will result in the invalid date of zero.

Note, the C library API expresses dates as 8-digit longs in the form yyyymmdd. This object also supports translation from/to that form.

class Date { private: long _data; public: enum ENTRY { // order of pieces passed to constructor YMD, // sortable MDY, // American DMY // European }; Date(int, int, int, ENTRY = YMD ); // construct from pieces /* construct a date from a string ordered via entry and with the pieces separated by sep. If sep is not found assumes (for historical reasons) that string is yyyymmdd and ignores ENTRY. */ Date(const char *, ENTRY, char sep = '/'); Date(long = 0); // construct a date from a long /* construct a date by adding fractional years according to daycount to the given Date. Years can be negative, Note, this does not work for Business Days / 252, and will treat that daycount as if it were ACT/ACT. */ Date(const Date &, double yrs, Bond::DAYCOUNT); bool Good() const; // whether date is valid // C API date format, yyyymmdd as a long long Libdate() const { return _data; }; int DayOf() const { return ((int) (_data) % 100); }; int MonthOf() const { return (((int) (_data) / 100) % 100); }; int YearOf() const { return ((int) (_data) / 10000); }; /* returns time from date to other (i.e. other - this) in fractional years according to the daycount. Note: this does not work for Business Days / 252, and will return an ACT/ACT year fraction. */ double YearsTo(const Date &other, Bond::DAYCOUNT) const; // compute calendar days between dates int DaysTo(const Date &other) const; Date & operator +=(int); Date & operator -=(int days) { return *this += -days; }; bool operator <(const Date &other) const { return Libdate() < other.Libdate();}; bool operator <= (const Date &other) const { return Libdate() <= other.Libdate();}; bool operator == (const Date &other) const { return Libdate() == other.Libdate();}; bool operator >= (const Date &other) const { return Libdate() >= other.Libdate();}; bool operator > (const Date &other) const { return Libdate() > other.Libdate();}; };

This object handles memory for a constant string. Methods that return strings may return this. This object may be safely copied, and assigned. The memory handling is transparent. Note, it cannot be constructed.

class ConstantString { private: class ConstantStringData *data; ConstantString(const char *, long); // made privately, used publicly friend class InterestRateModel; friend class Bond; public: ConstantString(const ConstantString &); ConstantString & operator=(ConstantString &); ~ConstantString(); /* Returns pointer to the string. Note: The returned pointer will cease to valid if the object goes out of scope. I.e., use this as a temporary. */ const char *String() const; operator const char *() const { return String(); }; // length of string long Length() const; };

Section 9. Arrays

The following is a template class for very simple arrays used to pass and return API objects and fundamental types. std::vectors are avoided in order to avoid dependencies on the std C++ library.

This template should not be used directly. Typedef'd specific instantiations are specified above, where needed.

template <class T> class AKAArray { public: explicit AKAArray(unsigned int sz = 0) : size(sz) { Alloc(); }; AKAArray(const AKAArray<T> &); const AKAArray<T> & operator=(const AKAArray<T> &other); ~AKAArray() { DeAlloc(); }; unsigned int Size() const { return size; }; // NOTE: these are not bounds checked and do not grow the array. const T & operator[](unsigned int index) const { return array[index]; }; const T & Get(unsigned int index) const { return array[index]; }; T & Set(unsigned int index, const T &v) { return array[index] = v; }; T & operator[](unsigned int index) { return array[index]; }; /* shrink/grow the array. Growing is expensive; iteratively growing is very inefficient. Shrinking is free, however the memory is not recovered until the object is destroyed. */ void ReSize(unsigned int sz); private: unsigned int size; T *array; private: void Alloc(); void DeAlloc(); };

Index of Classes

Bond
ConstantString
Date
Duration
Initialization
InterestRateModel
InterestRateScenario
MuniCurve
Quote
ScenarioAnalysis
ScenarioHorizon
SinkingFundStatus
Status
Value

C++/C Compatibility — akaapi_compatibility.hpp

* Copyright (c) 2013, Andrew Kalotay Associates. All rights reserved. *

#include "akaapi.hpp" #include "akaapi.h" Note: all objects are defined within the namespace 'AndrewKalotayAssociates'

Overview

The C language API is defined in akaapi.h. The C++ API provides all the functionality of the C API, however, it may be useful when migrating code to use to both APIs in a mixed model. The compatibility layer support this approach.

// allows akaapi C API functions to be intermixed with the C++ API. class Compatibility { public: /* Provide C API interest rate tree handle so that C API functions can be used. Solve() must have been successfully invoked on the InterestRateModel or else a tree handle of zero (no tree) will be returned. IMPORTANT: This method should only be used to get the AKAHTREE as a temporary. Using a Set{x}() method on, or deleting the InterestModel object which returned the TreeHandle invalidates the returned handle. The returned TreeHandle should never be released (i.e., do not call AKATreeRelease()). */ static AKAHTREE CApiTreeHandle(const InterestRateModel &); /* Provide C style structure so that C API functions can be used. This returns a constant pointer to constant memory. The memory points to an AKA Library C AKABOND structure. IMPORTANT: This method should only be used to get the C structure as a temporary. Using a Set{x}() method on, or deleting the Bond object which returned the AKABOND structure invalidates the returned structure. The returned structure should never be freed (i.e., do not call AKABondFree()). */ static const AKABOND* const CApiBond(const Bond &); /* Provide C style structure so that C API functions can be used. This returns a constant pointer to constant memory. The memory points to an AKA Library C AKACURVE structure. IMPORTANT: This method should only be used to get the C structure as a temporary. Using a Set{x}() method on, or deleting the InterestRateModel object which returned the AKACURVE structure invalidates the returned structure. The returned structure should never be freed (i.e., do not call AKACurveFree()). */ static const AKACURVE* const CApiCurve(const InterestRateModel &); /* Create an InterestRateModel from a C API AKACURVE. The resulting InterestRateModel still needs to be solved. The returned object is a new object and may be freely assigned and used. */ static InterestRateModel ModelFromCurve(const AKACURVE *); /* Create a C++ API Bond from a C API AKABOND. The returned object is a new object and may be freely assigned and used. */ static Bond BondFromBOND(const AKABOND *); };

Section 1. Calling C Functions with C++ Objects

Invoking a C API function using C++ objects is supported with Compatibility methods. For example:

Date pvdate; InterestRateModel model; Bond bond(...); ... // initialize the objects model.Solve(); AKABONDREPORT report; // old style report structure AKABONDVAL(pvdate.Libdate(), AKA_QUOTE_PRICE, 100, Compatibility::CApiTreeHandle(model), Compatibility::CApiBond(bond), &report);

Section 2. Creating C++ Objects from C Structures

The C++ API objects can be created from already initialized C structures. For example:

AKACURVE *curve = AKACurveAlloc(10); AKABOND *cbond = AKABondAlloc(1, 0, 0, 0); ... // initialize the structures InterestRateModel model = Compatibility::ModelFromCurve(curve); AKACurveFree(curve); // curve may be freed, it is not referenced in model model.Solve(); // model must be solved before it can be used Bond bond = Compatibility::BondFromBOND(cbond); // assign from C structure AKABondFree(cbond); // cbond may be freed, it is not referenced in bond Value value(bond, model, Date(2013, 10, 12)); // create value object

Section 3. Mixed Model Issues

There are two potential problems when mixing the C and C++ APIs.

The library initialization must be done using the C++ API Initialization object or the C++ API will not function correctly. The C++ initialization will enable the C API.

Error handling in the C API is on a global basis. If a C function is used the C API error interfaces AKAError() and AKAWarnings() must be called immediately afterward or any errors/warnings will be lost or confused with subsequent operations.

Section 4. C++ API to C API Correspondence

In most cases the values stored in C report structures have a recognizable one-to-one correspondence to methods of the Value object. The method names follow C++ naming conventions and so vary slightly from the C structure member names.

a) The method names are consistently title capitalized. E.g., the C report structure member accrued becomes the method Accrued() and price becomes Price().

b) The method names are fully instantiated. E.g., the C report structure member ytc becomes the method YieldToCall() and modDur becomes ModifiedDuration().

The remainder of this document describes cases where there is not an exact correspondence.

Section 5. Flow Reports

All the flows for an instrument can be gotten by using the Flow() access methods in Value. These can be used as is or discounted using the Discount() method. The Scenario Analysis section below has an example of how to walk the flows.

Section 6. Scenario Analysis

The Value::AnalyzeScenario() provides the redemption information and the reinvestment income. The remainder of the values can be calculated using other Value methods. The initial price, accrued, duration, etc., is returned by the same Value object used for AnalyzeScenario(). The horizon values can be computed by creating a new Value object with the horizon Interest Rate Model. The summed principals and coupon income at the horizon can be computed by walking the bond flows. For example:

double outstanding = 1; double remaining = 1; // these two handle sinking funds for (int f = 1; f < value.FlowCount(); f++) { if (value.FlowDate(f) > horizondate) break; if (f < value.FirstFlow()) // calculate outstanding outstanding -= value.Principal(f); else { if (f == value.FirstFlow()) // keep track of remaining remaining = outstanding; // always get coupon on the flow couponincome += value.Interest(f); if (f == analysis.flowwhen) { // done // if balance is gone, get any accrued couponincome += value.Accrued(f); // default final price is sink or redemption double atprice = value.PrincipalPrice(f); if (analysis.redeemed == ScenarioAnalysis::CALL) atprice = value.CallPrice(f); else if (analysis.redeemed == ScenarioAnalysis::PUT) atprice = value.PutPrice(f); // note, using remaining in case of sinking fund principalincome += atprice * remaining / outstanding; remaining = 0; break; } else { // just a regular flow, only for sinks principalincome += value.PrincipalPrice(f) * value.Principal(f) / outstanding; remaining -= value.Principal(f); } } } Please see additional scenario analysis example code in the example directory of the release.

Index of Classes

Compatibility

Java API

BondOAS™ provides a Java API. The API exactly follows the C++ API except for operator method names (see below). The class files and the bodoas.jar file are in the java directory of the release. The akalib/java/bondoas.jar file is created by compiling the .java files in the akalib/java directory and assembling the .jar file. The package path used is com/kalotay/akalib. Both the compiled jar file and the java sources are provided in akalib/java.

C++ operator methods such as += or < do not translate. All such operators have been consistently renamed as follows:

C++ OperatorJava Method
operator+=PlusEqual
operator-=MinusEqual
operator<IsLT
operator<=IsLE
operator==IsEq
operator>=IsGE
operator>IsGT

A dynamic library bondoas_java_wrap is provided in the architecture appropriate lib directory of the release. The bondoas.jar file can be used in your java project. Before objects in the jar file can be used, you must dynamically load the bondoas_java_wrap dynamic library. If your path is set up approriately so that the Andrew Kalotay Associates library for the appropriate architecture can be found, the load instruction looks like: System.loadLibrary("bondoas_java_wrap");

C# API

BondOAS™ provides a C# API. The C# API exactly follows the C++ API. The C# class files are in the csharp directory of the release. These need to be compiled. The C# classes explicitly load the Andrew Kalotay Associates C# API dynamic library bondoas_csharp_wrap. This dynamic library is provided in the architecture appropriate lib directory of the release.

.Net

These instructions apply to using the Andrew Kalotay Associates C# API under Windows for a .NET application.

The .cs files in the akalib/csharp directory need to be compiled. They can either be imported directly into your project or they can be separately compiled into a .NET dll. In the latter case, that compiled dll can then be referenced in a project.

Note, It is not necessary (and does not work) to directly reference the akalib library dlls in a .NET project. The code in AkaApiPINVOKE.cs dynamically loads the appropriate Andrew Kalotay Associates bondoas dlls. The path to the Andrew Kalotay Associates bondoas dlls, (e.g., akalib/lib/win64) must be in your path at runtime.

C API — akaapi.h

* Copyright (c) 1995-2012, Andrew Kalotay Associates, Inc.. All rights reserved. *

Overview

This file contains the function prototypes, structure definitions, and constants needed for invoking BondOAS™. This file also serves as documentation for the API. It is arranged in the following sections:

  1. General Notes
  2. Initialization and Shutdown
  3. Tree Creation
  4. Valuation
  5. Bond Structure Configuration Functions
  6. Miscellaneous Functions
  7. Error Handling
  8. Memory Allocation and Free
  9. Data Structures and Constants
  10. Deprecated Functions

Section 1. General Notes

BondOAS™ is a multi-thread safe C library. Library interface calls take objects in the form of C structures. These structures are described below. All structures are documented.

All dates are expressed as 8-digit longs in the form yyyymmdd. Percentages are expressed as x 100. I.e., 10% is 10 rather than 0.10.

All AKA structures which have allocators (e.g., reports, AKABOND, etc.) must be allocated using the library provided allocation functions only. Using stack local variables or directly allocating the structures via malloc will cause unexpected results and memory errors. The only stack safe report structure is AKABONDREPORT.

Section 2. Initialization and Shutdown

One of the initialization functions must be called before the library may be used.

The library requires a valid user name and key to run. These must be provided to the initialization routines. The user name and key are authorization keys provided to authorized users by AKA.

The initialization routines return an AKA_ERROR code. Any code but AKA_ERROR_NONE is a failure. The return code must be checked; continuing to call BondOAS routines after init fails will not work. Similarly, calling a BondOAS routine prior to a valid initialization will not work.

One of the shutdown functions should be called after the library use is finished. Memory will be lost if this is not done.

The initialization function should not be called more than once. It is valid to call the initialization function again if the shutdown function has been called. This is not recommended as initialization and shutdown functions require cycles.

MULTI-THREAD note: only one thread may call the initialization function. The initialization function creates BondOAS mutex. Calling the shutdown function while other threads are still running BondOAS routines is not safe. The configuration settings used in the init function are inherited by each thread. The duration global settings can be reset on a per thread basis, see AKA_set_duration_shift().

typedef struct AKAInitData AKAINITDATA; /* The initialization routines return an error code. A value other that AKA_ERROR_NONE is a failure. AKA_initialize() uses default configuration values; see AKAINITDATA below. */ long AKA_initialize(long key, const char *uname); long AKA_initialize_configure(long key, const char *uname, AKAINITDATA *config); /* Gets the default initialization configuration values and assigns them to the passed in configuration structure. */ void AKA_initialize_get_defaults(AKAINITDATA *config); /* Returns expiration of key; only valid after call to init, */ void AKA_authorize_expiration_date(int *year, int *month, int *day); /* Shutdown the library, free internal memory */ void AKA_shutdown(); /* Shutdown the library */ void AKA_shutdown_configure(int unused); /* The variable, AKA_memory_diagnostics_enabled, controls whether all memory allocations in library routines are wrapped in a memory diagnostics counter. Enabling memory diagnostics allows the user track library memory usage. The variable must be set to one prior to library initialization in order for memory diagnostics to be enabled. Enabling memory diagnostics will impact performance of multi-threaded invocations of the BondOAS library. */ extern int AKA_memory_diagnostics_enabled; /* Provides diagnostics information on library memory usage. Allocations, total_memory, and trees are a snapshot of usage when the function is called. The numbers are for unfreed allocations and unreleased trees. After shutdown, all the numbers should be zero. This routine is multi-thread safe. Note, allocations and total_memory will always be zero unless AKA_memory_diagnostics_enabled is set. */ void AKA_memory_diagnostics(unsigned long *allocations, unsigned long *total_memory, unsigned long *trees);

Section 3. Tree Creation

Trees are interest rate lattices used to value instruments. The first step in any valuation is to create a tree using one of the tree fit routines below.

These return an AKAHTREE which is a library internal reference. The user is given the handle to pass to other routines. This is not a pointer. The AKATreeRelease() routine frees internal library memory. After AKATreeRelease(), the handle is no longer valid. Un-released trees will cause memory leaks. An AKAHTREE of zero indicates failure and is not a valid tree.

MULTI-THREAD note: the tree handle may be shared across threads. Freeing the handle via AKATreeRelease() more than once is not safe. Freeing the handle while it is in use by multiple threads is not safe.

Performance Note: When AKABondVal() and AKABondVal2() is used to compute par duration, the library will internally attempt to fit trees. The handles to these trees are not exposed to the caller. They will be cached internally with the tree structure.

typedef unsigned long AKAHTREE; /* Returned from tree fit routines */ /* forward declarations -- definitions in structures section below */ typedef struct AKACurve AKACURVE; typedef struct AKASpreads AKASPREAD; /* Fit trees from yield curves; spread curves are optional, pass as NULL */ AKAHTREE AKATreeFit(const AKACURVE *crv, const AKASPREAD *spr); /* Fit a tree from another tree and a spread curve */ AKAHTREE AKATreeFitSpreads(AKAHTREE tree, const AKASPREAD *spr); /* Fit a tree from another tree and a shift of the zero or par curve. bpShift of 20 means 20 basis points. Select mode from AKAShiftMode defined below. Using SHIFT_NONE here is an error. */ AKAHTREE AKATreeFitShift(AKAHTREE tree, double bpShift, long mode); /* Fit a tree from a yield curve using zero volatility. For computing Z-Spread. Z-Spread is the zero-volatility OAS of a bond given its price. */ AKAHTREE AKATreeFitZero(const AKACURVE *crv); /* Return the minimum rate on a tree (.10 is 10%) -1 is error */ double AKATreeMinRate(AKAHTREE hTree); /* Release a tree handle returned by one of the tree fit routines */ void AKATreeRelease(AKAHTREE tree);

Section 4. Valuation

These routines value bonds.

There are two types of valuation routines.

  1. Simple Valuation -- return a single value through the function return
  2. Report Based -- return multiple values via a report structure

Simple Valuation routines return their answer as the function return value. Error return values are as described below. These routines also set the error handling flags like the Report Based routines.

Report Based routines require a report structure to be passed in. All report structures except AKABONDREPORT must be created with the appropriate allocation function and must be freed with the corresponding free function. The return code for report based functions is not used. See the error handling section below for checking errors.

MULTI-THREAD note: AKAHTREE may be shared across threads. Pointers to AKABOND and AKASCEN are to const objects in these functions and therefore may be shared across threads. However, changing the values of an AKABOND or AKASCEN while it is in use by another thread violates the const requirement and is not thread safe.

/* forward declarations -- definitions below */ typedef struct AKABond AKABOND; typedef struct AKAScen AKASCEN; typedef struct AKAScenSetup AKASCENSETUP; typedef struct AKABondReport AKABONDREPORT; typedef struct AKABondYieldReport AKABONDYIELDREPORT; typedef struct AKAFlowReport AKAFLOWREPORT; typedef struct AKAFwdReport AKAFWDREPORT; typedef struct AKAKRDurReport AKAKRDURREPORT; typedef struct AKAkrdursetup AKAKRDURSETUP; typedef struct AKAScenReport AKASCENREPORT; typedef struct AKAVolReport AKAVOLREPORT; typedef struct AKAYldWorst AKAYLDWORST; typedef struct AKAPrcWorst AKAPRCWORST; typedef struct AKAAtaxYld AKAATAXYLD; typedef struct AKAAtaxBasis AKAATAXBASIS; /* SIMPLE VALUATION routines */ /* Price a bond; returns price; -1 indicates an error */ double AKABondPrice(long pvdate, AKAHTREE hTree, const AKABOND *bond, double oas); /* Compute the OAS for a bond; returns OAS; -99999 indicates an error */ double AKABondOAS(long pvdate, AKAHTREE hTree, const AKABOND *bond, double price); /* Determine accrued for a bond - returns accrued; -1 indicates an error */ double AKABondAccrued(long pvdate, const AKABOND *bond); /* Determine accrued and accrued days for a bond. Returns 1 on success, 0 on an error */ double AKABondAccrued2(long pvdate, const AKABOND *bond, double *accrued, int *accrued_days); /* Spot shift (see AKAShiftMode, below) a tree <treeshift> basis points then value a bond; returns price; -1 indicates an error */ double AKABondPriceShifted(long pvdate, AKAHTREE hTree, const AKABOND *bond, double oas, double treeshift); /* convert between price and yield. Select cnvfrom/cnvto from AKAQuoteType defined below. AKAQuoteType OAS is not supported for price conversion. To convert from OAS use AKABondVal(). Returns: value in cnvto units; -99999 indicates an error. */ double AKABondPriceCnv(long pvdate, long cnvfrom, long cnvto, double quote, const AKABOND *bond); /* Solve for a single fixed spread such that if the same spread is added to each coupon in the coupon schedule of the bond, then the clean price of the bond, computed using the tree with zero OAS, is equal to clean_price provided as input. Returns: this spread, in basis points, with sign reversed -99999 indicates an error. */ double AKAAssetSwapSpread(double clean_price, long pvdate, AKAHTREE hTree, const AKABOND *bond); /* Compute the price of a bond at zero OAS when the input asset_swap_spread is applied. Returns: the clean price -99999 indicates an error */ double AKAConvertAssetSwapSpread(double asset_swap_spread, long pvdate, AKAHTREE hTree, const AKABOND *bond); /* Compute the I-Spread. This is the difference between the YTM of a bond at the provided price, and the yield on the weighted-average-maturity-matched point on the provided yield curve. The yield will be straight-line interpolated between points on the provided curve. Industry refers to this spread as I-Spread if swap curve provided and G-Spread if government curve (treasuries) provided. Returns: this spread, in basis points, -99999 indicates an error. */ double AKAISpread(const AKABOND *bond, long pvdate, double price, const AKACURVE *crv); /* Discount the provided value to now from the time in the future expressed as fractional years using the rates in the tree. */ double AKADiscount(AKAHTREE hTree, double oas, double value, double fromtime); /* REPORT STRUCTURE BASED VALUATION routines */ /* Value a bond and fill out all fields in the bond report (see bond report definition below). Select quoteType from AKAQuoteType */ long AKABondVal(long pvDate, long quoteType, double quote, AKAHTREE hTree, const AKABOND *bond, AKABONDREPORT *rpt); /* Like AKABondVal() but allows configuration of which bond report values to calculate. See the definition of the bond report below to understand which values are calculated. Set value_x to 1 to value, zero to not value. */ long AKABondVal2(long pvDate, long quoteType, double quote, AKAHTREE hTree, const AKABOND *bond, AKABONDREPORT *rpt, int value_option, int value_duration, int value_yield); /* Like AKABondVal3() but w/ a single control flag of or'd values */ enum { AKABONDVAL_DURATION = 1, AKABONDVAL_OPTION = 2, AKABONDVAL_YIELDS = 4 }; long AKABondVal3(long pvDate, long quoteType, double quote, AKAHTREE hTree, const AKABOND *bond, AKABONDREPORT *rpt, void *reserved, /* use NULL for reserved */ int value_what_flag); /* Perform scenario analysis for a bond over a series of interest rate scenarios (usually two). See the definitions of AKASCENSETUP and AKASCENREPORT, below, for details of the inputs and outputs. */ long AKABondScenEx(long quoteType, double quote, const AKASCENSETUP *akascen, const AKABOND *bond, AKASCENREPORT *rpt, double *efficiency); /* Compute the key rate durations for a bond and return the results in an allocated report. The returned report must be freed by the caller using AKAKRDurReportFree(). On failure, it returns NULL. This routine uses shifts of the par curve at each maturity to do duration. These are created by calling AKAKeyDurSetup(); */ AKAKRDURREPORT *AKABondKeyDur3(long pvdate, const AKABOND *bond, long quoteType, double quote, AKAKRDURSETUP *setup); /* Construct a structure for computing the key rate durations of a bond using the specified duration shift (durbp), at specific maturities. This structure is used in AKABondKeyDur3(). The array maturities contains the specific key rates for which to calculate duration. If it is NULL (or maturities_count is zero) all the maturities in the curve are used. maturities_count must be the number of elements in the maturities_array. This structure must be freed by the caller using AKAKeyDurSetupFree(). */ AKAKRDURSETUP *AKAKeyDurSetup(const AKACURVE *curve, const AKASPREAD *spread, double durbp, double *maturities, int maturities_count); /* Frees the structure created in AKAKeyDurSetup(). Always returns NULL. */ AKAKRDURSETUP *AKAKeyDurSetupFree(AKAKRDURSETUP *setup); /* AKABondKeyDur2() is the same as invoking, AKAKeyDurSetup(), then AKABondKeyDur3(), and finally AKAKeyDurSetupFree(). Because creating the par shifted trees for each maturity is relatively expensive, calling this routine repeatedly with the same curve/spread is inefficient. Use AKABondKeyDur3(), instead. */ AKAKRDURREPORT *AKABondKeyDur2(long pvdate, const AKABOND *bond, long quoteType, double quote, const AKACURVE *curve, const AKASPREAD *spread, int durbp, AKAKRDURREPORT *rpt); /* AKABondKeyDur() is exactly the same as calling AKABondKeyDur2() with the rpt structure being NULL. */ AKAKRDURREPORT *AKABondKeyDur(long pvdate, const AKABOND *bond, long quoteType, double quote, const AKACURVE *curve, const AKASPREAD *spread, int durbp); /* Compute key-rate durations using SPOT shift. It must be passed an allocated AKAKRDURREPORT with the maturities of the desired key rates for durations, already filled out. Because it does spot shifts of the tree, we recommend using AKABondKeyDur3(), instead. */ long AKABondKRDur(long pvDate, long quoteType, double quote, AKAHTREE hTree, const AKABOND *bond, AKAKRDURREPORT *rpt); /* Both the following cash flow reports use the same structure. The first simply reports the cash flows from the instrument. The second discounts the flows and calculates bond value fundamentals. */ /* report cashflows -- leaves much of the report structure blank */ long AKABondFlowOnly(long pvDate, const AKABOND *bond, AKAFLOWREPORT *rpt); /* Compute and discount cashflows */ long AKABondFlow(long pvDate, long quoteType, double quote, AKAHTREE hTree, const AKABOND *bond, AKAFLOWREPORT *rpt); /* Compute yield for each option exercise date in option schedules and to maturity. If both a call and a put are in effect, both are reported. The function also returns the lowest of all these yields. */ long AKAYieldToWorst(long pvDate, long quoteType, double quote, const AKABOND *bond, AKAYLDWORST *rpt); /* Same as AKAYieldToWorst except that yields are computed to each sink date. */ long AKALowestYieldToSink(long pvDate, long quoteType, double quote, const AKABOND *bond, AKAYLDWORST *rpt); /* Compute yields for each option or flow date of a bond. The price of the bond must be supplied. The two control flags ascfy and tosink extend the behavior. If tosink is 1 the worst yields are for yields to sink dates. If ascfy is 1 the ytc, ytp, and worst yields are on a cash flow basis. The two flags can be combined. If both ascfy is 0 and tosink is 0, the behavior is the same as AKABondValueYields(). */ long AKAYieldToWorstEx(long pvDate, long quoteType, double quote, const AKABOND *bond, int tosink, int ascfy, AKAYLDWORST *rpt); /* Exactly like AKAYieldToWorstEx() except this returns the allocated report structure, or NULL on error. The returned structure must be freed via AKAYldWorstReportFree(). Note it is safe to call any {X}Free() function with NULL. */ AKAYLDWORST *AKAYieldToWorstEx2(long pvDate, long quoteType, double quote, const AKABOND *bond, int tosink, int ascfy); /* Compute price for each option exercise date in option schedules and to maturity. If both a call and a put are in effect, both are reported. The function also returns the lowest of all these prices. The bond ytm is used as the yield at each date when computing the price. If the provided quoteType is not AKA_QUOTE_YTM, the ytm will be calculated based on the provided quote. */ long AKAPriceToWorst(long pvDate, long quoteType, double quote, const AKABOND *bond, AKAPRCWORST *rpt); /* Fill out after-tax yield report -- input fields in report structure must be filled out prior to invocation. Pvdate is purchase date, and quote is purchase price. quoteType cannot be OAS. */ long AKAAtaxYield(long pvDate, long quoteType, double quote, const AKABOND *bond, AKAATAXYLD *rpt); /* Fill out after-tax basis report -- input fields in report structure must be filled out prior to invocation. Pvdate is sale date, and quote is sale price. quoteType cannot be OAS. */ long AKAAtaxBasis(long pvDate, long quoteType, double quote, const AKABOND *akabond, AKAATAXBASIS *rpt); /* Compute yields and modified durations for a bond. The price of the bond must be supplied. */ long AKABondValueYields(long pvdate, double price, const AKABOND *bond, AKABONDYIELDREPORT *rpt); /* Compute yields and modified durations for a bond. The price of the bond must be supplied. The two control flags ascfy and tosink extend the behavior. If tosink is 1 the worst yields are for yields to sink dates. If ascfy is 1 the ytc, ytp and worst yields are on a cash flow basis. The two flags can be combined. If both ascfy and tosink are 0, the behavior is the same as AKABondValueYields(). */ long AKABondValueYieldsEx(long pvdate, double price, const AKABOND *bond, int tosink, int ascfy, AKABONDYIELDREPORT *rpt);

Section 5. Bond Structure Configuration Functions

/* AFTER-TAX CONFIGURATION */ /* Set the default tax rate used for after-tax valuation of bonds. Tax-rates are as percents, i.e., 15 is 15%. If this function is not called the defaults are: 35%, 35%, 15%, 15% */ void AKADefaultTaxRate(double income, double capgain_short, double capgain_long, double capgain_superlong); /* Set the after-tax rate of a specific bond, defaults are used otherwise */ void AKABondTaxRate(AKABOND *bond, double income, double capgain_short, double capgain_long, double capgain_superlong); /* Get the after-tax rate in effect for a specific bond */ void AKABondTaxRateGet(AKABOND *bond, double *income, double *capgain_short, double *capgain_long, double *capgain_superlong); /* Configure the business day behavior of the bond */ enum AKANotifyBehavior { /* Extend the end of the notification/ex-coupon period so that it falls on a a business day. This is the default behavior. Example, for a currently callable American call with 30 days required notice, if the 30th day is a weekend (or holiday, if holiday list supplied) then push the next possible call opportunity to the next business day. */ AKABusinessDaysExtend, /* Only count business days when determining the notification * date. */ AKABusinessDaysOnly }; /* Configure the notify behavior, select from AKANotifyBehavior. Returns prior setting. */ int AKA_set_notifybehavior(AKABOND *, int behavior); /* Set weekends to be business days, returns prior setting. The default setting, for historical compatibility, is true. Note, if weekends are business days and no holidays are set (see below), notification is simply calendar days. */ int AKA_set_notifyweekends(AKABOND *, int); /* Set a day to be a non-business day */ void AKA_set_notifyholiday(AKABOND *, long); /* Remove all set holidays */ void AKA_clear_notifyholidays(AKABOND *); /* Mortgage Setup Configure a bond to behave like a mortgage. This configures the option and sink schedules so that the bond behaves like a mortgage. Existing sink and option schedules are removed. The bond must already have valid values for: - Dated/Initial Date - Maturity Date - Coupon - Daycount (recommend 30/360) - Frequency (recommend monthly) - Fcdate/lcdate Subsequently changing any of those values will corrupt the mortgage configuration and valuation results will be undefined. The call option delay days will be set to 15. This can be modified. A frequency of Interest at Maturity will be reset to Monthly and the warning AKA_WARN_FREQUENCY will be set. Amortization years is optional. If zero is passed, the bond amortizes at maturity. If the years are less than the life of the mortgage the warning WARN_AMORTIZATION is set. Reficost is the mortgage refinancing fees as a percent of par for "calling" the mortgage. Fees are expressed as points, 1.5% is 1.5. The function returns an AKA_ERROR code or AKA_ERROR_NONE. */ int AKABondMortgage(AKABOND *bond, double amount, double amortization_years, double reficost);

Section 6. Miscellaneous Functions

/* Version information as floating point number in the format v.rr where v = major version number rr = minor release number e.g., 1.10 */ double AKA_version(); /* Version information as a string: AKA BondOAS Library version v.rr */ const char *AKA_version_string(); /* Compute par curves at forward times based on rates of input tree or curve. See definition of AKAFWDRATE report below */ long AKAFwdRates(AKAHTREE hTree, AKAFWDREPORT *report); long AKAFwdRatesFromCurve(AKACURVE *curve, AKAFWDREPORT *report); /* Probe the term structure of volatility */ long AKAYieldVol(AKAHTREE hTree, AKAVOLREPORT *report); /* Set the duration shift method and basis points - like in AKAINITDATA. Permits the user to reset the duration shift parameters during a run of the library. MULTI-THREAD note: this routine is multi-thread safe. It will change these settings for the thread only. */ void AKA_set_duration_shift(long smode, double bp_no_options, double bp_with_options); /* Return the time between two dates in fractional years, according to the daycount. */ double AKAYears(long adate, long bdate, long daycount); /* Return a new date by adding the year fraction to the passed in date, according to the daycount. */ long AKADateAdd(long adate, double time, long daycount); /* Pack the settlement date and the trade date into a pvdate long. The settlement date will be the pvdate and the trade date will be used for counting days until an option for call notification. */ long AKADatePack(long settlement, long trade); /* Converts 5% callable (NC-10) muni yield curve into optionless par yield curve. Input curve can also be specified with varying coupons by maturity and a different non-call period. The passed in curve structure will be OVERWRITTEN with the resulting par curve. If *coupons is NULL the input curve underlying bonds have the default 5% coupon. Otherwise, *coupons must point to an array of coupons of a length that matches the date/rate entries in the curve and all values must be valid coupons. If non-call-period is <= 0 it is set to the default, which is 10 years. The function returns and sets the AKA_ERROR_CODE. AKA_ERROR_NONE is returned on success. */ long AKAConvertMuniCurve(AKACURVE *, double *coupons, double noncallperiod);

Section 7. Error Handling

All AKA API routines will set the AKA_ERROR_CODE. The error codes are described below. AKA_ERROR_NONE is zero, and indicates success. Unlike the C library errno, the AKA_ERROR_CODE is reset to AKA_ERROR_NONE after any API routine completes successfully. Access to the error code is provided by a thread-safe function. After a non-zero error, results of valuation routines are not defined.

Many AKA API routines can also generate warnings. These are recoverable errors. There may be more than one warning per invocation. Warnings, like errors are reset in each invocation. Access to the warnings is provided by a thread-safe function.

Warnings can be one of two types: a) Fully recoverable, in which the operation proceeds and all returned values are valid. These warnings are all named AKA_WARN_x. b) Partially recoverable, in which some portions of a complex operation failed and some of the returned data is invalid. These second class of warnings use the error codes of AKA_ERROR_x in the warnings. Note, the operation as a whole, could still have an error value of AKA_ERROR_NONE because it was partially successful.

MULTI-THREAD note: each thread has its own error message stack. All error handling routines are per thread. Errors for one thread are not visible to any other thread.

#include "akaerrno.h" /* All error numbers and AKA_WARNINGS_MAX are defined in akaerrno.h */ /* Returns the error, if any, from the last operation. */ enum AKA_ERROR_NUMBER AKAError(); /* Returns the number of warnings from the last operation. The array passed into this function must be large enough to hold AKA_WARNINGS_MAX values. No more than AKA_WARNINGS_MAX warnings will be returned. If more warnings are generated, the warnings will include AKA_WARN_TOOMANY. */ int AKAWarnings(enum AKA_ERROR_NUMBER *warnings); /* Returns the string representation of the error represented by errnum. */ const char *AKAErrorString(enum AKA_ERROR_NUMBER errnum);

Section 8. Memory Allocation and Free

These routines must be used to allocate and free BondOAS structures.

All AKA structures which have allocators (e.g., reports, AKABOND, etc.) must be allocated using the library provided allocation functions only. Using stack local variables or directly allocating the structures via malloc will cause unexpected results and memory errors. The only stack safe report structure is AKABONDREPORT.

/* forward declarations -- definitions below */ typedef struct AKASecurity AKASECURITY; typedef struct AKACoupon AKACOUPON; typedef struct AKAOption AKAOPTION; typedef struct AKASink AKASINK; AKACURVE * AKACurveAlloc(long n); AKACURVE * AKACurveFree(AKACURVE *curve); AKACURVE * AKACurveCopy(const AKACURVE *other); AKASPREAD * AKASpreadAlloc(long n); AKASPREAD * AKASpreadFree(AKASPREAD *spr); AKABOND * AKABondAlloc(long nCpns, long nCalls, long nPuts, long nSinks); AKABOND * AKABondFree(AKABOND *bond); AKABOND * AKABondCopy(const AKABOND *other); /* allocate pieces of a bond -- not the recommended approach */ AKACOUPON * AKACouponFree(AKACOUPON *cpn); AKACOUPON * AKACouponAlloc(long n); AKAOPTION * AKAOptionAlloc(long n); AKAOPTION * AKAOptionFree(AKAOPTION *opt); AKASINK * AKASinkAlloc(long n); AKASINK * AKASinkFree(AKASINK *opt); AKASCEN * AKAScenAlloc(long n); AKASCEN * AKAScenFree(AKASCEN *scen); /* Allocate and free the extended scenario analysis setup structure. AKAScenSetupFree() does not release the trees. The trees in the AKASCENSETUP structure must be created and released by the caller. */ AKASCENSETUP *AKAScenSetupAlloc(long n); AKASCENSETUP *AKAScenSetupFree(AKASCENSETUP *scen); AKAFLOWREPORT * AKAFlowReportAlloc(); AKAFLOWREPORT * AKAFlowReportFree(AKAFLOWREPORT *rpt); AKAKRDURREPORT * AKAKRDurReportAlloc(long n); AKAKRDURREPORT * AKAKRDurReportFree(AKAKRDURREPORT *rpt); AKAFWDREPORT * AKAFwdReportAlloc(long nTimes, long nMats); AKAFWDREPORT * AKAFwdReportFree(AKAFWDREPORT *rpt); AKAVOLREPORT * AKAVolReportAlloc(long n); AKAVOLREPORT * AKAVolReportFree(AKAVOLREPORT *rpt); AKAYLDWORST * AKAYldWorstReportAlloc(); AKAYLDWORST * AKAYldWorstReportFree(AKAYLDWORST *rpt); AKAPRCWORST * AKAPrcWorstReportAlloc(); AKAPRCWORST * AKAPrcWorstReportFree(AKAPRCWORST *rpt);

Section 9. Data Structures and Constants

It is important to read the notes in Section 8., above, about using AKA allocation functions.

/* MULTI-THREAD note: all initialization settings are global and are across all threads. */ /* INITIALIZATION structure with global configuration settings */ struct AKAInitData { /* the following three settings are deprecated and ignored */ char treePath[512]; long maxTrees; long maxTreesPurge; long msg_pop_order; /* 0 - last on first off (default prior to v. 2.00) 1 - first on first off (recommended) msg_pop_order is deprecated as of v. 2.10 */ long enable_tls; /* controls use of thread local storage -1 -- do not use tls 0 -- use default setting for architecture 1 -- enable tls The default settings are: linux/linux64 : tls enabled win32/64 lib_md : tls enabled win32/64 lib_mt, dll : tls disabled on versions prior to Vista sun-x86: tls enabled sun-sparc: cannot be enabled */ long treeCacheSize; /* deprecated and ignored */ long _reserved3; /* reserved for future use */ /* duration calculation settings */ long durationShift; /* Select from AKAShiftMode: default: AKA_SHIFT_PAR */ double durBPNoOpts; /* Duration shift when no options present default: 10.0 */ double durBPOpts; /* Duration shift when options present default: 40.0 */ /* scenario analysis settings for old style scenario analysis calls */ double efficiency; /* Efficiency of option exercise default: 100.0 */ }; /* RATE TERM structure */ struct AKACurve /* Curve specified at a list of maturities in years */ { long mode; /* Volatility type. Select from AKAVolatilityMode: */ /* AKA_VOLMODE_MEANREV: Supply mean reversion, compute lvol */ /* AKA_VOLMODE_LONGVOL: Supply lvol, compute mean reversion */ double vol; /* Short-rate volatility, 18% represented as 18.0 */ double lvol; /* 30-year rate volatility, 12% represented as 12.0 */ double alpha; /* Mean reversion speed, 2% represented as 2.0 */ long type; /* Select from AKACurveType */ long reseverd; /* reserved for future use */ long n; /* Number of entries */ double *time; /* Years in appropriate daycount convention */ double *yield; /* Rates: 7% as 7.0; Discount factors: 0.9 as 0.9 */ }; /* ISSUER SPREAD structure */ struct AKASpreads /* BEY corporate bond spreads */ { long n; /* Number of points */ double *time; /* Time in 30/360 years */ double *spread; /* Spread in BEY bp; 25 bp represented as 25.0 */ }; /* BOND structure, and supporting sub-structures It is important to read the notes in Section 8., above, about using AKA allocation functions. */ struct AKABond { AKASECURITY *sec; AKACOUPON *cpn; /* Set to NULL for fixed-coupon bond */ AKAOPTION *call; /* Issuer's option */ AKAOPTION *put; /* Holder's option */ AKASINK *sink; /* Sinking fund options */ }; struct AKASecurity { char name[80]; /* Optional identifier */ long idate; /* Issue date (yyyymmdd) (optional; defaults * to ddate) */ long ddate; /* Dated date (yyyymmdd) */ long fcdate; /* First coupon date (optional; defaults to the first flow date after the idate, determined by the frequency, counting back from the lcdate) */ long lcdate; /* Last regular coupon date (optional; * defaults to maturity) */ long mdate; /* Maturity date */ /* NOTE: To specify an interest at maturity bond, set the fcdate to the mdate and either leave the lcdate unspecified (zero) or set it to the mdate as well. */ long daycount; /* Select from AKADaycount */ long frequency; /* Select from AKAFrequency */ /* Note, the coupon frequency also applies to zero coupon bonds. Frequency is used to determine yields. Do not use Interest at Maturity for zero coupon bonds. */ long ex_cpn_days; /* Number of days bond trades ex-coupon (optional; defaults to zero), see option delay */ long payday; /* The pay day is the day of the month on which the coupon is paid. The default is to pay on the day of month of the last coupon, or the first coupon, or the maturity, in that precedence, if first or last coupons are specified. For bonds where the resulting day is the end of the month of the applicable date, but not the end of the month of the cyclical coupon months, this can be used to force the end-of-month rule. For example a semiannual bond that matures on 6/30 (or has a last coupon date of 6/30, if specified) will pay on 6/30 and 12/30 if the end-of-month rule is not in effect. It will pay on 6/30 and 12/31 if the end of month rule is in effect. If the payday is < 0 or > 30 the EOM rule is in effect, otherwise it is not. The default is 0. */ double redemption_value; /* Usually 100, sometimes not at par. Useful for valuing pre-refunded bonds that are defeased to the first call date and the call is at a premium. */ double coupon; /* Fixed coupon, ignored for step-ups */ /* Note, see discussion of zero coupon bonds in frequency, above */ long yld_method; /* select from AKA_YIELD_METHOD */ /* Bond Specification Information used in After-Tax Valuations */ double issue_price; /* defaults to par */ void *taxinfo; /* configuration data for AKAAfterTax, do not assign or access directly */ /* private configuration data, never assign to this */ void *_data; }; struct AKACoupon /* Used for step-up coupons */ { long n; /* Number of coupon/date pairs */ long type; /* Select from AKAPeriodType */ long *date; /* Coupon period boundary dates (see type) */ double *cpn; /* Coupons, 7.0% represented as 7.0 */ }; struct AKAOption /* Used for call and put options */ { long n; /* Number of strike dates (0 => No option) */ long type; /* Select from AKAOptionType */ long delay; /* Number of days notice required, this is in calendar days. The first exercise date will be pushed to a Monday if it falls on a weekend. For finer control, please use the C++ API. */ long *date; /* Strike dates */ double *px; /* Strike prices */ }; struct AKASink /* Sinking fund option */ { long n; /* Number of sink dates (0 => No sinking fund) */ long delivery; /* Issuer's option to buy bonds in open market */ /* and deliver to trustee to meet SF requirement */ /* 1 if present, 0 otherwise */ long allocation; /* Select from AKAAllocation */ double face; /* Original face in dollars, used to verify schedule. A value of zero means trust schedule */ double outstanding; /* Current amount outstanding in dollars */ double acceleration; /* 100 for a double-up, 200 for triple-up, etc. */ double accumulation; /* Face amount in dollars held by accumulators */ long *date; /* Sink dates */ double *amt; /* Sink amounts in dollars */ double *px; /* Sink prices (usually 100) */ }; /* SCENARIO valuation definition structure */ struct AKAScenSetup { long type; /* Select from AKAScenType */ long n; /* Number of points (n >= 2) */ long *dates; /* Vector of dates (yyyymmdd) */ AKAHTREE *trees; /* Vectors of prevailing trees */ double eff_threshold; /* efficiency threshold for option exercise, default is 100% */ int reinvestment_method; /* Select from AKASCEN_REINVESTMENT */ double reinvestment_rate; /* for fixed reinvestment behavior, 10.0 is 10%. */ int is_aftertax; /* compute on after-tax basis, 0 no, 1 yes, default is no. */ }; /* Scenario analysis is normally based on input yield curves and the OAS implied by the initial price. In situations where the user inputs a price that implies an unreasonable OAS, the scenario-based option exercise and cashflow reinvestment calculations may be distorted. Assuming the input initial yield curve is appropriate for the issuer of the security, the user can suppress the use of implied OAS for purposes of option exercise and reinvestment by providing an fixed reinvestment OAS and setting the reinvest_at_fixed_oas flag, below. In this case only the horizon price will be calculated using the implied OAS. All option exercise decisions and reinvestment calculations will relative to the entered curves. Alternatively, the user can provide a fixed reinvestment rate which will be used in lieu of the curve implied rate. */ enum AKASCEN_REINVESTMENT { AKASCEN_REINVEST_OAS, /* default, reinvest at the applicable yield plus the implied oas of the security */ AKASCEN_REINVEST_ZERO, /* reinvest at the applicable yield without an oas. */ AKASCEN_REINVEST_FIXED /* reinvest at a fixed rate */ }; /* REPORT BASED VALUATION routines structures */ struct AKABondReport { /* price is always calculated (or supplied) */ double price; /* Dollar price as a percentage of par */ /* accrued is always calculated */ double accrued; /* Accrued as a percentage of par */ /* option value is calculated if value options is set */ double optval; /* Option value as a percentage of par */ /* oas is always calculated (or supplied) */ double oas; /* Option-adjusted spread, 25 bp = 25.0 */ /* duration values are calculated if value duration is set */ double effDur; /* Option adjusted duration in years */ double effCon; /* (vup - 2*v + vdn)/(v*(dr)^2) */ double effDV01; /* (price + accrued)*effDur/100.0 */ /* yields are calculated if value yields is set */ double ytm; /* Yield to maturity, 7% = 7.0; ignores amortization */ double ytc; /* Yield to next call */ double ytp; /* Yield to next put */ double cfy; /* Cashflow yield; includes amortization */ double wam; /* Weighted average maturity in years */ /* modified duration values are calculated if value yields is set */ double modDur; /* Modified duration in years */ double modCon; /* Modified convexity, same units as effCon */ double modDV01; /* (price + accrued)*modDur/100.0 */ }; struct AKABondYieldReport { double ytm; /* Yield to maturity, 7% = 7.0 */ double ytc; /* Yield to call */ double ytp; /* Yield to put */ double cfy; /* Cashflow yield */ double wam; /* Weighted average maturity in years */ double modDur; /* Modified duration in years */ double modCon; /* Modified convexity, same units as effCon */ double modDV01; /* (price + accrued)*modDur/100.0 */ double modDurCall; /* Modified duration to call */ /* to worst values */ long worstdate; /* date of worst option exercise */ double ytw; /* yield to worst */ double modDurWorst; /* modified duration to worst */ double modConWorst; /* modified convexity to worst */ }; struct AKAFlowReport { long nFlows; /* Number of cashflows remaining */ /* These bond fundamental values are not calculated by the flow only cash flow function */ double oas; /* Option-adjusted spread */ double value; /* Fair value */ double accrued; /* Accrued interest */ double optval; /* Value of embedded options */ double npv; /* Net present value of scheduled flows */ /* The remaining elements are arrays of nFlows doubles. */ /* The following are returned by each cash flow function. */ long *date; /* Cashflow dates (yyyymmdd) */ double *iflow; /* Interest flows */ double *pflow; /* Principal flows */ double *tflow; /* Total cashflow */ /* These discounted cash flow calculations are not calculated by the flow only cash flow function */ double *zero; /* Zero-coupon rate */ double *factor; /* Discount factor */ double *pv; /* Present values of individual flows */ }; struct AKAFwdReport { /* INPUTS */ long nMats; /* Number of maturities in computed yield curves */ long nTimes; /* Number of forward times at which to solve */ double *mats; /* Maturities for which to solve (e.g., 1yr, 5yr) */ double *times; /* Times at which to solve (e.g., 6mo, 1yr ...) */ /* OUTPUT */ double **fwds; /* nTimes par curves, each with nMats maturities, i.e., fwds[iTime][iMat] */ }; struct AKAKRDurReport { long n; /* Number of maturities supplied (input/output) */ double oas; /* Option-adjusted spread */ double value; /* Fair value */ double accrued; /* Accrued interest */ double npv; /* Net present value of scheduled flows */ double effDur; /* Option adjusted duration in years */ double effCon; /* (vup - 2*v + vdn)/(v*(dr)^2) */ double *mats; /* Maturities, in 30/360 years (input/output) */ double *durs; /* Key-rate durations */ }; struct AKAScenReport { double cap0; /* Initial capital (dirty px) per $100 face amount */ double val0; /* Initial clean price per $100 face amount */ double acc0; /* Initial accrued per $100 face amount */ /* NB: cap0 = val0 + acc0 */ double interest; /* Interest received to horizon per $100 face */ double principal; /* Principal received to horizon per $100 face */ double intOnInt; /* Reinvestment income received to horizon per $100 */ double cap1; /* Final capital per $100 face amount, is: val1 + acc1 + interest + principal + intOnInt */ double val1; /* Final clean price per $100 face amount */ double acc1; /* Final accrued per $100 face amount */ double totalRet; /* totalRet = cap1 - cap0 */ double dur0; /* Initial effective duration of cap0 */ double dur1; /* Final effective duration of cap1, but note that */ /* dur of interest + principal + intOnInt is zero, */ /* i.e. all intervening flows are cash at horizon */ double con0; /* Initial effective convexity of cap0 */ double con1; /* Final effective convexity of cap1, but note that */ /* con of interest + principal + intOnInt is zero, */ /* i.e. all intervening flows are cash at horizon */ double oas; /* OAS, either given or computed */ double balance; /* Fraction of original balance remaining */ long redeemed; /* Logical OR of flags from AKAScenRedemption */ long rDate; /* Date of option exercise if put or called */ }; struct AKAVolReport { long n; /* Number of maturities supplied (input) */ double alpha; /* Mean reversion (output) */ double *mats; /* Maturities, in 30/360 years (input) */ double *vols; /* Volatilities (output) */ }; struct AKAYldWorst { long *dates; /* all flows with option exercisable and maturity date */ double *yields; /* yield on each of the above dates */ int n; /* number of entries in above arrays */ int worst; /* index in above arrays with worst yield */ }; struct AKAPrcWorst { long *dates; /* all flows with option exercisable and maturity date */ double *prices; /* price on each of the above dates */ int n; /* number of entries in above arrays */ int worst; /* index in above arrays with worst price */ }; struct AKAAtaxYldResult { double principal; /* principal, e.g., redemption at maturity */ double tax; /* tax on principal */ double yield; /* yield implied by final cash flow being principal - tax */ }; struct AKAAtaxYld { /* INPUT fields - must be filled out by the caller - or - input fields can be left at zero and the settings in the bond will be used and copied into the report */ double issue_price; /* price at issue 100 is par; will over-ride issue_price in bond unless this is set to zero */ double taxrate_short; /* short term capital gains, 10.0 = 10% */ double taxrate_long; /* long ... */ double taxrate_superlong; /* super long ... > 5yrs, issued since 1/1/01 */ double taxrate_income; /* income tax rate */ /* OUTPUT fields */ struct AKAAtaxYldResult ytm; /* after tax yield to maturity */ struct AKAAtaxYldResult ytc; /* after tax yield to call */ struct AKAAtaxYldResult ytp; /* after tax yield to put */ }; struct AKAAtaxBasis { /* TAX INPUT fields - must be filled out by the caller - or - input fields can be left at zero and the settings in the bond will be used and copied into the report */ double issue_price; /* price at issue 100 is par; will over-ride issue_price in bond unless this is set to zero */ double taxrate_short; /* short term capital gains, 10.0 = 10% */ double taxrate_long; /* long ... */ double taxrate_superlong; /* super long ... > 5yrs, issued since 1/1/01 */ double taxrate_income; /* income tax rate */ /* INPUT Purchase date and price must be filled out by user */ long purchase_date; /* date of purchase as yyyymmdd */ double purchase_price; /* purchase price */ /* OUTPUT fields */ double purchase_basis; /* bond basis on purchase date */ double holder_basis; /* holder's basis on sale date */ double sale_basis; /* bond basis on sale date */ double atax_price; /* sale price adjusting for taxes */ }; /* USEFUL CONSTANTS */ /* Define TRUE and FALSE constants, if they are not already defined. */ #ifndef TRUE #define TRUE (1==1) #ifndef FALSE #define FALSE (!TRUE) enum AKAQuoteType /* Type of value supplied as input to valuation routines */ { AKA_QUOTE_OAS = 0, AKA_QUOTE_PRICE = 1, AKA_QUOTE_YTM = 2, AKA_QUOTE_YTC = 3, AKA_QUOTE_YTP = 4, AKA_QUOTE_ATAX_PRICE = 5 /* reserved for future use */ }; enum AKAShiftMode /* Shift for duration calculation */ { AKA_SHIFT_SPOT = 0, /* shift the tree, i.e., shift the OAS */ AKA_SHIFT_PAR = 1, /* shift the par yield curve, compute a new tree For factor curves, a par rate curve is extracted from the computed tree; this is then shifted */ AKA_SHIFT_NONE = 2 /* do not calculate duration or convexity */ }; enum AKAVolatilityMode /* How the volatility input is specified */ { AKA_VOLMODE_MEANREV = 0, AKA_VOLMODE_LONGVOL = 1 }; enum AKACurveType /* Yield curve type */ { AKA_CURVE_FACTOR = 0, /* discount factors */ AKA_CURVE_PAR = 1, /* par yields */ AKA_CURVE_ZERO = 2, /* zero coupon rates */ AKA_CURVE_FORWARD = 3 /* forward rates - do not use for TreeFit() */ }; enum AKADaycount /* Supported daycounts */ { AKA_DAYS_BUS_252 = 30, /* business days / 252 */ AKA_DAYS_30_360 = 33, /* US */ AKA_DAYS_30E_360 = 34, /* 30/360 with European treatment of Feb. */ AKA_DAYS_30_360_ISDA = 35, /* ISDA version of 30/360 conventions */ AKA_DAYS_30E_360_ISDA = 36, AKA_DAYS_ACT_360 = 39, AKA_DAYS_NO_LEAP_365 = 45, AKA_DAYS_ACT_365 = 47, AKA_DAYS_ACT_ACT = 63, /* CD daycounts cause interest cash flows to be proportional to the number of actual days in the period, i.e., the interest cash flow is the coupon * days-in-period / 365. Note: bonds with CD daycounts always use the CD yield method regardless of the yield method specified. */ AKA_DAYS_CD_365 = 111 }; enum AKAFrequency /* Supported frequencies */ { AKA_FREQ_INT_AT_MATURITY = 0, /* implies an interest at maturity bond with an annual frequency for BEY yields. Set security yld_method to 2, (AKA_YLD_SIMPLE_LAST_PERIOD) for annualized simple interest yield. */ AKA_FREQ_ANNUAL = 1, AKA_FREQ_SEMIANNUAL = 2, AKA_FREQ_QUARTERLY = 4, AKA_FREQ_MONTHLY = 12, AKA_FREQ_SEMIANNUAL_COMPOUNDED = 18, AKA_FREQ_QUARTERLY_COMPOUNDED = 20 }; /* Note: see discussion of CD yields in AKADayCount above */ enum AKA_YIELD_METHOD { AKA_YLD_GLOBAL, /* use global setting, defaults to BEY and can be overridden with deprecated function AKA_set_simple_interest_type() */ /* following yields are compounded at the bond frequency */ AKA_YLD_BEY, /* discount cash flows using bond equivalent yield */ AKA_YLD_SIMPLE_LAST_PERIOD, /* use simple interest if in final coupon */ AKA_YLD_SIMPLE_LAST_YEAR, /* use simple interest if in final year */ AKA_YLD_MUNI, /* use municipal bond convention */ /* following yields ignore bond frequency when computing yield */ AKA_YLD_ANNUALIZED, AKA_YLD_ANNUALIZED_SIMPLE_LAST_PERIOD, AKA_YLD_ANNUALIZED_SIMPLE_LAST_YEAR }; enum AKAOptionType /* Supported call and put option types */ { AKA_OPTION_EUROPEAN = 0, AKA_OPTION_AMERICAN = 1, AKA_OPTION_BERMUDAN = 2 /* Deprecated; Use European and specify all call dates */ }; enum AKAAllocation /* Designation option in sinking funds */ { AKA_ALLOC_PRORATA = 0, AKA_ALLOC_FRONT = 1, AKA_ALLOC_BACK = 2 }; enum AKAScenRedemption /* Type of redemption returned by scenario analysis */ { AKA_REDEEM_NONE = 0, AKA_REDEEM_CALL = 1, AKA_REDEEM_PUT = 2, AKA_REDEEM_SINK = 4, AKA_REDEEM_MATURITY = 8 }; enum AKAScenType /* When scenario shifts occur */ { AKA_SCEN_NOW = 0, /* Suddenly at time 0 */ AKA_SCEN_GRADUAL = 1, /* Linearly in time */ /* Note: Using AKA_SCEN_GRADUAL is slow. Using AKA_SCEN_GRADUAL with factor curve based trees is particularly slow. */ AKA_SCEN_THEN = 2 /* Suddenly at horizon */ }; enum AKAPeriodType /* Whether dates mark beginnings or ends of step-up coupon periods */ { AKA_PERIOD_BEGIN = 0, AKA_PERIOD_END = 1 };

Section 10. Deprecated Functions

These routines are supported for backward compatibility

/* Sets whether to use simple interest calculations if the pvdate is within the final pay period or final year. By default, this is off. MULTI-THREAD note: this routine is multi-thread safe. It will change the setting for the invoking thread only. */ enum AKA_SIMPLE_INTEREST_TYPE { AKA_SI_OFF, AKA_SI_LAST_PERIOD, AKA_SI_LAST_YEAR }; void AKA_set_simple_interest_type(enum AKA_SIMPLE_INTEREST_TYPE it); #define AKA_set_simple_interest_yield(x) \
AKA_set_simple_interest_type((x) ? AKA_SI_LAST_PERIOD : AKA_SI_OFF) #define AKA_set_global_simple_interest_yield(x) \
AKA_set_simple_interest_yield(x) #define AKA_set_thread_simple_interest_yield(x) \
AKA_set_simple_interest_yield(x) #define AKACouponSpread(pvdate, hTree, bond) AKAAssetSwapSpread(100.0, pvdate, hTree, bond) /* backward compatible declarations for earlier initialization calls */ #define AKAINIT_ERR_NONE AKA_ERROR_NONE #define AKAINIT_ERR_AUTHORIZE AKA_ERROR_AUTHORIZATION #define AKAINIT_ERR_ALLOC AKA_ERROR_MEMORY /* --- old style initialization --- Two function interface, authorize_init() must be called before calling AKAInit() */ #define AKATerm() AKA_shutdown_configure(0) /* support old name */ /* Check user authorization to access library. Returns TRUE if a valid key for the user was provided, otherwise FALSE. A valid key can be expired. This will show up when init is called */ int AKA_authorize_init(long key, const char *uname); /* Like the above but returns the error code or NONE (0) on success */ int AKA_authorize_init2(long key, const char *uname); /* Initialize with settings. If initdata == NULL default settings are used returns one of AKAINIT_ERR_ defined above */ long AKAInit(AKAINITDATA *config);

The following two functions handled calculating duration outside of the standard bond valuation functions, AKABondVal() and AKABondVal2(). This was due to inefficiencies in computing duration shifts due to the handling of the shifted trees needed in the valuations. This is no longer the case and they should not be used. ABABondVal() or AKABondVal2() should be used instead.

/* Create two shifted trees suitable for computing duration. The input is the original tree and the basis points to shift. The bpShift is passed as a pointer, is always a positive number, and may be updated in the function. The down-shifted and up-shifted trees are returned in the pointer reference parameters passed into the routine. The trees are fitted by shifting the par curve by bpShift basis points. If this fails, the bpShift value is adjusted until the trees can be successfully fitted. A tree will fail to fit when shifting causes excessively low rates. This routine returns 1 on success and 0 on failure. */ int AKATreeFitShift2(AKAHTREE tree, double *bpShift, AKAHTREE *treeup, AKAHTREE *treedown); /* Calculate the convexity and duration values assuming that the bond report is already filled out with the other data (price, OAS, accrued). For use with AKA_SHIFT_NONE. The hTree_up and hTree_down trees are assumed to be trees which were created by shifting the yield curve durbp basis points up and down. These trees can be created by shifting the original curve and calling AKATreeFit() or by using AKATreeFitShift(). The price and OAS values in the rpt are assumed to have come by valuing the bond with the unshifted tree. */ long AKABondDuration(long pvdate, AKAHTREE hTree_up, AKAHTREE hTree_down, double durbp, const AKABOND *bond, AKABONDREPORT *rpt); /* Note: for scenario functions below, entering the initial price as a negative price, i.e., 99.375 is entered as -99.375, causes the scenario analysis to be done with an oas of zero. See the definitions of the AKASCENSETUP structure and AKASCEN_REINVESTMENT, above. */ /* Perform scenario analysis on a bond, uses efficiency set in init(). */ long AKABondScen(long quoteType, double quote, const AKASCEN *scen, const AKABOND *bond, AKASCENREPORT *rpt); /* Like AKABondScen() but allows setting of efficiency threshold and returns the observed efficiency */ long AKABondScen2(long quoteType, double quote, const AKASCEN *akascen, const AKABOND *bond, AKASCENREPORT *rpt, double eff_threshold, double *efficiency); /* Like AKABondScen2() but if reinvest is greater than zero, use the supplied reinvestment rate rather than the scenario indicated forward rate plus the instrument OAS. Rate is as percent, i.e., for 10% use 10. Rate is BEY, 30/360 semi-annual */ long AKABondScen3(long quoteType, double quote, const AKASCEN *akascen, const AKABOND *bond, AKASCENREPORT *rpt, double eff_threshold, double *efficiency, double reinvest); /* Like AKABondScen3() but if ataxinfo is non-null does an after tax total return analysis. The AKAATAXYLD input fields must be filled out if ataxinfo is non-null. The AKAATAXYLD report output fields are not computed -- the report is only used in this routine to supply input data. To compute aftertax yields see AKAAtaxYield() below. */ long AKABondScen4(long quoteType, double quote, const AKASCEN *akascen, const AKABOND *bond, AKASCENREPORT *rpt, double eff_threshold, double *efficiency, double reinvest, AKAATAXYLD *ataxinfo); /* scenario analysis setup */ struct AKAScen { long type; /* Select from AKAScenType */ long n; /* Number of points (n >= 2) */ long *dates; /* Vector of dates (yyyymmdd) */ AKAHTREE *trees; /* Vectors of prevailing trees */ }; /* Fit a tree from a set of curves */ /* INTEREST RATE structure alternative form composed from known prices of bonds and zero coupon rates */ struct AKARun { long mode; /* Select from AKAVolatilityMode: */ /* AKA_VOLMODE_MEANREV: Supply mean reversion, compute lvol */ /* AKA_VOLMODE_LONGVOL: Supply lvol, compute mean reversion */ double vol; /* Short-rate volatility, 12% represented as 12.0 */ double lvol; /* 30-year rate volatility, 10% represented as 10.0 */ double alpha; /* Mean reversion speed, 2% represented as 2.0 */ long pvdate; /* Required to price instruments, */ /* but tree is independent of time. */ long nBonds; /* Number of bonds */ AKABOND **bonds; /* Optionless bond specifications */ double *bondPx; /* Clean bond prices */ long nRates; /* Number of zero coupon rates */ long *rateDaycount; /* Appropriate daycount type */ long *rateMat; /* Discount note maturities */ double *rate; /* Discount rates */ }; typedef struct AKARun AKARUN;

This function is no longer supported. It will always return a zero (failed) tree and generate an error message

AKAHTREE AKATreeFitRun(const AKARUN *crv, const AKASPREAD *spr); AKARUN * AKARunAlloc(long nBonds, long nRates); AKARUN * AKARunFree(AKARUN *run);

ERROR handling has been entirely revised. All these interfaces are deprecated. They will continue to work but you are strongly urged to move to the newer error handling interface, described in the Error Handling section, above.

typedef enum { /* Error Message type enumerations. */ AKA_MSG_NONE, AKA_MSG_INFORMATION, /* Note: there are never msgs of this type */ AKA_MSG_WARNING, AKA_MSG_FATAL /* Note: these are not fatal, merely failures of the last operation */ } AKA_MSGTYPE; #define AKA_MSG_MAXLEN 300 /* max length of an error message string */ /* Pop the messages off the message stack - returns AKA_MSG_NONE when empty text must be at least char[AKA_MSG_MAXLEN]. The order messages are popped is determined by the AKAInitData configuration setting, msg_pop_order. */ AKA_MSGTYPE AKA_msg_pop(char *text); /* Returns TRUE if there is an un-popped error message from the last operation */ int AKAFatalStatus(); /* Marks all messages from the last operation as popped */ void AKAFatalReset(); /* Returns the highest level of the un-popped errors from the last operation */ AKA_MSGTYPE AKA_msg_status(); /* the following two function continue to exist for linkage purposes but no longer do anything. */ void AKA_msg_push(char *text, AKA_MSGTYPE mtype); AKA_MSGTYPE AKA_msg_suppress(AKA_MSGTYPE mtype); /* Provide random walks through the expected interest rates in order to do sampling valuation analysis. Returns 0 on success. */ struct TREESAMPLE { int nmats; /* number of maturities - size of mats array */ int npaths; /* number of paths to solve for */ int ntimes; /* number of times - size of times array */ double *mats; /* array of maturities to solve for */ double *times; /* array of times to solve for */ struct PATH_ITEM ***paths; /* samples: [<mat-i>][<path-i>][<time-i>] */ }; struct PATH_ITEM { double rate; double center; }; struct TREESAMPLE *AKA_treesample_alloc(int nmats, int npaths, int ntimes); void AKA_treesample_free(struct TREESAMPLE *sample); int AKA_treesample(AKACURVE *curve, struct TREESAMPLE *sample);

Index of Functions

AKAAssetSwapSpread
AKAAtaxBasis
AKAAtaxYield
AKABondAccrued
AKABondAccrued2
AKABondAlloc
AKABondCopy
AKABondDuration
AKABondFlow
AKABondFlowOnly
AKABondFree
AKABondKRDur
AKABondKeyDur
AKABondKeyDur2
AKABondKeyDur3
AKABondMortgage
AKABondOAS
AKABondPrice
AKABondPriceCnv
AKABondPriceShifted
AKABondScen
AKABondScen2
AKABondScen3
AKABondScen4
AKABondScenEx
AKABondTaxRate
AKABondTaxRateGet
AKABondVal
AKABondVal2
AKABondVal3
AKABondValueYields
AKABondValueYieldsEx
AKAConvertAssetSwapSpread
AKAConvertMuniCurve
AKACouponAlloc
AKACouponFree
AKACurveAlloc
AKACurveCopy
AKACurveFree
AKADateAdd
AKADatePack
AKADefaultTaxRate
AKADiscount
AKAError
AKAErrorString
AKAFatalReset
AKAFatalStatus
AKAFlowReportAlloc
AKAFlowReportFree
AKAFwdRates
AKAFwdRatesFromCurve
AKAFwdReportAlloc
AKAFwdReportFree
AKAISpread
AKAInit
AKAKRDurReportAlloc
AKAKRDurReportFree
AKAKeyDurSetup
AKAKeyDurSetupFree
AKALowestYieldToSink
AKAOptionAlloc
AKAOptionFree
AKAPrcWorstReportAlloc
AKAPrcWorstReportFree
AKAPriceToWorst
AKARunAlloc
AKARunFree
AKAScenAlloc
AKAScenFree
AKAScenSetupAlloc
AKAScenSetupFree
AKASinkAlloc
AKASinkFree
AKASpreadAlloc
AKASpreadFree
AKATreeFit
AKATreeFitRun
AKATreeFitShift
AKATreeFitShift2
AKATreeFitSpreads
AKATreeFitZero
AKATreeMinRate
AKATreeRelease
AKAVolReportAlloc
AKAVolReportFree
AKAWarnings
AKAYears
AKAYieldToWorst
AKAYieldToWorstEx
AKAYieldToWorstEx2
AKAYieldVol
AKAYldWorstReportAlloc
AKAYldWorstReportFree
AKA_authorize_expiration_date
AKA_authorize_init
AKA_authorize_init2
AKA_clear_notifyholidays
AKA_initialize
AKA_initialize_configure
AKA_initialize_get_defaults
AKA_memory_diagnostics
AKA_msg_pop
AKA_msg_push
AKA_msg_status
AKA_msg_suppress
AKA_set_duration_shift
AKA_set_notifybehavior
AKA_set_notifyholiday
AKA_set_notifyweekends
AKA_set_simple_interest_type
AKA_shutdown
AKA_shutdown_configure
AKA_treesample
AKA_treesample_alloc
AKA_treesample_free
AKA_version
AKA_version_string

Error Numbers and Definitions — akaerrno.h

#ifndef _AKAERRNO_H_ #define _AKAERRNO_H_ /* ERROR NUMBERS */ enum AKA_ERROR_NUMBER { /* INITIALIZATION ERRORS */ AKA_ERROR_NONE, /* no error */ AKA_ERROR_AUTHORIZATION, /* authorization did not run successfully */ AKA_ERROR_MEMORY, /* memory allocation error -- should not occur */ AKA_ERROR_EXPIREDKEY, /* authorization key has expired */ AKA_ERROR_UNINITIALIZED, /* not initialized or shutdown */ /* FEATURE PERMISSION ERRORS */ AKA_ERROR_PERMISSION_LATTICE, /* not authorized to use lattice functions */ AKA_ERROR_PERMISSION_ADVANCED_LATTICE, /* not authorized to use advanced lattice functions */ AKA_ERROR_PERMISSION_SCENARIOS, /* not authorized to use scenario analysis functions */ AKA_ERROR_PERMISSION_ATAX, /* not authorized to use after-tax functions */ /* VALUATION ERRORS */ AKA_ERROR_COMPUTE_COUPON, /* failed to compute coupon spread */ AKA_ERROR_COMPUTE_KEYRATES, /* failed to compute key rate durations */ AKA_ERROR_COMPUTE_OAS, /* failed to compute OAS from price */ AKA_ERROR_COMPUTE_PRICE, /* failed to compute price from OAS */ AKA_ERROR_COMPUTE_YIELD_ATAX, /* failed to compute after-tax yield */ AKA_ERROR_TREEFIT, /* failed to construct interest rate model */ AKA_ERROR_INTERNAL, /* internal library failure -- this should never occur */ /* INPUT ERRORS */ AKA_ERROR_TREESAMPLE, /* invalid treesample structure as input */ AKA_ERROR_HTREE, /* invalid interest rate model as input */ AKA_ERROR_COUPON, /* invalid coupon as input, must be > 0 */ AKA_ERROR_QUOTETYPE, /* invalid quote type as input */ AKA_ERROR_OAS, /* invalid OAS as input */ AKA_ERROR_PRICE, /* invalid price as input */ AKA_ERROR_YIELD, /* invalid yield as input */ AKA_ERROR_MATURED, /* pvdate is after maturity */ AKA_ERROR_RETIRED, /* deprecated, will not occur */ AKA_ERROR_CURVE, /* invalid curve as input */ AKA_ERROR_DATE, /* invalid date input */ AKA_ERROR_DURSHIFT, /* invalid duration shift basis points as input, must be >= 1 and < 300, must also not be so high that is causes very negative rates */ AKA_ERROR_FACEAMOUNT, /* invalid face amount as input */ AKA_ERROR_FCDATE, /* invalid first coupon date as input */ AKA_ERROR_IDATE, /* invalid initial date as input */ AKA_ERROR_LCDATE, /* invalid last coupon date as input */ AKA_ERROR_MATURITY, /* invalid maturity as input */ AKA_ERROR_OPTIONDATE, /* invalid option date as input */ AKA_ERROR_OPTIONPRICE, /* invalid option price as input */ AKA_ERROR_PURCHASEDATE, /* invalid purchase date as input */ AKA_ERROR_PVDATE, /* invalid Pvdate as input */ AKA_ERROR_SALEDATE, /* invalid sale date as input */ AKA_ERROR_SINKDATE, /* invalid sink date as input */ AKA_ERROR_SINKPRICE, /* invalid sink price as input */ /* RECOVERABLE INPUT ISSUES */ AKA_WARN_SINK_ALLOCATION, /* invalid sinking fund allocation, using prorata */ AKA_WARN_SINK_UNDESIGNATED, /* sink allocated amount could not be fully designated */ AKA_WARN_FREQUENCY, /* invalid coupon frequency as input, using semi-annual */ AKA_WARN_DAYCOUNT, /* invalid day count, using 30/360 */ AKA_WARN_OPTIONDELAY, /* option delay less than zero or greater than bond frequency, adjusting to 30 days or bond frequency */ AKA_WARN_OUTSTANDING_HIGH, /* input amount outstanding is greater than remaining flows, reducing amount outstanding accordingly */ AKA_WARN_PAYDAY, /* invalid payday, using none */ AKA_WARN_SINKSUM_HIGH, /* sum of sinking fund schedule exceeds input face amount, trusting schedule */ AKA_WARN_SINKSUM_LOW, /* sum of sinking fund schedule is less than input face amount, adding remainder to final flow */ AKA_WARN_TRADEDATE, /* invalid trade date in packed date, ignoring trade date */ AKA_WARN_YIELDMETHOD, /* invalid yield method, using simple last period */ /* RECOVERABLE VALUATION ISSUES */ AKA_WARN_IMPERFECT_COUPON, /* imperfect fit of coupon spread */ AKA_WARN_IMPERFECT_OAS, /* imperfect fit of OAS to price */ AKA_WARN_TOOMANY, /* too many warnings */ AKA_WARN_AMORTIZATION, /* amortization period before maturity */ AKA_WARN_SINK_TOO_SOON, /* sink schedule retires bond before maturity, either schedule, maturity, or face amount are wrong */ AKA_WARN_OUTSTANDING_LOW, /* input amount outstanding is less than 0.1% of face, disregarding input and trusting schedule */ AKA_WARN_LCDATE_NONCYCLICAL, /* last regular coupon date not cyclical with first coupon date, ignoring last coupon date */ AKA_WARN_XML_PARSE_FAILURE /*parsing xml definition failed */ }; /* maximum number of warnings that will be generated by any operation */ #define AKA_WARNINGS_MAX 12
Contents