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.

Enfusion API

Prev Next

FINBOURNE’s Enfusion API integration lets you bring positions and transactions straight from Enfusion into LUSID using reports. You decide which fields flow through by designing the report yourself, and LUSID maps the fields onto instruments, transactions, and holdings as it ingests the data.

This integration is powered by LUSID’s record capture framework. Before setting it up, you should be familiar with the core concepts of the framework, as described in Creating custom integrations for SFTP or API data sources. This article details the Enfusion-specific elements of the configuration.

Prerequisites

In addition to the record capture framework prerequisites, ensure you have:

  • An Enfusion Desktop licence, which you use to build and maintain the custom reports the integration sources data from.

Supported data types

The Enfusion API integration supports the following data types:

  • Transactions

  • Holdings

  • Instrument properties

  • Portfolio properties

The integration supports data ingestion for the following LUSID instrument types:

  • SimpleInstrument

  • Equity

  • Bond

  • ComplexBond

  • Future

  • FxSpot

  • FxForward

  • FxSwap

  • FxOption

  • InterestRateSwap

  • CreditDefaultSwap

  • CdsIndex

How it works

Enfusion surfaces your portfolio data through reports. You build a custom report in Enfusion and make it available via the Enfusion API; during an integration run, LUSID:

  1. Calls the Enfusion API and retrieves the rows from your shared report.

  2. For each row, maps each column onto the relevant LUSID instrument, transaction, or holding, applying any transformations defined in the mapping file.

Your Enfusion report columns are entirely under your control, which means you must tailor the mapping file to your specific report.

Setting up the integration

Setting up an Enfusion integration follows the same process as any record capture framework integration: you create an integration instance, then supply a control file and mapping file to LUSID Drive. The following steps detail only Enfusion-specific elements of the process.

For the full process, see Creating custom integrations for SFTP or API data sources.

Step 1: Build and share your Enfusion report

  1. In Enfusion Desktop, build a custom report containing the columns you want to bring into LUSID.

  2. Configure the report as shared so that it can be retrieved via the Enfusion API.

  3. Note the report’s path, which you will reference in the control file (see step 2).

    Note

    Enfusion sets the file extension based on the report type. LUSID supports the following types:

    • .trb: Trade blotter (source for transactions)

    • .ppr: Position report (source for holdings)

Step 2: Configure the control file

The control file tells LUSID to retrieve data from a specified report using the Enfusion API.

Include the following Enfusion-specific fields in your control file:

  • ApiRetrievalType: Set to Enfusion

  • DataReaderType: Set to EnfusionApiReader

  • ReportPath: The path to your shared Enfusion report, for example shared/Finbourne-Examples/AcmeTradeBlotter.trb

  • ReportFilter: Optionally, a filter to append to the report API request

Note

An Enfusion position report can be used as the data source for several LUSID entity types in one run (for example instruments, holdings and quotes). List the entities you want the report to load in ImportTypes.

All other control file fields behave as described in Appendix A of Creating custom integrations for SFTP or API data sources.

For example, the control file for a transactions report might look like this:

{
  "FileSpecs": [
    {
      "ApiRetrievalType": "Enfusion",
      "ReportPath": "shared/Finbourne-Examples/AcmeTradeBlotter.trb",
      "ReportFilter": "",
      "FileReference": "enfusion-transactions",
      "FileNameMask": "enfusion_trades_{{COBDATE:yyyy-MM-dd}}.json",
      "DriveSubfolder": "transactions",
      "DataReaderType": "EnfusionApiReader",
      "MappingFile": "MappingFiles/Enfusion_Transaction_Mapping.json",
      "ImportTypes": [ "Instruments", "Transactions" ],
      "ReliesUpon": []
    }
  ]
}

For example, the control file for a holdings report might look like this:

{
  "FileSpecs": [
    {
      "ApiRetrievalType": "Enfusion",
      "ReportPath": "shared/Finbourne-Examples/AcmeHoldingsExportAgg.ppr",
      "ReportFilter": "",
      "FileReference": "enfusion-holdings",
      "FileNameMask": "enfusion_response_{{COBDATE:yyyy-MM-dd}}.json",
      "DriveSubfolder": "holdings",
      "DataReaderType": "EnfusionApiReader",
      "MappingFile": "MappingFiles/Enfusion_Holdings_Mapping.json",
      "ImportTypes": [ "Instruments", "Holdings", "Quotes", "RelationalDatasets" ],
      "ReliesUpon": []
    }
  ]
}

Step 3: Configure the mapping file

The mapping file behaves as described in Appendix B of Creating custom integrations for SFTP or API data sources.

Each ColumnHeader you specify in ColumnSpecs must match the field name exactly as it appears in your Enfusion report output (typically camelCase).

For example:

"ColumnSpecs": [
  { "ColumnHeader": "tradeId", "ColumnReference": "TradeIdColumn" },
  { "ColumnHeader": "instrumentId", "ColumnReference": "InstrumentIdColumn" },
  { "ColumnHeader": "tradeCurrency", "ColumnReference": "TradeCurrencyColumn" }
]

Ensure you decorate your target LUSID portfolios with the required rcf-config properties described in Configure portfolios for holdings/transactions loads.

Example: Transactions mapping file

{
  "CsvSeparator": "Comma",
  "RowIdentificationSourceName": "RowId",
  "ColumnSpecs": [
    {
      "ColumnHeader": "tradeId",
      "ColumnReference": "TradeIdColumn"
    },
    {
      "ColumnHeader": "tradeTransactionType",
      "ColumnReference": "TradeTransactionTypeColumn"
    },
    {
      "ColumnHeader": "tradeDate",
      "ColumnReference": "TradeDateColumn"
    },
    {
      "ColumnHeader": "notionalQuantity",
      "ColumnReference": "NotionalQuantityColumn"
    },
    {
      "ColumnHeader": "tradePrice",
      "ColumnReference": "TradePriceColumn"
    },
    {
      "ColumnHeader": "tradeCurrency",
      "ColumnReference": "TradeCurrencyColumn"
    },
    {
      "ColumnHeader": "tradingNetProceeds",
      "ColumnReference": "TradingNetProceedsColumn"
    },
    {
      "ColumnHeader": "instrumentId",
      "ColumnReference": "InstrumentIdColumn"
    },
    {
      "ColumnHeader": "instrumentType",
      "ColumnReference": "InstrumentTypeColumn"
    }
  ],
  "ValueSources": [
    {
      "Name": "RowId",
      "ColumnReferences": [
        "TradeIdColumn"
      ],
      "ValueConversion": "None"
    },
    {
      "Name": "TradeIdValue",
      "ColumnReferences": [
        "TradeIdColumn"
      ],
      "ValueConversion": "None"
    },
    {
      "Name": "TradeTransactionTypeValue",
      "ColumnReferences": [
        "TradeTransactionTypeColumn"
      ],
      "ValueConversion": "None"
    },
    {
      "Name": "TradeDateValue",
      "ColumnReferences": [
        "TradeDateColumn"
      ],
      "ValueConversion": "None"
    },
    {
      "Name": "NotionalQuantityValue",
      "ColumnReferences": [
        "NotionalQuantityColumn"
      ],
      "ValueConversion": "None"
    },
    {
      "Name": "TradePriceValue",
      "ColumnReferences": [
        "TradePriceColumn"
      ],
      "ValueConversion": "None",
      "MultiplierValueSourceName": "TradePriceMultiplier"
    },
    {
      "Name": "TradeCurrencyValueMapped",
      "ColumnReferences": [
        "TradeCurrencyColumn"
      ],
      "ValueConversion": "None",
      "ValueMapName": "CurrencyCodeMapping"
    },
    {
      "Name": "TradeCurrencyValue",
      "ColumnReferences": [
        "TradeCurrencyColumn"
      ],
      "ValueConversion": "None"
    },
    {
      "Name": "TradingNetProceedsValue",
      "ColumnReferences": [
        "TradingNetProceedsColumn"
      ],
      "ValueConversion": "None"
    },
    {
      "Name": "InstrumentIdValue",
      "ColumnReferences": [
        "InstrumentIdColumn"
      ],
      "ValueConversion": "None"
    },
    {
      "Name": "InstrumentTypeValue",
      "ColumnReferences": [
        "InstrumentTypeColumn"
      ],
      "ValueConversion": "None"
    }
  ],
  "ConditionalValueSources": [
    {
      "Name": "InstrumentTypeSelector",
      "LogicalExpressions": [
        {
          "Condition": "InstrumentTypeValue = \"Equity\"",
          "Result": "\"Equity\""
        },
        {
          "Condition": "",
          "Result": "\"SimpleInstrument\""
        }
      ]
    },
    {
      "Name": "UnderlyingInstrumentHandling",
      "LogicalExpressions": [
        {
          "Condition": "",
          "Result": "\"None\""
        }
      ]
    },
    {
      "Name": "TradePriceMultiplier",
      "LogicalExpressions": [
        {
          "Condition": "TradeCurrencyValue InMapKeys CurrencyCodeMapping",
          "Result": "\"0.01\""
        },
        {
          "Condition": "",
          "Result": "\"1\""
        }
      ]
    }
  ],
  "ValueMaps": [
    {
      "Name": "CurrencyCodeMapping",
      "Map": {
        "GBp": "GBP",
        "ZAc": "ZAR"
      }
    }
  ],
  "DQChecks": [],
  "InstrumentsLoadControl": {
    "InstrumentTypeSelectorSourceName": "InstrumentTypeSelector",
    "UnderlyingInstrumentHandlingSourceName": "UnderlyingInstrumentHandling",
    "Identifiers": [
      {
        "IdentifierType": "ClientInternal",
        "IdentifierValueSourceName": "InstrumentIdValue",
        "IsUnique": true
      }
    ],
    "InstrumentDefControls": [
      {
        "InstrumentType": "Equity",
        "DomesticCurrencySourceName": "TradeCurrencyValueMapped",
        "InstrumentNameSourceName": "InstrumentIdValue",
        "Properties": []
      },
      {
        "InstrumentType": "SimpleInstrument",
        "InstrumentNameSourceName": "InstrumentIdValue",
        "DomesticCurrencySourceName": "TradeCurrencyValueMapped",
        "SimpleInstrumentTypeSourceName": "InstrumentTypeValue",
        "Properties": []
      }
    ],
    "CommonProperties": [
      {
        "LusidPropertyName": "Instrument/Finbourne-Examples/Instrument_Type",
        "ValueSourceName": "InstrumentTypeValue",
        "IsPerpetual": true
      }
    ]
  },
  "HoldingsLoadControl": null,
  "PortfoliosLoadControl": null,
  "TransactionsLoadControl": {
    "TransactionIdSourceName": "TradeIdValue",
    "TransactionTypeSourceName": "TradeTransactionTypeValue",
    "TransactionDateSourceName": "TradeDateValue",
    "SettlementDateSourceName": "TradeDateValue",
    "UnitsSourceName": "NotionalQuantityValue",
    "TotalConsiderationCurrencySourceName": "TradeCurrencyValueMapped",
    "TotalConsiderationAmountSourceName": "TradingNetProceedsValue",
    "TransactionPriceSourceName": "TradePriceValue",
    "Properties": [
      {
        "LusidPropertyName": "Transaction/Finbourne-Examples/Traded_Currency",
        "ValueSourceName": "TradeCurrencyValueMapped",
        "IsPerpetual": true
      },
      {
        "LusidPropertyName": "Transaction/Finbourne-Examples/Net_Proceeds",
        "ValueSourceName": "TradingNetProceedsValue",
        "IsPerpetual": true,
        "LusidPropertyDataType": "number"
      }
    ]
  }
}

Running, monitoring, and troubleshooting integration runs

You can run the integration, view logs, and troubleshoot as described in Creating custom integrations for SFTP or API data sources.