@seedalpha/ticker
Version:
ticker parser of seedalpha
186 lines (144 loc) • 5 kB
JavaScript
var Queue = require('@seedalpha/queue');
var log = require('./utils/log');
var data = require('./data/index');
var ticker = {
parse: function(str) {
var pattern = /^([0-9a-z]{1,5}|[0-9]{6})[\s]*[\s\.:][\s]*([a-z]{1,2})$/i;
var matches = str.trim().match(pattern);
// CapIQ style pattern
var pattern2 = /^([a-z]{3,6}):A?([0-9]{1,6})$/i;
var matches2 = str.trim().match(pattern2);
if ((!matches || matches.length !== 3)
&& (!matches2 || matches2.length !== 3)) {
log.trace('input does not match ticker pattern');
return null;
}
var stockCode, exchangeCode;
if (matches) {
stockCode = matches[1].replace(/^[0]+/g, '').toUpperCase();
exchangeCode = matches[2].toUpperCase();
} else if (matches2) {
stockCode = matches2[2].replace(/^[0]+/g, '').toUpperCase();
exchangeCode = matches2[1].toUpperCase();
}
log.trace('ticker pattern matched, code: %s, exchange: %s', stockCode, exchangeCode);
return {
code: stockCode,
exchange: exchangeCode
}
},
_findPossibleExchanges: function(obj) {
return data.exchanges.filter(function(exchange) {
return exchange.codes.indexOf(obj.exchange.toUpperCase()) > -1;
});
},
lookup: function(obj, callback) {
var stock = null;
var exchange = null;
ticker._findPossibleExchanges(obj).some(function(ex) {
if (stock = data.stocks[ex.key][obj.code.toUpperCase()]) {
exchange = ex;
return true;
}
});
log.debug('stock found: ', stock);
if (!stock) return callback('stock not found');
callback(null, {
stock: stock,
exchange: exchange
});
},
getTerms: function(info, includeNoLeadingZeros, withKeywords, callback) {
if (typeof includeNoLeadingZeros === 'function') {
callback = includeNoLeadingZeros;
includeNoLeadingZeros = false;
withKeywords = false;
} else if (typeof withKeywords === 'function') {
callback = withKeywords;
withKeywords = false;
}
log.trace('includeNoLeadingZeros: %s, with keywords: %s', includeNoLeadingZeros, withKeywords);
var terms = [];
var stock = info.stock;
var exchange = info.exchange;
var separators = [' ', '.', ':'];
exchange.codes.forEach(function(exchangeCode) {
var stockCode = stock.code;
if (isInt(stock.code) && isInt(exchange.numericLength)) {
stockCode = padZeros(stock.code, exchange.numericLength);
}
terms = terms.concat(separators.map(function(sep) {
return [stockCode, exchangeCode].join(sep);
}));
if (isInt(stock.code) && includeNoLeadingZeros) {
terms = terms.concat(separators.map(function(sep) {
return [stock.code, exchangeCode].join(sep);
}));
}
});
terms.push(stock.name);
log.trace('terms got: %o', terms);
// TODO: add more related keywords to the dataset and support withKeywords argument
/*if (withKeywords) {
}*/
callback(null, terms);
},
findTickers: function(contentText, callback) {
try {
var pattern1 = /(?:[^0-9a-z]|^)([0-9a-z]{1,4}|[0-9]{6})[\.:]([a-z]{1,2})(?:[^0-9a-z]|$)/ig;
var pattern2 = /(?:[^0-9a-z]|^)([0-9]{4,6})[\s]([a-z]{2})(?:[^0-9a-z]|$)/ig;
var objs = [];
var i = 0;
var extract = function(matches, objs) {
if (matches.length === 3) {
var stockCode = matches[1].replace(/^[0]+/g, '').toUpperCase();
var exchangeCode = matches[2].toUpperCase();
var obj = {
code: stockCode,
exchange: exchangeCode
};
if (ticker._findPossibleExchanges(obj).length) {
objs.push(obj);
}
}
}
var matches;
while ((matches = pattern1.exec(contentText)) !== null) {
extract(matches, objs);
}
while ((matches = pattern2.exec(contentText)) !== null) {
extract(matches, objs);
}
var lookups = objs.map(function(obj) {
return function(results, next) {
ticker.lookup(obj, function(err, result) {
if (err) return next();
results.push(result);
next();
});
}
});
Queue([]).add(lookups)
.end(function(err, results) {
callback(null, results.map(function(result) {
return [result.stock.code.toString().toUpperCase(), result.exchange.codes[0].toUpperCase()].join('.');
}));
});
} catch(err) {
callback(err);
}
}
}
exports = module.exports = ticker;
function isInt(value) {
return !isNaN(value) &&
parseInt(Number(value)) == value &&
!isNaN(parseInt(value, 10));
}
function padZeros(str, len) {
var padded = str;
while(padded.length < len) {
padded = '0' + padded;
}
return padded;
}