quote-observer 2.0.1 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/core.js CHANGED
@@ -9,6 +9,9 @@ const logger = require('./logger')();
9
9
  const Futu = require('./services/futu');
10
10
  const KLine = require('./services/kline');
11
11
 
12
+ // Update KLine every 10 minutes
13
+ const KLINE_UPDATE_PERIOD = 10 * 60 * 1000;
14
+
12
15
  // https://github.com/Marak/colors.js/blob/56de9f0983f68cd0a08c5b76d10a783e4b881716/lib/styles.js
13
16
  const styleCodes = {
14
17
  black: [30, 39],
@@ -23,13 +26,13 @@ const styleCodes = {
23
26
  };
24
27
 
25
28
  function colors(string, name) {
26
- let [open, close] = styleCodes[name];
29
+ const [open, close] = styleCodes[name];
27
30
  return `\u001b[${open}m${string}\u001b[${close}m`;
28
31
  }
29
32
 
30
33
  function moving_average(datas, days = 3) {
31
34
  if (!Array.isArray(datas)) return 0;
32
- let total = datas
35
+ const total = datas
33
36
  .slice(0, days)
34
37
  .map(v => parseFloat(v[2]))
35
38
  .reduce((sum, v) => sum += v, 0);
@@ -44,7 +47,7 @@ function moving_average(datas, days = 3) {
44
47
  // => 2tm0 = 3tm4 + 3tm3 - 2tm2 - 2tm1
45
48
  // => tm0 = 1.5tm4 + 1.5tm3 - tm2 - tm1
46
49
  function marginal_value(datas) {
47
- let [tm4, tm3, tm2, tm1, tm0] = datas.slice(0, 5).map(v => parseFloat(v[2])).reverse();
50
+ const [tm4, tm3, tm2, tm1, tm0] = datas.slice(0, 5).map(v => parseFloat(v[2])).reverse();
48
51
  return {
49
52
  now: tm0,
50
53
  curr: 1.5 * tm4 + 1.5 * tm3 - tm2 - tm1,
@@ -65,9 +68,9 @@ const padding = [
65
68
  ];
66
69
  const pad = (items) => {
67
70
  return items.map((item, index) => {
68
- let conf = padding[index];
69
- let size = conf.size || conf;
70
- let text = item[index ? 'padStart' : 'padEnd'](size - item.split(/[^\x00-\xff]/).length - 1);
71
+ const conf = padding[index];
72
+ const size = conf.size || conf;
73
+ const text = item[index ? 'padStart' : 'padEnd'](size - item.split(/[^\x00-\xff]/).length - 1);
71
74
  return conf.color ? colors(text, conf.color(item)) : text;
72
75
  }).join('');
73
76
  };
@@ -76,13 +79,13 @@ const LINE = new Array(128).fill('=').join('');
76
79
 
77
80
  const STOCKS_MAP = new Map();
78
81
  function holding(code) {
79
- let stock = STOCKS_MAP.get(code);
82
+ const stock = STOCKS_MAP.get(code);
80
83
  return (stock && stock.market_val) ? '*' : '';
81
84
  }
82
85
 
83
86
  function roc(MV) {
84
- let { now, next } = MV;
85
- let v = 100 * (next - now) / now;
87
+ const { now, next } = MV;
88
+ const v = 100 * (next - now) / now;
86
89
  return (v > 0 ? '+' : '') + v.toFixed(2) + '%';
87
90
  }
88
91
 
@@ -91,33 +94,37 @@ function ceil(v, d = 2) {
91
94
  }
92
95
 
93
96
  function sale_signal(code, now) {
94
- let stock = STOCKS_MAP.get(code);
95
- let { cost_price } = stock;
97
+ const stock = STOCKS_MAP.get(code);
98
+ const { cost_price } = stock;
96
99
  if (!cost_price) return '[=====][00]';
97
- let irate = 100 * (now - cost_price) / cost_price;
98
- let srate = [-25, -15, -8, -5, -2].map(signal => irate < signal ? '-' : ' ').join('');
100
+ const irate = 100 * (now - cost_price) / cost_price;
101
+ const srate = [-25, -15, -8, -5, -2].map(signal => irate < signal ? '-' : ' ').join('');
99
102
  return `[${srate}][${ceil(irate)}]`;
100
103
  }
101
104
 
105
+ function random_delay() {
106
+ return new Promise(r => setTimeout(r, Math.random() * 60 * 1000));
107
+ }
108
+
102
109
  function start() {
103
- let quotes = [...STOCKS_MAP.keys()].map(code => KLine(code, 10));
110
+ const quotes = [...STOCKS_MAP.keys()].map(code => random_delay().then(() => KLine(code, 10)));
104
111
  Promise.all(quotes).then(resps => {
105
112
  console.reset();
106
113
  console.log((new Date()).toTimeString().split(' ')[0]);
107
114
  console.log(LINE);
108
- console.log(pad(['ID', '名称', 'NOW', 'MA3', 'MA5', 'MVC', 'MVN', 'MVN-ROC', 'S-SIG']));
115
+ console.log(pad(['ID', 'NAME', 'NOW', 'MA3', 'MA5', 'MVC', 'MVN', 'MVN-ROC', 'S-SIG']));
109
116
  console.log(LINE);
110
- let rows = [[], LINE.replace(/=/g, '-'), []];
111
- let errors = resps.filter((data, index) => {
112
- let { fid, id, info, data: resp } = data;
117
+ const rows = [[], LINE.replace(/=/g, '-'), []];
118
+ const errors = resps.filter((data, index) => {
119
+ const { fid, id, info, data: resp } = data;
113
120
  if (!id || !info || !resp) return false;
114
- let name = String(info[1] || '').replace(/(ETF|\s).+$/i, '');
115
- let MA3 = moving_average(resp, 3);
116
- let MA5 = moving_average(resp, 5);
117
- let MV = marginal_value(resp);
121
+ const name = String(info[1] || '').replace(/(ETF|\s).+$/i, '');
122
+ const MA3 = moving_average(resp, 3);
123
+ const MA5 = moving_average(resp, 5);
124
+ const MV = marginal_value(resp);
118
125
  if (!MV.now) return global.MARKET[id] = `us${info[2]}`;
119
- let hold_star = holding(fid);
120
- let row = pad([
126
+ const hold_star = holding(fid);
127
+ const row = pad([
121
128
  fid + hold_star, String(name).replace(/-\w+$/, ''),
122
129
  MV.now.toFixed(3), MA3.toFixed(3), MA5.toFixed(3),
123
130
  MV.curr.toFixed(3), MV.next.toFixed(3), roc(MV),
@@ -128,10 +135,9 @@ function start() {
128
135
  console.log(rows.flat().join('\n'));
129
136
  console.log(LINE);
130
137
  if (errors.length) throw new Error('Errors occur.');
131
- setTimeout(() => start(), 10 * 1000);
138
+ setTimeout(() => start(), KLINE_UPDATE_PERIOD);
132
139
  }).catch((error) => {
133
140
  logger.error(error.message);
134
- setTimeout(() => start(), 1 * 1000);
135
141
  });
136
142
  }
137
143
 
package/logger.js CHANGED
@@ -19,9 +19,9 @@ const Logger = new Console(
19
19
  fs.writeFileSync(logfile, '');
20
20
 
21
21
  module.exports = () => {
22
- let error = (new Error()).stack.toString().split('\n')[2] || '';
23
- let filename = (error.match(/[\\\/\(]([-\w\.]+.\w+):\d+:\d+\)$/) || [])[1] || 'unknown';
24
- let logger = {};
22
+ const error = (new Error()).stack.toString().split('\n')[2] || '';
23
+ const filename = (error.match(/[\\\/\(]([-\w\.]+.\w+):\d+:\d+\)$/) || [])[1] || 'unknown';
24
+ const logger = {};
25
25
  'trace,debug,info,warn,error,fatal,mark'.split(',').forEach(name => {
26
26
  logger[name] = (...args) => {
27
27
  Logger.info(`[${(new Date()).toISOString()}] [${filename}] [${name.toUpperCase()}]`, ...args);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quote-observer",
3
- "version": "2.0.1",
3
+ "version": "2.0.2",
4
4
  "description": "quote observer",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/services/futu.js CHANGED
@@ -10,8 +10,8 @@ const conf = global.config.futu;
10
10
  const logger = require('../logger')();
11
11
 
12
12
  function apply(name) {
13
- let headers = { Authorization: conf.auth };
14
- let url = `${conf.base}${conf[name]}`;
13
+ const headers = { Authorization: conf.auth };
14
+ const url = `${conf.base}${conf[name]}`;
15
15
  logger.info(`Query ${name}: ${url}`);
16
16
  return axios
17
17
  .get(url, { headers })
package/services/kline.js CHANGED
@@ -40,26 +40,26 @@ const save_resp = (data) => {
40
40
  };
41
41
 
42
42
  function kline(id, days = 10) {
43
- let [mkt, code] = id.split('.');
43
+ const [mkt, code] = id.split('.');
44
44
  if (!code) {
45
45
  logger.info(`[${id}] INDEX SKIP`);
46
46
  return {};
47
47
  }
48
- let _id = fix_id(`${mkt.toLowerCase()}${code}${'US' === mkt ? '.OQ' : ''}`);
49
- let _var = 'kline_dayqfq';
50
- let params = {
48
+ const _id = fix_id(`${mkt.toLowerCase()}${code}${'US' === mkt ? '.OQ' : ''}`);
49
+ const _var = 'kline_dayqfq';
50
+ const params = {
51
51
  _var,
52
52
  _r: Math.random(),
53
53
  param: `${_id},day,,,${days},qfq`,
54
54
  };
55
- let url = `${base_url}${path_mkt[mkt]}?${querystring.stringify(params)}`;
55
+ const url = `${base_url}${path_mkt[mkt]}?${querystring.stringify(params)}`;
56
56
  logger.info(`[${id}] -> ${url}`);
57
57
  return axios.get(url)
58
58
  .then((raw = '') => {
59
59
  try {
60
- let resp = JSON.parse(raw.data.toString().replace(`${_var}=`, ''));
61
- let data = (resp || {}).data[_id] || [];
62
- let info = (data.qt || {})[_id] || [];
60
+ const resp = JSON.parse(raw.data.toString().replace(`${_var}=`, ''));
61
+ const data = (resp || {}).data[_id] || [];
62
+ const info = (data.qt || {})[_id] || [];
63
63
  return save_resp({ fid: id, id: _id, info, data: (data.day || data.qfqday || []).reverse() });
64
64
  } catch (error) {
65
65
  logger.error(`[${id}] PARSE RESPONSE ERROR:`, error.message);