---
title: "Modelling repurchase agreements (repos) in LUSID"
slug: "modelling-repurchase-agreements-in-lusid"
tags: ["repo"]
updated: 2026-06-26T06:47:46Z
published: 2026-06-26T06:47:46Z
canonical: "support.lusid.com/modelling-repurchase-agreements-in-lusid"
---

> ## 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.

# Modelling repurchase agreements (repos) in LUSID

You can model a repurchase agreement (“repo”) as a buyer or as a seller using the `FlexibleRepo` instrument type. [See all supported instruments](/v1/docs/supported-instruments-in-lusid).

This article explains how to use the LUSID API to first master an instrument and then load a transaction:

- You can simplify setup by loading a transaction in the web app and have LUSID [master the instrument for you](/v1/docs/modelling-repurchase-agreements-in-lusid#appendix-using-the-lusid-web-app-to-simplify-repurchase-agreements).
- If you enable instrument events you must create transaction types to [handle those events](/v1/docs/handling-instrument-events-for-repurchase-agreements).
- For an implementation using the Python SDK see [this Jupyter Notebook](https://github.com/finbourne/finbourne-notebooks/blob/main/V3/features/instrument-events/flexiblerepo-and-instrument-events.ipynb).

## Mastering an instrument

There are [numerous tools](/v1/docs/how-do-i-master-an-instrument) you can use to master a `FlexibleRepo` in the LUSID Security Master.

Some fields are common to all types of instrument, such as an intuitive `name`, the [requirement to specify a set](/v1/docs/understanding-instrument-identifiers) of `identifiers`, and the facility to [store extra information](/v1/docs/properties) as `properties`.

Fields in the economic `definition` object are specific to `FlexibleRepo`. For more information on these fields, select **FlexibleRepo** from the **definition** dropdown in the [UpsertInstruments](https://www.lusid.com/docs/api/lusid/endpoints/instruments/UpsertInstruments) API reference, or alternatively examine the [FlexibleRepo](https://www.lusid.com/docs/api/lusid/schemas/FlexibleRepo/) schema:

![](https://cdn.document360.io/d575ad81-c0ed-4980-bbd1-d59ac5c3de82/Images/Documentation/image-CUKVC79B.png)

### Mastering a collateral instrument

If the repo has collateral that is a [supported instrument](/v1/docs/supported-instruments-in-lusid), master it separately and then provide a reference to a `MasteredInstrument`. [See how to master a bond](/v1/docs/modelling-fixed-rate-vanilla-bonds-in-lusid).

### Mastering a `FlexibleRepo` instrument

The following call to the [UpsertInstruments](https://www.lusid.com/docs/api/lusid/endpoints/instruments/UpsertInstruments) API masters a term repo as a buyer with a `MasteredInstrument` reference to a vanilla fixed-rate bond as collateral:

```json
curl -X POST 'https://mydomain.lusid.com/api/api/instruments?scope=MyCustomInstrScope'
   -H 'Content-Type: application/json-patch+json'
   -H 'Authorization: Bearer myAPIAccessToken'
   -d '{"upsert-request-1": {
    "name": "Buyer-TermFlexRepo",
    "identifiers": {"ClientInternal": {"value": "Buyer-TermFlexRepo"}},
    "definition": {
      "instrumentType": "FlexibleRepo",
      "startDate": "2025-01-02T00:00:00.0000000+00:00",
      "maturityDate": "2025-03-31T00:00:00.0000000+00:00",
      "buyerOrSeller": "Buyer",
      "repoCcy": "GBP",
      "repoType": "TermRepo",
      "accrualBasis": "Act365",
      "collateral": {
        "collateralInstruments": [{
          "units": 1,
          "instrument": {
            "instrumentType": "MasteredInstrument",
            "identifiers": {"Instrument/default/ClientInternal": "BondCollateral"}
            }
          }
        ],
        "collateralValue": 1100000,
        "buyerReceivesCashflows": false,
        "buyerReceivesCorporateActionPayments": false
      },
      "isCollateralTransferActivated": True,
      "haircut": 0.091,
      "margin": null,
      "purchasePrice": null,
      "repoRateSchedules": [{
        "scheduleType": "FixedSchedule",
        "couponRate": 0.05,
        "startDate": "2025-01-02T00:00:00.0000000+00:00",
        "maturityDate": "2025-03-31T00:00:00.0000000+00:00",
        "flowConventions": {
          "currency": "GBP",
          "paymentFrequency": "1T",
          "dayCountConvention": "Act365",
          "rollConvention": "None",
          "paymentCalendars": [],
          "resetCalendars": []
        },
        "notional": 1,
        "paymentCurrency": "GBP"
        }
      ],
      "repurchasePrice": null,
      "openRepoRollingPeriod": "1D"
    }
  }
}'
```

Note the following:

- This `FlexibleRepo` instrument is mastered in a [custom instrument scope](/v1/docs/understanding-instrument-scopes) (specified in the URL).
- Its `identifiers` object is set to reference a `ClientInternal` [unique identifier](/v1/docs/what-are-unique-and-non-unique-identifiers).
- `buyerOrSeller` is set to `Buyer` to receive collateral and send cash, but it could be `Seller` to send collateral and receive cash.
- `repoType` is `TermRepo` because `maturityDate` is known. If it is not, specify `OpenRepo` and set:
  - `maturityDate` to a significantly distant date, for example `9999-12-31`.
  - `openRepoRollingPeriod` to a tenor representing an interest payment window, for example `1D` or `1W` or `1M`.
- `accrualBasis` is `Act365` to count the number of accrual days using a particular [convention](/v1/docs/day-count-conventions-supported-by-lusid).
- The [Collateral](https://www.lusid.com/docs/api/lusid/schemas/Collateral/) object:
  - Specifies an `instrumentType` of `MasteredInstrument` and a unique identifier (in this case `ClientInternal`) to [resolve](/v1/docs/how-does-lusid-resolve-data-to-instruments) to the collateral instrument.
  - Specifies the `collateralValue`.
  - Retains the default values of `false` for `buyerReceivesCashFlows` and `buyerReceivesCorporateActionPayments`, so the seller keeps payments while the contract is in effect. Note the buyer actually *receives* the cashflows but LUSID uses instrument events to automatically refund the seller. [More information](/v1/docs/handling-instrument-events-for-repurchase-agreements#understanding-cashflow-ownership-for-collateral-transferred).
- `isCollateralTransferActivated` is set to `True` (the default is `False`) to trigger LUSID to emit `FlexibleRepoCollateralTransferEvent` on `startDate` to transfer collateral units to the buyer, and again on `maturityDate` to transfer units back to the seller. [More information](/v1/docs/modelling-repurchase-agreements-in-lusid#handling-the-lifecycle-of-the-instrument).
- The `haircut` is set to `0.091` but you could specify either a `margin` or `purchasePrice` if these are known instead.
- The `repoRateSchedules` array has a single [FixedSchedule](https://www.lusid.com/docs/api/lusid/schemas/FixedSchedule/) object to specify an absolute repo rate, though you can specify a single [FloatSchedule](https://www.lusid.com/docs/api/lusid/schemas/FloatSchedule) to link the repo rate to an index if you wish:
  - The `couponRate` (that is, repo rate) is expressed as a fraction, so `0.05` represents 5%. Note you can omit the `repoRateSchedules` array entirely and specify an explicit `repurchasePrice` if this is known instead.
  - The `startDate` and `maturityDate` must be the same as the `FlexibleRepo` itself.
  - The [FlowConventions](https://www.lusid.com/docs/api/lusid/schemas/FlowConventions/) object determines the repurchase date. Note the `currency` must be the same as `repoCcy`. The `paymentFrequency`:
    - Should be `1T` for a `TermRepo`
    - Set to the same as `openRepoRollingPeriod`for an `OpenRepo`.
  - `notional` should be `1`.
  - `paymentCurrency` must be the same as `repoCcy`.

#### Determining the purchase price

In summary, you must specify `collateralValue` and one of `haircut`, `margin` or `purchasePrice` to determine the purchase price. Note if you do not specify an explicit `purchasePrice` then LUSID calculates it as follows:

- `purchasePrice = collateralValue * (1 - haircut)`. In our example, this yields `1000000`.
- `purchasePrice = collateralValue / margin`

#### Determining the repurchase price

In summary, you must specify either `couponRate` (within the `repoRateSchedules` array) or `repurchasePrice` to determine the repurchase price. Note if you do not specify an explicit `repurchasePrice` then LUSID calculates it as follows: `repurchasePrice = (1 + couponRate * &lt;day-count-fraction&gt;) * purchasePrice` …where `&lt;day-count-fraction&gt;` depends on the number of days in the contract and the day count convention. In our example, this yields `1012054.79`.

### Examining the response

Providing the request is successful, the response:

- Confirms the globally-unique [LUID](/v1/docs/what-is-a-lusid-instrument-id-or-luid) of the `FlexibleRepo` instrument (in this case `LUID_00003G9T`).
- Confirms the LUID of the collateral `MasteredInstrument` providing LUSID is able to resolve it correctly (in this case `LUID_00003G9S`). If not, the [unknown instrument](/v1/docs/what-is-the-unknown-instrument-or-luid-zzzzzzzz) is returned.
- Generates extra fields that are stored as part of the instrument definition and can be [filtered on](/v1/docs/filtering-information-retrieved-from-lusid).
- Supplies default values for fields not explicitly specified in the request.

For example:

```json
{
  "values": {
    "upsert-request-1": {
      "scope": "MyCustomInstrScope",
      "lusidInstrumentId": "LUID_00003G9T",
      "name": "Buyer-TermFlexRepo",
      "identifiers": {
        "ClientInternal": "Buyer-TermFlexRepo",
        "LusidInstrumentId": "LUID_00003G9T"
      },
      "properties": [],
      "instrumentDefinition": {
        "startDate": "2025-01-02T00:00:00.0000000+00:00",
        "maturityDate": "2025-03-31T00:00:00.0000000+00:00",
        "buyerOrSeller": "Buyer",
        "repoCcy": "GBP",
        "repoType": "TermRepo",
        "accrualBasis": "Actual365",
        "collateral": {
          "buyerReceivesCashflows": false,
          "buyerReceivesCorporateActionPayments": false,
          "collateralInstruments": [
            {
              "units": 1,
              "instrument": {
                "identifiers": {
                  "Instrument/default/ClientInternal": "BondCollateral"
                },
                "masteredDomCcy": "GBP",
                "masteredInstrumentType": "Bond",
                "masteredLusidInstrumentId": "LUID_00003G9S",
                "masteredName": "BondCollateral",
                "masteredScope": "MyCustomInstrScope",
                "masteredAssetClass": "Credit",
                "instrumentType": "MasteredInstrument"
              }
            }
          ],
          "collateralValue": 1100000
        },
        "isCollateralTransferActivated": True,
        "haircut": 0.091,
        "repoRateSchedules": [
          {
            "startDate": "2025-01-02T00:00:00.0000000+00:00",
            "maturityDate": "2025-03-31T00:00:00.0000000+00:00",
            "flowConventions": {
              "currency": "GBP",
              "paymentFrequency": "1T",
              "dayCountConvention": "Actual365",
              "rollConvention": "None",
              "paymentCalendars": [],
              "resetCalendars": [],
              "settleDays": 0,
              "resetDays": 0,
              "leapDaysIncluded": true,
              "accrualDateAdjustment": "Adjusted",
              "businessDayConvention": "None",
              "accrualDayCountConvention": "Actual365"
            },
            "couponRate": 0.05,
            "notional": 1,
            "paymentCurrency": "GBP",
            "stubType": "None",
            "scheduleType": "FixedSchedule"
          }
        ],
        "tradingConventions": {
          "priceScaleFactor": 1,
          "minimumOrderSize": 0,
          "minimumOrderIncrement": 0
        },
        "instrumentType": "FlexibleRepo"
      },
      "state": "Active",
      "assetClass": "InterestRates",
      "domCcy": "GBP",
      "relationships": [],
      "dataModelMembership": {
        "membership": []
      }
    }
  },
  ...
}
```

## Booking a transaction to establish a position

Once a `FlexibleRepo` instrument is mastered, you can call the [BatchUpsertTransactions](https://www.lusid.com/docs/api/lusid/endpoints/transaction-portfolios/BatchUpsertTransactions/) API to record the acquisition of a number of contracts in a particular portfolio, for example:

```json
curl -X POST 'https://mydomain.lusid.com/api/api/transactionportfolios/MyPortfolioScope/MyPortfolioCode/transactions/$batchUpsert?successMode=Partial&preserveProperties=true'
  -H 'Content-Type: application/json-patch+json'
  -H 'Authorization: Bearer myAPIAccessToken'
  -d '{
  "transactionRequest-1": {
    "transactionId": "my_repo_purchase_001",
    "type": "EnterRepo",
    "instrumentIdentifiers": {"Instrument/default/ClientInternal": "Buyer-TermFlexRepo"},
    "transactionDate": "2025-01-01T00:00:00.0000000+00:00",
    "settlementDate": "2025-01-01T00:00:00.0000000+00:00",
    "units": 1,
    "transactionPrice": {
      "price": 0,
      "type": "Price"
    },
    "totalConsideration": {
      "amount": -1000000,
      "currency": "GBP"
    }
  }
}'
```

Note the following:

- The `type` field invokes a custom `EnterRepo` [transaction type](/v1/docs/what-is-a-transaction-type) to acquire a single unit of the repo at a particular cost (see below).
- The `transactionDate` and `settlementDate` **must be before the start date of the repo** in the instrument definition. This is so LUSID can automatically handle the transfer of collateral and cash between buyer and seller. [More information](/v1/docs/modelling-repurchase-agreements-in-lusid#handling-the-lifecycle-of-the-instrument).
- The `totalConsideration.amount` (cost) is set to the `purchasePrice` of the `FlexibleRepo`. See the [section above](/v1/docs/modelling-repurchase-agreements-in-lusid#determining-the-purchase-price) for how to work this out if not explicitly known:
  - If `buyerOrSeller` is `Buyer` in the instrument definition, the amount must be signed negative, for example `-1000000`
  - If `buyerOrSeller` is `Seller`, the amount must be signed positive, for example `1000000`.

> **Note**: This example assumes the transaction, settlement and portfolio currencies are all the same. If not, you can [specify exchange rates](/v1/docs/transactions-and-exchange-rates).

We might create a custom `EnterRepo` transaction type as follows:

```json
curl -X PUT 'https://<your-domain>.lusid.com/api/api/transactionconfiguration/types/default/EnterRepo?scope=default'
  -H 'Content-Type: application/json-patch+json'
  -H 'Authorization: Bearer <your-API-access-token>'
  -d '{
  "aliases": [
    {
      "type": "EnterRepo",
      "description": "Transaction type for starting a repurchase agreement",
      "transactionClass": "Basic",
      "transactionRoles": "AllRoles",
      "isDefault": false
    }
  ],
  "movements": [
    {
      "name": "Increase units of security",
      "movementTypes": "StockMovement",
      "side": "Side1EnterRepo",
      "direction": 1
    },
    {
      "name": "Transfer cash",
      "movementTypes": "CashReceivable",
      "side": "Side2",
      "direction": 1
    },
    {
      "name": "Report cost",
      "movementTypes": "StockMovement",
      "side": "Side1EnterRepoCost",
      "direction": -1
    }
  ]
}'
```

Note both `StockMovement` [movements](/v1/docs/what-is-a-movement) have custom sides:

| `Side1EnterRepo` custom side | `Side1EnterRepoCost` custom side |
| --- | --- |
| ```json curl -X PUT 'https://<your-domain>.lusid.com/api/api/ transactionconfiguration/sides/Side1EnterRepo?scope=default' -H 'Content-Type: application/json-patch+json' -H 'Authorization: Bearer <your-API-access-token>' -d '{ "security": "Txn:LusidInstrumentId", "currency": "Txn:TradeCurrency", "rate": "Txn:TradeToPortfolioRate", "units": "Txn:Units", "amount": "0" }' ``` | ```json curl -X PUT 'https://<your-domain>.lusid.com/api/api/ transactionconfiguration/sides/Side1EnterRepoCost?scope=default' -H 'Content-Type: application/json-patch+json' -H 'Authorization: Bearer <your-API-access-token>' -d '{ "security": "Txn:LusidInstrumentId", "currency": "Txn:TradeCurrency", "rate": "Txn:TradeToPortfolioRate", "units": "0", "amount": "Txn:TotalConsideration" }' ``` |
| This is the same as `Side1` except `amount` is `0` instead of `Txn:TradeAmount` | This is similar to `Side1` except `units` is `0` and `amount` is set to respect the sign of `totalConsideration.amount`. |

### Confirming positions

As a buyer, we can [generate a holdings report](/v1/docs/how-do-i-generate-a-holdings-report) on the transaction/settlement date of 1 January 2025 to see that we have:

- One unit of the repo holding.
- A negative cash balance of -£1,000,000 representing the transfer of `purchasePrice` to the seller by the `EnterRepo` transaction type.
- Three units of a holding in the bond collateral instrument (the transaction to generate this holding isn’t shown in this article but you can see an example [here](/v1/docs/modelling-fixed-rate-vanilla-bonds-in-lusid#booking-a-transaction-to-establish-a-position)).

![](https://cdn.document360.io/d575ad81-c0ed-4980-bbd1-d59ac5c3de82/Images/Documentation/image-F3HDEIUT.png)

If we fast-forward to the start date of the instrument on 2 January 2025 we see that we have:

- One unit of the repo holding.
- A negative cash balance of -£1,000,000.
- *Four* units of a holding in the bond collateral instrument (the transfer of collateral from the seller has been handled by the `FlexibleRepoCollateralEvent` [instrument event](/v1/docs/modelling-repurchase-agreements-in-lusid#handling-the-lifecycle-of-the-instrument)).

![](https://cdn.document360.io/d575ad81-c0ed-4980-bbd1-d59ac5c3de82/Images/Documentation/image-UZ1QK2EV.png)

### Auditing LUSID’s automatically-generated transactions

We can examine the [output transactions](/v1/docs/input-and-output-transactions) to understand how LUSID has automatically transfered collateral and cash between buyer and seller between 1 and 2 January 2025 (click to enlarge):

![](https://cdn.document360.io/d575ad81-c0ed-4980-bbd1-d59ac5c3de82/Images/Documentation/image-M8CIPQ6L.png)

## Valuing your position

To value a position in a `FlexibleRepo` (and also any collateral instrument) held in a portfolio, work through our [valuation checklist](/v1/docs/valuation-checklist).

> **Note**: The default pricing model for a `FlexibleRepo` is `SimpleStatic`. We strongly recommend changing this to the dedicated `FlexibleRepoSimplePricer`. [See how to do this](/v1/docs/recipes-changing-the-default-pricing-models-for-instrument-types).

For example, to value the portfolio shown above on 15 February 2025:

1. Load a market price for the collateral instrument valid for the valuation date into the LUSID Quote Store (there is no need to load market data for the `FlexibleRepo`):

```json
curl -X POST 'https://mydomain.lusid.com/api/api/quotes/MyRepoPortfolioQuotes'
  -H 'Authorization: Bearer myAPIAccessToken'
  -H 'Content-Type: application/json-patch+json'
  -d '{
    "Quote-0001": {
      "quoteId": {
        "quoteSeriesId": {
          "provider": "Lusid",
          "instrumentIdType": "ClientInternal",
          "instrumentId": "BondCollateral",
          "quoteType": "Price",
          "field": "mid"
        },
        "effectiveAt": "2025-02-15T00:00:00Z"
      },
      "metricValue": {
        "value": 101, "unit": "GBP"
      },
      "scaleFactor": 100
    }
  }'
```
2. [Create a recipe](/v1/docs/how-do-i-create-or-generate-a-recipe) to locate this market data and change the default pricing models:

```json
curl -X POST 'https://mydomain.lusid.com/api/api/recipes'
  -H 'Content-Type: application/json-patch+json'
  -H 'Authorization: Bearer myAPIAccessToken'
  -d '{
  "configurationRecipe": {
    "scope": "MyRecipes",
    "code": "MyRepoValuationRecipe",
    "market": {
      "marketRules": [
        {
          "key": "Quote.ClientInternal.*",
          "dataScope": "MyRepoPortfolioQuotes",
          "supplier": "Lusid",
          "quoteType": "Price",
          "field": "mid",
          "quoteInterval": "1D.0D"
        }
      ]
    },
    "pricing": {
      "modelRules": [
        {
          "instrumentType": "FlexibleRepo",
          "modelName": "FlexibleRepoSimplePricer"
        },
        {
          "instrumentType": "Bond",
          "modelName": "BondLookupPricer"
        }
      ]
    }
  }
}'
```
3. [Generate a valuation report](/v1/docs/how-do-i-perform-a-valuation) with appropriate metrics, for example: ![](https://cdn.document360.io/d575ad81-c0ed-4980-bbd1-d59ac5c3de82/Images/Documentation/image-7WNU74C2.png)

## Assessing risk

For more on how LUSID calculates exposure, see [this article](/v1/docs/how-does-lusid-calculate-exposure).

LUSID supports both analytic and bump and valuation mechanisms for assessing risk; contact [Technical Support](/v1/docs/how-do-i-use-the-support-centre) for more information.

## Handling the lifecycle of the instrument

A `FlexibleRepo` instrument is tightly integrated into LUSID’s [instrument event framework](/v1/docs/understanding-instrument-lifecycle-events-emitted-by-lusid). To enable this for your domain, you must:

1. Register a recipe with every portfolio holding a `FlexibleRepo`.
2. Create transaction types to determine the economic impact of the transactions automatically generated by `FlexibleRepo` events.

For much more information, learn how to [handle instrument events for repurchase agreements](/v1/docs/handling-instrument-events-for-repurchase-agreements).

| **Instrument event** | Repo type | Event emission criteria | **If emitted, effect of LUSID default transaction template** |
| --- | --- | --- | --- |
| `FlexibleRepoCashFlowEvent` | Both | This event is automatically emitted by LUSID on the maturity date (`TermRepo`) or closure date (`OpenRepo`) to transfer `repurchasePrice` from seller to buyer, though without the accrued interest (see below). | One transaction for a cash amount is automatically generated. |
| `FlexibleRepoInterestPaymentEvent` | Both | This event is automatically emitted by LUSID on the maturity date (`TermRepo`) or closure date (`OpenRepo`) to transfer the accrued interest component of `repurchasePrice` from seller to buyer. | One transaction for a cash amount is automatically generated. |
| `OpenRepo` | This event is automatically emitted by LUSID at the end of each payment window to transfer incremental accrued interest from seller to buyer. | One transaction for a cash amount is automatically generated on each payment date. |
| `FlexibleRepoCollateralEvent` **Note**: `isCollateralTransferActivated` must be `True` in the [instrument definition](/v1/docs/modelling-repurchase-agreements-in-lusid#mastering-a-flexiblerepo-instrument). | Both | If activated, this event is automatically emitted by LUSID: - On the start date to transfer collateral unit(s) from seller to buyer. - On the maturity date (`TermRepo`) or closure date (`OpenRepo`) to transfer collateral unit(s) from buyer to seller. | One transaction for a number of collateral units at zero cost is automatically generated on each date. |
| `FlexibleRepoPartialClosureEvent` | Both | This event is **not automatically emitted** by LUSID. You can manually load it to partially close a repo. | N/A |
| `FlexibleRepoFullClosureEvent` | `OpenRepo` | This event is **not automatically emitted** by LUSID. You should manually load it to close an open repo. | N/A |
| `MaturityEvent` | Both | This event is automatically emitted by LUSID on the maturity date (`TermRepo`) or closure date (`OpenRepo`). | One transaction for all units at zero cost is automatically generated to reduce the holding to zero. |

## Appendix: Using the LUSID web app to simplify repurchase agreements

A dashboard is available in the LUSID web app that you can use to both book a trade and simultaneously master a `FlexibleRepo` instrument, which may be a simpler user experience. To enable this:

1. Contact [Technical Support](/v1/docs/how-do-i-use-the-support-centre) for the required license.
2. In the transaction type you use to [enter into a repurchase agreement](/v1/docs/modelling-repurchase-agreements-in-lusid#booking-a-transaction-to-establish-a-position), add the `TransactionConfiguration/default/UIClass` system property and set the value to `PMS - Repo`.
3. Navigate to **Portfolio Management > Transactions**
4. Click the **Create transaction** button and open the **Repo** tab.
