--- title: "How do I load complex market data into LUSID?" slug: "how-do-i-upload-an-object-to-the-complex-market-data-store" tags: ["complex market data"] updated: 2026-10-10T09:48:09Z published: 2026-10-10T09:48:09Z canonical: "support.lusid.com/how-do-i-upload-an-object-to-the-complex-market-data-store" --- > ## Documentation Index > Fetch the complete documentation index at: https://support.lusid.com/llms.txt > Use this file to discover all available pages before exploring further. # How do I load complex market data into LUSID? You can load an object such as a discount factor curve, an FX forward curve or a volatility surface into the Complex Market Data (CMD) Store, for example a GBP OIS discount curve for 1 October 2026. Note the following: - Complex market data is required to value most instruments with a pricing model that discounts cashflows, projects interest or FX rates, or values options. [See the categories of complex market data](/v1/docs/categories-of-complex-market-data). - Each version of an object is a complete curve or surface for one effective date. To build a history, load the same object again with a new effective date each time. [Find out more about versions](/docs/how-do-i-upload-an-object-to-the-complex-market-data-store#subsequent-updates). - Choices you make when uploading market data impact the composition of the [recipe](/v1/docs/what-is-a-recipe) you must create in order to use that data. In particular, the name you give each object must follow the [naming syntax for its category](/v1/docs/categories-of-complex-market-data#how-lusid-names-and-finds-complex-market-data). ## Methods LUSID web appLUSID APILuminesce Navigate to **Data Management > Curves**, click the **New curve** button and choose a curve type. Enter the data in the editor, then click **Create** and specify a **Scope**, **Market Asset**, **Provider** and **Effective Date**. Note the following: - You can create FX forward curves, discount factor curves, yield curves (from swaps and FRAs), FX volatility surfaces and equity volatility surfaces (lognormal). To load any other category, use the API or Luminesce. - You type the **Market Asset** yourself, so make sure it follows the naming syntax for the category. For example, the FX forward curve editor suggests `USD/JPY`, which you must change to `USD/JPY/FxFwdCurve`. - LUSID saves an FX forward curve as `FxForwardTenorCurveData` if you enter a spot rate, or as `FxForwardTenorPipsCurveData` if you do not. - You cannot set a price source or curve options in the web app. To set either, use the API or Luminesce. ![](https://cdn.document360.io/d575ad81-c0ed-4980-bbd1-d59ac5c3de82/Images/Documentation/image-DLKJR9KA.png?sv=2026-02-06&spr=https&st=2026-11-09T06%3A00%3A21Z&se=2026-11-09T07%3A00%3A21Z&sr=c&sp=r&sig=hKGAK8z9tmQlrGfbBgl6b9iWYZ%2FB%2BxoYwHjFjfljBBA%3D) Call the [UpsertComplexMarketData](https://www.lusid.com/docs/api#operation/UpsertComplexMarketData) API to load up to 2000 objects in a single request. You must: - Encapsulate all the objects in a single `scope` (namespace) in the URL. - For each object, specify an ephemeral ID (to track errors in the response). In the following example, a GBP discount factor curve with curve options and a EUR/USD FX forward curve quoted in forward points are loaded together into a `MyCurves` scope: ```json curl -X POST "https://.lusid.com/api/api/complexmarketdata/MyCurves"  -H "Authorization: Bearer "  -H "Content-Type: application/json-patch+json"  -d '{  "CMD-0001": {    "marketDataId": {      "provider": "Lusid",      "effectiveAt": "2026-10-01T00:00:00Z",      "marketAsset": "GBP/GBPOIS"    },    "marketData": {      "marketDataType": "DiscountFactorCurveData",      "baseDate": "2026-10-01T00:00:00Z",      "dates": ["2027-01-01T00:00:00Z", "2027-10-01T00:00:00Z", "2028-10-01T00:00:00Z", "2031-10-01T00:00:00Z"],      "discountFactors": [0.9902, 0.9612, 0.9238, 0.8187],      "marketDataOptions": {        "marketDataOptionsType": "CurveOptions",        "interpolationType": "LinearOnLogDiscountFactors",        "backExtrapolationType": "Flat"      }    }  },  "CMD-0002": {    "marketDataId": {      "provider": "Lusid",      "effectiveAt": "2026-10-01T00:00:00Z",      "marketAsset": "EUR/USD/FxFwdCurve"    },    "marketData": {      "marketDataType": "FxForwardTenorPipsCurveData",      "baseDate": "2026-10-01T00:00:00Z",      "domCcy": "EUR",      "fgnCcy": "USD",      "tenors": ["1M", "3M", "6M", "1Y"],      "pipRates": [6.75, 27.32, 49.20, 104.91]    }  } }' ``` We recommend checking the `failed` section of the response for any objects LUSID could not load. For a FX forward curve, you can write a Luminesce SQL query using the dedicated `Lusid.ComplexMarketData.FxForwardCurve` provider and execute it using a tool such as the LUSID web app. For any other object, use the `Lusid.ComplexMarketData.Writer` provider, specifying a `Scope` and `DefinitionJson` for each containing the same `marketDataId` and `marketData` as one object in the query: ```sql @table_of_data = select 'MyCurves' as Scope, '{"marketDataId": {"provider": "Lusid", "effectiveAt": "2026-10-01T00:00:00Z", "marketAsset": "GBP/GBPOIS"},  "marketData": {"marketDataType": "DiscountFactorCurveData", "baseDate": "2026-10-01T00:00:00Z",    "dates": ["2027-01-01T00:00:00Z", "2027-10-01T00:00:00Z", "2028-10-01T00:00:00Z"],    "discountFactors": [0.9902, 0.9612, 0.9238]}}' as DefinitionJson; select * from Lusid.ComplexMarketData.Writer where ToWrite = @table_of_data; ``` We recommend examining the `WriteErrorCode`, `WriteError` and `WriteErrorDetail` fields in the results to check each object loaded successfully. ## Data fields This section supplements the [API documentation](https://www.lusid.com/docs/api#operation/UpsertComplexMarketData) and on-screen help text in the LUSID web app. | Mandatory field or parameter | Allowed values | Must be matched in recipe? | | --- | --- | --- | | `scope` | Any, for example `MyCurves` | ✅ [dataScope field](/v1/docs/recipes-locating-market-data#summary-of-fields-in-a-market-data-rule) | | `provider` | [Any valid](/v1/docs/understanding-valid-market-data-provider-and-field-combinations), for example `Lusid` | ✅ [supplier field](/v1/docs/recipes-locating-market-data#summary-of-fields-in-a-market-data-rule) | | `marketAsset` | Must follow the [naming syntax](/v1/docs/categories-of-complex-market-data#how-lusid-names-and-finds-complex-market-data) for the category, for example `GBP/GBPOIS` for a GBP discount curve | ✅ [key field](/v1/docs/recipes-locating-market-data#more-information-on-the-key-field), for example `Rates.GBP.GBPOIS` or `Rates.*.*` | | `effectiveAt` | A UTC datetime, or date and [cut label](/v1/docs/what-is-a-cut-label) | ❌ [but must be within quoteInterval](/v1/docs/recipes-locating-market-data#more-information-on-the-quoteinterval-field) | | `marketDataType` | One of the [categories of complex market data](/v1/docs/categories-of-complex-market-data#summary-of-categories), for example `DiscountFactorCurveData` | ❌ | | Other `marketData` fields | Depend on the `marketDataType`, for example `baseDate`, `dates` and `discountFactors` for a discount factor curve. [Find out more about each category](/v1/docs/categories-of-complex-market-data). | ❌ | The following fields are optional: - A `priceSource` indicating a sub-supplier to the `provider`, for example Tradeweb or RRPS for Refinitiv DataScope. [**Match this using the priceSource field in a recipe**](/v1/docs/recipes-locating-market-data#summary-of-fields-in-a-market-data-rule). Note that if omitted, your recipe must also omit its `priceSource` field. - A `lineage` in `marketData` providing additional information. - A `marketDataOptions` object in `marketData` setting [curve options](/v1/docs/categories-of-complex-market-data#curve-options) such as interpolation and extrapolation, for categories that accept them. ## Subsequent updates LUSID identifies each object by its `scope`, `provider`, `priceSource` and `marketAsset`. An object can have many versions, each with a different `effectiveAt`, so one object can hold a complete history of a curve or surface. When you load an object, LUSID compares these four fields and the `effectiveAt` with the objects already in the CMD Store: - If the four fields and the `effectiveAt` all match an existing version, LUSID replaces that version with the new one. It replaces the whole version, so include every field you want to keep, not only the ones you changed. - If the four fields match but the `effectiveAt` is new, LUSID adds a version to the existing object and leaves its other versions in place. It does not create a new object. LUSID increases the object's `version.asAtVersionNumber`, which counts every change to the object at any effective date. This number does not tell you which version a valuation uses. - If any of the four fields differs, LUSID creates a new object. A valuation uses the version with the latest `effectiveAt` on or before the valuation date, provided it falls within the [quoteInterval](/v1/docs/recipes-locating-market-data#more-information-on-the-quoteinterval-field) in your recipe. For example, if an object has versions effective on 1 October and 8 October, a valuation on 3 October uses the 1 October version and a valuation on 9 October uses the 8 October version. To see the version in force on a particular date, call [GetComplexMarketData](https://www.lusid.com/docs/api#operation/GetComplexMarketData) with that date as the `effectiveAt`. The date does not need to match a version exactly. You cannot rename an object, move it to another scope, or change its provider or price source. Instead: 1. Load a copy of the object with the new values. 2. Delete the original. In the web app, click **Delete** on its row in **Data Management > Curves**. Using the API, call [DeleteComplexMarketData](https://www.lusid.com/docs/api#operation/DeleteComplexMarketData), specifying its `scope` and `marketDataId`. If you do not delete the original, both objects remain in the CMD Store and a valuation may use the one you meant to replace. To add a point to the end of an existing FX forward curve without loading the whole curve again, call the [UpsertAppendComplexMarketData](https://www.lusid.com/docs/api#operation/UpsertAppendComplexMarketData) API. The `effectiveAt` you specify must exactly match an existing version. ### Editing in the LUSID web app When you click **Edit** on an object in **Data Management > Curves** and then **Save**, the web app asks for the **Scope**, **Market Asset**, **Provider** and **Effective Date** again. To change the original object rather than create a new one, keep the **Scope**, **Market Asset** and **Provider** the same. The **Effective Date** then decides what happens: the same date replaces that version, and a different date adds a new version. The web app fills in the **Effective Date** from the curve's base date, which may differ from the version's effective date, and saves it without a time, so check it before you click **Save**. > **Note**: The web app does not keep an object's price source or curve options. If the object you want to edit has either, edit it using the API or Luminesce instead. Saving it in the web app creates a separate object without the price source, or replaces the version and resets its curve options to the defaults.