FINBOURNE’s JPMorgan PricingDirect integration allows you to seamlessly deliver Fixed Income pricing data into LUSID.
Prerequisites
Before getting started, ensure you have:
An active contract with JP Morgan for PricingDirect services
A technical account username and password issued by JP Morgan to access PricingDirect services
Contacted your FINBOURNE representative to enable the integration in your LUSID domain
Supported data types
The integration provides quote data for Fixed Income instruments with a valid CUSIP identifier.
Setting up the integration
Step 1: Create an integration instance
An integration instance configures the snapshot timing, price types, and instruments for your quote import:
Navigate to Integrations > Dashboard.
Select Create instance and choose JPM PricingDirect.

Specify a friendly Name and Description for the integration instance.
Specify the following in the Integration settings tab:
Base URL: The base URL for the JPM PricingDirect API
Username: Your JPM PricingDirect technical account username
Password: Your JPM PricingDirect technical account password
Pricing configuration:
Pricing category:
FixedIncome; support forDerivativesis coming soonClose type: Defines the snapshot time (
effectiveAt) for a quote; note that there is a delay between the price snapshot capture time and the data becoming available via API, see appendix A for more details on the available close typesPrice type: Choose whether to retrieve
BID,MEAN,OFFER, or all three quotes for each instrumentInstrument scopes: Import quotes for LUSID instruments with the
Instrument/LUSIDConfig-JPM-PricingDirect/RefreshQuoteDataproperty in the specified scopesQuote instrument identifier types: By default, quotes are stored with CUSIP identifiers; optionally specify additional identifier types to duplicate quotes against those identifiers
Debug configuration:
Request/response output Drive folder path: Optionally, specify a Drive path starting with
LUSID-Horizon/to log request and response payloads for debugging

Specify the following in the Execution settings tab:
A cron Schedule to trigger the integration instance at
A Schedule timezone for LUSID to use with the cron Schedule
Whether the schedule should be Enabled upon saving; if enabled, the integration instance will subsequently run according to your specified schedule
For example, to schedule runs for Close type
NY15 | NY Bond 3PM(snapshot at 15:00 ET, data available at 16:30 ET), you could specify the cron expression0 35 16 ? * MON-FRIwith timezoneAmerica/New_York; this runs on weekdays at 16:35, allowing for a 5-minute error margin.
Click Save to create the integration instance. Note the Instance ID, which you need for the next step.
Step 2: Select the instruments to import quotes for
LUSID selects instruments for quote imports using the Instrument/LUSIDConfig-JPM-PricingDirect/RefreshQuoteData property. To include instruments in imports:
Ensure each Fixed Income instrument has a CUSIP identifier value.
Follow these steps to add the instrument property with Scope
LUSIDConfig-JPM-PricingDirectand CodeRefreshQuoteDatato the instruments you want to include in the JPM PricingDirect integration instance import.
Set the property value to your integration Instance ID from step 1. You can enter more than one ID if you want to include the instrument in multiple integration instances.

Bulk updates
You can use Luminesce to schedule a query to populate the property for all relevant instruments daily before the scheduled integration instance run; see appendix B.
Monitoring and troubleshooting integration runs
See how to monitor integrations and troubleshoot general issues.
LUSID stores JPMorgan PricingDirect data as quotes in the LUSID-JPM-PricingDirect scope.  
Understanding JPM PricingDirect run logs
You can use the Source Primary ID Value column in the logs to view the instruments fetched for processing in an integration run.

The ApiIdentifier Source Primary ID Type and Value displays the file used (if one is specified in the integration instance Request / Response Output Drive Folder Path) for the request and response.
LUSID logs the status of rows as follows:
ResourceSkipped: LUSID was unable to retrieve a price for the specified instrument
ResourceExtracted and ResourceMapped: LUSID was able to retrieve a price for the specified instrument; if your instance is configured to retrieve all price types, you should expect three quotes per instrument identifier type

The final Log ID rows show the details of the quotes loaded by LUSID:

Troubleshooting
PayloadFailed with Exception occurred when calling JPM PricingDirect API: 'HTTP Unauthorized'
PayloadFailed with Exception occurred when calling JPM PricingDirect API: 'HTTP Unauthorized'
If you experience this error message, verify the Username and Password values you entered in your integration instance are correct.
No quotes loaded for all instruments

If you experience this error, validate your instruments were in scope for the run via the logs. Expand the initial log and check the Description column for a message containing with 0 instrument(s) for instrument scope ‘<your-scope>‘ . 
If no instruments were in scope, verify:
The
Instrument/LUSIDConfig-JPM-PricingDirect/RefreshQuoteDataproperty is set on at least one instrument, and the value matches the integration Instance IDEach instrument has a value for the CUSIP identifier
The relevant instrument scopes have been added as values for Instrument scopes in the integration instance
Appendix A: Close types
Until the delivery time associated with the quote, the system retrieves quotes for T-1. The following table contains indicative snapshot and delivery times for each Close type:
Note
For the latest definitive guide on snapshot and delivery times, see the Product Delivery Matrix from JPM PricingDirect.
Close Type  | Snapshot  | Delivery  | 
|---|---|---|
AP18 | APAC 6PM  | 18:00 JST  | 19:00 JST  | 
AP19 | APAC 7PM  | 19:00 JST  | 20:00 JST  | 
LN12 | London 12PM  | 12:00 BST  | 12:30 BST  | 
CE15 | Continental Europe 3PM  | 15:00 CET  | 15:45 CET  | 
CE16 | Continental Europe 4PM  | 16:00 CET  | 16:45 CET  | 
LN16 | London 4PM  | 16:15 BST  | 17:15 BST  | 
NY13 | NY 1PM  | 13:00 ET  | 13:45 ET  | 
NY15 | NY Bond 3PM  | 15:00 ET  | 16:30 ET  | 
NY16 | NY Stock 4PM  | 16:00 ET  | 16:45 ET  | 
NY17 | NY EOD 5PM  | 17:00 ET  | 17:30 ET  | 
Index | JPM Index  | 17:00 ET  | 17:15 ET  | 
Appendix B: Populating the RefreshQuoteData property on instruments in bulk
You can schedule a Luminesce query to populate the Instrument/LUSIDConfig-JPM-PricingDirect/RefreshQuoteData property for all relevant instruments daily, before the integration instance runs.
Click to expand Luminesce query
For example, to add the RefreshQuoteData property to all new Fixed Income instruments in the default scope to include them in the NY15 | NY Bond 3PM daily quote import:
--Close type = NY15 | NY Bond 3PM
-- Define the integration instance ID:
@@integrationInstanceId =
select [InstanceId] from Integration.Dashboard
where [Type] = 'jpm-pricing-direct'
  and [Name] = 'JPM PricingDirect FI NY15'
limit 1;
-- Specify which instrument scope(s) to include. Note this scope must also be specified in the integration instance config.
@instrumentScopes = select 'default' as Scope;
-- Specify which Product types are in scope. Note each instrument must have a valid CUSIP for JPM PricingDirect.
@instruments=
select  i.Scope as EntityScope,
  'LusidInstrumentId' as 'EntityIdType',
  i.[LusidInstrumentId] as 'EntityId',
  i.Scope || '/LusidInstrumentId/' || i.[LusidInstrumentId] as InstrumentKey
from [Lusid.Instrument.Bond] i
  join @instrumentScopes s
    on i.[Scope] = s.[Scope]
where i.[State] = 'Active'
  and i.[Cusip] is not null
  and LENGTH(i.Cusip) = 9
UNION
select i.Scope as EntityScope,
  'LusidInstrumentId' as 'EntityIdType',
  i.[LusidInstrumentId] as 'EntityId',
  i.Scope || '/LusidInstrumentId/' || i.[LusidInstrumentId] as InstrumentKey
from [Lusid.Instrument.ComplexBond] i
  join @instrumentScopes s
    on i.[Scope] = s.[Scope]
where i.[State] = 'Active'
  and i.[Cusip] is not null
  and LENGTH(i.CUSIP) = 9
UNION
select i.Scope as EntityScope,
  'LusidInstrumentId' as 'EntityIdType',
  i.[LusidInstrumentId] as 'EntityId',
  i.Scope || '/LusidInstrumentId/' || i.[LusidInstrumentId] as InstrumentKey
from [Lusid.Instrument.SimpleInstrument] i
  join @instrumentScopes s
    on i.[Scope] = s.[Scope]
where i.[State] = 'Active'
  and i.[Cusip] is not null
  and LENGTH(i.CUSIP) = 9
  and i.[SimpleInstrumentType] = 'TBA'
;
-- Fetch the current Instrument/LUSIDConfig-JPM-PricingDirect/RefreshQuoteData settings
@existing=
select p.Domain, p.EntityScope, p.EntityIdType, p.EntityId, p.PropertyDomain, p.PropertyScope, p.PropertyCode, p.Value, 
  p.EntityScope || '/' || p.EntityIdType || '/' || p.EntityId as InstrumentKey
from [Lusid.Property] p
where p.Domain = 'Instrument'
  and p.PropertyDomain = 'Instrument'
  and p.PropertyScope = 'LUSIDConfig-JPM-PricingDirect'
  and p.PropertyCode = 'RefreshQuoteData';
        
-- Add this integration instance ID to instruments that are already included in a different JPM PricingDirect instance:
@updates =
select p.Domain, p.EntityScope, p.EntityIdType, p.EntityId, p.PropertyDomain, p.PropertyScope, p.PropertyCode, p.InstrumentKey,
  p.Value || ',' || @@integrationInstanceId as Value, 'Upsert' as WriteAction
from @existing p
  join @instruments i 
    on p.InstrumentKey = i.InstrumentKey
where p.Value not like '%' || @@integrationInstanceId || '%';
-- Add the instance ID to instruments that are not in the @updates set or @existing set
@inserts =
select 'Instrument' as Domain, i.EntityScope, i.EntityIdType, i.EntityId, 'Instrument' as PropertyDomain,
  'LUSIDConfig-JPM-PricingDirect' as PropertyScope, 'RefreshQuoteData' as PropertyCode,
  @@integrationInstanceId as Value, 'Upsert' As WriteAction
from @instruments i 
where i.InstrumentKey not in (select InstrumentKey from @existing where Value like '%' || @@integrationInstanceId || '%')
  and i.InstrumentKey not in (select InstrumentKey from @updates)
;
-- Define the changes to write to the instruments
@toWrite=
select Domain, EntityScope, EntityIdType, EntityId, PropertyDomain, PropertyScope, PropertyCode, Value, WriteAction 
from @updates 
UNION
select Domain, EntityScope, EntityIdType, EntityId, PropertyDomain, PropertyScope, PropertyCode, Value, WriteAction 
from @inserts
;
-- Upsert the changes
@response =
select WriteErrorCode, WriteError, WriteErrorDetail, Domain, EntityScope, EntityIdType, EntityId, PropertyDomain, PropertyScope, PropertyCode, Value
from Lusid.Property.Writer
where ToWrite = @toWrite;
-- Return the response
select WriteErrorCode, WriteError, WriteErrorDetail, Domain, EntityScope, EntityIdType, EntityId, PropertyDomain, PropertyScope, PropertyCode, Value
from @response;
-- Handle any errors
@@numErrors = select COUNT(*) from @response where WriteErrorCode <> 0;
@@errorMsg = select 'LUSIDConfig-JPM-PricingDirect/RefreshQuoteData not updated on ' ||  @@numErrors || ' instruments';
select IIF(@@numErrors>0,throw(@@errorMsg),'') 
where @@numErrors>0;