Skip to main content

Price Data Provider

Overview

A price data provider is a custom application that connects to the KeySquare platform and publishes live market prices for consumption by Price Engine. Rather than entering prices manually, a data provider connects to an external feed (a market data vendor, internal system, exchange, or file) and streams price updates directly to the platform.

Price Engine subscribes to these updates and uses them as the raw input for the SOURCE and BENCHMARK pricing models.

The data-provider-api library provides the PriceDataProvider base class, which handles all low-level topic routing and session interactions so you can focus entirely on the data.

note

This guide focuses on implementing a custom price data provider in Java.
Before continuing, ensure you have:

Maven Dependency

Add the data-provider-api artifact to your project:

<dependency>
<groupId>trading.keysquare</groupId>
<artifactId>data-provider-api-all</artifactId>
<version>${version}</version>
</dependency>

data-provider-api-all-{version}.jar is an uber jar containing keysquare-api and all required models (ks-model-canonical, ks-model-static-data-server, ks-model-pricing). Please reach out to us if you do not have this file.

Implementing a Price Data Provider

Extend PriceDataProvider and implement your feed logic. The base class handles topic construction, session publishing, and result validation automatically.

MyPriceProvider.java
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import trading.keysquare.api.session.KeySession;
import trading.keysquare.api.session.Result;
import trading.keysquare.data.provider.PriceDataProvider;
import trading.keysquare.model.canonical.sbe.PriceDto;

public class MyPriceProvider extends PriceDataProvider {

private static final Logger log = LoggerFactory.getLogger(MyPriceProvider.class);

public MyPriceProvider(KeySession session) {
super(session);
}

public void onFeedUpdate(String isin, double bidPrice, double askPrice) {
PriceDto price = new PriceDto();
price.priceSource("MY_FEED"); // must match topicSource in KS_PE_PRICE_SOURCES
price.priceType(LIVE);
price.instrumentId(isin);
price.bidPrice(bidPrice);
price.askPrice(askPrice);
price.midPrice((bidPrice + askPrice) / 2.0);
price.ok(true);

Result result = publish(price);
if (result.isFailure()) {
log.warn("Publish failed: [{}] for instrument: {}", result, isin);
}
}
}

PriceDataProvider.publish(PriceDto) derives the topic automatically from the dto:

Topic componentTaken from
topicSourcedto.priceSource() (falls back to application name if blank)
topicGroupdto.priceType().name() (e.g. LIVE, EOD)
topicIddto.instrumentId()

Price Engine uses the instrumentIdType configured in KS_PE_PRICE_SOURCES to resolve topicId back to a canonical platform instrument.

Publishing Yields Instead of Prices

If your feed provides yields rather than clean prices, populate the yield fields and set priceType. Price Engine uses the spreadType on each PriceControl to decide whether to use price or yield as its input:

PriceDto price = new PriceDto();
price.priceSource("MY_FEED");
price.instrumentId(isin);
price.bidYield(bidYield);
price.askYield(askYield);
price.midYield((bidYield + askYield) / 2.0);
price.ok(true);

Result result = publish(price);

Marking a Price as Invalid

If your feed cannot provide a valid price (no data, stale, or error condition), publish with ok=false and a human-readable message. Price Engine propagates this status and displays it in the Error column in Key UI:

PriceDto price = new PriceDto();
price.priceSource("MY_FEED");
price.instrumentId(isin);
price.ok(false);
price.message("No data available from feed");

publish(price);

Registering Your Provider with Price Engine

Tell Price Engine to subscribe to your prices by adding an entry to KS_PE_PRICE_SOURCES in the Price Engine configuration:

KS_PE_PRICE_SOURCES=[
{
"name": "MY_FEED",
"topicSource": "my-data-provider",
"topicGroup": "MY_FEED",
"instrumentIdType": "ISIN",
"instrumentIdSource": ""
}
]
PropertyDescription
nameDisplay name shown in the Price Source dropdown in Key UI
topicSourceMust match your application's registered name in KeyAccess exactly
topicGroupMust match the priceSource field you set on published PriceDto objects
instrumentIdTypeHow your topicId (i.e. instrumentId on the dto) maps to platform instruments
instrumentIdSourceFor ALIAS type: restrict lookup to a specific alias source. Leave empty to match any.

Instrument ID Types

instrumentIdTypeDescription
STATIC_DATA_SERVERinstrumentId is the platform-assigned instrument ID (e.g. BUSD00001)
ISINinstrumentId is the ISIN (e.g. US0378331005)
CUSIPinstrumentId is the CUSIP (9-character)
FIGIinstrumentId is the Bloomberg FIGI
ALIASinstrumentId is a custom alias registered in Static Data Server

Price Engine uses the instrument ID reverse-mapping published by Static Data Server to resolve instrumentId values to canonical instrument IDs at runtime.

Permissions

Two sets of permissions must be configured in KeyAccess: one for your data provider application and one for the Price Engine instance.

Your Data Provider Application

PUB/SUBSchemaSourceGroup
PUBKsCanonical.Price{your-app-name}*

Replace {your-app-name} with the application name you registered in KeyAccess.

Price Engine

Price Engine must be permissioned to subscribe to your prices topic:

PUB/SUBSchemaSourceGroup
SUBKsCanonical.Price{your-app-name}*

This is in addition to the standard Price Engine entitlements listed in Price Engine — Entitlements.

Multiple Data Providers

Price Engine supports multiple simultaneous data providers. Each entry in KS_PE_PRICE_SOURCES is an independent subscription. A single instrument can receive prices from multiple providers; each PriceControl specifies which provider to use for its calculations via the Price Source field.

Benchmark Prices

If a price control uses model=BENCHMARK, Price Engine needs a price for the benchmark instrument. This is sourced from the provider configured in benchmarkPriceSource on the PriceControl. If no benchmark price source is set, Price Engine uses its own internally computed price for the benchmark.

For benchmark pricing to work correctly, the benchmark instrument's price must include a valid yield. If the benchmark provider only publishes clean prices, ensure spreadType=PRICE is not set on the benchmark instrument's own PriceControl so that Price Engine can compute its yield via Analytics Engine.