EasyMSX Documentation

The EasyMSX code samples are various projects to demonstrate how Bloomberg EMSX API along with other Bloomberg API and industry standard algorithms can be implemented for building and implementing an efficient trading environment.

Important

Please note that this is not a compiled binary. This is a CODE SAMPLE. There is no SLA (Service Level Agreement) or quality assessment or guarantees.

Warning

Please do not reach out to Bloomberg for support or help.

Introduction

The EasyMSX wrappers consists of various code samples that can be compiled into a library. The EasyMSX are set of files to build a project that demonstrates one possible way to build caching data or a starting place to work with Bloomberg EMSX API and other Bloomberg APIs.

The EMSX API is just another service in Bloomberg API V3. The Bloomberg API follows an event-driven asynchronous API paradigm.

The Bloomberg API is lightweight, thread safe and maintains extensible service-oriented data model. The Bloomberg API generally understands the concept of subscription and request-response services.

Projects

There are currently three active projects written in C Sharp and Python. Other programming languages and projects will follow shortly.

Prerequisites

  • All C# projects requires .NET 4.0 but has no other external dependencies.
  • The python projects runs in Python 3.

EasyMSX

The EasyMSX allows getting orders, routes, and static data from EMSX API service. The EasyMSX allows adding notification handler on the real-time events. There is an observer pattern that can throw exceptions.

Installing

  • For C#, Download the source code and build the library from the source. Once the Bloomberg API SDK has been referenced in your project, create an instance of EasyMSX:-
  • For python, create the new directory and extract easymsx-1.0.x into the new directory. Change the directory to easymsx-1.0.x and in the directory run the following command:-
C:\Users\Me\>cd easymsx-1.0.x

C:\Users\Me\easymsx-1.0.x>C:\Python34\python.exe setup.py install
  • Run easymsxdemo.py
C:\Users\Me\>cd easymeasymsx-1.0.x

C:\Users\Me\easymsx-1.0.x>py -3 easymsxdemo.py
  • The GitHub link to the EasyMSX sample in EasyMSX.

EasyMKT

The EasyMKT and EasyMKTSample are essentially an EasyMSX for market data where the project demonstrates one possible way to build caching data on Bloomberg real-time market data.

Installing

  • For C#, Download the source code and build the library from the source. Once the Bloomberg API SDK has been referenced in your project, create an instance of EasyMKT:-
  • For python, create the new directory and extract easymkt-1.0.x into the new directory. Change the directory to easymkt-1.0.x and in the directory run the following command:-
C:\Users\Me\>cd easymkt-1.0.x

C:\Users\Me\easymkt-1.0.x>C:\Python34\python.exe setup.py install
  • Run easymktdemo.py
C:\Users\Me\>cd easymsx-1.0.x

C:\Users\Me\easymkt-1.0.x>py -3 easymktdemo.py
  • The GitHub link to the EasyMKT sample in EasyMSX.

RuleMSX

Rather than making use of domain specific language (DSL) to define the rules, it exposes a series of abstract classes. It facilitates the creation of complex if-this-then-that behavior.

Installing

  • For C#, Download the source code and build the library from the source.
  • For python, create the new directory and extract easymsx-1.0.0 and rulemsx-1.0.0 into the new directory.
C:\Users\Me\_rulemsx>dir
Volume in drive C is Windows
Volume Serial Number is ABCD-1234

Directory of C:\Users\Me\_rulemsx

12/21/2017  09:08 AM    <DIR>          .
12/21/2017  09:08 AM    <DIR>          ..
12/21/2017  09:01 AM    <DIR>          easymsx-1.0.0
12/21/2017  09:01 AM    <DIR>          rulemsx-1.0.0
12/21/2017  09:01 AM    <DIR>          RuleMSXDemo.py
               1 File(s)              0 bytes
               4 Dir(s)  11,538,878,464 bytes free
  • Change the directory to rulemsx-1.0.0 and in the directory run the following command:-
C:\Users\Me\_rulemsx>cd rulemsx-1.0.0

C:\Users\Me\_rulemsx\rulemsx-1.0.0>C:\Python34\python.exe setup.py install
  • Please make sure the path for python is set to where you currently have your python 3 installed. Change directory to easymsx-1.0.0 and in the diretory run the following command:-
C:\Users\Me\_rulemsx>cd easymsx-1.0.0

C:\Users\Me\_rulemsx\easymsx-1.0.0>C:\Python34\python.exe setup.py install
  • Run RuleMSXDemo.py
C:\Users\Me\_rulemsx>py -3 RuleMSXDemo.py
Initialising RuleMSX...
RuleMSX initialised...
Initialising EasyMSX...
EasyMSX initialised...
Create RuleSet...
Building Rules...
Rules built.
RuleSet ready...
Press any to terminate

Getting Started

The following is the C# implementation of the RuleMSX sample. RuleMSX provides the core functionality of a rule engine. Once the library has been referenced in your project, create an instance of RuleMSX:-

RuleMSX rmsx = new RuleMSX();

RuleMSX is divided into ‘Rules’_, ‘DataPoints’_ and ‘Actions’_. Rules are organized into ‘RuleSets’_:-

RuleSet myRuleSet = this.rmsx.CreateRuleSet("MyRuleSet");

A RuleSet contains one or more Rules, and each Rule is made up of one or more RuleConditions. Each RuleCondition has a RuleEvaluator which is the code written by the developer. Each rule also has one or more RuleAction associated with it. When all the RuleConditions are met, the RuleAction is excuted.

To create a Rule:-

Rule myNewRule = myRuleSet.AddRule("NewRule");

To create a RuleCondition:-

RuleCondition myRuleCondition = new RuleCondition("MyConditoin", new MyCondtionCode());

The ‘MyConditionCode’ class extends the RuleEvaluator abstract class, guarenteeing the presence of an Evalute() method. This method must return a boolean value.

For example:-

class MyConditionCode : RuleEvaluator
{
    public MyConditionCode()
    {
        // constructor code
    }

    public override bool Evalute(DataSet dataSet)
    {
        if(<sometest>) {
            return True;
        }
        else
        {
            return False;
        }
    }
}

Add the RuleCondition to the Rule:-

myNewRule.AddRuleCondtion(myRuleCondition);

Alternatively:-

myRuleCondition.AddRuleConditino(new RuleCondition("MyCondition", new MyConditionCode()));

When the RuleEvaluator of each of the RuleConditions Associated with a Rule return True, then any Actions associated with the Rule will be fired.

Actions are created independently of a Rule, so that a single action can be reused across multipel Rules, An action consists of a Rule object, and an associated RuleEvaluator which is extended by the developer.

To create an Action:-

Action myAction = rmsx.CreateAction("MyAction", new MyActionCode());

The ‘MyActionCode’ class extends the ActionExecutor abstract class, guarenteeing the presence of an Execute() method.

For example:-

class MyActionCode: ActionExecutor
{

    public MyActionCode()
    {
        // constructor code
    }

    public void Execute(DataSet, dataset)
    {
        // do something here
    }
}

Add the Action to the Rule:-

myNewRule.AddAction(myAction);

Alternatively:-

myNewRule.AddAction(rmsx.CreateAction("MyAction", new MyActionCode()));

The data to be processed is a RuleSet is defined as ‘DataPoints’_, which are organized into ‘DataSets’_.

A DataPoint is a single named item of data that has an assocated DataPointSource. The DataPointSource is an abstract class that the developer extends, which guarentees teh presense of a GetValue() method. Think of the DataSet as an object with properties. Think of the DataSet as a collection of DataPoints, each of which is a key-value pair.

You submit a DataSet for execution by a RuleSet’s execution agent, as follows:-

myRuleSet.execute(myDataSet);

To create a DataSet:-

DataSet myDataSet = rmsx.CreateDataSet("<some unique name>");

To create a DataPoint, you first need to create a DataPointSource. This is done by creating a class that extends DataPointSource:-

private class ConstantDataPointSource : DataPointSource
{
    string retValue;

    public TestDataPointSource(string retValule)
    {
        this.retValue = retValue;
    }
    public override object GetValue()
    {
        return retValue;
    }
}

An instance of thi sclass will return the value that was passesd to the constructor whenever the GetValue() method is called.

Create the DataPoint as follows:-

DataPoint myDataPoint = new ConstantDataPointSource("Return this!");

Add the DataPoint to the DataSet:-

myDataSet.AddDataPoint("DataPoint1", myDataPoint);

Alternatively:-

myDataSet.AddDataPoint("DataPoint1", new ConstantDataPointSource("Return this!"));

Operation

The execution agent that underlies a RuleSet operates in its own thread. When a RuleSets Execute() method is first invoked, the execution agent is created. Thereafter, any further calls to Execute() will result in the DataSet simply being passed to the already running agent.

When a DataSet is ingested by the execution agent, all the Rules will be tested. Once a rule is tested, it will not be tested again, unless it is re-introduced. This happesn when a RuleCondition whin the rule has a delcared dependency on a DataPoint whos DataPointSource has been marked as stale. This is done on the client side, by calling SetStale() on a DataPointSource object. Any Rule that has a dependency on that DataPoint will be re-introduced into the queue of Rules to be tested.

This means that RuleCondition can be created that depends on the value of a variable or field that will change over time. When the rule is fist tested, perhpas the value is in a state that means that the Evaluate() method will return False. However, it may change later. The rule will not be tested again under normal circumstances. But if the variable or field changes values, simply call the SetStale() method on the DataPointSource object, and any and all Rules which have a RuleCondition that depends on its value will be re-tested. This means that the RuleCondition may now return True, and the associated ActionExecutor of Rule will be fired.

Tests

NUnit unit tests, as well as integration tests, are included in the project.

Deployment

Simply distribute the library with any application distribution.

License

This project is under the MIT License - see the License file for details.

EMSX API in Julia language

EMSX API in Julia Programming Language coming soon!

Resource

EMSX Route Status

Field Previous Value New Value Definition
EMSX_STATUS null SENT New route (placement) created.
EMSX_STATUS SENT SENT Field update on sent.
EMSX_STATUS SENT WORKING ACK received from the broker.
EMSX_STATUS WORKING PARTFILL First fill or multiple fills. (<100%)
EMSX_WORKING n <n and >0
EMSX_STATUS PARTFILL PARTFILL Middle fill or multiple fills. (<100%)
EMSX_WORKING n <n and >0
EMSX_STATUS PARTFILL FILLED Final fill or multiple fills. (100%)
EMSX_WORKING >0 0
EMSX_STATUS WORKING FILLED Full single fill.
EMSX_WORKING >0 0
EMSX_STATUS null FILLED Historic 100% fill on INIT_PAINT.
EMSX_STATUS null WORKING Working route (placement) on INIT_PAINT.
EMSX_STATUS null PARTFILL Part filled route (placement) on INIT_PAINT.
EMSX_STATUS null CXLREQ Cancel requested on route in INIT_PAINT.
EMSX_STATUS WORKING CXLREQ Cancel route request sent.
EMSX_STATUS CXLREQ WORKING Broker rejected cancel request.
EMSX_STATUS CXLREQ CXLPEN Broker sent ACK for cancel request.
EMSX_STATUS CXLPEN WORKING Broker rejected cancel request.
EMSX_STATUS CXLREQ CANCEL Broker cancelled route from request.
EMSX_STATUS CXLPEN CANCEL Broker cancelled route from request.
EMSX_STATUS PARTFILL CXLREQ Cancel requested on part filled route.
EMSX_STATUS CXLREQ PARTFILL Broker rejected cancel request.
EMSX_STATUS CXLPEN PARTFILL Broker rejected cancel request.
EMSX_STATUS WORKING CXLRPRQ Modify (cancel/replace) request sent to broker.
EMSX_STATUS CXLRPRQ REPPEN Broker sent ACK for modify request.
EMSX_STATUS REPPEN WORKING Broker rejected modify request on working route.
EMSX_BROKER_STATUS n/a CXRPRJ
EMSX_STATUS REPPEN WORKING Broker accepted and applied the modify request on working route. (placement)
EMSX_BROKER_STATUS n/a MODIFIED
EMSX_STATUS PARTFILL CXLRPRQ Modify (cancel/replace) request sent to broker.
EMSX_STATUS REPPEN PARTFILL Broker rejected modify request on part filled route. (placement)
EMSX_BROKER_STATUS n/a CXRPRJ
EMSX_STATUS REPPEN PARTFILL Broker accepted and applied the modify request on part filled route. (placement)
EMSX_BROKER_STATUS n/a MODIFIED
EMSX_STATUS SENT REJECTED Broker rejected the order from sent status.
EMSX_STATUS null REJECTED INIT_PAINT shows route (placement) rejected.
EMSX_STATUS null CANCEL INIT_PAINT shows route (placement) cancelled.
EMSX_STATUS CXLRPRQ WORKING Modify rejected from request.
EMSX_STATUS PARTFILL CANCEL Part filled route cancelled by broker.
EMSX_STATUS WORKING CANCEL Working route cancelled by broker.
EMSX_STATUS WORKING REJECTED Route rejected from working.

RuleMSX

The RuleMSX is a business rule management project using Bloomberg EMSX API for trading, Bloomberg Market Data for market data and rete algorithm for efficient business rule management.

RuleMSX provides the core functionality of a rule engine. It is designed to inter-operate with the EasyMSX and EasyMKT which use the Bloomberg API to access Bloomberg EMSX and market data. The RuleMSX is designed to use the rete algorithm to create an efficient business rule management system to work with Bloomberg EMSX API for automated trade execution for equities, futures, and options.

This functionality is provided in the shape of RuleSets, DataSets and Actions. By defining Rules and the conditions that must exist for these Rules to be triggered, the user can build complex reasoning based on the content of a DataSet, and how that DataSet changes over time. The Actions are the tasks performed as a result of a Rule being triggered.

.NET Reference for RuleMSX Project

Bloomberg API SDK in CSharp
(e.g. c:\blp\DAPI\APIv3\DotnetAPI\v3.8.9.2\lib\Bloomberglp.Blpapi.dll)

EasyMKT.dll
(e.g. c:\... \cs_EasyMKT-master\EasyMKT\bin\Debug\EasyMKT.dll)

EasyMSX.dll
(e.g. c:\... \cs_EasyMSX-master\EasyMSX\bin\Debug\EasyMSX.dll)

RuleMSX.dll
(e.g. c:\... \cs_RuleMSX-master\RuleMSX\bin\Debug\RuleMSX.dll)

ActionExecutors

An ActionExecutor is the client-side code that is run when an Action is executed. It is an abstract class that contains an Execute method that must be overridden.

When the RouteOrdertoBB action is executed, the Execute method of the instance of the abstract class would be called. This is the code that would create and send the route to the broker. Just as with the RuleCondition evaluators, the executors are passed the current dataset as a parameter when they are called.

DataPoints

A DataPoint is an object that represents a single piece of data. Fundamentally, it is a simple key-value pair. A DataPoint doesn’t have value itself, but rather has an underlying DataPointSource which is used to provide the value.

Examples of DataPoints would be OrderNumber, OrderStatus, OrderExchange, etc.

DataPointSource

A DataPointSource is a client-side code that provides a value for a named DataPoint. It is an abstract class with a GetValue method that must be overridden. It also provides a SetStale method that is used to indicate to the ExecutionAgent that the value must be re-examined. This will cause any WorkingRules for Rule that has a dependency on this DataPoint to be the queue for re-evaluation on the next cycle.

The DataPointSources for the above example DataPoints would access the EMSX data to return the correct EMSX_SEQUENCE and EMSX_STATUS, and perhaps use the reference data service to get the exchange code for the ticker on the order.

DataSets

DataSets are named entities that represent a collection of DataPoint objects. They are only used to organize DataPoints into logical groupings.

In our current example, we would create a DataSet object for each order. Once the DataSet object is defined, we can add it to the list of DataSets being run through a RuleSet by the ExecutionAgent.

ExecutionAgent

When the application has completed the configuration of all the main elements (Rules, RuleConditions, Evaluators, Action, Executors, and etc.), one or more RuleSets can be executed.

This involves taking a DataSet and asking the RuleSet to be executed against that DataSet: -

myRuleSet.Execute(dataSet_1);

If this is the first time this RuleSet has been executed, a new ExecutionAgent will be created for the RuleSet. If the RuleSet already has an ExecutionAgent, it will be reused. The specified DataSet is then passed to the RuleSet’s ExecutionAgent: -

executionAgent = new ExecutionAgent(myRuleSet, dataSet_1);

or

executionAgent.AddDataSet(dataSet_1);

Each ExecutionAgent has a DataSetQueue. Adding a DataSet to an ExecutionAgent simply adds the DataSet reference into the DataSetQueue. This is used to ensure that new DataSets are only ingested at the correct time, and not at the mid-point of a cycle.

A new ExecutionAgent will create a new internal thread that will operate a WorkingSetAgent. This WorkingSetAgent is the main loop that controls the execution of the rules and actions for a RuleSet, and it continues to run until stopped by an external request (a call to the stop() method).

Each cycle of the WorkingSetAgent begins with ingesting any DataSets in the ExecutionAgent’s DataSetQueue. This is the process of creating a WorkingRule for each Rule in the RuleSet and the specified DataSet.

To create a WorkingRule, a Rule and a DataSet are required. A process known as dereferencing takes place, which has two steps. The first step is to take each Action associated with the Rule and add the ActionExecutor references to the WorkingRule’s Executors collection.

The second part of the dereferencing process is to iterate each RuleCondition of the Rule, and add it’s RuleEvaluator to the Evaluators collection of the WorkingRule. Each RuleEvaluator has a collection of DataPoint names that it depends on. For each of these dependant data point names, we find the actual DataPoint in the DataSet that matches the name. The WorkingRule is then added to the AssociatedWorkingRules collection of the DataPoint’s DataPointSource object.

The reason for doing this is that when a DataPointSource’s value changes, its SetStale() method is (should be) fired. This forces each WorkingRule dependency of the DataPointSource to be added to the OpenSetQueue in the WorkingSetAgent for execution in the next cycle, unless the WorkingRule is already in the OpenSetQueue.

Following the ingestion process, the current OpenSetQueue becomes the OpenSet, and the OpenSetQueue is then reset to empty. The OpenSet is now iterated, and each WorkingRule in the queue is processed. Each Evaluator in the WorkingRule is fired, passing it the WorkingRule’s DataSet. If all Evaluators in the WorkingRule return true, then the action process begins. Each action associated with the WorkingRule is executed.

RETE Algorithm

The word rete is Latin for net or network. The rete algorithm is essentially a pattern matching algorithm.

The main objective behind rete algorithm for RuleMSX is to decouple the various trading or business rules from rule execution or executing sequences on a particular data set.

The data set here can be both trading data obtained from EMSX API, market data, or non-trading based proprietary data set.

The RuleMSX views each rule exists as a stand-alone rule that is either true or false at any given moment.

A pattern contains one or more rules. All the rules in a pattern must evaluate to true for the action attached to the pattern to be executed. In this case, the action itself is responsible for introducing the new rules to be checked and/or new patterns or patterns to be removed from the set.

Rules

Each Rule in a RuleSet is a named collection of RuleConditions and RuleActions. When all conditions in a Rule evaluate to True, the associated actions are executed.

Following the above example, and single rule within the AutoRoute ruleset would be RouteUStoBB, which would route any orders on the US exchange code to the broker known as BB. The other rule example could be RouteLNtoBMTB.

RuleActions

A Rule can have many RuleActions. Each RuleAction has a client-side component called an``ActionExecutor``. When a Rule evaluates to True, all associated RuleActions are executed.

For example, we would have a RuleAction called RouteOrdertoBB. which would be called as a consequence of the RouteUStoBB rules all evaluating to True.

RuleConditions

A RuleCondition is a named item within a Rule, which evaluates to either True or False. It does this through client-side code using a RuleEvaluator. A single Rule can have multiple RuleConditions, and they must all evaluate to True for the associated RuleActions to be executed.

For our RouteUStoBB example, we would have a condition called MustBeUSExchange that checked the order to ensure that it was for the US exchange. Another condition would be that the order must be in a NEW state, perhaps called CheckNEWState, to ensure that this rule is only triggered once.

RuleEvaluator

A RuleEvaluator is an abstract class that must be implemented in the client-side code. This abstract class has an Evaluate method that must be overridden. This method must return True or False. When the Evaluate method is called, it is passed the current DataSet as a parameter, to support the determination of the return value.

The abstract class also provides a mechanism for creating a dependency between a Rule and named DataPoints. To do this, we call the AddDependantDataPointName method of the class, as follows :-

this.AddDependantDataPointName("OrderStatus")

In this case, we are saying that this particular Rule uses the value of the OrderStatus DataPoint. The purpose of using this mechanism is to ensure that if the value of OrderStatus in any DataSet changes, any WorkingRules add queue to be re-tested in the next cycle. The change to the value of a DataPoint is indicated by calling the SetStale method (see DataPointSource).

RuleSets

RuleSets are named entities that represent a collection of RuleSet objects. This is only used to organize rules into logical groupings. A RuleSet is a named collection of Rules.

An example of a RuleSet would be to route new orders to a particular broker code, based on certain criteria, such as the exchange. We will call this the “AutoRoute” ruleset.

Once we have a RuleSet and a DataSet object, we can execute the RuleSet. RuleSets need one or more supporting DataSets to operate against.

Earlier Version

The initial approach to RuleMSX handled the rete in the following structure where each RuleSet consists of a single rule. Each rule consisted of child rules and rule evaluator.

_images/rete_orig.png

As part of the reiteration of RuleMSX, we have made the changes to reflect the rete algorithm in the following structure:

_images/rete_new.png

Full Code Samples

Full EasyMSX Code Samples

The link to the main EasyMSX Code Sample.

Full EMSX API Documentation

The link to the main EMSX API Documentation.

Full EMSX API Code Samples

The github link to the EMSX API Code Sample.

Full Bloomberg API Developer Guide

The link to the Open API Core Developer Guide.

License

Copyright (c) 2018

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.