Using calendars in LUSID

A calendar in LUSID is a repository of market holiday data that can contain:

  • All the holiday dates in a particular jurisdiction for as many years as data is provided for, for example a GBP calendar containing all UK public holidays for the next 30 years.

  • The days of the week that constitute the weekend in that jurisdiction, for example Saturday and Sunday.

LUSID then infers that any date not in the calendar, or not at the weekend, is a business day.

There are several ways to create calendars in LUSID:

  • Subscribe to FINBOURNE's Horizon: Copp Clark utility to access ready-made calendars containing the latest market holiday data.

  • Use the APIs in the Calendars collection to create your own calendars and manually load them with holiday data.

  • Use the dashboard in the LUSID web app to create your own calendars (coming soon).

  • Use dedicated Luminesce providers to create your own calendars.

All calendars in LUSID have a scope and a code. You can pass one or more calendar codes into various LUSID operations to cause those operations to occur only on business days. For example, you can ensure that:

By default, calendar codes are selected from the scope CoppClarkHolidayCalendars. This default scope is defined within the recipe you use. See how to use calendars from a different scope.

Using calendars to distribute cashflows on business days

You can specify paymentCalendars when modelling instruments that take a flowConventions object in their economic definition to factor in market holidays when performing certain operations, such as distributing cashflows.

Note: You can currently specify calendars for the following instrument types: Bond, ComplexBond, InterestRateSwap, CreditDefaultSwap, FixedLeg, FloatingLeg, TermDeposit, EquitySwap, CapFloor, CdsIndex, FundingLeg, InflationLinkedBond, InflationSwap.

Consider the example of a UK government bond that generates cashflows until expiry. The bond might have an economic definition with a startDate of 1 January 2022 and an annual paymentFrequency, meaning all cashflows until 2052 (annual coupon payments and the final principal repayment) are scheduled for distribution on a UK public holiday. You can specify:

  • A rollconvention to determine the day a payment occurs.

  • A businessDayConvention to determine what happens if the scheduled day falls on a non-business day.

  • Calendar code(s) in paymentCalendars to determine good business days in appropriate jurisdiction(s). If more than one calendar code is specified, holidays for all the specified calendars are applied. Note calendar codes must exist in the calendar scope specified in a recipe.

More about roll conventions and business day conventions.

For example:

curl -X POST "https://<your-domain>.lusid.com/api/api/instruments"
  -H "Authorization: Bearer <your-API-access-token>"
  -H "Content-Type: application/json"
  -d '{"upsert-request-1": {
    "name": "T 3 01/01/52",
    "identifiers": {
      "ClientInternal": {"value": "T_3_01/01/52"}
      },
    "definition": {
      "instrumentType": "Bond",
      "startDate": "2022-01-01T10:00:00.0000000+00:00",
      "maturityDate": "2052-01-01T10:00:00.0000000+00:00",
      "identifiers": {},
      "flowConventions": {
        "currency": "GBP",
        "paymentFrequency": "1Y",
        "dayCountConvention": "Act365",
        "paymentCalendars": ["GBP"],        "rollConvention": "1",
        "resetCalendars": [],
        "resetDays": 0,
        "businessDayConvention": "ModifiedFollowing"
      },
      "domCcy": "GBP",
      "couponRate": 0.015,
      "principal": 1
    }
  }
}'

LUSID has numerous tools to manage cashflows. For example, you can call the GetUpsertablePortfolioCashFlows API for a transaction portfolio containing this example of a 2052 UK government bond to retrieve expected cashflows between 2045 and 2052 in a format ready-to-upsert into LUSID:

curl -X GET "https://<yourdomain>.lusid.com/api/api/transactionportfolios/<scope>/<code>/upsertablecashflows?effectiveAt=2022-01-01T10%3A00%3A00Z&windowStart=2045-01-01T10%3A00%3A00Z&windowEnd=2053-01-01T10%3A00%3A00Z&excludeUnsettledTrades=true"
  -H "Authorization: Bearer <your-API-access-token>"

Note the following:

  • Most years, cashflows are distributed on 2 January, which is the next available business day.

  • Some years, when the UK public holiday falls on a Friday, Saturday or Sunday, cashflows are distributed on subsequent days instead:

Using calendars to perform valuations on business days

When you perform a valuation you can specify a schedule encompassing a range of dates. LUSID then produces a separate report for each weekday in the range (Saturdays and Sundays are omitted).

To factor market holidays into your valuation schedule, call the GetValuation API and specify within the valuationSchedule object:

  • One or more calendar codes in holidayCalendars for the market holiday data you want LUSID to consider in your valuation. If more than one calendar code is specified, all holidays for all the specified calendars are applied. Note the calendar codes you choose must exist in the calendar scope specified in the recipe for the valuation.

  • A rollConvention for how the date should be changed if the valuation happens to fall on a holiday. Find out more about roll conventions.

  • An effectiveFrom and effectiveAt date.

Note: The operation only adjusts dates according to calendar data in this way if you are valuing across a range of dates. If you only specify a single effectiveAt date, the operation produces a valuation for that exact date, regardless of whether the date is a business day or not.

Consider the following example of factoring in market holidays when valuing this multi-asset, multi-region portfolio between 2 January 2023 (a UK public holiday) and 5 January 2023:

curl -X POST "https://<your-domain>.lusid.com/api/api/aggregation/$valuation"
  -H "Authorization: Bearer <your-API-access-token>"
  -H "Content-Type: application/json-patch+json"
  -d '{
    "portfolioEntityIds": [
      {"scope": "my-portfolio-scope", "code": "my-portfolio-code"}
    ],
    "recipeId": {"scope": "my-recipe-scope", "code": "my-recipe-code"},
    "valuationSchedule": {
      "effectiveFrom": "2023-01-02T00:00:00.0000000+00:00",
      "effectiveAt": "2023-01-05T00:00:00.0000000+00:00",
      "rollConvention": "ModifiedFollowing",
      "holidayCalendars": ["GBP"]
    },
    "metrics": [
      {"key": "Valuation/EffectiveAt", "op": "Value"},
      {"key": "Holding/Cost/Pfolio", "op": "Sum"},
      {"key": "Valuation/PvInPortfolioCcy", "op": "Sum"},
      {"key": "Valuation/PnL/Unrealised/PfolioCcy", "op": "Sum"}
    ],
    "groupBy": ["Valuation/EffectiveAt"]
  }'

Without specifying any holidayCalendars, the daily valuation looks like this, with all dates listed…

…but with holidayCalendars specified, the operation accounts for the UK public holiday on 2 January 2023 and only returns a daily valuation for business days:

Using calendars to reconcile valuations on business days

You can use calendars to factor in market holidays when performing a valuation reconciliation over a series of dates. To do this, call the ReconcileGeneric API, specifying within the valuationSchedule object for each of the left- and right-hand sides:

  • One or more calendar codes in holidayCalendars for the market holiday data you want LUSID to consider in your reconciliation. If more than one calendar code is specified, all holidays for all the specified calendars are applied. Note calendar codes must exist in the calendar scope specified in the recipe used for the reconciliation.

  • A rollConvention for how the date should be changed if the valuation happens to fall on a holiday. Find out more about roll conventions.

  • An effectiveFrom and effectiveAt date.

Consider the following example, of factoring in market holidays when reconciling daily valuations between 2 January 2023 (a UK public holiday) and 5 January 2023 for two portfolios containing the same instruments but using data from different data providers:

curl -X POST "https://<your-domain>.lusid.com/api/api/portfolios/$reconcileGeneric"
  -H "Authorization: Bearer <your-API-access-token>"
  -H "Content-Type: application/json-patch+json"
  -d '{
    "left": {
      "portfolioEntityIds": [
        {"scope": "my-left-portfolio-scope", "code": "my-left-portfolio-code"}
      ],
      "recipeId": {"scope": "my-left-recipe-scope", "code": "my-left-recipe-code"},
      "valuationSchedule": {
        "effectiveFrom": "2023-01-02T00:00:00.0000000+00:00",
        "effectiveAt": "2023-01-05T00:00:00.0000000+00:00",
        "rollConvention": "ModifiedFollowing",
        "holidayCalendars": ["GBP"]
      },
      "metrics": [
        {"key": "Valuation/EffectiveAt", "op": "Value"},
        {"key": "Valuation/PvInPortfolioCcy", "op": "Sum"}
      ],
      "groupBy": ["Valuation/EffectiveAt"],
    },
    "right": {
      "portfolioEntityIds": [
        {"scope": "my-right-portfolio-scope", "code": "my-right-portfolio-code"}
      ],
      "recipeId": {"scope": "my-right-recipe-scope", "code": "my-right-recipe-code"},
      "valuationSchedule": {
        "effectiveFrom": "2023-01-02T00:00:00.0000000+00:00",
        "effectiveAt": "2023-01-05T00:00:00.0000000+00:00",
        "rollConvention": "ModifiedFollowing",
        "holidayCalendars": ["GBP"]
      },
      "metrics": [
        {"key": "Valuation/EffectiveAt", "op": "Value"},
        {"key": "Valuation/PvInPortfolioCcy", "op": "Sum"}
      ],
      "groupBy": ["Valuation/EffectiveAt"],
    }
  }'

Without specifying any holidayCalendars, the daily valuation reconciliation looks like this, with all dates listed…

…but with holidayCalendars specified, the operation accounts for the UK public holiday on 2 January 2023 and only returns a daily valuation reconciliation for business days:

Changing calendar scope in a recipe

To select calendars from a scope other than the default CoppClarkHolidayCalendars, you will need to change your recipe. Specify the following market data options:

  • The calendarScope of a different set of calendars.

  • A defaultScope for a scope in which data should be located for rules you choose not to define in your recipe.

Note: You must specify a defaultScope when you set market options in a recipe. You can reset defaultScope to default to use the default LUSID settings.

curl -X POST "https://<your-domain>.lusid.com/api/api/recipes"
-H "Authorization: Bearer <your-API-access-token>"
-H "Content-Type: application/json"
-d '{
  "configurationRecipe": {
    "scope": "my-recipe-scope",
    "code": "my-recipe-code",
    "market": {
      "marketRules": [
        {
          "key": "Quote.Figi.*",
          "supplier": "Lusid",
          "dataScope": "MyQuoteScope",
          "quoteType": "Price",
          "field": "Mid",
          "sourceSystem": "Lusid"
        }
      ],
      "options": {
        "defaultScope": "default",
        "calendarScope": "my-own-calendar-scope",
      },
    },
    "description": "A recipe set to use calendars from a source other than Copp Clark",
  }
}'