Let's imagine we are preparing a fund with two share classes for launch.

We have already set up the underlying ABOR to have a single transaction portfolio.

Fund Z

Currency (of underlying ABOR)

GBP

Launch date

2024-01-01

Share class A

Share class B

Launch price

1

1

Currency

GBP

USD

Initial funding

£15000

$5000

Identifying short code

ShareClassA

ShareClassB

Mastering the share classes as instruments in the LUSID Security Master

We can call the UpsertInstruments API to master two instruments of type FundShareClass with different currencies and other characteristics in a custom MyShareClassInstrumentScope. More on mastering share classes.

curl -X POST 'https://<your-domain>.lusid.com/api/api/instruments?scope=MyShareClassInstrumentScope'
  -H 'Content-Type: application/json-patch+json'
  -H 'Authorization: Bearer <your-API-access-token>'
  -d '{
  "ephemeral-id-1": {
    "name": "Share class A",
    "identifiers": {
      "ClientInternal": {"value": "ShareClassA-Id"}
    },
    "definition": {
      "instrumentType": "FundShareClass",
      "shortCode": "ShareClassA",
      "fundShareClassType": "Income",
      "distributionPaymentType": "Net",
      "domCcy": "GBP",
      "hedging": "None"
    }
  },
  "ephemeral-id-2": {
    "name": "Share class B",
    "identifiers": {
      "ClientInternal": {"value": "ShareClassB-Id"}
    },
    "definition": {
      "instrumentType": "FundShareClass",
      "shortCode": "ShareClassB",
      "fundShareClassType": "Accumulation",
      "distributionPaymentType": "Gross",
      "domCcy": "USD",
      "hedging": "ApplyHedging"
    }
  },
}'

Note that LUSID automatically generates a LUID for each mastered share class instrument that uniquely identifies it, for example:

Setting up unitisation rules in the fund configuration module

LUSID calculates fund GAV as follows:

GAV = Dealing + PnL

…where dealing is subscriptions into—and redemptions out of—the fund. The purpose of the fund configuration module is to identify which general ledger accounts store journal entry lines representing dealing and PnL amounts.

Imagine we have the following chart of accounts in the underlying ABOR:

We can call the CreateFundConfiguration API to create a module with a scope of MyFunds and a code of StandardConfigModule identifying the relevant accounts. More on creating fund configuration modules.

curl -X POST 'https://<your-domain>.lusid.com/api/api/fundconfigurations/MyFunds'
  -H 'Content-Type: application/json-patch+json'
  -H 'Authorization: Bearer <your-API-access-token>'
  -d '{
  "code": "StandardConfigModule",
  "displayName": "Standard Fund Configuration",
  "dealingFilters": [
    {
      "filterId": "SUBS",
      "filter": "generalLedgerAccountCode eq '3-Subscriptions'"
    },
    {
      "filterId": "REDS",
      "filter": "generalLedgerAccountCode eq '4-Redemptions'"
    }
  ],
  "pnlFilters": [
    {
      "filterId": "PnL",
      "filter": "generalLedgerAccountCode eq '5-PnL'"
    }
  ],
  "backOutFilters": []
}'

Creating the fund

We can now call the CreateFund API to create a fund with a scope of MyFunds and a code of FundZ that references the underlying ABOR, the fund configuration module, and the two share class instruments with their launch prices in the custom instrument scope. More on creating funds.

curl -X POST 'https://<your-domain>.lusid.com/api/api/funds/MyFunds'
  -H 'Content-Type: application/json-patch+json'
  -H 'Authorization: Bearer <your-API-access-token>'
  -d '{
  "code": "FundZ",
  "displayName": "Growth Fund",
  "description": "Fund for growth",
  "aborId": {"scope": "MyAbors", "code": "StandardAbor"},
  "fundConfigurationId": {
    "scope": "MyFunds", 
    "code": "StandardConfigModule"
  },
  "shareClassInstrumentScopes": [
    "MyShareClassInstrumentScope",
  ],
  "shareClassInstruments": [
    {
      "instrumentIdentifiers": {
        "Instrument/default/LusidInstrumentId": "LUID_00003E1X",
        "launchPrice": 1,
      }
    },
    {
      "instrumentIdentifiers": {
        "Instrument/default/LusidInstrumentId": "LUID_00003E1Y",
        "launchPrice": 1,
      }
    }
  ],
  "type": "Standalone",
  "inceptionDate": "2024-01-01T00:00:00Z",
  "decimalPlaces": 2,
  "yearEndDate": {"day": 31, "month": 12}
}'

Assigning particular transactions to share classes

Transactions in the underlying portfolio that only apply to a particular share class must be explicitly assigned to that share class. Typically these are:

  • Subscription (funds in) and redemption (funds out) transactions (manually loaded into LUSID).

  • Certain share class-specific fee transactions (auto-generated by LUSID).

  • Distribution transactions.

Note: Transactions recording the purchase/sale of instruments typically do not belong to share classes but rather to the whole fund.

There are numerous ways to assign transactions to share classes and the following is just a recommendation.

Creating a property type to tag subscriptions and redemptions

We can call the CreatePropertyDefinition API to define a Transaction/MyFundProperties/ShareClass custom property in preparation for tagging appropriate transactions (such as subscriptions and redemptions) with the shortCode of the share class to which they belong:

curl -X POST 'https://<your-domain>.lusid.com/api/api/propertydefinitions"'
  -H 'Authorization: Bearer <your-API-access-token>'
  -H 'Content-Type: application/json-patch+json'
  -d '{
    "domain": "Transaction",
    "scope": "MyFundProperties",
    "code": "ShareClass",
    "displayName": "Fund share class",
    "dataTypeId": {"scope": "system", "code": "string"},
    "lifeTime": "Perpetual",
    "constraintStyle": "Property",
    "propertyDescription": "Share class to which a transaction belongs"
  }'

Creating suitable transaction types for subscriptions and redemptions

The most effective way to assign suitably-tagged subscription/redemption transactions to a share class is to use their respective transaction types to map the tagging custom property to the Transaction/default/ShareClassFundCode system property. Note we only want to do this on the Capital movement and not on the CashAccrual movement.

We can call the SetTransactionType API to create suitable Subscription and Redemption transaction types in the default scope and source, for example:

Subscription transaction type

Redemption transaction type

curl -X PUT 'https://<your-domain>.lusid.com/api/api/
transactionconfiguration/types/default/Subscription?scope=default'
  -H 'Content-Type: application/json-patch+json'
  -H 'Authorization: Bearer <your-API-access-token>'
  -d '{
  "aliases": [
    {
      "type": "Subscription",
      "description": "Transaction type for subscriptions",
      "transactionClass": "Longer",
      "transactionRoles": "AllRoles",
      "isDefault": false
    }
  ],
  "movements": [
    {
      "name": "Add cash to fund"
      "movementTypes": "CashAccrual",
      "side": "Side1",
      "direction": 1
    },
    {
      "name": "Assign cash to share class"
      "movementTypes": "Capital",
      "side": "Side1",
      "direction": 1,
      "mappings": [
        {
          "propertyKey": "Transaction/default/ShareClassShortCode",
          "mapFrom": "Transaction/MyFundProperties/ShareClass"
        }
      ]
    }
  ]
}'
curl -X PUT 'https://<your-domain>.lusid.com/api/api/
transactionconfiguration/types/default/Redemption?scope=default'
  -H 'Content-Type: application/json-patch+json'
  -H 'Authorization: Bearer <your-API-access-token>'
  -d '{
  "aliases": [
    {
      "type": "Redemption",
      "description": "Transaction type for redemptions",
      "transactionClass": "Shorter",
      "transactionRoles": "AllRoles",
      "isDefault": false
    }
  ],
  "movements": [
    {
      "name": "Remove cash from fund"
      "movementTypes": "CashAccrual",
      "side": "Side1",
      "direction": -1
    },
    {
      "name": "De-assign cash from share class"
      "movementTypes": "Capital",
      "side": "Side1",
      "direction": -1,
      "mappings": [
        {
          "propertyKey": "Transaction/default/ShareClassShortCode",
          "mapFrom": "Transaction/MyFundProperties/ShareClass"
        }
      ]
    }
  ]
}'

Registering the SHK with the underlying transaction portfolio

We must register the Transaction/default/ShareClassShortCode system property as a sub-holding key (SHK) with the portfolio in the underlying ABOR in order to segregate share class-specific transactions from generic fund transactions (such as purchase and sale transactions).

We can call the PatchPortfolioDetails API to patch an existing portfolio with a scope of MyAbors and code of Equities as follows:

curl -X POST 'https://<your-domain>.lusid.com/api/api/transactionportfolios/MyAbors/Equities/details'
 -H 'Authorization: Bearer <your-API-access-token>'
 -H 'Content-Type: application/json-patch+json'
 -d '[
  {
    "value": ["Transaction/default/ShareClassShortCode"],
    "path": "/subHoldingKeys/-",
    "op": "add"
  }
]'

Note /- at the end of "path": "/subHoldingKeys/-" appends this SHK to the end of the list; otherwise, existing portfolio SHKs are overwritten.

Funding the fund at the start of Day 1

We can call the BatchUpsertTransactions API to upsert two subscription transactions with the share class to which they belong tagged using the Transaction/MyFundProperties/ShareClass custom property:

  • £15000 for ShareClassA.

  • $5000 for ShareClassB at a USD/GBP trade to portfolio rate of 0.75.

Subscription transaction for ShareClassA

Subscription transaction for ShareClassB

curl -X POST 'https://<your-domain>.lusid.com/api/api/transactionportfolios/
MyAbors/Equities/transactions/$batchUpsert?successMode=Partial' 
  -H 'Content-Type: application/json-patch+json'
  -H 'Authorization: Bearer <your-API-access-token>'
  -d '{
  "ephemeral-id-1": {
    "transactionId": "Txn-001",
    "type": "Subscription",
    "instrumentIdentifiers": {
      "Instrument/default/LusidInstrumentId": "CCY_GBP"
    },
    "transactionDate": "2024-01-01T00:00:00.0000000+00:00",
    "settlementDate": "2024-01-01T00:00:00.0000000+00:00",
    "units": 15000,
    "totalConsideration": {"amount": 15000, "currency": "GBP"},
    "properties": {
      "Transaction/MyFundProperties/ShareClass": {
        "key": "Transaction/MyFundProperties/ShareClass",
        "value": {
          "labelValue": "ShareClassA"
        }
      }
    }
  }
}'

curl -X POST 'https://<your-domain>.lusid.com/api/api/transactionportfolios/
MyAbors/Equities/transactions/$batchUpsert?successMode=Partial' 
  -H 'Content-Type: application/json-patch+json'
  -H 'Authorization: Bearer <your-API-access-token>'
  -d '{
  "ephemeral-id-1": {
    "transactionId": "Txn-002",
    "type": "Subscription",
    "instrumentIdentifiers": {
      "Instrument/default/LusidInstrumentId": "CCY_USD"
    },
    "transactionDate": "2024-01-01T00:00:00.0000000+00:00",
    "settlementDate": "2024-01-01T00:00:00.0000000+00:00",
    "units": 5000,
    "totalConsideration": {"amount": 5000, "currency": "USD"},
    "properties": {
      "Transaction/MyFundProperties/ShareClass": {
        "key": "Transaction/MyFundProperties/ShareClass",
        "value": {
          "labelValue": "ShareClassB"
        }
      },
      "Transaction/default/TradeToPortfolioRate": {
        "key": "Transaction/default/TradeToPortfolioRate",
        "value": {
          "metricValue": {
            "value": 0.75, "unit": "USD/GBP"
          }
        }
      }
    }
  }
}'

Valuing the fund at the end of Day 1

Let’s imagine there has been a small change in the USD/GBP exchange rate during the day (from 0.75 to 0.8) but no other activity.

We can call the UpsertDiaryEntryTypeValuationPoint API and then the GetValuationPointData API to estimate the fund’s value at the end of the day. Note the response is quite large so here it is broken down into sections. More on valuing funds.

Fund valuation

Note the following:

  • Fund gav is £18750 (subscriptions in fund currency) + £250 (P&L from the currency gain/loss) = £19000

  • Fund nav is the same since no fees have yet been added to the fund.

  • This is the first fund valuation, so the previous nav is 0.

  "fundValuationPointData": {
    "backOut": {},
    "dealing": {
      "SUBS": {
        "value": 18750
      },
      "REDS": {
        "value": 0
      }
    },
    "pnL": {
      "nonClassSpecificPnl": {
        "PNL": {
          "value": 250
        }
      },
      "aggregatedClassPnl": {
        "PNL": {
          "value": 0
        }
      },
      "totalPnl": {
        "PNL": {
          "value": 250
        }
      }
    },
    "gav": 19000,
    "fees": {},
    "nav": 19000,
    "miscellaneous": {},
    "previousValuationPointData": {
      "nav": {
        "amount": 0
      }
    }
  }

Share class A valuation

£15000 was added to this share class (whose currency is the same as the fund currency). Note the following:

  • classDealingUnits is total dealing units in this valuation period: 15000 (subscriptions) + 0 (redemptions) = 15000.

  • classDealing is the total value of these dealing units in fund currency: £15000 (subscriptions) + £0 (redemptions) = £15000.

  • sharesInIssue is classDealingUnits from the previous valuation period plus classDealingUnits in this period: 0 + 15000 = 15000.

  • capitalRatio is share class A’s nav from the previous valuation period plus classDealing in this period divided by the total of the same for all share classes in the fund: (£0 + £15000) / £18750 = 0.8 (this means the capitalRatio of share class B is 0.2).

  • totalPnl is total fund PnL apportioned to share class A using capitalRatio: £250 × 0.8 = £200.

  • gav is classDealing  plus totalPnl: £15000 + £200 = £15200 (and nav is the same since there are no fees).

  • unitPrice is nav divided by sharesInIssue: 15200 / 15000 = 1.013333.

   "ShareClassA": {
      "shareClassBreakdown": {
        "backOut": {},
        "dealing": {
          "classDealing": {
            "SUBS": {
              "fundCurrencyAmount": 15000,
              "shareClassCurrencyAmount": 15000
            },
            "REDS": {
              "fundCurrencyAmount": 0,
              "shareClassCurrencyAmount": 0
            }
          },
          "classDealingUnits": {
            "SUBS": {
              "value": 15000
            },
            "REDS": {
              "value": 0
            }
          }
        },
        "pnL": {
          "apportionedNonClassSpecificPnl": {
            "PNL": {
              "fundCurrencyAmount": 200,
              "shareClassCurrencyAmount": 200
            }
          },
          "classPnl": {
            "PNL": {
              "fundCurrencyAmount": 0,
              "shareClassCurrencyAmount": 0
            }
          },
          "totalPnl": {
            "PNL": {
              "fundCurrencyAmount": 200,
              "shareClassCurrencyAmount": 200
            }
          }
        },
        "gav": {
          "fundCurrencyAmount": 15200,
          "shareClassCurrencyAmount": 15200
        },
        "fees": {},
        "nav": {
          "fundCurrencyAmount": 15200,
          "shareClassCurrencyAmount": 15200
        },
        "unitisation": {
          "sharesInIssue": 15000,
          "unitPrice": 1.013333,
          "netDealingUnits": 15000
        },
        "miscellaneous": {},
        "shareClassToFundFxRate": 1,
        "capitalRatio": 0.8,
        "previousShareClassBreakdown": {
          "nav": {
            "amount": {
              "fundCurrencyAmount": 0,
              "shareClassCurrencyAmount": 0
            }
          },
          "shareClassToFundFxRate": 1
        }
      },
      "shareClassDetails": {
        "lusidInstrumentId": "LUID_00003E1X",
        "instrumentScope": "MyShareClassInstrumentScope",
        "domCurrency": "GBP",
        "instrumentActive": true
      }
    }

Share class B valuation

$5000 was added to this share class at a USD/GBP rate of 0.75 = £3750. Note the following:

  • classDealingUnits is total dealing units in this valuation period: 5000 (subscriptions) + 0 (redemptions) = 5000.

  • classDealing is the total value of these dealing units in fund currency: £3750 (subscriptions) + £0 (redemptions) = £3750.

  • sharesInIssue is classDealingUnits in the previous valuation period plus classDealingUnits in this period: 0 + 5000 = 5000.

  • shareClassToFundFxRate is the USD/GBP exchange rate at the valuation point: 0.8.

  • capitalRatio is share class B’s nav from the previous valuation period plus classDealing in this period divided by the total of the same for all share classes in the fund: (£0 + £3750) / £18750 = 0.2 (this means the capitalRatio of share class A is 0.8).

  • totalPnl is total fund PnL apportioned to share class B using capitalRatio: £250 × 0.2 = £50.

  • gav is classDealing  plus totalPnl: £3750 + £50 = £3800 (and nav is the same since there are no fees).

  • unitPrice is nav divided by sharesInIssue and further divided by shareClassToFundFxRate to convert to share class currency: (3800 / 5000) / 0.8 = 0.95.

    "ShareClassB": {
      "shareClassBreakdown": {
        "backOut": {},
        "dealing": {
          "classDealing": {
            "SUBS": {
              "fundCurrencyAmount": 3750,
            },
            "REDS": {
              "fundCurrencyAmount": 0,
            }
          },
          "classDealingUnits": {
            "SUBS": {
              "value": 5000
            },
            "REDS": {
              "value": 0
            }
          }
        },
        "pnL": {
          "apportionedNonClassSpecificPnl": {
            "PNL": {
              "fundCurrencyAmount": 50,
              "shareClassCurrencyAmount": 62.5
            }
          },
          "classPnl": {
            "PNL": {
              "fundCurrencyAmount": 0,
              "shareClassCurrencyAmount": 0
            }
          },
          "totalPnl": {
            "PNL": {
              "fundCurrencyAmount": 50,
              "shareClassCurrencyAmount": 62.5
            }
          }
        },
        "gav": {
          "fundCurrencyAmount": 3800,
          "shareClassCurrencyAmount": 4750
        },
        "fees": {},
        "nav": {
          "fundCurrencyAmount": 3800,
          "shareClassCurrencyAmount": 4750
        },
        "unitisation": {
          "sharesInIssue": 5000,
          "unitPrice": 0.95,
          "netDealingUnits": 5000
        },
        "miscellaneous": {},
        "shareClassToFundFxRate": 0.8,
        "capitalRatio": 0.2,
        "previousShareClassBreakdown": {
          "nav": {
            "amount": {
              "fundCurrencyAmount": 0,
              "shareClassCurrencyAmount": 0
            }
          },
          "shareClassToFundFxRate": 1
        }
      },
      "shareClassDetails": {
        "lusidInstrumentId": "LUID_00003E1Y",
        "instrumentScope": "MyShareClassInstrumentScope",
        "domCurrency": "USD",
        "instrumentActive": true
      }
    }