Mapping messages

Available from Caplin Platform 6.1.

Mapping of messages enables client subscriptions for a given subject to be mapped to a different subject. This means multiple clients subscribing to different subjects could be mapped onto the same stream of data. The client is unaware that this mapping takes place, unless the data itself gives it away. Using mapping can reduce the volume of messages going through the system, as updates will only be received for the underlying subject. These updates will be then propagated to all the subjects mapped to them.

Amongst other possibilities, this means there is a more efficient way to support 'volume bands' - the definition of different spreads for different traded amounts. For example, you could specify one rate for trading between 0m to 10m GBPUSD (shown below) and another rate for 10m to 20m GBPUSD:

ClientClientLiberatorLiberatorDataSourceDataSource1Subject request (1m)2Subject request (1m)3Mapping message (map 1m to 10m)4Subject request (10m)5Data (10m)6Data (1m)

Looking at the example above, this is what happens:

  1. A request is received for a subject. In this case it is 1m GBPUSD.

  2. That request is sent through Liberator as normal.

  3. In response we receive a mapping message. In this case it is mapping 1m GBPUSD to 10m GBPUSD.

  4. As a result of that mapping, we send a request for the new subject (10m GBPUSD).

  5. At some point we receive an update for the new subject.

  6. Liberator sends the data update (for 1m GBPUSD) to the initial subject.

Take a look at how these mapping messages are actually implemented in the following code example:

@Override
public void onRequest(RequestEvent requestEvent)
{
    String subject = requestEvent.getSubject();
    MessageFactory messageFactory = publisher.getMessageFactory();
    Integer amountRequested = parseVolumeFromRequest(requestEvent);
    Integer volumeBand = getVolumeBandForAmountRequested(amountRequested, fakePricingSystem.getVolumeBands());
    if (volumeBand == null)
    {
        publisher.publishSubjectErrorEvent(messageFactory.createSubjectErrorEvent(subject, SubjectError.NotFound));
    }
    else if (amountRequested == volumeBand)
    {
        fakePricingSystem.subscribe(volumeBand);
    }
    else
    {
        String mapping = getSubjectForVolumeBand(requestEvent, volumeBand);
        publisher.publishMappingMessage(messageFactory.createMappingMessage(subject, mapping));
    }
}

private Integer getVolumeBandForAmountRequested(Integer volume, List<Integer> volumeBands)
{
    for (Integer band : volumeBands)
    {
        if (volume <= band)
        {
            return band;
        }
    }
    return null;
}

private String getSubjectForVolumeBand(RequestEvent requestEvent, Integer volumeBand)
{
    String subject = requestEvent.getSubject();
    String subjectWithoutVolume = subject.substring(0, subject.lastIndexOf('/') + 1);
    return subjectWithoutVolume + volumeBand;
}

private Integer parseVolumeFromRequest(RequestEvent requestEvent)
{
    String subject = requestEvent.getSubject();
    return Integer.parseInt(subject.substring(subject.lastIndexOf('/') + 1));
}

See also: