Q For Gods Edition 26
Q For Gods Edition 26
Michael Reynolds, who joined First Derivatives in 2013, works as a kdb+ consultant for
one of the largest investment banks in the world. As part of his daily job, Michael is
responsible for maintaining kdb+ databases as well as C# APIs and plug-ins.
© 2015 First Derivatives plc. All rights reserved. No part of this material may be copied, photocopied
or duplicated in any form by any means or redistributed without the prior written consent of First
Derivatives. All third party trademarks are owned by their respective owners and are used with
permission. First Derivatives and its affiliates do not recommend or make any representation as to
possible benefits from any securities or investments, or third-party products or services. Investors
should undertake their own due diligence regarding securities and investment practices. This
material may contain forward-looking statements regarding First Derivatives and its affiliates that
are based on the current beliefs and expectations of management, are subject to significant risks
and uncertainties, and which may differ from actual results. All data is as of June 11, 2015. First
Derivatives disclaims any duty to update this information.
First Derivatives q for Gods Whitepaper
TABLE OF CONTENTS
1 Introduction .................................................................................................................... 3
2 Connecting kdb+ and C# ................................................................................................. 4
2.1 C# Socket to enable client connection ....................................................................... 4
2.3 Validation with passwords .......................................................................................... 6
3 Queries .......................................................................................................................... 10
3.1 Simple queries .......................................................................................................... 10
3.2 Building dynamic queries .......................................................................................... 11
4 Managing Connections ................................................................................................. 14
5 Running Analytics .......................................................................................................... 17
6 Conclusion ..................................................................................................................... 23
1 INTRODUCTION
Over the course of fifteen years, C# has become one of the most commonly utilised programming
languages in the world. It has been used in applications ranging from computer games to medical
systems to storage systems.
In this paper, we will explain the basics of using C# to open connections to kdb+ processes running
on remote servers as well as setting up a basic API that will allow for authentication, error recovery
and basic queries through an interface. In this case, all C# code will be pointing to the same kdb+
process.
C# is heavily integrated into Windows software. It allows for the implementation of the .NET
environment into applications and can be utilised in the creation of websites using PHP and ASP.NET
as well as stand-alone Windows applications.
The paper makes use of the standard c.cs file offered by Kx to enable connections to C#. This can be
found here: http://code.kx.com/wsvn/code/kx/kdb+/c/c.cs
It is important to note that this paper does not aim to provide a full C# library, but instead give
guidance on how to quickly and easily allow a C# application to connect to and run queries against a
kdb+ process.
All kdb+ code will be highlighted in grey boxes and C# code in white.
The C# source code for this paper can be found on the First Derivatives GitHub page:
https://github.com/FirstDerivativesplc/qForGodsEdition26
To connect from C# to a running kdb+ process, it is first necessary to import the c.cs file mentioned
in the introduction. While it is possible to construct a bespoke plugin for use between kdb+ and C#,
and may be required depending on the requirements of the project, for basic connections and
queries, the default Kx plug-in will be satisfactory. This must then be called by referencing the
namespace provided (in this case, it is kx). After importing c.cs into a C# project, it can then be
called via the using directive:
using kx;
This will allow all objects, classes and methods within the kx namespace provided by the c.cs file to
be used throughout the project, allowing connections to the kdb+ process via TCP network sockets.
It will also permit querying and updates to be performed on the same kdb+ process.
To open a connection between C# and the kdb+ process, an object of class ‘c’ needs to be called and
instantiated. This is a Kx provided class that will act as an interface between kdb+ and C#. This will be
used in a method called ‘OpenConnection’. In the below example, a server and process will be
hardcoded to private variables though these could be modified to accept values from a configuration
file. The methods have also been set up to accept a username and password if desired, this will be
described in more detail later.
The above code shows a simple, generic connection method which can be called when starting a C#
application to create a connection to a running q process. We return the c object in this case as we
will need it in the main method to execute queries.
Note that a lot of the method consists of error catching. This is to ensure that the application can
recover in the event of the connection not being made successfully or another, unexpected error
occurring. In this example, we have merely outputted a message to the Visual Studio console to say
that we have an error but later, we will see how this error handling can be used to provide error
recovery or business continuity.
This method will be utilised as part of a ConnectionPool which will be used to monitor and assign
connections to users rather than having a haphazard collection of connections with each process.
This will reduce the load and traffic on the kdb+ instance as it cuts down on the number of handles
that could be attempting to query simultaneously.
This is an example of the OpenConnection method in operation (via the ConnectionPool) with a
simple click event for a button. It will check if the method has returned a c object for further use
and, if not, it will throw an error.
Figure 1
Figure 2
As previously mentioned, a bonus of using kdb+ as the back end for a C# or Java application is the
code on the server side is independent of both languages. This greatly eases the development
required to make such a service available and enables platforms operating either language to access
the same services. This also enables developers to take advantage of kdb+ as a language and move
much of the processing to the server side. An example of this is validation to prevent users from
connecting to the server without permission.
In the below process, we have created a simple table with a user and their password. The password
could be further encrypted using a hashing algorithm such as MD5 for extra security (this will not be
shown in this whitepaper but is highly recommended).
q)
user_table:([users:`mreynolds`user1`user2]password:("password";"passwor
d2";"password3"))
q)user_table
users | password
---------| -----------
mreynolds| "password"
user1 | "password2"
user2 | "password3"
This involves changing the c.cs file provided by Kx as this is not set up to accept customised
usernames (it instead takes the username stored in Environment.UserName) or any passwords at
all. We will also need to modify the OpenConnection method and define .z.pw.
This works by opening a byte stream to the kdb+ process and then feeding user input as bytes to the
handle.
A byte stream is an open connection that sends a collection of bytes from sender to receiver in a
bidirectional format. This connection is reliable and the use of bytes allows the C# query to be sent
to a kdb+ process and the kdb+ response to be returned and deserialised.
As defined currently, along with the host (h) and port (p), it will take a further parameter for the
username (u), but none for the password. To make it accept passwords as well, we need to modify
the c constructor in c.cs file to the following:
We have specified a new variable ‘pw’ which is now being read into the byte stream along with ‘u’. In
particular, it is ‘w(u + ":" + pw + "\x3")’ that will be interpreted by .z.pw or the -u argument
as a username and password. We can use a simple definition for .z.pw to query the users table
whenever a connection is made through C#.
This will return 0b if the user does not have permission to access the process. Within C#, this will
throw a KException with the message “access”. This can be used to track if the user has been
refused access in the C# API.
For more detailed information on validation and authentication, see Tom Martin’s whitepaper
‘Permissions with kdb+’ (http://firstderivatives.com/downloads/q_for_Gods_July_2013.pdf )
3 QUERIES
With a connection established between the C# application and the kdb+ process, it is now possible
to send queries from the front-end and receive data from the back-end. This is done through the
use of the c object which is created after opening the connection. This is why it is important to keep
track of the object in methods such as OpenConnection.
The method used to perform operations over the kdb+ connection is simply called ‘k’ and is called as
a child method of the c class. The same method is used to query, update and delete data from kdb+
and accepts a string as a parameter.
This is then fed into a method called ‘c’ which breaks it into bytes and passes it into kdb+. The result
is then received by the C# client as a stream of bytes which is deserialised by the c method into C#
compatible types. The result itself is a two dimensional array when used with select or a one
dimensional array when used with exec. This can then be cast to the type c.Flip, which mimics a
table with similar functionality and methods available.
In the below example, an app has been written with a hardcoded query to a simple trade table. This
will update the table in the application by use of a DataGridView every time the update button is
clicked. To push the data to a DataGridView, it first needs two loops to copy the data into the
correct formats (one loop for rows and one loop for columns).
QueryView.Columns.Clear();
//Clear columns first to allow clean population of table
foreach (string colName in table.getColumns())
{
QueryView.Columns.Add(colName, colName); //Add the columns to the Queryview
}
QueryView.Rows.Add(table.getNoRow());
Figure 5
It should be noted that while it is possible to build a dynamic query as shown in the below example,
it is vulnerable to injection attacks. Production systems should be more robust in dealing with these
kinds of attacks, though this is beyond the scope of this whitepaper.
Below is an example of a class and GUI that has been constructed using simple dropdowns and text
boxes yet creates a flexible and powerful editor we can use to query the trade table:
Figure 6
To carry this out, we use a new method called BuildQuery (presented on the next page) and replace
the hardcoded query with:
conn.k(BuildQuery());
The BuildQuery method takes the inputs of each textbox, checkbox and combo box seen above in
Figure 6 and combines them to build a query to send to kdb+. This allows those without much
knowledge of kdb+ queries or optimisation of queries to view data stored on kdb+ processes without
exposing them to the q-sql language.
This is the BuildQuery method which takes all the available inputs and creates a query string from
them:
if (checkBox1.Checked)
{
check1 = " not ";
}
if (checkBox2.Checked)
{
check2 = " not ";
}
if (checkBox3.Checked)
{
check3 = " not ";
}
queryString.Append(tableComboBox.SelectedItem);
if (argComboBox1.SelectedItem != null)
{
queryString.Append(" where (" + check1 + argComboBox1.SelectedItem +
signComboBox1.SelectedItem + argInput1.Text + ")");
//Append the above strings and the text boxes of the UI into a single string
query that can be sent to the kdb+ process
}
return queryString.ToString();
}
4 MANAGING CONNECTIONS
On the client side, we will utilize the KException and use this to fail over to a secondary connection
if a query cannot go through successfully. This method will then attempt to run the query again
using the backup connection and publish the data as normal. This can ensure continuity of business
in the event that the kdb+ process is rendered unable to respond.
conn = ConnectionPool.GetConnection();
c.Flip table = GetData(queryBox.Text);
PublishQuery(table);
}
catch (Exception ee)
{
errorLabel.Text = "ERROR - unable to connect: " + ee.Message;
}
}
else
{
errorLabel.Text = "ERROR: " + ex.Message;
}
}
In the above example, we are capturing any exception that is thrown with the ‘read’ error. This
means the GUI was unable to successfully send the query to the kdb+ back-end. To reconnect to the
secondary connection, we call the ConnectionPool.GetConnection method again and re-send the
query. The PublishQuery method simply publishes the result of the query into a DataGridView as
before. On the kdb+ side we have two processes running the same functions and trade table but on
different ports.
Figure 9
We can expand this functionality to take account of a process being busy, such as when it is
processing a large query or hanging for another reason. In this case, we have artificially increased
the amount of time it will take the query to run to test the below code. Timeout errors are supplied
on the kdb+ end and will return a stop error, which we can catch.
q)\T 1
The catch statement can then be modified to trap the stop error and rerun the query on another
process:
This is utilised by a method within the Connection pool called GetSecondaryConnection which will use
a predefined port and the same host to open a new connection. This will add the connection to the
same pool, preventing the application from exceeding its maximum number of connections;
Figure 10
5 RUNNING ANALYTICS
Until now, we’ve been using kdb+ to deliver raw trade data to our C# front-end. While viewing raw
data can be useful, many users will want to see an enriched view of each trade. We can take the
example from Section 3 and expand it so that each row in the DataGridView will be selectable,
allowing us to drill into each trade to provide further analysis on the product being traded. The
analytics will include:
We will also plot these on a line graph to allow users to better identify patterns and outliers
throughout the day.
To calculate these, we will create a new function called analyseData on the kdb+ side which will
then be called from C#.
This will calculate the min,max,average and vwap prices for a given symbol in 15-minute buckets.
We will also write a function called getSummary which provides the overall min,max,average and
vwap for the entire day. Note that we must unkey the table before returning it to C# as c.Flip will
treat this keyed table (type 99) as a dictionary and cause an error.
If we perform these on the table trade for one symbol (`FDP.O) in the kdb+ session, we can see the
results:
q)4#details
sym | fullName
------| -----------------------
FDP.O | "First Derivatives PLC"
BMW.O | "BMW AG"
MSFT.O| "Microsoft Corporation"
INTC.O| "Intel Corp"
q)getSummary[`FDP.O]
sym minPrice maxPrice avgPrice vwap total
--------------------------------------------
FDP.O 1.021 1.109 1.064 1.064 5082
q)10#analyseData[`FDP.O]
minute minPrice maxPrice vwapPrice avgPrice totalTransactions
-------------------------------------------------------------
00:00 1.022 1.108 1.063 1.063 93
00:15 1.022 1.108 1.063 1.064 114
00:30 1.022 1.108 1.061 1.061 132
00:45 1.022 1.108 1.065 1.066 139
01:00 1.021 1.108 1.066 1.068 143
01:15 1.021 1.108 1.069 1.069 126
01:30 1.021 1.108 1.061 1.061 137
01:45 1.022 1.108 1.063 1.062 144
02:00 1.022 1.108 1.066 1.066 130
02:15 1.022 1.108 1.067 1.067 129
The methods to pull this data into a graph in the case of analyseData and text boxes in the case
of getSummary are simple to implement, involving query calls to kdb+ to collect the data and then
using loops to process it.
symLabel.Text = symbol;
this.conn = conn;
c.Flip details = GetData("select details from details where sym=`" + symbol);
compLabel.Text = c.at(details.y[0], 0).ToString();
//This will execute the above functions using the symbol taken from the UI
details = GetData("getSummary[`" + symbol + "]");
GetDaily(details);
This calls the methods GetData (which was used in the previous section), GetDaily, SetAxis and
PopulateChart. Note that the form takes as arguments a string to represent the symbol and the
connection object. This is to avoid opening up new connections with each selection. These values are
supplied from the parent form in a CellEvent for the DataGrid, making it selectable:
The GetDaily method utilises the getSummary function on our kdb+ process to query the table and
return values for that single symbol over the entire day. We then use these to populate the boxes on
the left hand to provide a quick visual summary of the data:
minBox.Text = min.ToString("#.#####");
maxBox.Text = max.ToString("#.#####");
avgBox.Text = dAvg.ToString("#.#####");
dailyVwap.Text = dVwap.ToString("#.#####");
transNoBox.Text = transNo.ToString();
}
The SetAxis method is optional but provides a more pronounced set of peaks and troughs in the
data by setting the maximum and minimum values of the Y-axis depending on the data itself. This is
done by using a simple loop to find the maximum returned value and minimum returned value from
the subset of data. This does not include maximum or minimum prices over the period as this would
reduce the sensitivity of the chart.
}
reportChart.ChartAreas[0].AxisY.Minimum = min - 0.0025; //Add margin
reportChart.ChartAreas[0].AxisY.Maximum = max + 0.0025; //Add Margin
}
Finally, we need to plot the graph itself. This is done with a DataVisualization.Charting.Chart
object in the GUI, with the co-ordinates in each series being added via a loop:
As clients may also wish to see the data in its grid form, a grid is populated along with the chart with
a button to switch between the two views whenever required:
Figure 11
Figure 12
Figure 13
Though this has only been set up to query the trade table as it currently exists, it would not be
difficult to implement a timer to periodically query kdb+ (every minute, for example) and retain up
to date figures and charts. By the same measure, adding the ability to compare different symbols or
different time frames would not take much more effort, nor would giving the user the ability to
choose what period time they analyse. Furthermore, websockets could be used to deliver streaming
data from the kdb+ backend to the C# GUI.
6 CONCLUSION
Despite its popularity and the potential opportunities for development, combining C# and kdb+
remains a relatively unexploited area. We have demonstrated a few simple processes and
applications which could be useful in developing a trading application using kdb+ and C#.
The applications developed for this example are simple in nature and in implementation but the
potential for creating more sophisticated and powerful tools exists. We have shown very limited
analytical and GUI elements but these could be expanded upon by the use of Cascading Style Sheets
and more extensive configuration.
The Delta Dashboards component of the Delta Suite from First Derivatives is an example of an out of
the box front end allowing end users to analyse their kdb+ data, and data from other sources,
through an easy to use and customisable visualisation layer. For more information on Delta
Dashboards:
http://www.firstderivatives.com/downloads/Delta_Dashboards_Factsheet.pdf
The paper has also demonstrated the potential versatility of kdb+, not just in the banking and
financial sectors but in all sectors where C# is popular and a database is required for back-end data
storage and management. These examples could be pushed out to analytical or performance-based
sectors or markets inexperienced in kdb+ but requiring tools to help utilise the rapidly growing big
data environment.
All examples of kdb+ were run using version 3.2 (2015.01.14). All tests of C# were run using .NET
version 4.0. The example applications were built with Visual Studio 2010. The C# source code for this
paper can be found on the First Derivatives GitHub page:
https://github.com/FirstDerivativesplc/qForGodsEdition26