daxiapi-cli 1.1.0 → 2.0.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 +75 -70
- package/bin/index.js +16 -208
- package/commands/config.js +67 -0
- package/commands/kline.js +34 -0
- package/commands/market.js +87 -0
- package/commands/search.js +35 -0
- package/commands/secid.js +34 -0
- package/commands/sector.js +120 -0
- package/commands/stock.js +79 -0
- package/commands/zdt.js +38 -0
- package/lib/api.js +44 -223
- package/lib/config.js +0 -15
- package/lib/error.js +80 -0
- package/lib/output.js +3 -324
- package/package.json +28 -26
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
const config = require('../lib/config');
|
|
2
|
+
const api = require('../lib/api');
|
|
3
|
+
const {handleError, createParameterError} = require('../lib/error');
|
|
4
|
+
const {output} = require('../lib/output');
|
|
5
|
+
|
|
6
|
+
module.exports = function (program) {
|
|
7
|
+
const sectorCmd = program.command('sector');
|
|
8
|
+
|
|
9
|
+
sectorCmd
|
|
10
|
+
.description('板块数据')
|
|
11
|
+
.option('--order <field>', '排序字段', 'cs')
|
|
12
|
+
.option('--limit <num>', '数量限制', 5)
|
|
13
|
+
.action(async options => {
|
|
14
|
+
try {
|
|
15
|
+
const token = config.getToken();
|
|
16
|
+
if (!token) {
|
|
17
|
+
const error = new Error('未配置 API Token');
|
|
18
|
+
error.response = {status: 401};
|
|
19
|
+
throw error;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const data = await api.getSectorData(token, options.order, options.limit);
|
|
23
|
+
output(data);
|
|
24
|
+
} catch (error) {
|
|
25
|
+
handleError(error);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
sectorCmd
|
|
31
|
+
.command('bk')
|
|
32
|
+
.description('行业板块数据')
|
|
33
|
+
.action(async () => {
|
|
34
|
+
try {
|
|
35
|
+
const token = config.getToken();
|
|
36
|
+
if (!token) {
|
|
37
|
+
const error = new Error('未配置 API Token');
|
|
38
|
+
error.response = {status: 401};
|
|
39
|
+
throw error;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const data = await api.getBkData(token);
|
|
43
|
+
output(data);
|
|
44
|
+
} catch (error) {
|
|
45
|
+
handleError(error);
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
sectorCmd
|
|
51
|
+
.command('stocks')
|
|
52
|
+
.description('板块个股排名')
|
|
53
|
+
.requiredOption('--code <bkCode>', '板块代码')
|
|
54
|
+
.option('--order <field>', '排序字段', 'cs')
|
|
55
|
+
.action(async options => {
|
|
56
|
+
try {
|
|
57
|
+
const token = config.getToken();
|
|
58
|
+
if (!token) {
|
|
59
|
+
const error = new Error('未配置 API Token');
|
|
60
|
+
error.response = {status: 401};
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const data = await api.getSectorRankStock(token, options.code, options.order);
|
|
65
|
+
output(data);
|
|
66
|
+
} catch (error) {
|
|
67
|
+
handleError(error);
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
sectorCmd
|
|
73
|
+
.command('top')
|
|
74
|
+
.description('热门股票')
|
|
75
|
+
.action(async () => {
|
|
76
|
+
try {
|
|
77
|
+
const token = config.getToken();
|
|
78
|
+
if (!token) {
|
|
79
|
+
const error = new Error('未配置 API Token');
|
|
80
|
+
error.response = {status: 401};
|
|
81
|
+
throw error;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const data = await api.getTopStocks(token);
|
|
85
|
+
output(data);
|
|
86
|
+
} catch (error) {
|
|
87
|
+
handleError(error);
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
sectorCmd
|
|
93
|
+
.command('gn')
|
|
94
|
+
.description('热门概念')
|
|
95
|
+
.option('--type <type>', '数据源类型 (dfcf|ths)', 'ths')
|
|
96
|
+
.action(async options => {
|
|
97
|
+
try {
|
|
98
|
+
const token = config.getToken();
|
|
99
|
+
if (!token) {
|
|
100
|
+
const error = new Error('未配置 API Token');
|
|
101
|
+
error.response = {status: 401};
|
|
102
|
+
throw error;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (!['dfcf', 'ths'].includes(options.type)) {
|
|
106
|
+
throw createParameterError(
|
|
107
|
+
'参数无效',
|
|
108
|
+
["参数 'type' 必须是 dfcf 或 ths"],
|
|
109
|
+
['daxiapi sector gn --type ths', 'daxiapi sector gn --type dfcf']
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const data = await api.getGnHot(token, options.type);
|
|
114
|
+
output(data);
|
|
115
|
+
} catch (error) {
|
|
116
|
+
handleError(error);
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
const config = require('../lib/config');
|
|
2
|
+
const api = require('../lib/api');
|
|
3
|
+
const {handleError, createParameterError} = require('../lib/error');
|
|
4
|
+
const {output} = require('../lib/output');
|
|
5
|
+
|
|
6
|
+
module.exports = function(program) {
|
|
7
|
+
const stockCmd = program.command('stock');
|
|
8
|
+
|
|
9
|
+
stockCmd
|
|
10
|
+
.description('股票数据查询')
|
|
11
|
+
.argument('<codes...>', '股票代码(支持多个)')
|
|
12
|
+
.action(async (codes) => {
|
|
13
|
+
try {
|
|
14
|
+
const token = config.getToken();
|
|
15
|
+
if (!token) {
|
|
16
|
+
const error = new Error('未配置 API Token');
|
|
17
|
+
error.response = {status: 401};
|
|
18
|
+
throw error;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (!codes || codes.length === 0) {
|
|
22
|
+
throw createParameterError(
|
|
23
|
+
'参数无效',
|
|
24
|
+
["参数 'codes' 不能为空"],
|
|
25
|
+
[
|
|
26
|
+
'daxiapi stock 000001',
|
|
27
|
+
'daxiapi stock 000001 600031 300750'
|
|
28
|
+
]
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const data = await api.getStockData(token, codes);
|
|
33
|
+
output(data);
|
|
34
|
+
} catch (error) {
|
|
35
|
+
handleError(error);
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
stockCmd
|
|
41
|
+
.command('gn <gnId>')
|
|
42
|
+
.description('概念股查询')
|
|
43
|
+
.option('--type <type>', '数据源类型 (dfcf|ths)', 'ths')
|
|
44
|
+
.action(async (gnId, options) => {
|
|
45
|
+
try {
|
|
46
|
+
const token = config.getToken();
|
|
47
|
+
if (!token) {
|
|
48
|
+
const error = new Error('未配置 API Token');
|
|
49
|
+
error.response = {status: 401};
|
|
50
|
+
throw error;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (!gnId) {
|
|
54
|
+
throw createParameterError(
|
|
55
|
+
'参数无效',
|
|
56
|
+
["参数 'gnId' 不能为空"],
|
|
57
|
+
['daxiapi stock gn GN1234']
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (!['dfcf', 'ths'].includes(options.type)) {
|
|
62
|
+
throw createParameterError(
|
|
63
|
+
'参数无效',
|
|
64
|
+
["参数 'type' 必须是 dfcf 或 ths"],
|
|
65
|
+
[
|
|
66
|
+
'daxiapi stock gn GN1234 --type ths',
|
|
67
|
+
'daxiapi stock gn GN1234 --type dfcf'
|
|
68
|
+
]
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const data = await api.getGainianStock(token, gnId, options.type);
|
|
73
|
+
output(data);
|
|
74
|
+
} catch (error) {
|
|
75
|
+
handleError(error);
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
};
|
package/commands/zdt.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const config = require('../lib/config');
|
|
2
|
+
const api = require('../lib/api');
|
|
3
|
+
const {handleError, createParameterError} = require('../lib/error');
|
|
4
|
+
const {output} = require('../lib/output');
|
|
5
|
+
|
|
6
|
+
module.exports = function(program) {
|
|
7
|
+
program
|
|
8
|
+
.command('zdt')
|
|
9
|
+
.description('涨跌停池')
|
|
10
|
+
.option('--type <type>', '类型 (zt|dt)', 'zt')
|
|
11
|
+
.action(async (options) => {
|
|
12
|
+
try {
|
|
13
|
+
const token = config.getToken();
|
|
14
|
+
if (!token) {
|
|
15
|
+
const error = new Error('未配置 API Token');
|
|
16
|
+
error.response = {status: 401};
|
|
17
|
+
throw error;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (!['zt', 'dt'].includes(options.type)) {
|
|
21
|
+
throw createParameterError(
|
|
22
|
+
'参数无效',
|
|
23
|
+
["参数 'type' 必须是 zt 或 dt"],
|
|
24
|
+
[
|
|
25
|
+
'daxiapi zdt --type zt',
|
|
26
|
+
'daxiapi zdt --type dt'
|
|
27
|
+
]
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const data = await api.getZdtPool(token, options.type);
|
|
32
|
+
output(data);
|
|
33
|
+
} catch (error) {
|
|
34
|
+
handleError(error);
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
};
|
package/lib/api.js
CHANGED
|
@@ -3,305 +3,126 @@ const config = require('./config');
|
|
|
3
3
|
|
|
4
4
|
const BASE_URL = config.get('baseUrl') || 'https://daxiapi.com';
|
|
5
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
|
-
};
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* 获取市场类型前缀
|
|
18
|
-
*/
|
|
19
|
-
function getMarketPrefix(code) {
|
|
20
|
-
if (code.startsWith('688') || code.startsWith('689')) return 'sh';
|
|
21
|
-
if (code.startsWith('60')) return 'sh';
|
|
22
|
-
return 'sz';
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* 创建请求实例
|
|
27
|
-
*/
|
|
28
6
|
function createClient(token) {
|
|
29
7
|
return axios.create({
|
|
30
8
|
baseURL: `${BASE_URL}/coze`,
|
|
31
9
|
headers: {
|
|
32
|
-
'
|
|
10
|
+
'Authorization': `Bearer ${token}`,
|
|
33
11
|
'Content-Type': 'application/json'
|
|
34
12
|
},
|
|
35
13
|
timeout: 30000
|
|
36
14
|
});
|
|
37
15
|
}
|
|
38
16
|
|
|
39
|
-
/**
|
|
40
|
-
* GET 请求
|
|
41
|
-
*/
|
|
42
17
|
async function get(client, path) {
|
|
43
|
-
const {
|
|
18
|
+
const {data} = await client.get(path);
|
|
44
19
|
if (data.errCode !== 0) {
|
|
45
|
-
|
|
20
|
+
const error = new Error(data.errMsg || `API Error: ${data.errCode}`);
|
|
21
|
+
error.response = {status: data.errCode};
|
|
22
|
+
throw error;
|
|
46
23
|
}
|
|
47
24
|
return data.data;
|
|
48
25
|
}
|
|
49
26
|
|
|
50
|
-
/**
|
|
51
|
-
* POST 请求
|
|
52
|
-
*/
|
|
53
27
|
async function post(client, path, body = {}) {
|
|
54
|
-
const {
|
|
28
|
+
const {data} = await client.post(path, body);
|
|
55
29
|
if (data.errCode !== 0) {
|
|
56
|
-
|
|
30
|
+
const error = new Error(data.errMsg || `API Error: ${data.errCode}`);
|
|
31
|
+
error.response = {status: data.errCode};
|
|
32
|
+
throw error;
|
|
57
33
|
}
|
|
58
34
|
return data.data;
|
|
59
35
|
}
|
|
60
36
|
|
|
61
|
-
// ==================== API 方法 ====================
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* 获取指数K线
|
|
65
|
-
*/
|
|
66
|
-
async function getIndexK(token) {
|
|
67
|
-
const client = createClient(token);
|
|
68
|
-
return get(client, '/get_index_k');
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* 获取市场数据
|
|
73
|
-
*/
|
|
74
37
|
async function getMarketData(token) {
|
|
75
38
|
const client = createClient(token);
|
|
76
|
-
return get(client, '/
|
|
39
|
+
return get(client, '/get_index_data');
|
|
77
40
|
}
|
|
78
41
|
|
|
79
|
-
|
|
80
|
-
* 获取市场温度
|
|
81
|
-
*/
|
|
82
|
-
async function getMarketDegree(token) {
|
|
42
|
+
async function getMarketTemp(token) {
|
|
83
43
|
const client = createClient(token);
|
|
84
|
-
return get(client, '/
|
|
44
|
+
return get(client, '/get_market_temp');
|
|
85
45
|
}
|
|
86
46
|
|
|
87
|
-
/**
|
|
88
|
-
* 获取市场风格
|
|
89
|
-
*/
|
|
90
47
|
async function getMarketStyle(token) {
|
|
91
48
|
const client = createClient(token);
|
|
92
49
|
return get(client, '/get_market_style');
|
|
93
50
|
}
|
|
94
51
|
|
|
95
|
-
/**
|
|
96
|
-
* 获取指数估值
|
|
97
|
-
*/
|
|
98
52
|
async function getMarketValueData(token) {
|
|
99
53
|
const client = createClient(token);
|
|
100
54
|
return get(client, '/get_market_value_data');
|
|
101
55
|
}
|
|
102
56
|
|
|
103
|
-
|
|
104
|
-
* 获取收盘新闻
|
|
105
|
-
*/
|
|
106
|
-
async function getMarketNews(token) {
|
|
57
|
+
async function getBkData(token) {
|
|
107
58
|
const client = createClient(token);
|
|
108
|
-
return get(client, '/
|
|
59
|
+
return get(client, '/get_bk_data');
|
|
109
60
|
}
|
|
110
61
|
|
|
111
|
-
|
|
112
|
-
* 获取涨跌停股票池
|
|
113
|
-
*/
|
|
114
|
-
async function getZdtPool(token) {
|
|
62
|
+
async function getSectorData(token, orderBy = 'cs', limit = 5) {
|
|
115
63
|
const client = createClient(token);
|
|
116
|
-
return post(client, '/
|
|
64
|
+
return post(client, '/get_sector_data', {orderBy, lmt: limit});
|
|
117
65
|
}
|
|
118
66
|
|
|
119
|
-
|
|
120
|
-
* 获取板块热力图
|
|
121
|
-
*/
|
|
122
|
-
async function getSectorData(token, orderBy = 'cs', lmt = 5) {
|
|
67
|
+
async function getSectorRankStock(token, sectorCode, orderBy = 'cs') {
|
|
123
68
|
const client = createClient(token);
|
|
124
|
-
return post(client, '/
|
|
69
|
+
return post(client, '/get_sector_rank_stock', {sectorCode, orderBy});
|
|
125
70
|
}
|
|
126
71
|
|
|
127
|
-
|
|
128
|
-
* 获取板块内个股排名
|
|
129
|
-
*/
|
|
130
|
-
async function getSectorRankStock(token, sectorCode, orderBy = 'cs') {
|
|
72
|
+
async function getTopStocks(token) {
|
|
131
73
|
const client = createClient(token);
|
|
132
|
-
return post(client, '/
|
|
74
|
+
return post(client, '/get_top_stocks', {});
|
|
133
75
|
}
|
|
134
76
|
|
|
135
|
-
|
|
136
|
-
* 获取概念内个股
|
|
137
|
-
*/
|
|
138
|
-
async function getGainianStock(token, gnId) {
|
|
77
|
+
async function getGnHot(token, type = 'ths') {
|
|
139
78
|
const client = createClient(token);
|
|
140
|
-
return post(client, '/
|
|
79
|
+
return post(client, '/get_gn_hot', {type});
|
|
141
80
|
}
|
|
142
81
|
|
|
143
|
-
/**
|
|
144
|
-
* 获取个股数据
|
|
145
|
-
*/
|
|
146
82
|
async function getStockData(token, codes) {
|
|
147
83
|
const client = createClient(token);
|
|
148
|
-
return post(client, '/get_stock_data', {
|
|
84
|
+
return post(client, '/get_stock_data', {code: codes});
|
|
149
85
|
}
|
|
150
86
|
|
|
151
|
-
|
|
152
|
-
* 搜索股票/行业
|
|
153
|
-
*/
|
|
154
|
-
async function queryStock(token, keyword, type = 'stock') {
|
|
87
|
+
async function getGainianStock(token, gnId, type = 'ths') {
|
|
155
88
|
const client = createClient(token);
|
|
156
|
-
return post(client, '/
|
|
89
|
+
return post(client, '/get_gainian_stock', {gnId, type});
|
|
157
90
|
}
|
|
158
91
|
|
|
159
|
-
|
|
160
|
-
* 获取概念板块数据
|
|
161
|
-
*/
|
|
162
|
-
async function getGnTable(token) {
|
|
92
|
+
async function getKline(token, code) {
|
|
163
93
|
const client = createClient(token);
|
|
164
|
-
return post(client, '/
|
|
94
|
+
return post(client, '/get_kline', {code});
|
|
165
95
|
}
|
|
166
96
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
* 获取K线数据(首选腾讯,备选东方财富)
|
|
171
|
-
* @param {string} code - 股票代码
|
|
172
|
-
* @param {number} limit - 数据条数,默认300
|
|
173
|
-
* @param {string} type - K线类型: day(日线), week(周线), month(月线)
|
|
174
|
-
* @returns {Promise<Object>} K线数据
|
|
175
|
-
*/
|
|
176
|
-
async function getKline(code, limit = 300, type = 'day') {
|
|
177
|
-
// 首选腾讯
|
|
178
|
-
try {
|
|
179
|
-
const data = await getKlineFromQQ(code, limit, type);
|
|
180
|
-
return { source: 'qq', ...data };
|
|
181
|
-
} catch (err) {
|
|
182
|
-
console.log('腾讯数据源失败,切换到东方财富...');
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
// 备选东方财富
|
|
186
|
-
try {
|
|
187
|
-
const data = await getKlineFromEastmoney(code, limit, type);
|
|
188
|
-
return { source: 'eastmoney', ...data };
|
|
189
|
-
} catch (err) {
|
|
190
|
-
throw new Error('所有数据源均失败,请稍后重试');
|
|
191
|
-
}
|
|
97
|
+
async function getZdtPool(token, type = 'zt') {
|
|
98
|
+
const client = createClient(token);
|
|
99
|
+
return post(client, '/get_zdt_pool', {type});
|
|
192
100
|
}
|
|
193
101
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
* @param {number} limit - 数据条数
|
|
198
|
-
* @param {string} type - K线类型
|
|
199
|
-
*/
|
|
200
|
-
async function getKlineFromQQ(code, limit = 500, type = 'day') {
|
|
201
|
-
const market = getMarketPrefix(code);
|
|
202
|
-
const fullCode = `${market}${code}`;
|
|
203
|
-
|
|
204
|
-
// 腾讯接口限制最大2000条
|
|
205
|
-
if (limit > 2000) limit = 2000;
|
|
206
|
-
|
|
207
|
-
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 { data } = await axios.get(url, { timeout: 10000 });
|
|
210
|
-
|
|
211
|
-
if (!data.data || !data.data[fullCode]) {
|
|
212
|
-
throw new Error('腾讯数据源返回异常');
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
const klineData = data.data[fullCode].qfqday || data.data[fullCode].day;
|
|
216
|
-
if (!klineData || klineData.length === 0) {
|
|
217
|
-
throw new Error('无K线数据');
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
const klines = klineData.map(([date, open, close, high, low, volume, , , amount]) => ({
|
|
221
|
-
date,
|
|
222
|
-
open: parseFloat(open),
|
|
223
|
-
close: parseFloat(close),
|
|
224
|
-
high: parseFloat(high),
|
|
225
|
-
low: parseFloat(low),
|
|
226
|
-
volume: parseFloat(volume),
|
|
227
|
-
amount: parseFloat(amount)
|
|
228
|
-
}));
|
|
229
|
-
|
|
230
|
-
return {
|
|
231
|
-
code,
|
|
232
|
-
name: data.data[fullCode].qt?.[fullCode]?.[1] || code,
|
|
233
|
-
klines,
|
|
234
|
-
count: klines.length
|
|
235
|
-
};
|
|
102
|
+
async function getSecId(token, code) {
|
|
103
|
+
const client = createClient(token);
|
|
104
|
+
return post(client, '/get_sec_id', {code});
|
|
236
105
|
}
|
|
237
106
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
* @param {number} limit - 数据条数
|
|
242
|
-
* @param {string} type - K线类型: day=101, week=102, month=103
|
|
243
|
-
*/
|
|
244
|
-
async function getKlineFromEastmoney(code, limit = 300, type = 'day') {
|
|
245
|
-
// K线类型映射
|
|
246
|
-
const kltMap = { day: '101', week: '102', month: '103' };
|
|
247
|
-
const klt = kltMap[type] || '101';
|
|
248
|
-
|
|
249
|
-
// 市场代码
|
|
250
|
-
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
|
-
|
|
264
|
-
if (!data.data || !data.data.klines) {
|
|
265
|
-
throw new Error('东方财富数据源返回异常');
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
const klines = data.data.klines.map(line => {
|
|
269
|
-
const [date, open, close, high, low, volume, amount, , turnover] = line.split(',');
|
|
270
|
-
return {
|
|
271
|
-
date,
|
|
272
|
-
open: parseFloat(open),
|
|
273
|
-
close: parseFloat(close),
|
|
274
|
-
high: parseFloat(high),
|
|
275
|
-
low: parseFloat(low),
|
|
276
|
-
volume: parseFloat(volume),
|
|
277
|
-
amount: parseFloat(amount),
|
|
278
|
-
turnover: parseFloat(turnover) || 0
|
|
279
|
-
};
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
return {
|
|
283
|
-
code,
|
|
284
|
-
name: data.data.name || code,
|
|
285
|
-
klines,
|
|
286
|
-
count: klines.length
|
|
287
|
-
};
|
|
107
|
+
async function queryStockData(token, q, type = 'stock') {
|
|
108
|
+
const client = createClient(token);
|
|
109
|
+
return post(client, '/query_stock_data', {q, type});
|
|
288
110
|
}
|
|
289
111
|
|
|
290
112
|
module.exports = {
|
|
291
|
-
getIndexK,
|
|
292
113
|
getMarketData,
|
|
293
|
-
|
|
114
|
+
getMarketTemp,
|
|
294
115
|
getMarketStyle,
|
|
295
116
|
getMarketValueData,
|
|
296
|
-
|
|
297
|
-
getZdtPool,
|
|
117
|
+
getBkData,
|
|
298
118
|
getSectorData,
|
|
299
119
|
getSectorRankStock,
|
|
300
|
-
|
|
120
|
+
getTopStocks,
|
|
121
|
+
getGnHot,
|
|
301
122
|
getStockData,
|
|
302
|
-
|
|
303
|
-
getGnTable,
|
|
123
|
+
getGainianStock,
|
|
304
124
|
getKline,
|
|
305
|
-
|
|
306
|
-
|
|
125
|
+
getZdtPool,
|
|
126
|
+
getSecId,
|
|
127
|
+
queryStockData
|
|
307
128
|
};
|
package/lib/config.js
CHANGED
|
@@ -17,30 +17,18 @@ const config = new Conf({
|
|
|
17
17
|
schema
|
|
18
18
|
});
|
|
19
19
|
|
|
20
|
-
/**
|
|
21
|
-
* 获取Token(优先环境变量)
|
|
22
|
-
*/
|
|
23
20
|
function getToken() {
|
|
24
21
|
return process.env.DAXIAPI_TOKEN || config.get('token');
|
|
25
22
|
}
|
|
26
23
|
|
|
27
|
-
/**
|
|
28
|
-
* 获取配置项
|
|
29
|
-
*/
|
|
30
24
|
function get(key) {
|
|
31
25
|
return config.get(key);
|
|
32
26
|
}
|
|
33
27
|
|
|
34
|
-
/**
|
|
35
|
-
* 设置配置项
|
|
36
|
-
*/
|
|
37
28
|
function set(key, value) {
|
|
38
29
|
config.set(key, value);
|
|
39
30
|
}
|
|
40
31
|
|
|
41
|
-
/**
|
|
42
|
-
* 获取所有配置
|
|
43
|
-
*/
|
|
44
32
|
function getAll() {
|
|
45
33
|
return {
|
|
46
34
|
token: getToken() ? '******' + getToken().slice(-4) : undefined,
|
|
@@ -48,9 +36,6 @@ function getAll() {
|
|
|
48
36
|
};
|
|
49
37
|
}
|
|
50
38
|
|
|
51
|
-
/**
|
|
52
|
-
* 删除配置项
|
|
53
|
-
*/
|
|
54
39
|
function del(key) {
|
|
55
40
|
config.delete(key);
|
|
56
41
|
}
|