LUSID is an API-first, SaaS-native investment data management platform.
To get started, we'll explore fundamental principles and demonstrate core capabilities by using LUSID to perform the following task:
“As a UK asset manager, I run a single portfolio containing UK equities and investment-grade vanilla bonds, and additionally maintain a cash position. The portfolio contains around 20 positions and trades around 5 positions a week. I want to view the asset allocation (equities vs. bonds vs. cash) on a daily basis.”
We'll see how to:
- Model this scenario in LUSID using entities such as instruments, portfolios, transactions and more.
- Load trade and market data into LUSID.
- Generate positions and assemble the information required to value the portfolio on a per asset class basis.
You can examine and run the complete code sample for this exercise from this Jupyter Notebook, providing you have suitable access control permissions. This should automatically be the case if you set up your own LUSID domain (more on that below). If you are informed you do not have a license to perform a particular operation, please contact support.
- Section 1: Setting up your own LUSID domain
- Section 2: Understanding fundamental principles of LUSID
- Section 3: Populating the instrument master
- Section 4: Creating a portfolio
- Section 5: Setting initial positions
- Section 6: Generating holdings
- Section 7: Valuing the portfolio
If you haven't already, the first task is set up your own LUSID domain (instance) by starting a free trial.
Your LUSID domain:
- Is completely private to you. You'll share cloud infrastructure with other triallists in a multi-tenant environment, with strict safeguards in place to ensure data is segregated. When you go live, you can choose to migrate to a single tenant environment. More information.
- Does not expire (there is no timeout to the trial, although you'll be asked to change your password every six months).
- Has a standard license. Some advanced functionality is hidden behind additional licenses, but you can explore core capabilities using any of the interfaces and applications described here, including the REST API, SDKs and the web app. If you've never seen LUSID before, sign in to your web app to take a tour.
- Automatically creates a LUSID user for you, the domain owner, with full administrative privileges. You can onboard as many other users as you like, and restrict their access control permissions to reflect their professional responsibilities.
- Automatically creates an application that encapsulates the credentials required (client ID and client secret) to interact with LUSID using the REST API and/or SDKs. More information.
- Automatically loads demonstration data (portfolios, instruments and transactions) into a particular scope (see below).
Before we get started using LUSID to manage investment data, it's important to understand core LUSID concepts.
|LUSID has a schema-on-read data model|
LUSID's data model is designed to be flexible rather than constrain your data to our view of the world. We require you to model only a small set of real-world objects as entities. For example:
See the full list of LUSID entities and their key characteristics. If you need to extend the built-in set, you can create custom entities (see the box below).
By design, an entity has a minimal set of fields. For example, to create a portfolio you only need specify values for the name, scope, code, and base currency fields. A portfolio has a few other optional fields as well that either default to sensible values or can be left empty. However, you can extend a portfolio (and most entities) by adding properties to store as much additional information as you need (see the box below).
LUSID also provides core system settings to make key operations possible out-of-the-box:
|LUSID's data model is fully extensible|
You can extend almost any aspect of LUSID's data model. This means you can consolidate data from different systems without undertaking expensive and time-consuming ETL operations, by mapping discrepancies between systems onto custom properties or entities. Data stored by LUSID in this way retains its format and lineage, so it remains meaningful to the originating system.
Data from different systems can co-exist in LUSID but you can extract business intelligence as though it were a homogeneous set. For example:
|LUSID has a fine-grained entitlements system|
LUSID denies access to all resources for every user—whether human being or automated service, either via the web app or by calling the API directly—until explicitly allowed.
LUSID has separate identity management and access control systems that work together to authenticate users and grant each the permissions they need to access data and perform operations in keeping with their professional responsibilities, and no more. Read our IAM documentation.
|LUSID partitions and entitles data using scopes|
Almost every data item in LUSID must be assigned to a scope (or namespace). This enables you to:
Within a scope, a data item has a code; together, the scope and code uniquely identify that data item. More information.
|LUSID is bitemporal and immutable|
Almost every data item in LUSID is stored with two timestamps:
You can roll back either timeline, which gives you unparalleled audit capability. For example, you could correct a wrongly-entered transaction, which leaves the transaction with the original effective at timestamp but gives it a new as at timestamp. You can then query LUSID for either the data as it is now, or roll back the as at timeline to query for the data as it was before the correction.
The important implication here is that no data is ever truly deleted in LUSID. This is because it must be possible to roll back the as at timeline to recreate the data as it was in the past. So when you 'delete' (for example) an instrument, what you are actually doing is time-limiting it's effective at timestamp from the as at timestamp of the delete operation. More information.
|LUSID is an ecosystem of applications|
The core LUSID investment management application is a RESTful API that you can integrate or build upon. LUSID also has a web app (GUI front end) that exercises the API and can be used as a standalone application if you wish.
The LUSID ecosystem also includes the following supporting applications:
|LUSID has numerous operational interfaces|
You can perform CRUD operations, and also analytical and reporting tasks, on the investment data stored in LUSID using the following tools and interfaces:
You should now have your own LUSID domain and an understanding of the principles that drive LUSID.
To complete the task of setting up a basic IBOR and valuing our portfolio on a per asset class basis, we need to explore the following tasks in a little more detail.
The first task is to create one instrument modelling each equity and bond we want to hold in our portfolio. Note the following about instruments:
- The LUSID instrument master is a central repository that every portfolio in LUSID accesses. You can optionally partition the instrument master into protected scopes, perhaps to hide sensitive contractual information encapsulated in derivative instruments.
- An instrument is an economic definition. Every instrument must have a name and at least one market identifier, such as a FIGI or ISIN. Other fields are specific to the type of asset, for example coupon rate and payment frequency for bonds. You can of course add properties to instruments to store as much additional information as you like.
- We provide templates to help you model equities, different types of bond, swaps, options, CFDs, FX forwards and more.
- Your LUSID domain is prepopulated with a basket of standard currencies, so there is already a GBP currency instrument; you don't need to model currencies explicitly.
- When you create an instrument, LUSID automatically generates a LUID (LUSID Unique ID), an internal identifier that is guaranteed to be unique and never change.
- Every transaction you upsert into LUSID must be booked with an identifier (such as a FIGI, ISIN or LUID) that enables LUSID to resolve it to a mastered instrument, in order to guarantee an accurate position.
Let's assume we have a CSV file exported from a database containing information about our assets:
Step 1 of the accompanying Jupyter Notebook demonstrates how to do this using the LUSID Python SDK. You can execute the Notebook in Jupyterhub for your LUSID domain and then sign in to the web app to see the results on the Instruments dashboard, available from the left-hand Data Management menu:
The next task is to create a portfolio to store transactions for the instruments we want to hold, from which LUSID can generate positions. Note the following about portfolios:
- There are different types of portfolio. We need to create a transaction portfolio.
- A portfolio must be given a creation date that precedes the date of the first transaction we intend to load into it.
- You have the option to specify sub-holding keys when you create a portfolio that subsequently enable you to partition individual positions, for example equities into different investment strategies, or cash balances into different types such as income and margin, and so on.
We need to call the LUSID CreatePortfolio API, specifying a suitable scope and code, and name and base currency.
Step 2 of the accompanying Jupyter Notebook demonstrates how to do this using the LUSID Python SDK. You can execute the Notebook in Jupyterhub for your LUSID domain and then sign in to the web app to see the portfolio on the Data Management > Portfolios dashboard.
The next task is to set initial positions for the instruments in our portfolio (including an initial cash position). There are two ways of doing this:
- If we have access to a stream of historical transactions, we can call the LUSID UpsertTransactions API to load them and then have LUSID automatically generate positions from the results of buys and sells.
- If not, we can call the LUSID SetHoldings API to set positions explicitly.
Step 3 of the accompanying Jupyter Notebook demonstrates how to call the SetHoldings API using the LUSID Python SDK. You can execute the Notebook in Jupyterhub for your LUSID domain and then sign in to the web app to see the results on the Dashboard > Transactions:
The next task is to ask LUSID to generate holdings (positions) for the instruments in our portfolio. Note the following about holdings:
- LUSID generates a holding on-the-fly by decomposing all the events impacting a particular instrument into their underlying economic movements: these events can be transactions (buys and sells), any manual holdings adjustments you have made, and any corporate actions that affect that instrument (such as a stock split).
- Each event has a transaction type that controls how and when the holding is updated, whether the effect is positive or negative, and whether other holdings are impacted. For example, the built-in Buy transaction type increases an equity holding by the number of units purchased, and simultaneously decreases your cash holding by the total consideration. You can of course configure transaction types to specify your own economic impacts.
- A cash holding in a particular currency may therefore be determined by events impacting cash directly (such as an injection of funds using the built-in FundsIn transaction type), but also by events impacting other holdings, including other cash holdings.
- By default, LUSID reports a single holding of type ‘position’ for non-cash instruments (such as equities and bonds), though you can change this using sub-holding keys. For cash, LUSID reports holdings of different types over time to reflect lifecycle events: ‘cash balance' for settled cash, ’cash commitment' for future payments, ‘cash receivable’ for expected income, and so on.
We need to call the LUSID GetHoldings API, specifying the scope and code of the portfolio to generate.
Step 4 of the accompanying Jupyter Notebook demonstrates how to do this using the LUSID Python SDK. You can execute the Notebook in Jupyterhub for your LUSID domain and then sign in to the web app to see the current positions on the Dashboard > Holdings:
The final task is to configure LUSID to value the positions in our portfolio, aggregating up to asset class. Note the following about valuation:
- LUSID requires market data to begin the pricing operation. For vanilla equities, this can simply be the current mid price sourced from a data vendor, but more complex instruments typically require complex market data such as FX rates or discount or interest rate curves.
- Some instruments have lifecycles and/or cashflow implications that affect valuation. For example, a bond's value is affected both by its market price and the interest accrued to date, and has a maturity date after which the instrument drops out of valuations.
- You must create a recipe that tells LUSID where to find market data, and which pricing model(s) and methodology to use to perform the valuation.
- You must specify aggregation rules that tell LUSID how to report information in a meaningful way. It's possible to aggregate by properties you've created yourself, but in this case we can also take advantage of a built-in system property (the AssetClass queryable key) to aggregate our valuations by asset class (equities vs. bonds vs. cash).
Once market data, a recipe and aggregation rules are in place, we can call the LUSID GetValuation API to actually perform the valuation.
Steps 5 and 6 of the accompanying Jupyter Notebook demonstrate how to do this using the LUSID Python SDK. You can execute the Notebook in Jupyterhub for your LUSID domain and then sign in to the web app to see aggregated valuations on the Dashboard > Valuations.
Note to see the dashboard as it is below, you need to click the cog icon (highlighted middle right), choose Add column, select the Queryable Key with an Address Key of Instrument/AssetClass (value), drag it to the grouping position (highlighted left) and set the Effective date to 01/01/2022 (highlighted top right).