finvizor
Version:
Get finviz stock data in proper format
153 lines (152 loc) • 5.28 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.fixValues = exports.fixKeys = exports.capitalizeFirstLetters = exports.getStockPage = void 0;
const got_1 = __importDefault(require("got"));
const lodash_1 = require("lodash");
/**
* Get html page for chosen quote
* @param ticker
* @returns {Promise<string>}
*/
const getStockPage = async (ticker) => {
try {
const response = await (0, got_1.default)('https://finviz.com/quote.ashx', {
searchParams: {
t: ticker,
p: 'd',
},
});
return response.body;
}
catch (error) {
return '';
}
};
exports.getStockPage = getStockPage;
/**
* Capitalize each first letters (for insider names)
* @param str
* @returns {string}
*/
const capitalizeFirstLetters = (str) => {
const splitStr = str.toLowerCase().split(' ');
for (let i = 0; i < splitStr.length; i++) {
splitStr[i] = splitStr[i].charAt(0).toUpperCase() + splitStr[i].substring(1);
}
return splitStr.join(' ');
};
exports.capitalizeFirstLetters = capitalizeFirstLetters;
/**
* Converts string date like 'Feb 25 AMC' to Date object with current year
* @param {String} dateString - String date like 'Feb 25 AMC'
* @returns {Earnings} Returns the stored time value in milliseconds since midnight, January 1, 1970 UTC.
*/
const convertDate = (dateString) => {
if (!dateString) {
return {
date: 0,
marketTime: '',
};
}
// Use only first two statements from the date string
const dateArr = dateString.split(' '), currentDate = new Date(), date = new Date(dateArr[0] + dateArr[1]);
// To set proper year for the past date
if (currentDate.getMonth() - date.getMonth() < 0) {
date.setFullYear(currentDate.getUTCFullYear() - 1);
}
else {
date.setFullYear(currentDate.getFullYear());
}
return {
date: date.valueOf(),
marketTime: dateArr[2] || '',
};
};
/**
* Fix keys names
* @param {TempObject} obj
* @returns {Stock}
*/
const fixKeys = (obj) => {
let resultObj = {};
Object.keys(obj).forEach((key) => {
let newKey = key;
// 'Dividend %' => 'Dividend Percent'
newKey = newKey.replace(/%/gi, 'Percent');
// '52W High' => ' High52W'
const startsWithNumber = newKey.match(/^([0-9]{2}[A-Z]{1})/gm);
if (startsWithNumber) {
newKey = newKey.replace(/^([0-9]{2}[A-Z]{1})/gm, '');
newKey += startsWithNumber[0];
}
// 'RSI (14)' => 'RSI '
newKey = newKey.replace(/\(.*?\)/g, '');
// 'P/C' => 'PC', 'P/FCF' => 'P/CF' || 'EPS Q/Q' => 'EPS QQ'
if (newKey.match(/(^[A-z]{1}\/)|(\s[A-z]{1}\/)/g)) {
newKey = newKey.replace(/\//g, '');
}
// 'Debt/Eq' => 'Debt Eq'
newKey = newKey.replace(/\//g, ' ');
// To camel case 'Rel Volume' => 'relVolume'
newKey = (0, lodash_1.camelCase)(newKey);
resultObj[newKey] = obj[key];
});
return resultObj;
};
exports.fixKeys = fixKeys;
/**
* Fix values
* @param {TempObject} obj
* @returns {Stock}
*/
const fixValues = (obj) => {
// Keys that was already processed (good to go)
const processed = ['index', 'country', 'industry', 'sector', 'exchange', 'site', 'name', 'ticker'];
// Keys that need separate processing (text values or dates)
const exclusions = ['earnings', 'shortable', 'optionable'];
// Keys that need to be processed as range values (low high)
const range = ['volatility'];
// Fix numeric values
Object.keys(obj).forEach((key) => {
if (!processed.includes(key) && !exclusions.includes(key) && !range.includes(key)) {
let newValue = obj[key];
// Remove whitespaces, commas and percentage characters
newValue = newValue.replace(/[\s]|(%)|(,)|(\()|(\))/g, '');
// Fix if value ends with B (billions) or M (millions)
if (newValue.match(/M/g)) {
newValue = Math.floor(+newValue.replace(/M/g, '') * 1.0e6);
}
else if (newValue.match(/B/g)) {
newValue = Math.floor(+newValue.replace(/B/g, '') * 1.0e9);
}
else {
newValue = +newValue;
}
obj[key] = newValue || null;
}
else {
// Fix boolean values
obj[key] = obj[key] === 'Yes' ? true : obj[key];
obj[key] = obj[key] === 'No' ? false : obj[key];
}
});
// Fix range values for volatility: '1.57% 2.63%' => { week: 1.57, month: 2.63 }
range.forEach((k) => {
if (k === 'volatility') {
const rangeArr = obj[k].replace(/(%)|(-\s)/g, '').split(' ');
obj[k] = {
week: +rangeArr[0],
month: +rangeArr[1],
};
}
});
// Fix index if null
obj.index = obj.index === '-' ? undefined : obj.index;
// Fix earning date value
obj.earnings = convertDate(obj.earnings);
return obj;
};
exports.fixValues = fixValues;