Go Back   Developer Program Forum > Sports API > Other

Other Other programming languages

Thread Closed
 
Thread Tools Display Modes
  #1  
Old 03-23-2012, 10:14 AM
AlgoTrader AlgoTrader is offline
Senior Member
 
Join Date: Mar 2012
Posts: 513
Default Node.js Betfair Sports API work started

I was developping C++ Betfair applications for some time and found it too effort consuming to do the things done right.

Now I am switching to Node.js. Node.js is a platform built on Chrome's JavaScript runtime for easily building fast, scalable network applications. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices.

After just several days work with Node, I have a demo that logins to BF. Code is fantastic, performance is also great. If you already have node.js installed you can see it.

Quote:
npm install betfair-sports-api

and

node ./node_modules/betfair-sports-api/test/login.js
The result is
Quote:
login Request:
{ locationId: '0',
password: 'password',
productId: '82',
username: 'user',
vendorSoftwareId: '0' }

XML request:
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/"><soap:Body><login xmlns="http://www.betfair.com/publicapi/v3/BFGlobalService/"><request><locationId>0</locationId><password>password</password><productId>82</productId><username>user</username><vendorSoftwareId>0</vendorSoftwareId></request></login></soap:Body></soap:Envelope>

XML response:
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:n2="http://www.betfair.com/publicapi/types/global/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><n:loginResponse xmlns:n="http://www.betfair.com/publicapi/v3/BFGlobalService/"><n:Result xsi:type="n2:LoginResp"><header xsi:type="n2:APIResponseHeader"><errorCode xsi:type="n2:APIErrorEnum">OK</errorCode><minorErrorCode xsi:nil="1"></minorErrorCode><sessionToken xsi:nil="1"></sessionToken><timestamp xsi:type="xsd:dateTime">2012-03-23T09:55:00.422Z</timestamp></header><currency xsi:nil="1"></currency><errorCode xsi:type="n2:LoginErrorEnum">INVALID_USERNAME_OR_P ASSWORD</errorCode><minorErrorCode xsi:nil="1"></minorErrorCode><validUntil xsi:type="xsd:dateTime">0001-01-01T00:00:00.000Z</validUntil></n:Result></n:loginResponse></soap:Body></soap:Envelope>

login Response:
{ header:
{ errorCode: 'OK',
minorErrorCode: '',
sessionToken: '',
timestamp: Fri, 23 Mar 2012 09:55:00 GMT },
currency: '',
errorCode: 'INVALID_USERNAME_OR_PASSWORD',
minorErrorCode: '',
validUntil: Mon, 01 Jan 1 00:00:00 GMT }
The code is really beatiful:
Code:
var betfairUser = "user";
var betfairPassword = "password";

var betfairGlobalService = require("../lib/betfair_global_service.js");

var loginRequest = {
    locationId : "0",
    password : betfairPassword,
    productId : "82",
    username : betfairUser,
    vendorSoftwareId : "0"
};
console.log("login Request:");
console.log(loginRequest);

var login = betfairGlobalService.login(loginRequest);
login.execute(function(resp) {
    console.log("login Response:");
    console.log(resp);
});
This is only an early demo, I think some real work would need a week or two to develop. Although, porting from C++ is the real pleasure.

Why I do this? There are following reason
- I need simple, yet high performance platform for making Betfair apps
- Language should be easy, JavaScript (if properly used), is 3-5 times faster in development than C++ and 2-3 times faster than .Net/Java
- API should operate with dozens of invocations per second easily, node can handle it

Other scripting languages such as perl and php provide syncronous APIs. Node js API is asyncronous

Last edited by AlgoTrader; 03-28-2012 at 02:02 PM
  #2  
Old 03-27-2012, 09:50 AM
AlgoTrader AlgoTrader is offline
Senior Member
 
Join Date: Mar 2012
Posts: 513
Default

Work is in progress and now I have the first complete bot written in Node.js. The bot logins to Betfair, sends a number of parallel keepAlive requests and logs out.

module betfair-sports-api is in github https://github.com/BetfairTrader/betfair-sports-api. It is also avalable using "npm install betfair-sports-api".

Quote:
zemlyanov@linux-sgvr:~/tmp/node_modules/betfair-sports-api/test> node session.js
Logging in to Betfair...
Session token is: 6MDMeZj9e1f2NQd+Aplb6dkyGfEwAg53AN6u3qRzDxE=
Logged in OK
Send 30 keepAlive requests
keepAlive result: OK duration 0.333
keepAlive result: OK duration 0.35
keepAlive result: OK duration 0.381
keepAlive result: OK duration 0.362
keepAlive result: OK duration 0.109
keepAlive result: OK duration 0.211
keepAlive result: OK duration 0.295
keepAlive result: OK duration 0.379
keepAlive result: OK duration 0.416
keepAlive result: OK duration 0.433
keepAlive result: OK duration 0.447
keepAlive result: OK duration 0.462
keepAlive result: OK duration 0.465
keepAlive result: OK duration 0.501
keepAlive result: OK duration 0.516
keepAlive result: OK duration 0.529
keepAlive result: OK duration 0.546
keepAlive result: OK duration 0.549
keepAlive result: OK duration 0.584
keepAlive result: OK duration 0.6
keepAlive result: OK duration 0.611
keepAlive result: OK duration 0.629
keepAlive result: OK duration 0.632
keepAlive result: OK duration 0.666
keepAlive result: OK duration 0.683
keepAlive result: OK duration 0.694
keepAlive result: OK duration 0.712
keepAlive result: OK duration 0.715
keepAlive result: OK duration 0.748
keepAlive result: OK duration 0.766
Logging out...
Logged out OK
In this bot, there were 30 keepAlive invocations issued at the same time using pool of 5 HTTPS connections. Please note that HTTPS connection is expensive, so it is better to keep connections open and reuse them for following invocations. All 30 requests were done in 0.766 seconds.

the code is
Code:
var https = require('https');
var fs = require('fs');
var util = require('util');
var async = require('async')

var account = JSON.parse(fs.readFileSync('../account.json'));

var keepAliveRequests = 30;
https.globalAgent.maxSockets = 5;

account.login = account.login || 'nobody';
account.password = account.password || 'password';

var betfairSport = require('../index.js');
var session = betfairSport.openSession(account.login, account.password);

async.series({
    // Login to Betfair
    login : function(cb) {
        console.log('Logging in to Betfair...');
        session.open(function onLoginFinished(err, res) {
            if (err) {
                console.log('Login error', err);
                process.exit(-1);
            }
            console.log('Logged in OK');
            cb(null, "OK");
        });
    },

    // Send a number of keepAlive requests
    sendKeepAlives : function(cb) {
        console.log('Send %s keepAlive requests', keepAliveRequests);

        var keepAlives = [];
        for ( var cnt = 0; cnt < keepAliveRequests; ++cnt)
            keepAlives.push(session.keepAlive());

        async.forEach(keepAlives, function(inv, cb) {
            inv.execute(cb);
        }, function() {
            for ( var cnt = 0; cnt < keepAliveRequests; ++cnt)
                console.log("keepAlive result:",
                        keepAlives[cnt].isSuccess() ? 'OK' : 'Fail',
                        "duration", keepAlives[cnt].duration()/1000);
            cb(null, "OK");
        });
    },

    // Logout from Betfair
    logout : function(cb) {
        console.log('Logging out...');
        session.close(function(err, res) {
            console.log('Logged out OK');
        });
        cb(null, "OK");
    }
});
Looks quite good results, it seems node.js is the right tool for high-end Betfair apps

Last edited by AlgoTrader; 03-28-2012 at 02:03 PM
  #3  
Old 03-28-2012, 08:57 AM
AlgoTrader AlgoTrader is offline
Senior Member
 
Join Date: Mar 2012
Posts: 513
Default

I have fast pace progress with the betfair-sports-api for node.js. Today I added getAllMarkets support and added test app that gets current tennis markets. Results are good, code is also short, easy to develop and debug.

The source code of the test (64 lines of JavaScript code) is https://github.com/BetfairTrader/bet...all_markets.js

The execution result is following:

Quote:
/github/betfair-sports-api/test> node get_all_markets.js
Logging in to Betfair...
Session token is: [skipped]
Logged in OK
Get available tennis matches
there are 182 markets
action: getAllMarkets error: null duration: 0.364
Sony Ericsson Open 2012\Womens Tournament\Quarter Final Matches\Azarenka v Bartoli
Sony Ericsson Open 2012\Womens Tournament\Quarter Final Matches\V Williams v A Radwanska
Sony Ericsson Open 2012\Mens Doubles\Marrero/Verdasco v Paes/Stepanek
Sony Ericsson Open 2012\Mens Doubles\Kubot/Tipsarevic v Mirnyi/Nestor
Sony Ericsson Open 2012\Womens Doubles\Medina Garrigues/Pennet v King/Niculescu
Sony Ericsson Open 2012\Mens Tournament\Quarter Final Matches\Tipsarevic v A Murray
Sony Ericsson Open 2012\Womens Doubles\Pavlyuchenkova/Safarova v Kirilenko/Petrova
Sony Ericsson Open 2012\Womens Doubles\Errani/Vinci v Dulko/Suarez
Sony Ericsson Open 2012\Mens Tournament\Quarter Final Matches\Tsonga v Nadal
Sony Ericsson Open 2012\Mens Tournament\Quarter Final Matches\Monaco v Fish
Sony Ericsson Open 2012\Mens Tournament\Quarter Final Matches\Djokovic v Ferrer
Sony Ericsson Open 2012\Womens Tournament\Semi Final Matches\Wozniacki v Sharapova
Logging out...
Logged out OK
/github/betfair-sports-api/test>
I think JavaScript bot development time is some 5-6 times faster than C++ that I used before.

Last edited by AlgoTrader; 03-28-2012 at 02:03 PM
  #4  
Old 03-28-2012, 11:43 AM
AlgoTrader AlgoTrader is offline
Senior Member
 
Join Date: Mar 2012
Posts: 513
Default

Added support of getMarket.
New test bot: login, getAllMarkets, getMarket, logout invocations

Code:
github/betfair-sports-api/test> node get_market.js 
Logging in to Betfair...
Session token is: [skipped]
Logged in OK
Get available tennis matches
there are 195 markets
action: getAllMarkets error: null duration: 0.421
Call getMarket for marketId="105266777"
action: getMarket error: null duration: 0.28
marketId: 105266777
market name: Match Odds
market time: Wed, 28 Mar 2012 23:00:00 GMT
	playerOneId: 2263640
	playerOneName: Victoria Azarenka
	playerTwoId: 2250849
	playerTwoName: Marion Bartoli
Logging out...
Logged out OK
/github/betfair-sports-api/test>
the bot source file is there:
https://github.com/BetfairTrader/bet.../get_market.js

Adding new invocations is really a matter of minutes (this time I fixed bug in decoding arrays as I first time got arrays in response)

Last edited by AlgoTrader; 03-28-2012 at 02:04 PM
  #5  
Old 03-28-2012, 02:02 PM
AlgoTrader AlgoTrader is offline
Senior Member
 
Join Date: Mar 2012
Posts: 513
Default

Added getMarketPricesCompressed invocation

Code:
Logging in to Betfair...
Session token is: [skipped]
Logged in OK
Get available tennis matches
there are 195 markets
action: getAllMarkets error: null duration: 0.424
Call getMarketPricesCompressed for marketId="105266777"
action: getMarketPricesCompressed error: null duration: 0.269
marketId: 105266777
currency: USD
marketStatus: ACTIVE
inPlayDelay: 0
player 0
	selectionId: 2263640
	lastPriceMatched: 1.21
	totalMatched: 100982.04
	 back price:1.21 amount:40701.11
	 back price:1.2 amount:17650.14
	 back price:1.19 amount:14367.75
	 lay price:1.22 amount:5943.07
	 lay price:1.23 amount:11343.05
	 lay price:1.24 amount:13343.56
player 1
	selectionId: 2250849
	lastPriceMatched: 5.6
	totalMatched: 3636.31
	 back price:5.6 amount:713.96
	 back price:5.5 amount:257.58
	 back price:5.4 amount:472.17
	 lay price:5.7 amount:1667.07
	 lay price:5.8 amount:74.46
	 lay price:5.9 amount:780.83
Logging out...
Logged out OK
https://github.com/BetfairTrader/bet..._compressed.js

The most difficult API call to implement. The "compressed" data is really aweful:

Quote:
marketPrices: '105266777~USD~ACTIVE~0~1~~true~5.0~1332943231891~ ~N:2263640~0~100997.96~1.21~~~false~~~~|1.21~40742 .5~L~1~1.2~17888.85~L~2~1.19~14116.48~L~3~|1.22~57 63.64~B~1~1.23~11176.89~B~2~1.24~13343.56~B~3~:225 0849~1~3922.77~5.6~~~false~~~~|5.6~570.73~L~1~5.5~ 180.79~L~2~5.4~472.17~L~3~|5.7~1667.07~B~1~5.8~46. 34~B~2~5.9~780.83~B~3~'

Last edited by AlgoTrader; 03-28-2012 at 02:04 PM
  #6  
Old 03-29-2012, 09:29 AM
AlgoTrader AlgoTrader is offline
Senior Member
 
Join Date: Mar 2012
Posts: 513
Default

Another troublesome API call implemented: getCompleteMarketPricesCompressed. There is the last "compressed" call remaining getMarketTradedVolumeCompressed, other calls are very easy to implement

Code:
github/betfair-sports-api/test> node get_complete_market_prices_compressed.js 
Logging in to Betfair...
Session token is: [skipped]
Logged in OK
Get available tennis matches
there are 136 markets
action: getAllMarkets error: null duration: 0.369
Call getCompleteMarketPricesCompressed for marketId="105273413"
action: getCompleteMarketPricesCompressed error: null duration: 0.287
marketId: 105273413
inPlayDelay: 0
player 0
	selectionId: 6191276
	lastPriceMatched: 2.78
	totalMatched: 58.53
		price:1.01 backAmount:140.06 layAmount:0.0
		price:1.02 backAmount:91.24 layAmount:0.0
		price:1.05 backAmount:4.14 layAmount:0.0
		price:1.5 backAmount:3.18 layAmount:0.0
		price:1.67 backAmount:15.92 layAmount:0.0
		price:2.2 backAmount:915.4 layAmount:0.0
		price:2.26 backAmount:59.11 layAmount:0.0
		price:2.5 backAmount:327.71 layAmount:0.0
		price:2.54 backAmount:5.99 layAmount:0.0
		price:2.6 backAmount:4.0 layAmount:0.0
		price:2.64 backAmount:2.99 layAmount:0.0
		price:2.66 backAmount:2.99 layAmount:0.0
		price:2.68 backAmount:2.99 layAmount:0.0
		price:2.7 backAmount:23.44 layAmount:0.0
		price:2.72 backAmount:2.99 layAmount:0.0
		price:2.96 backAmount:0.0 layAmount:2.99
		price:2.98 backAmount:0.0 layAmount:15.92
		price:3.0 backAmount:0.0 layAmount:159.2
player 1
	selectionId: 3842875
	lastPriceMatched: 1.56
	totalMatched: 385.31
		price:1.01 backAmount:140.06 layAmount:0.0
		price:1.02 backAmount:91.24 layAmount:0.0
		price:1.05 backAmount:4.14 layAmount:0.0
		price:1.27 backAmount:15.92 layAmount:0.0
		price:1.4 backAmount:796.0 layAmount:0.0
		price:1.41 backAmount:4.0 layAmount:0.0
		price:1.45 backAmount:1685.89 layAmount:0.0
		price:1.46 backAmount:186.32 layAmount:0.0
		price:1.47 backAmount:8.44 layAmount:0.0
		price:1.5 backAmount:146.27 layAmount:0.0
		price:1.51 backAmount:9.86 layAmount:0.0
		price:1.56 backAmount:0.0 layAmount:31.61
		price:1.61 backAmount:0.0 layAmount:8.86
		price:1.7 backAmount:0.0 layAmount:489.18
		price:2.4 backAmount:0.0 layAmount:5.19
Logging out...
Logged out OK
/github/betfair-sports-api/test>
The test source is https://github.com/BetfairTrader/bet..._compressed.js
  #7  
Old 03-31-2012, 01:26 PM
AlgoTrader AlgoTrader is offline
Senior Member
 
Join Date: Mar 2012
Posts: 513
Default

Added two more API calls: getMarketTradedVolumeCompressed and getMUBets. Just works. API is going to reach minimally required set of Betfair calls.
  #8  
Old 04-02-2012, 07:58 AM
AlgoTrader AlgoTrader is offline
Senior Member
 
Join Date: Mar 2012
Posts: 513
Default

Added getMarketProfitAndLoss API call and test, it is the final API call from the minimum survival kit, so API quite is usable now

Code:
/github/betfair-sports-api/test> node get_market_profit_and_loss.js 
Logging in to Betfair...
Session token is: [skipped]
Logged in OK
Get available tennis matches
there are 256 markets
action: getAllMarkets error: null duration: 0.525
Call getMarketProfitAndLoss for marketId="105323846"
action: getMarketProfitAndLoss error: null duration: 0.348
Player 0
	Name:Anastasiya Yakimova
	Id:2264537
	IfWin:0.0
	IfLoss:0.0
Player 1
	Name:Varvara Lepchenko
	Id:2263576
	IfWin:0.0
	IfLoss:0.0
Logging out...
Logged out OK
The code is https://github.com/BetfairTrader/bet...it_and_loss.js
  #9  
Old 04-04-2012, 10:29 AM
AlgoTrader AlgoTrader is offline
Senior Member
 
Join Date: Mar 2012
Posts: 513
Default Window support

Windows users discrimination is in the past! Currently betfair-sports-api was tested on the folowing platforms:
- Linux 2.6
- MacOSX 10.6
- WindowsXP

The first succesful test run on Windows:

Code:
C:\Node>node.exe node_modules\betfair-sports-api\test\login.js
login Request:
{ locationId: '0',
  password: 'password',
  productId: '82',
  username: 'nobody',
  vendorSoftwareId: '0' }
login error: null Response: { header:
   { errorCode: 'OK',
     minorErrorCode: null,
     sessionToken: null,
     timestamp: Wed, 04 Apr 2012 10:24:46 GMT },
  currency: null,
  errorCode: 'INVALID_USERNAME_OR_PASSWORD',
  minorErrorCode: null,
  validUntil: Mon, 01 Jan 1 00:00:00 GMT }

C:\Node>
Well, all the major platforms supported! Windows, Mac, Linux - no difference.

Last edited by AlgoTrader; 04-04-2012 at 10:31 AM
  #10  
Old 04-05-2012, 09:10 AM
AlgoTrader AlgoTrader is offline
Senior Member
 
Join Date: Mar 2012
Posts: 513
Default

Finally, placeBets, updateBets and cancelBets are impremented! The project reached usable state, all other API calls willl be implemented upon need/request.

It took for me a couple weeks to make a decent working solution. My first github commit was March 22, on April 5 I have project that is ready for starting first production app using node.js + betfair-sports-api.

Code:
/github/betfair-sports-api/test> node place_update_cancel_bets.js 
===== Logging in to Betfair... =====
Session token is: [skipped]
Logged in OK
===== Get available tennis matches =====
there are 134 markets
action: getAllMarkets error: null duration: 0.44
market to test betting: 105357529 Family Circle Cup 2012\Third Round Matches\Voskoboeva v Stosur
===== Call getMarketPricesCompressed for marketId="105357529" =====
action: getMarketPricesCompressed error: null duration: 0.351
marketId: 105357529
currency: USD
marketStatus: ACTIVE
inPlayDelay: 0
player 0
	selectionId: 2264531
	lastPriceMatched: 4.1
player 1
	selectionId: 2248502
	lastPriceMatched: 1.32
Will use selectionId 2264531 for betting tests
===== Place a test lay bet marketId=105357529 selectionId=2264531 =====
action: placeBets error: null duration: 0.536
placeBets results:
	betId=19189862864
	resultCode=OK
	success=true
	sizeMatched=0.0
===== updateBets for betId=19189862864, change bet size =====
action: updateBets error: null duration: 0.516
updateBets results:
	betId=19189862864
	newPrice=1.01
	newBetId=0
	newSize=4.0
	resultCode=BET_CANCELLED_REMAINING_UNMATCHED
	sizeCancelled=1.0
	success=true
===== cancelBets for betId=19189862864 =====
action: cancelBets error: null duration: 0.52
cancelBets results:
	betId=19189862864
	resultCode=REMAINING_CANCELLED
	sizeCancelled=4.0
	sizeMatched=0.0
	success=true
===== Logging out... =====
Logged out OK
/github/betfair-sports-api/test>
Betting now works!
Thread Closed

Tags
node

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump


All times are GMT. The time now is 04:26 PM.


BETFAIR® and the BETFAIR LOGO are registered trade marks of The Sporting Exchange Limited. Data on Betfair website(s) (including pricing data) is protected by © and database rights. It may not be used for any purpose without a licence. © The Sporting Exchange Limited. All rights reserved.