In this tutorial we'll see how to set up a ‘parent’ portfolio so that it holds a position in a ‘child’ portfolio. The child portfolio must first be securitised; that is, turned into an instrument. We can then purchase a quantity of this instrument in the parent portfolio in the normal way.
Note: To complete this tutorial, you must have suitable permissions. This can most easily be achieved by assigning your LUSID user the built-in lusid-administrator
role. This should already be the case if you are the domain owner.
We can then value the parent portfolio and drill down (or ‘lookthrough’) to value individual holdings in the securitised child portfolio. We can choose to scale the value of each child holding relative to the value of the child portfolio holding in the parent portfolio.
- Step 1: Understanding fund of funds hierarchy
- Step 2: Securitising a child transaction portfolio; that is, turning it into an instrument.
- Step 3: Creating a parent transaction portfolio.
- Step 4: Establishing a holding by purchasing a quantity of the securitised instrument in the parent portfolio.
- Step 5: Preparing to value the parent portfolio by:
- Loading market data for all the instruments; that is, for the securitised instrument, and for all the instruments in the child portfolio.
- Creating a recipe that marshals this market data, enables lookthrough, and requests report metrics.
- Step 6: Valuing the parent portfolio:
- On its own.
- With lookthrough into the child portfolio.
For further information and a more complex example, see this Jupyter Notebook. In particular, the Notebook includes an example of pricing a future on an equity index, and then expanding the price over the constituents of the underlying index.
Understanding fund of funds hierarchy
Consider the following example of a parent fund holding positions in three child funds, two of which themselves have children:
Note the following:
- The root portfolio must be a transaction portfolio.
- A child portfolio can either be a transaction portfolio or a reference portfolio.
- A child portfolio can itself be a parent portfolio; that is, you can nest to any depth. However, looping is not permitted; a parent portfolio cannot hold a position in a child that holds a position in the parent, and so on.
Securitising an existing child transaction portfolio
Imagine we have a GBP-denominated transaction portfolio with a scope
of Lookthrough
, a code
of Child
and holdings in a mix of US and UK equities and bonds:
The first step is to securitise this portfolio by obtaining an API token and calling the UpsertInstruments API, specifying:
- A friendly
name
for the instrument. - At least one of the unique
identifiers
(see a list), for exampleClientInternal
. - A suitable economic
definition
. This can use any of the supported templates, butSimpleInstrument
is recommended. Note thedomCcy
of the instrument should be set to the base currency of the child portfolio. - A
lookthroughPortfolioId
consisting of thescope
andcode
of the child portfolio.
More information about creating instruments.
For example, to create an instrument with a ClientInternal
identifier value of ChildInstrument
(highlighted in red):
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": "ChildInstrument",
"identifiers": {
"ClientInternal": {
"value": "ChildInstrument",
}
},
"lookThroughPortfolioId": {
"scope": "Lookthrough",
"code": "Child"
},
"definition": {
"instrumentType": "SimpleInstrument",
"domCcy": "GBP",
"assetClass": "Unknown",
"simpleInstrumentType": "Fund"
}
}
}'
Creating a parent transaction portfolio
We can call the CreatePortfolio API to create a parent transaction portfolio in a particular scope
, specifying a suitable code
, baseCurrency
and a created
date likely to precede that of any transactions loaded into it. More information about creating portfolios.
For example, to create a portfolio with a scope
of Lookthrough
and code
of Parent
:
curl -X POST "https://<your-domain>.lusid.com/api/api/transactionportfolios/Lookthrough"
-H "Authorization: Bearer <your-API-access-token>"
-H "Content-Type: application/json"
-d '{
"displayName": "Parent lookthrough portfolio",
"code": "Parent",
"created": "2022-01-01T00:00:00Z",
"baseCurrency": "GBP"
}'
Purchasing a quantity of the securitised instrument in the parent portfolio
We can call the UpsertTransactions API with the scope
and code
of the parent portfolio to establish a position in the child portfolio, ensuring the instrumentIdentifiers
section of the transaction contains the unique identifier type and value of the securitised instrument (highlighted in red below).
For example, to purchase 5
units of ChildInstrument
at a price of 20
per unit:
curl -X POST "https://<your-domain>.lusid.com/api/api/transactionportfolios/Lookthrough/Parent/transactions"
-H "Authorization: Bearer <your-API-access-token>"
-H "Content-Type: application/json"
-d '[
{
"transactionId": "Txn-0001",
"type": "StockIn",
"instrumentIdentifiers": {
"instrument/default/ClientInternal": "ChildInstrument"
},
"transactionDate": "2022-03-01T00:00:00Z",
"settlementDate": "2022-03-03T00:00:00Z",
"units": 5,
"transactionPrice": {
"price": 20,
"type": "Price"
},
"totalConsideration": {
"amount": 100,
"currency": "GBP"
},
"transactionCurrency": "GBP"
}
]'
More information about upserting transactions.
To confirm the position, we can call the GetHoldings API with the scope
and code
of the parent portfolio:
Loading market data into the LUSID quote store
We can call the UpsertQuotes API to load market data (prices and, if necessary, FX rates) for ChildInstrument
, and for all the instruments in the child portfolio, into a particular quote scope
. More information about upserting quotes.
For example, to upsert a price of 25
for ChildInstrument
effective 7 March 2022 into a quote scope
of LookthroughQuotes
(highlighted in red in the URL):
curl -X POST "https://<your-domain>.lusid.com/api/api/quotes/LookthroughQuotes"
-H "Authorization: Bearer <your-API-access-token>"
-H "Content-Type: application/json"
-d '{
"Quote-0001": {
"quoteId": {
"quoteSeriesId": {
"provider": "Lusid",
"instrumentIdType": "ClientInternal",
"instrumentId": "ChildInstrument",
"quoteType": "Price",
"field": "mid"
},
"effectiveAt": "2022-03-07T00:00:00Z"
},
"metricValue": {
"value": 25,
"unit": "GBP"
}
}
}'
Creating a suitable valuation recipe
We can call the UpsertConfigurationRecipe API to create a valuation recipe. Note the following:
- The
market
section must have market rules enabling LUSID to find quotes forChildInstrument
and for all the instruments in the child portfolio. - The
pricing
section must have a vendor model rule that enables lookthrough for the securitised instrument type, which in this case isSimpleInstrument
.
More information about creating recipes.
In the following example:
- The
Quote.Figi.*
market rule locates quotes for the equities and bonds in the child portfolio. - The
Quote.ClientInternal.*
market rule locates quotes forChildInstrument
. - The
Fx.CurrencyPair.*
market rule locates USD/GBP exchange rates. - The vendor model rule chooses the
SimpleStatic
pricing model for theSimpleInstrument
type, and enables lookthrough by settingportfolioScaling
toSum
andmodelOptionsType
toIndexModelOptions
(highlighted in red below). Note an alternative portfolio scaling option isUnity
; see Appendix A for more information.
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": "Lookthrough",
"code": "ParentIntoChildRecipe",
"market": {
"marketRules": [
{
"key": "Quote.Figi.*",
"supplier": "Lusid",
"dataScope": "LookthroughQuotes",
"quoteType": "Price",
"field": "mid"
},
{
"key": "Quote.ClientInternal.*",
"supplier": "Lusid",
"dataScope": "LookthroughQuotes",
"quoteType": "Price",
"field": "mid"
},
{
"key": "Fx.CurrencyPair.*",
"supplier": "Lusid",
"dataScope": "LookthroughQuotes",
"quoteType": "Rate",
"field": "mid"
}
]
},
"pricing": {
"modelRules": [
{
"supplier": "Lusid",
"modelName": "SimpleStatic",
"instrumentType": "SimpleInstrument",
"modelOptions": {
"portfolioScaling": "Sum",
"modelOptionsType": "IndexModelOptions"
}
}
]
}
}
}'
Note: It is possible to request many metrics when calling the GetValuation API, but not all are meaningful in a lookthrough valuation report. In particular, metrics relating to cost and PnL do not scale properly, since scaling computation happens at a point in time different to that when the costs were calculated. More information about metrics.
In our example, we'll request the following metrics:
Holding/default/Units
to scale the number of units in each child portfolio holding.Valuation/PV
to scale PV in the transaction currency for each holding.Valuation/Accrued
to scale accrual in the transaction currency for each bond holding.Valuation/PVInPortfolioCcy
to scale PV in the portfolio currency for each holding (GBP).Valuation/AccruedInPortfolioCcy
to scale accrual in the portfolio currency for each bond holding.Holding/default/FundLineage
to track thescope
andcode
of the parent and child portfolios
Note also that reportCurrency
should be set to the portfolio currency of the root portfolio in a hierarchy, in this case GBP
(highlighted in red below):
curl -X POST "https://<your-domain>.lusid.com/api/api/aggregation/$valuation"
-H "Authorization: Bearer <your-API-access-token>"
-H "Content-Type: application/json"
-d '{
"recipeId": {
"scope": "Lookthrough",
"code": "ParentIntoChildRecipe"
},
"metrics": [
{ "key": "Holding/default/Units", "op": "Value" },
{ "key": "Valuation/PV", "op": "Value" },
{ "key": "Valuation/Accrued", "op": "Value" },
{ "key": "Valuation/PvInPortfolioCcy", "op": "Value" },
{ "key": "Valuation/AccruedInPortfolioCcy", "op": "Value" },
{ "key": "Holding/default/FundLineage", "op": "Value" },
],
"reportCurrency": "GBP",
"portfolioEntityIds": [
{
"scope": "Lookthrough",
"code": "Parent",
}
],
"valuationSchedule": {
"effectiveAt": "2022-03-07T00:00:00Z",
}
}'
Valuing the parent portfolio
When we value our parent portfolio with lookthrough, holdings in the child portfolio are scaled relative to the value of the securitised instrument in the parent portfolio.
The easiest way to understand the scaling calculations is to work through an example. Imagine we value the child portfolio independently on 7 March 2022; we can see that the total PV in GBP (the child portfolio currency) is 295,236.04
(the sum of 120,000 + 37,800 + 101,340.11 + 36,095.93
):
Note: Throughout this example the USD/GBP trade to portfolio rate is fixed at 0.7
.
When we value the parent portfolio without lookthrough on 7 March 2022, we can see that the PV in GBP (the parent portfolio currency) of the securitised instrument is 125
:
Now when we value the parent portfolio with lookthrough on 7 March 2022 (using this recipe and metrics), we see that the unit, PV and accrual figures have been scaled down relative to its value:
The calculations are as follows:
Scaled metric | Calculation | BP | Microsoft | UKT 0 ⅜ 10/22/26 | T 2.375% Aug 15 2024 | |
PV in GBP | (125 / 295236.04) * 120000 = 50.81 | (125 / 295236.04) * 37800 = 16.00 | (125 / 295236.04) * 101340.11 = 42.91 | (125 / 295236.04) * 36095.93 = 15.28 | ||
Units | (125 / 295236.04) * 4000 = 1.69 | (125 / 295236.04) * 3000 = 1.27 | (125 / 295236.04) * 100000 = 42.34 | (125 / 295236.04) * 50000 = 21.17 | ||
Accrual in GBP | n/a | n/a | (125 / 295236.04) * 140.11 = 0.06 | (125 / 295236.04) * 45.93 = 0.02 |
Appendix A: Unity scaling
You can select Unity
rather than Sum
in your recipe to value a parent portfolio with lookthrough and scale holdings in the child portfolio directly by the number of units held in the securitised instrument rather than relative to its value:
"pricing": {
"modelRules": [
{
"supplier": "Lusid",
"modelName": "SimpleStatic",
"instrumentType": "SimpleInstrument",
"modelOptions": {
"portfolioScaling": "Unity",
"modelOptionsType": "IndexModelOptions"
}
}
]
}
For example, if we hold 5 units of the securitised instrument:
...then unit, PV and accrual figures are scaled 5 times: