Over the last couple of days I was playing with what is known as spread betting. Spread betting is not a type of investment. It is gambling. You make money if you predict where the stock market is going. It is as simple as that. However, unlike the traditional forms of stock market investment practices, in spread betting there is no CGT (capital gain tax). Which is excellent!
I’ve made some money and I’ve lost some too. In fact, I’ve made about 100 pounds in less then 10 minutes and then I lost half of them during the course of the entire day. This made me learn an important lesson and also made me think how to improve my strategy.
You see, I am not a spread betting expert and I have very little knowledge about the stock market in general. However, I’ve learned one thing – you do have to have some kind of strategy and really stick to it if you want to be successful. Also, you have to be prepared to lose. But if you have a good strategy then you have nothing to worry about. As long as your winnings are more then your losses then you should be fine.
I started doing spread betting out of interest. I have a couple of friends that do this as well so I though I might take on the game from a slightly different angel. After getting a feeling with my spread betting company (IG Index) I realized that I can make a lot better decisions if I have a better interface to their website, i.e. have more features that will allow me to move faster and decide faster. This is essential if you want to play on highly-volatile indices such as the FTSE100. So I decided to to write a greasemonkey patch for IG Index that gives me essentially more features.
// ==UserScript==
// @name IG Index Helper
// @namespace http://www.igindex.co.uk/
// @description IG Index Helper
// @include http://www.igindex.co.uk/*
// ==/UserScript==
// some globals
var is_jquery_loaded = false;
var is_engine_started = false;
// the data object
var data = {prices:[], times:0};
// prototype patch for avarage computation on arrays
Array.prototype.average = function() {
var av = 0;
var cnt = 0;
var len = this.length;
for (var i = 0; i < len; i++) {
var e = +this[i];
if (!e && this[i] !== 0 && this[i] !== '0') {
e--;
}
if (this[i] == e) {
av += e; cnt++;
}
}
return av/cnt;
}
// load jQuery
function load_jquery(callback) {
// build the jQuery script element
var scr_e = document.createElement('script');
scr_e.src = 'http://jquery.com/src/jquery-latest.js';
scr_e.type = 'text/javascript';
// add the jQuery script
document.getElementsByTagName('head')[0].appendChild(scr_e);
// check for jQuery
function check_for_jquery() {
if(typeof unsafeWindow.jQuery == 'undefined') {
window.setTimeout(check_for_jquery, 100);
} else {
is_jquery_loaded = true;
$ = unsafeWindow.jQuery;
jQuery = unsafeWindow.jQuery;
callback();
}
}
// check if jQuery is loaded
check_for_jquery();
}
// patch
function patch() {
// get the ticket frame
var ifr = document.getElementById('ifrBetslip-0');
// get the ticket window
var doc = ifr.contentDocument;
// get the sell and buy elements
var sell_e = doc.getElementById('F|list|1|3|div');
var buy_e = doc.getElementById('F|list|1|4|div');
// populate some important data
data['sell_e'] = sell_e;
data['buy_e'] = buy_e;
// make the spread element
$('#BID_OFFER tr', doc).append('<td class="slash">/</td><td class="flasher"><span id="spread_e">n/a</span></td></tr>');
// populate some important data
data['spread_e'] = $('#spread_e', doc).get(0);
// make the flunctuation and speed row
$('#OTOTable > tbody', doc).append('<tr><td class="t1"><label>F/S/D</label></td><td colspan="3"><table cellspacing="0" cellpadding="0" border="0" class="prices"><tbody><tr><td class="flasher"><span id="flunctuation_e">n/a</span></td><td class="slash">/</td><td class="flasher"><span id="speed_e">n/a</span></td><td class="slash">/</td><td class="flasher"><span id="direction_e">n/a</span></td></tr></tbody></table></td></tr>');
// populate some important data
data['flunctuation_e'] = $('#flunctuation_e', doc).get(0);
data['speed_e'] = $('#speed_e', doc).get(0);
data['direction_e'] = $('#direction_e', doc).get(0);
// install the goal indicator
$('#OTOTable > tbody', doc).append('<tr><td class="t1"><label>S/L</label></td><td colspan="3"><table cellspacing="0" cellpadding="0" border="0" class="prices"><tbody><tr><td class="flasher"><span id="spread_in_e">n/a</span></td><td class="slash">/</td><td class="flasher"><span id="limit_in_e">n/a</span></td></tr></tbody></table></td></tr>');
// populate some important data
data['spread_in_e'] = $('#spread_in_e', doc).get(0);
data['limit_in_e'] = $('#limit_in_e', doc).get(0);
// install auto order level computator
$('#OTOTable > tbody', doc).append('<tr><td class="t1"><label>Auto OL</label></td><td class="pos3"><div class="inputIncrement"><input type="text" maxlength="9" id="auto_ol_e" value="" class="text large"/><a title="" href="#" class="down"/><a title="" href="#" class="up"/></div></td><td class="t3"></td></tr>');
// populate some important data
data['auto_ol_e'] = $('#auto_ol_e', doc).get(0);
data['order_direction_e'] = $('#directionDisplay', doc).get(0);
data['order_level_e'] = $('#ORDER_LEVEL', doc).get(0);
data['order_limit_e'] = $('#limitDistance', doc).get(0);
// indicated that the patch has completed
is_patched = true;
}
// start engine
function start_engine() {
// start the spread calculating rotine
data['calculate_spread_interval'] = setInterval(function () {
var sell = parseFloat(data['sell_e'].innerHTML);
var buy = parseFloat(data['buy_e'].innerHTML);
data['spread_e'].innerHTML = buy - sell;
}, 1000);
// start the prices collection rotine
data['calculate_prices_collection_interval'] = setInterval(function () {
var sell = parseFloat(data['sell_e'].innerHTML);
var buy = parseFloat(data['buy_e'].innerHTML);
var price = sell + ((buy - sell)/2);
data['prices'].push(price);
data['times'] += 1;
}, 1000);
// start the f/s/d/s/l calculating rotine
data['calculate_fsdsl_interval'] = setInterval(function () {
var fs = [];
var lfs = undefined;
for (var i = 0; i < data['prices'].length; i++) {
if (lfs == undefined) {
lfs = data['prices'][i];
} else {
var dif = lfs - data['prices'][i];
if (dif < 0) {
dif = -1 * dif
}
fs.push(dif);
}
}
var price_difference = data['prices'][0] - data['prices'][data['prices'].length - 1];
var price_speed = price_difference/data['times'];
var price_flunctuation = fs.average();
if (price_speed < 0) {
price_speed = -1 * price_speed;
}
data['flunctuation_e'].innerHTML = price_flunctuation.toFixed(2);
data['speed_e'].innerHTML = price_speed.toFixed(2);
if (price_difference < 0) {
data['direction_e'].innerHTML = 'Up';
} else if (price_difference > 0) {
data['direction_e'].innerHTML = 'Down';
} else {
data['direction_e'].innerHTML = 'n/a';
}
var spread = parseInt(data['spread_e'].innerHTML);
data['spread_in_e'].innerHTML = (spread/price_speed).toFixed(2);
if (data['order_limit_e'].value.replace(/^\s+|\s+$/g, '') != '') {
data['limit_in_e'].innerHTML = ((parseInt(data['order_limit_e'].value) + spread)/price_speed).toFixed(2);
} else {
data['limit_in_e'].innerHTML = 'n/a';
}
}, 10000);
// start the order level calculating rotine
data['calculate_order_level_interval'] = setInterval(function () {
if (data['auto_ol_e'].value.replace(/^\s+|\s+$/g, '') != '') {
try {
var auto_ol = parseInt(data['auto_ol_e'].value);
} catch(e) {
var auto_ol = 0;
}
if (data['order_direction_e'].value == 'Sell') {
var sell = parseFloat(data['sell_e'].innerHTML);
data['order_level_e'].value = sell - auto_ol;
} else if (data['order_direction_e'].value == 'Buy') {
var buy = parseFloat(data['buy_e'].innerHTML);
data['order_level_e'].value = buy + auto_ol;
}
}
}, 1000);
// indicate that the engine has started
is_engine_started = true;
}
// stop engine
function stop_engine() {
// stop the spread calculating rotine
clearInterval(data['calculate_spread_interval']);
// stop the prices collection rotine
clearInterval(data['calculate_prices_collection_interval']);
data['prices'] = [];
data['times'] = 0;
// stop the f/s/d/s/l calculating rotine
clearInterval(data['calculate_fsdsl_interval']);
// stop the order level calculating rotine
clearInterval(data['calculate_order_level_interval']);
// indicate that the engine is stopped
is_engine_started = false;
}
// rotine
function rotine() {
// patch the window
patch();
// if the engine is started then stop it...
if (is_engine_started == true) {
stop_engine();
}
// ...and start it again
start_engine();
}
// fire when IG inserts ifrBetslip-0 on the page
document.addEventListener("DOMNodeInserted", function (event) {
// exit if this is not the element we are looking for
if (event.target.id != 'ifrBetslip-0') {
return;
}
// start the rotine when the ifrBetslip-0 frame loads
event.target.addEventListener("load", function () {
// greasemonkey bug here! and this is the workaround.
setTimeout(function () {
// if jQuery is not loaded then load it and fire the rotine
if (is_jquery_loaded == false) {
load_jquery(rotine);
} else {
// otherwise just fire the rotine
rotine();
}
}, 0);
}, true);
}, true);
As you can see the patch is really bad. I’ve put it together in an agile fashion. But it works!
My final piece of advice is: don’t gamble! Get a feeling of the game and make smart decisions backed up by substantial data. Otherwise, spread betting will be no different than betting on dog races.
i would like to know exactly how it works i’m really intersted