daxiapi-cli 1.2.0 → 2.0.1

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