Creating a Trading Integration Adapter.


Classes

struct  ctl_app_listener
 Listener interface that should be registered to receive notification of tradechannel creation and closing. More...

Typedefs

typedef void(* ctl_audit_log_cb )(void *ctx, ctl_provider *provider, const char *id, ctl_trade *trade, ctl_tradeevent *ev)
 Definition of the function that you should implement to receive audit logging.

Functions

ctl_providerctl_create_ds_provider (ctl_app_listener *listener, void *context, int num_models, const char *const *models, const char *namespacePattern)
 Create a DataSource trading provider.
void ctl_provider_set_audit_dslog (ctl_provider *provider, ds_log_t *log)
 Set the logfile that audit logs will be written to.
void ctl_provider_set_audit_logger (ctl_provider *provider, ctl_audit_log_cb callback, void *ctx)
 Set the callback function for the audit logger.
void ctl_provider_set_use_generic_messages (ctl_provider *provider, int use_generic_messages)
 Set whether the Trading provider will use generic messages.

Detailed Description

The purpose of a Trading Integration Adapter is to integrate between the Caplin Platform and an arbitrary 3rd party trading system.

Integration Adapters are built in C/C++ using the Datasource SDK, the Trading API interfaces with DSDK and permits you to develop Trading adapters without needing to know about messaging.

Library name

The name of the library containing the implementation of the Trading API for DataSource applications is libtrading_ds.a on Linux/MacOSX and TradingDS.lib/TradingDS.dll on Windows.

You need to compile your code with the macro HAVE_DSDK to ensure that the DataSource version of the Trading API is available.

Example Trading Adapter

Below is an example Trading adapter that demonstrates one way to interface with the Trading API.

#define HAVE_DSDK
#include "datasrc.h"
#include "ctl.h"

static void  service_status_cb(void *context, const char *service_name, int state);
static void  peer_status_cb(void *context, int peer_index, const char *peer_name, int state);


typedef struct esp_trade_handler_s esp_trade_handler;

struct esp_trade_handler_s {
    void    (*on_event)(esp_trade_handler *handler,  ctl_provider *provider, ctl_channel *channel, ctl_trade *trade, ctl_tradeevent *ev);
    void    (*close)(esp_trade_handler *handler, ctl_provider *provider, ctl_channel *channel, ctl_trade *trade);
};


static int                        c_models_num = 0;
static char                     **c_models = NULL;
static char                      *c_namespace = "/TRADE/%u/CHANNEL";
static ds5_connectionlistener_t   connection_listener;
static ds_log_t                  *logfile;
static ctl_provider              *provider;


static ctl_app_listener           app_listener;
static ctl_channel_listener       channel_listener;
static ctl_trade_listener         trade_listener;




static void esp_on_event(esp_trade_handler *handle, ctl_provider *provider, ctl_channel *channel, ctl_trade *trade, ctl_tradeevent *ev)
{
    const char *msgtype = ctl_tradeevent_get_type(ev);

    if ( strcmp(msgtype,"Open") == 0 ) {
        ctl_tradeevent *ack = ctl_trade_create_tradeevent(provider,channel, trade, "OpenAck");
        ctl_trade_process_event(provider, channel, trade, ack);

        ack =  ctl_trade_create_tradeevent(provider,channel, trade, "TradeConfirmation");
        ctl_trade_process_event(provider, channel, trade, ack);
    }

}

static void esp_close(esp_trade_handler *handler,  ctl_provider *provider, ctl_channel *channel, ctl_trade *trade)
{
    free(handler);
}

static esp_trade_handler *create_esp_trade()
{
    esp_trade_handler *handler = calloc(1,sizeof(*handler));

    handler->close = esp_close;
    handler->on_event = esp_on_event;

    return handler;
}



static void on_event(void *context, ctl_provider *provider, ctl_channel *channel, ctl_trade *trade, ctl_tradeevent *ev)
{
    const char *protocol = ctl_trade_get_protocol(provider,channel,trade);

    if ( strcmp(protocol,"ESP") == 0 ) {
        esp_trade_handler *handler = context;

        handler->on_event(handler, provider,channel,trade,ev);
    }
}


static void  trade_created(void *context, ctl_provider *provider, ctl_channel *channel, ctl_trade *trade)
{
    const char *protocol = ctl_trade_get_protocol(provider,channel,trade);
    ds_log(logfile, DS_LOG_NOTIFY|DS_LOG_TERMINAL,"trade_created: Trade %p created type %s\n",trade,protocol);

    if ( strcmp(protocol,"ESP") == 0 ) {
        esp_trade_handler *handler = create_esp_trade();
        
        ctl_trade_set_user_pointer(provider, channel, trade, handler);
        ctl_trade_set_listener(provider,channel,trade,&trade_listener,handler);
    }
}


static void  trade_closed(void *context, ctl_provider *provider, ctl_channel *channel, ctl_trade *trade)
{
    const char *protocol = ctl_trade_get_protocol(provider,channel,trade);
    ds_log(logfile, DS_LOG_NOTIFY|DS_LOG_TERMINAL,"trade_closed: Trade %p closed\n",trade);

    if ( strcmp(protocol,"ESP") == 0 ) {
        esp_trade_handler *handler = ctl_trade_get_user_pointer(provider, channel, trade);
        handler->close(handler, provider,channel,trade);
    }
}







static void channel_created(void *context, ctl_provider *provider, ctl_channel *channel)
{
    ds_log(logfile, DS_LOG_NOTIFY|DS_LOG_TERMINAL,"channel_created: Channel %p created\n",channel);

    ctl_channel_set_listener(provider, channel, &channel_listener, NULL);
}


static void channel_closed(void *context, ctl_provider *provider, ctl_channel *channel)
{
    ds_log(logfile, DS_LOG_NOTIFY|DS_LOG_TERMINAL,"channel_closed: Channel %p closed\n",channel);
}

static void  service_status_cb(void *context, const char *service_name, int state)
{
    char  *state_str = "";
    switch ( state )
    {
    case SVC_STATUS_OK:
        state_str = "Ok";
        break;
    case SVC_STATUS_DOWN:
        state_str = "Down";
        break;
    case SVC_STATUS_LIMITED:
        state_str = "Limited";
    }

    ds_log(logfile, DS_LOG_NOTIFY|DS_LOG_TERMINAL,"service_status_cb: Service <%s> is now %s\n",service_name,state_str);
}

static void  peer_status_cb(void *context, int peer_index, const char *peer_name, int state)
{
    char  *state_str = "";
    switch ( state )
    {
    case DS_MSG_CONNECT:
        state_str = "Connected";
        break;
    case DS_MSG_DISCONNECT:
        state_str = "Disconnected";
        break;
    }

    ds_log(logfile, DS_LOG_NOTIFY|DS_LOG_TERMINAL,"source_status_cb: DataSource Peer <%s> index %d is now %s\n",peer_name,peer_index,state_str);
}




int main(int argc, char *argv[])
{
#ifdef WIN32
   WORD                wVersionRequested;
   int                 err;     
   WSADATA             wsaData;

   wVersionRequested = MAKEWORD(2,2);
   err = WSAStartup(wVersionRequested, &wsaData);
   if (err != 0)
     {
        fprintf(stderr, "demosrc: Unable to initalise socket library\n");
        exit(EXIT_CODE_SYS);
     }
#endif /* WIN32 */   
   ds5_config_init("tradingds.conf", argc, argv);

   ds_config_add_array_option("model-file", "Define a file for trade models",DS_CONFIG_STR,&c_models,&c_models_num);
   ds_config_add_option(0,"trading-namespace","Namespace for trade subjects",DS_CONFIG_STR,&c_namespace);

   ds5_init(argc,argv);

   connection_listener.service_status = service_status_cb;
   connection_listener.peer_status = peer_status_cb;
   logfile = ds_get_event_log();
   ds5_add_connectionlistener(&connection_listener, NULL);


   /* Setup the listener callbacks */
   app_listener.channel_created = channel_created;
   app_listener.channel_closed = channel_closed;
   channel_listener.trade_created = trade_created;
   channel_listener.trade_closed = trade_closed;
   trade_listener.on_event = on_event;

   provider = ctl_create_ds_provider(&app_listener, NULL, c_models_num, (const char * const *)c_models, c_namespace);

   ds_log(logfile,DS_LOG_NOTIFY|DS_LOG_TERMINAL,"tradingds is now starting\n");




   ds_loop();
   return 0;
}



Typedef Documentation

typedef void(* ctl_audit_log_cb)(void *ctx, ctl_provider *provider, const char *id, ctl_trade *trade, ctl_tradeevent *ev)

Definition of the function that you should implement to receive audit logging.

Parameters:
ctx - Your context (registered with ctl_provider_set_audit_logger())
provider - The trading provider
id - A textual representation of what has happened
trade - The trade to which this audit event pertains
ev - The trade event that stimulated this audit event


Function Documentation

ctl_provider* ctl_create_ds_provider ( ctl_app_listener listener,
void *  context,
int  num_models,
const char *const *  models,
const char *  namespacePattern 
)

Create a DataSource trading provider.

Parameters:
listener - The application listener that will receive notification of trade channel opens and closes.
context - A callback context for the listener parameter
num_models - Number of trade model files to read
models - An array of XML files that contain trademodel definitions
namespacePattern - The pattern that matches trade channels
Returns:
A new provider
The namespacePattern should include a %u to indicate the position of the username, for example: "/TRADE/%u/CHANNEL".

void ctl_provider_set_audit_dslog ( ctl_provider provider,
ds_log_t *  log 
)

Set the logfile that audit logs will be written to.

Parameters:
provider - The trading provider
log - The DataSource logfile that audit logs will be written to
Note:
If you want to handle audit log events yourself then you register a function with ctl_provider_set_audit_logger()

void ctl_provider_set_audit_logger ( ctl_provider provider,
ctl_audit_log_cb  callback,
void *  ctx 
)

Set the callback function for the audit logger.

Parameters:
provider - The trading provider
callback - Callback that will be invoked when an audit event is generated
ctx - Callback context

void ctl_provider_set_use_generic_messages ( ctl_provider provider,
int  use_generic_messages 
)

Set whether the Trading provider will use generic messages.

Parameters:
provider - The Trading provider
use_generic_messages - Non zero if generic messages should be used
Generic messages do not require field configuration or extra configuration in the Liberator to disable throttling. In general it is recommended that they are used.

This function should be called before the first trade channel has been been opened, that is prior to the ds_loop() call in your Adapter.


Generated on Fri Aug 14 12:41:23 2015 for Trading API for C by  doxygen 1.5.3