-
Notifications
You must be signed in to change notification settings - Fork 121
Binary EntryPoint Support
Binary EntryPoint is a FIXP based protocol for binary order entry used by B3. The B3 Documentation provides details of the protocol itself and should be considered a reference guide, the rest of this wiki page just explains how Artio can be used with Binary EntryPoint.
Binary EntryPoint is an order entry protocol that Artio supports. Just in the same way that Artio supports different versions of the FIX protocol. That means that Artio will manage the Binary EntryPoint session protocol and your application has to handle the business logic side of things for example sending orders and handling execution reports.
Feature complete.
The Binary EntryPoint implementation requires additional dependencies to artio-core with the following coordinates: uk.co.real-logic:artio-binary-entrypoint-codecs
and uk.co.real-logic:artio-binary-entrypoint-impl
. These packages are released to maven central along with normal artio releases. Here is an example dependencies section that includes Artio with Binary EntryPoint support.
dependencies {
implementation "uk.co.real-logic:artio-binary-entrypoint-codecs:${artioVersion}"
implementation "uk.co.real-logic:artio-binary-entrypoint-impl:${artioVersion}"
implementation "uk.co.real-logic:artio-codecs:${artioVersion}"
implementation "uk.co.real-logic:artio-core:${artioVersion}"
}
Within Artio each FIXP session is uniquely identified by a uk.co.real_logic.artio.fixp.FixPKey
and each individual connection by a uk.co.real_logic.artio.fixp.FixPContext
. Because sessions can have many connections each FixPKey
can be associated with many FixPContext
objects. The core object that represents a FIXP connection is a uk.co.real_logic.artio.fixp.FixPConnection
- the equivalent of our Session
object for FIX. This defines the state and the API that is common to all FIXP implementations. Each implementation has a specific key and context class that the classes can be downcasted to in order to extract implementation specific fields.
For any Binary EntryPoint implementation specific methods you can cast this connection object to a uk.co.real_logic.artio.binary_entrypoint.BinaryEntryPointConnection
.
Please refer to Artio's normal documentation and samples for examples of how to setup a FixEngine and FixLibrary within your project. These examples assume that you have a connected Library and go from there. The general pattern for accepting FIXP connections is that you have equivalent to Handler interfaces to the FIX interface but with a FIXP prefix here is a table showing comparable interfaces. Due to the nature of the difference between the FIX and FIXP protocols we don't share the exact same interface.
FIX | FIXP |
---|---|
uk.co.real_logic.artio.session.CompositeKey | uk.co.real_logic.artio.fixp.FixPKey |
uk.co.real_logic.artio.library.SessionExistsHandler | uk.co.real_logic.artio.library.FixPConnectionExistsHandler |
uk.co.real_logic.artio.library.SessionAcquireHandler | uk.co.real_logic.artio.library.FixPConnectionAcquiredHandler |
uk.co.real_logic.artio.library.SessionHandler | uk.co.real_logic.artio.fixp.FixPConnectionHandler |
uk.co.real_logic.artio.session.Session | uk.co.real_logic.artio.fixp.FixPConnection |
uk.co.real_logic.artio.engine.logger.FixMessageConsumer | uk.co.real_logic.artio.fixp.FixPMessageConsumer |
uk.co.real_logic.artio.BusinessRejectRefIdExtractor | uk.co.real_logic.artio.fixp.FixPRejectRefIdExtractor |
You can take a look at a working example in the uk.co.real_logic.artio.example_fixp_exchange
package of the artio-samples
project. This can be run with the sample program uk.co.real_logic.artio.system_tests.FixPExchangeApplication
.
Firstly in order to accept Binary EntryPoint connections you need to set EngineConfiguration
configuration option: configuration.acceptFixPProtocol(FixPProtocolType.BINARY_ENTRYPOINT)
.
If you want to configure an authentication strategy in order to accept or reject connections based upon a username or password then you need to set a FIXP specific authentication strategy. If none is set then all connections are accepted. Here is an example of setting an authentication strategy:
configuration.fixPAuthenticationStrategy((context, authProxy) ->
{
System.out.println("Request to authenticate: " + context);
authProxy.accept();
});
Two library callbacks need to be configured for FIXP connections to be accepted - similar to FIX sesions. These are the FixPConnectionExistsHandler
and FixPConnectionAcquiredHandler
.
The exists handler is a callback that notifies the library of a FIXP connection having connected and lets libraries make a request to the engine to acquire a FIXP connection - just like they would do with a FIX session. Here is an example of setting an exists handler: libraryConfiguration.fixPConnectionExistsHandler(existsHandler);
.
The only method that this needs to implement is the onConnectionExists
callback, here is an example that requests the session in question.
public Action onConnectionExists(
final FixLibrary library,
final long surrogateSessionId,
final FixPProtocolType protocol,
final FixPContext context)
{
final Reply<SessionReplyStatus> reply = library.requestSession(
surrogateSessionId, NO_MESSAGE_REPLAY, NO_MESSAGE_REPLAY, 5_000);
replies.add(reply);
return Action.CONTINUE;
}
The session acquire handler is again conceptually similar to its FIX equivalent and should return an instance of the FixPConnectionHandler which takes callbacks for events related to the FIXP Connection.
// Configuring the handler:
libraryConfiguration.fixPConnectionAcquiredHandler(connection -> onAcquire((BinaryEntryPointConnection)connection));
// Handler implementation:
FixPConnectionHandler onAcquire(final BinaryEntryPointConnection connection)
{
System.out.println(connection.key() + " logged in" + " with sessionId=" + connection.sessionId());
return new FixPExchangeSessionHandler(connection);
}
When Artio receives a FIXP message then the onBusinessMessage
method of your FixPConnectionHandler
will be invoked. Here is an example with inline comments explaining what to do:
public void onBusinessMessage(
final FixPConnection connection,
final int templateId,
final DirectBuffer buffer,
final int offset,
final int blockLength,
final int version,
final boolean possRetrans)
{
// (1) You can use the provided template id of the message in order to understand which message your system has received and ...
if (templateId == NewOrderSingleDecoder.TEMPLATE_ID)
{
final NewOrderSingleDecoder newOrderSingle = this.newOrderSingle;
// (2) ... then wrap the SBE decoder around the buffer, using the provided offset, block length and version.
newOrderSingle.wrap(buffer, offset, blockLength, version);
// (3) You need an SBE encoder flyweight - these are provided by the `artio-binary-entrypoint-codecs` project.
// In an idiomatic, low-allocation, system these encoders should be reused
final ExecutionReport_NewEncoder executionReport = this.executionReport;
// (4) Use the tryClaim API in order to wrap the encoder around an in memory buffer
// the second parameters is the length of the variable length component of the SBE codec.
final long position = connection.tryClaim(
executionReport, ExecutionReport_NewEncoder.NoMetricsEncoder.sbeBlockLength());
if (position < 0)
{
// Your attempt to claim a buffer has been back-pressured. This is unlikely to happen, but you
// want to re-attempt this operation later until it succeeds.
}
// (5) Set the values for your message - you can see some values are taken from the order that you've just decoded.
executionReport
.orderID(orderId++)
.clOrdID(newOrderSingle.clOrdID())
.securityID(newOrderSingle.securityID())
.secondaryOrderID(ExecutionReport_NewEncoder.secondaryOrderIDNullValue())
.ordStatus(OrdStatus.NEW)
.execRestatementReason(ExecRestatementReason.NULL_VAL)
.multiLegReportingType(MultiLegReportingType.NULL_VAL)
.workingIndicator(Bool.NULL_VAL)
.transactTime().time(System.nanoTime());
executionReport
.putTradeDate(1, 2)
.protectionPrice().mantissa(1234);
executionReport.receivedTime().time(System.nanoTime());
executionReport.noMetricsCount(0);
// (4) Commit the message - this tells Artio that it is ready to send. If an error or exception has
// happened during processing then you should call connection.abort() instead of commit.
connection.commit();
}
}
Artio's Binary EntryPoint implementation is Acceptor only, doesn't support Engine owned sessions, sole library mode.