xConnectivity

xConnectivity is a FIX connectivity bridge. It comes with a high performance FIX engines plugin developed in C++.It has an open iterface that allowed customer to developer their own plugins for integration with your private OMS.

The x Connectivity platform support FIX versions from 4.2 to 5.0sp2. Different FIX version can be configured with differernt plugins. The bridge provide a feature to allow you to transfer the messages from one plugin to another plugin with a different version using Lua scripting language.

How to integrate the system with your private OMS? The solution provides an open interface for you to development your own plugins. Its FIX plugin can also be directed called from your private OMS system.

Installation

The system is designed to run on 64 bit Windows and Linux.

Windows

xconnectivity
│──bin
│   │   codec_fix.dll                 --Fix encoder/decoder
│   │   fix.dll                       --FIX plugin, support all version of FIX protocol
│   │   fix.lib                       --FIX plugin library for re-development
│   │   key                           --License key file
│   │   LICENSE.txt                   --License policy
│   │   message.dll                   --Processes message template
│   │   msvcp140.dll                  --VC140 redistribution library
│   │   vcruntime140.dll              --VC140 redistribution library
│   │   x.exe                         --xConnectivity application
│   │   x.xml                         --xConnectivity configuration file
│   │   buy.exe                       --buy side sample application
│   │   buy.xml                       --buy side sample configuration
│   │   sell.exe                      --sell side sample application
│   │   sell.xml                      --sell side sample configuration
│   ├───db                            
│   ├───fix                           --FIX specifications
│   │       fix42.xml
│   │       fix44.xml
│   │       fix50sp1.xml
│   │       fix50sp2.xml
│   ├───log
│   └───script
├───include
└───sample
		
Linux

xconnectivity
├───bin
│   │   buy
│   │   buy.sh
│   │   buy.xml
│   │   key
│   │   libcodec_fix.so
│   │   libfix.so
│   │   libmessage.so
│   │   LICENSE.txt
│   │   sell
│   │   sell.sh
│   │   sell.xml
│   │   x
│   │   x.sh
│   │   x.xml
│   ├───db
│   ├───fix
│   │       fix42.xml
│   │       fix44.xml
│   │       fix50sp1.xml
│   │       fix50sp2.xml
│   ├───log
│   └───script
├───include
└───sample
		

Configuration

The syste is designed to use XML format as standard configuration file. it always comes with the following format:


<?xml version="1.0" encoding="utf-8"?>
<!--x system configuration always start with application. Name will display on the UI-->
<application name="xConnectivity">
	<!-- Log configuration
		name : name of the log
		file : log file path and name, the actual name will be suffixed with date & time.
		queue_size: async log queue size. default set 65535
		pattern: each log line format:
				%Y - year in 4 digital
				%C - year in 2 digital
				%m - Month 01- 12
				%d - Day of the month 01-31
				%H - Hour
				%M - Minutes
				%S - Seconds
				%f - Microseconds
				%t - thread id
				%L - log level
				%V - log content
				%E - line end
				%P - process id
				%n - log name
		level: 0 - 10, 0 is the lowest, and 10 is the highest.
	-->
	<log name="x" file="./log/x" queue_size="65536" pattern="[%H:%M:%S.%f] %t %L %v%E" level="2" />
	
	<!--In menory data file configuration, initial db size=128mb, 
		set this number big enough to avoid memory relocation.
		file : file path and name of the database. it creates as an memory map file.
		name : name of the database
		access_type: 0-read only, 1 - read & write
		init_size : 1,2,4,8,16m etc in byte.
		extension_quantum : specify the extension size when mentioned size is in sufficent.
		commit_delay: 1 - delayed, 0- no delayed, synchorinize immediately into file.
		
		Replications can be setup for the in memory database.
	-->
	<db file="./db/x.fdb"
			name="x"
			access_type="1"
			init_size="134217728"
			extension_quantum="0"
			commit_delay="1">
		<replication my_index="0">
			<connection addr="127.0.0.1:18000"/>
		</replication>
	</db>

	<!-- configure the plugins to be loaded into the application. The system comes with a series of 
		 ready to use plugins such as FIX, ipc, IBMMQ, multicast, exchange APIs, (SGX, etc.)
		 With the open source interface, it is easy to develop your own plugins.
	-->
	<plugins>
		<plugin name="fix" lib="fix" config="./x.xml" />
	</plugins>

	<!-- Below configuration used by FIX plugin.
		the fix can be configured as initiator or acceptor.
		sender : compid for this instance
		target : compid for counter party
		template : specifys the version of FIX plugins.
		codec : encoding /decoding format.
		heartbeat_interval: for initiator
		recv_buffer_size/send_buffer_size :  receive and sender buffer size for each session
		property : default 0x0
		connections : specifies the connections, can add multiple ip address and port for 
					  auto failover.
		scheduler : fix session start , stop and reset timing. holidays can be configured as well.
		
	-->
	<fix number_of_thread="1">
		<initiator sender="X"
				   target="SELL"
				   template="./fix/fix42.xml"
				   codec="codec_fix"
				   heartbeat_interval="10"
				   recv_buffer_size="102400"
				   send_buffer_size="102400"
				   property="0x00000001">

			<connections connect_interval="10" connect_timeout="10">
				<connection addr="127.0.0.1" port="8001" />
			</connections>
			<scheduler>
				<tasks>
				<session start="daily@00:10:00" stop="daily@23:59.59" reset="daily@00:05"/>
				</tasks>
			</scheduler>
		</initiator>
		
		<acceptor sender="X"
				target=""
				template="./fix/fix42.xml"
				codec="codec_fix"
				recv_buffer_size="1024000"
				send_buffer_size="1024000"
				property="0x00000059">

			<!-- connections -->
			<connections connect_timeout="10">
				<connection port="8000"/>
			</connections>

			<scheduler>
				<tasks>
				<session start="daily@00:10:00" stop="daily@23:59.59"  reset="daily@00:05"/>
				</tasks>
				<holidays>
					<holiday date="20161120" />
				</holidays>
			</scheduler>
		</acceptor>
	</fix>

	<!-- Specifies the routing option
		 dropcopy : for any message, you can specify multiple destination for dropcopy. 
		 encrichment : you can specify the enrichment script as well.
	-->
	<router>
		<target name="SELL">
			<sender name="BUY"  dropcopy="BO"/>
		</target>
	</router>
</application>
				
		

Development

With the open source interface, it is it easy to develop your own plugin or integrate the ultra low latency fix plugins into your own application. The interface files in C++ are provided in the include in the package.

The following are the interfaces files:

sessionhandler.h virtual interface to handle the session activity. You have to implement this virtual interface to handle the messages or sending message out.

session.h define the session interface. you can start/stop session via this interface.

message.h message definition.It defines the interfaces to get/set value on a specific messages.

field.h interface for the specific field on a message.

fix42.h fix tag/value definition. You can modify this file to add your customermized tags.

plugin.h to start and stop a plugin.

Below is am exaple in C++ code. For more details, refer to the sample code included in this package.


class Application :public SessionHandler
{
public:
	Application() : id(0)
	{
		void* handle = dlopen("libfix.so", RTLD_NOW| RTLD_GLOBAL|RTLD_DEEPBIND);
		if (handle != NULL)
		{
			createPlugin = (lib_func) dlsym(handle, "createPlugin");
	
			plugin = createPlugin(*this, NULL, NULL);			
		}
	}

	virtual ~Application() {}

	virtual bool Initialize(const char* config, bool encrypted = false)
	{
		if (!plugin->Initialize(config, encrypted))
		{
			printf("error:failed to initialize fix plugin");
			return false;
		}
		return true;
	}

	virtual bool Start()
	{
		if (!plugin->Start())
		{
			printf("error:failed to start fix plugin");
			return false;
		}
		return true;
	}

	virtual void Stop()
	{
		plugin->Stop();
	}

	virtual void Destory(bool force_failover = false)
	{
		plugin->Destory(force_failover);
	}

	virtual Session* findSession(const char* target)
	{
		return plugin->findSession(target);
	}

	virtual void onUnhandledMessage(Session* session, Message* msg, const char* msg_type, char* buffer, int len)
	{
		if (session->isConnected())
		{
			if (msg_type[0] == 'D')// NewOrderSingle
				ExecutionReport(session, msg);
		}
	}
public:
	void ExecutionReport(Session* session, Message* imsg)
	{
		Message* omsg = session->CreateMessage(MsgType::EXECUTION_REPORT);
		if (omsg != NULL)
		{
			Field* ibody = imsg->getBody();
			Field* obody = omsg->getBody();
			
			char execid[20];
			char t[25];
			sprintf(execid, "%015d", ++id);
			obody->setString(ExecutionReport::OrderID, "NONE")
				->setString(ExecutionReport::ClOrdID, ibody->getString(NewOrderSingle::ClOrdID, NULL))
				->setString(ExecutionReport::ExecID, execid)
				->setChar(ExecutionReport::ExecType, ExecType::REJECTED)
				->setChar(ExecutionReport::OrdStatus, OrdStatus::REJECTED)
				->setString(ExecutionReport::Account, ibody->getString(NewOrderSingle::Account, NULL))
				->setString(ExecutionReport::Symbol, ibody->getString(NewOrderSingle::SecurityExchange))
				->setString(ExecutionReport::SecurityType, ibody->getString(NewOrderSingle::SecurityType, NULL))
				->setString(ExecutionReport::SecurityExchange, ibody->getString(NewOrderSingle::SecurityExchange, NULL))
				->setChar(ExecutionReport::Side, ibody->getChar(NewOrderSingle::Side, Side::BUY))
				->setString(ExecutionReport::TransactTime, GetUTCDateTime(t, 25))
				->setDouble(ExecutionReport::OrderQty, ibody->getDouble(NewOrderSingle::OrderQty, 0))
				->setChar(ExecutionReport::OrdType, ibody->getChar(NewOrderSingle::OrdType))
				->setDouble(ExecutionReport::Price, ibody->getDouble(NewOrderSingle::Price, 0))
				->setChar(ExecutionReport::TimeInForce, ibody->getChar(NewOrderSingle::TimeInForce, '0'))
				->setDouble(ExecutionReport::LastShares, 0.0)
				->setDouble(ExecutionReport::LastPx, 0.0)
				->setDouble(ExecutionReport::LeavesQty, 0.0)
				->setDouble(ExecutionReport::CumQty, 0.0)
				->setString(ExecutionReport::Text, "Order Rejected");

				
			sendMessage(session, omsg, MsgType::EXECUTION_REPORT, true);
			session->ReleaseMessage(omsg);
		}
		else
		{
			printf("error: failed to create message:%s\n", MsgType::EXECUTION_REPORT);
		}
	}
private:
	Plugin* plugin;	
	lib_func createPlugin;
	int id;
};

	

int main()
{
	const char* config_file = "./sell.xml";
	char buffer[100];
	Application app;
	try
	{
		if (app.Initialize(config_file))
		{
			if (!app.Start())
			{
				printf("error: failed to start application\n");
				printf("Press ENTER to quit!\n");
				GetLine(buffer, 100);
			}
		}
		else
		{
			printf("error: failed to initialize application\n");
			printf("Press ENTER to quit!\n");
			GetLine(buffer, 100);
		}


		printf("Press ENTER to quit!\n");
		GetLine(buffer, 100);

		app.Stop();
		app.Destory();
	}
	catch (std::exception& e)
	{
		printf("exception:%s\n", e.what());
	}

	printf("Press ENTER to quit!\n");
	GetLine(buffer, 100);
	return 0;
}
		

Examples

There are two examples included in this package:

example 1: integrate ultra low latency fix plugin into your own application, and directly connect to other counter party. In this example, after you start both buy & sell application, you can trigger the NewOrderSingle message to sell side. It will response with an ExecutionReport(8) once received the NewOrderSingle message.

Below is the performance shows for a round trip latency.Both buy and sell application runs on the same server. The sample testing runs on Ubuntu 18.04, Intel Core i7-8750H CPU @2.2GHz, 8G DDR3 RAM and 500G SSD

ultra low latency fix engine latency statistic
ultra low latency fix engine latency statistic

example 2: buy and sell side to connect to xConnectivity and routing message via xConnectivity.

In this example, we measures the timing xConnectivity used to forward a message.Ubuntu 18.04, Intel Core i7-8750H CPU @2.2GHz, 8G DDR3 RAM and 500G SSD

ultra low latency xConnectivity bridge latency statistic
ultra low latency xConnectivity bridge latency statistic