Atp's external memory

LMAX API - a simple ticker app

In this article I run through how to create a simple ticker app off the LMAX API using PHP.

LMAX is the London Multi Asset Exchange. This is a low latency financial exchange which can be accessed directly by retail customers over the web using JSON or XML over a REST based interface.

The raw protocol not that pretty, so there are client libraries written in C# and Java. For fun and monitoring, I have written an unofficial PHP client library which I'm using here.

We want to produce a simple ticker that prints out the bid and ask prices and spread for GBP/USD.

This is a command line php program, so you'll need to install php5-cli and php-curl. 

sudo apt-get install php5-cli php-curl

Desired output;

20110804-17:33:05.036ms GBP/USD bids: 1.63004 1.62996 asks: 1.6301 1.63012 spread: 6.0000000000171E-5
20110804-17:33:05.576ms GBP/USD bids: 1.63004 1.62994 asks: 1.6301 1.63012 spread: 6.0000000000171E-5
20110804-17:33:07.198ms GBP/USD bids: 1.63011 1.62997 asks: 1.63012 1.63014 spread: 1.0000000000066E-5
20110804-17:33:07.739ms GBP/USD bids: 1.63011 1.62999 asks: 1.63012 1.63014 spread: 1.0000000000066E-5

1. Setup and Login

We first need to include the library, initialise it and login

$conn = new lmaxapi("");

if (!$conn->login("my username","my password","CFD_DEMO")) {
    print "Unable to login. Incorrect username or password?";

We first include the lmaxapi PHP script. We then create a new instance of the php api object. If you don't include it, the URL will default to the one shown - the test or demo site. You'll need to register on the website for a demo account and enter the username and password where indicated. Website:

We then login to the selected site. The login process will make several calls in addition to the login call. These calls retrieve data which we can use to search for the instruments or symbols we are interested in.

For example 

// will return an array of symbol groups; FX, RATES, INDICES 
// we can also get the symbols within a group
print implode(',',$conn->get_symbols_by_group("FX"));

Will return;


2. Searching for Instruments

To find  the information for a particular cross - in this case GBP/USD we can search using one of the search terms listed above from get_symbols_by_group().  This will return an array of instrument objects that match the search term, indexed by the unique instrument id. 

$fx_markets = $conn->search_instruments("GBP");
$myid = 0;

foreach ($fx_markets as $fx_id => $fx_cross) {
    if ($fx_cross->symbol == "GBP/USD") $myid = $fx_id;

if (0 == $myid) {
    print "Unable to find GBP/USD\n";

The instrument class is fairly comprehensive, containing details like the symbol, trading times, currency, minimum order quantities, underlying isin and a whole lot more. 

In the code snippet above, we iterate through the returned array and save the id of the instrument that matches GBP/USD. 

3. Subscribing to Market Data

A subscription to market data is a two stage process. First we need to subscribe to the order book event stream, and then set up a subscription to a particular orderbook. 

if ($conn->setup_subscription("order") === FALSE) {
    print "Unable to set up subscription to order book event stream\n";

$instrument_list = array( $myid );

if ($conn->subscribe_to_orderbook($instrument_list) === FALSE) {
    print "Failed to subscribe ".implode(",",$instrument_list)."\n";
    exit (0);

The subscribe_to_orderbook() function takes an array of instrument id's, so you can subscribe to several instruments at once. Once this has been done, we can start polling for events. 

4. Reading events and displaying the market data

We're now at the place where we can start reading events, and displaying them. 

while (1) {
    $result = $conn->get_events();
    if ($result !== FALSE) 
     foreach ($result as $update) {
    if ($update->type == "orderbook") {
        $bid = $update->bids[0]->price;
        $ask = $update->asks[0]->price;
        $spread = $ask - $bid;
        print date("Ymd-h:i:s",($update->exchange_time_stamp)/1000) . "." . 
             sprintf("%03.3dms",$update->exchange_time_stamp %1000) . 
          "  $update->instrument_id bids: " . $update->bids[0]->price ." ". 
             $update->bids[1]->price .
          "  asks: " . $update->asks[0]->price . " ". 
             $update->asks[1]->price . " spread: $spread\n"; 

 get_events() will return an array of events. We're interested in events of type "orderbook" so we select those. Orderbook events are another type of object. The price data is held as price and quantity for both bid and ask for 5 levels of depth (This is an exchange remember). To calculate the spread, we take the prices for the best bid and ask  in lines 6 and 7. 

After that its just a matter of converting the exchange time stamp which is held in milliseconds into a readable time, and printing out the data. I'm printing out prices to a depth of 2 plus the spread to give the examples at the top of the page. 

Thats it!

The full program and the library classes it depends on can be grabbed from here.

The library is currently not complete, but I'll be improving it over the next few weeks. As of the time of writing, place orders works, but cancelling is still in progess. The library will handle orderbook and account state events, but does not maintain persistent account state. It does not handle position events yet. Use with caution. 

Next week, placing orders. 

Some small print;

  1. LMAX are my employers. This is something I've done mostly on my own time, as part of an educational exercise, and to help me write monitoring software. 

  2. The PHP API Client Library is not a supported or official client library. The supported API Clients are Java and C#. They're faster and better than this one and have been designed by people who know what they're doing.  They can be found on the LMAX website -

  3. The library and examples here are for learning/demonstration purposes. There is no warranty/fitness for purpose. There are likely to be bugs in it, and if you use it for trading, then you do so at your own risk. The library classes are changing rapidly at the moment as I fill out the functionality. You've been warned.   

  4. Nothing in this article should be constituted as being an inducement to trade. If you want to find out about the benefits/risks of trading on an exchange I suggest you get independent advice. This is a technical howto using a demo site. 

    Dammit Jim, I'm a doctor not a lawyer.

Written by atp

Wednesday 03 August 2011 at 1:04 pm

Posted in Default

Leave a Reply