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
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# daxiapi-cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
大虾皮金融数据API命令行工具。需要注册 daxiapi.com 网站,并且获取API Token之后才能使用。
|
|
4
4
|
|
|
5
5
|
## 安装
|
|
6
6
|
|
|
@@ -45,119 +45,124 @@ daxiapi config delete token
|
|
|
45
45
|
### 市场数据
|
|
46
46
|
|
|
47
47
|
```bash
|
|
48
|
-
#
|
|
48
|
+
# 市场概览(主流指数)
|
|
49
49
|
daxiapi market
|
|
50
50
|
|
|
51
51
|
# 市场温度
|
|
52
|
-
daxiapi market
|
|
52
|
+
daxiapi market temp
|
|
53
53
|
|
|
54
|
-
#
|
|
55
|
-
daxiapi market
|
|
54
|
+
# 市场风格
|
|
55
|
+
daxiapi market style
|
|
56
56
|
|
|
57
|
-
#
|
|
58
|
-
daxiapi market
|
|
59
|
-
|
|
60
|
-
# 收盘新闻
|
|
61
|
-
daxiapi market -n
|
|
62
|
-
|
|
63
|
-
# 涨跌停股票池
|
|
64
|
-
daxiapi market -z
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
### 指数K线
|
|
68
|
-
|
|
69
|
-
```bash
|
|
70
|
-
# 获取上证指数K线
|
|
71
|
-
daxiapi index
|
|
57
|
+
# 市场估值
|
|
58
|
+
daxiapi market value
|
|
72
59
|
```
|
|
73
60
|
|
|
74
61
|
### 板块数据
|
|
75
62
|
|
|
76
63
|
```bash
|
|
77
|
-
#
|
|
64
|
+
# 板块列表
|
|
78
65
|
daxiapi sector
|
|
79
66
|
|
|
80
|
-
#
|
|
81
|
-
daxiapi sector
|
|
67
|
+
# 指定排序和数量
|
|
68
|
+
daxiapi sector --order zdf --limit 10
|
|
69
|
+
|
|
70
|
+
# 行业板块数据
|
|
71
|
+
daxiapi sector bk
|
|
82
72
|
|
|
83
|
-
#
|
|
84
|
-
daxiapi sector
|
|
73
|
+
# 板块内个股排名
|
|
74
|
+
daxiapi sector stocks --code BK0477
|
|
85
75
|
|
|
86
|
-
#
|
|
87
|
-
daxiapi sector
|
|
76
|
+
# 热门股票
|
|
77
|
+
daxiapi sector top
|
|
78
|
+
|
|
79
|
+
# 热门概念
|
|
80
|
+
daxiapi sector gn
|
|
88
81
|
```
|
|
89
82
|
|
|
90
|
-
###
|
|
83
|
+
### 股票数据
|
|
91
84
|
|
|
92
85
|
```bash
|
|
86
|
+
# 搜索股票或板块
|
|
87
|
+
daxiapi search 平安
|
|
88
|
+
daxiapi search 锂电 --type bk
|
|
89
|
+
|
|
93
90
|
# 查询单个股票
|
|
94
91
|
daxiapi stock 000001
|
|
95
92
|
|
|
96
93
|
# 查询多个股票
|
|
97
94
|
daxiapi stock 000001 600031 300750
|
|
98
95
|
|
|
99
|
-
#
|
|
100
|
-
daxiapi stock
|
|
96
|
+
# 概念股查询
|
|
97
|
+
daxiapi stock gn GN1234
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### K线数据
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
# 获取K线数据
|
|
104
|
+
daxiapi kline 000001
|
|
101
105
|
```
|
|
102
106
|
|
|
103
|
-
###
|
|
107
|
+
### 涨跌停
|
|
104
108
|
|
|
105
109
|
```bash
|
|
106
|
-
#
|
|
107
|
-
daxiapi
|
|
110
|
+
# 涨停池
|
|
111
|
+
daxiapi zdt
|
|
108
112
|
|
|
109
|
-
#
|
|
110
|
-
daxiapi
|
|
113
|
+
# 跌停池
|
|
114
|
+
daxiapi zdt --type dt
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### 工具
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
# 代码转换
|
|
121
|
+
daxiapi secid 000001
|
|
111
122
|
```
|
|
112
123
|
|
|
113
124
|
> 💡 提示:`daxiapi` 命令也可以使用简写 `dxp`
|
|
114
125
|
|
|
115
|
-
##
|
|
126
|
+
## 全局选项
|
|
116
127
|
|
|
117
|
-
|
|
128
|
+
```bash
|
|
129
|
+
# 查看帮助
|
|
130
|
+
daxiapi --help
|
|
131
|
+
daxiapi market --help
|
|
118
132
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
主要指数:
|
|
123
|
-
┌─────────┬────────┬───────────┬───────┬─────────┬─────────┐
|
|
124
|
-
│ (index) │ 名称 │ 涨跌幅 │ CS │ 5日 │ 20日 │
|
|
125
|
-
├─────────┼────────┼───────────┼───────┼─────────┼─────────┤
|
|
126
|
-
│ 0 │ '上证' │ '0.50%' │ 5.23 │ '2.10%' │ '3.50%' │
|
|
127
|
-
│ 1 │ '深证' │ '0.80%' │ 6.45 │ '2.50%' │ '4.20%' │
|
|
128
|
-
│ 2 │ '创业' │ '1.20%' │ 8.12 │ '3.00%' │ '5.10%' │
|
|
129
|
-
└─────────┴────────┴───────────┴───────┴─────────┴─────────┘
|
|
133
|
+
# 查看版本
|
|
134
|
+
daxiapi --version
|
|
130
135
|
```
|
|
131
136
|
|
|
132
|
-
|
|
137
|
+
## 错误处理
|
|
138
|
+
|
|
139
|
+
CLI 工具提供详细的错误提示和解决建议:
|
|
140
|
+
|
|
141
|
+
### 认证错误 (401)
|
|
133
142
|
|
|
134
143
|
```
|
|
135
|
-
|
|
144
|
+
❌ 错误: API Token 无效或已过期
|
|
145
|
+
|
|
146
|
+
解决方法:
|
|
147
|
+
1. 检查 Token 是否正确配置:
|
|
148
|
+
daxiapi config set token YOUR_TOKEN
|
|
136
149
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
价格: 18.50 涨跌幅: 2.50%
|
|
150
|
+
2. 或设置环境变量:
|
|
151
|
+
export DAXIAPI_TOKEN=YOUR_TOKEN
|
|
140
152
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
153
|
+
3. Token 可在 daxiapi.com 用户中心获取
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### 限流错误 (429)
|
|
144
157
|
|
|
145
|
-
形态标签: Good, LPS
|
|
146
|
-
技术形态: VCP, SOS
|
|
147
158
|
```
|
|
159
|
+
❌ 错误: 请求频率超限
|
|
148
160
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
| SM | 中期动量,短期与中期均线乖离率。>0多头排列 |
|
|
155
|
-
| ML | 长期动量,中期与长期均线乖离率 |
|
|
156
|
-
| RPS | 欧奈尔相对强度,>80为强势股 |
|
|
157
|
-
| SCTR | 技术排名百分比,如60代表强于市场60%股票 |
|
|
158
|
-
| VCP | 马克米勒维尼波动收缩模式 |
|
|
159
|
-
| SOS | Wyckoff强势走势行为 |
|
|
160
|
-
| LPS | Wyckoff最后支撑点 |
|
|
161
|
+
解决方法:
|
|
162
|
+
1. 请稍后重试
|
|
163
|
+
2. 检查您的请求频率是否过高
|
|
164
|
+
3. 升级账户获取更高配额
|
|
165
|
+
```
|
|
161
166
|
|
|
162
167
|
## 限流规则
|
|
163
168
|
|
package/bin/index.js
CHANGED
|
@@ -1,213 +1,21 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
const {
|
|
4
|
-
const
|
|
5
|
-
const config = require('../lib/config');
|
|
6
|
-
const api = require('../lib/api');
|
|
7
|
-
const output = require('../lib/output');
|
|
8
|
-
|
|
9
|
-
// 显示欢迎信息
|
|
10
|
-
function showWelcome() {
|
|
11
|
-
console.log(chalk.cyan.bold('\n📊 大虾皮 CLI - A股量化数据工具\n'));
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
// 检查Token配置
|
|
15
|
-
function checkToken() {
|
|
16
|
-
const token = config.getToken();
|
|
17
|
-
if (!token) {
|
|
18
|
-
console.log(chalk.yellow('⚠️ 未配置 API Token'));
|
|
19
|
-
console.log(chalk.gray(' 请先运行: daxiapi config set token YOUR_TOKEN'));
|
|
20
|
-
console.log(chalk.gray(' 或设置环境变量: DAXIAPI_TOKEN=YOUR_TOKEN\n'));
|
|
21
|
-
process.exit(1);
|
|
22
|
-
}
|
|
23
|
-
return token;
|
|
24
|
-
}
|
|
3
|
+
const {program} = require('commander');
|
|
4
|
+
const package = require('../package.json');
|
|
25
5
|
|
|
26
6
|
program
|
|
27
7
|
.name('daxiapi')
|
|
28
|
-
.
|
|
29
|
-
.
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
program
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
console.log(chalk.red('用法: daxiapi config set <key> <value>'));
|
|
43
|
-
console.log(chalk.gray('示例: daxiapi config set token abc123...'));
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
config.set(key, value);
|
|
47
|
-
console.log(chalk.green(`✓ 已设置 ${key}`));
|
|
48
|
-
break;
|
|
49
|
-
case 'get':
|
|
50
|
-
if (!key) {
|
|
51
|
-
const all = config.getAll();
|
|
52
|
-
console.log(JSON.stringify(all, null, 2));
|
|
53
|
-
} else {
|
|
54
|
-
console.log(config.get(key) || '');
|
|
55
|
-
}
|
|
56
|
-
break;
|
|
57
|
-
case 'delete':
|
|
58
|
-
config.delete(key);
|
|
59
|
-
console.log(chalk.green(`✓ 已删除 ${key}`));
|
|
60
|
-
break;
|
|
61
|
-
default:
|
|
62
|
-
console.log(chalk.red('未知操作:', action));
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
// ==================== 市场数据命令 ====================
|
|
67
|
-
program
|
|
68
|
-
.command('market')
|
|
69
|
-
.description('市场数据')
|
|
70
|
-
.option('-d, --degree', '获取市场温度')
|
|
71
|
-
.option('-s, --style', '获取大小盘风格')
|
|
72
|
-
.option('-v, --value', '获取指数估值')
|
|
73
|
-
.option('-n, --news', '获取收盘新闻')
|
|
74
|
-
.option('-z, --zdt', '获取涨跌停股票池')
|
|
75
|
-
.action(async (options) => {
|
|
76
|
-
showWelcome();
|
|
77
|
-
const token = checkToken();
|
|
78
|
-
|
|
79
|
-
try {
|
|
80
|
-
if (options.degree) {
|
|
81
|
-
const data = await api.getMarketDegree(token);
|
|
82
|
-
output.text(data);
|
|
83
|
-
} else if (options.style) {
|
|
84
|
-
const data = await api.getMarketStyle(token);
|
|
85
|
-
output.table(data);
|
|
86
|
-
} else if (options.value) {
|
|
87
|
-
const data = await api.getMarketValueData(token);
|
|
88
|
-
output.valueTable(data);
|
|
89
|
-
} else if (options.news) {
|
|
90
|
-
const data = await api.getMarketNews(token);
|
|
91
|
-
output.newsList(data);
|
|
92
|
-
} else if (options.zdt) {
|
|
93
|
-
const data = await api.getZdtPool(token);
|
|
94
|
-
output.text(data);
|
|
95
|
-
} else {
|
|
96
|
-
// 默认获取市场概览
|
|
97
|
-
const data = await api.getMarketData(token);
|
|
98
|
-
output.marketOverview(data);
|
|
99
|
-
}
|
|
100
|
-
} catch (err) {
|
|
101
|
-
output.error(err);
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
// ==================== 指数K线命令 ====================
|
|
106
|
-
program
|
|
107
|
-
.command('index')
|
|
108
|
-
.description('获取上证指数K线数据')
|
|
109
|
-
.action(async () => {
|
|
110
|
-
showWelcome();
|
|
111
|
-
const token = checkToken();
|
|
112
|
-
|
|
113
|
-
try {
|
|
114
|
-
const data = await api.getIndexK(token);
|
|
115
|
-
output.klines(data);
|
|
116
|
-
} catch (err) {
|
|
117
|
-
output.error(err);
|
|
118
|
-
}
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
// ==================== 板块数据命令 ====================
|
|
122
|
-
program
|
|
123
|
-
.command('sector')
|
|
124
|
-
.description('板块数据')
|
|
125
|
-
.option('-c, --code <code>', '板块代码,获取板块内个股')
|
|
126
|
-
.option('-o, --order <field>', '排序字段', 'cs')
|
|
127
|
-
.option('-l, --limit <days>', '天数', '5')
|
|
128
|
-
.option('-g, --gn <gnId>', '概念代码,获取概念内个股')
|
|
129
|
-
.action(async (options) => {
|
|
130
|
-
showWelcome();
|
|
131
|
-
const token = checkToken();
|
|
132
|
-
|
|
133
|
-
try {
|
|
134
|
-
if (options.code) {
|
|
135
|
-
const data = await api.getSectorRankStock(token, options.code, options.order);
|
|
136
|
-
output.stockList(data);
|
|
137
|
-
} else if (options.gn) {
|
|
138
|
-
const data = await api.getGainianStock(token, options.gn);
|
|
139
|
-
output.stockList(data);
|
|
140
|
-
} else {
|
|
141
|
-
const data = await api.getSectorData(token, options.order, parseInt(options.limit));
|
|
142
|
-
output.sectorHeatmap(data);
|
|
143
|
-
}
|
|
144
|
-
} catch (err) {
|
|
145
|
-
output.error(err);
|
|
146
|
-
}
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
// ==================== 个股查询命令 ====================
|
|
150
|
-
program
|
|
151
|
-
.command('stock <codes...>')
|
|
152
|
-
.description('获取个股数据,支持多个股票代码')
|
|
153
|
-
.option('-j, --json', '输出JSON格式')
|
|
154
|
-
.action(async (codes, options) => {
|
|
155
|
-
showWelcome();
|
|
156
|
-
const token = checkToken();
|
|
157
|
-
|
|
158
|
-
try {
|
|
159
|
-
const data = await api.getStockData(token, codes.join(','));
|
|
160
|
-
if (options.json) {
|
|
161
|
-
console.log(JSON.stringify(data, null, 2));
|
|
162
|
-
} else {
|
|
163
|
-
output.stockDetail(data);
|
|
164
|
-
}
|
|
165
|
-
} catch (err) {
|
|
166
|
-
output.error(err);
|
|
167
|
-
}
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
// ==================== 搜索命令 ====================
|
|
171
|
-
program
|
|
172
|
-
.command('search <keyword>')
|
|
173
|
-
.description('搜索股票或行业')
|
|
174
|
-
.option('-t, --type <type>', '类型: stock/hy', 'stock')
|
|
175
|
-
.action(async (keyword, options) => {
|
|
176
|
-
showWelcome();
|
|
177
|
-
const token = checkToken();
|
|
178
|
-
|
|
179
|
-
try {
|
|
180
|
-
const data = await api.queryStock(token, keyword, options.type);
|
|
181
|
-
output.searchResult(data);
|
|
182
|
-
} catch (err) {
|
|
183
|
-
output.error(err);
|
|
184
|
-
}
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
// ==================== K线数据命令 ====================
|
|
188
|
-
program
|
|
189
|
-
.command('kline <code>')
|
|
190
|
-
.description('获取个股K线数据')
|
|
191
|
-
.option('-l, --limit <days>', '数据条数', '300')
|
|
192
|
-
.option('-t, --type <type>', 'K线类型: day/week/month', 'day')
|
|
193
|
-
.option('-j, --json', '输出JSON格式')
|
|
194
|
-
.option('-s, --simple', '简单输出格式')
|
|
195
|
-
.action(async (code, options) => {
|
|
196
|
-
showWelcome();
|
|
197
|
-
// K线数据不需要token,使用免费数据源
|
|
198
|
-
|
|
199
|
-
try {
|
|
200
|
-
const data = await api.getKline(code, parseInt(options.limit), options.type);
|
|
201
|
-
if (options.json) {
|
|
202
|
-
console.log(JSON.stringify(data, null, 2));
|
|
203
|
-
} else if (options.simple) {
|
|
204
|
-
output.klineSimple(data, 10);
|
|
205
|
-
} else {
|
|
206
|
-
output.klineData(data, 20);
|
|
207
|
-
}
|
|
208
|
-
} catch (err) {
|
|
209
|
-
output.error(err);
|
|
210
|
-
}
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
program.parse();
|
|
8
|
+
.alias('dxp')
|
|
9
|
+
.version(package.version)
|
|
10
|
+
.description('大虾皮金融数据API命令行工具');
|
|
11
|
+
|
|
12
|
+
require('../commands/config')(program);
|
|
13
|
+
require('../commands/market')(program);
|
|
14
|
+
require('../commands/sector')(program);
|
|
15
|
+
require('../commands/stock')(program);
|
|
16
|
+
require('../commands/kline')(program);
|
|
17
|
+
require('../commands/zdt')(program);
|
|
18
|
+
require('../commands/secid')(program);
|
|
19
|
+
require('../commands/search')(program);
|
|
20
|
+
|
|
21
|
+
program.parse(process.argv);
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
const config = require('../lib/config');
|
|
2
|
+
const { handleError, createParameterError } = require('../lib/error');
|
|
3
|
+
|
|
4
|
+
module.exports = function(program) {
|
|
5
|
+
const configCmd = program.command('config');
|
|
6
|
+
|
|
7
|
+
configCmd
|
|
8
|
+
.command('set <key> <value>')
|
|
9
|
+
.description('设置配置项')
|
|
10
|
+
.action((key, value) => {
|
|
11
|
+
try {
|
|
12
|
+
if (!key || !value) {
|
|
13
|
+
throw createParameterError(
|
|
14
|
+
'参数无效',
|
|
15
|
+
[
|
|
16
|
+
"参数 'key' 不能为空",
|
|
17
|
+
"参数 'value' 不能为空"
|
|
18
|
+
],
|
|
19
|
+
[
|
|
20
|
+
'daxiapi config set token YOUR_TOKEN',
|
|
21
|
+
'daxiapi config set baseUrl https://daxiapi.com'
|
|
22
|
+
]
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
config.set(key, value);
|
|
27
|
+
console.log(`✓ ${key} 已设置`);
|
|
28
|
+
} catch (error) {
|
|
29
|
+
handleError(error);
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
configCmd
|
|
35
|
+
.command('get')
|
|
36
|
+
.description('查看所有配置')
|
|
37
|
+
.action(() => {
|
|
38
|
+
try {
|
|
39
|
+
const allConfig = config.getAll();
|
|
40
|
+
console.log(JSON.stringify(allConfig, null, 2));
|
|
41
|
+
} catch (error) {
|
|
42
|
+
handleError(error);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
configCmd
|
|
48
|
+
.command('delete <key>')
|
|
49
|
+
.description('删除配置项')
|
|
50
|
+
.action((key) => {
|
|
51
|
+
try {
|
|
52
|
+
if (!key) {
|
|
53
|
+
throw createParameterError(
|
|
54
|
+
'参数无效',
|
|
55
|
+
["参数 'key' 不能为空"],
|
|
56
|
+
['daxiapi config delete token']
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
config.delete(key);
|
|
61
|
+
console.log(`✓ ${key} 已删除`);
|
|
62
|
+
} catch (error) {
|
|
63
|
+
handleError(error);
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
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('kline <code>')
|
|
9
|
+
.description('K线数据')
|
|
10
|
+
.action(async (code) => {
|
|
11
|
+
try {
|
|
12
|
+
const token = config.getToken();
|
|
13
|
+
if (!token) {
|
|
14
|
+
const error = new Error('未配置 API Token');
|
|
15
|
+
error.response = {status: 401};
|
|
16
|
+
throw error;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (!code) {
|
|
20
|
+
throw createParameterError(
|
|
21
|
+
'参数无效',
|
|
22
|
+
['参数 \'code\' 不能为空'],
|
|
23
|
+
['daxiapi kline 000001']
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const data = await api.getKline(token, code);
|
|
28
|
+
output(data);
|
|
29
|
+
} catch (error) {
|
|
30
|
+
handleError(error);
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
const config = require('../lib/config');
|
|
2
|
+
const api = require('../lib/api');
|
|
3
|
+
const { handleError } = require('../lib/error');
|
|
4
|
+
const { output } = require('../lib/output');
|
|
5
|
+
|
|
6
|
+
module.exports = function(program) {
|
|
7
|
+
const marketCmd = program.command('market');
|
|
8
|
+
|
|
9
|
+
marketCmd
|
|
10
|
+
.description('市场数据')
|
|
11
|
+
.action(async () => {
|
|
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
|
+
const data = await api.getMarketData(token);
|
|
21
|
+
output(data);
|
|
22
|
+
} catch (error) {
|
|
23
|
+
handleError(error);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
marketCmd
|
|
29
|
+
.command('temp')
|
|
30
|
+
.description('市场温度')
|
|
31
|
+
.action(async () => {
|
|
32
|
+
try {
|
|
33
|
+
const token = config.getToken();
|
|
34
|
+
if (!token) {
|
|
35
|
+
const error = new Error('未配置 API Token');
|
|
36
|
+
error.response = {status: 401};
|
|
37
|
+
throw error;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const data = await api.getMarketTemp(token);
|
|
41
|
+
output(data);
|
|
42
|
+
} catch (error) {
|
|
43
|
+
handleError(error);
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
marketCmd
|
|
49
|
+
.command('style')
|
|
50
|
+
.description('市场风格')
|
|
51
|
+
.action(async () => {
|
|
52
|
+
try {
|
|
53
|
+
const token = config.getToken();
|
|
54
|
+
if (!token) {
|
|
55
|
+
const error = new Error('未配置 API Token');
|
|
56
|
+
error.response = {status: 401};
|
|
57
|
+
throw error;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const data = await api.getMarketStyle(token);
|
|
61
|
+
output(data);
|
|
62
|
+
} catch (error) {
|
|
63
|
+
handleError(error);
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
marketCmd
|
|
69
|
+
.command('value')
|
|
70
|
+
.description('市场估值')
|
|
71
|
+
.action(async () => {
|
|
72
|
+
try {
|
|
73
|
+
const token = config.getToken();
|
|
74
|
+
if (!token) {
|
|
75
|
+
const error = new Error('未配置 API Token');
|
|
76
|
+
error.response = {status: 401};
|
|
77
|
+
throw error;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const data = await api.getMarketValueData(token);
|
|
81
|
+
output(data);
|
|
82
|
+
} catch (error) {
|
|
83
|
+
handleError(error);
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
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('search <keyword>')
|
|
9
|
+
.description('搜索股票或板块代码')
|
|
10
|
+
.option('-t, --type <type>', '搜索类型:stock(股票)或 bk(板块)', 'stock')
|
|
11
|
+
.action(async (keyword, 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 (!keyword) {
|
|
21
|
+
throw createParameterError(
|
|
22
|
+
'参数无效',
|
|
23
|
+
["参数 'keyword' 不能为空"],
|
|
24
|
+
['daxiapi search 平安', 'daxiapi search 锂电 --type bk']
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const data = await api.queryStockData(token, keyword, options.type);
|
|
29
|
+
output(data);
|
|
30
|
+
} catch (error) {
|
|
31
|
+
handleError(error);
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
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('secid <code>')
|
|
9
|
+
.description('代码转换')
|
|
10
|
+
.action(async (code) => {
|
|
11
|
+
try {
|
|
12
|
+
const token = config.getToken();
|
|
13
|
+
if (!token) {
|
|
14
|
+
const error = new Error('未配置 API Token');
|
|
15
|
+
error.response = {status: 401};
|
|
16
|
+
throw error;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (!code) {
|
|
20
|
+
throw createParameterError(
|
|
21
|
+
'参数无效',
|
|
22
|
+
["参数 'code' 不能为空"],
|
|
23
|
+
['daxiapi secid 000001']
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const data = await api.getSecId(token, code);
|
|
28
|
+
output(data);
|
|
29
|
+
} catch (error) {
|
|
30
|
+
handleError(error);
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
};
|