Implementing Post-trade Allocation

Requirements

You require:

  • Front end: FX Sales 2.33 or greater, configured to use the User Config to supply user entitlements instead of permissioning.

  • Back end: an integration adapter built against the FX Integration API 3.69 or later, with a registered implementation of the AllocateTradeListener interface.

Implement the AllocateTradeListener interface

In this section you will implement the AllocateTradeListener interface.

AllocateTradeListener handles client-sent events in the Allocate trade model, the state diagram for which is reproduced below:

InitialDetailsRequestedDetailsProvidedClientCloseSentSubmittedAllocatedQueuedExpiredPickedUpClientClosedExecutableExecuteSentExecutedWarningSentTradeConfirmedAcceptWarningSentDetailsRequestDetailsUpdateClientCloseSubmitClientCloseAllocateAckSubmitAckExpireClientClosePickUpHoldClientCloseAckPriceUpdateWithdrawClientCloseExpireExecutePriceUpdateResubmitClientCloseExecuteAckPriceUpdateWarningExpireTradeConfirmationAcceptWarningRejectWarningClientCloseAcceptWarningAckLegendTransitions initiated by the client are inyellow.Transitions initiated by the server are inblue.
The Allocate trade model (FX Integration API 8.3.0)

Once an Allocate trade enters the Queued state, the trade model is identical to the RFS trade model. If your system already supports the RFS trade model and implements the RFSTradeListener interface, it is likely you can reuse that class for generating price updates and trade confirmation messages with some small modifications to support the Allocation trading type.

Follow the steps below:

  1. Create an implementation of the AllocateTradeListener interface:

    com.caplin.generated.motif.fx.trading.allocateAllocateTradeListeneronDetailsRequest(AllocateTradeEvent)onClientClose(ClientCloseTradeEvent)onSubmit(SubmitTradeEvent)onExecute(SubmitTradeEvent)onTradeClosed()MyAllocateTradeListenerAllocateTrade allocateTradeMyAllocateTradeListener(AllocateTrade)onDetailsRequest(DetailsRequestTradeEvent)onClientClose(ClientCloseTradeEvent)onSubmit(SubmitTradeEvent)onExecute(ExecuteTradeEvent)onTradeClosed()
  2. In the constructor for your implementation, store a reference to the AllocateTrade constructor parameter:

    public class MyAllocateTradeListener implements AllocateTradeListener
    {
      private AllocateTrade allocateTrade = null;
    
      public MyAllocateTradeListener(AllocateTrade allocateTrade)
      {
        this.allocateTrade = allocateTrade;
      }
    
      ...
    }
  3. Implement the following AllocateTradeListener methods:

Implement onDetailsRequest

When the user launches an allocation, a DetailsRequest message is received from the client and the onDetailsRequest(DetailsRequestTradeEvent) listener is triggered.

In the onDetailsRequest(DetailsRequestTradeEvent) method of your implementation, handle the client’s request for trade details:

  1. Using the TradeID field of the DetailsRequestTradeEvent as a reference, request the trade’s details from your trading system.

  2. Check the trade is identified by the trading system as allocatable, and perform any further validation required by your implementation. If the trade is invalid, then send a Reject message to the client:

    this.allocateTrade.sendRejectTradeEvent();
  3. If the trade is valid, then create and send a DetailsUpdate message to the client:

    1. Create an instance of AllocationSpotSalesDetailsUpdate or AllocationForwardSalesDetailsUpdate using the class’s associated builder, accessed via the newBuilder() method. For documentation on the builders, see AllocationSpotSalesDetailsUpdate.Builder and AllocationForwardSalesDetailsUpdate.Builder.

      // Build the DetailsUpdate message
      Message tradeDetails = AllocationSpotSalesDetailsUpdate.newBuilder()
                                        .setSpotSalesTradeConfirmation( ... )
                                        .setDisplayFields( ... )
                                        // ... example truncated

      The DisplayFields value on the DetailsUpdate message determines which fields are displayed under the Original Deal Details heading. You may use the utility method addDefaultSalesAllocationDetailsUpdateFields, which adds the Caplin-default display fields to a DisplayFields instance. Using this method, you may add custom fields before or after the default fields. Alternatively, you can compose your display fields configuration field by field, combining your custom fields with Caplin-default fields, for which DefaultDisplayFields provides static builders methods.

      The Caplin-default display fields for the Sales Allocate DetailsUpdate message are: Amount, Contra Amount, Currency Pair, Settlement Currency (if non-deliverable), Settlement, Fixing Date (if non-deliverable), Fixing Source (if non-deliverable), Account and Rate.
    2. Send the AllocationSpotSalesDetailsUpdate or AllocationForwardSalesDetailsUpdate message to the client:

      // Send the DetailsUpdate message to the client
      this.allocateTrade.sendDetailsUpdateEvent(tradeDetails);

Implement onClientClose

In the onClientClose(ClientCloseEvent) method of your implementation, handle the client’s closure of the allocation:

  1. Perform any clean up and logging required by your implementation

  2. Send a ClientCloseAck message to the client:

    this.allocateTrade.sendClientCloseAckTradeEvent();

Implement onSubmit

When a user submits the allocation they want to perform, a Submit message is sent to your adapter and the onSubmit(SubmitTradeEvent) listener method is called.

In the onSubmit(SubmitTradeEvent) method of your implementation, handle the submitted allocation:

  1. Retrieve the legs from the SubmitTradeEvent instance and validate them. If any of the allocation legs are invalid, then send a Reject message to the client:

    this.allocateTrade.sendRejectTradeEvent();
  2. If the settlement date of each leg is identical to the settlement date of the original trade, then follow the steps below:

    1. Send an AllocateAck message to the client, which transitions the trade from the Submitted state to the Allocated state:

      this.allocateTrade.sendAllocateAckTradeEvent();
    2. Re-allocate the trade using your trading system’s API.

    3. Update blotter records for the original trade:

      Field Value

      Status

      Allocated

      CanAllocate

      false

      CanRoll

      false

      IsAllocated

      true

  3. If the settlement date of any leg is different to the settlement date of the original trade, then follow the steps below.

    1. Send a SubmitAck message to the client, which transitions the trade from the Submitted state to the Queued state:

      this.allocateTrade.sendSubmitAckTradeEvent();
    2. Currently, manual pricing via dealer intervention is not supported for allocations. Do not send the allocation to the active deals blotter. Instead, immediately send a PickUp message to the client, which transitions the trade from the Queued state to the PickedUp state:

      this.allocateTrade.sendPickUpTradeEvent();
    3. Send the first of a series of PriceUpdate messages, which transitions the trade from the PickedUp state to the Executable state:

      // Build the PriceUpdate message
      PriceUpdateTradeEvent priceUpdate = AllocationQuote.newBuilder()
                                        .setCommonTradeDetailsFields( ... )
                                        // ... example truncated
      
      this.allocateTrade.sendPriceUpdateEvent(priceUpdate);

Implement onExecute

When the user attempts to finalise a reprice allocation, an Execute message is received from the client and the onExecute(ExecuteTradeEvent) listener method will be triggered.

In the onExecute(ExecuteTradeEvent) method of your implementation, perform the following steps:

  1. Send an ExecuteAck message to the client, which transitions the trade from the Executable state to the ExecuteSent state:

    this.allocateTrade.sendExecuteAckTradeEvent();
  2. Validate the ExecuteTradeEvent legs. If the leg data is invalid, then send a Reject message to the client:

    this.allocateTrade.sendRejectTradeEvent();
  3. If the leg date is valid, perform the following steps:

    1. Re-allocate the trade using your trading system’s API.

      New trades created from repriced legs should use the rate and margin details of the Allocate trade, however legs that were not repriced should still use the details of the original trade.

    2. Send a TradeConfirmation message to the client:

      // Build the TradeConfirmed message
      AllocationSalesConfirmation msg = AllocationSalesConfirmation.newBuilder()
                                                          .setCommonFields( ... )
                                                          .setDisplayfields( ... )
                                                          // ... example truncated
      
      this.allocateTrade.sendTradeConfirmationEvent(msg);

      The DisplayFields value on the DetailsUpdate message drives which fields are displayed above the trade confirmation table. You may utilise the utility method addDefaultSalesAllocationConfirmationFields, which adds the Caplin-default display fields to a DisplayFields instance. Using this method, you may add custom fields before or after the default fields. Alternatively, you can compose your display fields configuration field by field, combining your custom fields with Caplin-default fields, for which DefaultDisplayFields provides static builders methods.

      The Caplin-default display fields for the Sales Allocate TradeConfirmation message are: Client, Currency Pair, Settlement Currency (if non-deliverable), Fixing Source (if non-deliverable), Date, Time, Trader Spot Rate, Spot Margin, Client Spot Rate, Total Deals, Estimated Profit.
    3. Update blotter records for the original trade:

      Field Value

      Status

      Allocated

      CanAllocate

      false

      CanRoll

      false

      IsAllocated

      true

Implement onTradeClosed

In the onTradeClosed method in your implementation, handle any clean up and logging required when the trade channel is closed.

Register your implementation of AllocateTradeListener

Implement and register an instance of AllocateTradeListenerFactory with the FXTradeAdapter instance in your adapter.

The code example below creates and registers an anonymous implementation of the AllocateTradeListenerFactory interface:

fxTradeAdapter.registerAllocateTradeListenerFactory(
  new AllocateTradeListenerFactory() {
    @Override
    public AllocateTradeListener createTradeListener(AllocateTrade trade)
        throws TradeException {
      return new MyAllocateTradeListener(trade);
    }
  }
)

The code above can also be expressed using a Java method reference to the MyAllocateTradeListener constructor, which shares the same method signature as the method createTradeListener in AllocateTradeListenerFactory:

fxTradeAdapter.registerAllocateTradeListenerFactory(MyAllocateTradeListener::new);

Add PTA fields to trade confirmation messages

Wherever your back end code creates a trade confirmation message, set values for the CanAllocate, CanRoll and IsAllocated fields in the CommonTradeConfirmationFields field set.

The CommonTradeConfirmationFields field set is used in TradeConfirmation messages in the following trade models:

The CommonTradeConfirmationFields field set is used in the following blotter records:

Field definitions
CanAllocate

When you set this field to true, it indicates to front-end applications that the back-end trading system supports allocation of this trade.

CanRoll

When you set this field to true, it indicates to front-end applications that the back-end trading systems supports the rolling of settlement dates during allocations of this trade.

IsAllocated

When you set this field to true, it indicates to front-end applications that the trade has been allocated and can no longer be allocated or rolled (regardless of the value of CanAllocate).

Front-end applications should refer to the values of both CanAllocate and IsAllocated to determine if a trade is allocatable.

Determining if a trade is allocatable or rollable
CanAllocate CanRoll IsAllocated Trade is allocatable? Trade is rollable?

true

true

true

true

true

false

true

false

true

true

false

false

false

true

true

false

true

false

false

false

true

false

false

false

Configure user entitlements

Post-trade Allocation is enabled via the Configuration Service.

Add the following feature to the feature configuration in your client configuration:

new FXFeatures().postAllocation(new FXFeaturesPostAllocation().enabled(true));

If CAPLIN.PTA.ENTITY_SEARCH.ENABLED is enabled, i.e. if the Client or Entity column is shown on your frontend, add the following feature to the feature configuration in your user configuration:

new FXFeatures().postAllocation(new FXFeaturesPostAllocation().toboSelection(USER_CONFIG));

For toboSelection, choose either USER_CONFIG to provide clients via user config, or CLIENT_SEARCH to provide clients via the client search API.

For more information on the configuration service see, see User Config.

Configure Post-trade Allocation in FX Sales

The following FX Sales configuration items apply to Post-trade Allocation:

CAPLIN.PTA.ENTITY_SEARCH.ENABLED

Set to true to display the client column in the allocation table on Post-trade Allocation tickets. The client column allows the trader to allocate to a different client than that of the original trade. For more information, see CAPLIN.PTA.ENTITY_SEARCH.ENABLED.

CAPLIN.MOTF.TICKET.ACCOUNT.ALLOW_NULL_SELECTION

Set to true to allow traders to allocate to null trading accounts. Also allows traders to trade against null trading accounts in MOTF tickets. For more information, see CAPLIN.MOTF.TICKET.ACCOUNT.ALLOW_NULL_SELECTION

CAPLIN.MOTF.TICKET.ACCOUNT.AUTO_SELECT_FIRST

Set to true to automatically select the first valid trading account after changing the value in a Client cell in the allocation table on Post-trade Allocation tickets (see CAPLIN.PTA.ENTITY_SEARCH.ENABLED). Also automatically selects the first valid trading account in MOTF tickets. For more information, see CAPLIN.MOTF.TICKET.ACCOUNT.AUTO_SELECT_FIRST


See also: