You can model a repurchase agreement (“repo”) as a buyer or a seller using the FlexibleRepo
instrument type. See all supported instruments.
Note: This article explains how to master an instrument and then load a transaction using the LUSID API. It is possible to simply load a transaction in the LUSID web app and have LUSID master the instrument for you. Contact us for more information.
Mastering an instrument
There are numerous tools 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 of identifiers
, and the facility to store extra information 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 API reference, or alternatively examine the FlexibleRepo schema:
Mastering a collateral instrument
If the repo has collateral that is a supported instrument, master it separately and then provide a reference to a MasteredInstrument
. See how to master a bond.
Mastering a FlexibleRepo
instrument
The following call to the UpsertInstruments API masters a term repo as a buyer with a vanilla fixed-rate bond as collateral:
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
},
"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
}
}
}'
Note the following:
This
FlexibleRepo
instrument is mastered in a custom instrument scope (specified in the URL).Its
identifiers
object is set to reference aClientInternal
unique identifier.buyerOrSeller
is set toBuyer
to receive collateral and send cash onstartDate
, but it could beSeller
to send collateral and receive cash.repoType
isTermRepo
becausematurityDate
is known. If it is not, specifyOpenRepo
and set:maturityDate
to a significantly distant date, for example9999-12-31
.openRepoRollingPeriod
to a tenor representing an interest payment window, for example1D
or1W
or1M
.
accrualBasis
isAct365
to count the number of accrual days using a particular convention.The Collateral object:
Specifies an
instrumentType
ofMasteredInstrument
and a unique identifier (in this caseClientInternal
) to resolve to the collateral instrument.Specifies the
collateralValue
.Retains the default values of
false
forbuyerReceivesCashFlows
andbuyerReceivesCorporateActionPayments
, so the seller keeps payments while the contract is in effect. Note the buyer actually receives the cashflows but LUSID can automatically handle refunding the seller (more information coming soon).
The
haircut
is set to0.091
but you could specify either amargin
or apurchasePrice
if these are known instead.The
repoRateSchedules
array has a single FixedSchedule object to specify an absolute repo rate, though you can specify a single FloatSchedule to link the repo rate to an index instead if you wish:The
couponRate
(that is, repo rate) is expressed as a fraction, so0.05
representing 5%. Note you can omit therepoRateSchedules
array entirely and specify an explicitrepurchasePrice
if this is known instead.The
startDate
andmaturityDate
must be the same as theFlexibleRepo
itself.The FlowConventions object configures the repurchase date. Note the
paymentFrequency
must be1T
andcurrency
the same asrepoCcy
. More information on roll and business day conventions.notional
should be1
.paymentCurrency
must be the same asrepoCcy
.
In summary:
You must specify
collateralValue
and one ofhaircut
,margin
orpurchasePrice
to determine the purchase price. Note if you do not specify an explicitpurchasePrice
then LUSID calculates it as follows:purchasePrice = collateralValue * (1 - haircut)
. In our example, this yields1000000
.purchasePrice = collateralValue / margin
You must specify either
couponRate
(within therepoRateSchedules
array) orrepurchasePrice
to determine the repurchase price. Note if you do not specify an explicitrepurchasePrice
then LUSID calculates it as follows:repurchasePrice = (1 + couponRate * <day-count-fraction>) * purchasePrice
…where<day-count-fraction>
depends on the number of days in the contract and the day count convention. In our example, this yields1012054.79
.
Providing the request is successful, the response:
Confirms the globally-unique LUID of the
FlexibleRepo
instrument (in this caseLUID_00003EPX
).Confirms the LUID of the collateral
MasteredInstrument
providing LUSID is able to resolve it correctly (in this caseLUID_00003EPW
). If not, the unknown instrument is returned.Generates extra fields that are stored as part of the instrument definition and can be filtered on.
Supplies default values for fields not explicitly specified in the request:
{
"values": {
"upsert-request-1": {
"scope": "MyCustomInstrScope",
"lusidInstrumentId": "LUID_00003EPX",
"name": "Buyer-TermFlexRepo",
"identifiers": {
"ClientInternal": "Buyer-TermFlexRepo",
"LusidInstrumentId": "LUID_00003EPX"
},
"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_00003EPW",
"masteredName": "BondCollateral",
"masteredScope": "MyCustomInstrScope",
"masteredAssetClass": "Credit",
"instrumentType": "MasteredInstrument"
}
}
],
"collateralValue": 1100000
},
"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 API to record the acquisition of a number of contracts in a particular portfolio, for example:
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": "StockIn",
"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": 1000000,
"type": "Price"
},
"totalConsideration": {
"amount": 1000000,
"currency": "GBP"
}
}
}'
Note the following:
The
type
field invokes the built-inStockIn
transaction type to acquire a single unit of the repo without impacting cash holdings, though you can create a custom transaction type with a different economic impact if you wish.The
transactionDate
andsettlementDate
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.The
totalConsideration.amount
(cost) is set to thepurchasePrice
of theFlexibleRepo
to yield the correct accounting treatment. See the previous section for how to work this out if not explicitly known.
Note: This example assumes the transaction, settlement and portfolio currencies are all the same. If not, you can specify exchange rates.
Confirming positions
We can generate a holdings report on the transaction date of 1 January 2025 to see that we have:
One unit of the repo holding
Three units of a holding in the bond collateral instrument (this transaction isn’t shown above but you can see an example here):
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
Four units of the bond holding (LUSID has automatically transferred one unit from the seller)
A cash holding of -£1000000 (LUSID has automatically transferred
purchasePrice
to the seller):
Auditing LUSID’s automatically-generated transactions
We can examine the output transactions generated by instrument events to understand how LUSID automatically transfers collateral and cash between buyer and seller on 2 January 2025:
Valuing your position
To value a position in a FlexibleRepo
(and also any collateral instrument) held in a portfolio, work through our valuation checklist.
Note: The default pricing model for a
FlexibleRepo
isSimpleStatic
. We recommend keeping this default.
For example, to value the portfolio shown above on 15 February 2025:
Load market prices into the LUSID Quote Store:
A dummy price of
1
for theFlexibleRepo
. TheSimpleStatic
model has a dependency on this data, but it can be unitised and valid for the lifetime of the contract.A price for the bond collateral instrument valid for the valuation date:
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": "Buyer-TermFlexRepo", "quoteType": "Price", "field": "mid" }, "effectiveAt": "2025-01-01T00:00:00Z" }, "metricValue": { "value": 1, "unit": "GBP" } }, "Quote-0002": { "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 } }'
Create a recipe to locate this market data and change the default pricing model for the bond collateral instrument. Note the ‘look back’
quoteInterval
for the dummyFlexibleRepo
price is equivalent to the length of the contract: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": "3M.0D" } ] }, "pricing": { "modelRules": [ { "instrumentType": "Bond", "modelName": "BondLookupPricer" } ] } } }'
Generate a valuation report with appropriate metrics, for example:
Assessing risk
For more on how LUSID calculates exposure, see this article.
LUSID supports both analytic and bump and valuation mechanisms for assessing risk; contact Technical Support for more information.
Handling the lifecycle of the instrument
A FlexibleRepo
instrument is tightly integrated into LUSID’s instrument event framework. To enable this for your domain, you must:
Register a recipe with every portfolio holding a
FlexibleRepo
.Create transaction types to determine the economic impact of the transactions automatically generated by
FlexibleRepo
events.
For much more on the instrument event framework, start here.
The following events are available for a FlexibleRepo
:
Instrument event type | Repo type | Event emission criteria | If emitted, effect of LUSID default transaction template | Transaction type recommendations |
---|---|---|---|---|
| Any | This event is automatically emitted by LUSID:
| One transaction for a cash amount is automatically generated on each date. | More information coming soon. |
| Any | This event is automatically emitted by LUSID:
| One transaction for a number of collateral units at zero cost is automatically generated on each date. | |
|
| This event is automatically emitted by LUSID on each payment window date to transfer accrued interest from seller to buyer. | One transaction for a cash amount is automatically generated on each date. | |
| Any | This event is not automatically emitted by LUSID. You can manually load it to partially close a repo. | N/A | |
|
| This event is not automatically emitted by LUSID. You should manually load it to close an open repo. | N/A | |
| Any | This event is automatically emitted by LUSID on the maturity date. | One transaction for all units at zero cost is automatically generated to reduce the holding to zero. |