Let's imagine we are preparing a fund with two share classes for launch.
For the purposes of this tutorial we assume we have performed steps 1 and 2 in this checklist to set up an underlying IBOR with a single portfolio and created a suitable chart of accounts.
Fund Z | ||
|---|---|---|
Currency (same as underlying portfolio) | 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 |
|
|
Mastering 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:
.png?sv=2022-11-02&spr=https&st=2025-11-02T11%3A16%3A14Z&se=2025-11-02T11%3A40%3A14Z&sr=c&sp=r&sig=doSgMA6z2nv2z3bG%2FUrELHGdDOZe45XaXUXD133A%2Fbc%3D)
Setting up unitisation rules in the pricing template
LUSID calculates fund GAV as follows:
GAV = Dealing + PnL
…where dealing is subscriptions into—and redemptions out of—the fund. The purpose of the pricing template is to identify which general ledger accounts store journal entry lines representing dealing and PnL amounts.
Imagine we have the following chart of accounts:
.png?sv=2022-11-02&spr=https&st=2025-11-02T11%3A16%3A14Z&se=2025-11-02T11%3A40%3A14Z&sr=c&sp=r&sig=doSgMA6z2nv2z3bG%2FUrELHGdDOZe45XaXUXD133A%2Fbc%3D)
We can call the CreateFundConfiguration API to create a template with a scope of MyFunds and a code of Standard identifying the relevant accounts. More on creating pricing templates.
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": "Standard",
"displayName": "Standard pricing template",
"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 sets up a primary NAV type and references the underlying IBOR, the pricing template, 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",
"baseCurrency": "GBP",
"portfolioIds": [
{
"scope": "Scope1",
"code": "Portfolio1",
"portfolioEntityType": "SinglePortfolio"
}
],
"fundConfigurationId": {
"scope": "MyFunds",
"code": "Standard"
},
"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": 6,
"primaryNavType": {
"code": "Daily",
"displayName": "Daily",
"description": "This is the primary NAV type",
"chartOfAccountsId": {
"scope": "ChartOfAccountsScope",
"code": "ChartOfAccountsCode"
},
"postingModuleCodes": [
"PostingModule1"
],
"cleardownModuleCodes": [
"CleardownModule1"
],
"valuationRecipeId": {
"scope": "RecipeScope",
"code": "RecipeCode"
},
"holdingRecipeId": {
"scope": "RecipeScope",
"code": "RecipeCode"
},
"accountingMethod": "FirstInFirstOut",
"subHoldingKeys": ["Transaction/default/ShareClassShortCode"],
"amortisationMethod": "EffectiveYield",
"transactionTypeScope": "TransactionTypeScope",
"cashGainLossCalculationDate": "Default"
}
}'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/ShareClassShortCode 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:
|
|
| |
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 IBOR 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 MyPortfolios and code of Equities as follows:
curl -X POST 'https://<your-domain>.lusid.com/api/api/transactionportfolios/MyPortfolios/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 and tag the share class to which they belong using the Transaction/MyFundProperties/ShareClass custom property. The total considerations are:
£15000 for
ShareClassA.$5000 for
ShareClassBat a USD/GBP trade to portfolio rate of 0.75.
Subscription transaction for | Subscription transaction for |
| |
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 large so it is broken down below into sections. More on valuing funds.
Fund valuation
Note the following:
This is the first fund valuation, so the
previousValuationPointData.navis 0.Fund
gavispreviousValuationPointData.navplus the sum of subscriptions/redemptions and P&L in this period: £0 + £18750 + £250 = £19000.Fund
navin this period is the same since no fees have yet been added to the fund.
"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:
classDealingUnitsis total dealing units in this valuation period: 15000 (subscriptions) + 0 (redemptions) = 15000.classDealingis the total value of these dealing units in fund currency: £15000 (subscriptions) + £0 (redemptions) = £15000.sharesInIssueisclassDealingUnitsfrom the previous valuation period plusclassDealingUnitsin this period: 0 + 15000 = 15000.capitalRatiois share class A’snavfrom the previous valuation period plusclassDealingin this period divided by the total of the same for all share classes in the fund: (£0 + £15000) / £18750 = 0.8 (this means thecapitalRatioof share class B is 0.2).totalPnlis total fund PnL apportioned to share class A usingcapitalRatio: £250 × 0.8 = £200.gavisclassDealingplustotalPnl: £15000 + £200 = £15200 (andnavis the same since there are no fees).unitPriceisnavdivided bysharesInIssue: 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:
classDealingUnitsis total dealing units in this valuation period: 5000 (subscriptions) + 0 (redemptions) = 5000.classDealingis the total value of these dealing units in fund currency: £3750 (subscriptions) + £0 (redemptions) = £3750.sharesInIssueisclassDealingUnitsin the previous valuation period plusclassDealingUnitsin this period: 0 + 5000 = 5000.shareClassToFundFxRateis the USD/GBP exchange rate at the valuation point: 0.8.capitalRatiois share class B’snavfrom the previous valuation period plusclassDealingin this period divided by the total of the same for all share classes in the fund: (£0 + £3750) / £18750 = 0.2 (this means thecapitalRatioof share class A is 0.8).totalPnlis total fund PnL apportioned to share class B usingcapitalRatio: £250 × 0.2 = £50.gavisclassDealingplustotalPnl: £3750 + £50 = £3800 (andnavis the same since there are no fees).unitPriceisnavdivided bysharesInIssueand further divided byshareClassToFundFxRateto 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
}
}