tag:blogger.com,1999:blog-69516347022073321752024-03-15T18:10:01.194-07:00Gambling and TechnologyUnknownnoreply@blogger.comBlogger14125tag:blogger.com,1999:blog-6951634702207332175.post-15600876698555698472010-03-09T01:04:00.000-08:002010-03-09T01:21:27.717-08:00Comparing the APIs: what's the best way to access Betfair from Python?<p style="margin-bottom: 0cm">(Just a quick break from the blog series on building a Betfair bot: this is a quick comparison of the various options for accessing the API through Python.)</p> <p style="margin-bottom: 0cm"><br /></p> <p style="margin-bottom: 0cm">In the examples I've used to date, I've used either Betfair's own Excel plugin, or I've used Resolver Systems' own Betfair plugin (which I've modified to add additional features to...) But Resolver's own plugin may not be the best for accessing Betfair – even from within Resolver One – and it does come with a number of disadvantages: it is Windows only, for instance. But what are the other options:</p> <p style="margin-bottom: 0cm"><br /></p> <p style="margin-bottom: 0cm; font-weight: normal">Well, there's the <u><b><a href="http://code.google.com/p/pythonbetfairlibrary/">Python Betfair Library</a></b></u>, hosted on Google Code, and last updated in mid-2008. The readme suggests it will not be completely simple to install under Windows, but as I'm using my Ubuntu box at the moment, that isn't likely to be a serious problem. So, OK, let's download and untar it. Looking into the example code, it looks like it operates in a very similar way to the Resolver libraries:</p> <p style="margin-bottom: 0cm"><br /></p> <p style="margin-bottom: 0cm"> <i><span style="font-weight: normal"><span class="Apple-style-span" style="font-family:'courier new';">exchange = Exchange()</span></span></i></p> <p style="margin-bottom: 0cm"> <i><span style="font-weight: normal"><span class="Apple-style-span" style="font-family:'courier new';">exchange.login(username, password)</span></span></i></p> <p style="margin-bottom: 0cm"> <i><span style="font-weight: normal"><span class="Apple-style-span" style="font-family:'courier new';"># How to call get_account_funds</span></span></i></p> <p style="margin-bottom: 0cm"> <i><span style="font-weight: normal"><span class="Apple-style-span" style="font-family:'courier new';">funds = exchange.get_account_funds(Exchange.EXCHANGE_UK)</span></span></i></p> <p style="margin-bottom: 0cm"><br /></p> <p style="margin-bottom: 0cm; font-weight: normal">Yep: all similar here. If it works, and is easily cross-platform, this might be a goer. OK: let's run the example code:</p> <p style="margin-bottom: 0cm"><br /></p> <p style="margin-bottom: 0cm; font-weight: normal"><i><span class="Apple-style-span" style="font-family:'courier new';">python example.py</span></i></p> <p style="margin-bottom: 0cm"><br /></p> <p style="margin-bottom: 0cm; font-weight: normal">Uh oh:</p> <p style="margin-bottom: 0cm"><br /></p> <p style="margin-bottom: 0cm; font-weight: normal"><i><span class="Apple-style-span" style="font-family:'courier new';">ImportError: No module named ZSI</span></i></p> <p style="margin-bottom: 0cm; font-weight: normal"><br /></p> <p style="margin-bottom: 0cm"><span style="font-style: normal"><span style="font-weight: normal">OK: this may not be quite as simple as I thought. ZSI is the Python Web Services project (Zolera SOAP Infrastructure). It's no big deal to install this on my box, but it does explain with these libraries might struggle to be easily cross-platform. Is ZSI/pywebsvc in the Ubuntu packages? Yep, it's python-zsi (as you might expect). A simple </span></span><i><span style="font-weight: normal"><span class="Apple-style-span" style="font-family:'courier new';">sudo apt-get install python-zsi</span></span></i><span style="font-style: normal"><span style="font-weight: normal"> is all that's needed.</span></span></p> <p style="margin-bottom: 0cm"><br /></p> <p style="margin-bottom: 0cm; font-style: normal; font-weight: normal"> Let's run again. It's asking me for my username and password – this is good. And now I wait... and I wait... </p> <p style="margin-bottom: 0cm"><br /></p> <p style="margin-bottom: 0cm; font-weight: normal"><i>...lots of errors followed by...</i></p> <p style="margin-bottom: 0cm; font-weight: normal"><i><span class="Apple-style-span" style="font-family:'courier new';">socket.gaierror: [Errno -2] Name or service not known</span></i></p> <p style="margin-bottom: 0cm; font-weight: normal"><br /></p> <p style="margin-bottom: 0cm; font-style: normal"><span style="font-weight: normal">Grr: let's run again. It's always hard to know whether the problem is Betfair's (often down, particularly for the free service, API) or whether it's because the PythonBetfairLibrary is out of date.</span></p> <p style="margin-bottom: 0cm"><br /></p> <p style="margin-bottom: 0cm; font-style: normal"><span style="font-weight: normal">This time it's better: it's giving me lots of information on markets that I don't have positions in. Then it craps out on a '<span class="Apple-style-span" style="font-family:'courier new';"><i>MARKET_CLOSED</i></span>' error, that I can at least trap. Initial impression: promising (the syntax looks fine), but it's not been updated for a long while, and it doesn't seem to trap errors very well.</span></p> <p style="margin-bottom: 0cm; font-style: normal; font-weight: normal"><br /></p> <p style="margin-bottom: 0cm; font-style: normal; font-weight: normal"> Let's try a slightly more complex test: I have a Python app for simple market making, that I've optimized for golf tournaments. Normally, I run this in Resolver. But there's no reason it cannot run it as a standalone application – with the proviso that I lose the pretty display.</p> <p style="margin-bottom: 0cm; font-style: normal; font-weight: normal"><br /></p> <p style="margin-bottom: 0cm; font-style: normal; font-weight: normal"> [25 minutes later]</p> <p style="margin-bottom: 0cm; font-style: normal; font-weight: normal"><br /></p> <p style="margin-bottom: 0cm; font-style: normal; font-weight: normal"> Well, that was simpler than I thought. The Python Betfair Library works pretty well, with two major provisos. Firstly, it doesn't trap errors particularly well. I may do a little bit of work to allow it to throw out more useful exceptions. Secondly, it's sloooooooooooooow. (This can be an advantage, as you are less likely to accidentally exceed 60 API requests per minutes.) Perhaps it's because I'm used to the Windows native Betfair DLL that backs up the Resolver libraries, but taking 20-30 seconds to execute and output the results of GetAllMarkets (against less than 2 for the native DLL) is pretty slow. It was hard to market-make more than 6-7 golfers in an efficient manner, against to 30-40 I manage using the Resolver libraries. There is nothing intrinsically slow about using pure Python libraries, so I shall do a little investigation, and see if it's anything about my setup that is causing the slow performance...</p> <p style="margin-bottom: 0cm; font-style: normal; font-weight: normal"><br /></p> <p style="margin-bottom: 0cm; font-style: normal"><span style="font-weight: normal">Which bring us to the library at </span><b>BespokeBets.com</b><span style="font-weight: normal">. This can be got here: <a href="http://bespokebots.com/showme.php?id=betfair_api_python.zip">http://bespokebots.com/showme.php?id=betfair_api_python.zip</a>. It's a pretty simple library, that uses Python's built-in url2 library to do web service queries:</span></p> <p style="margin-bottom: 0cm; font-style: normal"></p><span><span><br /><span class="Apple-style-span" style="font-family:'courier new';"><i>bot = API() # create new api object<br /></i></span></span></span><div><span><span><span class="Apple-style-span" style="font-family:'courier new';"><i>print "Login:", bot.login(username, password)<br />bot.get_account_funds()<br /></i></span></span></span><p style="margin-bottom: 0cm; font-style: normal"><br /></p> <p style="margin-bottom: 0cm; font-style: normal"><span style="font-weight: normal">The code behind the library is pretty simple: this is a very thin wrapper around the Betfair API. (I was impressed to note that there is no Betfair DLL dependence, and everything fits into a few hundred lines of code. Nice work.) And this thin-ness brings a cost: it implements only a limited subset of the API – there is no </span><i><span style="font-weight: normal">GetDetailAvailableMktDepth</span></i><span style="font-weight: normal"> or </span><i><span style="font-weight: normal">GetMarketProfitAndLoss </span></i><span style="font-weight: normal">for example. That said, extending this library would be simple, and it certainly seems capable of 4-5 simple API calls a second, which makes it quite a lot faster than the PBL.</span></p> <p style="margin-bottom: 0cm; font-style: normal"><br /></p> <p style="margin-bottom: 0cm; font-style: normal"><span style="font-weight: normal">I am not going to re-implement my market making system, because a small part of the algorithm relies on </span><i><span style="font-weight: normal">GetMarketProfitAndLoss</span></i><span style="font-weight: normal">. But in theory, working around that would not be difficult.</span></p> <p style="margin-bottom: 0cm; font-style: normal"><br /></p> <p style="margin-bottom: 0cm; font-style: normal"><span style="font-weight: normal">For now, I am going to stick with the Resolver libraries – which are, of course, just a thin interface round Betfair's own .NET ones: but for those in a non-Windows environment, both the Python Betfair Library and BespokeBot's library will work well. For anyone playing with building my bot, very few code changes should be necessary...</span></p> <p style="margin-bottom: 0cm; font-style: normal"><br /></p> <p style="margin-bottom: 0cm; font-style: normal"><span style="font-weight: normal">And now I need to get back to work...</span></p> </div>Unknownnoreply@blogger.com58tag:blogger.com,1999:blog-6951634702207332175.post-2538655587841743602010-03-04T06:18:00.000-08:002010-03-04T12:30:49.780-08:00Building Our First Betfair Bot IV - Talking to the API and storing your bets<span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><div><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">*EDIT: In this piece, I originally said you needed to use the paid API to place bets; this is no longer the case*</span></span></div><div><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></div>In the last missive, I wrote about how we want to store data. In theory, we could use Betfair itself to store data – and pull everything we need on an </span></span><i><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">ad hoc</span></span></i><span style="font-style: normal"><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"> basis. So: if we want to see which bets are open, we'd query Betfair, and it would return a list of betIDs. But, this comes with two major problems: speed and cost. Betfair can charge as much as 0.5p for certain data intensive API calls: you need some pretty amazing programming and trading skills to overcome those costs.</span></span></span><p></p> <p style="margin-bottom: 0cm"><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">So, our 'bot needs to store as much information locally as possible. And this means a (very simple) database – in our case SQLite. In today's missive, we're going to put a bet on, and then store it in our database.</span></span></p><p style="margin-bottom: 0cm"><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">The first thing we'll need is a programming language. I am going to be a little Windows-centric and use IronPython – the Microsoft implementation of Python 2.6. You'll <span class="Apple-style-span" style=" ;font-family:Georgia, serif;"><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">also need this zip file: </span></span><a href="http://automatingbetfair.s3.amazonaws.com/betfairdatabase.zip"><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">betfairdatabase.zip</span></span></a><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">. This contains the following files:</span></span></span></span></span></p> <p style="margin-bottom: 0cm"><i><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">betfair.py</span></span></i></p> <p style="margin-bottom: 0cm; "><i><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">lib.py</span></span></i></p> <p style="margin-bottom: 0cm; "><i><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">betfair.dll</span></span></i></p> <p style="margin-bottom: 0cm; font-style: normal"><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">→ these are the IronPython / Resolver Betfair libraries</span></span></p> <p style="margin-bottom: 0cm"><i><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">SystemData.SQLite.dll</span></span></i></p> <p style="margin-bottom: 0cm; font-style: normal"><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">→ The .NET ADO SQLite connector</span></span></p> <p style="margin-bottom: 0cm"><i><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">bettinghistory.s3db</span></span></i></p> <p style="margin-bottom: 0cm; font-style: normal"><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">→ An empty SQLite database</span></span></p> <p style="margin-bottom: 0cm"><i><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">database.py</span></span></i></p> <p style="margin-bottom: 0cm; font-style: normal"><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">→ our database library</span></span></p> <p style="margin-bottom: 0cm"><span class="Apple-style-span" style=" ;font-family:'Times New Roman';"></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-style: normal; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">What we'd like to achieve (ultimately) is to put bets on, and then put them in a table that looks something like this:</span></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /><img alt="" height="440" src="http://docs.google.com/File?id=ddz6xfsk_58v5b2w4dx_b" width="642" style="border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; border-width: initial; border-color: initial; " /><br /></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-style: normal; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-style: normal; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">After you've installed IronPython, it's time to have a play. For simplicities sake, copy the contents of the above folder into your IronPython directory. Now, run 'ipy.exe', which you'll find in the selfsame directory. You should get something that looks like this:</span></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /><img alt="" height="322" src="http://docs.google.com/File?id=ddz6xfsk_59g2c2sbfh_b" width="642" style="border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; border-width: initial; border-color: initial; " /><br /></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-style: normal; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-style: normal; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">OK: Let's import the database module:</span></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-style: normal; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';"><br /></span></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-style: normal; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';">>>> import database</span></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-style: normal; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-style: normal; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">And create a new database connection object:</span></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-style: normal; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-style: normal; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';">>>> dc = database.database()</span></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-style: normal; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-style: normal; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">Open the database file, so we can interact with it:</span></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-style: normal; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-style: normal; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';">>>> dc.open('bettinghistory.s3db')</span></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">OK: so, what can we do with our database connection? Well, firstly we can record our betting activities. Let's set-up and record a bet:</span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-style: normal; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-style: normal; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';">>>> </span></span></span><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';">import betfair</span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-style: normal; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';">>>> </span></span></span><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';">betfairGateway = betfair.BetfairGateway('username', 'password', productId = 22)</span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';">OK</span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">(This assumes you have a Betfair paid API subscription. If you don't, you'll be reading, rather than doing.)</span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-style: normal; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';">>>> </span></span></span><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';">betfairMarket = betfairGateway.GetMarketById(20692870)</span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">We've set up a betfairMarket object for the winner of the World Cup 2010 (which, slightly surprisingly, Spain is the favourite to win.)</span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">Shall we see who the runners are?</span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-style: normal; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-style: normal; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';">>>> </span></span></span><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';">for runner in betfairMarket.GetRunners()</span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';">... print runner, runner.Id, runner.Back</span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';">...</span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">The screen should look something like this:</span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /><img alt="" height="619" src="http://docs.google.com/File?id=ddz6xfsk_609mpcm7gc_b" width="642" style="border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; border-width: initial; border-color: initial; " /><br /></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">Now, I'm working on the theory that – if England moves out to 10-1 (11.0 in Betfair speak) – then I want some of that action. (Of course, the current price is 7.0, so that isn't very likely right now... but still...) To do this we have to get hold of the Betfair runner (selection) object:</span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-style: normal; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-style: normal; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';">>>> </span></span></span><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';">selection = betfairMarket.getRunner(27)</span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">(We've gotten the selectionID by looking at the print-out above, and entering it manually. You'd probabaly want to iterate over GetRunners() until you got the object you wanted... but this will do for now.) And let's check we have the right object:</span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-style: normal; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';">>>> selection, selection.Back</span></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-style: normal; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';">(England, 7.0)</span></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">Perfect: that looks like the right object, and we need to pass this object to the betfairGateway if we want to put a bet on:</span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-style: normal; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';">>>> response = betfairGateway.Back(selection, 11, 2)</span></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-style: normal; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';">OK</span></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">The first thing we pass is the selection object, the second the desired odds, and finally the amount (in this case, the £2 minimum).</span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">Now, the Betfair bet response object is a complex beast, but the only bit that is really of interest to us is the array of results. Let's pull it out:</span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';">>>> betsArray = response.betResults</span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">And see how many bet objects it contains:</span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';">>>> len(betsArray)</span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';">1</span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">No great surprise here: the bet we've put into the system is so far out the money I'd be surprised if there was more than one object: that of an unmatched bet. (If you were to offer to back England at 6, with £100,000, then you would get an awful lot of bet objects in return: one covering the bets matched at 7.0, one at 6.9, etc.</span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">But let's take a look at the bet object we've gotten here:</span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';">>>> bet = betsArray[0]</span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style=" ;font-family:arial;">Ha ha! Now we (finally) have an object with the details of our bet. Let's see if it was succesfully placed into the system (i.e. that the market is still live, and we still have money in our account):</span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style=" ;font-family:arial;"><br /></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';">>>> bet.success</span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';">True</span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">Excellent. We've placed the bet. That's a good start. Was it matched?</span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';">>>> bet.sizeMatched</span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';">0.0</span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">No surprise: it wasn't matched. It's sitting in the Betfair system waiting for someone to offer 10-1 on England. Finally, before we call it a wrap for the evening, let's store this bet in our database:</span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';">>>> dc.openBet(bet, </span></span><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';">20692870, 27, 200, 11, 'BACK')</span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">The openBet method takes the following paramaters: bet object, marketID, selectionID, amount (in pence), odds (a float), type (either 'BACK' or 'LAY').</span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"> </span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">Tomorrow – or in a few days – we'll play a little more with putting bets into the system, and reading the responses. But, hey, pat yourself on the back, you've just put some money on England to win the World Cup :-)</span></span></p><p style="margin-top: 0pt; margin-right: 0pt; margin-bottom: 0pt; margin-left: 0pt; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"> </span></span></p><div><span class="Apple-style-span" style=" ;font-family:'Courier 10 Pitch';"><span class="Apple-style-span" style="font-size:100%;"><br /></span></span></div><p></p>Unknownnoreply@blogger.com41tag:blogger.com,1999:blog-6951634702207332175.post-39333122126424931412010-02-19T14:01:00.000-08:002010-02-19T14:05:41.432-08:00Building Our First Bot III - Storing Our Data<p class="MsoNormal">(Apologies for the delay in the posting of this… I foolishly decided to move my work PC to Ubuntu. In the process, I discovered GNOME does not handle multiple monitors on multiple graphics cards particularly gracefully.)</p> <p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p> <p class="MsoNormal"><span lang="EN-US">Amyway, back to the Betfair ‘bot: it's funny; if I wasn't writing about this as I build it, I'd get out a text editor, hack up some Python, chuck it into Resolver, and see how it did. (With a little bit of testing... probably... to make sure that the idea and the code is not completely hairbrained. Heck, when I wrote my first marketmaking 'bot, that's exactly what I did.)</span></p> <p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p> <p class="MsoNormal"><span lang="EN-US">But when I'm writing for an audience, even a pretty small one, I feel the need to do things at least vaguely properly. No 'magic numbers', relatively well structured code, not using object orientation unless it is strictly necessary. </span></p> <p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p> <p class="MsoNormal"><span lang="EN-US">I'm also starting to think a little about 'bot program structure. And what I've been thinking about is the importance of keeping our own record of bets (aside from Betfair's own one). That is, my spreadsheet should contain a transaction list, and I should be able to find the betIDs of open bets, without querying Betfair.</span></p> <p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p> <p class="MsoNormal"><span lang="EN-US">Why? Well, there are three good reasons:</span></p> <p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p> <p class="MsoNormal" style="margin-left:36.0pt;text-indent:-18.0pt;mso-list:l0 level1 lfo1; tab-stops:list 36.0pt"><span lang="EN-US" style="mso-fareast-font-family: "Times New Roman""><span style="mso-list:Ignore">1.<span style="font:7.0pt "Times New Roman""> </span></span></span><span lang="EN-US">Querying Betfair is expensive. If we do more than a certain number of API calls a month, we'll get charged extra. If our 'bot is low margin (as this first 'bot certainly will be...), this could be a fatal flaw.</span></p> <p class="MsoNormal" style="margin-left:36.0pt;text-indent:-18.0pt;mso-list:l0 level1 lfo1; tab-stops:list 36.0pt"><span lang="EN-US" style="mso-fareast-font-family: "Times New Roman""><span style="mso-list:Ignore">2.<span style="font:7.0pt "Times New Roman""> </span></span></span><span lang="EN-US">Querying Betfair is slow. Let's say we want to run this strategy on 200 markets, with 4 selections apiece, then that means we'll be doing close to 1,000 API calls a minute: and that's somewhere between mildly and completely impossible, given how slow the Betfair API can be.</span></p> <p class="MsoNormal" style="margin-left:36.0pt;text-indent:-18.0pt;mso-list:l0 level1 lfo1; tab-stops:list 36.0pt"><span lang="EN-US" style="mso-fareast-font-family: "Times New Roman""><span style="mso-list:Ignore">3.<span style="font:7.0pt "Times New Roman""> </span></span></span><span lang="EN-US">We'll want to do analysis of where and why our bot worked, and where and why it didn't. Having easily – machine readable – logs of everything we've done is a clear positive. Yes, we can pull data out of Betfair. But if we don't have to, that's preferable.</span></p> <p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p> <p class="MsoNormal"><span lang="EN-US">So: how to record our activity?</span></p> <p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p> <p class="MsoNormal"><span lang="EN-US">Well: we could use a table/worksheet in Excel or Resolver. But that has a number of problems: it’s difficult to collate across multiple different strategies, markets and selections. It also makes for an often unwieldy and slow spreadsheet. (Spreadsheets aren’t really meant to be used as databases…)</span></p> <p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p> <p class="MsoNormal"><span lang="EN-US">Or we could use flatfiles or self generated XML. But then we’re building a complex interface, and this isn’t really hierarchical data.</span></p> <p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p> <p class="MsoNormal"><span lang="EN-US">No, what we want is a simple (but proper) database of all open and closed transactions, that can be queried extremely quickly and efficiently. Which brings us immediately to the question of which database: mySQL, PostgreSQL, Access, SQL Server or… SQLite.</span></p> <p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p> <p class="MsoNormal"><span lang="EN-US">And it really is no contest: SQLite is the option. Simple, fast to deploy, multi-platform, works with Excel, Resolver, Python, PHP, VBA, .NET, etc. In addition: an SQLite database, sitting in a Dropbox directory, can be used by different instances and computers in different locations, running atop different platforms. Nice.</span></p> <p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p> <p class="MsoNormal"><span lang="EN-US">Now, before we delve into the technical details, let’s ask what we’re going to store in this database:</span></p> <p class="MsoNormal"></p><p class="MsoNormal"></p><ul><li><i>key </i>– simple auto-incrementing integer</li><li><i>betID</i> - integer</li><li><i>marketID</i> - integer</li><li><i>selectionID</i> - integer</li><li><i>amount</i> – integer (we’ll store stuff in pence)</li><li><i>back</i> – Boolean (if True, we’ve put a back bet into the system, if false, we’ve put a lay)</li><li><i>open</i> – Boolean (is the bet open, or was it taken)</li><li><i>cancelled</i> – flag</li><li><i>odds</i> – float</li><li><i>strategy</i> – integer (which will be the primary key on a table of strategies. We’ll set this as 1 for now)</li><li><i>timeopened</i> – time</li><li><i>timeclosed</i> - time</li></ul><p></p> <p></p> <p class="MsoNormal"><span lang="EN-US">This is not a complex selection for now; no great need for joins. This is a rapidly searchable data store, not an ERP system. Relationality is for convenience only.</span></p> <p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p> <p class="MsoNormal"><span lang="EN-US">Inside our ‘bot, we’ll have a worksheet that reflects the activity of that strategy in that selection on that market. And it will get this data out through the simple use of SQLite. (Best of all, this datastore will be useful for all your ‘bots going forwards.)</span></p> <p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p> <p class="MsoNormal"><span lang="EN-US">Right: that’s all the theory for this post. Next one, we’ll implement this store.</span></p>Unknownnoreply@blogger.com13tag:blogger.com,1999:blog-6951634702207332175.post-32141716875320152162010-02-13T03:20:00.000-08:002010-02-13T09:59:19.101-08:00Off The Shelf Bots<div><span class="Apple-style-span" style="font-family:Verdana;"><span class="Apple-style-span" style=" ;font-family:Georgia, serif;"><div><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">There are an extraordinary number of off-the shelf pieces of software that promise extraordinary trading gains. All you have to do is hand over a small amount of money... load up your Betfair account... and... </span></span><i><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">profit</span></span></i><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">!</span></span></div><div><span class="Apple-style-span" style="font-family:Verdana;font-size:13px;"><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">I am naturally suspicious of all get rich quick schemes. This blog will not make you rich. It will, I hope, give you the tools that will enable you to write sensible Betfair bots. It will, I hope, improve the quality of your betting, and perhaps your enjoyment of it.</span></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">But there are no 'guaranteed winner' Betfair bots out there. As soon as more than one person knows about a strategy, they will ruthlessly exploit it until the gains no longer exist. A year ago there were plenty of opportunities to make money though the arbitrage explained in <a href="http://automatingbetfair.blogspot.com/2010/02/betfair-bots-and-opportunity-out-there.html">this post</a>. Now, the opportunities are extremely limited, if they exist at all - because when the smallest gap between bet and lay prices opens up, it is immediately exploited. Two years ago, uberbot sought out thousands of opportunities to make £2 bets at 100/1, which were really 70/1 shots. For an individual, exploiting this was all but impossible. For a bot it was a winning strategy. But that opportunity has been and gone: the uberbot team has had to find other ways to make a turn.</span></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">Natural suspicions aside, what's in these 'bots? What does my £25 or $50 or $1,000 buy me? What kind of strategy does it run? Colour me intrigued, if cautious. A little bit of Googling is in order, I think:</span></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">Well, first up is the (aptly named) </span></span><b><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><a href="http://www.betfairbot.com/">Betfair Bot</a></span></span></b><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">. This is a "</span></span><span class="Apple-style-span" style=" color: rgb(51, 51, 51); line-height: 16px; "><i><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">is a brand new Automated Betfair Laying Software which will supercharge your betting activities even while you're away at work or simply want to spend time with your family</span></span></i><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">." There is the obligatory quote about a chap called Adam who "</span></span><span class="Apple-style-span" style="border-collapse: collapse; -webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; "><i><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">made over £100,000 profit on Betfair from a starting bank of £200 with no knowledge of gambling by trading on Betfair!"</span></span></i><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">. Well, I don't know about you, but I'm considering giving up my day job to cash in on this £100,000 bonanza. OK, so this is a system that automatically lays things on Betfair. In other words, it's a super-simplified market making application of some description - I can see that would work. I'll download and review at some point.</span></span></span></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style=" color: rgb(51, 51, 51); line-height: 16px; "><span class="Apple-style-span" style="border-collapse: collapse; -webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></span></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style=" color: rgb(51, 51, 51); line-height: 16px; "><span class="Apple-style-span" style="border-collapse: collapse; -webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">Then there is the wonderfully titled <b><a href="http://www.makemoneyonbetfair.com/">Make Money on Betfair</a></b>, which proudly advertises "the proof is in the video", and claims that the system - in one two hour period - made £200. If all I need (to sell a 'bot) is a video of a making money on Betfair, then I think this should be pretty simple. Even the world's worst system - given vaguely efficient Betfair markets - should occasionally make money, even if only briefly. The site continually harps on about "100% Proof". Sign me up!</span></span></span></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style=" color: rgb(51, 51, 51); line-height: 16px; "><span class="Apple-style-span" style="border-collapse: collapse; -webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></span></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style=" color: rgb(51, 51, 51); line-height: 16px; "><span class="Apple-style-span" style="border-collapse: collapse; -webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">And then there is <a href="http://www.betangel.com/"><b>Bet Angel</b></a>, which has by far the most professional web page. A cursory glance makes it look a pretty useful tool: it seems to introduce a lot of financial world concepts to gambling and Betfair, dressed up into wonderful terms such as a 'riskometer' (which I suspect is a combination of a NAV calculator, with some simple variance calculations). The charts it seems to produce look very Bloomberg - and I wouldn't be surprised if the people involved in this project worked in Financial Services at one point or another. The pricing mechanism also seems very reasonable: I like the way it charges by the month, etc. Most of all, I like the way Bet Angel doesn't promise instant riches: for that reason, I give the first G&T Thumbs Up.</span></span></span></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style=" color: rgb(51, 51, 51); line-height: 16px; "><span class="Apple-style-span" style="border-collapse: collapse; -webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;"><br /></span></span></span></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style=" color: rgb(51, 51, 51); line-height: 16px; "><span class="Apple-style-span" style="border-collapse: collapse; -webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; "><span class="Apple-style-span" style="font-family:arial;"><span class="Apple-style-span" style="font-size:small;">Well: this has been a diversion (caused by lack of access to Betfair from the hotel I'm staying in!) I'll continue with the Betfair 'bot on Monday or Tuesday. </span></span></span></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style=" color: rgb(51, 51, 51); line-height: 16px; font-family:Arial, Helvetica, sans-serif;"><span class="Apple-style-span" style=" ;font-size:small;"><span class="Apple-style-span" style="border-collapse: collapse; -webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; "> </span></span></span></div></span></div></span></span></div>Unknownnoreply@blogger.com17tag:blogger.com,1999:blog-6951634702207332175.post-30100597903560553312010-02-11T11:12:00.000-08:002010-02-11T15:31:15.322-08:00Building Our First Bot - Part II, FrameworkLast post, we looked at how out 'bot would make money. This post, we'll put the framework in place. The framework is the outline of the code we'll be using. One of the nice things about this framework is that it is pretty language-independent. With just a little work, it can be converted to pretty much any language: Ruby, VBA, Java, etc. I shall, of course, be using Python - and will probably implement it in Resolver down the road.<div><br /></div><div>The main program loop will look something like this:</div><div><pre>Evaluate Status<br /><br />if No Open or Matched Bets:<br /> Offer To Back<br />else if Unmatched Offer to Back:<br /> See if Conditions for Backing Still Exist<br /> Move or Cancel Bet if they do not<br />else if Unmatched Offer to Lay:<br /> Do Nothing For Now (we're doing this simply, remember)<br />else if Matched Offer to Back:<br /> Record the Matched Bet<br /> Create new Offer to Lay<br />else if Matched Offer to Lay:<br /> Record the Matched Bet<br /> Offer To Back</pre><br />This is the simplest kind of pseudo-code. Moving it into more real Python gets us this:</div><div><div><pre><br />import betfair<br />betfairGateway = betfair.BetfairGateway(username, password, productID)<br /><br />marketID = xx<br />selectionID = xx<br /><br />while not MarketInPlay():<br /><br />status = EvaluateStatus()<br /><br />if status == 'No Open or Matched Bets':<br /> if ConditionsExistToBack():<br /> OfferToBack()<br /><br />elif status == 'Unmatched Offer to Back':<br /> if not MyBestBestBet():<br /> CancelBets()<br /> <br /> if ConditionsExistToBack():<br /> OfferToBack()<br /><br />elif status == 'Unmatched Offer to Lay':<br /> # Do Nothing For Now (we're doing this simply, remember)<br /> pass<br /><br />elif status == 'Matched Offer to Back':<br /> RecordMatchedBackBet()<br /> OfferToLay()<br /><br />elif status == 'Matched Offer to Lay':<br /> RecordMatchedLayBet()<br /> if ConditionsExistToBack():<br /> OfferToBack()<br /></pre><br />Now, while we're not quite at a working, trading 'bot, we have the outline in place. Tomorrow (or in the next few days), I'll fill in the missing methods, and transition the 'bot to Resolver One.</div><div><br /></div><div>Next week (when I'm back in the UK, with reliable Internet access again...), I'll set it up and running.</div></div>Unknownnoreply@blogger.com4tag:blogger.com,1999:blog-6951634702207332175.post-48848777879364698982010-02-10T03:33:00.000-08:002010-02-10T03:34:05.201-08:00Building Our First Bot - Part I, Theory<p style="margin-bottom: 0cm">OK: we've done a lot of theory. Now, let's actually build something that can <b>actually</b> trade. What we're going to do is a very, very simple version of a market-making bot. Why so simple? Because we want to minimise risk during this learning experience, and also because it'll be easier to understand what we're doing. We'll build out this 'bot over the next couple of weeks and months, but this should get you started.</p> <p style="margin-bottom: 0cm"><br /></p> <p style="margin-bottom: 0cm">First things first: what's this bot going to do?</p> <p style="margin-bottom: 0cm"><br /></p> <p style="margin-bottom: 0cm">Well, it's going to act as a very simple market maker. It will offer liquidity, for a given selection, at a slightly better price than the best price currently offered. Every few minutes it will check whether it is still the best price, and will move it if price change around it. Should our meagre offer be taken, it will jump to the other side of the trade, offering up a price for someone else to take.</p> <p style="margin-bottom: 0cm"><br /></p> <p style="margin-bottom: 0cm">Simple? Well, let's explain it using some pictures. A typical Betfair selection looks like this:</p> <p style="margin-bottom: 0cm"><br /></p> <p style="margin-bottom: 0cm">Tottenham Hotspur vs Arsenal</p> <table width="100%" border="1" bordercolor="#000000" cellpadding="4" cellspacing="0"> <col width="85*"> <col width="85*"> <col width="85*"> <tbody><tr valign="TOP"> <td width="33%"> <p><br /> </p> </td> <td width="33%"> <p>Back</p> </td> <td width="33%"> <p>Lay</p> </td> </tr> <tr valign="TOP"> <td width="33%"> <p>Tottenham</p> </td> <td width="33%" sdval="2.2" sdnum="2057;"> <p>2.2</p> </td> <td width="33%" sdval="2.4" sdnum="2057;"> <p>2.4</p> </td> </tr> <tr valign="TOP"> <td width="33%"> <p>Arsenal</p> </td> <td width="33%" sdval="1.5" sdnum="2057;"> <p>1.5</p> </td> <td width="33%" sdval="1.7" sdnum="2057;"> <p>1.7</p> </td> </tr> </tbody></table> <p style="margin-bottom: 0cm"><br /></p> <p style="margin-bottom: 0cm">Now, for the purposes of our super-simple 'bot, let's simply look at one selection – Tottenham. So, we have an option to back them at 2.2, and to lay them at 2.4.</p> <p style="margin-bottom: 0cm"><br /></p> <p style="margin-bottom: 0cm">What out 'bot will do is this: it will <u>offer to back</u> Tottenham with a £2 (the minimum) bet at 2.38. </p> <p style="margin-bottom: 0cm"><br /></p> <p style="margin-bottom: 0cm">Tottenham Hotspur vs Arsenal</p> <table width="100%" border="1" bordercolor="#000000" cellpadding="4" cellspacing="0"> <col width="85*"> <col width="85*"> <col width="85*"> <tbody><tr valign="TOP"> <td width="33%"> <p><br /> </p> </td> <td width="33%"> <p>Back</p> </td> <td width="33%"> <p>Lay</p> </td> </tr> <tr valign="TOP"> <td width="33%"> <p>Tottenham</p> </td> <td width="33%" sdval="2.2" sdnum="2057;"> <p>2.2</p> </td> <td width="33%" sdval="2.38" sdnum="2057;"> <p><b><span style="background: #ff00ff">2.38</span></b></p> </td> </tr> <tr valign="TOP"> <td width="33%"> <p>Arsenal</p> </td> <td width="33%" sdval="1.5" sdnum="2057;"> <p>1.5</p> </td> <td width="33%" sdval="1.7" sdnum="2057;"> <p>1.7</p> </td> </tr> </tbody></table> <p style="margin-bottom: 0cm"><br /></p> <p style="margin-bottom: 0cm">Now, the market will look like this. (I've highlighted the bet that is ours.) Our 'bot will then monitor the market every 30 seconds or so. If our bet is taken (and nothing else happens), then the market will look like the first figure again. And we will have a profit of £2.76, should Tottenham win.</p> <p style="margin-bottom: 0cm"><br /></p> <p style="margin-bottom: 0cm">But we're not interested in whether Tottenham wins or not – our goal is to make money by supplying liquidity to the market. So, what we'll do now is <u>offer to lay</u> Tottenham at 2.22. </p> <p style="margin-bottom: 0cm"><br /></p> <p style="margin-bottom: 0cm">Tottenham Hotspur vs Arsenal</p> <table width="100%" border="1" bordercolor="#000000" cellpadding="4" cellspacing="0"> <col width="85*"> <col width="85*"> <col width="85*"> <tbody><tr valign="TOP"> <td width="33%"> <p><br /> </p> </td> <td width="33%"> <p>Back</p> </td> <td width="33%"> <p>Lay</p> </td> </tr> <tr valign="TOP"> <td width="33%"> <p>Tottenham</p> </td> <td width="33%" sdval="2.22" sdnum="2057;"> <p lang="en-GB" style="widows: 0; orphans: 0"><span style="color:#000000;"><span style="font-family:Times New Roman, serif;"><span style="font-size:100%;"><b><span style="background: #ff00ff">2.22</span></b></span></span></span></p> </td> <td width="33%" sdval="2.4" sdnum="2057;"> <p lang="en-GB" style="widows: 0; orphans: 0"><span style="color:#000000;"><span style="font-family:Times New Roman, serif;"><span style="font-size:100%;">2.4</span></span></span></p> </td> </tr> <tr valign="TOP"> <td width="33%"> <p>Arsenal</p> </td> <td width="33%" sdval="1.5" sdnum="2057;"> <p>1.5</p> </td> <td width="33%" sdval="1.7" sdnum="2057;"> <p>1.7</p> </td> </tr> </tbody></table> <p style="margin-bottom: 0cm"><br /></p> <p style="margin-bottom: 0cm">Should someone take our bet, then we'll have a (£0.32) profit irrespective of whoever wins. </p> <p style="margin-bottom: 0cm"><br /></p> <p style="margin-bottom: 0cm">This will be the simplest Betfair 'bot in the world: it will monitor somewhere between 1 and 100 selections, and will attempt to grab a small chunk of the action by acting as a (very limited) market maker.</p> <p style="margin-bottom: 0cm"><br /></p> <p style="margin-bottom: 0cm">But what happens if no-one takes my <u>offered back</u> bet, or if the market moves away from me? Well, no great loss. You can just reset the level of your bet, so that it is inside the best lay price available. The 'bot needs to be smart enough to only put bets on when there is a reasonable (say 3%) gap between the back and lay prices.</p> <p style="margin-bottom: 0cm"><br /></p> <p style="margin-bottom: 0cm">And what happens if someone takes my <u>offered back</u><span style="text-decoration: none"><span style="font-weight: normal"> bet, but then no-one takes my </span></span><u><span style="font-weight: normal">offered lay</span></u><span style="text-decoration: none"><span style="font-weight: normal">, or the market moves away from me so I am making a guaranteed loss? Well, the 'bot has two possible choices: it can always stay inside the best back price, and so sometimes it will take small losses. Or it can leave the bet in place and hope the market returns. Because the amounts we're playing with are so small, the worst that happens is that we end up with a small uncovered back bet on Tottenham.</span></span></p> <p style="margin-bottom: 0cm"><br /></p> <p style="margin-bottom: 0cm"><span style="text-decoration: none"><span style="font-weight: normal">This 'bot will work best on markets where the odds move around a lot. And it will work least well on odds which will tend to trend for long-periods in certain directions. It will also work very poorly for in-play markets – not least because it will only be checking on prices every 30 seconds or so. The 'bot needs a reasonably, but not excessively, liquid markets: we need to have a gap between the back and the lay prices, otherwise we're not offering anything useful. (The aim with this 'bot is to get paid for the provision of liquidity.) We'll work on some algorithms that find appropriate markets and selections down the road.</span></span></p> <p style="margin-bottom: 0cm"><br /></p> <p style="margin-bottom: 0cm"><span style="text-decoration: none"><span style="font-weight: normal">In the second part of this post – which will hopefully be tomorrow, but may be Friday – we'll actually program this 'bot, and get it trading on some real markets.</span></span></p>Unknownnoreply@blogger.com11tag:blogger.com,1999:blog-6951634702207332175.post-21953695374419614502010-02-08T09:51:00.000-08:002010-02-08T09:34:40.033-08:00Four Trading StrategiesThere are probably a hundred different, already implemented, trading strategies on Betfair. Someone will have - I'm sure - hooked the Fink Tank football predictor up to Betfair. Some of these will be fiendishly complex, others will simple. Some will make money for a short while, others will remain profitable for a long time, many will never consistently make money.<div><br /></div><div>All trading systems will fall into one of four broad categories:</div><div><br /></div><div><b>Algorithms that are better at calculating probabilities than most gamblers</b>. I know of one system that trades only cricket matches, and it relies on the fact that many people over-react when a wicket goes down. Apparently, one wicket falling has less impact than many gamblers expect (in the short run, they over-estimate its importance). By immediately buying the side who has lost the wicket, assuming the odds have swung enough, the system has had significantly positive returns over the last several years. Another - also cricket related - system was based on the fact that people significantly over-estimate the probability of draws. For a long-while this was also pretty profitable - until other gamblers noted that Betfair odds were out of line with history. Each of these systems is based upon a better ability to calculate true odds than most punters.</div><div><br /></div><div><b>Arbitrage related algorithms. </b>The system described in <a href="http://automatingbetfair.blogspot.com/2010/02/betfair-bots-and-opportunity-out-there.html">this post</a>, was an arbitrage related one. Arbitrage - executed correctly - is riskless profits. The principle is always roughly the same: there will be multiple markets or selections whose results are highly correlated in one way or another - and whose prices should move in lock-step. To take a political example, the Betfair markets on the individual seats should match up pretty accurately to the party seats line (a 50/50 bet on the number of seats individual parties will achieve). Frequently it does not. During the US Primaries, Hillary Clinton was still the favourite, even when the state betting was strongly favouring Barack Obama. There was arbitrage opportunity backing Hillary in the individual States, and backing Barack to be nominee. Some arbitrage happens between Betfair and Betdaq, and/or the spreadbetting firms and/or traditional bookmakers. For example, bookmakers typically give each-way odds based on a simple 1/4 formula. It used to be possible to look for races with strong favourites, back the second or third horses each way with bookmakers, and then sell the win portion of the bet on Betfair. This was enormously profitable - until the bookmakers realised their mistakes.</div><div><br /></div><div><b>Flow of Funds Systems</b>. This is what people tend to think of when they think of financial algorithmic trading; it is systems that are plugged into price feeds, monitoring movements, and detecting where prices are going to go. Flow of funds trading is unique because it requires limited information about the underlying market: you don't need to be a horse racing expert, just a maths whizz. The simplest flow of funds trading system will be the one we implement on here first: a simple market making system. Market making involves providing liquidity to a market: i.e., being prepared to take other peoples' bets. In return for this, prices you put into the system include an over-round (that is, the raw implied probabilities add up to more than 100%). If you are able to correctly judge the market so that you get roughly similar numbers of people backing each of the runners, then you will profit.<br /><br /><span style="font-weight: bold;">Informational Advantage Systems</span>. "The most valuable commodity," said Gordon Gecko to Bud Fox, "is information". The first person to see that a cricket wicket has fallen, or a goal scored, is able to adjust prices that bit quicker. (To encourage market making, Betfair has a 5 second delay on bet placing - but this still gives opportunities when a foolish cricket market maker goes on a bathroom break at just the wrong moment.) Given limited resources, it will be extremely hard for you or I to know things other people do not: however, it is possible we will be able to react <span style="font-style: italic;">quicker</span> if we leave the trading in the hands of a 'bot. There are a number of Python Bayesian analysis tools that might be useful to automatically divine of a piece of information is likely to move a market... before human traders can react.<br /><br />Now, I have never written a bot based around types one or two (although I have made money with manual trading of this type.) I currently run a reasonably successful marketmaking bot that prices up perhaps 20-30 markets, and makes c. £300-400/month. (One of the impetuses behind this blog was that if I wrote about it, I might get around to improving it!) I am very keen to deploy a system based on informational advantage - and after we cover building a market making 'bot, I think we'll go straight onto Bayesian analysis.<br /><br />So: until next time...<br /></div>Unknownnoreply@blogger.com45tag:blogger.com,1999:blog-6951634702207332175.post-55207171531424394252010-02-07T08:58:00.000-08:002010-02-07T09:23:00.436-08:00Tabulating Net Asset Values<div><span class="Apple-style-span" style=" ;font-family:Verdana;font-size:13px;"><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size:small;">I've written a lot about generalities. About what works, and how it works. Or more likely, what doesn't work and why it doesn't work.</span></div><span class="Apple-style-span" style="font-size:small;"><br /></span><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size:small;">Now it's time to be a little more practical. There is no more useful thing for a Betfair professional than a dashboard. I find it somewhat bizarre that Betfair doesn't provide one themselves - but nevermind, let's build one. Let's start off really simple: let's allow you to enter a list of MarketIDs, and then the dashboard shows your markets and your NAVs for each one. We'll make it a little bit cleverer and allow you to click on each one to go to direct to the Betfair page.</span></div><span class="Apple-style-span" style="font-size:small;"><br /></span><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size:small;">In other words, we'll build something that looks exactly like this:</span></div><span class="Apple-style-span" style="font-size:small;"><br /></span><div id="zkm_" style="margin-top: 0px; margin-bottom: 0px; text-align: left; "><span class="Apple-style-span" style="font-size:small;"><img src="https://docs.google.com/File?id=ddz6xfsk_56f8x9tdct_b" style="height: 655.86755px; width: 648px; " /></span></div><span class="Apple-style-span" style="font-size:small;"><br />You can download this <a href="http://automatingbetfair.s3.amazonaws.com/CollatingNAVs.zip">here</a>. But the principle is pretty simple, and the whole sheet is driven by a slghtly improved version of the simple NAV generator discussed <a href="http://automatingbetfair.blogspot.com/2010/02/automating-navs.html">here</a>. Let me run you through it:<br /><br /></span><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-family:'courier new';"><span class="Apple-style-span" style="font-size:small;"># Define worksheet names</span></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-family:'courier new';"><span class="Apple-style-span" style="font-size:small;">NAV = workbook['NAV']</span></span></div><span class="Apple-style-span" style="font-size:small;"><br /></span><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size:small;">This is pretty simple. The worksheet (as you can tell by the tab under it) we want to deal with is called NAV. Normally, to access it, we'd refer to workbook['NAV'], but as that's long-winded, let's create a shortcut.</span></div><span class="Apple-style-span" style="font-size:small;"><br /></span><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';">import betfair</span></span></div><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';"><br /></span></span><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';">betfairGateway = betfair.BetfairGateway(username.Value, password.Value, productId=productID.Value)</span></span></div><span class="Apple-style-span" style="font-size:small;"><br />Now, let's import the Betfair libraries, and then create a gateway object. The gateway object is how we interact with Betfair. It initiates the connection, and we can then query it for details on specific markets and bets.<br /><br /></span><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';">for row in NAV.ContentRows:</span></span></div><span class="Apple-style-span" style="font-size:small;"><br /></span><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size:small;">Now, one of the great joys about Python (and indeed, Resolver) is the whole iterating process. Here we are asking to iterate over each of the content rows (i.e., the rows excluding the header row at the top). In each iteration, the code will have a row object to play with. You can access the contents of each row by name: so row['marketID'] would contain '100329014' for the first row, etc.</span></div><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';"><br /></span></span><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';"> output = RunWorkbook("automated NAV generator.rsl", gatewayObject = betfairGateway, marketID = row['marketID'])</span></span></div><span class="Apple-style-span" style="font-size:small;"><br /></span><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size:small;">This is where it gets </span><i><span class="Apple-style-span" style="font-size:small;">really clever</span></i><span class="Apple-style-span" style="font-size:small;">. RunWorkbook allows us to run another workbook, passing it certain parameters. In this case, we're opening up the NAV generator we produced a few posts ago, and we're passing two arguments: firstly we're passing the Betfair Gateway object, so that the workbook doesn't have to generate its own. This is to save on resources (ours and Betfairs!) and to reduce the time needed to run the sheet. Secondly, we're passing the marketID from the row. </span></div><span class="Apple-style-span" style="font-size:small;"><br /></span><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size:small;">To put it another way, we're going through each market listed in the marketID column, and executing the NAV calculating sheet. The completed sheet is stored in the output object, and we could query anything we liked about this sheet. (We could find out the value of Sheet3!A1 by using output['Sheet3'].A1. Cool, huh?)</span></div><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';"><br /></span></span><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';"> row['marketName'] = output.marketname</span></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';"> row['NAV'] = output.theNAV</span></span></div><span class="Apple-style-span" style="font-size:small;"><br />And, indeed, we not pull out two bits of data from the sheet: the matketName that corresponds to the marketID, and the NAV the sheet has calculated. We then put that data into the row object. (Again, we're referencing by name - row['NAV'] means the NAV cell in that particular row.<br /><br /></span><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';"> href = "http://sports.betfair.com/Index.do?mi=%i&ex=1&origin=MRL" % (row['marketID'])</span></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size:small;"><span class="Apple-style-span" style="font-family:'courier new';"> NAV.Cells['marketName', row['marketID']].Href = href</span></span></div><span class="Apple-style-span" style="font-size:small;"><br /></span><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size:small;">One last cool thing to do: let's create a hyperlink from the name of the market to the Betfair page that holds it. </span></div><span class="Apple-style-span" style="font-size:small;"><br /></span><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size:small;">This whole sheet does one thing reasonably well - it shows the NAVs for all the different marketIDs you feed it. It is not complex, and has no ability to act yet - but it is a useful </span><i><span class="Apple-style-span" style="font-size:small;">aide memoir</span></i><span class="Apple-style-span" style="font-size:small;"> for your betting even at this relatively early stage.</span></div><span class="Apple-style-span" style="font-size:small;"><br /></span><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size:small;">We will enhance this sheet in the coming days and months - adding additional risk metrics, and buttons that allow the system to autimatically bet for you. We'll also get it working *in* a browser, so you won't need to fire up Resolver One, and we'll let it auto-generate the list of marketIDs dependent on what markets you are currently involved in.</span></div><span class="Apple-style-span" style="font-size:small;"><br /></span><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size:small;">'til next time...</span></div><div><br /></div></span></div>Unknownnoreply@blogger.com5tag:blogger.com,1999:blog-6951634702207332175.post-32562545766942008522010-02-05T03:12:00.000-08:002010-02-05T15:47:59.249-08:00Betfair Bots and the Opportunity Out There<span class="Apple-style-span" style="font-family: verdana;font-family:Verdana;font-size:100%;" ><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span">I am lucky to know some of the people behind the original Betfair bot: uberbot. At one point uberbot was making more than £100,000 each month in profits - and the computers that ran the system filled a small room. (And generated quite a lot of heat, and some significant electricity bills.) One story I heard, and I don't know if this is true, is that uberbot was accounting for 20 to 30% of Betfair's server capacity at one point.</span></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span">The success of uberbot has led to a raft of competitors. There are now four to five syndicates running large automated botting (betting, geddit?) networks, with various strategies (automated arbitrage, statistical arbitrage, Duckworth Lewis related algorithms, etc.) And while, as far as I know, these are all nicely profitable, the easy days when three or four people could knock together a system that made them more than £1m a year, while the founders headed off to the pub, are probably over. </span></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span">Having been involved at the cross-section of the gambling and technology industries for over a decade, I am reasonably </span><i><span class="Apple-style-span">au fait</span></i><span class="Apple-style-span"> with how some of these bots worked. Perhaps taking a single example of a - for a time - very profitable algorithm would be instructive. What I am about to share was once a great secret, known to relatively few people, and which may have generated significant sums. But knowledge spreads, and the more people that know about a strategy, and the more people execute it, the less profitable it will be. This strategy is so simple, and so copyable that BETDAQ themselves run it on their markets! (Personally, I don't think the exchange should be engaged in simple arbitrage, but that's another story.) Many (smart) people who decide to write a Betfair bot stumble across this idea, then spend time implementing it, only to discover they make, alas, no money. So, don't think you can just reimplement this and retire rich!</span></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span">What's the big idea?</span></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span">Well, let's start by looking at a simple two outcome market; literally a two horse race. Let's choose some random American Football match: the </span><i><span class="Apple-style-span">Miami Dolphins</span></i><span class="Apple-style-span"> versus the </span><i><span class="Apple-style-span">New Orleans Saints</span></i><span class="Apple-style-span">. Now, Betfair displays the market like this:</span></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px;"><div style="margin-top: 0px; margin-bottom: 0px;"><table id="xvdu" class="" style="line-height: inherit; border-collapse: collapse; color: rgb(0, 0, 0);" width="40%" border="1" cellpadding="3" cellspacing="0"><tbody><tr style="text-align: left;"><td><span class="Apple-style-span"><br /></span></td><td width="33.333333333333336%"><span class="Apple-style-span">Back</span></td><td width="33.333333333333336%"><span class="Apple-style-span">Lay</span></td></tr><tr style="text-align: left;"><td><span class="Apple-style-span">Miami Dolphins</span></td><td width="33.333333333333336%"><span class="Apple-style-span">2.1</span></td><td width="33.333333333333336%"><span class="Apple-style-span">2.4</span></td></tr><tr style="text-align: left;"><td><span class="Apple-style-span">New Orleans Saints</span></td><td width="33.333333333333336%"><span class="Apple-style-span">1.5</span></td><td width="33.333333333333336%"><span class="Apple-style-span">1.8</span></td></tr></tbody></table></div><span class="Apple-style-span"><br /></span></div><span class="Apple-style-span">(Regular Betfair bettors will notice I've simplified it - taking out all the non-core elements.)</span><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span">Focussing </span><b><span class="Apple-style-span">just</span></b><span class="Apple-style-span"> on the top, Miami Dolphins line. I have the choice of betting on the Miami Dolphins to win (i.e., I can back them) at 2.1. This means, if I put £1 down, I get £2.1 back if they win - a profit of £1.1, or lose £1 if the Dolphins lose. Likewise, I can bet on the Miami Dolphins to lose (i.e., I can lay them) at 2.4. When I lay something, I am acting as bookmaker. Somebody else is backing the Miami Dolphins to win. In other words: if they bet £1 and I have laid the Miami Dolphins at 2.4, then I owe them £1.4 if they win. And if the Dolphins lose, then I make a profit of £1.</span></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span">Now, there is one thing here that is very interesting. A bet on the Miami Dolphins to win is *exactly* the same as a bet on the New Orleans Saints to lose. And backing the Saints is the same as laying the Dolphins.</span></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span">Got that?</span></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span">So, if I want to bet on the Dolphins to win, should I take the back Dolphins odds, or should I take the lay Saints odds? Well, let's convert these numbers to raw implied probabilities, to see which one offers the better value.</span></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span">Miami Dolphins - chance of winning, based on back price = 1 / 2.1 = 47.6%</span></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span">New Orleans - chance of winning, based on lay price = 1/1.8 = 55.6%</span></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span">Clear yet? Perhaps not. Let's invert the New Orleans number so it is comparable with the Miami Dolphins win number. </span></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span">New Orleans - chance of losing, based on lay price = 1 - 55.6% = 44.4%</span></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span">So, if you want to bet on the Miami Dolphins winning, you can either back them at a 47.6% probability, or at a 44.4% probability. Which is better? Well, given you are paid 100% on win (as opposed to 0% on lose), then you want to bet on the option with the lowest probability. To bet on the the Dolphins, you should lay the New Orleans Saints.</span></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span">But what has this to do with arbitrage? Well, you can put a new bet in the Betfair system, that will be *better* than the best current back price. And if someone takes your bet, you can they 'lay it off', generating a guaranteed profit. So, we could offer to lay the Miami Dolphins at 2.12. (This would mean that the Betfair odds table would look like this.)</span></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px;"><div style="margin-top: 0px; margin-bottom: 0px;"></div><div style="margin-top: 0px; margin-bottom: 0px;"><div style="margin-top: 0px; margin-bottom: 0px;"><div style="margin-top: 0px; margin-bottom: 0px;"><table id="kzw9" class="" style="line-height: inherit; border-collapse: collapse; color: rgb(0, 0, 0);" width="40%" border="1" cellpadding="3" cellspacing="0"><tbody><tr style="text-align: left;"><td><span><span class="Apple-style-span"><br /></span></span></td><td width="33.333333333333336%"><span><span class="Apple-style-span">Back</span></span></td><td width="33.333333333333336%"><span><span class="Apple-style-span">Lay</span></span></td></tr><tr style="text-align: left;"><td><span><span class="Apple-style-span">Miami Dolphins</span></span></td><td width="33.333333333333336%"><span><span class="Apple-style-span">2.12</span></span></td><td width="33.333333333333336%"><span><span class="Apple-style-span">2.4</span></span></td></tr><tr style="text-align: left;"><td><span><span class="Apple-style-span">New Orleans Saints</span></span></td><td width="33.333333333333336%"><span><span class="Apple-style-span">1.5</span></span></td><td width="33.333333333333336%"><span><span class="Apple-style-span">1.8</span></span></td></tr></tbody></table></div></div></div></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span">If someone took this bet, we would then bet an equivalent amount on the New Orleans Saints to lose (laying at 1.8), and we'd capture a small but very real profit.</span></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span">Of course, to do this, you need to be constantly monitoring hundreds of different markets. And if the prices offered changed (so, for example, it was no longer possible to lay the Saints at 1.8), then you'd want to pull your bets. Similarly, you'd need to make sure that as soon as someone took your offered 2.12, you lay it off as soon as possible - otherwise you'd run the risk of someone taking the lay Saints price before you got a chance to.</span></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span">This system works with multiple selection markets too - although the mathematics start becoming a little more complex. The bad news, though, is that you're unlikely to make any money with it. Because lots and lots of people, with expensive and powerful computer systems, are already running these models, scraping pennies up from markets. The ubiquity of these algorithms can easily be seen by looking at the relative over-round (and under-round) on various events. If the over-round is equal to 1/under-round (or vice-versa) then you have </span><i><span class="Apple-style-span">exactly </span></i><span class="Apple-style-span">the same take laying the whole market as backing it. (There are very often differences, but the gap is usually so small, it is impossible to benefit because you are forced to bet in certain increments, making exact matches harder than they might be.) This is a characteristic of a market where the differences between back and lay prices have been well and truly arbitraged out. Look at the list below:</span></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px;"><div id="noda" style="margin-top: 0px; margin-bottom: 0px; text-align: left;"><span class="Apple-style-span"><img src="https://docs.google.com/File?id=ddz6xfsk_47k7t5mmfg_b" style="width: 428px; height: 233px;" /></span></div><span class="Apple-style-span"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span">(Essentially, any situation where the theoretical opportunity is less than 1% is not going to be exploitable. I am slightly surprised to see that there is an opportunity to make a small amount of money in the Birmingham versus Wolves game. Of course, just because you put a riskless bet into the system, doesn't mean someone is going to take you up on it.)</span></div><span class="Apple-style-span"><br /></span><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span">That this system is - broadly - un-exploitable should not be disheartening. This blog is about giving you the tools to create your own bots, and to understand the interaction of technology and gambling. There are perhaps 1,000 hedge funds with profitable quantitative trading strategies. There is no reason why there cannot be the same opportunities in the betting markets (although the sums involved will be, inevitably rather smaller).</span></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px;"><span class="Apple-style-span">Anyway... till next post...</span></div></span>Unknownnoreply@blogger.com75tag:blogger.com,1999:blog-6951634702207332175.post-86068553323592005022010-02-04T00:43:00.001-08:002010-02-05T15:48:53.129-08:00Making Money Gambling<span style="font-family: verdana;font-family:verdana;font-size:100%;" >Many more people lose money gambling than make money. The equation is pretty simple, and makes salutory reading:</span><div style="font-family: verdana;font-family:arial;" ><span style="font-size:100%;"><br /></span></div><div style="font-family: verdana;font-family:arial;" ><span style="font-size:100%;">Money Gambled </span></div><div style="font-family: verdana;font-family:arial;" ><span style="font-size:100%;">-</span></div><div style="font-family: verdana;font-family:arial;" ><span style="font-size:100%;">Bookmakers' and Betfair's costs</span></div><div style="font-family: verdana;font-family:arial;" ><span style="font-size:100%;">Bookmakers' and Betfair's profits</span></div><div style="font-family: verdana;font-family:arial;" ><span style="font-size:100%;">=</span></div><div style="font-family: verdana;font-family:arial;" ><span style="font-size:100%;">Money Won by Punters</span></div><div style="font-family: verdana;font-family:arial;" ><span style="font-size:100%;"><br /></span></div><div style="font-family: verdana;font-family:arial;" ><span style="font-size:100%;">The numbers in the middle are large: Both Ladbrokes and William Hill have huge chains of stores and each has <b>more than 16,000 employees</b> (albeit not all in the fixed odds business). Betfair and the like have large marketing budgets. And there are hundreds of smaller bookmakers - from on-course betting, to the Tote, to Australian and Swedish imports.</span></div><div style="font-family: verdana;font-family:arial;" ><span style="font-size:100%;"><br /></span></div><div style="font-family: verdana;font-family:arial;" ><span style="font-size:100%;">There are a host of small businesses that make money off the bookmakers and betting exchanges as suppliers of technology: I might mention Finsoft or Orbis or Betgenius. Plus the spend with technology suppliers like IBM or HP is pretty enormous - I heard Betfair spends something like £80m a year on technology alone. </span></div><div style="font-family: verdana;font-family:arial;" ><span style="font-size:100%;"><br /></span></div><div style="font-family: verdana;font-family:arial;" ><span style="font-size:100%;">And then there are the profits made by these businesses, Betfair is rumoured to make hundreds of millions of pounds of pre-tax profit, William Hill and Ladbrokes probably made £100m last year, and even Paddy Power made £50 or so.</span></div><div style="font-family: verdana;font-family:arial;" ><span style="font-size:100%;"><br /></span></div><div style="font-family: verdana;font-family:arial;" ><span style="font-size:100%;">Basically, there are a lot of people who are better placed to hoover up the profits from punters' losing bets than you or me.</span></div><div style="font-family: verdana;font-family:arial;" ><span style="font-size:100%;"><br /></span></div><div style="font-family: verdana;font-family:arial;" ><span style="font-size:100%;">But that is not to say it is impossible. Gambling is like financial services - where the profits made by investing go first to the investment banks and stock exchanges and traders, and only eventually to the poor punters' saving for their retirements. And like financial services, the rise of technology is democratising gambling. It used to be that punters' could only bet with Ladbrokes or Hills, and had to live with 17% over-rounds. (In other words, you were placing bets at 17% below NAV. You have to be pretty good to make money in that environment.) The only market makers were the bookmakers' themselves. And if you ever did prove yourself to be a successful gambler... well, then bookmakers simply wouldn't take your bets. (I know one professional gambler who would spend the first half of every day cycling around 30 to 40 bookmakers placing small bets in cash to avoid detection.)</span></div><div style="font-family: verdana;font-family:arial;" ><span style="font-size:100%;"><br /></span></div><div style="font-family: verdana;font-family:arial;" ><span style="font-size:100%;">The rise of Betfair and odds comparison engines like Oddschecker and Bestbetting has enormously democratised things. (BTW, it's no coincidence that the bookmakers' use Bestbetting themselves - it has a significantly better odds comparison engine than Oddschecker.) The over-round charged on - say - UK Premiership football has fallen from double digits to mid-single. Bookmaker profits have compressed sharply. Volumes have risen commensurately. You want to know why bookmakers push you towards multiples bets: it's because over-round multiplies up. So, a bet on Chelsea to win 1-0, and John Terry to score first, has twice the margin of a bet on Chelsea alone.</span></div><div style="font-family: verdana;font-family:arial;" ><span style="font-size:100%;"><br /></span></div><div style="font-family: verdana;font-family:arial;" ><span style="font-size:100%;">So, faced with this brave new world, armed with access to Oddschecker, Betfair and Betdaq - how do you make money?</span></div><div style="font-family: verdana;font-family:arial;" ><span style="font-size:100%;"><br /></span></div><div style="font-family: verdana;font-family:arial;" ><span style="font-size:100%;">Well, let us first define the man (for it is usually a man) who will *lose* money. Let us not forget that every penny you make as a gambler will be a penny someone else has lost. He will have a view: someone will have tipped him a horse that he is sure will win. Or he wants to back England in the football because he always backs England at home. Or he's round a mate's house and the rugby is on, and it'll be a bit more interesting if he's got some money on it. Or he has a compulsive gambling habit, and he thinks this one winner he feels really good about... </span></div><div style="font-family: verdana;font-family:arial;" ><span style="font-size:100%;"><br /></span></div><div style="font-family: verdana;font-family:arial;" ><span style="font-size:100%;">But one thing dominate's this man's thought process: he wants to back the winner. He is odds insensitive. He'll almost certainly be backing something, rather than laying it.</span></div><div style="font-family: verdana;font-family:arial;" ><span style="font-size:100%;"><br /></span></div><div style="font-family: verdana;font-family:arial;" ><span style="font-size:100%;">And, of course, he has no idea what a balanced book is, nor does he know what the NAV of his positions is. He may have - once or twice - made what he considered a 'value bet', a synonym for a long odds one. But the gambler is really after the thrill of betting and racing. He might as well be at the casino, or putting money on the National Lottery.</span></div><div style="font-family: verdana;font-family:arial;" ><span style="font-size:100%;"><br /></span></div><div style="font-family: verdana;font-family:arial;" ><span style="font-size:100%;">(Of course, he'll probably not recognise these symptoms in himself. He may boast of his extensive knowledge of the form book. Or he might swear by a certain racing tipster. One thing I can absolutely guarantee: he will have no idea whether he is up or down. He'll say he 'breaks even'.)</span></div><div style="font-family: verdana;font-family:arial;" ><span style="font-size:100%;"><br /></span></div><div style="font-family: verdana;font-family:arial;" ><span style="font-size:100%;">And people like this need to lose billions of pounds, to pay for the tens of thousands of employees of bookmakers' and the sport of racing and the advertisements on Sky TV and the shareholders of Betfair. You, semi-professional or merely interested gambler, need to recognise where and how you will make money. And you need to recognise that this is not going to be easy.</span></div><div style="font-family: verdana;font-family:arial;" ><span style="font-size:100%;"><br /></span></div><div style="font-family: verdana;font-family:arial;" ><span style="font-size:100%;">In the next post (or the one after that, or the one after that...), I'll run down four broad strategies for making money. None of them are work, or risk, free. But they all offer you a small, real, opportunity to make money. And, hey, with the right tools in your armoury, you might invent the next uberbot.</span></div>Unknownnoreply@blogger.com7tag:blogger.com,1999:blog-6951634702207332175.post-47072729508946719462010-02-01T09:01:00.000-08:002010-02-04T01:40:28.245-08:00Automating NAVs<span class="Apple-style-span" style=" ;font-family:Verdana;font-size:13px;"><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">In the previous piece, I showed how to calculate your NAV for a given market. It was theoretical rather than practical: in the real world, you'll want a spreadsheet that looks like this:</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><div id="t5l0" style="margin-top: 0px; margin-bottom: 0px; text-align: left; "><span class="Apple-style-span" style="font-size: small;"><img src="https://docs.google.com/File?id=ddz6xfsk_41fmppj3fn_b" style="width: 648px; height: 459px; " /></span></div><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">If you want to download this sheet, you can get it </span><a href="http://automatingbetfair.s3.amazonaws.com/simple%20nav%20sheet.xls"><span class="Apple-style-span" style="font-size: small;">here</span></a><span class="Apple-style-span" style="font-size: small;">. But I'd advise you to build your own. (Actually, I'd advise you develop a more sophisticated one - but this one will do for now.) Now, let us take a typical Betfair market:</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><div id="ai24" style="margin-top: 0px; margin-bottom: 0px; text-align: left; "><span class="Apple-style-span" style="font-size: small;"><img src="https://docs.google.com/File?id=ddz6xfsk_42g68kpccz_b" style="width: 648px; height: 413.316px; " /></span></div><span class="Apple-style-span" style="font-size: small;"><br /></span></div><span class="Apple-style-span" style="font-size: small;">Now, copying us across this data to our Excel sheet gives us:</span><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><div id="suni" style="margin-top: 0px; margin-bottom: 0px; text-align: left; "><span class="Apple-style-span" style="font-size: small;"><img src="https://docs.google.com/File?id=ddz6xfsk_43hfjnbnh2_b" style="width: 648px; height: 407.099px; " /></span></div><span class="Apple-style-span" style="font-size: small;"><br /></span></div><span class="Apple-style-span" style="font-size: small;">Wow: positive £80.85 - not bad :-) That said, according to the market, there is at least a 45% chance I will lose £177! (This is a classic example of an unbalanced book - and there are trading strategies that seek to, as best as possible, maintain your overall NAV, while balancing your book somewhat. To put in context, a perfectly balanced book with a NAV of £80.85 would have return £80.85 irrespective of the outcome. Sometimes you'll want balanced books, and sometimes you won't.)</span><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">But while it's good to be able to generate NAVs, it is pain creating them manually. What we want to be able to do is take what we learnt a few posts ago and automate the procedure. At this point I'm torn: do I continue to use Excel, or do I switch to Resolver? Because I'm lazy, and automating this in Resolver will be clearer (for you) and take less time (for me), I'll make switch. </span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">First things first: I need to recreate the sheet I had in Excel. There is one additional step we should take: </span><b><i><span class="Apple-style-span" style="font-size: small;">right click on first row selector, and choose "Set Header Row"</span></i></b><span class="Apple-style-span" style="font-size: small;">:</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><div id="gvzw" style="margin-top: 0px; margin-bottom: 0px; text-align: left; "><span class="Apple-style-span" style="font-size: small;"><img src="https://docs.google.com/File?id=ddz6xfsk_44g2vg5sfn_b" style="width: 648px; height: 485.594px; " /></span></div><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><b><i><span class="Apple-style-span" style="font-size: small;">Now, do the same with selecting the 'A' column, and set the header column</span></i></b><span class="Apple-style-span" style="font-size: small;">. This allows us to reference cells by meaningful names rather than by 'A3', etc. So, we can refer to ['Odds', 'Conservatives'] for example. Once you've used header rows and columns extensively, you'll never go back :-)</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">Let's do a couple of other things. Let's call the sheet 'NAV'. (In the same way we do in Excel, by double clicking on the Sheet1 tab at the bottom, and changing it to NAV). Then add the following:</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><div id="pn:s" style="margin-top: 0px; margin-bottom: 0px; text-align: left; "><span class="Apple-style-span" style="font-size: small;"><img src="https://docs.google.com/File?id=ddz6xfsk_45hdwsnvdm_b" style="width: 648px; height: 912.058px; " /></span></div><span class="Apple-style-span" style="font-size: small;"><br /></span></div><span class="Apple-style-span" style="font-size: small;">The code is pretty self explanatory (and if you don't feel like typing it in, you can download a slightly more sophisticated version of it </span><a href="http://automatingbetfair.s3.amazonaws.com/automated%20NAV%20generator.rsl"><span class="Apple-style-span" style="font-size: small;">here</span></a><span class="Apple-style-span" style="font-size: small;">, and remember you will need the Betfair libraries from </span><a href="http://automatingbetfair.s3.amazonaws.com/betfair%20resolver.zip"><span class="Apple-style-span" style="font-size: small;">here</span></a><span class="Apple-style-span" style="font-size: small;">) - but I'll explain it anyway. The first section ('Pre-constants user code') basically sets up the connection to Betfair, and creates the objects we'll deal with. The grand-daddy of these is the </span><i><span class="Apple-style-span" style="font-size: small;">betfairGateway </span></i><span class="Apple-style-span" style="font-size: small;">which is our logged in connection. We get other objects - relating to markets or P&Ls - from this parent.<br /></span><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">We create two more objects from this gateway object - a market object (</span><i><span class="Apple-style-span" style="font-size: small;">betfairMarket</span></i><span class="Apple-style-span" style="font-size: small;">) and a P&L object (</span><i><span class="Apple-style-span" style="font-size: small;">betfairPL</span></i><span class="Apple-style-span" style="font-size: small;">). These objects contain details of runners and prices (</span><i><span class="Apple-style-span" style="font-size: small;">betfairMarket</span></i><span class="Apple-style-span" style="font-size: small;">) and our positions on the market (</span><i><span class="Apple-style-span" style="font-size: small;">betfairPL</span></i><span class="Apple-style-span" style="font-size: small;">).</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">The 'Pre-formula user code' section does the formatting and display of the data in these objects. </span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-family:'Courier New';"><span class="Apple-style-span" style="font-size: small;">row = 2</span></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-family:'Courier New';"><span class="Apple-style-span" style="font-size: small;">for selection in betfairMarket.GetRunners():</span></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-family:'Courier New';"><span class="Apple-style-span" style="font-size: small;"> NAV['Selection', row] = str(selection)</span></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-family:'Courier New';"><span class="Apple-style-span" style="font-size: small;"> NAV['Odds', row] = selection.Back</span></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-family:'Courier New';"><span class="Apple-style-span" style="font-size: small;"> row += 1</span></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "> </div><span class="Apple-style-span" style="font-size: small;">Firstly, we set the first row that we will copy data into. Then we iterate over the runner objects (GetRunners() returns an array of runner objects).<br /></span><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">For each of these selections, we put into the NAV worksheet, in the 'Selection' column, the name of the selection (str(selection)), and then the Back price (selection.Back). We then increment the row number.</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-family:'Courier New';"><span class="Apple-style-span" style="font-size: small;">for item in betfairPL:</span></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-family:'Courier New';"><span class="Apple-style-span" style="font-size: small;"> NAV['Outcome', str(item.selectionName)] = item.ifWin</span></span></div></div><span class="Apple-style-span" style="font-size: small;"><br /></span><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">We then iterate over the objects in the betfairPL objects, putting the outcome (item.ifWin) in the appropriate cell. (One of Resolver One's real strength's is the ability to dynamically reference cells by their names.)</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-family:'Courier New';"><span class="Apple-style-span" style="font-size: small;">for row in NAV.ContentRows:</span></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-family:'Courier New';"><span class="Apple-style-span" style="font-size: small;"> row['Raw IP'] = 1 / row['Odds']</span></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">Now we iterate over each row (ContentRows is rows excluding the Header Row we set earlier), filling in the 'Raw IP' cell with the calculated raw implied percentage.</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-family:'Courier New';"><span class="Apple-style-span" style="font-size: small;">totalIP = SUM(NAV.Cols['Raw IP'])</span></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">Now, we sum the column to see how much we need to deflate individual percentages.</span></div></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-family:'Courier New';"><span class="Apple-style-span" style="font-size: small;">for row in NAV.ContentRows:</span></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-family:'Courier New';"><span class="Apple-style-span" style="font-size: small;"> row['IP'] = row['Raw IP'] / totalIP</span></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-family:'Courier New';"><span class="Apple-style-span" style="font-size: small;"> row['NAV'] = row['IP'] * row['Outcome']</span></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">This should be pretty obvious now: we're iterating over the rows again, filling in the Implied Percentage (IP) and NAV columns.</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-family:'Courier New';"><span class="Apple-style-span" style="font-size: small;">rowNum = NAV.MaxRow + 2</span></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-family:'Courier New';"><span class="Apple-style-span" style="font-size: small;">NAV[1, rowNum] = 'Total'</span></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-family:'Courier New';"><span class="Apple-style-span" style="font-size: small;">NAV.Rows[rowNum].Bold = True</span></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-family:'Courier New';"><span class="Apple-style-span" style="font-size: small;">NAV['NAV', rowNum] = SUM(NAV.Cols['NAV'])</span></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">Finally, let's add a pretty Total row and calculation at the bottom.</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">Well - that's it for now. You now have an automated NAV calculator for any given market. </span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div><br /></div></div></span>Unknownnoreply@blogger.com6tag:blogger.com,1999:blog-6951634702207332175.post-65921910632279541562010-01-31T11:16:00.001-08:002010-02-02T00:52:18.157-08:00Net Asset Values<span class="Apple-style-span" style=" ;font-family:Verdana;font-size:13px;"><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">When you do a lot of gambling, it is useful to know whether you are up, or down, in a market. Because individual markets can be complex, gamblers tend to talk about whether they are 'in the green' - i.e. whether they are profitable on a market, irrespective of the outcome. But this is simplistic - what you need to be able to do is to mark you positions to market, or, as I prefer to call it, generate a Net Asset Value or NAV.<br /><br />This is a fairly simple concept: but understanding whether certain positions will be positive or negative to your NAV will be a core component for building trading systems. (Now, the NAV model we're building here is pretty simple - and later we will bring in more complex elements, adjusting for commission and the like - but the concept of the NAV will help you score your trading, and build better systems in the future.)<br /><br />OK. Let's say there is a market for a football match: say England versus Germany. There are three possible selections (outcomes): England, Germany, and Draw. The current odds for each are:<br /><br />England: 2.36<br />Germany: 3.05<br />Draw: 3.35<br /></span></div><span class="Apple-style-span" style="font-size: small;"><br />And let us assume that - in the event of an England win, we make £23; if Germany wins, we lose £15, and if it's a draw we lose £3. So - are we up or done on this market? Well, the simplistic answer is - we're up if England wins, and down otherwise! But that's not the right way to look at this. We need to convert those odds into percentage probabilities, and then weight the outcomes.<br /><br />Each odd is - in effect - a measure of probability. If the odds on England are 2.36, that means the (unadjusted) probability is 42.4%. (We get the probability by dividing 1 by the decimal odds. So England is 1 / 2.36 = 0.424 = 42.4%.) So the probabilities the odds are telling us are:<br /><br />England: 42.4%<br />Germany: 32.8%<br />Draw: 29.9%<br />---<br />Total: 105.0%<br /><br />Now, obviously, the true probabilities have to add up to 100% - so we need to divide every probibility by 105% to get a total that adds up to 100%. This tells us exactly what probabilities the gambling markets expect:<br /></span><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">England: 40.4%</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">Germany: 31.2%</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">Draw: 28.4%</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">---</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">Total: 100.0%</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">To see our expected outcomes, we need to multiply those percentages by the amounts we win on each outcome:</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">England: 40.4% * £23 = £9.28</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">Germany: 31.2% * £-15 = £-4.68</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">Draw: 28.4% * £-3 = £-0.85</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">---</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">NAV: £3.74</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">If we have a positive NAV on a market, we have a positive likely outcome. Of course, things get a little more complex with the concepts of balanced books, and the like. But if you want to 'score' your positions now, you have no better tool in your armoury than the NAV. </span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">In our next post, we'll draw together NAVs with the ability to get prices out of Betfair, so you'll be able to see - on a market by market basis - where you're winning, and where you're losing.</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><br /></div></span>Unknownnoreply@blogger.com8tag:blogger.com,1999:blog-6951634702207332175.post-17234715635130467012010-01-31T11:07:00.000-08:002010-02-01T09:17:38.824-08:00Getting Prices from Betfair<span class="Apple-style-span" style=" ;font-family:Verdana;font-size:13px;"><span class="Apple-style-span" style="font-size: small;">Betfair uses a web services system to allow people to query prices and even place bets (although we'll cover that part later). What this means is that your program opens a special web page that returns an XML formatted response. With appropriate wrappers we can easily get useful information into our programs, and make trading decisions based on that.<br /><br />Now, we don't need to worry too much about the technical details right now, beyond a few important points. Firstly, this is a 'pull' service. Your application queries the Betfair servers - so you never have a truly live price, you only have the price that was valid last time you read the page. Betfair will not tell you that a bet of yours has been taken, or that the price has moved away from you. Therefore, in fast moving markets, you'll want to have your scripts poll the server every 15 to 30 seconds. For slower markets, like UK election constituency betting, you can probably get away with requests every 20 minutes or so. Secondly, if you are going to poll the server regularly (or, indeed, automatically trade), then you will need to spend 200GBP/month for a more expensive Betfair API account.<br /><br />With this is mind, there are two ways to get prices from Betfair: the hard way and the easy way. The hard way involves writing our own libraries that interact with Betfair's servers. The easy way means taking off the shelf libraries, and using them instead. For now, we'll take the former approach - although in a later piece, well probably do something a ittle more sophisticated.<br /><br />If you want to use Excel, then let's start with the example spreadsheet from Betfair, which can be downloaded from </span><a href="http://bdp.betfair.com/index.php?option=com_weblinks&task=view&catid=59&id=9"><span class="Apple-style-span" style="font-size: small;">here</span></a><span class="Apple-style-span" style="font-size: small;">. Alternatively, for Resolver you'll need the Betfair libraries which can be got </span><a href="http://automatingbetfair.s3.amazonaws.com/betfair%20resolver.zip"><span class="Apple-style-span" style="font-size: small;">here</span></a><span class="Apple-style-span" style="font-size: small;">. I haven't used the Python Betfair library (http://code.google.com/p/pythonbetfairlibrary/), but they might also be worth looking at.<br /><br /></span><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">One final bit of background, before we pull out the prices. Betfair divides the world into markets and selections (or runners). So, the 3:30 at Kempton Park might have a two different markets: winner and placed. Each of these markets has its own ID: in Betfair terminology this is the marketID. Inside each market, each selection - whether the horse </span><i><span class="Apple-style-span" style="font-size: small;">Dancing Brave</span></i><span class="Apple-style-span" style="font-size: small;"> or </span><i><span class="Apple-style-span" style="font-size: small;">Machester United</span></i><span class="Apple-style-span" style="font-size: small;"> or </span><i><span class="Apple-style-span" style="font-size: small;">John Terry</span></i><span class="Apple-style-span" style="font-size: small;"> or </span><i><span class="Apple-style-span" style="font-size: small;">The Conservative Party</span></i><span class="Apple-style-span" style="font-size: small;"> - has its own code, the selectionID. </span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">The easiest way to get the marketID (although not the way you'll use in the longer term) is to login to the Betfair web site, navigate to the appropriate market, and then click on the rules tab on the right. You now get a screen like this:</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><div id="w6o2" style="margin-top: 0px; margin-bottom: 0px; text-align: left; "><span class="Apple-style-span" style="font-size: small;"><img src="https://docs.google.com/File?id=ddz6xfsk_35fbk4txdx_b" style="width: 648px; height: 537.396px; " /></span></div> </div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">The bit circled in red is the marketID. </span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">(A lot of the information in here is gleaned from the - soon to be an excellent resource I'm sure - </span><a href="http://bettingonresolverone.com/?p=15"><span class="Apple-style-span" style="font-size: small;">Betting on Resolver One</span></a><span class="Apple-style-span" style="font-size: small;"> blog.)</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">Right, let's get started. From Resolver One, you need to put the Betfair libraries you downloaded above in the same directory where you're going to save files. Now, in the 'Pre-constants user code' section of the code box, enter the following:</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-family:'Courier New';"><span class="Apple-style-span" style="font-size: small;">import betfair</span></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-family:'Courier New';"><span class="Apple-style-span" style="font-size: small;">betfairGateway = betfair.BetfairGateway('yourusername', 'yourpassword', productId=82)</span></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><i><span class="Apple-style-span" style="font-size: small;">(This imports the Betfair library, then creates a connection to Betfair using your username and password. The productId of 82 tells Betfair we're using the free API.)</span></i></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div></div><span class="Apple-style-span" style="font-size: small;">Now hit F9 to recalculate. If you don't get any errors, and an 'OK' is printed in the status window at the bottom - well, congratulations, you've just programatically connected to Betfair. Let's be a bit more sophisticated. Add the following (below the code above):<br /></span><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-family:'Courier New';"><span class="Apple-style-span" style="font-size: small;">betfairMarket = betfairGateway.GetMarketById(2725554)</span></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-family:'Courier New';"><span class="Apple-style-span" style="font-size: small;">print betfairMarket.GetRunners()</span></span></div></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><i><span class="Apple-style-span" style="font-size: small;">(This creates an object that contains details of a single Betfair market, and then prints the list of runners.)</span></i></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><span class="Apple-style-span" style="font-size: small;">Hit F9 again... and now, at the bottom of the screen, you see the three 'runners' in the UK General Election Most Seats market: [Conservatives, Labour, Liberal Democrats].<br /></span><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">(If you're not - yet - a Python guru, this is a Python list. Python does lists, arrays and dictionaries very well. Once you've used Python, even just a little bit, you will never return to VBA or PHP or Java ever again...) The screen below shows what you should see:</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><div id="tz0z" style="margin-top: 0px; margin-bottom: 0px; text-align: left; "><span class="Apple-style-span" style="font-size: small;"><img src="https://docs.google.com/File?id=ddz6xfsk_36cstffrpx_b" style="width: 648px; height: 541.098px; " /></span></div><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">Let's get a little more creative, and get that pricing data out. Delete the line printing the runners, and add the following instead:</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-family:'Courier New';"><span class="Apple-style-span" style="font-size: small;">for selection in betfairMarket.GetRunners():</span></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-family:'Courier New';"><span class="Apple-tab-span" style="white-space:pre"><span class="Apple-style-span" style="font-size: small;"> </span></span><span class="Apple-style-span" style="font-size: small;">print selection.Name, selection.Back, selection.Lay</span></span></div></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">Hit F9 to recalculate again, and now you'll see something like this:</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">OK</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">OK</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">OK</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">Conservatives 1.13 1.14</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">Labour 8.2 8.6</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">Liberal Democrats 220.0 310.0</span></div></div><span class="Apple-style-span" style="font-size: small;"><br /></span><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">The three 'OK's are just the library printing out status messages. The rest is the important bit. Now, pat yourself on the back - you've gotten prices and runners/selections into Resolver. Of course, you'll still want to get them into the grid. But we'll cover that in a future posting.</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">Let's now do this in Excel.</span></div><span class="Apple-style-span" style="font-size: small;"><br /></span><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">The good news with Excel is that getting a grid with prices in is easy. I'm assuming you're running Excel 2007. Running the Betfair Excel spreadsheet requires two dependancies to be installed: Microsoft SOAP toolkit 3.0 and Microsoft XML Library (Service Pack 2). You can get them </span><a href="http://www.microsoft.com/downloads/info.aspx?na=90&p=&SrcDisplayLang=en&SrcCategoryId=&SrcFamilyId=C943C0DD-CEEC-4088-9753-86F052EC8450&u=http%3a%2f%2fdownload.microsoft.com%2fdownload%2f2%2fe%2f0%2f2e068a11-9ef7-45f5-820f-89573d7c4939%2fsoapsdk.exe"><span class="Apple-style-span" style="font-size: small;">here</span></a><span class="Apple-style-span" style="font-size: small;"> and </span><a href="http://www.microsoft.com/downloads/info.aspx?na=46&p=1&SrcDisplayLang=en&SrcCategoryId=&SrcFamilyId=3144b72b-b4f2-46da-b4b6-c5d7485f2b42&u=http%3a%2f%2fdownload.microsoft.com%2fdownload%2f9%2f6%2f5%2f9657c01e-107f-409c-baac-7d249561629c%2fmsxml.msi"><span class="Apple-style-span" style="font-size: small;">here</span></a><span class="Apple-style-span" style="font-size: small;">.</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">Now, restart Excel, and load the spreadsheet you downloaded from Betfair. Your screen should look something like this:</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><div id="c99o" style="margin-top: 0px; margin-bottom: 0px; text-align: left; "><span class="Apple-style-span" style="font-size: small;"><img src="https://docs.google.com/File?id=ddz6xfsk_37g55pv8hc_b" style="width: 648px; height: 490.629px; " /></span></div><span class="Apple-style-span" style="font-size: small;"><br /></span></div><span class="Apple-style-span" style="font-size: small;">Enter your username and passwords in the appropriate cells, and change the product ID from 0 to 82. (82 is the number for the free, read-only, API.)</span><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">Now, click on 'Select Market' on the right. A dialog will open. You can now choose a market; let's choose 'Politics', 'UK', 'Next General Election', 'Most Seats'.</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">A new tab opens - this gives you the prices of all the selections. In fact, it gives you a rather attractive screen with all the prices and amounts available. A lot of your work is already done.</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><div id="hnih" style="margin-top: 0px; margin-bottom: 0px; text-align: left; "><span class="Apple-style-span" style="font-size: small;"><img src="https://docs.google.com/File?id=ddz6xfsk_38gbp92bft_b" style="width: 648px; height: 490.629px; " /></span></div><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">However, this spreadsheet also demonstrates the disadvantages of the Betfair Excel spreadsheet. We have a nice, pretty display of the prices available. But manipulating these, or indeed, showing multiple selections across different markets, is hard. The Python code we produced was simple. Using the Resolver One grid to display things is pretty simple. It's the best of both worlds. Don't worry Excel gurus - we'll be doing plenty of stuff in Excel over the course of these blog posts. We'll delve into VBA, and write complex multi-line formulae. But for education and edification, we need to put together clean and readable examples. And we probably need to do things from the ground up, rather than relying on what the Betfair developers think we need. (It would also be nice to put together a clean library that allows seamless access to Betfair, Betdaq and other providers of gambling liquidity.) And that's why a lot of what we do will be in Resolver One and Python.</span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;"><br /></span></div><div style="margin-top: 0px; margin-bottom: 0px; "><span class="Apple-style-span" style="font-size: small;">Till next post...</span></div><div><br /></div></span>Unknownnoreply@blogger.com79tag:blogger.com,1999:blog-6951634702207332175.post-3972163171155947672010-01-31T11:04:00.000-08:002010-01-31T11:05:27.467-08:00First Post<span class="Apple-style-span" style="font-family: Verdana; font-size: 13px; "><div style="margin-top: 0px; margin-bottom: 0px; ">Let me tell you what this blog is about - it's about linking up programming, spreadsheets and gambling sites like <a href="http://betfair.com">Betfair</a>, <a href="http://www.betdaq.com">Betdaq</a> and other sites where there is a public API. The hope is that I'll develop some automated trading application that will make me some money, and that I'll learn something.</div><div style="margin-top: 0px; margin-bottom: 0px; "><br /></div><div style="margin-top: 0px; margin-bottom: 0px; ">There are three automated trading applications I am keen to put together: (1) a simple automated market making application for relatively illiquid markets. Seeded with basically OK probabilities, it will attempt to maintain a balanced book. In particular, this will be used for the UK general election, where current volumes are modest, and there is little in the way of inside information. (2) something that uses Bayesian analysis to autotrade certain markets. The idea will be automatically 'train' a system to recognise stories (off an RSS feed) that should affect prices, and then get there ahead of human traders. In financial services, such systems already exist; I haven't seen anything like that in gambling. (3) A system that relies on a degree of mean reversion - so when prices move too quickly, particularly on just a single selection in a market, it supplies a small amount of liquidity, in the hope that it will take a small cut when prices stabilise. I may also do some cross-pricing/arbitrage between Betfair and Betdaq and the bookies - although I suspect anything that simple will have been already comprehensively done by others.</div><div style="margin-top: 0px; margin-bottom: 0px; "><br /></div><div style="margin-top: 0px; margin-bottom: 0px; ">What I'm not going to do is to apply any specific sporting knowledge or algorithms. I know plenty of professional gamblers that have their own proprietary cricket or football pricing models. I can't match that.</div><div style="margin-top: 0px; margin-bottom: 0px; "><br /></div><div style="margin-top: 0px; margin-bottom: 0px; ">As far as tools, I'll be mostly using Excel and Resolver One. The former because it is the <i>de facto </i>spreadsheet that everyone uses. The latter because it is much more programmable, and because Python is a much better language than VBA. (Resolver isn't much used by individuals, but is very popular with traders and quantitative analysts in the City. It's also only $99 for individual use - which makes it rather better value than Excel.)</div><div style="margin-top: 0px; margin-bottom: 0px; "><br /></div><div style="margin-top: 0px; margin-bottom: 0px; ">Next post: getting simple prices out of Betfair...</div><div><br /></div></span>Unknownnoreply@blogger.com12