[
  {
    "path": ".babelrc",
    "content": "{\n  \"presets\": [\"es2015\", \"stage-2\"]\n}\n\n"
  },
  {
    "path": ".eslintrc",
    "content": "{\n  \"extends\": \"airbnb\",\n  \"parserOptions\": {\n    \"ecmaVersion\": 6,\n    \"sourceType\": module,\n    \"ecmaFeatures\": {\n      \"jsx\": true,\n      \"experimentalObjectRestSpread\": true\n    },\n  },\n  \"env\": {\n    \"browser\": true,\n    \"node\": true\n  },\n  \"rules\": {\n    \"arrow-parens\": [\"error\", \"as-needed\"],\n    \"comma-dangle\": [\"error\", \"always-multiline\"],\n    \"dot-notation\": 0,\n    \"guard-for-in\": 0,\n    \"no-underscore-dangle\": 0,\n    \"no-use-before-define\": [2, \"nofunc\"],\n    \"space-before-function-paren\": [2, \"never\"],\n    \"import/no-extraneous-dependencies\": [\"error\", {\"devDependencies\": true, \"optionalDependencies\": false, \"peerDependencies\": false}],\n    \"import/prefer-default-export\": 0\n  }\n}\n"
  },
  {
    "path": ".gitignore",
    "content": "node_modules\n.env\ndist\nlib\nlibexample\n.idea\n*.iml\ncoverage\n.nyc_output\n"
  },
  {
    "path": ".npmignore",
    "content": "src/\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# v0.3.1\n\n> 获取指定年月限售解禁股数据\n\n```\nstock.getXSGData()\n```\n\n# v0.3.0\n\n> 目标同时支持browser和nodejs环境，因此改用fetch替换掉superagent.\n\n### 这个比较大的改动：\n使用fetch，因为接口返回改为promise，而不是之前的callback\n\n"
  },
  {
    "path": "README.md",
    "content": "# tushare.js\n\n这是[tushare](http://tushare.org/)的nodejs版，正在开发当中。如果有感兴趣的同学，非常欢迎一起完善该项目。\n\ntushare的数据大多来自于各大网站股票金融频道的数据。本质上是去抓取这些网站的数据，以此方便二次使用。文档目前并不完善，使用方法（接口）\n请参考`test/`目录内的单元测试\n\n### 使用方法:\n```\nnpm install tushare --save\nnpm run build\nnpm run test\n```\n\n然后:\n```\nimport { stock } from 'tushare';\n\nstock.getTodayAll().then(({ data }) => {\n  console.log(data);\n});\n\n```\n\n## 交易数据\n\n## 1. 获取个股历史数据\n```\nconst options = {\n  code: '600848',\n  ktype: 'week'\n};\nstock.getHistory(options).then(({ data }) => {\n  console.log(data);\n});\n\n```\n\n`options` 参数说明：\n```\n{\ncode: {String} 股票代码，6位数字代码\nktype: {String} 数据类型，day=日k线 week=周 month=月 5=5分钟 15=15分钟 30=30分钟 60=60分钟，默认为day\nstart: {String} 开始日期，格式YYYY-MM-DD\nend: {String} 结束日期，格式YYYY-MM-DD\nautype: {String} 复权，默认前复权(fq), 不复权(last)\n}\n```\n\n## 2. 获取历史分笔数据\n```\nconst options = {\n  code: '600848',\n  date: '2015-12-31'\n};\nstock.getTick(options).then(({ data }) => {\n  console.log(data);\n});\n```\n\n`options` 参数说明：\n```\n{\n  date: {String} 历史分笔日期，格式YYYY-MM-DD\n  code: {String} 股票代码，6位数字代码\n}\n```\n\n### 获取历史K线数据\n```\nconst options = {\n  code: '000001',\n  index: true,\n  start : '2015-01-01',\n  end: '2016-10-22',\n  args: '000001'\n};\nstock.getKData(options).then(data => {\n   console.log('code %s',options.code);\n   console.log(data);  \n  })\n  .catch(err => {\n    console.error('get %s error %s', options.code, err);\n  });\n```\n\n`options` 参数说明：\n```\n{\n  start: {string} 起始时间，格式YYYY-MM-DD\n  end: {string} 结束时间，格式YYYY-MM-DD\n  code: {string} 股票代码\n  ktype: {string} K线类型 ('day','week','month','5','10','15','30','60')\n  index: {bool}  表示是否是指数，默认是否\n}\n```\n\n## 3. 实时行情\n```\nstock.getTodayAll().then(({ data }) => {\n  console.log(data);\n});\n```\n\n`options(可选)` 参数说明：\n```\n{\n  pageSize: 设置单次返回股票的数量，默认10000，即全部股票\n  pageNo: 页码，都懂得\n}\n```\n\n## 4. 实时分笔\n```\nvar options = {\n  codes: [\n    '600848',\n    '600000'\n  ]\n};\nstock.getLiveData(options).then(({ data }) => {\n  console.log(data);\n});\n```\n\n`options` 参数说明：\n```\n{\n  codes: 股票代码数组\n}\n```\n\n## 5. 当日历史分笔\n>该方法返回指定时间前五分钟的分笔数据，如需获得所有数据，需要多次调用该方法\n\n```\nvar options = {\n  code: '600848',\n  end: '15:00:00'\n};\nstock.getTodayTick(options).then(({ data }) => {\n  console.log(data);\n});\n```\n\n`options` 参数说明：\n```\n{\n  code: 股票代码，6位数字\n  end: 结束时间\n}\n```\n\n## 6. 大盘指数行情数据\n```\nstock.getIndex().then(({ data }) => {\n  console.log(data);\n});\n```\n\n## 7. 大单交易数据\n```\nvar options = {\n  code: '600848',\n  volume: 700\n};\nstock.getSinaDD(options).then(({ data }) => {\n  console.log(data);\n});\n```\n\n`options` 参数说明：\n```\n{\n  code: 股票代码，6位数字\n  volume: (手)默认400，返回大于xx手的大单数据\n}\n```\n\n## 行业分类数据\n\n## 1. 获取新浪行业分类信息\n比如：房地产、电子信息、钢铁行业等等新浪行业分类信息\n```\nstock.getSinaIndustryClassified().then(({ data }) => {\n  console.log(data);\n});\n```\n\n## 2. 获取新浪某个行业分类的具体信息：所包含的股票及其交易信息\n这里的tag是分类行业分类的tag，可以从上一个接口：tushare.stock.getSinaIndustryClassified获得\n```\nvar options = {\n  tag: 'new_jrhy'\n};\nstock.getSinaClassifyDetails(options).then(({ data }) => {\n  console.log(data);\n});\n```\n\n`options` 参数说明：\n```\n{\n  tag: 新浪行业代码\n}\n```\n\n## 3. 获取新浪概念分类信息\n返回数据中的tag可用于上面（#2）的接口，用于获取某个概念分类的具体信息\n```\nstock.getSinaConceptsClassified().then(({ data }) => {\n  console.log(data);\n});\n```\n\n## 4. 获取所有上市公司股票基本信息\n```\nstock.getAllStocks().then(({ data }) => {\n  console.log(data);\n});\n```\n\n## 5. 获取沪深300股票信息\n```\nstock.getHS300().then(({ data }) => {\n  console.log(data);\n});\n```\n\n## 6. 获取上证50股票信息\n```\nstock.getSZ50().then(({ data }) => {\n  console.log(data);\n});\n```\n\n## 7. 获取指定年月限售解禁股数据\n```\nstock.getXSGData().then(({ data }) => {\n  console.log(data);\n});\n```\n\n## 龙虎榜\n\n## 1. 龙虎榜单（来自网易财经）\n```\n  var options = {\n    start: '2016-01-15',\n    end: '2016-01-15',\n    pageNo: 1,\n    pageSize: 150\n  };\n  stock.lhb(options).then(({ data }) => {\n    console.log(data);\n  });\n```\n\n`options` 参数说明：\n```\n{\nstart: 开始日期\nend: 结束日期\npageNo: （optional, default: 1）\npageSize: optional, default: 150）\n}\n```\n\n## 2. 大宗交易（来自网易财经）\n```\n  var options = {\n    start: '2016-01-15',\n    end: '2016-01-15',\n    pageNo: 1,\n    pageSize: 150\n  };\n  stock.blockTeade(options).then(({ data }) => {\n    console.log(data);\n  });\n```\n\n`options` 参数说明：\n```\n{\nstart: 开始日期\nend: 结束日期\npageNo: （optional, default: 1）\npageSize: optional, default: 150）\n}\n```\n"
  },
  {
    "path": "example/getkdata/getk.js",
    "content": "/* eslint-disable no-console */\nimport { stock } from '../../lib';\nimport * as extargsparse from 'extargsparse';\n\nconst util = require('util');\nconst strftime = require('strftime');\n\nconst commandfmt = `\n{\n\t\"ktype|k\" : \"day\",\n\t\"autype|a\" : \"hfq\",\n\t\"index|i\" : false,\n\t\"start|s\" : \"%s\",\n\t\"end|e\" : \"%s\",\n\t\"$\" : \"+\"\n}`;\n\nconst nowtime = new Date();\nconst etime = new Date(nowtime.getTime() - 24 * 1 * 3600 * 1000);\nconst stime = new Date(etime.getTime() - 24 * 365 * 3600 * 1000);\n\nconst sdate = strftime('%Y-%m-%d',stime);\nconst edate = strftime('%Y-%m-%d',etime);\n\nconst command=util.format(commandfmt,sdate,edate);\nconst parser = extargsparse.ExtArgsParse();\nparser.load_command_line_string(command);\nconst args = parser.parse_command_line();\n\n\nargs.args.forEach(function(code) {\n\tlet options = {};\n\toptions.code = code;\n\toptions.start = args.start;\n\toptions.end = args.end;\n\toptions.ktype = args.ktype;\n\toptions.autype = args.autype;\n\toptions.isIndex = args.index;\n\tstock.getKData(options).then(data => {\n\t\tconsole.log('code %s',code);\n\t\tdata.forEach(function(d) {\n\t\t\tconsole.log('%s',d);\n\t\t});\n\t})\n\t.catch(err => {\n\t\tconsole.error('get %s error %s', code, err);\n\t});\n});\n"
  },
  {
    "path": "example/getkdata/merge.js",
    "content": "/* eslint-disable no-console */\nimport * as extargsparse from 'extargsparse';\n\nconst util = require('util');\nconst fs = require('fs');\n\n\nconst _getTimeTick = ts => {\n  const sarr = ts.split('-');\n  let retval = 0;\n  if (sarr.length >= 3) {\n    retval += parseInt(sarr[0], 10) * 100 * 100;\n    retval += parseInt(sarr[1], 10) * 100;\n    retval += parseInt(sarr[2], 10);\n    retval *= 10000;\n  } else {\n    retval += parseInt(ts, 10);\n  }\n  return retval;\n};\n\nconst _findStoreIndex = (arr1,arr2) => {\n  let idx = 0;\n  let minidx = 0;\n  let maxidx = arr1.length - 1;\n  let curidx = Math.floor((minidx + maxidx) / 2);\n  let v1min;\n  let v1max;\n  let v1cur;\n  let v2;\n\n  while( minidx < maxidx ) {\n    v1min = _getTimeTick(arr1[minidx][0]);\n    v1max = _getTimeTick(arr1[maxidx][0]);\n    v1cur = _getTimeTick(arr1[curidx][0]);\n    v2 = _getTimeTick(arr2[0][0]);\n    if (v1min >= v2) {\n      idx = 0;\n      break;\n    } else if (v1max <= v2) {\n      idx = (maxidx + 1);\n      break;\n    }\n\n    if ((minidx + 1) >= maxidx) {\n      /*this is the smallest one*/\n      if (v1min < v2 && v1max > v2) {\n        idx = (minidx);\n        break;\n      } else {\n        idx = (maxidx + 1);\n        break;\n      }\n    }\n\n    if (v1cur < v2) {\n      minidx = curidx;\n    } else if (v1cur > v2) {\n      maxidx = curidx;\n    } else if (v1cur == v2) {\n      idx = curidx;\n      break;\n    }\n    \n    curidx = Math.floor((minidx + maxidx) / 2);\n  }\n  return idx;\n};\n\nconst _mergeArray = (arr1,arr2) => {\n\tlet _idx = 0;\n\t_idx = _findStoreIndex(arr1,arr2);\n\tarr2.forEach(function(d) {\n\t\tarr1.splice(_idx,0,d);\n\t\t_idx += 1;\n\t});\n\treturn arr1;\n};\n\nconst commandline = `\n{\n\t\"$\" : 2\n}\n`;\n\nconst parser = extargsparse.ExtArgsParse();\nparser.load_command_line_string(commandline);\nconst args = parser.parse_command_line();\n\nfs.readFile(args.args[0],function(err1,data1) {\n\tif (err1 !== undefined && err1 !== null) {\n\t\tconsole.error('can not read [%s] error %s', args.args[0], err1);\n\t\tprocess.exit(4);\n\t}\n\tfs.readFile(args.args[1],function(err2,data2) {\n\t\tlet json1;\n\t\tlet json2;\n\t\tlet idx;\n\t\tlet lastval,curval;\n\t\tif (err2 !== undefined && err2 !== null) {\n\t\t\tconsole.error('can not read [%s] error %s', args.args[1], err2);\n\t\t\tprocess.exit(4);\n\t\t}\n\n\t\t// console.log('(%s)', data1);\n\t\tjson1 = JSON.parse(data1);\n\t\tjson2 = JSON.parse(data2);\n\t\t_mergeArray(json1,json2);\n\t\tlastval = 0;\n\n\t\tjson1.forEach(function(d) {\n\t\t\tconsole.log('%s',d);\n\t\t\tcurval = _getTimeTick(d[0]);\n\t\t\tif (curval < lastval) {\n\t\t\t\tconsole.log('%s not right for %s', d, lastval);\n\t\t\t}\n\t\t\tlastval = curval;\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"tushare\",\n  \"version\": \"0.3.1\",\n  \"description\": \"port of tushare for nodejs\",\n  \"main\": \"lib/index.js\",\n  \"scripts\": {\n    \"test\": \"node ./node_modules/ava/cli.js --verbose test/*\",\n    \"build\": \"node ./node_modules/babel-cli/bin/babel.js src --out-dir lib\",\n    \"build:watch\": \"node ./node_modules/babel-cli/bin/babel.js src --out-dir lib --watch\",\n    \"prepublish\": \"npm run build\",\n    \"buildexample\": \"node ./node_modules/babel-cli/bin/babel.js example --out-dir libexample\",\n    \"lint\": \"node ./node_modules/eslint/bin/eslint.js src/\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/ruanyl/tushare.js.git\"\n  },\n  \"keywords\": [\n    \"github\",\n    \"api\"\n  ],\n  \"author\": \"Ruan Yulong <ruanyu1@gmail.com> (http://github.com/ruanyl)\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/ruanyl/tushare.js/issues\"\n  },\n  \"homepage\": \"https://github.com/ruanyl/tushare.js#readme\",\n  \"dependencies\": {\n    \"async\": \"^2.4.1\",\n    \"iconv-lite\": \"^0.4.15\",\n    \"js-base64\": \"^2.1.9\",\n    \"no-fetch\": \"^1.6.2\",\n    \"ramda\": \"^0.23.0\",\n    \"strftime\": \"^0.10.0\",\n    \"whatwg-fetch\": \"^2.0.2\"\n  },\n  \"devDependencies\": {\n    \"ava\": \"^0.18.1\",\n    \"babel-cli\": \"^6.23.0\",\n    \"babel-core\": \"^6.23.1\",\n    \"babel-loader\": \"^6.3.0\",\n    \"babel-plugin-transform-runtime\": \"^6.23.0\",\n    \"babel-polyfill\": \"^6.23.0\",\n    \"babel-preset-es2015\": \"^6.22.0\",\n    \"babel-preset-stage-2\": \"^6.22.0\",\n    \"babel-runtime\": \"^6.22.0\",\n    \"eslint\": \"^3.15.0\",\n    \"eslint-config-airbnb\": \"^14.1.0\",\n    \"eslint-plugin-import\": \"^2.2.0\",\n    \"eslint-plugin-jsx-a11y\": \"^4.0.0\",\n    \"eslint-plugin-react\": \"^6.9.0\",\n    \"extargsparse\": \"^0.2.2\"\n  },\n  \"ava\": {\n    \"require\": [\n      \"babel-register\"\n    ]\n  }\n}\n"
  },
  {
    "path": "src/index.js",
    "content": "import * as stock from './stock';\n\nexport { stock };\n"
  },
  {
    "path": "src/stock/billboard.js",
    "content": "import { lhbUrl, blockTradeUrl, longPeriodRankUrl } from './urls';\nimport { codeToSymbol, checkStatus } from './util';\nimport { DATE_NOW } from './cons';\nimport '../utils/fetch';\n\n/**\n * lhb - 获取龙虎榜数据\n * [\n *  {\n *    symbol: 股票代码\n *    name: 股票名称\n *    price: 收盘价格\n *    date: 日期哦\n *    changePercent: 涨跌幅\n *    type: 上榜理由\n *    volume: 成交量（手）\n *    amount: 成交额（万）\n *  }\n * ]\n */\nexport const lhb = (query = {}) => {\n  const defaults = {\n    start: DATE_NOW,\n    end: DATE_NOW,\n    pageNo: 1,\n    pageSize: 150,\n  };\n  const options = Object.assign({}, defaults, query);\n  const url = lhbUrl(options.start, options.end, options.pageNo, options.pageSize);\n  const mapData = data => {\n    const result = {};\n    result.page = data.page + 1;\n    result.total = data.total;\n    result.pageCount = data.pagecount;\n    result.items = data.list.map(item => ({\n      symbol: codeToSymbol(item.SYMBOL),\n      name: item.SNAME,\n      price: item.TCLOSE,\n      date: item.TDATE,\n      changePercent: item.PCHG,\n      type: item.SMEBTSTOCK1,\n      volume: item.VOTURNOVER * 100,\n      amount: item.VATURNOVER * 100,\n    }));\n    return { data: result };\n  };\n\n  return fetch(url)\n  .then(checkStatus)\n  .then(res => res.json())\n  .then(mapData)\n  .catch(error => ({ error }));\n};\n\n/**\n * blockTrade - 大宗交易\n * 返回数据格式:\n * [\n *  {\n *    symbol: 股票代码\n *    name: 股票名称\n *    dealPrice: 成交价\n *    price: 收盘价\n *    date: 日期\n *    volumn: 成交量（手）\n *    amout: 成交额（万）\n *    buyer: 买方\n *    seller: 卖方\n *    dopRate: 折溢价率\n *  }\n * ]\n */\nexport const blockTrade = (query = {}) => {\n  const defaults = {\n    start: DATE_NOW,\n    end: DATE_NOW,\n    pageNo: 1,\n    pageSize: 150,\n  };\n  const options = Object.assign({}, defaults, query);\n  const url = blockTradeUrl(options.start, options.end, options.pageNo, options.pageSize);\n  const mapData = data => {\n    const result = {};\n    result.page = data.page + 1;\n    result.total = data.total;\n    result.pageCount = data.pagecount;\n    result.items = data.list.map(item => ({\n      symbol: codeToSymbol(item.SYMBOL),\n      name: item.SNAME,\n      dealPrice: item.DZJY5,\n      price: item.TCLOSE,\n      date: item.PUBLISHDATE,\n      volume: item.DZJY2 * 100,\n      amount: item.DZJY6,\n      buyer: item.DZJY9,\n      seller: item.DZJY11,\n      dopRate: item.DZJY55,\n    }));\n    return { data: result };\n  };\n\n  return fetch(url)\n  .then(checkStatus)\n  .then(res => res.json())\n  .then(mapData)\n  .catch(error => ({ error }));\n};\n\n/**\n * longPeriodRank - 长期阶段涨跌幅\n * 返回数据格式:\n * [\n *  {\n *    symbol: 股票代码\n *    name: 股票名称\n *    price: 股票价格\n *    date: 时间\n *    dayPercent: 单日涨跌幅\n *    weekPercent: 周涨跌幅\n *    monthPercent: 月涨跌幅\n *    quarterPercent: 季度涨跌幅\n *    halfYearPercent: 半年涨跌幅\n *    yearPercent: 年度涨跌幅\n *  }\n * ]\n */\nexport const longPeriodRank = (query = {}) => {\n  const defaults = {\n    period: 'month',\n    pageNo: 1,\n    pageSize: 100,\n  };\n  const options = Object.assign({}, defaults, query);\n  const url = longPeriodRankUrl(options.period, options.pageNo, options.pageSize);\n  const mapData = data => {\n    const result = {};\n    result.page = data.page + 1;\n    result.total = data.total;\n    result.pageCount = data.pagecount;\n    result.items = data.list.map(item => ({\n      symbol: codeToSymbol(item.CODE),\n      name: item.NAME,\n      price: item.PRICE,\n      date: item.LONG_PERIOD_RANK.TIME,\n      dayPercent: item['PERCENT'],\n      weekPercent: item['LONG_PERIOD_RANK']['WEEK_PERCENT'],\n      monthPercent: item['LONG_PERIOD_RANK']['MONTH_PERCENT'],\n      quarterPercent: item['LONG_PERIOD_RANK']['QUARTER_PERCENT'],\n      halfYearPercent: item['LONG_PERIOD_RANK']['HALF_YEAR_PERCENT'],\n      yearPercent: item['LONG_PERIOD_RANK']['YEAR_PERCENT'],\n    }));\n    return { data: result };\n  };\n\n  return fetch(url)\n  .then(checkStatus)\n  .then(res => res.json())\n  .then(mapData)\n  .catch(error => ({ error }));\n};\n"
  },
  {
    "path": "src/stock/classifying.js",
    "content": "import {\n  sinaIndustryIndexUrl,\n  sinaClassifyDetailUrl,\n  sinaConceptsIndexUrl,\n  allStockUrl,\n  hs300Url,\n  sz50Url,\n  xsgUrl,\n} from './urls';\nimport { csvToObject, arrayObjectMapping, checkStatus } from './util';\nimport { charset } from '../utils/charset';\nimport '../utils/fetch';\n\n/**\n * getSinaIndustryClassified: 获取新浪行业板块数据\n * 返回数据格式 - 数组，包含：\n * tag: 新浪行业分类标识\n * name: 新浪行业分类名称\n * num: 行业包含股票数量\n * price: 平均价\n * changePrice: 涨跌额\n * changePercent: 涨跌幅\n * volume: 总成交量（手）\n * amount: 总成交额（万）\n * leadingSymbol: 领涨股票代码\n * leadingChangePercent: 领涨股涨跌幅\n * leadingPrice: 领涨股价格\n * leadingChangePrice: 领涨股涨跌额\n * leadingName: 领涨股名称\n */\nexport const getSinaIndustryClassified = () => {\n  const url = sinaIndustryIndexUrl();\n  const mapData = data => {\n    const result = [];\n    const json = JSON.parse(data.split('=')[1].trim());\n    Object.keys(json).forEach(tag => {\n      const industryArr = json[tag].split(',');\n      result.push({\n        tag: industryArr[0],\n        name: industryArr[1],\n        num: industryArr[2],\n        price: industryArr[3],\n        changePrice: industryArr[4],\n        changePercent: industryArr[5],\n        volume: industryArr[6] / 100,\n        amount: industryArr[7] / 10000,\n        leadingSymbol: industryArr[8],\n        leadingChangePercent: industryArr[9],\n        leadingPrice: industryArr[10],\n        leadingChangePrice: industryArr[11],\n        leadingName: industryArr[12],\n      });\n    });\n    return { data: result };\n  };\n\n  return fetch(url, { disableDecoding: true })\n    .then(checkStatus)\n    .then(charset('GBK'))\n    .then(mapData)\n    .catch(error => ({ error }));\n};\n\n/**\n * getClassifyDetails - 获取新浪某个行业分类下的股票数据\n * 返回数组:\n * [\n *  {\n *    symbol: 股票代码\n *    name: 股票名称\n *    price: 当前价格\n *    changePrice: 涨跌额\n *    changePercent: 涨跌幅\n *    open: 开盘价\n *    high: 最高价\n *    low: 最低价\n *    volume: 成交量（手）\n *    amount: 成交额（万）\n *    tickTime: 数据时间\n *  }\n * ]\n *\n * @param {Object} options\n * @param {string} options.tag - 新浪行业代码，从getSinaIndustryClassified返回，例如new_jrhy: 金融行业\n * @param cb\n * @return {undefined}\n */\n/* eslint-disable no-eval */\nexport const getSinaClassifyDetails = (query = {}) => {\n  const defaults = {\n    tag: 'new_jrhy', // 默认金融行业\n  };\n  const options = Object.assign({}, defaults, query);\n  const url = sinaClassifyDetailUrl(options.tag);\n  const mapData = data => {\n    let result = [];\n    result = eval(data);\n    if (result) {\n      result = result.map(ele => ({\n        symbol: ele.symbol,\n        name: ele.name,\n        price: ele.trade,\n        changePrice: ele.pricechange,\n        changePercent: ele.changepercent,\n        open: ele.open,\n        high: ele.high,\n        low: ele.low,\n        volume: ele.volume / 100,\n        amount: ele.amount / 10000,\n        tickTime: ele.ticktime,\n      }));\n    }\n    return { data: result };\n  };\n\n  return fetch(url, { disableDecoding: true })\n    .then(checkStatus)\n    .then(charset('GBK'))\n    .then(mapData)\n    .catch(error => ({ error }));\n};\n\n/**\n * getSinaConceptsClassified - 获取新浪概念板块分类数据\n * 返回数据格式 - 数组，包含：\n * tag: 新浪概念分类标识\n * name: 新浪概念分类名称\n * num: 概念包含股票数量\n * price: 平均价\n * changePrice: 涨跌额\n * changePercent: 涨跌幅\n * volume: 总成交量（手）\n * amount: 总成交额（万）\n * leadingSymbol: 领涨股票代码\n * leadingChangePercent: 领涨股涨跌幅\n * leadingPrice: 领涨股价格\n * leadingChangePrice: 领涨股涨跌额\n * leadingName: 领涨股名称\n *\n * @param cb\n * @returns {undefined}\n */\nexport const getSinaConceptsClassified = () => {\n  const url = sinaConceptsIndexUrl();\n  const mapData = data => {\n    const json = JSON.parse(data.split('=')[1].trim());\n    const result = Object.keys(json).map(tag => {\n      const conceptsArr = json[tag].split(',');\n      return {\n        name: conceptsArr[1],\n        num: conceptsArr[2],\n        price: conceptsArr[3],\n        changePrice: conceptsArr[4],\n        changePercent: conceptsArr[5],\n        volume: conceptsArr[6] / 100,\n        amount: conceptsArr[7] / 10000,\n        leadingSymbol: conceptsArr[8],\n        leadingChangePercent: conceptsArr[9],\n        leadingPrice: conceptsArr[10],\n        leadingChangePrice: conceptsArr[11],\n        leadingName: conceptsArr[12],\n      };\n    });\n    return { data: result };\n  };\n\n  return fetch(url)\n    .then(checkStatus)\n    .then(charset('GBK'))\n    .then(mapData)\n    .catch(error => ({ error }));\n};\n\n/**\n * getAllStocks - 返回沪深上市公司基本情况\n * 返回数据格式:\n * [\n *  {\n *    code,代码\n *    name,名称\n *    industry,所属行业\n *    area,地区\n *    pe,市盈率\n *    outstanding,流通股本\n *    totals,总股本(万)\n *    totalAssets,总资产(万)\n *    liquidAssets,流动资产\n *    fixedAssets,固定资产\n *    reserved,公积金\n *    reservedPerShare,每股公积金\n *    eps,每股收益\n *    bvps,每股净资\n *    pb,市净率\n *    timeToMarket,上市日期\n *  }\n * ]\n *\n * @param cb\n * @returns {undefined}\n */\nexport const getAllStocks = () => {\n  const url = allStockUrl();\n\n  return fetch(url)\n    .then(checkStatus)\n    .then(charset('GBK'))\n    .then(data => ({ data: csvToObject(data) }))\n    .catch(error => ({ error }));\n};\n\n/**\n * getHS300 - 获取沪深300股票信息\n * 返回数据格式: 数组\n * [\n *   {\n *     symbol: 股票代码, 如：sh600000\n *     name: 股票名称\n *     trade: 最新价\n *     pricechange: 涨跌额\n *     changepercent: 涨跌幅\n *     buy: 买入价\n *     sell: 卖出价\n *     settlement: 昨收\n *     open: 开盘价\n *     high: 最高价\n *     low: 最低价\n *     volume: 成交量（手）\n *     amount: 成交额（万）\n *     code: 股票六位代码, 如: 600000\n *     ticktime:\n *     focus:\n *     fund:\n *   }\n * ]\n *\n * @param cb\n * @returns {undefined}\n */\nexport const getHS300 = () => {\n  const url = hs300Url();\n\n  return fetch(url)\n    .then(checkStatus)\n    .then(res => res.json())\n    .then(json => ({ data: arrayObjectMapping(json[0].fields, json[0].items) }))\n    .catch(error => ({ error }));\n};\n\n/**\n * getSZ50 - 获取上证50股票信息\n * 返回数据格式: 数组\n * [\n *   {\n *     symbol: 股票代码, 如：sh600000\n *     name: 股票名称\n *     trade: 最新价\n *     pricechange: 涨跌额\n *     changepercent: 涨跌幅\n *     buy: 买入价\n *     sell: 卖出价\n *     settlement: 昨收\n *     open: 开盘价\n *     high: 最高价\n *     low: 最低价\n *     volume: 成交量（手）\n *     amount: 成交额（万）\n *     code: 股票六位代码, 如: 600000\n *     ticktime:\n *     focus:\n *     fund:\n *   }\n * ]\n *\n * @param cb\n * @returns {undefined}\n */\nexport const getSZ50 = () => {\n  const url = sz50Url();\n\n  return fetch(url)\n    .then(checkStatus)\n    .then(res => res.json())\n    .then(json => ({ data: arrayObjectMapping(json[0].fields, json[0].items) }))\n    .catch(error => ({ error }));\n};\n\n/**\n * 获取指定年月限售解禁股数据\n * 返回数据格式: 数组\n * [\n *   {\n *     symbol: 股票代码\n *     name: 股票名称\n *     date: 解除限售日期\n *     percent: 占总股本比例\n *     count: 数量（万股）\n *     close: 最新收盘价（元）\n *     curTotalValue: 当前市值（亿元）\n *   }\n * ]\n * @param year\n * @param month\n * @returns {Promise.<TResult>}\n */\nexport const getXSGData = (year, month) => {\n  const url = xsgUrl(year, month);\n  const mapData = data => {\n    let arr = JSON.parse(data.substring(1, data.length - 1));\n    arr = arr.map(item => {\n      const itemData = item.split(',');\n      return {\n        symbol: itemData[1],\n        name: itemData[3],\n        date: itemData[4],\n        percent: itemData[6],\n        count: (itemData[5] / 10000).toFixed(2),\n        close: itemData[7],\n        curTotalValue: (itemData[8] / 100000000).toFixed(4),\n      };\n    });\n    return arr;\n  };\n  return fetch(url)\n    .then(checkStatus)\n    .then(res => res.text())\n    .then(mapData)\n    .catch(error => ({ error }));\n};\n\n"
  },
  {
    "path": "src/stock/cons.js",
    "content": "import strftime from 'strftime';\n\nexport const K_TYPE = {\n  day: 'akdaily',\n  week: 'akweekly',\n  month: 'akmonthly',\n  minute: 'akmin',\n};\n\nexport const INDEX_LABELS = ['sh', 'sz', 'hs300', 'sz50', 'cyb', 'zxb', 'zx300', 'zh500'];\nexport const K_LABELS = ['day', 'month', 'week'];\nexport const K_MIN_LABELS = ['1', '5', '15', '30', '30'];\n\nexport const INDEX_LIST = {\n  sh: 'sh000001',\n  sz: 'sz399001',\n  hs300: 'sz399300',\n  sz50: 'sh000016',\n  zxb: 'sz399005',\n  cyb: 'sz399006',\n  zx300: 'sz399008',\n  zh500: 'sh000905',\n  399990: 'sz399990',\n  '000006': 'sh000006',\n  399998: 'sz399998',\n  399436: 'sz399436',\n  399678: 'sz399678',\n  399804: 'sz399804',\n  '000104': 'sh000104',\n  '000070': 'sh000070',\n  399613: 'sz399613',\n  399690: 'sz399690',\n  399928: 'sz399928',\n  '000928': 'sh000928',\n  '000986': 'sh000986',\n  399806: 'sz399806',\n  '000032': 'sh000032',\n  '000005': 'sh000005',\n  399381: 'sz399381',\n  399908: 'sz399908',\n  '000908': 'sh000908',\n  399691: 'sz399691',\n  '000139': 'sh000139',\n  399427: 'sz399427',\n  399248: 'sz399248',\n  '000832': 'sh000832',\n  399901: 'sz399901',\n  399413: 'sz399413',\n  '000901': 'sh000901',\n  '000078': 'sh000078',\n  '000944': 'sh000944',\n  '000025': 'sh000025',\n  399944: 'sz399944',\n  399307: 'sz399307',\n  '000052': 'sh000052',\n  399680: 'sz399680',\n  399232: 'sz399232',\n  399993: 'sz399993',\n  '000102': 'sh000102',\n  '000950': 'sh000950',\n  399950: 'sz399950',\n  399244: 'sz399244',\n  399925: 'sz399925',\n  '000925': 'sh000925',\n  '000003': 'sh000003',\n  '000805': 'sh000805',\n  '000133': 'sh000133',\n  399677: 'sz399677',\n  399319: 'sz399319',\n  399397: 'sz399397',\n  399983: 'sz399983',\n  399654: 'sz399654',\n  399440: 'sz399440',\n  '000043': 'sh000043',\n  '000012': 'sh000012',\n  '000833': 'sh000833',\n  '000145': 'sh000145',\n  '000053': 'sh000053',\n  '000013': 'sh000013',\n  '000022': 'sh000022',\n  '000094': 'sh000094',\n  399299: 'sz399299',\n  '000101': 'sh000101',\n  399817: 'sz399817',\n  399481: 'sz399481',\n  399434: 'sz399434',\n  399301: 'sz399301',\n  '000029': 'sh000029',\n  399812: 'sz399812',\n  399441: 'sz399441',\n  '000098': 'sh000098',\n  399557: 'sz399557',\n  '000068': 'sh000068',\n  399298: 'sz399298',\n  399302: 'sz399302',\n  '000961': 'sh000961',\n  '000959': 'sh000959',\n  399961: 'sz399961',\n  '000126': 'sh000126',\n  '000036': 'sh000036',\n  399305: 'sz399305',\n  '000116': 'sh000116',\n  399359: 'sz399359',\n  399810: 'sz399810',\n  '000062': 'sh000062',\n  399618: 'sz399618',\n  399435: 'sz399435',\n  '000149': 'sh000149',\n  '000819': 'sh000819',\n  '000020': 'sh000020',\n  '000061': 'sh000061',\n  '000016': 'sh000016',\n  '000028': 'sh000028',\n  399809: 'sz399809',\n  '000999': 'sh000999',\n  399238: 'sz399238',\n  '000100': 'sh000100',\n  399979: 'sz399979',\n  '000979': 'sh000979',\n  399685: 'sz399685',\n  '000152': 'sh000152',\n  '000153': 'sh000153',\n  399318: 'sz399318',\n  '000853': 'sh000853',\n  '000040': 'sh000040',\n  399693: 'sz399693',\n  '000076': 'sh000076',\n  '000017': 'sh000017',\n  '000134': 'sh000134',\n  399989: 'sz399989',\n  '000042': 'sh000042',\n  '000066': 'sh000066',\n  '000008': 'sh000008',\n  '000002': 'sh000002',\n  '000001': 'sh000001',\n  '000011': 'sh000011',\n  '000031': 'sh000031',\n  399403: 'sz399403',\n  '000951': 'sh000951',\n  399951: 'sz399951',\n  '000092': 'sh000092',\n  399234: 'sz399234',\n  '000823': 'sh000823',\n  399986: 'sz399986',\n  399647: 'sz399647',\n  '000050': 'sh000050',\n  '000073': 'sh000073',\n  399357: 'sz399357',\n  '000940': 'sh000940',\n  '000107': 'sh000107',\n  '000048': 'sh000048',\n  399411: 'sz399411',\n  399366: 'sz399366',\n  399373: 'sz399373',\n  '000015': 'sh000015',\n  '000021': 'sh000021',\n  '000151': 'sh000151',\n  '000851': 'sh000851',\n  '000058': 'sh000058',\n  399404: 'sz399404',\n  399102: 'sz399102',\n  399431: 'sz399431',\n  399971: 'sz399971',\n  '000125': 'sh000125',\n  '000069': 'sh000069',\n  '000063': 'sh000063',\n  399395: 'sz399395',\n  '000038': 'sh000038',\n  399240: 'sz399240',\n  399903: 'sz399903',\n  '000989': 'sh000989',\n  399321: 'sz399321',\n  399675: 'sz399675',\n  399235: 'sz399235',\n  '000057': 'sh000057',\n  '000056': 'sh000056',\n  '000903': 'sh000903',\n  399310: 'sz399310',\n  '000004': 'sh000004',\n  '000019': 'sh000019',\n  399919: 'sz399919',\n  '000974': 'sh000974',\n  '000919': 'sh000919',\n  399635: 'sz399635',\n  399663: 'sz399663',\n  399106: 'sz399106',\n  399107: 'sz399107',\n  399555: 'sz399555',\n  '000090': 'sh000090',\n  '000155': 'sh000155',\n  '000060': 'sh000060',\n  399636: 'sz399636',\n  '000816': 'sh000816',\n  '000010': 'sh000010',\n  399671: 'sz399671',\n  '000035': 'sh000035',\n  399352: 'sz399352',\n  399683: 'sz399683',\n  399554: 'sz399554',\n  399409: 'sz399409',\n  '000018': 'sh000018',\n  399101: 'sz399101',\n  '000992': 'sh000992',\n  399416: 'sz399416',\n  399918: 'sz399918',\n  399379: 'sz399379',\n  399674: 'sz399674',\n  399239: 'sz399239',\n  399384: 'sz399384',\n  399367: 'sz399367',\n  '000918': 'sh000918',\n  '000914': 'sh000914',\n  399914: 'sz399914',\n  '000054': 'sh000054',\n  '000806': 'sh000806',\n  399619: 'sz399619',\n  399015: 'sz399015',\n  399393: 'sz399393',\n  399313: 'sz399313',\n  399231: 'sz399231',\n  '000846': 'sh000846',\n  '000854': 'sh000854',\n  399010: 'sz399010',\n  399666: 'sz399666',\n  399387: 'sz399387',\n  399399: 'sz399399',\n  '000026': 'sh000026',\n  399934: 'sz399934',\n  '000150': 'sh000150',\n  '000934': 'sh000934',\n  399317: 'sz399317',\n  '000138': 'sh000138',\n  399371: 'sz399371',\n  399394: 'sz399394',\n  399659: 'sz399659',\n  399665: 'sz399665',\n  399931: 'sz399931',\n  '000161': 'sh000161',\n  399380: 'sz399380',\n  '000931': 'sh000931',\n  399704: 'sz399704',\n  399616: 'sz399616',\n  '000817': 'sh000817',\n  399303: 'sz399303',\n  399629: 'sz399629',\n  399624: 'sz399624',\n  399009: 'sz399009',\n  399233: 'sz399233',\n  399103: 'sz399103',\n  399242: 'sz399242',\n  399627: 'sz399627',\n  '000971': 'sh000971',\n  399679: 'sz399679',\n  399912: 'sz399912',\n  '000982': 'sh000982',\n  399668: 'sz399668',\n  '000096': 'sh000096',\n  399982: 'sz399982',\n  '000849': 'sh000849',\n  '000148': 'sh000148',\n  399364: 'sz399364',\n  '000912': 'sh000912',\n  '000129': 'sh000129',\n  '000055': 'sh000055',\n  '000047': 'sh000047',\n  399355: 'sz399355',\n  399622: 'sz399622',\n  '000033': 'sh000033',\n  399640: 'sz399640',\n  '000852': 'sh000852',\n  399966: 'sz399966',\n  399615: 'sz399615',\n  399802: 'sz399802',\n  399602: 'sz399602',\n  '000105': 'sh000105',\n  399660: 'sz399660',\n  399672: 'sz399672',\n  399913: 'sz399913',\n  399420: 'sz399420',\n  '000159': 'sh000159',\n  399314: 'sz399314',\n  399652: 'sz399652',\n  399369: 'sz399369',\n  '000913': 'sh000913',\n  '000065': 'sh000065',\n  '000808': 'sh000808',\n  399386: 'sz399386',\n  399100: 'sz399100',\n  '000997': 'sh000997',\n  '000990': 'sh000990',\n  '000093': 'sh000093',\n  399637: 'sz399637',\n  399439: 'sz399439',\n  399306: 'sz399306',\n  '000855': 'sh000855',\n  '000123': 'sh000123',\n  399623: 'sz399623',\n  399312: 'sz399312',\n  399249: 'sz399249',\n  399311: 'sz399311',\n  399975: 'sz399975',\n  399356: 'sz399356',\n  399400: 'sz399400',\n  399676: 'sz399676',\n  '000136': 'sh000136',\n  399361: 'sz399361',\n  399974: 'sz399974',\n  399995: 'sz399995',\n  399316: 'sz399316',\n  399701: 'sz399701',\n  '000300': 'sh000300',\n  '000030': 'sh000030',\n  '000976': 'sh000976',\n  399686: 'sz399686',\n  399108: 'sz399108',\n  399374: 'sz399374',\n  '000906': 'sh000906',\n  399707: 'sz399707',\n  '000064': 'sh000064',\n  399633: 'sz399633',\n  399300: 'sz399300',\n  399628: 'sz399628',\n  399398: 'sz399398',\n  '000034': 'sh000034',\n  399644: 'sz399644',\n  399905: 'sz399905',\n  399626: 'sz399626',\n  399625: 'sz399625',\n  '000978': 'sh000978',\n  399664: 'sz399664',\n  399682: 'sz399682',\n  399322: 'sz399322',\n  '000158': 'sh000158',\n  '000842': 'sh000842',\n  399550: 'sz399550',\n  399423: 'sz399423',\n  399978: 'sz399978',\n  399996: 'sz399996',\n  '000905': 'sh000905',\n  '000007': 'sh000007',\n  '000827': 'sh000827',\n  399655: 'sz399655',\n  399401: 'sz399401',\n  399650: 'sz399650',\n  '000963': 'sh000963',\n  399661: 'sz399661',\n  399922: 'sz399922',\n  '000091': 'sh000091',\n  399375: 'sz399375',\n  '000922': 'sh000922',\n  399702: 'sz399702',\n  399963: 'sz399963',\n  399011: 'sz399011',\n  399012: 'sz399012',\n  399383: 'sz399383',\n  399657: 'sz399657',\n  399910: 'sz399910',\n  399351: 'sz399351',\n  '000910': 'sh000910',\n  '000051': 'sh000051',\n  399376: 'sz399376',\n  399639: 'sz399639',\n  '000821': 'sh000821',\n  399360: 'sz399360',\n  399604: 'sz399604',\n  399315: 'sz399315',\n  399658: 'sz399658',\n  '000135': 'sh000135',\n  '000059': 'sh000059',\n  399006: 'sz399006',\n  399320: 'sz399320',\n  '000991': 'sh000991',\n  399606: 'sz399606',\n  399428: 'sz399428',\n  399406: 'sz399406',\n  399630: 'sz399630',\n  '000802': 'sh000802',\n  399803: 'sz399803',\n  '000071': 'sh000071',\n  399358: 'sz399358',\n  399013: 'sz399013',\n  399385: 'sz399385',\n  399008: 'sz399008',\n  399649: 'sz399649',\n  399673: 'sz399673',\n  399418: 'sz399418',\n  399370: 'sz399370',\n  '000814': 'sh000814',\n  399002: 'sz399002',\n  399814: 'sz399814',\n  399641: 'sz399641',\n  399001: 'sz399001',\n  399662: 'sz399662',\n  399706: 'sz399706',\n  399932: 'sz399932',\n  '000095': 'sh000095',\n  '000932': 'sh000932',\n  399965: 'sz399965',\n  399363: 'sz399363',\n  399354: 'sz399354',\n  399638: 'sz399638',\n  399648: 'sz399648',\n  399608: 'sz399608',\n  '000939': 'sh000939',\n  399939: 'sz399939',\n  399365: 'sz399365',\n  399382: 'sz399382',\n  399631: 'sz399631',\n  399612: 'sz399612',\n  399611: 'sz399611',\n  399645: 'sz399645',\n  399324: 'sz399324',\n  399552: 'sz399552',\n  '000858': 'sh000858',\n  '000045': 'sh000045',\n  '000121': 'sh000121',\n  399703: 'sz399703',\n  399003: 'sz399003',\n  399348: 'sz399348',\n  399389: 'sz399389',\n  399007: 'sz399007',\n  399391: 'sz399391',\n  '000973': 'sh000973',\n  '000984': 'sh000984',\n  '000969': 'sh000969',\n  '000952': 'sh000952',\n  399332: 'sz399332',\n  399952: 'sz399952',\n  399553: 'sz399553',\n  '000856': 'sh000856',\n  399969: 'sz399969',\n  399643: 'sz399643',\n  399402: 'sz399402',\n  399372: 'sz399372',\n  399632: 'sz399632',\n  399344: 'sz399344',\n  399808: 'sz399808',\n  399620: 'sz399620',\n  '000103': 'sh000103',\n  399911: 'sz399911',\n  '000993': 'sh000993',\n  '000983': 'sh000983',\n  399687: 'sz399687',\n  399933: 'sz399933',\n  '000933': 'sh000933',\n  399437: 'sz399437',\n  399433: 'sz399433',\n  '000046': 'sh000046',\n  '000911': 'sh000911',\n  '000114': 'sh000114',\n  '000049': 'sh000049',\n  399392: 'sz399392',\n  399653: 'sz399653',\n  '000975': 'sh000975',\n  '000044': 'sh000044',\n  399378: 'sz399378',\n  '000828': 'sh000828',\n  399634: 'sz399634',\n  399005: 'sz399005',\n  '000162': 'sh000162',\n  399333: 'sz399333',\n  '000122': 'sh000122',\n  399646: 'sz399646',\n  '000077': 'sh000077',\n  '000074': 'sh000074',\n  399656: 'sz399656',\n  399396: 'sz399396',\n  399415: 'sz399415',\n  399408: 'sz399408',\n  '000115': 'sh000115',\n  '000987': 'sh000987',\n  399362: 'sz399362',\n  '000841': 'sh000841',\n  '000141': 'sh000141',\n  '000120': 'sh000120',\n  399992: 'sz399992',\n  '000807': 'sh000807',\n  399350: 'sz399350',\n  '000009': 'sh000009',\n  '000998': 'sh000998',\n  399390: 'sz399390',\n  399405: 'sz399405',\n  '000099': 'sh000099',\n  399337: 'sz399337',\n  '000142': 'sh000142',\n  399419: 'sz399419',\n  399407: 'sz399407',\n  '000909': 'sh000909',\n  '000119': 'sh000119',\n  399909: 'sz399909',\n  399805: 'sz399805',\n  '000996': 'sh000996',\n  '000847': 'sh000847',\n  '000130': 'sh000130',\n  399377: 'sz399377',\n  399388: 'sz399388',\n  399610: 'sz399610',\n  '000958': 'sh000958',\n  399958: 'sz399958',\n  '000075': 'sh000075',\n  399346: 'sz399346',\n  '000147': 'sh000147',\n  '000132': 'sh000132',\n  '000108': 'sh000108',\n  399642: 'sz399642',\n  '000977': 'sh000977',\n  399689: 'sz399689',\n  399335: 'sz399335',\n  399977: 'sz399977',\n  399972: 'sz399972',\n  399970: 'sz399970',\n  399004: 'sz399004',\n  399341: 'sz399341',\n  399330: 'sz399330',\n  399917: 'sz399917',\n  '000160': 'sh000160',\n  399432: 'sz399432',\n  399429: 'sz399429',\n  '000917': 'sh000917',\n  '000128': 'sh000128',\n  '000067': 'sh000067',\n  '000079': 'sh000079',\n  399236: 'sz399236',\n  399994: 'sz399994',\n  399237: 'sz399237',\n  '000966': 'sh000966',\n  '000957': 'sh000957',\n  399328: 'sz399328',\n  399353: 'sz399353',\n  399957: 'sz399957',\n  399412: 'sz399412',\n  '000904': 'sh000904',\n  399904: 'sz399904',\n  399410: 'sz399410',\n  '000027': 'sh000027',\n  399667: 'sz399667',\n  '000857': 'sh000857',\n  '000131': 'sh000131',\n  '000964': 'sh000964',\n  399339: 'sz399339',\n  399964: 'sz399964',\n  399991: 'sz399991',\n  399417: 'sz399417',\n  '000146': 'sh000146',\n  399551: 'sz399551',\n  '000137': 'sh000137',\n  '000118': 'sh000118',\n  399976: 'sz399976',\n  '000109': 'sh000109',\n  399681: 'sz399681',\n  399438: 'sz399438',\n  '000117': 'sh000117',\n  399614: 'sz399614',\n  399669: 'sz399669',\n  '000111': 'sh000111',\n  399670: 'sz399670',\n  '000097': 'sh000097',\n  '000106': 'sh000106',\n  '000039': 'sh000039',\n  399935: 'sz399935',\n  '000935': 'sh000935',\n  399813: 'sz399813',\n  '000037': 'sh000037',\n  399811: 'sz399811',\n  399705: 'sz399705',\n  399556: 'sz399556',\n  '000113': 'sh000113',\n  '000072': 'sh000072',\n  399651: 'sz399651',\n  399617: 'sz399617',\n  399684: 'sz399684',\n  '000041': 'sh000041',\n  399807: 'sz399807',\n  399959: 'sz399959',\n  399967: 'sz399967',\n  399326: 'sz399326',\n  399688: 'sz399688',\n  399368: 'sz399368',\n  399241: 'sz399241',\n  399696: 'sz399696',\n  '000850': 'sh000850',\n  '000110': 'sh000110',\n  399621: 'sz399621',\n  399243: 'sz399243',\n  399973: 'sz399973',\n  399987: 'sz399987',\n  '000112': 'sh000112',\n  399997: 'sz399997',\n  hkHSI: 'hkHSI',\n};\n\nexport const DATE_NOW = strftime('%Y-%m-%d', new Date());\nexport const CUR_YEAR = DATE_NOW.split('-')[0];\nexport const CUR_MONTH = DATE_NOW.split('-')[1];\n"
  },
  {
    "path": "src/stock/index.js",
    "content": "export * from './trading';\nexport * from './classifying';\nexport * from './billboard';\n"
  },
  {
    "path": "src/stock/trading.js",
    "content": "import { unnest } from 'ramda';\nimport util from 'util';\n\n/* eslint-disable no-console */\nimport {\n  priceUrl,\n  tickUrl,\n  todayAllUrl,\n  liveDataUrl,\n  todayTickUrl,\n  indexUrl,\n  sinaDDUrl,\n  klineTTUrl,\n  klineTTMinUrl,\n} from './urls';\n\nimport * as cons from './cons';\nimport { codeToSymbol, checkStatus, DATE_NOW, randomString, runTasksInParallel, createFetchTasks } from './util';\nimport { charset } from '../utils/charset';\nimport '../utils/fetch';\nimport { ttDates } from '../utils/dateu';\n\n/**\n * getHistory: 获取个股历史数据\n * 返回数据格式 - 日期 ，开盘价， 最高价， 收盘价， 最低价， 成交量， 价格变动 ，涨跌幅，5日均价，10日均价，20日均价，5日均量，10日均量，20日均量，换手率\n *\n * @param {Object} options = {} - options\n * @param {String} options.code - 股票代码, 例如： '600848'\n * @param {String} options.start - 开始日期 format：YYYY-MM-DD 为空时取到API所提供的最早日期数据\n * @param {String} options.end - 结束日期 format：YYYY-MM-DD 为空时取到最近一个交易日数据\n * @param {String} options.ktype - 数据类型，day=日k线 week=周 month=月 5=5分钟 15=15分钟 30=30分钟 60=60分钟，默认为day\n * @param {String} options.autype - 复权类型，默认前复权, fq=前复权, last=不复权\n * @return {undefined}\n */\nexport const getHistory = (query = {}) => {\n  const defaults = {\n    code: null,\n    start: null,\n    end: null,\n    ktype: 'day',\n    autype: 'fq',\n  };\n  const options = Object.assign({}, defaults, query);\n\n  const symbol = codeToSymbol(options.code);\n  const url = priceUrl(options.ktype, options.autype, symbol);\n\n  return fetch(url)\n  .then(checkStatus)\n  .then(res => res.json())\n  .then(json => ({ data: json }))\n  .catch(error => ({ error }));\n};\n\nconst getTimeTick = ts => {\n  const sarr = ts.split('-');\n  let retval = 0;\n  if (sarr.length >= 3) {\n    retval += parseInt(sarr[0], 10) * 100 * 100;\n    retval += parseInt(sarr[1], 10) * 100;\n    retval += parseInt(sarr[2], 10);\n    retval *= 10000;\n  } else {\n    retval += parseInt(ts, 10);\n  }\n  return retval;\n};\n\nconst getSymbol = ({ code, isIndex }) => {\n  if (isIndex && code in cons.INDEX_LIST) {\n    return cons.INDEX_LIST[code];\n  }\n  return codeToSymbol(code);\n};\n\nconst getEndDate = ({ start, end }) => (start && !end ? cons.DATE_NOW : end);\n\nconst getFq = ({ autype, code, isIndex }) => {\n  let fq = autype || '';\n  if (code[0] === '1' || code[0] === '5' || isIndex) {\n    fq = '';\n  }\n  return fq;\n};\n\nconst getKline = ({ autype }) => (autype ? 'fq' : '');\n\nconst parseKData = (rawData, ktype, code) => {\n  const rawDataArray = rawData.split('=');\n  if (rawDataArray.length > 1) {\n    const json = JSON.parse(rawDataArray[1].replace(/,\\{\"nd.*?\\}/, ''));\n    if ('data' in json && code in json['data'] && ktype in json['data'][code]) {\n      return json['data'][code][ktype];\n    }\n  }\n  return [];\n};\n\nconst getKDataLong = (options = {}) => {\n  if (!cons.K_LABELS.includes(options.ktype)) {\n    throw new Error(util.format('unknown ktype %s', options.ktype));\n  }\n\n  const kline = getKline(options);\n  const fq = getFq(options);\n  const symbol = getSymbol(options);\n  const sdate = options.start;\n  const edate = getEndDate(options);\n  let urls = [];\n\n  if (!sdate && !edate) {\n    const randomstr = randomString(17);\n    const url = klineTTUrl(kline, fq, symbol, options.ktype, sdate, edate, fq, randomstr);\n    urls = urls.concat(url);\n  } else {\n    const years = ttDates(sdate, edate);\n    urls = years.map(year => {\n      const startOfYear = util.format('%s-01-01', year);\n      const endOfYear = util.format('%s-12-31', year);\n\n      const randomstr = randomString(17);\n      return klineTTUrl(kline, year, symbol, options.ktype, startOfYear,\n        endOfYear, fq, randomstr);\n    });\n  }\n\n  const tasks = createFetchTasks(urls);\n  return runTasksInParallel(tasks)\n    .then(results => results.map(dataStr => parseKData(dataStr, options.ktype, symbol)))\n    .then(unnest);\n};\n\nconst getKDataShort = (options = {}) => {\n  if (!cons.K_MIN_LABELS.includes(options.ktype)) {\n    throw new Error(util.format('unknown ktype %s', options.ktype));\n  }\n\n  const symbol = getSymbol(options);\n  const sdate = options.start;\n  const edate = getEndDate(options);\n  const randomstr = randomString(16);\n  const ktype = util.format('m%s', options.ktype);\n  const url = klineTTMinUrl(symbol, options.ktype, randomstr);\n\n  return fetch(url)\n    .then(checkStatus)\n    .then(res => res.text())\n    .then(dataStr => parseKData(dataStr, ktype, symbol))\n    .then(data => data.filter(tick => {\n      const stick = getTimeTick(sdate);\n      const etick = getTimeTick(edate);\n      const curtick = getTimeTick(tick[0]);\n      return curtick >= stick && curtick <= etick;\n    }));\n};\n\n\n/**\n * getKData: 获取k线数据\n * 返回数据格式 - 日期 ，开盘价， 最高价， 收盘价， 最低价， 成交量， 价格变动 ，涨跌幅，5日均价，10日均价，20日均价，5日均量，10日均量，20日均量，换手率\n *\n * @param {Object} options = {} - options\n * @param {String} options.code - 股票代码, 例如： '600848'\n * @param {String} options.start - 开始日期 format：YYYY-MM-DD 为空时取到API所提供的最早日期数据\n * @param {String} options.end - 结束日期 format：YYYY-MM-DD 为空时取到最近一个交易日数据\n * @param {String} options.ktype - 数据类型，day=日k线 week=周 month=月 5=5分钟 15=15分钟 30=30分钟 60=60分钟，默认为day\n * @param {String} options.autype - 复权类型，默认前复权, fq=前复权, last=不复权\n * @param {Bool}   options.isIndex - 是否为指数，默认为false\n * @return {Promise object}      Promise Object 可以调用 then catch函数\n */\nexport const getKData = (query = {}) => {\n  const defaults = {\n    code: null,\n    start: '',\n    end: '',\n    ktype: 'day',\n    autype: 'fq',\n    isIndex: false,\n  };\n\n\n  const options = Object.assign({}, defaults, query);\n\n\n  if (cons.K_LABELS.includes(options.ktype)) {\n    return getKDataLong(options);\n  }\n\n  if (cons.K_MIN_LABELS.includes(options.ktype)) {\n    return getKDataShort(options);\n  }\n\n  throw new Error(util.format('not supported ktype %s', options.ktype));\n};\n\n\n/**\n * getTick - 获取历史分笔数据\n * 返回格式：成交时间 成交价  涨跌幅  价格变动  成交量(手)  成交额(元)  性质\n *\n * @param {Object} options\n * @param {string} options.code - 股票代码, 例如： '600848'\n * @param {string} options.date - 日期 格式：YYYY-MM-DD\n * @param cb\n * @return {undefined}\n */\nexport const getTick = (query = {}) => {\n  const defaults = {\n    code: null,\n    date: null,\n  };\n  const options = Object.assign({}, defaults, query);\n\n  const symbol = codeToSymbol(options.code);\n  const url = tickUrl(options.date, symbol);\n  const mapData = data => {\n    const result = [];\n    data.split('\\n').forEach((line, i) => {\n      if (i !== 0 && line !== '') {\n        result.push(line.split('\\t'));\n      }\n    });\n    return { data: result };\n  };\n\n  return fetch(url)\n  .then(checkStatus)\n  .then(charset('GBK'))\n  .then(mapData)\n  .catch(error => ({ error }));\n};\n\n/**\n * getTodayAll - 一次性获取最近一个日交易日所有股票的交易数据\n * 返回数据格式：代码，名称，涨跌幅，现价，开盘价，最高价，最低价，最日收盘价，成交量，换手率\n *\n * @param options - (可选) 若为空，则返回A股市场今日所有数据\n * @param {Number} options.pageSize - 分页的大小，如：80， 默认10000，即返回所有数据\n * @param {Number} options.pageNo - 分页页码，默认1\n * @param cb\n * @return {undefined}\n */\n/* eslint-disable no-eval */\nexport const getTodayAll = (query = {}) => {\n  const defaults = {\n    pageSize: 10000,\n    pageNo: 1,\n  };\n  const options = Object.assign({}, defaults, query);\n  const url = todayAllUrl(options.pageSize, options.pageNo);\n\n  return fetch(url)\n  .then(checkStatus)\n  .then(res => res.text())\n  .then(data => ({ data: eval(data) }))\n  .catch(error => ({ error }));\n};\n\n/**\n * getLiveData - 获取实时交易数据\n * 返回数据：{Array}\n * 0：股票代码\n * 1：股票名字\n * 2：今日开盘价\n * 3：昨日收盘价\n * 4：当前价格\n * 5：今日最高价\n * 6：今日最低价\n * 7：竞买价，即“买一”报价\n * 8：竞卖价，即“卖一”报价\n * 9：成交量 maybe you need do volume/100\n * 10：成交金额（元 CNY）\n * 11：委买一（笔数 bid volume）\n * 12：委买一（价格 bid price）\n * 13：“买二”\n * 14：“买二”\n * 15：“买三”\n * 16：“买三”\n * 17：“买四”\n * 18：“买四”\n * 19：“买五”\n * 20：“买五”\n * 21：委卖一（笔数 ask volume）\n * 22：委卖一（价格 ask price）\n * ...\n * 31：日期；\n * 32：时间；\n *\n * @param {Object} options\n * @param {Array} options.codes - 股票代码数组，例如['600848', '600000', '600343']\n * @param cb\n * @return {undefined}\n */\nexport const getLiveData = (query = {}) => {\n  const defaults = { codes: ['600000'] };\n  const options = Object.assign({}, defaults, query);\n  const codes = options.codes.map(code => codeToSymbol(code));\n  const url = liveDataUrl(codes);\n  const mapData = data => {\n    const result = data.split('\\n')\n    .filter(item => item !== '')\n    .map(item => {\n      const matches = item.match(/(sz|sh)(\\d{6}).*\"(.*)\"/i);\n      const symbol = matches[1] + matches[2];\n      const records = matches[3].split(',');\n      return [symbol, ...records];\n    });\n\n    return { data: result };\n  };\n\n  return fetch(url)\n  .then(checkStatus)\n  .then(charset('GBK'))\n  .then(mapData)\n  .catch(error => ({ error }));\n};\n\n/**\n * getTodayTick - 获取当日分笔明细数据，用于在交易进行的时候获取\n * 返回数据：\n * {\n *  begin: 开始时间,\n *  end: 结束时间,\n *  zhubi_list: [\n *    {\n *      TRADE_TYPE: 交易类型, 1: 买盘，0：中性盘，-1：卖盘\n *      PRICE_PRE: 上一档价格\n *      PRICE: 当前价格\n *      VOLUME_INC: 成交量(股)\n *      TURNOVER_INC: 成交额\n *      TRADE_TYPE_STR: 交易类型：买盘、卖盘、中性盘\n *      DATE_STR: 时间\n *    }\n *  ]\n * }\n *\n * @param {Object} options\n * @param {String} options.code - 六位股票代码\n * @param {String} options.end - 结束时间。例如：15:00:00, 那么就会获取14:55:00 - 15:00:00之间的分笔数据，也就是end指定时间之前的五分钟\n * @param cb\n * @return {undefined}\n */\nexport const getTodayTick = (query = {}) => {\n  const defaults = {\n    code: '600000',\n    end: '15:00:00',\n  };\n  const options = Object.assign({}, defaults, query);\n  const url = todayTickUrl(options.code, options.end);\n\n  return fetch(url)\n  .then(checkStatus)\n  .then(res => res.json())\n  .then(json => ({ data: json }))\n  .catch(error => ({ error }));\n};\n\nexport const getIndex = () => {\n  const url = indexUrl();\n  const mapData = data => {\n    const result = data.split('\\n')\n      .filter(item => item !== '')\n      .map(item => {\n        const matches = item.match(/(sz|sh)(\\d{6}).*\"(.*)\"/i);\n        const symbol = matches[1] + matches[2];\n        const records = matches[3].split(',');\n        return {\n          code: symbol,\n          name: records[0],\n          open: records[1],\n          preclose: records[2],\n          close: records[3],\n          high: records[4],\n          low: records[5],\n          volume: records[8],\n          amount: records[9],\n        };\n      });\n    return { data: result };\n  };\n\n  return fetch(url)\n  .then(checkStatus)\n  .then(charset('GBK'))\n  .then(mapData)\n  .catch(error => ({ error }));\n};\n\n/**\n * getSinaDD - 获取新浪大单数据\n * 返回数组：\n * [\n *  {\n *    symbol: 股票代码\n *    name: 股票名字\n *    time: 时间\n *    price: 成交价格\n *    volume: 成交量（手）\n *    preprice: 前一价格\n *    type: 类型，买盘、卖盘、中性盘\n *  }\n * ]\n *\n * @param {Object} options\n * @param {String} options.code - 六位股票代码\n * @param {String} options.volume - 设置多少手以上算大单，例如: 400，则返回400手以上交易量的大单\n * @param {String} options.date - 日期，格式YYYY-MM-DD， 默认当日日期\n * @param cb\n * @return {undefined}\n */\nexport const getSinaDD = (query = {}) => {\n  const defaults = {\n    code: '600000',\n    volume: 400,\n    date: DATE_NOW,\n  };\n  const options = Object.assign({}, defaults, query);\n  const url = sinaDDUrl(codeToSymbol(options.code), options.volume * 100, options.date);\n  const mapData = data => {\n    const result = data.split('\\n')\n      .filter((item, idx) => item !== '' && idx !== 0)\n      .map(item => {\n        const ddArr = item.split(',');\n        return {\n          symbol: ddArr[0],\n          name: ddArr[1],\n          time: ddArr[2],\n          price: ddArr[3],\n          volume: ddArr[4] / 100,\n          preprice: ddArr[5],\n          type: ddArr[6],\n        };\n      });\n    return { data: result };\n  };\n\n  return fetch(url)\n  .then(checkStatus)\n  .then(charset('GBK'))\n  .then(mapData)\n  .catch(error => ({ error }));\n};\n"
  },
  {
    "path": "src/stock/urls.js",
    "content": "import { K_TYPE, CUR_YEAR, CUR_MONTH } from './cons';\n\nexport const priceUrl = (ktype, autype, symbol) => {\n  const _ktype = K_TYPE[ktype] ? K_TYPE[ktype] : K_TYPE.minute;\n  const type = _ktype === K_TYPE.minute ? ktype : autype;\n  const codeStr = _ktype === K_TYPE.minute ? 'scode' : 'code';\n  return `http://api.finance.ifeng.com/${_ktype}/?${codeStr}=${symbol}&type=${type}`;\n};\n\nexport const tickUrl = (date, symbol) => `http://market.finance.sina.com.cn/downxls.php?date=${date}&symbol=${symbol}`;\n\nexport const todayAllUrl = (pageSize, pageNo) =>\n  `http://vip.stock.finance.sina.com.cn/quotes_service/api/json_v2.php/Market_Center.getHQNodeData?num=${pageSize}&sort=changepercent&asc=0&node=hs_a&symbol=&_s_r_a=page&page=${pageNo}`;\n\nexport const liveDataUrl = symbols => `http://hq.sinajs.cn/list=${symbols.join(',')}`;\n\nexport const todayTickUrl = (code, end = '15:00:00') => `http://quotes.money.163.com/service/zhubi_ajax.html?symbol=${code}&end=${end}`;\n\nexport const indexUrl = () =>\n  'http://hq.sinajs.cn/rn=xppzh&list=sh000001,sh000002,sh000003,sh000008,sh000009,sh000010,sh000011,sh000012,sh000016,sh000017,sh000300,sz399001,sz399002,sz399003,sz399004,sz399005,sz399006,sz399100,sz399101,sz399106,sz399107,sz399108,sz399333,sz399606';\n\nexport const klineTTUrl = (kline, fq, symbol, ktype, start, end, fq2, randomcode) =>\n      `http://web.ifzq.gtimg.cn/appstock/app/${kline}kline/get?_var=kline_day${fq}&param=${symbol},${ktype},${start},${end},640,${fq2}&r=0.${randomcode}`;\n\nexport const klineTTMinUrl = (symbol, ktype, randomcode) =>\n      `http://ifzq.gtimg.cn/appstock/app/kline/mkline?param=${symbol},m${ktype},,640&_var=m${ktype}_today&r=0.${randomcode}`;\n\nexport const sinaDDUrl = (symbol, volume, date) =>\n  `http://vip.stock.finance.sina.com.cn/quotes_service/view/cn_bill_download.php?symbol=${symbol}&num=60&page=1&sort=ticktime&asc=0&volume=${volume}&amount=0&type=0&day=${date}`;\n\nexport const sinaIndustryIndexUrl = () => 'http://vip.stock.finance.sina.com.cn/q/view/newSinaHy.php';\n\nexport const sinaClassifyDetailUrl = tag =>\n  `http://vip.stock.finance.sina.com.cn/quotes_service/api/json_v2.php/Market_Center.getHQNodeData?page=1&num=400&sort=symbol&asc=1&node=${tag}&symbol=&_s_r_a=page`;\n\nexport const sinaConceptsIndexUrl = () => 'http://money.finance.sina.com.cn/q/view/newFLJK.php?param=class';\n\nexport const allStockUrl = () => 'http://218.244.146.57/static/all.csv';\n\nexport const hs300Url = (pageNo = 1, pageSize = 300) =>\n  `http://money.finance.sina.com.cn/d/api/openapi_proxy.php/?__s=[[\"jjhq\",${pageNo},${pageSize},\"\",0,\"hs300\"]]`;\n\nexport const sz50Url = (pageNo = 1, pageSize = 50) =>\n  `http://money.finance.sina.com.cn/d/api/openapi_proxy.php/?__s=[[\"jjhq\",${pageNo},${pageSize},\"\",0,\"zhishu_000016\"]]`;\n\nexport function lhbUrl(start, end, pageNo = 1, pageSize = 150) {\n  const url = `http://quotes.money.163.com/hs/marketdata/service/lhb.php?page=${pageNo - 1}&query=start:${start};end:${end}&sort=TDATE&order=desc&count=${pageSize}`;\n  return url;\n}\n\nexport function blockTradeUrl(start, end, pageNo = 1, pageSize = 150) {\n  const url = `http://quotes.money.163.com/hs/marketdata/service/dzjy.php?page=${pageNo - 1}&query=start:${start};end:${end};&order=desc&count=${pageSize}&sort=PUBLISHDATE`;\n  return url;\n}\n\nexport function longPeriodRankUrl(period = 'month', pageNo = 1, pageSize = 100) {\n  let rankBy = '';\n  switch (period) {\n    case 'week':\n      rankBy = 'WEEK_PERCENT';\n      break;\n    case 'month':\n      rankBy = 'MONTH_PERCENT';\n      break;\n    case 'quarter':\n      rankBy = 'QUARTER_PERCENT';\n      break;\n    case 'year':\n      rankBy = 'YEAR_PERCENT';\n      break;\n    default:\n      rankBy = 'PERCENT';\n  }\n  const url = `http://quotes.money.163.com/hs/realtimedata/service/rank.php?page=${pageNo - 1}&query=LONG_PERIOD_RANK:_exists_&fields=RN,CODE,SYMBOL,NAME,PRICE,LONG_PERIOD_RANK,PERCENT&sort=LONG_PERIOD_RANK.${rankBy}&order=desc&count=${pageSize}`;\n  return url;\n}\n\nexport const xsgUrl = (year = CUR_YEAR, month = CUR_MONTH) => `http://datainterface.eastmoney.com/EM_DataCenter/JS.aspx?type=FD&sty=BST&st=3&sr=true&fd=${year}&stat=${month}`;\n"
  },
  {
    "path": "src/stock/util.js",
    "content": "import parallel from 'async/parallel';\nimport util from 'util';\n\nimport { INDEX_LABELS, INDEX_LIST } from './cons';\n\n\nexport function codeToSymbol(code) {\n  let symbol = '';\n  if (INDEX_LABELS.indexOf(code) >= 0) {\n    symbol = INDEX_LIST[code];\n  } else if (code.length === 6) {\n    symbol = ['5', '6', '9'].indexOf(code.charAt(0)) >= 0 ? `sh${code}` : `sz${code}`;\n  } else {\n    symbol = code;\n  }\n\n  return symbol;\n}\n\nexport function csvToObject(csv) {\n  let csvArr = csv.trim().split('\\r\\n');\n  let headers = csvArr.splice(0, 1);\n\n  headers = headers[0].split(',');\n  csvArr = csvArr.map(ele => {\n    const obj = {};\n    ele.split(',').forEach((s, i) => {\n      obj[headers[i]] = s;\n    });\n    return obj;\n  });\n\n  return csvArr;\n}\n\nexport function arrayObjectMapping(fields, items) {\n  return items.map(ele => {\n    const obj = {};\n    ele.forEach((s, i) => {\n      const field = fields[i];\n      if (field === 'volume') {\n        obj[field] = s / 100;\n      } else if (field === 'amount') {\n        obj[field] = s / 10000;\n      } else {\n        obj[field] = s;\n      }\n    });\n    return obj;\n  });\n}\n\nconst _pow = (base, exp) => {\n  let _b = base;\n  for (let _i = 0; _i < exp; _i += 1) {\n    _b *= base;\n  }\n  return _b;\n};\n\nexport function randomString(num) {\n  const lower = _pow(10, (num - 1));\n  const upper = _pow(10, num) - 1;\n  const rnum = lower + (Math.random() * (upper - lower));\n  return util.format('%s', rnum);\n}\n\nexport const checkStatus = response => {\n  if (response.status >= 200 && response.status < 300) {\n    return response;\n  }\n\n  const error = new Error(response.statusText);\n  error.response = response;\n  throw error;\n};\n\n/**\n * create a list of fetch tasks\n * return [promise, promise, ...]\n */\nexport const createFetchTasks = urls =>\n  urls.map(url =>\n    fetch(url)\n    .then(checkStatus)\n    .then(res => res.text())\n  );\n\n/**\n * @return [ [obj, obj, ...], [obj, obj, ...], ... ]\n */\nexport const runTasksInParallel = tasks =>\n  new Promise((resolve, reject) => {\n    parallel(\n      tasks.map(task => callback => task.then(data => callback(null, data))),\n      (err, results) => {\n        if (err) {\n          reject(err);\n        } else {\n          resolve(results);\n        }\n      }\n    );\n  });\n\n"
  },
  {
    "path": "src/utils/charset.js",
    "content": "/* eslint-disable global-require */\n/* eslint-disable import/newline-after-import */\nexport const charset = enc => res => {\n  // if under nodejs environment\n  if (typeof module !== undefined && module.exports) {\n    const iconv = require('iconv-lite');\n    return res.buffer().then(buffer => iconv.decode(buffer, enc));\n  }\n  return res.blob().then(blob => {\n    const reader = new FileReader();\n    reader.readAsText(blob, enc);\n    return new Promise(\n      resolve => {\n        reader.onloadend(() => resolve(reader.result));\n      }\n    );\n  });\n};\n"
  },
  {
    "path": "src/utils/dateu.js",
    "content": "export function ttDates(sdate, edate) {\n  const retyears = [];\n  let iyear;\n  let sarr = sdate.split('-');\n  const syear = parseInt(sarr[0], 10);\n  sarr = edate.split('-');\n  const eyear = parseInt(sarr[0], 10);\n  iyear = syear;\n  while (iyear < eyear) {\n    retyears.push(iyear);\n    iyear += 1;\n  }\n  if (eyear !== syear) {\n    retyears.push(eyear);\n  } else if (syear === eyear) {\n    retyears.push(syear);\n  }\n  return retyears;\n}\n"
  },
  {
    "path": "src/utils/fetch.js",
    "content": "/* eslint-disable */\nif (typeof module !== undefined && module.exports) {\n  var realFetch = require('no-fetch');\n  module.exports = function(url, options) {\n    if (/^\\/\\//.test(url)) {\n      url = 'https:' + url;\n    }\n    return realFetch.call(this, url, options);\n  };\n\n  if (!global.fetch) {\n    global.fetch = module.exports;\n    global.Response = realFetch.Response;\n    global.Headers = realFetch.Headers;\n    global.Request = realFetch.Request;\n  }\n} else {\n  require('whatwg-fetch');\n  module.exports = self.fetch.bind(self);\n}\n"
  },
  {
    "path": "test/billboardDZJYTest.js",
    "content": "import test from 'ava';\nimport { stock } from '../src';\n\ntest('Get All Stock Data', t => {\n  const options = {\n    start: '2016-01-15',\n    end: '2016-01-15',\n  };\n  return stock.blockTrade(options).then(({ data }) => {\n    t.truthy(data.items.length > 0, 'It should return more than one stocks');\n  });\n});\n"
  },
  {
    "path": "test/billboardLHBTest.js",
    "content": "import test from 'ava';\nimport { stock } from '../src';\n\ntest('Get All Stock Data', t => {\n  const options = {\n    start: '2016-01-15',\n    end: '2016-01-15',\n  };\n  return stock.lhb(options).then(({ data }) => {\n    t.truthy(data.items.length > 0, 'It should return more than one stocks');\n  });\n});\n"
  },
  {
    "path": "test/billboardRankTest.js",
    "content": "import test from 'ava';\nimport { stock } from '../src';\n\ntest('Get Long Period Rank Data by month', t => {\n  const options = {\n    period: 'month',\n    pageNo: 1,\n    pageSize: 100,\n  };\n  return stock.longPeriodRank(options).then(({ data }) => {\n    t.truthy(data.items.length === 100, 'It should return 100 records');\n  });\n});\n\ntest('Get Long Period Rank Data by month', t => {\n  const options = {\n    period: 'quarter',\n    pageNo: 1,\n    pageSize: 100,\n  };\n  return stock.longPeriodRank(options).then(({ data }) => {\n    t.truthy(data.items.length === 100, 'It should return 100 records');\n  });\n});\n"
  },
  {
    "path": "test/classifyingAllStocksTest.js",
    "content": "import test from 'ava';\nimport { stock } from '../src';\n\ntest('Get All Stock Data', t => {\n  t.plan(2);\n  return stock.getAllStocks().then(({ data }) => {\n    t.truthy(Object.prototype.toString.apply(data) === '[object Array]',\n      'It should return an array of stocks');\n    t.truthy(data.length > 0, 'It should return more than one stocks');\n  });\n});\n"
  },
  {
    "path": "test/classifyingConceptsTest.js",
    "content": "import test from 'ava';\nimport { stock } from '../src';\n\ntest('Get Concepts Classify', t => {\n  t.plan(2);\n  return stock.getSinaConceptsClassified().then(({ data }) => {\n    t.truthy(Object.prototype.toString.apply(data) === '[object Array]',\n      'It should return an array concepts classified data');\n    t.truthy(data.length > 0, 'It should return more than one concepts classified data');\n  });\n});\n"
  },
  {
    "path": "test/classifyingDetailsTest.js",
    "content": "import test from 'ava';\nimport { stock } from '../src';\n\ntest('Get default classifying Details', t => {\n  t.plan(2);\n  return stock.getSinaClassifyDetails().then(({ data }) => {\n    t.truthy(Object.prototype.toString.apply(data) === '[object Array]',\n      'It should return an array of stocks of an industry');\n    t.truthy(data.length > 0, 'It should return more than one stocks in an industry');\n  });\n});\n\ntest('Get specified classifying Details', t => {\n  t.plan(2);\n  const options = {\n    tag: 'gn_zndw',\n  };\n  return stock.getSinaClassifyDetails(options).then(({ data }) => {\n    t.truthy(Object.prototype.toString.apply(data) === '[object Array]',\n      'It should return an array of stocks of an industry');\n    t.truthy(data.length > 0, 'It should return more than one stocks in an industry');\n  });\n});\n"
  },
  {
    "path": "test/classifyingHS300Test.js",
    "content": "import test from 'ava';\nimport { stock } from '../src';\n\ntest('Get HS300 Stock Data', t => {\n  t.plan(2);\n  return stock.getHS300().then(({ data }) => {\n    t.truthy(Object.prototype.toString.apply(data) === '[object Array]',\n      'It should return an array of stocks');\n    t.truthy(data.length === 300, 'It should return 300 records');\n  });\n});\n"
  },
  {
    "path": "test/classifyingIndustryTest.js",
    "content": "import test from 'ava';\nimport { stock } from '../src';\n\ntest('Get Day Price', t => {\n  t.plan(2);\n  return stock.getSinaIndustryClassified().then(({ data }) => {\n    t.truthy(Object.prototype.toString.apply(data) === '[object Array]',\n      'It should return an array industry data');\n    t.truthy(data.length > 0, 'It should return more than one industry data');\n  });\n});\n"
  },
  {
    "path": "test/classifyingSZ50Test.js",
    "content": "import test from 'ava';\nimport { stock } from '../src';\n\ntest('Get SZ50 Stock Data', t => {\n  t.plan(2);\n  return stock.getSZ50().then(({ data }) => {\n    t.truthy(Object.prototype.toString.apply(data) === '[object Array]',\n      'It should return an array of stocks');\n    t.truthy(data.length === 50, 'It should return 50 records');\n  });\n});\n"
  },
  {
    "path": "test/classifyingXSG.js",
    "content": "import test from 'ava';\nimport { stock } from '../src';\n\ntest('Get XSG Stock Data', t => stock.getXSGData().then(data => {\n  t.truthy(Object.prototype.toString.apply(data) === '[object Array]',\n    'It should return an array of stocks');\n}));\n"
  },
  {
    "path": "test/getkdata.js",
    "content": "/* eslint no-unused-vars: [\"error\", {\"args\" : \"none\"}]*/\nimport test from 'ava';\nimport { stock } from '../src';\n\nconst strftime = require('strftime');\nconst util = require('util');\n\ntest.cb('Get Special case for long time ago', t => {\n  t.plan(1);\n  const opt = {};\n  opt.code = '000002';\n  opt.start = '2002-01-01';\n  opt.end = '2002-04-06';\n  const callback = function cb(data) {\n    t.truthy(data.length >= 20, 'get data length 20');\n    t.end();\n  };\n  opt.cb = callback;\n  opt.args = null;\n  stock.getKData(opt).then(callback).catch(err => {\n    t.truthy(false, util.format('long time getkdata error %s', err));\n  });\n});\n\nconst _getTimeTick = ts => {\n  const sarr = ts.split('-');\n  let retval = 0;\n  if (sarr.length >= 3) {\n    retval += parseInt(sarr[0], 10) * 100 * 100;\n    retval += parseInt(sarr[1], 10) * 100;\n    retval += parseInt(sarr[2], 10);\n    retval *= 10000;\n  } else {\n    retval += parseInt(ts, 10);\n  }\n  return retval;\n};\n\nconst _getTimeTickShort = ts => {\n  let retval = 0;\n  retval += parseInt(ts, 10);\n  return retval;\n};\n\n\ntest.cb('Get short time index', t => {\n  const opt = {};\n  const etime = new Date();\n  const stime = new Date(etime.getTime() - (24 * 365 * 3600 * 1000));\n  const sdate = strftime('%Y-%d-%m', stime);\n  const edate = strftime('%Y-%d-%m', etime);\n  opt.code = '000001';\n  opt.index = true;\n  opt.ktype = '5';\n  opt.start = sdate;\n  opt.end = edate;\n  const callback = function cb(data) {\n    let curtick;\n    const stick = _getTimeTick(sdate);\n    const etick = _getTimeTick(edate);\n    let idx = 0;\n    t.truthy(data.length >= 20, 'get data for index');\n    while (idx < data.length) {\n      const d = data[idx];\n      curtick = _getTimeTickShort(d[0]);\n      t.truthy(curtick >= stick && curtick <= etick, util.format('%s >= %s && %s <= %s', curtick, stick, curtick, etick));\n      idx += 1;\n    }\n    t.end();\n  };\n  opt.cb = callback;\n  opt.args = null;\n  stock.getKData(opt).then(callback).catch( err => {\n    t.truthy(false, util.format('short time index error %s', err));\n    t.end();\n  });\n});\n\ntest.cb('get data for sequence', t => {\n  const opt = {};\n  const etime = new Date();\n  const stime = new Date(etime.getTime() - (24 * 365 * 3600 * 1000));\n  const sdate = strftime('%Y-%d-%m', stime);\n  const edate = strftime('%Y-%d-%m', etime);\n  opt.code = '000001';\n  opt.index = true;\n  opt.ktype = '5';\n  opt.start = sdate;\n  opt.end = edate;\n  const callback = function cb(data) {\n    let curtick;\n    let idx = 0;\n    let lastval = 0;\n    let curval = 0;\n    let lastd;\n    t.truthy(data.length >= 20, 'get data for index');\n    lastd = '';\n    data.forEach(function(d) {\n      curval = _getTimeTick(d[0]);\n      t.truthy(curval >= lastval, util.format('%s for %s not sequence', lastd, d));\n      lastval = curval;\n      lastd = d;\n    });\n\n    t.end();\n  };\n  opt.cb = callback;\n  opt.args = null;\n  stock.getKData(opt).then(callback).catch(err => {\n      t.truthy( false , util.format('get sequence error %s', err));\n      t.end();\n  });\n});\n"
  },
  {
    "path": "test/stockHistoryTest.js",
    "content": "import test from 'ava';\nimport { stock } from '../src';\n\ntest('Get Day Price', t => {\n  t.plan(3);\n  const query = { code: '600848' };\n  return stock.getHistory(query).then(({ data }) => {\n    t.truthy(Object.prototype.toString.apply(data) === '[object Object]',\n      'It should return the object of day price');\n    t.truthy(data.record, 'The returned data should have a key with name `record`');\n    t.truthy(data.record.length, 'It should not return an empty array');\n  });\n});\n\ntest('Get Week Price', t => {\n  t.plan(3);\n  const query = {\n    code: '600848',\n    ktype: 'week',\n  };\n  return stock.getHistory(query).then(({ data }) => {\n    t.truthy(Object.prototype.toString.apply(data) === '[object Object]',\n      'It should return the object of day price');\n    t.truthy(data.record, 'The returned data should have a key with name `record`');\n    t.truthy(data.record.length, 'It should not return an empty array');\n  });\n});\n\ntest('Get Minute Price', t => {\n  t.plan(3);\n  const query = {\n    code: '600848',\n    ktype: '15',\n  };\n  return stock.getHistory(query).then(({ data }) => {\n    t.truthy(Object.prototype.toString.apply(data) === '[object Object]',\n      'It should return the object of day price');\n    t.truthy(data.record, 'The returned data should have a key with name `record`');\n    t.truthy(data.record.length, 'It should not return an empty array');\n  });\n});\n"
  },
  {
    "path": "test/stockIndexTest.js",
    "content": "import test from 'ava';\nimport { stock } from '../src';\n\ntest('Get Index Data', t => {\n  t.plan(1);\n  return stock.getIndex().then(({ data }) => {\n    t.truthy(data.length > 0, 'It should return an array of index data');\n  });\n});\n"
  },
  {
    "path": "test/stockLiveDataTest.js",
    "content": "import test from 'ava';\nimport { stock } from '../src';\n\ntest('Get Live Data', t => {\n  t.plan(2);\n  const query = {\n    codes: [\n      '600848',\n      '600000',\n    ],\n  };\n  return stock.getLiveData(query).then(({ data }) => {\n    t.truthy(Object.prototype.toString.apply(data) === '[object Array]',\n      'It should return an array of live data for the specified stock symbol');\n\n    t.truthy(data.length === 2,\n      'It should return the same number of stock symbols which passed in');\n  });\n});\n"
  },
  {
    "path": "test/stockSinaDDTest.js",
    "content": "import test from 'ava';\nimport { stock } from '../src';\n\ntest('Get Sina Highballing Data', t => {\n  const query = {\n    code: '600848',\n    volume: 70,\n    date: '2016-08-26',\n  };\n  return stock.getSinaDD(query).then(({ data }) => {\n    t.truthy(Object.prototype.toString.apply(data) === '[object Array]',\n      'It should return an array of da dan data');\n  });\n});\n"
  },
  {
    "path": "test/stockTickTest.js",
    "content": "import test from 'ava';\nimport { stock } from '../src';\n\ntest('Get Tick Data', t => {\n  t.plan(1);\n  const query = {\n    code: '600848',\n    date: '2015-12-31',\n  };\n  return stock.getTick(query).then(({ data }) => {\n    t.truthy(Object.prototype.toString.apply(data) === '[object Array]',\n      'It should return the object of day price');\n  });\n});\n"
  },
  {
    "path": "test/stockTodayTest.js",
    "content": "import test from 'ava';\nimport { stock } from '../src';\n\ntest('Get Tick Data', t => {\n  t.plan(1);\n  return stock.getTodayAll().then(({ data }) => {\n    t.truthy(Object.prototype.toString.apply(data) === '[object Array]',\n      'It should return an array of today stock data');\n  });\n});\n\ntest('Get Tick Data', t => {\n  t.plan(1);\n  const query = {\n    pageSize: 80,\n    pageNo: 1,\n  };\n  return stock.getTodayAll(query).then(({ data }) => {\n    t.truthy(data.length, 80, 'It should return 80 results');\n  });\n});\n"
  },
  {
    "path": "test/stockTodayTickTest.js",
    "content": "import test from 'ava';\nimport { stock } from '../src';\n\ntest('Get Tick Data', t => {\n  t.plan(2);\n  const query = {\n    code: '600848',\n    end: '15:00:00',\n  };\n  return stock.getTodayTick(query).then(({ data }) => {\n    t.truthy(Object.prototype.toString.apply(data) === '[object Object]',\n      'It should return the object of today tock price');\n    t.truthy(Object.prototype.toString.apply(data.zhubi_list) === '[object Array]',\n      'It should return an array of ticks');\n  });\n});\n"
  }
]