daxiapi-cli 1.1.0 → 1.2.0

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/README.md CHANGED
@@ -59,9 +59,6 @@ daxiapi market -v
59
59
 
60
60
  # 收盘新闻
61
61
  daxiapi market -n
62
-
63
- # 涨跌停股票池
64
- daxiapi market -z
65
62
  ```
66
63
 
67
64
  ### 指数K线
package/bin/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- const { program } = require('commander');
3
+ const {program} = require('commander');
4
4
  const chalk = require('chalk');
5
5
  const config = require('../lib/config');
6
6
  const api = require('../lib/api');
@@ -71,11 +71,10 @@ program
71
71
  .option('-s, --style', '获取大小盘风格')
72
72
  .option('-v, --value', '获取指数估值')
73
73
  .option('-n, --news', '获取收盘新闻')
74
- .option('-z, --zdt', '获取涨跌停股票池')
75
- .action(async (options) => {
74
+ .action(async options => {
76
75
  showWelcome();
77
76
  const token = checkToken();
78
-
77
+
79
78
  try {
80
79
  if (options.degree) {
81
80
  const data = await api.getMarketDegree(token);
@@ -89,9 +88,6 @@ program
89
88
  } else if (options.news) {
90
89
  const data = await api.getMarketNews(token);
91
90
  output.newsList(data);
92
- } else if (options.zdt) {
93
- const data = await api.getZdtPool(token);
94
- output.text(data);
95
91
  } else {
96
92
  // 默认获取市场概览
97
93
  const data = await api.getMarketData(token);
@@ -109,7 +105,7 @@ program
109
105
  .action(async () => {
110
106
  showWelcome();
111
107
  const token = checkToken();
112
-
108
+
113
109
  try {
114
110
  const data = await api.getIndexK(token);
115
111
  output.klines(data);
@@ -126,10 +122,10 @@ program
126
122
  .option('-o, --order <field>', '排序字段', 'cs')
127
123
  .option('-l, --limit <days>', '天数', '5')
128
124
  .option('-g, --gn <gnId>', '概念代码,获取概念内个股')
129
- .action(async (options) => {
125
+ .action(async options => {
130
126
  showWelcome();
131
127
  const token = checkToken();
132
-
128
+
133
129
  try {
134
130
  if (options.code) {
135
131
  const data = await api.getSectorRankStock(token, options.code, options.order);
@@ -154,7 +150,7 @@ program
154
150
  .action(async (codes, options) => {
155
151
  showWelcome();
156
152
  const token = checkToken();
157
-
153
+
158
154
  try {
159
155
  const data = await api.getStockData(token, codes.join(','));
160
156
  if (options.json) {
@@ -175,7 +171,7 @@ program
175
171
  .action(async (keyword, options) => {
176
172
  showWelcome();
177
173
  const token = checkToken();
178
-
174
+
179
175
  try {
180
176
  const data = await api.queryStock(token, keyword, options.type);
181
177
  output.searchResult(data);
@@ -195,7 +191,7 @@ program
195
191
  .action(async (code, options) => {
196
192
  showWelcome();
197
193
  // K线数据不需要token,使用免费数据源
198
-
194
+
199
195
  try {
200
196
  const data = await api.getKline(code, parseInt(options.limit), options.type);
201
197
  if (options.json) {
package/lib/api.js CHANGED
@@ -1,24 +1,18 @@
1
1
  const axios = require('axios');
2
2
  const config = require('./config');
3
3
 
4
- const BASE_URL = config.get('baseUrl') || 'https://daxiapi.com';
5
-
6
- // 市场类型映射
7
- const MARKET_MAP = {
8
- '6': 'sh', // 上海
9
- '0': 'sz', // 深圳
10
- '3': 'sz', // 创业板
11
- '9': 'bj',
12
- '688': 'sh', // 科创板
13
- '689': 'sh' // 科创板CDR
14
- };
4
+ const BASE_URL = config.getBaseUrl() || 'https://daxiapi.com';
15
5
 
16
6
  /**
17
7
  * 获取市场类型前缀
18
8
  */
19
9
  function getMarketPrefix(code) {
20
- if (code.startsWith('688') || code.startsWith('689')) return 'sh';
21
- if (code.startsWith('60')) return 'sh';
10
+ if (code.startsWith('688') || code.startsWith('689')) {
11
+ return 'sh';
12
+ }
13
+ if (code.startsWith('60')) {
14
+ return 'sh';
15
+ }
22
16
  return 'sz';
23
17
  }
24
18
 
@@ -40,7 +34,7 @@ function createClient(token) {
40
34
  * GET 请求
41
35
  */
42
36
  async function get(client, path) {
43
- const { data } = await client.get(path);
37
+ const {data} = await client.get(path);
44
38
  if (data.errCode !== 0) {
45
39
  throw new Error(data.errMsg || `API Error: ${data.errCode}`);
46
40
  }
@@ -51,7 +45,7 @@ async function get(client, path) {
51
45
  * POST 请求
52
46
  */
53
47
  async function post(client, path, body = {}) {
54
- const { data } = await client.post(path, body);
48
+ const {data} = await client.post(path, body);
55
49
  if (data.errCode !== 0) {
56
50
  throw new Error(data.errMsg || `API Error: ${data.errCode}`);
57
51
  }
@@ -108,20 +102,12 @@ async function getMarketNews(token) {
108
102
  return get(client, '/get_market_end_news');
109
103
  }
110
104
 
111
- /**
112
- * 获取涨跌停股票池
113
- */
114
- async function getZdtPool(token) {
115
- const client = createClient(token);
116
- return post(client, '/get_zdt_pool');
117
- }
118
-
119
105
  /**
120
106
  * 获取板块热力图
121
107
  */
122
108
  async function getSectorData(token, orderBy = 'cs', lmt = 5) {
123
109
  const client = createClient(token);
124
- return post(client, '/get_sector_data', { orderBy, lmt });
110
+ return post(client, '/get_sector_data', {orderBy, lmt});
125
111
  }
126
112
 
127
113
  /**
@@ -129,7 +115,7 @@ async function getSectorData(token, orderBy = 'cs', lmt = 5) {
129
115
  */
130
116
  async function getSectorRankStock(token, sectorCode, orderBy = 'cs') {
131
117
  const client = createClient(token);
132
- return post(client, '/get_sector_rank_stock', { sectorCode, orderBy });
118
+ return post(client, '/get_sector_rank_stock', {sectorCode, orderBy});
133
119
  }
134
120
 
135
121
  /**
@@ -137,7 +123,7 @@ async function getSectorRankStock(token, sectorCode, orderBy = 'cs') {
137
123
  */
138
124
  async function getGainianStock(token, gnId) {
139
125
  const client = createClient(token);
140
- return post(client, '/get_gainian_stock', { gnId });
126
+ return post(client, '/get_gainian_stock', {gnId});
141
127
  }
142
128
 
143
129
  /**
@@ -145,7 +131,7 @@ async function getGainianStock(token, gnId) {
145
131
  */
146
132
  async function getStockData(token, codes) {
147
133
  const client = createClient(token);
148
- return post(client, '/get_stock_data', { code: codes });
134
+ return post(client, '/get_stock_data', {code: codes});
149
135
  }
150
136
 
151
137
  /**
@@ -153,7 +139,7 @@ async function getStockData(token, codes) {
153
139
  */
154
140
  async function queryStock(token, keyword, type = 'stock') {
155
141
  const client = createClient(token);
156
- return post(client, '/query_stock_data', { q: keyword, type });
142
+ return post(client, '/query_stock_data', {q: keyword, type});
157
143
  }
158
144
 
159
145
  /**
@@ -177,15 +163,15 @@ async function getKline(code, limit = 300, type = 'day') {
177
163
  // 首选腾讯
178
164
  try {
179
165
  const data = await getKlineFromQQ(code, limit, type);
180
- return { source: 'qq', ...data };
166
+ return {source: 'qq', ...data};
181
167
  } catch (err) {
182
168
  console.log('腾讯数据源失败,切换到东方财富...');
183
169
  }
184
-
170
+
185
171
  // 备选东方财富
186
172
  try {
187
173
  const data = await getKlineFromEastmoney(code, limit, type);
188
- return { source: 'eastmoney', ...data };
174
+ return {source: 'eastmoney', ...data};
189
175
  } catch (err) {
190
176
  throw new Error('所有数据源均失败,请稍后重试');
191
177
  }
@@ -200,23 +186,25 @@ async function getKline(code, limit = 300, type = 'day') {
200
186
  async function getKlineFromQQ(code, limit = 500, type = 'day') {
201
187
  const market = getMarketPrefix(code);
202
188
  const fullCode = `${market}${code}`;
203
-
189
+
204
190
  // 腾讯接口限制最大2000条
205
- if (limit > 2000) limit = 2000;
206
-
191
+ if (limit > 2000) {
192
+ limit = 2000;
193
+ }
194
+
207
195
  const url = `https://proxy.finance.qq.com/ifzqgtimg/appstock/app/newfqkline/get?_var=&param=${fullCode},${type},,,${limit},qfq&r=0.${Date.now()}`;
208
-
209
- const { data } = await axios.get(url, { timeout: 10000 });
210
-
196
+
197
+ const {data} = await axios.get(url, {timeout: 10000});
198
+
211
199
  if (!data.data || !data.data[fullCode]) {
212
200
  throw new Error('腾讯数据源返回异常');
213
201
  }
214
-
202
+
215
203
  const klineData = data.data[fullCode].qfqday || data.data[fullCode].day;
216
204
  if (!klineData || klineData.length === 0) {
217
205
  throw new Error('无K线数据');
218
206
  }
219
-
207
+
220
208
  const klines = klineData.map(([date, open, close, high, low, volume, , , amount]) => ({
221
209
  date,
222
210
  open: parseFloat(open),
@@ -226,7 +214,7 @@ async function getKlineFromQQ(code, limit = 500, type = 'day') {
226
214
  volume: parseFloat(volume),
227
215
  amount: parseFloat(amount)
228
216
  }));
229
-
217
+
230
218
  return {
231
219
  code,
232
220
  name: data.data[fullCode].qt?.[fullCode]?.[1] || code,
@@ -243,28 +231,20 @@ async function getKlineFromQQ(code, limit = 500, type = 'day') {
243
231
  */
244
232
  async function getKlineFromEastmoney(code, limit = 300, type = 'day') {
245
233
  // K线类型映射
246
- const kltMap = { day: '101', week: '102', month: '103' };
234
+ const kltMap = {day: '101', week: '102', month: '103'};
247
235
  const klt = kltMap[type] || '101';
248
-
236
+
249
237
  // 市场代码
250
238
  const secid = code.startsWith('6') ? `1.${code}` : `0.${code}`;
251
-
252
- const url = `https://push2his.eastmoney.com/api/qt/stock/kline/get?` +
253
- `fields1=f1,f2,f3,f4,f5,f6&` +
254
- `fields2=f51,f52,f53,f54,f55,f56,f57,f58,f61&` +
255
- `ut=7eea3edcaed734bea9cbfc24409ed989&` +
256
- `end=29991010&` +
257
- `klt=${klt}&` +
258
- `secid=${secid}&` +
259
- `fqt=1&` +
260
- `lmt=${limit}`;
261
-
262
- const { data } = await axios.get(url, { timeout: 10000 });
263
-
239
+
240
+ const url = `https://push2his.eastmoney.com/api/qt/stock/kline/get?fields1=f1,f2,f3,f4,f5,f6&fields2=f51,f52,f53,f54,f55,f56,f57,f58,f61&ut=7eea3edcaed734bea9cbfc24409ed989&end=29991010&klt=${klt}&secid=${secid}&fqt=1&lmt=${limit}`;
241
+
242
+ const {data} = await axios.get(url, {timeout: 10000});
243
+
264
244
  if (!data.data || !data.data.klines) {
265
245
  throw new Error('东方财富数据源返回异常');
266
246
  }
267
-
247
+
268
248
  const klines = data.data.klines.map(line => {
269
249
  const [date, open, close, high, low, volume, amount, , turnover] = line.split(',');
270
250
  return {
@@ -278,7 +258,7 @@ async function getKlineFromEastmoney(code, limit = 300, type = 'day') {
278
258
  turnover: parseFloat(turnover) || 0
279
259
  };
280
260
  });
281
-
261
+
282
262
  return {
283
263
  code,
284
264
  name: data.data.name || code,
@@ -294,7 +274,6 @@ module.exports = {
294
274
  getMarketStyle,
295
275
  getMarketValueData,
296
276
  getMarketNews,
297
- getZdtPool,
298
277
  getSectorData,
299
278
  getSectorRankStock,
300
279
  getGainianStock,
package/package.json CHANGED
@@ -1,28 +1,28 @@
1
1
  {
2
- "name": "daxiapi-cli",
3
- "version": "1.1.0",
4
- "description": "大虾皮(daxiapi.com)金融数据API命令行工具",
5
- "bin": {
6
- "daxiapi": "./bin/index.js",
7
- "dxp": "./bin/index.js"
8
- },
9
- "scripts": {
10
- "test": "node bin/index.js"
11
- },
12
- "keywords": [
13
- "stock",
14
- "api",
15
- "daxiapi",
16
- "cli",
17
- "finance"
18
- ],
19
- "author": "daxiapi.com",
20
- "license": "MIT",
21
- "dependencies": {
22
- "axios": "^1.6.0",
23
- "chalk": "^4.1.2",
24
- "commander": "^11.1.0",
25
- "conf": "^10.2.0",
26
- "console.table": "^0.10.0"
27
- }
28
- }
2
+ "name": "daxiapi-cli",
3
+ "version": "1.2.0",
4
+ "description": "大虾皮(daxiapi.com)金融数据API命令行工具",
5
+ "bin": {
6
+ "daxiapi": "./bin/index.js",
7
+ "dxp": "./bin/index.js"
8
+ },
9
+ "scripts": {
10
+ "test": "node bin/index.js"
11
+ },
12
+ "keywords": [
13
+ "stock",
14
+ "api",
15
+ "daxiapi",
16
+ "cli",
17
+ "finance"
18
+ ],
19
+ "author": "daxiapi.com",
20
+ "license": "MIT",
21
+ "dependencies": {
22
+ "axios": "^1.6.0",
23
+ "chalk": "^4.1.2",
24
+ "commander": "^11.1.0",
25
+ "conf": "^10.2.0",
26
+ "console.table": "^0.10.0"
27
+ }
28
+ }