Atp's external memory

php api revisited.

In 2011 I put out an example php class that could be used to talk to the LMAX API protocol. It was incomplete and for illustrative purposes only. It remains that way. Over the years however there have been some improvements and it can now be used for placing, closing and cancelling orders. I've made the latest version available on github, just in case the handful of people who have contacted me over the years about it find it useful to have the latest version. 

Here is the lmax-php-api github repo. As well as the original ticker app, there's a small example web app that shows how to get and handle position state events, as well as the example that forms the rest of the post. 

Its not under active development. Its not supported, and should not be used for real trading - its purely an educational tool. However if you send me a patch I'll probably add it in.

I promised placing orders "next week" about 3 years ago. Here's the brief run down. The code is on github under examples/place_close/

There are a subset of order types and strategies supported. 

class order_type
   const market= 0;
   const limit = 1;
   const market_stop = 2;
class fill_strategy
   const fill_or_kill = 0;
   const immediate_or_cancel = 1;
   const good_for_day = 2;
   const good_til_cancel = 3;
// aliases
   const FoK = 0;
   const IoC = 1;
   const GFD = 2;
   const GTC = 3;

The market stop has been retired, and is no longer available on the protocol, so I should really remove it. 

As a reminder the basic steps to use the php class are;


// instantiate, login, housekeeping. 
$conn = new lmaxapi();

if ($conn->login($username,$password,$productType="CFD_DEMO") == FALSE) {
    bailout("Error logging in\n");


At this point the housekeeping is done.  get_username_password() is a helper function that can also be found under the src directory. Look in the lmaxapi.php for the alternatives for the other parameters. For example productType="CFD_LIVE".

The call to get_longpollkey() is needed, but the value is cached inside the instance and can be safely ignored at this level.

We can now search for our instrument id for the cross we wish to place an order on. 

$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) {
  bailout("Unable to find GBP/USD\n");

The search term in search_instruments generated a bit of discussion. In previous versions of the API I was searching by assetClass. It turns out that its not needed. You're pretty safe to search by a currency. There are other search terms that also will work - for example "INDEX", "CURRENCY", "GOLD", "STREET", "TECH", "UK". Run test.php and look at the search terms returned in the debug information for the login() call for more detail. 

Now, armed with our instrument id, we can place a market order. We'll use immediate or cancel as the fill strategy, and we'll go large to buy with 1 contract.

// place a market order
$result = $conn->place_order($myid,order_type::market,fill_strategy::IoC,1);
if (!$result) {
   bailout("Failed to place immediate or cancel market buy order on $myid for 1 contract\n");
} else {
   print "placed immediate or cancel market buy order on $myid for quantity 1, order id $result\n";


Now we close out to even our position back to zero. 

// close out the market order
$result = $conn->close_order($myid,$market_order_id,-1);
if (!$result) {
   bailout( "Failed to close out market buy order on $myid for 1 contract\n");
} else {
   print "Closed market order for quantity 1, order id $result\n";

Last but not least, we log out. As we're responsible citizens. 

// logout 
$result = $conn->logout();

That sequence looks like this;

atp@bar:~/lmaxapi/git_repo/lmax-php-api/examples/place_close$ php place_close.php
username: mylogin
password: ********
placed immediate or cancel  market buy order on 4002 for quantity 1, 
       order id 7215601888287395946
Closed market order on 4002 for quantity 1, order id 7215601888287395949
logged out 

And generates a couple of lines in our activity log like this;

14/05/2014 14:23:21 Your position in GBP/USD was closed.
14/05/2014 14:23:21 Your order to close 1 contracts in GBP/USD was matched.
                    Filled qty 1, closed qty 1.
14/05/2014 14:23:21 Your market order to buy 1 contracts in GBP/USD was matched.
                    Filled qty 1, opened qty 1, avg open price 1.6758.

And we've probably triggered some sort of "flashing the market" alarm somewhere in the bowels of lmax risk department by placing and immediately closing like that. Or painting the tape, or dancing the jig. Market surveillance are a surprisingly colourful lot when it comes to language. 

The example above is very basic. At minimum we would want to register subscriptions to different event types so we get the position state events and account state events back. At the moment we're ignoring everything that the API may want to send back to us about how we're doing and whether the orders were successfully executed or not. 

So there we have it. Another broken/long overdue promise remedied and new years resolution checked off. Only a few months late, but then thats par for the course.

Written by atp

Wednesday 14 May 2014 at 2:42 pm

Posted in Default, Linux

Leave a Reply