gch-truefx-pricefeed
Version:
LIVE FX price feed FREE from trueFX
315 lines (205 loc) • 8.73 kB
JavaScript
/**
* Author : Bill Gooch
*
* TRUE FX price feed ...
*/
module.exports = function (io,trueFXConfig) {
'use strict';
// ======== Dependencies
var request = require("request");
var cheerio = require('cheerio');
// ======== TRUE FX configuration
var curPairs = trueFXConfig.curPairs;
var trueFXusername = trueFXConfig.userName;
var trueFXpassword = trueFXConfig.password;
var trueFXID = trueFXConfig.trueFXID;
// ======== TRUE FX static
var fxGroup = 'fxrates';
var format = 'html';
var priceFeedHost = 'http://webrates.truefx.com/rates/connect.html?';
// ========
var fxServiceYetToBeInitiated = true;
var userNotAuthenticated = true;
var currencyPairs = [];
if(trueFXConfigIsNotValid()){
return;
}
authenticateSession();
//================================================
// SOCKET SETUP
//================================================
io.on('connection', function (socket) {
if(fxServiceYetToBeInitiated){
setInterval(function () {
requestFXprices(socket);
}, 1000)
}
socket.on('disconnect', function () {
fxServiceYetToBeInitiated = true;
socket.emit('disconnected');
});
});
//================================================
// PRICING API
//================================================
function requestFXprices(socket){
if(userNotAuthenticated)authenticateSession();
console.log(trueFXconfigPath());
request(trueFXconfigPath(), function(error, response, body) {
if (!error && response.statusCode === 200) {
var fxPriceData = updatePrices(body);
fxServiceYetToBeInitiated = false;
socket.emit('fxPriceUpdate', {
payload: fxPriceData
});
}
else if(error){
fxServiceYetToBeInitiated = true;
console.error ("There has been en ERROR when requesting prices from : " + trueFXconfigPath());
console.error ("ERROR status code : " + error);
}
})
}
function updatePrices(body){
var $;
$ = cheerio.load(body);
var priceUpdates = $('table').find('tr').length;
if(priceUpdates === 0 )return currencyPairs;
//SET - UP initial pairs
if(currencyPairs.length === 0){
currencyPairs = $('table tr').map(function() {
var $row = $(this);
var symbolVO = createSymbolVO($row);
return symbolVO;
}).get();
return currencyPairs;
}
// ONLY UPDATE CERTAIN PAIRS
else{
var updatedPairs = [];
updatedPairs = $('table tr').map(function() {
var $row = $(this);
var symbolVO = createSymbolVO($row);
return symbolVO;
}).get();
//UPDATE ALL PAIRS
if(updatedPairs.length === currencyPairs.length ) {
determinePriceChange(currencyPairs, updatedPairs);
currencyPairs = updatedPairs;
return currencyPairs;
}
var i,b;
for (i=0; i< updatedPairs.length ; i++){
var symbolToUpdate = updatedPairs[i].symbol;
var symbolToUpdateBid = updatedPairs[i].bidPoint;
var symbolToUpdateOffer = updatedPairs[i].offerPoint;
var symbol = updatedPairs[i];
for(b=0; b < currencyPairs.length ; b++){
if(symbolToUpdate === currencyPairs[b].symbol){
var oldBid = currencyPairs[b].bidPoint;
var oldOffer = currencyPairs[b].offerPoint;
if(symbolToUpdateBid > oldBid){
symbol.bidBullBear = "bull";
}
else if(symbolToUpdateBid < oldBid){
symbol.bidBullBear = "bear";
}
if(symbolToUpdateOffer > oldOffer){
symbol.offerBullBear = "bull";
}
else if(symbolToUpdateOffer < oldOffer){
symbol.offerBullBear = "bear";
}
currencyPairs[b] = symbol;
break;
}
}
}
return currencyPairs;
}
}
//================================================
// HELPER METHODS
//================================================
function determinePriceChange(oldPrice, newPrice){
var i;
for (i=0; i< newPrice.length ; i++){
var newPricebid = newPrice[i].bidPoint;
var oldPricebid = oldPrice[i].bidPoint;
var newPriceoffer = newPrice[i].offerPoint;
var oldPriceoffer = oldPrice[i].offerPoint;
if(newPricebid > oldPricebid){
newPrice[i].bidBullBear = "bull";
}
else if(newPricebid < oldPricebid){
newPrice[i].bidBullBear = "bear";
}
if(newPriceoffer > oldPriceoffer){
newPrice[i].offerBullBear = "bull";
}
else if(newPriceoffer < oldPriceoffer){
newPrice[i].offerBullBear = "bear";
}
}
}
function createSymbolVO(row){
return {
symbol: row.find(':nth-child(1)').text(),
timeStamp: row.find(':nth-child(2)').text(),
bidBig: row.find(':nth-child(3)').text(),
bidPoint: row.find(':nth-child(4)').text(),
offerBig: row.find(':nth-child(5)').text(),
offerPoint: row.find(':nth-child(6)').text(),
high: row.find(':nth-child(7)').text(),
low: row.find(':nth-child(8)').text(),
mid: row.find(':nth-child(9)').text(),
bidBullBear: 0 ,
offerBullBear: 0
};
}
function authenticateSession(){
var options = {
host: priceFeedHost,
path: trueFXauthPath()
};
request(trueFXauthPath(), function(error, response, body) {
if (!error && response.statusCode === 200) {
var bodyNoWhitSpace = body.replace(/ /g,'');
var authorised = bodyNoWhitSpace.search('notauthorized');
if(authorised === 0){
console.error('ERROR Username or password is wrong and has returned not authorized');
return;
}
userNotAuthenticated = false;
trueFXID = bodyNoWhitSpace;
}
else if(error){
fxServiceYetToBeInitiated = true;
console.error ("There has been en ERROR when requesting prices from : " + trueFXconfigPath());
console.error ("ERROR status code : " + error);
}
})
}
function trueFXauthPath(){
var truePath = priceFeedHost+'u='+trueFXusername+'&p='+trueFXpassword+'&q='+fxGroup+"&f="+format+"&c="+curPairs;
return truePath;
}
function trueFXconfigPath(){
var truePath = priceFeedHost+'u='+trueFXusername+'&p='+trueFXpassword+'&q='+fxGroup+"&id="+trueFXID;
return truePath;
}
function trueFXConfigIsNotValid(){
if(!trueFXConfig.hasOwnProperty("userName") || typeof trueFXConfig.userName !== "string" ) {
console.error('UserName was not defined or is not a string as part of the trueFXconfig')
return true;
}
if(!trueFXConfig.hasOwnProperty("password") || typeof trueFXConfig.password !== "string" ) {
console.error('PAssword was not defined or is not a string as part of the trueFXconfig')
return true;
}
if(!trueFXConfig.hasOwnProperty("curPairs") || typeof trueFXConfig.curPairs !== "string" ) {
console.error('Currency pairs was not defined or is not a string as part of the trueFXconfig')
return true;
}
}
};