sharewatch
Version:
Fetch Real-time Indian stock market data from NSE (National Stock Exchange) and BSE (Bombay Stock Exchange)
173 lines (158 loc) • 4.94 kB
JavaScript
/*!
* sharewatch
* Copyright(c) 2019 Anjul Garg <anjulgarg@live.com>
* MIT Licensed
*/
/**
* Module dependencies
* @private
*/
const fs = require('fs')
const moment = require('moment')
const request = require('request-promise')
const AdmZip = require('adm-zip')
const uuid = require('uuid/v4')
const CSV = require('../utils/csv')
/**
* Module settings
* @private
*/
const HOST_URL = 'https://www.bseindia.com'
const EQUITY_LIST_URL = `${HOST_URL}/corporates/List_Scrips.aspx`
const INDICE_URL = 'https://api.bseindia.com/bseindia/api/Sensex/getSensexData?json={"fields":"2,3,4,5,6,7"}'
const QUOTE_URL = (scripCode) => `https://api.bseindia.com/BseIndiaAPI/api/StockReachGraph/w?scripcode=${scripCode}&flag=0&fromdate=&todate=&seriesid=`
const QUOTE_PEER = (scripCode) => `https://api.bseindia.com/BseIndiaAPI/api/EQPeerGp/w?scripcode=${scripCode}&scripcomare=`
const BHAVCOPY_URL = (dt) => {
dt = moment(dt)
let year = dt.format('YY')
let month = dt.format('MM').toUpperCase()
let day = dt.format('DD')
return `${HOST_URL}/download/BhavCopy/Equity/EQ_ISINCODE_${day}${month}${year}.zip`
}
const INVALID_RESPONSE = 'invalid server response'
const TIMEOUT = 5 * 1000
/**
* Service object
* @public
*/
const BSE = Object.create(null)
/**
* Module exports
* @public
*/
module.exports = BSE
/**
* Get a list of all the equity securities listed under BSE
*
* @param {Number} timeout Defaults to 5 * 1000
* @return {Array} Array containing fields like `isin_no` etc.
* @public
*/
BSE.equityList = (timeout = TIMEOUT * 4) => new Promise((resolve, reject) => {
let headers = { 'content-type': 'application/x-www-form-urlencoded' }
let options = {
url: EQUITY_LIST_URL,
method: 'POST',
headers: headers,
body: fs.readFileSync(__dirname + '/bse_formdata.txt'),
timeout: timeout,
}
request(options)
.then((res) => {
let lines = res.split(/[\r\n]+/)
if (lines.length < 2) return reject(new Error(INVALID_RESPONSE))
let columns = lines[0].split(',').map((el) => {
return el.trim().toLowerCase().replace(/ /g, '_')
})
if (columns.indexOf('isin_no') < 0) return reject(new Error(INVALID_RESPONSE))
let results = []
lines.forEach((line, index) => {
if (index == 0) return
let data = {}
let values = line.split(',')
columns.forEach((el, idx) => { data[el] = values[idx] })
results.push(data)
})
resolve(results)
})
.catch((err) => reject(err))
})
/**
* Get live BSE Indice data.
*
* @param {Number} timeout Defaults to 5 * 1000
* @return {Object}
* @public
*/
BSE.indices = (timeout = TIMEOUT) => new Promise((resolve, reject) => {
request(INDICE_URL, { timeout: timeout })
.then((res) => {
if (!res) return reject(new Error(INVALID_RESPONSE))
try {
let result = JSON.parse(res)[0]
resolve(result)
} catch (err) { return reject(new Error(INVALID_RESPONSE)) }
})
.catch((err) => reject(err))
})
/**
* Get live quote for a `scripCode`
*
* @param {String} scripCode
* @param {Number} timeout Defaults to 5 * 1000
* @return {Object}
* @public
*/
BSE.quote = (scripCode, timeout = TIMEOUT) => new Promise((resolve, reject) => {
request(QUOTE_URL(scripCode), { timeout: timeout })
.then((res) => {
if (!res) return reject(new Error(INVALID_RESPONSE))
try {
let result = JSON.parse(res)
resolve(result)
} catch (error) { return reject(new Error(INVALID_RESPONSE)) }
})
.catch((err) => reject(err))
})
/**
* Get live quote and peer comparison for a `scripCode`
*
* @param {String} scripCode
* @param {Number} timeout Defaults to 5 * 1000
* @return {Object}
* @public
*/
BSE.quoteWithComparison = (scripCode, timeout = TIMEOUT) => new Promise((resolve, reject) => {
request(QUOTE_PEER(scripCode), { timeout: timeout })
.then((res) => {
if (!res) return reject(new Error(INVALID_RESPONSE))
try {
let result = JSON.parse(res)
resolve(result)
} catch (error) { return reject(new Error(INVALID_RESPONSE)) }
})
.catch((err) => reject(err))
})
/**
* Download Bhavcopy (End of day stats) for a `date`
* Creates a zip file containing the bhavcopy for this date.
*
* @param {String} date YYYY-MM-DD Example: 2018-01-01
* @param {Number} timeout Defaults to 5 * 1000
* @return {String}
* @public
*/
BSE.bhavcopy = (date, timeout = TIMEOUT) => new Promise((resolve, reject) => {
let temp_storage = `/tmp/${uuid()}.zip`
request(BHAVCOPY_URL(date), { timeout: timeout })
.on('error', (err) => reject(err))
.pipe(fs.createWriteStream(temp_storage))
.on('close', () => {
let zip = new AdmZip(temp_storage)
let csvData = zip.getEntries()[0].getData().toString('utf8')
fs.unlinkSync(temp_storage)
let result = CSV.parse_data(csvData)
resolve(result)
})
})