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 +0 -3
- package/bin/index.js +9 -13
- package/lib/api.js +37 -58
- package/package.json +27 -27
package/README.md
CHANGED
package/bin/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
const {
|
|
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
|
-
.
|
|
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
|
|
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.
|
|
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'))
|
|
21
|
-
|
|
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 {
|
|
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 {
|
|
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', {
|
|
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', {
|
|
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', {
|
|
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', {
|
|
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', {
|
|
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 {
|
|
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 {
|
|
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)
|
|
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=¶m=${fullCode},${type},,,${limit},qfq&r=0.${Date.now()}`;
|
|
208
|
-
|
|
209
|
-
const {
|
|
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 = {
|
|
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
|
-
|
|
254
|
-
|
|
255
|
-
|
|
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
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
|
+
}
|